From d545e84eae2b30536a17e746137647e1de256417 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Fri, 24 Jan 2025 01:04:14 -0800 Subject: [PATCH 001/745] update llvm workaround comment to link to rust tracking issue too --- crates/core_simd/src/simd/num/float.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/core_simd/src/simd/num/float.rs b/crates/core_simd/src/simd/num/float.rs index 79954b937b39..6371276ae262 100644 --- a/crates/core_simd/src/simd/num/float.rs +++ b/crates/core_simd/src/simd/num/float.rs @@ -263,7 +263,8 @@ macro_rules! impl_trait { unsafe { core::intrinsics::simd::simd_as(self) } } - // https://github.com/llvm/llvm-project/issues/94694 + // workaround for https://github.com/llvm/llvm-project/issues/94694 (fixed in LLVM 20) + // tracked in: https://github.com/rust-lang/rust/issues/135982 #[cfg(target_arch = "aarch64")] #[inline] fn cast(self) -> Self::Cast From 42c9c109fe1a794ff959111f6be52d0d2ec17642 Mon Sep 17 00:00:00 2001 From: Mu001999 Date: Sat, 25 Jan 2025 14:25:10 +0800 Subject: [PATCH 002/745] Remove unused trait BoundedSize --- library/core/src/iter/adapters/flatten.rs | 55 ----------------------- 1 file changed, 55 deletions(-) diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index 9b9353b800a9..a820045521b9 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -172,61 +172,6 @@ where } } -/// Marker trait for iterators/iterables which have a statically known upper -/// bound of the number of items they can produce. -/// -/// # Safety -/// -/// Implementations must not yield more elements than indicated by UPPER_BOUND if it is `Some`. -/// Used in specializations. Implementations must not be conditional on lifetimes or -/// user-implementable traits. -#[rustc_specialization_trait] -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe trait BoundedSize { - const UPPER_BOUND: Option> = NonZero::new(1); -} - -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl BoundedSize for Option {} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl BoundedSize for option::IntoIter {} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl BoundedSize for Result {} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl BoundedSize for result::IntoIter {} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl BoundedSize for Once {} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl BoundedSize for OnceWith {} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl BoundedSize for [T; N] { - const UPPER_BOUND: Option> = NonZero::new(N); -} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl BoundedSize for array::IntoIter { - const UPPER_BOUND: Option> = NonZero::new(N); -} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl BoundedSize for Filter { - const UPPER_BOUND: Option> = I::UPPER_BOUND; -} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl BoundedSize for FilterMap { - const UPPER_BOUND: Option> = I::UPPER_BOUND; -} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl BoundedSize for Map { - const UPPER_BOUND: Option> = I::UPPER_BOUND; -} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl BoundedSize for Copied { - const UPPER_BOUND: Option> = I::UPPER_BOUND; -} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl BoundedSize for Cloned { - const UPPER_BOUND: Option> = I::UPPER_BOUND; -} - /// An iterator that flattens one level of nesting in an iterator of things /// that can be turned into iterators. /// From 51c5700f15a23ac55c51e8e6a3f478a7fd77fcc6 Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Tue, 28 Jan 2025 09:38:54 +0100 Subject: [PATCH 003/745] clarify BufRead::{fill_buf, consume} docs Fixes #85394 --- library/std/src/io/mod.rs | 41 ++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index cfd03b8e3d6d..767e6e18cca8 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -2250,24 +2250,18 @@ fn skip_until(r: &mut R, delim: u8) -> Result { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub trait BufRead: Read { - /// Returns the contents of the internal buffer, filling it with more data - /// from the inner reader if it is empty. + /// Returns the contents of the internal buffer, filling it with more data, via Read methods, if empty. /// - /// This function is a lower-level call. It needs to be paired with the - /// [`consume`] method to function properly. When calling this - /// method, none of the contents will be "read" in the sense that later - /// calling `read` may return the same contents. As such, [`consume`] must - /// be called with the number of bytes that are consumed from this buffer to - /// ensure that the bytes are never returned twice. + /// This is a lower-level method and is meant to be used together with [`consume`], + /// which can be used to mark bytes that should not be returned by subsequent calls to `read`. /// /// [`consume`]: BufRead::consume /// - /// An empty buffer returned indicates that the stream has reached EOF. + /// Returns an empty buffer to indicate that the stream has reached EOF. /// /// # Errors /// - /// This function will return an I/O error if the underlying reader was - /// read, but returned an error. + /// Passes on I/O errors from Read. /// /// # Examples /// @@ -2285,7 +2279,7 @@ pub trait BufRead: Read { /// // work with buffer /// println!("{buffer:?}"); /// - /// // ensure the bytes we worked with aren't returned again later + /// // mark the bytes we worked with as read /// let length = buffer.len(); /// stdin.consume(length); /// # std::io::Result::Ok(()) @@ -2293,18 +2287,13 @@ pub trait BufRead: Read { #[stable(feature = "rust1", since = "1.0.0")] fn fill_buf(&mut self) -> Result<&[u8]>; - /// Tells this buffer that `amt` bytes have been consumed from the buffer, - /// so they should no longer be returned in calls to `read`. + /// Marks the given `amount` of additional bytes from the internal buffer as having been read. + /// Subsequent calls to `read` return bytes that have not yet been so marked. /// - /// This function is a lower-level call. It needs to be paired with the - /// [`fill_buf`] method to function properly. This function does - /// not perform any I/O, it simply informs this object that some amount of - /// its buffer, returned from [`fill_buf`], has been consumed and should - /// no longer be returned. As such, this function may do odd things if - /// [`fill_buf`] isn't called before calling it. + /// This is a lower-level method and is meant to be used together with [`fill_buf`], + /// which can be used to fill the internal buffer via Read methods. /// - /// The `amt` must be `<=` the number of bytes in the buffer returned by - /// [`fill_buf`]. + /// It is a logic error if `amount` exceeds the number of unread bytes in the internal buffer. /// /// # Examples /// @@ -2313,9 +2302,9 @@ pub trait BufRead: Read { /// /// [`fill_buf`]: BufRead::fill_buf #[stable(feature = "rust1", since = "1.0.0")] - fn consume(&mut self, amt: usize); + fn consume(&mut self, amount: usize); - /// Checks if the underlying `Read` has any data left to be read. + /// Checks if there is any data left to be `read`. /// /// This function may fill the buffer to check for data, /// so this functions returns `Result`, not `bool`. @@ -2324,6 +2313,10 @@ pub trait BufRead: Read { /// returned slice is empty (which means that there is no data left, /// since EOF is reached). /// + /// # Errors + /// + /// Passes on I/O errors from Read. + /// /// Examples /// /// ``` From f1010442cc650aba832a11b95a2b1a75f23cdf0e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 4 Feb 2025 15:15:28 +0100 Subject: [PATCH 004/745] intrinsics: unify rint, roundeven, nearbyint in a single round_ties_even intrinsic --- src/intrinsics/mod.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 26f14532b458..4d9bed8652cb 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -340,14 +340,10 @@ fn codegen_float_intrinsic_call<'tcx>( sym::ceilf64 => ("ceil", 1, fx.tcx.types.f64, types::F64), sym::truncf32 => ("truncf", 1, fx.tcx.types.f32, types::F32), sym::truncf64 => ("trunc", 1, fx.tcx.types.f64, types::F64), - sym::rintf32 => ("rintf", 1, fx.tcx.types.f32, types::F32), - sym::rintf64 => ("rint", 1, fx.tcx.types.f64, types::F64), + sym::round_ties_even_f32 => ("rintf", 1, fx.tcx.types.f32, types::F32), + sym::round_ties_even_f64 => ("rint", 1, fx.tcx.types.f64, types::F64), sym::roundf32 => ("roundf", 1, fx.tcx.types.f32, types::F32), sym::roundf64 => ("round", 1, fx.tcx.types.f64, types::F64), - sym::roundevenf32 => ("roundevenf", 1, fx.tcx.types.f32, types::F32), - sym::roundevenf64 => ("roundeven", 1, fx.tcx.types.f64, types::F64), - sym::nearbyintf32 => ("nearbyintf", 1, fx.tcx.types.f32, types::F32), - sym::nearbyintf64 => ("nearbyint", 1, fx.tcx.types.f64, types::F64), sym::sinf32 => ("sinf", 1, fx.tcx.types.f32, types::F32), sym::sinf64 => ("sin", 1, fx.tcx.types.f64, types::F64), sym::cosf32 => ("cosf", 1, fx.tcx.types.f32, types::F32), @@ -399,8 +395,8 @@ fn codegen_float_intrinsic_call<'tcx>( | sym::ceilf64 | sym::truncf32 | sym::truncf64 - | sym::nearbyintf32 - | sym::nearbyintf64 + | sym::round_ties_even_f32 + | sym::round_ties_even_f64 | sym::sqrtf32 | sym::sqrtf64 => { let val = match intrinsic { @@ -408,7 +404,9 @@ fn codegen_float_intrinsic_call<'tcx>( sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(args[0]), sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(args[0]), sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(args[0]), - sym::nearbyintf32 | sym::nearbyintf64 => fx.bcx.ins().nearest(args[0]), + sym::round_ties_even_f32 | sym::round_ties_even_f64 => { + fx.bcx.ins().nearest(args[0]) + } sym::sqrtf32 | sym::sqrtf64 => fx.bcx.ins().sqrt(args[0]), _ => unreachable!(), }; From c0126939617dc86b0c5d29a712ce9e8fc67d2f0f Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 4 Feb 2025 13:01:32 -0700 Subject: [PATCH 005/745] needless_collect: avoid warning if non-iterator methods are used It can make sense to `collect()` an iterator and then immediately iterate over it if the iterator has special methods that you need. For example, the Map iterator doesn't implement Clone, but the collection iterator might. Or the collection iterator might support slicing. --- clippy_lints/src/methods/needless_collect.rs | 71 ++++++++++++++++++-- tests/ui/needless_collect.fixed | 14 ++++ tests/ui/needless_collect.rs | 14 ++++ 3 files changed, 93 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/methods/needless_collect.rs b/clippy_lints/src/methods/needless_collect.rs index 2780c3f8af5c..6732aeeb4985 100644 --- a/clippy_lints/src/methods/needless_collect.rs +++ b/clippy_lints/src/methods/needless_collect.rs @@ -1,3 +1,5 @@ +use std::ops::ControlFlow; + use super::NEEDLESS_COLLECT; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; use clippy_utils::source::{snippet, snippet_with_applicability}; @@ -9,9 +11,9 @@ use clippy_utils::{ }; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, MultiSpan}; -use rustc_hir::intravisit::{Visitor, walk_block, walk_expr}; +use rustc_hir::intravisit::{Visitor, walk_block, walk_expr, walk_stmt}; use rustc_hir::{ - BindingMode, Block, Expr, ExprKind, HirId, HirIdSet, LetStmt, Mutability, Node, PatKind, Stmt, StmtKind, + BindingMode, Block, Expr, ExprKind, HirId, HirIdSet, LetStmt, Mutability, Node, Pat, PatKind, Stmt, StmtKind, }; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; @@ -103,6 +105,12 @@ pub(super) fn check<'tcx>( return; } + if let IterFunctionKind::IntoIter(hir_id) = iter_call.func + && !check_iter_expr_used_only_as_iterator(cx, hir_id, block) + { + return; + } + // Suggest replacing iter_call with iter_replacement, and removing stmt let mut span = MultiSpan::from_span(name_span); span.push_span_label(iter_call.span, "the iterator could be used here instead"); @@ -253,7 +261,7 @@ struct IterFunction { impl IterFunction { fn get_iter_method(&self, cx: &LateContext<'_>) -> String { match &self.func { - IterFunctionKind::IntoIter => String::new(), + IterFunctionKind::IntoIter(_) => String::new(), IterFunctionKind::Len => String::from(".count()"), IterFunctionKind::IsEmpty => String::from(".next().is_none()"), IterFunctionKind::Contains(span) => { @@ -268,7 +276,7 @@ impl IterFunction { } fn get_suggestion_text(&self) -> &'static str { match &self.func { - IterFunctionKind::IntoIter => { + IterFunctionKind::IntoIter(_) => { "use the original Iterator instead of collecting it and then producing a new one" }, IterFunctionKind::Len => { @@ -284,7 +292,7 @@ impl IterFunction { } } enum IterFunctionKind { - IntoIter, + IntoIter(HirId), Len, IsEmpty, Contains(Span), @@ -343,7 +351,7 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> { } match method_name.ident.name.as_str() { "into_iter" => self.uses.push(Some(IterFunction { - func: IterFunctionKind::IntoIter, + func: IterFunctionKind::IntoIter(expr.hir_id), span: expr.span, })), "len" => self.uses.push(Some(IterFunction { @@ -520,3 +528,54 @@ fn get_captured_ids(cx: &LateContext<'_>, ty: Ty<'_>) -> HirIdSet { set } + +struct IteratorMethodCheckVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + hir_id_of_expr: HirId, + hir_id_of_let_binding: Option, +} + +impl<'tcx> Visitor<'tcx> for IteratorMethodCheckVisitor<'_, 'tcx> { + type Result = ControlFlow<()>; + fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) -> ControlFlow<()> { + if let ExprKind::MethodCall(_method_name, recv, _args, _) = &expr.kind + && (recv.hir_id == self.hir_id_of_expr + || self + .hir_id_of_let_binding + .is_some_and(|hid| path_to_local_id(recv, hid))) + && !is_trait_method(self.cx, expr, sym::Iterator) + { + return ControlFlow::Break(()); + } + walk_expr(self, expr) + } + fn visit_stmt(&mut self, stmt: &'tcx Stmt<'tcx>) -> ControlFlow<()> { + if let StmtKind::Let(LetStmt { + init: Some(expr), + pat: + Pat { + kind: PatKind::Binding(BindingMode::NONE | BindingMode::MUT, id, _, None), + .. + }, + .. + }) = &stmt.kind + && expr.hir_id == self.hir_id_of_expr + { + self.hir_id_of_let_binding = Some(*id); + } + walk_stmt(self, stmt) + } +} + +fn check_iter_expr_used_only_as_iterator<'tcx>( + cx: &LateContext<'tcx>, + hir_id_of_expr: HirId, + block: &'tcx Block<'tcx>, +) -> bool { + let mut visitor = IteratorMethodCheckVisitor { + cx, + hir_id_of_expr, + hir_id_of_let_binding: None, + }; + visitor.visit_block(block).is_continue() +} diff --git a/tests/ui/needless_collect.fixed b/tests/ui/needless_collect.fixed index bd83581bdd97..e33b984a44b5 100644 --- a/tests/ui/needless_collect.fixed +++ b/tests/ui/needless_collect.fixed @@ -73,6 +73,20 @@ fn main() { let mut out = vec![]; values.iter().cloned().map(|x| out.push(x)).collect::>(); let _y = values.iter().cloned().map(|x| out.push(x)).collect::>(); // this is fine + + // Don't write a warning if we call `clone()` on the iterator + // https://github.com/rust-lang/rust-clippy/issues/13430 + let my_collection: Vec<()> = vec![()].into_iter().map(|()| {}).collect(); + let _cloned = my_collection.into_iter().clone(); + let my_collection: Vec<()> = vec![()].into_iter().map(|()| {}).collect(); + let my_iter = my_collection.into_iter(); + let _cloned = my_iter.clone(); + // Same for `as_slice()`, for same reason. + let my_collection: Vec<()> = vec![()].into_iter().map(|()| {}).collect(); + let _sliced = my_collection.into_iter().as_slice(); + let my_collection: Vec<()> = vec![()].into_iter().map(|()| {}).collect(); + let my_iter = my_collection.into_iter(); + let _sliced = my_iter.as_slice(); } fn foo(_: impl IntoIterator) {} diff --git a/tests/ui/needless_collect.rs b/tests/ui/needless_collect.rs index 6a81a767bbb6..fab00d67dbfd 100644 --- a/tests/ui/needless_collect.rs +++ b/tests/ui/needless_collect.rs @@ -73,6 +73,20 @@ fn main() { let mut out = vec![]; values.iter().cloned().map(|x| out.push(x)).collect::>(); let _y = values.iter().cloned().map(|x| out.push(x)).collect::>(); // this is fine + + // Don't write a warning if we call `clone()` on the iterator + // https://github.com/rust-lang/rust-clippy/issues/13430 + let my_collection: Vec<()> = vec![()].into_iter().map(|()| {}).collect(); + let _cloned = my_collection.into_iter().clone(); + let my_collection: Vec<()> = vec![()].into_iter().map(|()| {}).collect(); + let my_iter = my_collection.into_iter(); + let _cloned = my_iter.clone(); + // Same for `as_slice()`, for same reason. + let my_collection: Vec<()> = vec![()].into_iter().map(|()| {}).collect(); + let _sliced = my_collection.into_iter().as_slice(); + let my_collection: Vec<()> = vec![()].into_iter().map(|()| {}).collect(); + let my_iter = my_collection.into_iter(); + let _sliced = my_iter.as_slice(); } fn foo(_: impl IntoIterator) {} From 2b5f6f05b552026673c272411ed5db3f1cccd479 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 12 Feb 2025 15:17:46 -0800 Subject: [PATCH 006/745] Migrate core_simd to Rust 2024 --- crates/core_simd/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/core_simd/Cargo.toml b/crates/core_simd/Cargo.toml index a7a6d43b11d3..537ce459c07c 100644 --- a/crates/core_simd/Cargo.toml +++ b/crates/core_simd/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "core_simd" version = "0.1.0" -edition = "2021" +edition = "2024" homepage = "https://github.com/rust-lang/portable-simd" repository = "https://github.com/rust-lang/portable-simd" keywords = ["core", "simd", "intrinsics"] From 007e0f18982519e0e7a521240c7e67e7b9e3e7a0 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 12 Feb 2025 16:49:46 -0800 Subject: [PATCH 007/745] Apply style_edition 2024 --- crates/core_simd/src/ops.rs | 2 +- crates/core_simd/src/simd/cmp/eq.rs | 2 +- crates/core_simd/src/simd/cmp/ord.rs | 2 +- crates/core_simd/src/simd/num/float.rs | 2 +- crates/core_simd/src/simd/num/int.rs | 4 ++-- crates/core_simd/src/simd/num/uint.rs | 2 +- crates/core_simd/src/simd/prelude.rs | 3 ++- crates/core_simd/src/simd/ptr/const_ptr.rs | 2 +- crates/core_simd/src/simd/ptr/mut_ptr.rs | 2 +- crates/core_simd/src/to_bytes.rs | 2 +- crates/core_simd/src/vector.rs | 2 +- crates/core_simd/tests/pointers.rs | 2 +- 12 files changed, 14 insertions(+), 13 deletions(-) diff --git a/crates/core_simd/src/ops.rs b/crates/core_simd/src/ops.rs index d3bd14a34027..be3bacb76d57 100644 --- a/crates/core_simd/src/ops.rs +++ b/crates/core_simd/src/ops.rs @@ -1,4 +1,4 @@ -use crate::simd::{cmp::SimdPartialEq, LaneCount, Simd, SimdElement, SupportedLaneCount}; +use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount, cmp::SimdPartialEq}; use core::ops::{Add, Mul}; use core::ops::{BitAnd, BitOr, BitXor}; use core::ops::{Div, Rem, Sub}; diff --git a/crates/core_simd/src/simd/cmp/eq.rs b/crates/core_simd/src/simd/cmp/eq.rs index 93989ce91b89..2312ba401fa7 100644 --- a/crates/core_simd/src/simd/cmp/eq.rs +++ b/crates/core_simd/src/simd/cmp/eq.rs @@ -1,6 +1,6 @@ use crate::simd::{ - ptr::{SimdConstPtr, SimdMutPtr}, LaneCount, Mask, Simd, SimdElement, SupportedLaneCount, + ptr::{SimdConstPtr, SimdMutPtr}, }; /// Parallel `PartialEq`. diff --git a/crates/core_simd/src/simd/cmp/ord.rs b/crates/core_simd/src/simd/cmp/ord.rs index 899f00a83164..e813e7613032 100644 --- a/crates/core_simd/src/simd/cmp/ord.rs +++ b/crates/core_simd/src/simd/cmp/ord.rs @@ -1,7 +1,7 @@ use crate::simd::{ + LaneCount, Mask, Simd, SupportedLaneCount, cmp::SimdPartialEq, ptr::{SimdConstPtr, SimdMutPtr}, - LaneCount, Mask, Simd, SupportedLaneCount, }; /// Parallel `PartialOrd`. diff --git a/crates/core_simd/src/simd/num/float.rs b/crates/core_simd/src/simd/num/float.rs index 79954b937b39..46b94ad9f1ca 100644 --- a/crates/core_simd/src/simd/num/float.rs +++ b/crates/core_simd/src/simd/num/float.rs @@ -1,7 +1,7 @@ use super::sealed::Sealed; use crate::simd::{ - cmp::{SimdPartialEq, SimdPartialOrd}, LaneCount, Mask, Simd, SimdCast, SimdElement, SupportedLaneCount, + cmp::{SimdPartialEq, SimdPartialOrd}, }; /// Operations on SIMD vectors of floats. diff --git a/crates/core_simd/src/simd/num/int.rs b/crates/core_simd/src/simd/num/int.rs index 3a51235ff954..d25050c3e4b4 100644 --- a/crates/core_simd/src/simd/num/int.rs +++ b/crates/core_simd/src/simd/num/int.rs @@ -1,7 +1,7 @@ use super::sealed::Sealed; use crate::simd::{ - cmp::SimdOrd, cmp::SimdPartialOrd, num::SimdUint, LaneCount, Mask, Simd, SimdCast, SimdElement, - SupportedLaneCount, + LaneCount, Mask, Simd, SimdCast, SimdElement, SupportedLaneCount, cmp::SimdOrd, + cmp::SimdPartialOrd, num::SimdUint, }; /// Operations on SIMD vectors of signed integers. diff --git a/crates/core_simd/src/simd/num/uint.rs b/crates/core_simd/src/simd/num/uint.rs index 1ab2d8c7b731..45d978068b66 100644 --- a/crates/core_simd/src/simd/num/uint.rs +++ b/crates/core_simd/src/simd/num/uint.rs @@ -1,5 +1,5 @@ use super::sealed::Sealed; -use crate::simd::{cmp::SimdOrd, LaneCount, Simd, SimdCast, SimdElement, SupportedLaneCount}; +use crate::simd::{LaneCount, Simd, SimdCast, SimdElement, SupportedLaneCount, cmp::SimdOrd}; /// Operations on SIMD vectors of unsigned integers. pub trait SimdUint: Copy + Sealed { diff --git a/crates/core_simd/src/simd/prelude.rs b/crates/core_simd/src/simd/prelude.rs index 4b7c744c0132..e5d7a2aeb73d 100644 --- a/crates/core_simd/src/simd/prelude.rs +++ b/crates/core_simd/src/simd/prelude.rs @@ -7,10 +7,11 @@ #[doc(no_inline)] pub use super::{ + Mask, Simd, cmp::{SimdOrd, SimdPartialEq, SimdPartialOrd}, num::{SimdFloat, SimdInt, SimdUint}, ptr::{SimdConstPtr, SimdMutPtr}, - simd_swizzle, Mask, Simd, + simd_swizzle, }; #[rustfmt::skip] diff --git a/crates/core_simd/src/simd/ptr/const_ptr.rs b/crates/core_simd/src/simd/ptr/const_ptr.rs index 3f5fb1f2c1bc..34d46216710c 100644 --- a/crates/core_simd/src/simd/ptr/const_ptr.rs +++ b/crates/core_simd/src/simd/ptr/const_ptr.rs @@ -1,5 +1,5 @@ use super::sealed::Sealed; -use crate::simd::{cmp::SimdPartialEq, num::SimdUint, LaneCount, Mask, Simd, SupportedLaneCount}; +use crate::simd::{LaneCount, Mask, Simd, SupportedLaneCount, cmp::SimdPartialEq, num::SimdUint}; /// Operations on SIMD vectors of constant pointers. pub trait SimdConstPtr: Copy + Sealed { diff --git a/crates/core_simd/src/simd/ptr/mut_ptr.rs b/crates/core_simd/src/simd/ptr/mut_ptr.rs index c909cca1fb20..bf5d160c09ea 100644 --- a/crates/core_simd/src/simd/ptr/mut_ptr.rs +++ b/crates/core_simd/src/simd/ptr/mut_ptr.rs @@ -1,5 +1,5 @@ use super::sealed::Sealed; -use crate::simd::{cmp::SimdPartialEq, num::SimdUint, LaneCount, Mask, Simd, SupportedLaneCount}; +use crate::simd::{LaneCount, Mask, Simd, SupportedLaneCount, cmp::SimdPartialEq, num::SimdUint}; /// Operations on SIMD vectors of mutable pointers. pub trait SimdMutPtr: Copy + Sealed { diff --git a/crates/core_simd/src/to_bytes.rs b/crates/core_simd/src/to_bytes.rs index 4833ea9e1136..fee2cc06c5b0 100644 --- a/crates/core_simd/src/to_bytes.rs +++ b/crates/core_simd/src/to_bytes.rs @@ -1,6 +1,6 @@ use crate::simd::{ - num::{SimdFloat, SimdInt, SimdUint}, LaneCount, Simd, SimdElement, SupportedLaneCount, + num::{SimdFloat, SimdInt, SimdUint}, }; mod sealed { diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs index 9c4dd36c24fe..498715887e1d 100644 --- a/crates/core_simd/src/vector.rs +++ b/crates/core_simd/src/vector.rs @@ -1,8 +1,8 @@ use crate::simd::{ + LaneCount, Mask, MaskElement, SupportedLaneCount, Swizzle, cmp::SimdPartialOrd, num::SimdUint, ptr::{SimdConstPtr, SimdMutPtr}, - LaneCount, Mask, MaskElement, SupportedLaneCount, Swizzle, }; /// A SIMD vector with the shape of `[T; N]` but the operations of `T`. diff --git a/crates/core_simd/tests/pointers.rs b/crates/core_simd/tests/pointers.rs index d7db4e82b3ca..6e74c2d18b1e 100644 --- a/crates/core_simd/tests/pointers.rs +++ b/crates/core_simd/tests/pointers.rs @@ -1,8 +1,8 @@ #![feature(portable_simd)] use core_simd::simd::{ - ptr::{SimdConstPtr, SimdMutPtr}, Simd, + ptr::{SimdConstPtr, SimdMutPtr}, }; macro_rules! common_tests { From 0b90953a2d35b1886829fb8ec986d59d337f9c3a Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 15 Feb 2025 14:13:01 +0000 Subject: [PATCH 008/745] Merge commit '557ed8ebb7e981817d03c87352892c394183dd70' into sync_cg_clif-2025-02-15 --- .github/workflows/main.yml | 4 ++-- rust-toolchain | 2 +- rustfmt.toml | 3 ++- src/abi/pass_mode.rs | 2 +- src/common.rs | 7 ++++++- src/debuginfo/mod.rs | 2 +- src/debuginfo/types.rs | 4 ++-- src/inline_asm.rs | 3 ++- src/value_and_place.rs | 6 +++--- 9 files changed, 20 insertions(+), 13 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a8333df77e6e..61a4c1270c99 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -188,8 +188,8 @@ jobs: fail-fast: false matrix: include: - # FIXME update at some point in the future once most distros use a newer glibc - - os: ubuntu-20.04 + # Intentionally using an older ubuntu version to lower the glibc requirements of the distributed cg_clif + - os: ubuntu-22.04 env: TARGET_TRIPLE: x86_64-unknown-linux-gnu - os: macos-latest diff --git a/rust-toolchain b/rust-toolchain index 8d423319fa97..481903c6afb2 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-02-07" +channel = "nightly-2025-02-15" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" diff --git a/rustfmt.toml b/rustfmt.toml index d9e6ac3d543c..f31fa9c76abc 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -3,8 +3,9 @@ ignore = [ ] # Matches rustfmt.toml of rustc -version = "Two" +style_edition = "2024" use_small_heuristics = "Max" merge_derives = false group_imports = "StdExternalCrate" imports_granularity = "Module" +use_field_init_shorthand = true diff --git a/src/abi/pass_mode.rs b/src/abi/pass_mode.rs index 7594a53fc758..b28c4c9539ce 100644 --- a/src/abi/pass_mode.rs +++ b/src/abi/pass_mode.rs @@ -195,7 +195,7 @@ pub(super) fn from_casted_value<'tcx>( // It may also be smaller for example when the type is a wrapper around an integer with a // larger alignment than the integer. std::cmp::max(abi_param_size, layout_size), - u32::try_from(layout.align.pref.bytes()).unwrap(), + u32::try_from(layout.align.abi.bytes()).unwrap(), ); let mut offset = 0; let mut block_params_iter = block_params.iter().copied(); diff --git a/src/common.rs b/src/common.rs index 534557fcd41b..766278d87183 100644 --- a/src/common.rs +++ b/src/common.rs @@ -382,6 +382,11 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { } pub(crate) fn create_stack_slot(&mut self, size: u32, align: u32) -> Pointer { + assert!( + size % align == 0, + "size must be a multiple of alignment (size={size}, align={align})" + ); + let abi_align = if self.tcx.sess.target.arch == "s390x" { 8 } else { 16 }; if align <= abi_align { let stack_slot = self.bcx.create_sized_stack_slot(StackSlotData { @@ -403,7 +408,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { align_shift: 4, }); let base_ptr = self.bcx.ins().stack_addr(self.pointer_type, stack_slot, 0); - let misalign_offset = self.bcx.ins().urem_imm(base_ptr, i64::from(align)); + let misalign_offset = self.bcx.ins().band_imm(base_ptr, i64::from(align - 1)); let realign_offset = self.bcx.ins().irsub_imm(misalign_offset, i64::from(align)); Pointer::new(self.bcx.ins().iadd(base_ptr, realign_offset)) } diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index f3a8623e2161..bba6567774d7 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -304,7 +304,7 @@ impl DebugContext { entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(file_id))); entry.set(gimli::DW_AT_decl_line, AttributeValue::Udata(line)); - entry.set(gimli::DW_AT_alignment, AttributeValue::Udata(static_layout.align.pref.bytes())); + entry.set(gimli::DW_AT_alignment, AttributeValue::Udata(static_layout.align.abi.bytes())); let mut expr = Expression::new(); expr.op_addr(address_for_data(data_id)); diff --git a/src/debuginfo/types.rs b/src/debuginfo/types.rs index a2f6691cdd23..017d7784dc03 100644 --- a/src/debuginfo/types.rs +++ b/src/debuginfo/types.rs @@ -166,7 +166,7 @@ impl DebugContext { let tuple_entry = self.dwarf.unit.get_mut(tuple_type_id); tuple_entry.set(gimli::DW_AT_name, AttributeValue::StringRef(self.dwarf.strings.add(name))); tuple_entry.set(gimli::DW_AT_byte_size, AttributeValue::Udata(layout.size.bytes())); - tuple_entry.set(gimli::DW_AT_alignment, AttributeValue::Udata(layout.align.pref.bytes())); + tuple_entry.set(gimli::DW_AT_alignment, AttributeValue::Udata(layout.align.abi.bytes())); for (i, (ty, dw_ty)) in components.into_iter().enumerate() { let member_id = self.dwarf.unit.add(tuple_type_id, gimli::DW_TAG_member); @@ -179,7 +179,7 @@ impl DebugContext { member_entry.set( gimli::DW_AT_alignment, AttributeValue::Udata( - FullyMonomorphizedLayoutCx(tcx).layout_of(ty).align.pref.bytes(), + FullyMonomorphizedLayoutCx(tcx).layout_of(ty).align.abi.bytes(), ), ); member_entry.set( diff --git a/src/inline_asm.rs b/src/inline_asm.rs index f2b0ec977c63..310b226814d4 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -871,7 +871,8 @@ fn call_inline_asm<'tcx>( inputs: Vec<(Size, Value)>, outputs: Vec<(Size, CPlace<'tcx>)>, ) { - let stack_slot = fx.create_stack_slot(u32::try_from(slot_size.bytes()).unwrap(), 16); + let stack_slot = + fx.create_stack_slot(u32::try_from(slot_size.bytes().next_multiple_of(16)).unwrap(), 16); let inline_asm_func = fx .module diff --git a/src/value_and_place.rs b/src/value_and_place.rs index c17d1f30fbe3..a9b8e1bd3935 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -101,7 +101,7 @@ impl<'tcx> CValue<'tcx> { /// The is represented by a dangling pointer of suitable alignment. pub(crate) fn zst(layout: TyAndLayout<'tcx>) -> CValue<'tcx> { assert!(layout.is_zst()); - CValue::by_ref(crate::Pointer::dangling(layout.align.pref), layout) + CValue::by_ref(crate::Pointer::dangling(layout.align.abi), layout) } pub(crate) fn layout(&self) -> TyAndLayout<'tcx> { @@ -392,7 +392,7 @@ impl<'tcx> CPlace<'tcx> { assert!(layout.is_sized()); if layout.size.bytes() == 0 { return CPlace { - inner: CPlaceInner::Addr(Pointer::dangling(layout.align.pref), None), + inner: CPlaceInner::Addr(Pointer::dangling(layout.align.abi), None), layout, }; } @@ -405,7 +405,7 @@ impl<'tcx> CPlace<'tcx> { let stack_slot = fx.create_stack_slot( u32::try_from(layout.size.bytes()).unwrap(), - u32::try_from(layout.align.pref.bytes()).unwrap(), + u32::try_from(layout.align.abi.bytes()).unwrap(), ); CPlace { inner: CPlaceInner::Addr(stack_slot, None), layout } } From 287a9421d37dc8b5232c0afdf7d0f128178c19ac Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 15 Feb 2025 10:38:51 +0100 Subject: [PATCH 009/745] =?UTF-8?q?`comparison=5Fchain`:=20`style`=20?= =?UTF-8?q?=E2=86=92=20`pedantic`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `comparison_chain` lint might suggest code which seems less natural to beginners. [Discussion](https://rust-lang.zulipchat.com/#narrow/channel/257328-clippy/topic/demote.20some.20lints.20to.20.60pedantic.60) --- clippy_lints/src/comparison_chain.rs | 2 +- tests/ui/crashes/if_same_then_else.rs | 1 - tests/ui/ifs_same_cond.rs | 7 +----- tests/ui/ifs_same_cond.stderr | 16 ++++++------- tests/ui/same_functions_in_if_condition.rs | 7 +----- .../ui/same_functions_in_if_condition.stderr | 24 +++++++++---------- 6 files changed, 23 insertions(+), 34 deletions(-) diff --git a/clippy_lints/src/comparison_chain.rs b/clippy_lints/src/comparison_chain.rs index 61c92d441d09..0e7f01e44b04 100644 --- a/clippy_lints/src/comparison_chain.rs +++ b/clippy_lints/src/comparison_chain.rs @@ -53,7 +53,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.40.0"] pub COMPARISON_CHAIN, - style, + pedantic, "`if`s that can be rewritten with `match` and `cmp`" } diff --git a/tests/ui/crashes/if_same_then_else.rs b/tests/ui/crashes/if_same_then_else.rs index 58ee751948b5..8a27b3c6d47d 100644 --- a/tests/ui/crashes/if_same_then_else.rs +++ b/tests/ui/crashes/if_same_then_else.rs @@ -1,6 +1,5 @@ //@ check-pass -#![allow(clippy::comparison_chain)] #![deny(clippy::if_same_then_else)] // Test for https://github.com/rust-lang/rust-clippy/issues/2426 diff --git a/tests/ui/ifs_same_cond.rs b/tests/ui/ifs_same_cond.rs index 6ecb7cb1eba9..ebc3acb1b77f 100644 --- a/tests/ui/ifs_same_cond.rs +++ b/tests/ui/ifs_same_cond.rs @@ -1,10 +1,5 @@ #![warn(clippy::ifs_same_cond)] -#![allow( - clippy::if_same_then_else, - clippy::comparison_chain, - clippy::needless_if, - clippy::needless_else -)] // all empty blocks +#![allow(clippy::if_same_then_else, clippy::needless_if, clippy::needless_else)] // all empty blocks fn ifs_same_cond() { let a = 0; diff --git a/tests/ui/ifs_same_cond.stderr b/tests/ui/ifs_same_cond.stderr index 81fbb921e846..df21e6f1b826 100644 --- a/tests/ui/ifs_same_cond.stderr +++ b/tests/ui/ifs_same_cond.stderr @@ -1,11 +1,11 @@ error: this `if` has the same condition as a previous `if` - --> tests/ui/ifs_same_cond.rs:14:15 + --> tests/ui/ifs_same_cond.rs:9:15 | LL | } else if b { | ^ | note: same as this - --> tests/ui/ifs_same_cond.rs:13:8 + --> tests/ui/ifs_same_cond.rs:8:8 | LL | if b { | ^ @@ -13,37 +13,37 @@ LL | if b { = help: to override `-D warnings` add `#[allow(clippy::ifs_same_cond)]` error: this `if` has the same condition as a previous `if` - --> tests/ui/ifs_same_cond.rs:19:15 + --> tests/ui/ifs_same_cond.rs:14:15 | LL | } else if a == 1 { | ^^^^^^ | note: same as this - --> tests/ui/ifs_same_cond.rs:18:8 + --> tests/ui/ifs_same_cond.rs:13:8 | LL | if a == 1 { | ^^^^^^ error: this `if` has the same condition as a previous `if` - --> tests/ui/ifs_same_cond.rs:25:15 + --> tests/ui/ifs_same_cond.rs:20:15 | LL | } else if 2 * a == 1 { | ^^^^^^^^^^ | note: same as this - --> tests/ui/ifs_same_cond.rs:23:8 + --> tests/ui/ifs_same_cond.rs:18:8 | LL | if 2 * a == 1 { | ^^^^^^^^^^ error: this `if` has the same condition as a previous `if` - --> tests/ui/ifs_same_cond.rs:58:15 + --> tests/ui/ifs_same_cond.rs:53:15 | LL | } else if a.contains("ah") { | ^^^^^^^^^^^^^^^^ | note: same as this - --> tests/ui/ifs_same_cond.rs:57:8 + --> tests/ui/ifs_same_cond.rs:52:8 | LL | if a.contains("ah") { | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/same_functions_in_if_condition.rs b/tests/ui/same_functions_in_if_condition.rs index b7ed3aab0043..a98b73c9e1c8 100644 --- a/tests/ui/same_functions_in_if_condition.rs +++ b/tests/ui/same_functions_in_if_condition.rs @@ -3,12 +3,7 @@ // ifs_same_cond warning is different from `ifs_same_cond`. // clippy::if_same_then_else, clippy::comparison_chain -- all empty blocks #![allow(incomplete_features)] -#![allow( - clippy::comparison_chain, - clippy::if_same_then_else, - clippy::ifs_same_cond, - clippy::uninlined_format_args -)] +#![allow(clippy::if_same_then_else, clippy::ifs_same_cond, clippy::uninlined_format_args)] use std::marker::ConstParamTy; diff --git a/tests/ui/same_functions_in_if_condition.stderr b/tests/ui/same_functions_in_if_condition.stderr index 6cd4f96c13e3..35dcbadce595 100644 --- a/tests/ui/same_functions_in_if_condition.stderr +++ b/tests/ui/same_functions_in_if_condition.stderr @@ -1,11 +1,11 @@ error: this `if` has the same function call as a previous `if` - --> tests/ui/same_functions_in_if_condition.rs:39:15 + --> tests/ui/same_functions_in_if_condition.rs:34:15 | LL | } else if function() { | ^^^^^^^^^^ | note: same as this - --> tests/ui/same_functions_in_if_condition.rs:38:8 + --> tests/ui/same_functions_in_if_condition.rs:33:8 | LL | if function() { | ^^^^^^^^^^ @@ -16,61 +16,61 @@ LL | #![deny(clippy::same_functions_in_if_condition)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this `if` has the same function call as a previous `if` - --> tests/ui/same_functions_in_if_condition.rs:44:15 + --> tests/ui/same_functions_in_if_condition.rs:39:15 | LL | } else if fn_arg(a) { | ^^^^^^^^^ | note: same as this - --> tests/ui/same_functions_in_if_condition.rs:43:8 + --> tests/ui/same_functions_in_if_condition.rs:38:8 | LL | if fn_arg(a) { | ^^^^^^^^^ error: this `if` has the same function call as a previous `if` - --> tests/ui/same_functions_in_if_condition.rs:49:15 + --> tests/ui/same_functions_in_if_condition.rs:44:15 | LL | } else if obj.method() { | ^^^^^^^^^^^^ | note: same as this - --> tests/ui/same_functions_in_if_condition.rs:48:8 + --> tests/ui/same_functions_in_if_condition.rs:43:8 | LL | if obj.method() { | ^^^^^^^^^^^^ error: this `if` has the same function call as a previous `if` - --> tests/ui/same_functions_in_if_condition.rs:54:15 + --> tests/ui/same_functions_in_if_condition.rs:49:15 | LL | } else if obj.method_arg(a) { | ^^^^^^^^^^^^^^^^^ | note: same as this - --> tests/ui/same_functions_in_if_condition.rs:53:8 + --> tests/ui/same_functions_in_if_condition.rs:48:8 | LL | if obj.method_arg(a) { | ^^^^^^^^^^^^^^^^^ error: this `if` has the same function call as a previous `if` - --> tests/ui/same_functions_in_if_condition.rs:60:15 + --> tests/ui/same_functions_in_if_condition.rs:55:15 | LL | } else if v.pop().is_none() { | ^^^^^^^^^^^^^^^^^ | note: same as this - --> tests/ui/same_functions_in_if_condition.rs:59:8 + --> tests/ui/same_functions_in_if_condition.rs:54:8 | LL | if v.pop().is_none() { | ^^^^^^^^^^^^^^^^^ error: this `if` has the same function call as a previous `if` - --> tests/ui/same_functions_in_if_condition.rs:65:15 + --> tests/ui/same_functions_in_if_condition.rs:60:15 | LL | } else if v.len() == 42 { | ^^^^^^^^^^^^^ | note: same as this - --> tests/ui/same_functions_in_if_condition.rs:64:8 + --> tests/ui/same_functions_in_if_condition.rs:59:8 | LL | if v.len() == 42 { | ^^^^^^^^^^^^^ From b141440f8621e238941f1b79a4e9ea7bcd9c38bc Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 3 Feb 2025 10:45:49 +1100 Subject: [PATCH 010/745] Move some `Map` methods onto `TyCtxt`. The end goal is to eliminate `Map` altogether. I added a `hir_` prefix to all of them, that seemed simplest. The exceptions are `module_items` which became `hir_module_free_items` because there was already a `hir_module_items`, and `items` which became `hir_free_items` for consistency with `hir_module_free_items`. --- src/driver/jit.rs | 2 +- src/global_asm.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 2e713171ae06..57c88f4b0f9f 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -124,7 +124,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec< crate::constant::codegen_static(tcx, &mut jit_module, def_id); } MonoItem::GlobalAsm(item_id) => { - let item = tcx.hir().item(item_id); + let item = tcx.hir_item(item_id); tcx.dcx().span_fatal(item.span, "Global asm is not supported in JIT mode"); } } diff --git a/src/global_asm.rs b/src/global_asm.rs index c0a3ce84d529..54745b0d8c10 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -15,7 +15,7 @@ use rustc_target::asm::InlineAsmArch; use crate::prelude::*; pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) { - let item = tcx.hir().item(item_id); + let item = tcx.hir_item(item_id); if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind { let is_x86 = matches!(tcx.sess.asm_arch.unwrap(), InlineAsmArch::X86 | InlineAsmArch::X86_64); From 6321ac79e1a24b4be336a8b6f3dd426251b773d4 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 17 Feb 2025 13:06:57 -0700 Subject: [PATCH 011/745] needless_collect: look through assignments, not just declarations --- clippy_lints/src/methods/needless_collect.rs | 7 +++++++ tests/ui/needless_collect.fixed | 9 +++++++++ tests/ui/needless_collect.rs | 9 +++++++++ 3 files changed, 25 insertions(+) diff --git a/clippy_lints/src/methods/needless_collect.rs b/clippy_lints/src/methods/needless_collect.rs index 6732aeeb4985..def7bf635daf 100644 --- a/clippy_lints/src/methods/needless_collect.rs +++ b/clippy_lints/src/methods/needless_collect.rs @@ -546,6 +546,12 @@ impl<'tcx> Visitor<'tcx> for IteratorMethodCheckVisitor<'_, 'tcx> { && !is_trait_method(self.cx, expr, sym::Iterator) { return ControlFlow::Break(()); + } else if let ExprKind::Assign(place, value, _span) = &expr.kind + && value.hir_id == self.hir_id_of_expr + && let Some(id) = path_to_local(place) + { + // our iterator was directly assigned to a variable + self.hir_id_of_let_binding = Some(id); } walk_expr(self, expr) } @@ -561,6 +567,7 @@ impl<'tcx> Visitor<'tcx> for IteratorMethodCheckVisitor<'_, 'tcx> { }) = &stmt.kind && expr.hir_id == self.hir_id_of_expr { + // our iterator was directly assigned to a variable self.hir_id_of_let_binding = Some(*id); } walk_stmt(self, stmt) diff --git a/tests/ui/needless_collect.fixed b/tests/ui/needless_collect.fixed index e33b984a44b5..8a0208e4a7ed 100644 --- a/tests/ui/needless_collect.fixed +++ b/tests/ui/needless_collect.fixed @@ -87,6 +87,15 @@ fn main() { let my_collection: Vec<()> = vec![()].into_iter().map(|()| {}).collect(); let my_iter = my_collection.into_iter(); let _sliced = my_iter.as_slice(); + // Assignment outside of main scope + { + let x; + { + let xxx: Vec<()> = vec![()].into_iter().map(|()| {}).collect(); + x = xxx.into_iter(); + for i in x.as_slice() {} + } + } } fn foo(_: impl IntoIterator) {} diff --git a/tests/ui/needless_collect.rs b/tests/ui/needless_collect.rs index fab00d67dbfd..b7e8e7b90b14 100644 --- a/tests/ui/needless_collect.rs +++ b/tests/ui/needless_collect.rs @@ -87,6 +87,15 @@ fn main() { let my_collection: Vec<()> = vec![()].into_iter().map(|()| {}).collect(); let my_iter = my_collection.into_iter(); let _sliced = my_iter.as_slice(); + // Assignment outside of main scope + { + let x; + { + let xxx: Vec<()> = vec![()].into_iter().map(|()| {}).collect(); + x = xxx.into_iter(); + for i in x.as_slice() {} + } + } } fn foo(_: impl IntoIterator) {} From 44af9d30ff49f0d9fa360222a5a8f68c1a42877b Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 11 Feb 2025 22:33:18 -0800 Subject: [PATCH 012/745] cg_clif: use exclusively ABI alignment --- src/abi/comments.rs | 5 ++--- src/constant.rs | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/abi/comments.rs b/src/abi/comments.rs index 521a250ab82c..e2c9f40d1479 100644 --- a/src/abi/comments.rs +++ b/src/abi/comments.rs @@ -65,7 +65,7 @@ pub(super) fn add_locals_header_comment(fx: &mut FunctionCx<'_, '_, '_>) { if fx.clif_comments.enabled() { fx.add_global_comment(String::new()); fx.add_global_comment( - "kind local ty size align (abi,pref)".to_string(), + "kind local ty size align (abi)".to_string(), ); } } @@ -84,13 +84,12 @@ pub(super) fn add_local_place_comments<'tcx>( let (kind, extra) = place.debug_comment(); fx.add_global_comment(format!( - "{:<5} {:5} {:30} {:4}b {}, {}{}{}", + "{:<5} {:5} {:30} {:4}b {}, {}{}", kind, format!("{:?}", local), format!("{:?}", ty), size.bytes(), align.abi.bytes(), - align.pref.bytes(), if extra.is_empty() { "" } else { " " }, extra, )); diff --git a/src/constant.rs b/src/constant.rs index 425b2adf32a3..bcc70f4567fb 100644 --- a/src/constant.rs +++ b/src/constant.rs @@ -272,7 +272,7 @@ fn data_id_for_static( .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) .unwrap() .align - .pref + .abi .bytes(); let linkage = if import_linkage == rustc_middle::mir::mono::Linkage::ExternalWeak From 616fe134c258e0aa4e139a2caf3280a4249a66b4 Mon Sep 17 00:00:00 2001 From: Jubilee Date: Tue, 18 Feb 2025 01:29:23 -0800 Subject: [PATCH 013/745] cg_clif: Tweak formatting of global comments Co-authored-by: bjorn3 <17426603+bjorn3@users.noreply.github.com> --- src/abi/comments.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/abi/comments.rs b/src/abi/comments.rs index e2c9f40d1479..c74efeb59f3f 100644 --- a/src/abi/comments.rs +++ b/src/abi/comments.rs @@ -84,13 +84,13 @@ pub(super) fn add_local_place_comments<'tcx>( let (kind, extra) = place.debug_comment(); fx.add_global_comment(format!( - "{:<5} {:5} {:30} {:4}b {}, {}{}", + "{:<5} {:5} {:30} {:4}b {}{}{}", kind, format!("{:?}", local), format!("{:?}", ty), size.bytes(), align.abi.bytes(), - if extra.is_empty() { "" } else { " " }, + if extra.is_empty() { "" } else { " " }, extra, )); } From 3fc1a5852193e6be4d9ef3d05f70ac167eb31091 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 19 Feb 2025 09:25:24 +0000 Subject: [PATCH 014/745] Rustup to rustc 1.87.0-nightly (827a0d638 2025-02-18) --- patches/coretests-lock.toml | 75 +++++++++++++++++++++++++++++++++---- rust-toolchain | 2 +- 2 files changed, 68 insertions(+), 9 deletions(-) diff --git a/patches/coretests-lock.toml b/patches/coretests-lock.toml index af8f28a193bc..bb7f519f7a7c 100644 --- a/patches/coretests-lock.toml +++ b/patches/coretests-lock.toml @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "coretests" @@ -11,25 +11,84 @@ dependencies = [ ] [[package]] -name = "rand" -version = "0.8.5" +name = "proc-macro2" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ "rand_core", + "zerocopy", ] [[package]] name = "rand_core" -version = "0.6.4" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "a88e0da7a2c97baa202165137c158d0a2e824ac465d13d81046727b34cb247d3" +dependencies = [ + "zerocopy", +] [[package]] name = "rand_xorshift" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" dependencies = [ "rand_core", ] + +[[package]] +name = "syn" +version = "2.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe" + +[[package]] +name = "zerocopy" +version = "0.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79386d31a42a4996e3336b0919ddb90f81112af416270cff95b5f5af22b839c2" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76331675d372f91bf8d17e13afbd5fe639200b73d01f0fc748bb059f9cca2db7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/rust-toolchain b/rust-toolchain index 481903c6afb2..854ca5db8011 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-02-15" +channel = "nightly-2025-02-19" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From e297c84703593fc5fccdef42714ccf9f40e94823 Mon Sep 17 00:00:00 2001 From: alexey semenyuk Date: Wed, 19 Feb 2025 18:23:47 +0500 Subject: [PATCH 015/745] Remove Known problems section for vec_box --- clippy_lints/src/types/mod.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/clippy_lints/src/types/mod.rs b/clippy_lints/src/types/mod.rs index 579cbf447a2b..146fb75a5f76 100644 --- a/clippy_lints/src/types/mod.rs +++ b/clippy_lints/src/types/mod.rs @@ -60,10 +60,6 @@ declare_clippy_lint! { /// `Vec` already keeps its contents in a separate area on /// the heap. So if you `Box` its contents, you just add another level of indirection. /// - /// ### Known problems - /// Vec> makes sense if T is a large type (see [#3530](https://github.com/rust-lang/rust-clippy/issues/3530), - /// 1st comment). - /// /// ### Example /// ```no_run /// struct X { From 410a68a907b14db7eaa2152eccbbcef9ae357f7c Mon Sep 17 00:00:00 2001 From: Zachary S Date: Sat, 25 Jan 2025 20:15:24 -0600 Subject: [PATCH 016/745] Remove `BackendRepr::Uninhabited`, replaced with an `uninhabited: bool` field in `LayoutData`. Also update comments that refered to BackendRepr::Uninhabited. --- src/value_and_place.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/value_and_place.rs b/src/value_and_place.rs index a9b8e1bd3935..1b3f86c8405d 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -638,9 +638,7 @@ impl<'tcx> CPlace<'tcx> { } CPlaceInner::Addr(_, Some(_)) => bug!("Can't write value to unsized place {:?}", self), CPlaceInner::Addr(to_ptr, None) => { - if dst_layout.size == Size::ZERO - || dst_layout.backend_repr == BackendRepr::Uninhabited - { + if dst_layout.size == Size::ZERO { return; } From 8622c818e2474b1973cce49b11c4826c2d3f93d9 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 28 Jan 2025 22:25:23 +0000 Subject: [PATCH 017/745] Use `public-dependencies` in all sysroot crates In [1], most dependencies of `std` and other sysroot crates were marked private, but this did not happen for `alloc` and `test`. Update these here, marking public standard library crates as the only non-private dependencies. [1]: https://github.com/rust-lang/rust/pull/111076 --- .../0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index e3a9512dda9c..eb1fc4b0ad59 100644 --- a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -15,7 +15,7 @@ index 7165c3e48af..968552ad435 100644 edition = "2021" [dependencies] - core = { path = "../core" } + core = { path = "../core", public = true } -compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std', 'no-f16-f128'] } From 9dd86e64cc19d24d5e62a028cae4515a1fbe95c2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 17 Feb 2025 05:33:06 +0000 Subject: [PATCH 018/745] Make asm a named field --- src/global_asm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/global_asm.rs b/src/global_asm.rs index 54745b0d8c10..0a23f63d6ba9 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -16,7 +16,7 @@ use crate::prelude::*; pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) { let item = tcx.hir_item(item_id); - if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind { + if let rustc_hir::ItemKind::GlobalAsm { asm } = item.kind { let is_x86 = matches!(tcx.sess.asm_arch.unwrap(), InlineAsmArch::X86 | InlineAsmArch::X86_64); From ea760dd09911d5bd73fd8a4321f319620e0cc53a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 17 Feb 2025 16:09:46 +0000 Subject: [PATCH 019/745] Make a fake body to store typeck results for global_asm --- src/global_asm.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/global_asm.rs b/src/global_asm.rs index 0a23f63d6ba9..9ea92c300f89 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -16,7 +16,7 @@ use crate::prelude::*; pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) { let item = tcx.hir_item(item_id); - if let rustc_hir::ItemKind::GlobalAsm { asm } = item.kind { + if let rustc_hir::ItemKind::GlobalAsm { asm, .. } = item.kind { let is_x86 = matches!(tcx.sess.asm_arch.unwrap(), InlineAsmArch::X86 | InlineAsmArch::X86_64); @@ -55,7 +55,7 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, } } } - InlineAsmOperand::SymFn { anon_const } => { + InlineAsmOperand::SymFn { expr } => { if cfg!(not(feature = "inline_asm_sym")) { tcx.dcx().span_err( item.span, @@ -63,7 +63,7 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, ); } - let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id); + let ty = tcx.typeck(item_id.owner_id).expr_ty(expr); let instance = match ty.kind() { &ty::FnDef(def_id, args) => Instance::new(def_id, args), _ => span_bug!(op_sp, "asm sym is not a function"), From 5ff55a4783e09ce3eda33e0db0a419c15a7f8b00 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 22 Feb 2025 11:42:10 +0000 Subject: [PATCH 020/745] Rustup to rustc 1.87.0-nightly (794c12416 2025-02-21) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 854ca5db8011..1017b9550d03 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-02-19" +channel = "nightly-2025-02-22" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From af40c23215dc9e82041dab9e6d40b376b88313e9 Mon Sep 17 00:00:00 2001 From: lapla-cogito Date: Fri, 7 Feb 2025 16:40:10 +0900 Subject: [PATCH 021/745] fix suggestion for assignments wrapped in parentheses under `needless_late_init` --- clippy_lints/src/needless_late_init.rs | 9 +++++---- tests/ui/needless_late_init.fixed | 6 ++++++ tests/ui/needless_late_init.rs | 6 ++++++ tests/ui/needless_late_init.stderr | 18 +++++++++++++++++- 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/needless_late_init.rs b/clippy_lints/src/needless_late_init.rs index 4e19a2f409dd..6960371fc4a5 100644 --- a/clippy_lints/src/needless_late_init.rs +++ b/clippy_lints/src/needless_late_init.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::path_to_local; -use clippy_utils::source::{SourceText, SpanRangeExt}; +use clippy_utils::source::{SourceText, SpanRangeExt, snippet}; use clippy_utils::ty::needs_ordered_drop; use clippy_utils::visitors::{for_each_expr, for_each_expr_without_closures, is_local_used}; use core::ops::ControlFlow; @@ -100,7 +100,6 @@ fn stmt_needs_ordered_drop(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool { #[derive(Debug)] struct LocalAssign { lhs_id: HirId, - lhs_span: Span, rhs_span: Span, span: Span, } @@ -118,7 +117,6 @@ impl LocalAssign { Some(Self { lhs_id: path_to_local(lhs)?, - lhs_span: lhs.span, rhs_span: rhs.span.source_callsite(), span, }) @@ -281,7 +279,10 @@ fn check<'tcx>( format!("move the declaration `{binding_name}` here"), vec![ (local_stmt.span, String::new()), - (assign.lhs_span, let_snippet.to_owned()), + ( + assign.span, + let_snippet.to_owned() + " = " + &snippet(cx, assign.rhs_span, ".."), + ), ], Applicability::MachineApplicable, ); diff --git a/tests/ui/needless_late_init.fixed b/tests/ui/needless_late_init.fixed index eb67e6cc8282..391d4bc3fcc7 100644 --- a/tests/ui/needless_late_init.fixed +++ b/tests/ui/needless_late_init.fixed @@ -297,3 +297,9 @@ fn issue13776() { let x; issue13776_mac!(x, 10); // should not lint } + +fn issue9895() { + + //~^ needless_late_init + let r = 5; +} diff --git a/tests/ui/needless_late_init.rs b/tests/ui/needless_late_init.rs index 7de2202dc323..6096e8300e1a 100644 --- a/tests/ui/needless_late_init.rs +++ b/tests/ui/needless_late_init.rs @@ -297,3 +297,9 @@ fn issue13776() { let x; issue13776_mac!(x, 10); // should not lint } + +fn issue9895() { + let r; + //~^ needless_late_init + (r = 5); +} diff --git a/tests/ui/needless_late_init.stderr b/tests/ui/needless_late_init.stderr index 02fd2811da58..e7c36136847b 100644 --- a/tests/ui/needless_late_init.stderr +++ b/tests/ui/needless_late_init.stderr @@ -275,5 +275,21 @@ LL | }, LL ~ }; | -error: aborting due to 16 previous errors +error: unneeded late initialization + --> tests/ui/needless_late_init.rs:302:5 + | +LL | let r; + | ^^^^^^ created here +LL | +LL | (r = 5); + | ^^^^^^^ initialised here + | +help: move the declaration `r` here + | +LL ~ +LL | +LL ~ let r = 5; + | + +error: aborting due to 17 previous errors From c7b251e09e097a9b33bcaf5ae677ac641da9a360 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 19 Feb 2025 20:17:02 -0500 Subject: [PATCH 022/745] Update `compiler-builtins` to 0.1.147 Removes an ABI hack that used `<2 x i64>` to return `i128` in `xmm0` on Windows [1]. [1]: https://github.com/rust-lang/compiler-builtins/pull/759 Link: https://github.com/rust-lang/rust/issues/116558 Link: https://github.com/rust-lang/compiler-builtins/issues/758 --- ...029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index eb1fc4b0ad59..364a6a035ab8 100644 --- a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -16,8 +16,8 @@ index 7165c3e48af..968552ad435 100644 [dependencies] core = { path = "../core", public = true } --compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std', 'no-f16-f128'] } +-compiler_builtins = { version = "=0.1.147", features = ['rustc-dep-of-std'] } ++compiler_builtins = { version = "=0.1.147", features = ['rustc-dep-of-std', 'no-f16-f128'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } From 447d85845de2dc68ec366c27cb1d1b65a1ba6e75 Mon Sep 17 00:00:00 2001 From: DianQK Date: Sun, 17 Nov 2024 14:21:23 +0800 Subject: [PATCH 023/745] The embedded bitcode should always be prepared for LTO/ThinLTO --- src/driver/aot.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index a52b18573b15..366e83853e51 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -210,7 +210,7 @@ fn produce_final_output_artifacts( // to get rid of it. for output_type in crate_output.outputs.keys() { match *output_type { - OutputType::Bitcode | OutputType::ThinLinkBitcode => { + OutputType::Bitcode | OutputType::ThinLinkBitcode | OutputType::ThinBitcode => { // Cranelift doesn't have bitcode // user_wants_bitcode = true; // // Copy to .bc, but always keep the .0.bc. There is a later From 016f429c56992f2d62717fe2b6554ca4c4dd1f4a Mon Sep 17 00:00:00 2001 From: DianQK Date: Thu, 6 Feb 2025 22:01:08 +0800 Subject: [PATCH 024/745] Remove unused `OutputType::ThinLinkBitcode` --- src/driver/aot.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 366e83853e51..a52b18573b15 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -210,7 +210,7 @@ fn produce_final_output_artifacts( // to get rid of it. for output_type in crate_output.outputs.keys() { match *output_type { - OutputType::Bitcode | OutputType::ThinLinkBitcode | OutputType::ThinBitcode => { + OutputType::Bitcode | OutputType::ThinLinkBitcode => { // Cranelift doesn't have bitcode // user_wants_bitcode = true; // // Copy to .bc, but always keep the .0.bc. There is a later From 63a3ab4fae27ffc6af807598a5634546f9c05a9f Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 24 Feb 2025 02:47:59 +0000 Subject: [PATCH 025/745] Add a span to `CompilerBuiltinsCannotCall` Currently, this error emit a diagnostic with no context like: error: `compiler_builtins` cannot call functions through upstream monomorphizations; encountered invalid call from ` as core::fmt::LowerHex>::fmt` to `core::fmt::num::::fmt` With this change, it at least usually points to the problematic function: error: `compiler_builtins` cannot call functions through upstream monomorphizations; encountered invalid call from ` as core::fmt::LowerHex>::fmt` to `core::fmt::num::::fmt` --> src/../libm/src/math/support/hex_float.rs:270:5 | 270 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | --- src/abi/mod.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index 756a2226753f..e8076ce77abc 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -402,9 +402,13 @@ pub(crate) fn codegen_terminator_call<'tcx>( if is_call_from_compiler_builtins_to_upstream_monomorphization(fx.tcx, instance) { if target.is_some() { - let caller = with_no_trimmed_paths!(fx.tcx.def_path_str(fx.instance.def_id())); - let callee = with_no_trimmed_paths!(fx.tcx.def_path_str(def_id)); - fx.tcx.dcx().emit_err(CompilerBuiltinsCannotCall { caller, callee }); + let caller_def = fx.instance.def_id(); + let e = CompilerBuiltinsCannotCall { + span: fx.tcx.def_span(caller_def), + caller: with_no_trimmed_paths!(fx.tcx.def_path_str(caller_def)), + callee: with_no_trimmed_paths!(fx.tcx.def_path_str(def_id)), + }; + fx.tcx.dcx().emit_err(e); } else { fx.bcx.ins().trap(TrapCode::user(2).unwrap()); return; From 957389c196d744a68c51dd265e6ec63f984f80a4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 23 Feb 2025 17:34:50 +0100 Subject: [PATCH 026/745] remove support for rustc_intrinsic_must_be_overridden from the compiler --- example/mini_core.rs | 65 +++++++++----------------------------------- 1 file changed, 13 insertions(+), 52 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index 79820232496a..72c9df59d833 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -620,70 +620,31 @@ pub union MaybeUninit { pub mod intrinsics { #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } + pub fn abort() -> !; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn size_of() -> usize { - loop {} - } + pub fn size_of() -> usize; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn size_of_val(_val: *const T) -> usize { - loop {} - } + pub unsafe fn size_of_val(_val: *const T) -> usize; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn min_align_of() -> usize { - loop {} - } + pub fn min_align_of() -> usize; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn min_align_of_val(_val: *const T) -> usize { - loop {} - } + pub unsafe fn min_align_of_val(_val: *const T) -> usize; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn copy(_src: *const T, _dst: *mut T, _count: usize) { - loop {} - } + pub unsafe fn copy(_src: *const T, _dst: *mut T, _count: usize); #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn transmute(_e: T) -> U { - loop {} - } + pub unsafe fn transmute(_e: T) -> U; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn ctlz_nonzero(_x: T) -> u32 { - loop {} - } + pub unsafe fn ctlz_nonzero(_x: T) -> u32; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn needs_drop() -> bool { - loop {} - } + pub fn needs_drop() -> bool; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn bitreverse(_x: T) -> T { - loop {} - } + pub fn bitreverse(_x: T) -> T; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn bswap(_x: T) -> T { - loop {} - } + pub fn bswap(_x: T) -> T; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn write_bytes(_dst: *mut T, _val: u8, _count: usize) { - loop {} - } + pub unsafe fn write_bytes(_dst: *mut T, _val: u8, _count: usize); #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn unreachable() -> ! { - loop {} - } + pub unsafe fn unreachable() -> !; } pub mod libc { From be4eb9a3aa976e864d69f7c361cca8779c8d09f7 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 24 Feb 2025 07:46:55 +0000 Subject: [PATCH 027/745] Update `compiler-builtins` to 0.1.148 Includes `f16` symbols on MIPS [1], updates for `libm` [2], and reapplies the patch that drops the `public_test_deps!` macro [3]. [1]: https://github.com/rust-lang/compiler-builtins/pull/762 [2]: https://github.com/rust-lang/compiler-builtins/pull/765 [3]: https://github.com/rust-lang/compiler-builtins/pull/766 --- ...029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index 364a6a035ab8..bedc6ca11b3f 100644 --- a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -16,8 +16,8 @@ index 7165c3e48af..968552ad435 100644 [dependencies] core = { path = "../core", public = true } --compiler_builtins = { version = "=0.1.147", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "=0.1.147", features = ['rustc-dep-of-std', 'no-f16-f128'] } +-compiler_builtins = { version = "=0.1.148", features = ['rustc-dep-of-std'] } ++compiler_builtins = { version = "=0.1.148", features = ['rustc-dep-of-std', 'no-f16-f128'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } From fb85ef70fc599827ed520df32eb486b0d80ce29e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 24 Feb 2025 14:21:50 +0000 Subject: [PATCH 028/745] Rustup to rustc 1.87.0-nightly (f8a913b13 2025-02-23) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 1017b9550d03..94b1403e47c1 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-02-22" +channel = "nightly-2025-02-24" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From ae5f2c2d5cd7734d77c9b87de272b96783e5e18b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 24 Feb 2025 14:35:19 +0000 Subject: [PATCH 029/745] Fix rustc test suite --- scripts/test_rustc_tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index 55230a0b5988..599ce63bab56 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -57,7 +57,6 @@ rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't rm tests/ui/asm/x86_64/goto.rs # inline asm labels not supported rm tests/ui/simd/simd-bitmask-notpow2.rs # non-pow-of-2 simd vector sizes rm -r tests/run-make/embed-source-dwarf # embedding sources in debuginfo -rm tests/ui/simd-abi-checks.rs # vector types >128bits not yet supported # requires LTO rm -r tests/run-make/cdylib @@ -120,6 +119,7 @@ rm tests/ui/mir/mir_raw_fat_ptr.rs # same rm tests/ui/consts/issue-33537.rs # same rm tests/ui/consts/const-mut-refs-crate.rs # same rm tests/ui/abi/large-byval-align.rs # exceeds implementation limit of Cranelift +rm tests/ui/abi/simd-abi-checks-avx.rs # attempts to declare function with two different signatures # doesn't work due to the way the rustc test suite is invoked. # should work when using ./x.py test the way it is intended From a91db48ecf32f3e4c188679aee9897e107d31295 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 24 Feb 2025 19:10:55 +0100 Subject: [PATCH 030/745] =?UTF-8?q?rename=20simd=5Fshuffle=5Fgeneric=20?= =?UTF-8?q?=E2=86=92=20simd=5Fshuffle=5Fconst=5Fgeneric?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/intrinsics/simd.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index fcccda62355c..0929218ea2b2 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -116,8 +116,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }); } - // simd_shuffle_generic(x: T, y: T) -> U - sym::simd_shuffle_generic => { + // simd_shuffle_const_generic(x: T, y: T) -> U + sym::simd_shuffle_const_generic => { let [x, y] = args else { bug!("wrong number of args for intrinsic {intrinsic}"); }; From cae7c76d509386ea29a90c4001bb8dbc59c79d22 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 28 Jul 2024 16:54:14 -0400 Subject: [PATCH 031/745] Avoid no-op unlink+link dances in incr comp --- .../rustc_codegen_cranelift/src/driver/aot.rs | 8 ++++- compiler/rustc_codegen_ssa/src/back/write.rs | 21 ++++++++---- compiler/rustc_codegen_ssa/src/base.rs | 1 + compiler/rustc_codegen_ssa/src/lib.rs | 2 ++ compiler/rustc_fs_util/src/lib.rs | 32 +++++++++++-------- .../src/persist/work_product.rs | 7 +++- 6 files changed, 50 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index a52b18573b15..d1843f90a07d 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -103,12 +103,14 @@ impl OngoingCodegen { ("o", &module_regular.object.as_ref().unwrap()), ("asm.o", &module_global_asm.object.as_ref().unwrap()), ], + &[], ) } else { rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( sess, &module_regular.name, &[("o", &module_regular.object.as_ref().unwrap())], + &[], ) }; if let Some((work_product_id, work_product)) = work_product { @@ -381,6 +383,7 @@ fn emit_cgu( bytecode: None, assembly: None, llvm_ir: None, + links_from_incr_cache: Vec::new(), }), existing_work_product: None, }) @@ -437,6 +440,7 @@ fn emit_module( bytecode: None, assembly: None, llvm_ir: None, + links_from_incr_cache: Vec::new(), }) } @@ -487,6 +491,7 @@ fn reuse_workproduct_for_cgu( bytecode: None, assembly: None, llvm_ir: None, + links_from_incr_cache: Vec::new(), }, module_global_asm: has_global_asm.then(|| CompiledModule { name: cgu.name().to_string(), @@ -496,6 +501,7 @@ fn reuse_workproduct_for_cgu( bytecode: None, assembly: None, llvm_ir: None, + links_from_incr_cache: Vec::new(), }), existing_work_product: Some((cgu.work_product_id(), work_product)), }) @@ -637,6 +643,7 @@ fn emit_metadata_module(tcx: TyCtxt<'_>, metadata: &EncodedMetadata) -> Compiled bytecode: None, assembly: None, llvm_ir: None, + links_from_incr_cache: Vec::new(), } } @@ -745,7 +752,6 @@ pub(crate) fn run_aot( let metadata_module = if need_metadata_module { Some(emit_metadata_module(tcx, &metadata)) } else { None }; - Box::new(OngoingCodegen { modules, allocator_module, diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index f008bd12ed8f..b8dc6f93349b 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -540,9 +540,12 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir( if let Some(path) = &module.bytecode { files.push((OutputType::Bitcode.extension(), path.as_path())); } - if let Some((id, product)) = - copy_cgu_workproduct_to_incr_comp_cache_dir(sess, &module.name, files.as_slice()) - { + if let Some((id, product)) = copy_cgu_workproduct_to_incr_comp_cache_dir( + sess, + &module.name, + files.as_slice(), + &module.links_from_incr_cache, + ) { work_products.insert(id, product); } } @@ -934,7 +937,9 @@ fn execute_copy_from_cache_work_item( ) -> WorkItemResult { let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap(); - let load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| { + let mut links_from_incr_cache = Vec::new(); + + let mut load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| { let source_file = in_incr_comp_dir(incr_comp_session_dir, saved_path); debug!( "copying preexisting module `{}` from {:?} to {}", @@ -943,7 +948,10 @@ fn execute_copy_from_cache_work_item( output_path.display() ); match link_or_copy(&source_file, &output_path) { - Ok(_) => Some(output_path), + Ok(_) => { + links_from_incr_cache.push(source_file); + Some(output_path) + } Err(error) => { cgcx.create_dcx().handle().emit_err(errors::CopyPathBuf { source_file, @@ -966,7 +974,7 @@ fn execute_copy_from_cache_work_item( load_from_incr_comp_dir(dwarf_obj_out, saved_dwarf_object_file) }); - let load_from_incr_cache = |perform, output_type: OutputType| { + let mut load_from_incr_cache = |perform, output_type: OutputType| { if perform { let saved_file = module.source.saved_files.get(output_type.extension())?; let output_path = cgcx.output_filenames.temp_path(output_type, Some(&module.name)); @@ -986,6 +994,7 @@ fn execute_copy_from_cache_work_item( } WorkItemResult::Finished(CompiledModule { + links_from_incr_cache, name: module.name, kind: ModuleKind::Regular, object, diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 40238f4b4915..e4db2bed9e8d 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -656,6 +656,7 @@ pub fn codegen_crate( bytecode: None, assembly: None, llvm_ir: None, + links_from_incr_cache: Vec::new(), } }) }); diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 9d2ac219d592..7ff97f127e03 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -102,6 +102,7 @@ impl ModuleCodegen { bytecode, assembly, llvm_ir, + links_from_incr_cache: Vec::new(), } } } @@ -115,6 +116,7 @@ pub struct CompiledModule { pub bytecode: Option, pub assembly: Option, // --emit=asm pub llvm_ir: Option, // --emit=llvm-ir, llvm-bc is in bytecode + pub links_from_incr_cache: Vec, } impl CompiledModule { diff --git a/compiler/rustc_fs_util/src/lib.rs b/compiler/rustc_fs_util/src/lib.rs index 4e9d21c900df..0df1b243d697 100644 --- a/compiler/rustc_fs_util/src/lib.rs +++ b/compiler/rustc_fs_util/src/lib.rs @@ -55,25 +55,31 @@ pub enum LinkOrCopy { Copy, } -/// Copies `p` into `q`, preferring to use hard-linking if possible. If -/// `q` already exists, it is removed first. +/// Copies `p` into `q`, preferring to use hard-linking if possible. /// The result indicates which of the two operations has been performed. pub fn link_or_copy, Q: AsRef>(p: P, q: Q) -> io::Result { + // Creating a hard-link will fail if the destination path already exists. We could defensively + // call remove_file in this function, but that pessimizes callers who can avoid such calls. + // Incremental compilation calls this function a lot, and is able to avoid calls that + // would fail the first hard_link attempt. + let p = p.as_ref(); let q = q.as_ref(); - match fs::remove_file(q) { - Ok(()) => (), - Err(err) if err.kind() == io::ErrorKind::NotFound => (), - Err(err) => return Err(err), + + let err = match fs::hard_link(p, q) { + Ok(()) => return Ok(LinkOrCopy::Link), + Err(err) => err, + }; + + if err.kind() == io::ErrorKind::AlreadyExists { + fs::remove_file(q)?; + if fs::hard_link(p, q).is_ok() { + return Ok(LinkOrCopy::Link); + } } - match fs::hard_link(p, q) { - Ok(()) => Ok(LinkOrCopy::Link), - Err(_) => match fs::copy(p, q) { - Ok(_) => Ok(LinkOrCopy::Copy), - Err(e) => Err(e), - }, - } + // Hard linking failed, fall back to copying. + fs::copy(p, q).map(|_| LinkOrCopy::Copy) } #[cfg(any(unix, all(target_os = "wasi", target_env = "p1")))] diff --git a/compiler/rustc_incremental/src/persist/work_product.rs b/compiler/rustc_incremental/src/persist/work_product.rs index 048981f0d5ce..7b1eb0a82e39 100644 --- a/compiler/rustc_incremental/src/persist/work_product.rs +++ b/compiler/rustc_incremental/src/persist/work_product.rs @@ -3,7 +3,7 @@ //! [work products]: WorkProduct use std::fs as std_fs; -use std::path::Path; +use std::path::{Path, PathBuf}; use rustc_data_structures::unord::UnordMap; use rustc_fs_util::link_or_copy; @@ -20,6 +20,7 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( sess: &Session, cgu_name: &str, files: &[(&'static str, &Path)], + known_links: &[PathBuf], ) -> Option<(WorkProductId, WorkProduct)> { debug!(?cgu_name, ?files); sess.opts.incremental.as_ref()?; @@ -28,6 +29,10 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( for (ext, path) in files { let file_name = format!("{cgu_name}.{ext}"); let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name); + if known_links.contains(&path_in_incr_dir) { + let _ = saved_files.insert(ext.to_string(), file_name); + continue; + } match link_or_copy(path, &path_in_incr_dir) { Ok(_) => { let _ = saved_files.insert(ext.to_string(), file_name); From 12f7ae1ebbfcbe9ab38c92b95b9306312fbef720 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 28 Jul 2024 16:54:14 -0400 Subject: [PATCH 032/745] Avoid no-op unlink+link dances in incr comp --- src/driver/aot.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index a52b18573b15..d1843f90a07d 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -103,12 +103,14 @@ impl OngoingCodegen { ("o", &module_regular.object.as_ref().unwrap()), ("asm.o", &module_global_asm.object.as_ref().unwrap()), ], + &[], ) } else { rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( sess, &module_regular.name, &[("o", &module_regular.object.as_ref().unwrap())], + &[], ) }; if let Some((work_product_id, work_product)) = work_product { @@ -381,6 +383,7 @@ fn emit_cgu( bytecode: None, assembly: None, llvm_ir: None, + links_from_incr_cache: Vec::new(), }), existing_work_product: None, }) @@ -437,6 +440,7 @@ fn emit_module( bytecode: None, assembly: None, llvm_ir: None, + links_from_incr_cache: Vec::new(), }) } @@ -487,6 +491,7 @@ fn reuse_workproduct_for_cgu( bytecode: None, assembly: None, llvm_ir: None, + links_from_incr_cache: Vec::new(), }, module_global_asm: has_global_asm.then(|| CompiledModule { name: cgu.name().to_string(), @@ -496,6 +501,7 @@ fn reuse_workproduct_for_cgu( bytecode: None, assembly: None, llvm_ir: None, + links_from_incr_cache: Vec::new(), }), existing_work_product: Some((cgu.work_product_id(), work_product)), }) @@ -637,6 +643,7 @@ fn emit_metadata_module(tcx: TyCtxt<'_>, metadata: &EncodedMetadata) -> Compiled bytecode: None, assembly: None, llvm_ir: None, + links_from_incr_cache: Vec::new(), } } @@ -745,7 +752,6 @@ pub(crate) fn run_aot( let metadata_module = if need_metadata_module { Some(emit_metadata_module(tcx, &metadata)) } else { None }; - Box::new(OngoingCodegen { modules, allocator_module, From 143cf8da3dbf7d3a7d5a16766d48058bec8a299d Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Tue, 25 Feb 2025 09:20:10 +0100 Subject: [PATCH 033/745] remove `simd_fpow` and `simd_fpowi` --- src/intrinsics/simd.rs | 58 ------------------------------------------ 1 file changed, 58 deletions(-) diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index fcccda62355c..0c13fa91f7a7 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -460,64 +460,6 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }); } - sym::simd_fpow => { - intrinsic_args!(fx, args => (a, b); intrinsic); - - if !a.layout().ty.is_simd() { - report_simd_type_validation_error(fx, intrinsic, span, a.layout().ty); - return; - } - - simd_pair_for_each_lane(fx, a, b, ret, &|fx, lane_ty, _ret_lane_ty, a_lane, b_lane| { - match lane_ty.kind() { - ty::Float(FloatTy::F32) => fx.lib_call( - "powf", - vec![AbiParam::new(types::F32), AbiParam::new(types::F32)], - vec![AbiParam::new(types::F32)], - &[a_lane, b_lane], - )[0], - ty::Float(FloatTy::F64) => fx.lib_call( - "pow", - vec![AbiParam::new(types::F64), AbiParam::new(types::F64)], - vec![AbiParam::new(types::F64)], - &[a_lane, b_lane], - )[0], - _ => unreachable!("{:?}", lane_ty), - } - }); - } - - sym::simd_fpowi => { - intrinsic_args!(fx, args => (a, exp); intrinsic); - let exp = exp.load_scalar(fx); - - if !a.layout().ty.is_simd() { - report_simd_type_validation_error(fx, intrinsic, span, a.layout().ty); - return; - } - - simd_for_each_lane( - fx, - a, - ret, - &|fx, lane_ty, _ret_lane_ty, lane| match lane_ty.kind() { - ty::Float(FloatTy::F32) => fx.lib_call( - "__powisf2", // compiler-builtins - vec![AbiParam::new(types::F32), AbiParam::new(types::I32)], - vec![AbiParam::new(types::F32)], - &[lane, exp], - )[0], - ty::Float(FloatTy::F64) => fx.lib_call( - "__powidf2", // compiler-builtins - vec![AbiParam::new(types::F64), AbiParam::new(types::I32)], - vec![AbiParam::new(types::F64)], - &[lane, exp], - )[0], - _ => unreachable!("{:?}", lane_ty), - }, - ); - } - sym::simd_fsin | sym::simd_fcos | sym::simd_fexp From 6de7fd1feec480ba6af5eaa3a412255a8c8dd3d9 Mon Sep 17 00:00:00 2001 From: tiif Date: Wed, 26 Feb 2025 12:47:41 +0800 Subject: [PATCH 034/745] Resolve more FIXMEs --- src/tools/miri/tests/pass-dep/libc/libc-pipe.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs b/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs index 01433edf9a3c..d6072c2569e9 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs @@ -56,8 +56,7 @@ fn test_pipe_threaded() { assert_eq!(res, 5); assert_eq!(buf, "abcde".as_bytes()); }); - // FIXME: we should yield here once blocking is implemented. - //thread::yield_now(); + thread::yield_now(); let data = "abcde".as_bytes().as_ptr(); let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5) }; assert_eq!(res, 5); @@ -65,14 +64,11 @@ fn test_pipe_threaded() { // Read and write from different direction let thread2 = thread::spawn(move || { - // FIXME: we should yield here once blocking is implemented. - //thread::yield_now(); + thread::yield_now(); let data = "12345".as_bytes().as_ptr(); let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5) }; assert_eq!(res, 5); }); - // FIXME: we should not yield here once blocking is implemented. - thread::yield_now(); let mut buf: [u8; 5] = [0; 5]; let res = unsafe { libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) }; assert_eq!(res, 5); From 292256e9c3fb02a99e17c41dab62b8dc5207b527 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Wed, 26 Feb 2025 04:59:11 +0000 Subject: [PATCH 035/745] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index b3e207f53b8b..9ab3d5a6e7f5 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -f5729cfed3c45e061e8a443677fc1d5ef9277df7 +cb06d12710575a0d7ff71d6fe108f3bcff4f9195 From 530b35b805bbe7f7541ee4ec62b91978a1d2580f Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Wed, 26 Feb 2025 05:07:23 +0000 Subject: [PATCH 036/745] fmt --- src/tools/miri/tests/pass/float.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs index b3b6fe1a5d73..05ac5e82b564 100644 --- a/src/tools/miri/tests/pass/float.rs +++ b/src/tools/miri/tests/pass/float.rs @@ -1281,7 +1281,6 @@ fn test_non_determinism() { /// Ensure that the operation is non-deterministic #[track_caller] fn ensure_nondet(f: impl Fn() -> T) { - let rounds = 16; let first = f(); for _ in 1..rounds { From 94ac6e557f5ea35aee52089f66a20f3ae9230bc8 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 9 Jan 2025 12:07:50 +0000 Subject: [PATCH 037/745] Update to Cranelift 0.117 --- Cargo.lock | 89 ++++++++++++++++++++++++++++++------------------------ Cargo.toml | 24 +++++++-------- 2 files changed, 62 insertions(+), 51 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ca66ec5c6e93..011e291cd203 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -42,27 +42,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "cranelift-bforest" -version = "0.116.1" +name = "cranelift-assembler-x64" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e15d04a0ce86cb36ead88ad68cf693ffd6cda47052b9e0ac114bc47fd9cd23c4" +checksum = "d2b83fcf2fc1c8954561490d02079b496fd0c757da88129981e15bfe3a548229" +dependencies = [ + "cranelift-assembler-x64-meta", +] + +[[package]] +name = "cranelift-assembler-x64-meta" +version = "0.117.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7496a6e92b5cee48c5d772b0443df58816dee30fed6ba19b2a28e78037ecedf" + +[[package]] +name = "cranelift-bforest" +version = "0.117.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73a9dc0a8d3d49ee772101924968830f1c1937d650c571d3c2dd69dc36a68f41" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-bitset" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c6e3969a7ce267259ce244b7867c5d3bc9e65b0a87e81039588dfdeaede9f34" +checksum = "573c641174c40ef31021ae4a5a3ad78974e280633502d0dfc6e362385e0c100f" [[package]] name = "cranelift-codegen" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c22032c4cb42558371cf516bb47f26cdad1819d3475c133e93c49f50ebf304e" +checksum = "2d7c94d572615156f2db682181cadbd96342892c31e08cc26a757344319a9220" dependencies = [ "bumpalo", + "cranelift-assembler-x64", "cranelift-bforest", "cranelift-bitset", "cranelift-codegen-meta", @@ -71,7 +87,7 @@ dependencies = [ "cranelift-entity", "cranelift-isle", "gimli", - "hashbrown 0.14.5", + "hashbrown", "log", "regalloc2", "rustc-hash", @@ -82,42 +98,43 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c904bc71c61b27fc57827f4a1379f29de64fe95653b620a3db77d59655eee0b8" +checksum = "beecd9fcf2c3e06da436d565de61a42676097ea6eb6b4499346ac6264b6bb9ce" dependencies = [ + "cranelift-assembler-x64", "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40180f5497572f644ce88c255480981ae2ec1d7bb4d8e0c0136a13b87a2f2ceb" +checksum = "0f4ff8d2e1235f2d6e7fc3c6738be6954ba972cd295f09079ebffeca2f864e22" [[package]] name = "cranelift-control" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d132c6d0bd8a489563472afc171759da0707804a65ece7ceb15a8c6d7dd5ef" +checksum = "001312e9fbc7d9ca9517474d6fe71e29d07e52997fd7efe18f19e8836446ceb2" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d0d9618275474fbf679dd018ac6e009acbd6ae6850f6a67be33fb3b00b323" +checksum = "eb0fd6d4aae680275fcbceb08683416b744e65c8b607352043d3f0951d72b3b2" dependencies = [ "cranelift-bitset", ] [[package]] name = "cranelift-frontend" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fac41e16729107393174b0c9e3730fb072866100e1e64e80a1a963b2e484d57" +checksum = "9fd44e7e5dcea20ca104d45894748205c51365ce4cdb18f4418e3ba955971d1b" dependencies = [ "cranelift-codegen", "log", @@ -127,15 +144,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ca20d576e5070044d0a72a9effc2deacf4d6aa650403189d8ea50126483944d" +checksum = "f900e0a3847d51eed0321f0777947fb852ccfce0da7fb070100357f69a2f37fc" [[package]] name = "cranelift-jit" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e65c42755a719b09662b00c700daaf76cc35d5ace1f5c002ad404b591ff1978" +checksum = "55e37088dec72b7819f980558faaba9215d248fec4a2c3b89357b474f9e46f21" dependencies = [ "anyhow", "cranelift-codegen", @@ -153,9 +170,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d55612bebcf16ff7306c8a6f5bdb6d45662b8aa1ee058ecce8807ad87db719b" +checksum = "e9c3d728819ff644e8613d808378cbfed54fef464790f32e62079e638639eeff" dependencies = [ "anyhow", "cranelift-codegen", @@ -164,9 +181,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8dee82f3f1f2c4cba9177f1cc5e350fe98764379bcd29340caa7b01f85076c7" +checksum = "7617f13f392ebb63c5126258aca8b8eca739636ca7e4eeee301d3eff68489a6a" dependencies = [ "cranelift-codegen", "libc", @@ -175,9 +192,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aad5a6d3e379493c3f8b35dc61c93d0bf5f27003bbe20614e0200b0ec372ef52" +checksum = "60fc9092f7d9bba17c96ce51de5d91461f7905f3e1c43d1ba965df4b884d16ce" dependencies = [ "anyhow", "cranelift-codegen", @@ -226,12 +243,6 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - [[package]] name = "hashbrown" version = "0.15.2" @@ -248,7 +259,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown", ] [[package]] @@ -295,7 +306,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "crc32fast", - "hashbrown 0.15.2", + "hashbrown", "indexmap", "memchr", ] @@ -326,7 +337,7 @@ checksum = "145c1c267e14f20fb0f88aa76a1c5ffec42d592c1d28b3cd9148ae35916158d3" dependencies = [ "allocator-api2", "bumpalo", - "hashbrown 0.15.2", + "hashbrown", "log", "rustc-hash", "smallvec", @@ -425,9 +436,9 @@ checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "wasmtime-jit-icache-coherence" -version = "29.0.1" +version = "30.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec5e8552e01692e6c2e5293171704fed8abdec79d1a6995a0870ab190e5747d1" +checksum = "3f180cc0d2745e3a5df5d02231cd3046f49c75512eaa987b8202363b112e125d" dependencies = [ "anyhow", "cfg-if", diff --git a/Cargo.toml b/Cargo.toml index 670d6f4eef5c..fa3037e77a0c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.116.0", default-features = false, features = ["std", "unwind", "all-native-arch"] } -cranelift-frontend = { version = "0.116.0" } -cranelift-module = { version = "0.116.0" } -cranelift-native = { version = "0.116.0" } -cranelift-jit = { version = "0.116.0", optional = true } -cranelift-object = { version = "0.116.0" } +cranelift-codegen = { version = "0.117.2", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] } +cranelift-frontend = { version = "0.117.2" } +cranelift-module = { version = "0.117.2" } +cranelift-native = { version = "0.117.2" } +cranelift-jit = { version = "0.117.2", optional = true } +cranelift-object = { version = "0.117.2" } target-lexicon = "0.13" gimli = { version = "0.31", default-features = false, features = ["write"] } object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } @@ -24,12 +24,12 @@ smallvec = "1.8.1" [patch.crates-io] # Uncomment to use an unreleased version of cranelift -#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" } -#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" } -#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" } -#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" } -#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" } -#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" } +#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-30.0.0", version = "0.117.0" } +#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-30.0.0", version = "0.117.0" } +#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-30.0.0", version = "0.117.0" } +#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-30.0.0", version = "0.117.0" } +#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-30.0.0", version = "0.117.0" } +#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-30.0.0", version = "0.117.0" } # Uncomment to use local checkout of cranelift #cranelift-codegen = { path = "../wasmtime/cranelift/codegen" } From 439062052e9103a6286a4da462303ce56189eaa3 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 16 Jan 2025 18:02:21 +0000 Subject: [PATCH 038/745] Test and dist for arm64 linux on CI --- .github/workflows/abi-cafe.yml | 3 +++ .github/workflows/main.yml | 10 ++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/abi-cafe.yml b/.github/workflows/abi-cafe.yml index 30dc5cb16154..a32a275a027a 100644 --- a/.github/workflows/abi-cafe.yml +++ b/.github/workflows/abi-cafe.yml @@ -25,6 +25,9 @@ jobs: - os: ubuntu-latest env: TARGET_TRIPLE: x86_64-unknown-linux-gnu + - os: ubuntu-24.04-arm + env: + TARGET_TRIPLE: aarch64-unknown-linux-gnu - os: macos-latest env: TARGET_TRIPLE: x86_64-apple-darwin diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 61a4c1270c99..da0f95c77bb8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -53,13 +53,12 @@ jobs: - os: ubuntu-latest env: TARGET_TRIPLE: x86_64-unknown-linux-gnu + - os: ubuntu-24.04-arm + env: + TARGET_TRIPLE: aarch64-unknown-linux-gnu - os: macos-latest env: TARGET_TRIPLE: x86_64-apple-darwin - - os: ubuntu-latest - env: - TARGET_TRIPLE: aarch64-unknown-linux-gnu - apt_deps: gcc-aarch64-linux-gnu qemu-user - os: macos-latest env: TARGET_TRIPLE: aarch64-apple-darwin @@ -192,6 +191,9 @@ jobs: - os: ubuntu-22.04 env: TARGET_TRIPLE: x86_64-unknown-linux-gnu + - os: ubuntu-24.04-arm + env: + TARGET_TRIPLE: aarch64-unknown-linux-gnu - os: macos-latest env: TARGET_TRIPLE: x86_64-apple-darwin From bdcd07466b14db4965536b565c2b6ea5cf4d09d9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 26 Feb 2025 10:10:43 +0000 Subject: [PATCH 039/745] Use native x86_64 macOS runners for x86_64 builds Rather than running in Rosetta 2. This should make testing on CI faster. --- .github/workflows/main.yml | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index da0f95c77bb8..137504bc0aaa 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -56,7 +56,7 @@ jobs: - os: ubuntu-24.04-arm env: TARGET_TRIPLE: aarch64-unknown-linux-gnu - - os: macos-latest + - os: macos-13 env: TARGET_TRIPLE: x86_64-apple-darwin - os: macos-latest @@ -94,10 +94,6 @@ jobs: if: matrix.os == 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' run: rustup set default-host x86_64-pc-windows-gnu - - name: Use x86_64 compiler on macOS - if: matrix.os == 'macos-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-apple-darwin' - run: rustup set default-host x86_64-apple-darwin - - name: Install toolchain and emulator if: matrix.apt_deps != null run: | @@ -194,7 +190,7 @@ jobs: - os: ubuntu-24.04-arm env: TARGET_TRIPLE: aarch64-unknown-linux-gnu - - os: macos-latest + - os: macos-13 env: TARGET_TRIPLE: x86_64-apple-darwin - os: macos-latest @@ -220,10 +216,6 @@ jobs: if: matrix.os == 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' run: rustup set default-host x86_64-pc-windows-gnu - - name: Use x86_64 compiler on macOS - if: matrix.os == 'macos-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-apple-darwin' - run: rustup set default-host x86_64-apple-darwin - - name: Prepare dependencies run: ./y.sh prepare From 2695a19fb0fee087899616fe2f5b87e701732520 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 26 Feb 2025 10:35:27 +0000 Subject: [PATCH 040/745] Use native x86_64 runners for macOS abi-cafe tests too --- .github/workflows/abi-cafe.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/abi-cafe.yml b/.github/workflows/abi-cafe.yml index a32a275a027a..23e15866f52d 100644 --- a/.github/workflows/abi-cafe.yml +++ b/.github/workflows/abi-cafe.yml @@ -28,7 +28,7 @@ jobs: - os: ubuntu-24.04-arm env: TARGET_TRIPLE: aarch64-unknown-linux-gnu - - os: macos-latest + - os: macos-13 env: TARGET_TRIPLE: x86_64-apple-darwin - os: macos-latest @@ -59,10 +59,6 @@ jobs: if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' run: rustup set default-host x86_64-pc-windows-gnu - - name: Use x86_64 compiler on macOS - if: matrix.os == 'macos-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-apple-darwin' - run: rustup set default-host x86_64-apple-darwin - - name: Prepare dependencies run: ./y.sh prepare From 4698eb627647fe6fb78293024585ef27383e6f5a Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 26 Feb 2025 10:52:47 +0000 Subject: [PATCH 041/745] Rustup to rustc 1.87.0-nightly (85abb2763 2025-02-25) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 94b1403e47c1..86052b4df764 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-02-24" +channel = "nightly-2025-02-26" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From e173b714aa4307d136871025b1ef6e2a409d06ca Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 26 Feb 2025 11:05:26 +0000 Subject: [PATCH 042/745] You don't need y.sh prepare to build, only to test Also improve the error message when trying to test without having run y.sh prepare first. --- Readme.md | 2 +- build_system/prepare.rs | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 18a840f8a50e..28edb5795ce3 100644 --- a/Readme.md +++ b/Readme.md @@ -49,13 +49,13 @@ If you want to build the backend manually, you can download it from GitHub and b ```bash $ git clone https://github.com/rust-lang/rustc_codegen_cranelift $ cd rustc_codegen_cranelift -$ ./y.sh prepare $ ./y.sh build ``` To run the test suite replace the last command with: ```bash +$ ./y.sh prepare # only needs to be run the first time $ ./test.sh ``` diff --git a/build_system/prepare.rs b/build_system/prepare.rs index 11f73bdb61f9..ba5cc9a29f59 100644 --- a/build_system/prepare.rs +++ b/build_system/prepare.rs @@ -91,6 +91,13 @@ impl GitRepo { fn verify_checksum(&self, dirs: &Dirs) { let download_dir = self.download_dir(dirs); + if !download_dir.exists() { + eprintln!( + "Missing directory {download_dir}: Please run ./y.sh prepare to download.", + download_dir = download_dir.display(), + ); + std::process::exit(1); + } let actual_hash = format!("{:016x}", hash_dir(&download_dir)); if actual_hash != self.content_hash { eprintln!( From 994c8cfaf6c3e717365d5484a43bb20090e85460 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 26 Feb 2025 11:11:44 +0000 Subject: [PATCH 043/745] Skip downloading test crates in CI jobs that don't need them --- .github/workflows/abi-cafe.yml | 3 --- .github/workflows/main.yml | 6 ------ .github/workflows/rustc.yml | 6 ------ 3 files changed, 15 deletions(-) diff --git a/.github/workflows/abi-cafe.yml b/.github/workflows/abi-cafe.yml index 23e15866f52d..6ad041a796c9 100644 --- a/.github/workflows/abi-cafe.yml +++ b/.github/workflows/abi-cafe.yml @@ -59,9 +59,6 @@ jobs: if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' run: rustup set default-host x86_64-pc-windows-gnu - - name: Prepare dependencies - run: ./y.sh prepare - - name: Build run: ./y.sh build --sysroot none diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 137504bc0aaa..7d941887100d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -165,9 +165,6 @@ jobs: sudo apt update sudo apt install -y hyperfine - - name: Prepare dependencies - run: ./y.sh prepare - - name: Build run: ./y.sh build --sysroot none @@ -216,9 +213,6 @@ jobs: if: matrix.os == 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' run: rustup set default-host x86_64-pc-windows-gnu - - name: Prepare dependencies - run: ./y.sh prepare - - name: Build backend run: ./y.sh build --sysroot none diff --git a/.github/workflows/rustc.yml b/.github/workflows/rustc.yml index 70c214ce8b14..9253ab96353c 100644 --- a/.github/workflows/rustc.yml +++ b/.github/workflows/rustc.yml @@ -22,9 +22,6 @@ jobs: path: build/cg_clif key: ${{ runner.os }}-rustc-test-cargo-build-target-${{ hashFiles('rust-toolchain', 'Cargo.lock') }} - - name: Prepare dependencies - run: ./y.sh prepare - - name: Test run: ./scripts/test_bootstrap.sh @@ -50,8 +47,5 @@ jobs: sudo apt update sudo apt install -y ripgrep - - name: Prepare dependencies - run: ./y.sh prepare - - name: Test run: ./scripts/test_rustc_tests.sh From 410b09f28843fcdeaa39b6b918f2d657c1700eea Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Feb 2025 10:29:05 +0000 Subject: [PATCH 044/745] Update ui test --- src/tools/miri/Cargo.lock | 4 ++-- src/tools/miri/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index 57a757f9085c..b8100d0e7ad9 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -1079,9 +1079,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ui_test" -version = "0.28.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7484683d60d50ca1d1b6433c3dbf6c5ad71d20387acdcfb16fe79573f3fba576" +checksum = "14bf63f2931a28a04af0bd24c5f850223d29f3a40afae49ed6ce442a65eb8652" dependencies = [ "annotate-snippets", "anyhow", diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index 728a7552fd8c..5d8c9a866445 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -47,7 +47,7 @@ windows-sys = { version = "0.52", features = [ ] } [dev-dependencies] -ui_test = "0.28.0" +ui_test = "0.29.1" colored = "2" rustc_version = "0.4" regex = "1.5.5" From d27c67c941a0fa14dabfed98b475c8e84ffcc958 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 26 Feb 2025 11:24:41 +0000 Subject: [PATCH 045/745] Fix FIXME about unversioned macOS target names --- src/lib.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a3f437448757..2c019e754460 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,7 +41,6 @@ use std::sync::Arc; use cranelift_codegen::isa::TargetIsa; use cranelift_codegen::settings::{self, Configurable}; use rustc_codegen_ssa::CodegenResults; -use rustc_codegen_ssa::back::versioned_llvm_target; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; @@ -247,9 +246,7 @@ fn enable_verifier(sess: &Session) -> bool { } fn target_triple(sess: &Session) -> target_lexicon::Triple { - // FIXME(madsmtm): Use `sess.target.llvm_target` once target-lexicon supports unversioned macOS. - // See - match versioned_llvm_target(sess).parse() { + match sess.target.llvm_target.parse() { Ok(triple) => triple, Err(err) => sess.dcx().fatal(format!("target not recognized: {}", err)), } From 30ece8da06882b9cbca9f7e73f6804c669449a17 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 26 Feb 2025 13:06:01 +0000 Subject: [PATCH 046/745] Make tiny-skia work on arm64 --- src/intrinsics/llvm.rs | 8 +++ src/intrinsics/llvm_aarch64.rs | 119 +++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+) diff --git a/src/intrinsics/llvm.rs b/src/intrinsics/llvm.rs index 720a0d8fbf59..eb0dfbb69c3b 100644 --- a/src/intrinsics/llvm.rs +++ b/src/intrinsics/llvm.rs @@ -54,6 +54,14 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( ); } + "llvm.fptosi.sat.v4i32.v4f32" => { + intrinsic_args!(fx, args => (a); intrinsic); + + simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| { + fx.bcx.ins().fcvt_to_sint_sat(types::I32, lane) + }); + } + _ => { fx.tcx .dcx() diff --git a/src/intrinsics/llvm_aarch64.rs b/src/intrinsics/llvm_aarch64.rs index 4c59c81296ba..b77c99fa2896 100644 --- a/src/intrinsics/llvm_aarch64.rs +++ b/src/intrinsics/llvm_aarch64.rs @@ -1,5 +1,9 @@ //! Emulate AArch64 LLVM intrinsics +use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; +use rustc_target::asm::*; + +use crate::inline_asm::{CInlineAsmOperand, codegen_inline_asm_inner}; use crate::intrinsics::*; use crate::prelude::*; @@ -49,6 +53,121 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( }); } + "llvm.aarch64.neon.fcvtns.v4i32.v4f32" => { + intrinsic_args!(fx, args => (a); intrinsic); + + // Note: Using inline asm instead of fcvt_to_sint as the latter rounds to zero rather than to nearest + + let a_ptr = a.force_stack(fx).0.get_addr(fx); + let res_place = CPlace::new_stack_slot(fx, ret.layout()); + let res_ptr = res_place.to_ptr().get_addr(fx); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String( + "ldr q0, [x0] + fcvtns v0.4s, v0.4s + str q0, [x1]" + .into(), + )], + &[ + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64( + AArch64InlineAsmReg::x0, + )), + value: a_ptr, + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64( + AArch64InlineAsmReg::x1, + )), + value: res_ptr, + }, + ], + InlineAsmOptions::NOSTACK, + ); + let res = res_place.to_cvalue(fx); + ret.write_cvalue_transmute(fx, res); + } + + "llvm.aarch64.neon.frecpe.v4f32" => { + intrinsic_args!(fx, args => (a); intrinsic); + + let a_ptr = a.force_stack(fx).0.get_addr(fx); + let res_place = CPlace::new_stack_slot(fx, ret.layout()); + let res_ptr = res_place.to_ptr().get_addr(fx); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String( + "ldr q0, [x0] + frecpe v0.4s, v0.4s + str q0, [x1]" + .into(), + )], + &[ + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64( + AArch64InlineAsmReg::x0, + )), + value: a_ptr, + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64( + AArch64InlineAsmReg::x1, + )), + value: res_ptr, + }, + ], + InlineAsmOptions::NOSTACK, + ); + let res = res_place.to_cvalue(fx); + ret.write_cvalue_transmute(fx, res); + } + + "llvm.aarch64.neon.frecps.v4f32" => { + intrinsic_args!(fx, args => (a, b); intrinsic); + + let a_ptr = a.force_stack(fx).0.get_addr(fx); + let b_ptr = b.force_stack(fx).0.get_addr(fx); + let res_place = CPlace::new_stack_slot(fx, ret.layout()); + let res_ptr = res_place.to_ptr().get_addr(fx); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String( + "ldr q0, [x0] + ldr q1, [x1] + frecps v0.4s, v0.4s, v1.4s + str q0, [x2]" + .into(), + )], + &[ + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64( + AArch64InlineAsmReg::x0, + )), + value: a_ptr, + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64( + AArch64InlineAsmReg::x1, + )), + value: b_ptr, + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64( + AArch64InlineAsmReg::x2, + )), + value: res_ptr, + }, + ], + InlineAsmOptions::NOSTACK, + ); + let res = res_place.to_cvalue(fx); + ret.write_cvalue_transmute(fx, res); + } + _ if intrinsic.starts_with("llvm.aarch64.neon.sqadd.v") || intrinsic.starts_with("llvm.aarch64.neon.uqadd.v") => { From 8f001eaf62ca469887db7c9b47b6feb94cef597c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 19 Dec 2024 16:24:06 +1100 Subject: [PATCH 047/745] In `AssocOp::AssignOp`, use `BinOpKind` instead of `BinOpToken` `AssocOp::AssignOp` contains a `BinOpToken`. `ExprKind::AssignOp` contains a `BinOpKind`. Given that `AssocOp` is basically a cut-down version of `ExprKind`, it makes sense to make `AssocOp` more like `ExprKind`. Especially given that `AssocOp` and `BinOpKind` use semantic operation names (e.g. `Mul`, `Div`), but `BinOpToken` uses syntactic names (e.g. `Star`, `Slash`). This results in more concise code, and removes the need for various conversions. (Note that the removed functions `hirbinop2assignop` and `astbinop2assignop` are semantically identical, because `hir::BinOp` is just a synonum for `ast::BinOp`!) The only downside to this is that it allows the possibility of some nonsensical combinations, such as `AssocOp::AssignOp(BinOpKind::Lt)`. But `ExprKind::AssignOp` already has that problem. The problem can be fixed for both types in the future with some effort, by introducing an `AssignOpKind` type. --- clippy_utils/src/lib.rs | 1 - clippy_utils/src/sugg.rs | 58 +++------------------------------------- 2 files changed, 4 insertions(+), 55 deletions(-) diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 7fc25e3617d0..f7266ef4d4eb 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -31,7 +31,6 @@ // (Currently there is no way to opt into sysroot crates without `extern crate`.) extern crate rustc_abi; extern crate rustc_ast; -extern crate rustc_ast_pretty; extern crate rustc_attr_parsing; extern crate rustc_const_eval; extern crate rustc_data_structures; diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index d5e0e2e3436e..ff5bcba5adb8 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -5,8 +5,7 @@ use crate::source::{snippet, snippet_opt, snippet_with_applicability, snippet_wi use crate::ty::expr_sig; use crate::{get_parent_expr_for_hir, higher}; use rustc_ast::util::parser::AssocOp; -use rustc_ast::{ast, token}; -use rustc_ast_pretty::pprust::token_kind_to_string; +use rustc_ast::ast; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::{Closure, ExprKind, HirId, MutTy, TyKind}; @@ -158,7 +157,7 @@ impl<'a> Sugg<'a> { Sugg::BinOp(AssocOp::Assign, get_snippet(lhs.span), get_snippet(rhs.span)) }, ExprKind::AssignOp(op, lhs, rhs) => { - Sugg::BinOp(hirbinop2assignop(op), get_snippet(lhs.span), get_snippet(rhs.span)) + Sugg::BinOp(AssocOp::AssignOp(op.node), get_snippet(lhs.span), get_snippet(rhs.span)) }, ExprKind::Binary(op, lhs, rhs) => Sugg::BinOp( AssocOp::from_ast_binop(op.node), @@ -245,7 +244,7 @@ impl<'a> Sugg<'a> { snippet(rhs.span), ), ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => Sugg::BinOp( - astbinop2assignop(op), + AssocOp::AssignOp(op.node), snippet(lhs.span), snippet(rhs.span), ), @@ -389,7 +388,7 @@ fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String { }, AssocOp::Assign => format!("{lhs} = {rhs}"), AssocOp::AssignOp(op) => { - format!("{lhs} {}= {rhs}", token_kind_to_string(&token::BinOp(op))) + format!("{lhs} {}= {rhs}", op.as_str()) }, AssocOp::As => format!("{lhs} as {rhs}"), AssocOp::DotDot => format!("{lhs}..{rhs}"), @@ -619,55 +618,6 @@ fn associativity(op: AssocOp) -> Associativity { } } -/// Converts a `hir::BinOp` to the corresponding assigning binary operator. -fn hirbinop2assignop(op: hir::BinOp) -> AssocOp { - use rustc_ast::token::BinOpToken::{And, Caret, Minus, Or, Percent, Plus, Shl, Shr, Slash, Star}; - - AssocOp::AssignOp(match op.node { - hir::BinOpKind::Add => Plus, - hir::BinOpKind::BitAnd => And, - hir::BinOpKind::BitOr => Or, - hir::BinOpKind::BitXor => Caret, - hir::BinOpKind::Div => Slash, - hir::BinOpKind::Mul => Star, - hir::BinOpKind::Rem => Percent, - hir::BinOpKind::Shl => Shl, - hir::BinOpKind::Shr => Shr, - hir::BinOpKind::Sub => Minus, - - hir::BinOpKind::And - | hir::BinOpKind::Eq - | hir::BinOpKind::Ge - | hir::BinOpKind::Gt - | hir::BinOpKind::Le - | hir::BinOpKind::Lt - | hir::BinOpKind::Ne - | hir::BinOpKind::Or => panic!("This operator does not exist"), - }) -} - -/// Converts an `ast::BinOp` to the corresponding assigning binary operator. -fn astbinop2assignop(op: ast::BinOp) -> AssocOp { - use rustc_ast::ast::BinOpKind::{ - Add, And, BitAnd, BitOr, BitXor, Div, Eq, Ge, Gt, Le, Lt, Mul, Ne, Or, Rem, Shl, Shr, Sub, - }; - use rustc_ast::token::BinOpToken; - - AssocOp::AssignOp(match op.node { - Add => BinOpToken::Plus, - BitAnd => BinOpToken::And, - BitOr => BinOpToken::Or, - BitXor => BinOpToken::Caret, - Div => BinOpToken::Slash, - Mul => BinOpToken::Star, - Rem => BinOpToken::Percent, - Shl => BinOpToken::Shl, - Shr => BinOpToken::Shr, - Sub => BinOpToken::Minus, - And | Eq | Ge | Gt | Le | Lt | Ne | Or => panic!("This operator does not exist"), - }) -} - /// Returns the indentation before `span` if there are nothing but `[ \t]` /// before it on its line. fn indentation(cx: &T, span: Span) -> Option { From c79a7ed0687c771b5baeb781ea81917d35780533 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 19 Dec 2024 18:24:07 +1100 Subject: [PATCH 048/745] Introduce `AssocOp::Binary`. It mirrors `ExprKind::Binary`, and contains a `BinOpKind`. This makes `AssocOp` more like `ExprKind`. Note that the variants removed from `AssocOp` are all named differently to `BinOpToken`, e.g. `Multiply` instead of `Mul`, so that's an inconsistency removed. The commit adds `precedence` and `fixity` methods to `BinOpKind`, and calls them from the corresponding methods in `AssocOp`. This avoids the need to create an `AssocOp` from a `BinOpKind` in a bunch of places, and `AssocOp::from_ast_binop` is removed. `AssocOp::to_ast_binop` is also no longer needed. Overall things are shorter and nicer. --- .../operators/float_equality_without_abs.rs | 2 +- clippy_utils/src/sugg.rs | 69 ++++++++----------- 2 files changed, 28 insertions(+), 43 deletions(-) diff --git a/clippy_lints/src/operators/float_equality_without_abs.rs b/clippy_lints/src/operators/float_equality_without_abs.rs index 34f7dbea84e4..74e0a6333db0 100644 --- a/clippy_lints/src/operators/float_equality_without_abs.rs +++ b/clippy_lints/src/operators/float_equality_without_abs.rs @@ -50,7 +50,7 @@ pub(crate) fn check<'tcx>( // format the suggestion let suggestion = format!( "{}.abs()", - sugg::make_assoc(AssocOp::Subtract, &sug_l, &sug_r).maybe_par() + sugg::make_assoc(AssocOp::Binary(BinOpKind::Sub), &sug_l, &sug_r).maybe_par() ); // spans the lint span_lint_and_then( diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index ff5bcba5adb8..6e16778b343d 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -160,7 +160,7 @@ impl<'a> Sugg<'a> { Sugg::BinOp(AssocOp::AssignOp(op.node), get_snippet(lhs.span), get_snippet(rhs.span)) }, ExprKind::Binary(op, lhs, rhs) => Sugg::BinOp( - AssocOp::from_ast_binop(op.node), + AssocOp::Binary(op.node), get_snippet(lhs.span), get_snippet(rhs.span), ), @@ -249,7 +249,7 @@ impl<'a> Sugg<'a> { snippet(rhs.span), ), ast::ExprKind::Binary(op, ref lhs, ref rhs) => Sugg::BinOp( - AssocOp::from_ast_binop(op.node), + AssocOp::Binary(op.node), snippet(lhs.span), snippet(rhs.span), ), @@ -366,30 +366,9 @@ impl<'a> Sugg<'a> { /// Generates a string from the operator and both sides. fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String { match op { - AssocOp::Add - | AssocOp::Subtract - | AssocOp::Multiply - | AssocOp::Divide - | AssocOp::Modulus - | AssocOp::LAnd - | AssocOp::LOr - | AssocOp::BitXor - | AssocOp::BitAnd - | AssocOp::BitOr - | AssocOp::ShiftLeft - | AssocOp::ShiftRight - | AssocOp::Equal - | AssocOp::Less - | AssocOp::LessEqual - | AssocOp::NotEqual - | AssocOp::Greater - | AssocOp::GreaterEqual => { - format!("{lhs} {} {rhs}", op.to_ast_binop().expect("Those are AST ops").as_str()) - }, + AssocOp::Binary(op) => format!("{lhs} {} {rhs}", op.as_str()), AssocOp::Assign => format!("{lhs} = {rhs}"), - AssocOp::AssignOp(op) => { - format!("{lhs} {}= {rhs}", op.as_str()) - }, + AssocOp::AssignOp(op) => format!("{lhs} {}= {rhs}", op.as_str()), AssocOp::As => format!("{lhs} as {rhs}"), AssocOp::DotDot => format!("{lhs}..{rhs}"), AssocOp::DotDotEq => format!("{lhs}..={rhs}"), @@ -476,16 +455,17 @@ impl Neg for Sugg<'_> { impl<'a> Not for Sugg<'a> { type Output = Sugg<'a>; fn not(self) -> Sugg<'a> { - use AssocOp::{Equal, Greater, GreaterEqual, Less, LessEqual, NotEqual}; + use AssocOp::Binary; + use ast::BinOpKind::{Eq, Gt, Ge, Lt, Le, Ne}; if let Sugg::BinOp(op, lhs, rhs) = self { let to_op = match op { - Equal => NotEqual, - NotEqual => Equal, - Less => GreaterEqual, - GreaterEqual => Less, - Greater => LessEqual, - LessEqual => Greater, + Binary(Eq) => Binary(Ne), + Binary(Ne) => Binary(Eq), + Binary(Lt) => Binary(Ge), + Binary(Ge) => Binary(Lt), + Binary(Gt) => Binary(Le), + Binary(Le) => Binary(Gt), _ => return make_unop("!", Sugg::BinOp(op, lhs, rhs)), }; Sugg::BinOp(to_op, lhs, rhs) @@ -537,7 +517,7 @@ pub fn make_unop(op: &str, expr: Sugg<'_>) -> Sugg<'static> { pub fn make_assoc(op: AssocOp, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static> { /// Returns `true` if the operator is a shift operator `<<` or `>>`. fn is_shift(op: AssocOp) -> bool { - matches!(op, AssocOp::ShiftLeft | AssocOp::ShiftRight) + matches!(op, AssocOp::Binary(ast::BinOpKind::Shl | ast::BinOpKind::Shr)) } /// Returns `true` if the operator is an arithmetic operator @@ -545,7 +525,13 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static> fn is_arith(op: AssocOp) -> bool { matches!( op, - AssocOp::Add | AssocOp::Subtract | AssocOp::Multiply | AssocOp::Divide | AssocOp::Modulus + AssocOp::Binary( + ast::BinOpKind::Add + | ast::BinOpKind::Sub + | ast::BinOpKind::Mul + | ast::BinOpKind::Div + | ast::BinOpKind::Rem + ) ) } @@ -577,9 +563,9 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static> Sugg::BinOp(op, lhs.into(), rhs.into()) } -/// Convenience wrapper around `make_assoc` and `AssocOp::from_ast_binop`. +/// Convenience wrapper around `make_assoc` and `AssocOp::Binary`. pub fn make_binop(op: ast::BinOpKind, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static> { - make_assoc(AssocOp::from_ast_binop(op), lhs, rhs) + make_assoc(AssocOp::Binary(op), lhs, rhs) } #[derive(PartialEq, Eq, Clone, Copy)] @@ -604,16 +590,15 @@ enum Associativity { /// associative. #[must_use] fn associativity(op: AssocOp) -> Associativity { - use rustc_ast::util::parser::AssocOp::{ - Add, As, Assign, AssignOp, BitAnd, BitOr, BitXor, Divide, DotDot, DotDotEq, Equal, Greater, GreaterEqual, LAnd, - LOr, Less, LessEqual, Modulus, Multiply, NotEqual, ShiftLeft, ShiftRight, Subtract, + use rustc_ast::util::parser::AssocOp::{As, Assign, AssignOp, Binary, DotDot, DotDotEq}; + use ast::BinOpKind::{ + Add, BitAnd, BitOr, BitXor, Div, Eq, Gt, Ge, And, Or, Lt, Le, Rem, Mul, Ne, Shl, Shr, Sub, }; match op { Assign | AssignOp(_) => Associativity::Right, - Add | BitAnd | BitOr | BitXor | LAnd | LOr | Multiply | As => Associativity::Both, - Divide | Equal | Greater | GreaterEqual | Less | LessEqual | Modulus | NotEqual | ShiftLeft | ShiftRight - | Subtract => Associativity::Left, + Binary(Add | BitAnd | BitOr | BitXor | And | Or | Mul) | As => Associativity::Both, + Binary(Div | Eq | Gt | Ge | Lt | Le | Rem | Ne | Shl | Shr | Sub) => Associativity::Left, DotDot | DotDotEq => Associativity::None, } } From 6db6a4f4a7b86e4444153ec1fcaac505ce919b87 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 19 Dec 2024 21:42:46 +1100 Subject: [PATCH 049/745] Replace `AssocOp::DotDot{,Eq}` with `AssocOp::Range`. It makes `AssocOp` more similar to `ExprKind` and makes things a little simpler. And the semantic names make more sense here than the syntactic names. --- clippy_utils/src/sugg.rs | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index 6e16778b343d..fe5ae54fe50b 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -113,10 +113,7 @@ impl<'a> Sugg<'a> { /// function variants of `Sugg`, since these use different snippet functions. fn hir_from_snippet(expr: &hir::Expr<'_>, mut get_snippet: impl FnMut(Span) -> Cow<'a, str>) -> Self { if let Some(range) = higher::Range::hir(expr) { - let op = match range.limits { - ast::RangeLimits::HalfOpen => AssocOp::DotDot, - ast::RangeLimits::Closed => AssocOp::DotDotEq, - }; + let op = AssocOp::Range(range.limits); let start = range.start.map_or("".into(), |expr| get_snippet(expr.span)); let end = range.end.map_or("".into(), |expr| get_snippet(expr.span)); @@ -178,8 +175,6 @@ impl<'a> Sugg<'a> { ctxt: SyntaxContext, app: &mut Applicability, ) -> Self { - use rustc_ast::ast::RangeLimits; - let mut snippet = |span: Span| snippet_with_context(cx, span, ctxt, default, app).0; match expr.kind { @@ -228,13 +223,8 @@ impl<'a> Sugg<'a> { | ast::ExprKind::Err(_) | ast::ExprKind::Dummy | ast::ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(snippet(expr.span)), - ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::HalfOpen) => Sugg::BinOp( - AssocOp::DotDot, - lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)), - rhs.as_ref().map_or("".into(), |rhs| snippet(rhs.span)), - ), - ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::Closed) => Sugg::BinOp( - AssocOp::DotDotEq, + ast::ExprKind::Range(ref lhs, ref rhs, limits) => Sugg::BinOp( + AssocOp::Range(limits), lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)), rhs.as_ref().map_or("".into(), |rhs| snippet(rhs.span)), ), @@ -326,11 +316,8 @@ impl<'a> Sugg<'a> { /// Convenience method to create the `..` or `...` /// suggestion. - pub fn range(self, end: &Self, limit: ast::RangeLimits) -> Sugg<'static> { - match limit { - ast::RangeLimits::HalfOpen => make_assoc(AssocOp::DotDot, &self, end), - ast::RangeLimits::Closed => make_assoc(AssocOp::DotDotEq, &self, end), - } + pub fn range(self, end: &Self, limits: ast::RangeLimits) -> Sugg<'static> { + make_assoc(AssocOp::Range(limits), &self, end) } /// Adds parentheses to any expression that might need them. Suitable to the @@ -370,8 +357,7 @@ fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String { AssocOp::Assign => format!("{lhs} = {rhs}"), AssocOp::AssignOp(op) => format!("{lhs} {}= {rhs}", op.as_str()), AssocOp::As => format!("{lhs} as {rhs}"), - AssocOp::DotDot => format!("{lhs}..{rhs}"), - AssocOp::DotDotEq => format!("{lhs}..={rhs}"), + AssocOp::Range(limits) => format!("{lhs}{}{rhs}", limits.as_str()), } } @@ -590,7 +576,7 @@ enum Associativity { /// associative. #[must_use] fn associativity(op: AssocOp) -> Associativity { - use rustc_ast::util::parser::AssocOp::{As, Assign, AssignOp, Binary, DotDot, DotDotEq}; + use rustc_ast::util::parser::AssocOp::{As, Assign, AssignOp, Binary, Range}; use ast::BinOpKind::{ Add, BitAnd, BitOr, BitXor, Div, Eq, Gt, Ge, And, Or, Lt, Le, Rem, Mul, Ne, Shl, Shr, Sub, }; @@ -599,7 +585,7 @@ fn associativity(op: AssocOp) -> Associativity { Assign | AssignOp(_) => Associativity::Right, Binary(Add | BitAnd | BitOr | BitXor | And | Or | Mul) | As => Associativity::Both, Binary(Div | Eq | Gt | Ge | Lt | Le | Rem | Ne | Shl | Shr | Sub) => Associativity::Left, - DotDot | DotDotEq => Associativity::None, + Range(_) => Associativity::None, } } From 537577f79a694a289a4a7ae462a712fd76c18cf3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 19 Dec 2024 21:46:44 +1100 Subject: [PATCH 050/745] Rename `AssocOp::As` as `AssocOp::Cast`. To match `ExprKind::Cast`, and because a semantic name makes more sense here than a syntactic name. --- clippy_utils/src/sugg.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index fe5ae54fe50b..4a9ab17d4a60 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -163,7 +163,7 @@ impl<'a> Sugg<'a> { ), ExprKind::Cast(lhs, ty) | //FIXME(chenyukang), remove this after type ascription is removed from AST - ExprKind::Type(lhs, ty) => Sugg::BinOp(AssocOp::As, get_snippet(lhs.span), get_snippet(ty.span)), + ExprKind::Type(lhs, ty) => Sugg::BinOp(AssocOp::Cast, get_snippet(lhs.span), get_snippet(ty.span)), } } @@ -246,7 +246,7 @@ impl<'a> Sugg<'a> { ast::ExprKind::Cast(ref lhs, ref ty) | //FIXME(chenyukang), remove this after type ascription is removed from AST ast::ExprKind::Type(ref lhs, ref ty) => Sugg::BinOp( - AssocOp::As, + AssocOp::Cast, snippet(lhs.span), snippet(ty.span), ), @@ -265,7 +265,7 @@ impl<'a> Sugg<'a> { /// Convenience method to create the ` as ` suggestion. pub fn as_ty(self, rhs: R) -> Sugg<'static> { - make_assoc(AssocOp::As, &self, &Sugg::NonParen(rhs.to_string().into())) + make_assoc(AssocOp::Cast, &self, &Sugg::NonParen(rhs.to_string().into())) } /// Convenience method to create the `&` suggestion. @@ -356,7 +356,7 @@ fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String { AssocOp::Binary(op) => format!("{lhs} {} {rhs}", op.as_str()), AssocOp::Assign => format!("{lhs} = {rhs}"), AssocOp::AssignOp(op) => format!("{lhs} {}= {rhs}", op.as_str()), - AssocOp::As => format!("{lhs} as {rhs}"), + AssocOp::Cast => format!("{lhs} as {rhs}"), AssocOp::Range(limits) => format!("{lhs}{}{rhs}", limits.as_str()), } } @@ -432,7 +432,7 @@ impl Neg for Sugg<'_> { type Output = Sugg<'static>; fn neg(self) -> Sugg<'static> { match &self { - Self::BinOp(AssocOp::As, ..) => Sugg::MaybeParen(format!("-({self})").into()), + Self::BinOp(AssocOp::Cast, ..) => Sugg::MaybeParen(format!("-({self})").into()), _ => make_unop("-", self), } } @@ -576,14 +576,14 @@ enum Associativity { /// associative. #[must_use] fn associativity(op: AssocOp) -> Associativity { - use rustc_ast::util::parser::AssocOp::{As, Assign, AssignOp, Binary, Range}; + use rustc_ast::util::parser::AssocOp::{Assign, AssignOp, Binary, Cast, Range}; use ast::BinOpKind::{ Add, BitAnd, BitOr, BitXor, Div, Eq, Gt, Ge, And, Or, Lt, Le, Rem, Mul, Ne, Shl, Shr, Sub, }; match op { Assign | AssignOp(_) => Associativity::Right, - Binary(Add | BitAnd | BitOr | BitXor | And | Or | Mul) | As => Associativity::Both, + Binary(Add | BitAnd | BitOr | BitXor | And | Or | Mul) | Cast => Associativity::Both, Binary(Div | Eq | Gt | Ge | Lt | Le | Rem | Ne | Shl | Shr | Sub) => Associativity::Left, Range(_) => Associativity::None, } From 3a39629597b2d2cb7af988580cce949f94116bab Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 27 Feb 2025 00:17:58 +0100 Subject: [PATCH 051/745] Refactor function after adding a new diagnostic item The `has_eligible_receiver()` function had been adapted *a minima* when the `sym::ControlFlow` diagnostic item has been added to rustc. This refactors the function content to make its meaning clearer. --- clippy_lints/src/useless_conversion.rs | 28 +++++++++----------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs index 5e452c6d2ac0..57bb2fc27f14 100644 --- a/clippy_lints/src/useless_conversion.rs +++ b/clippy_lints/src/useless_conversion.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::{snippet, snippet_with_context}; use clippy_utils::sugg::{DiagExt as _, Sugg}; -use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts}; +use clippy_utils::ty::{get_type_diagnostic_name, is_copy, is_type_diagnostic_item, same_type_and_consts}; use clippy_utils::{ get_parent_expr, is_inherent_method_call, is_trait_item, is_trait_method, is_ty_alias, path_to_local, }; @@ -13,7 +13,7 @@ use rustc_infer::traits::Obligation; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::adjustment::{Adjust, AutoBorrow, AutoBorrowMutability}; -use rustc_middle::ty::{self, AdtDef, EarlyBinder, GenericArg, GenericArgsRef, Ty, TypeVisitableExt}; +use rustc_middle::ty::{self, EarlyBinder, GenericArg, GenericArgsRef, Ty, TypeVisitableExt}; use rustc_session::impl_lint_pass; use rustc_span::{Span, sym}; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; @@ -412,24 +412,14 @@ pub fn check_function_application(cx: &LateContext<'_>, expr: &Expr<'_>, recv: & } fn has_eligible_receiver(cx: &LateContext<'_>, recv: &Expr<'_>, expr: &Expr<'_>) -> bool { - let recv_ty = cx.typeck_results().expr_ty(recv); - if is_inherent_method_call(cx, expr) - && let Some(recv_ty_defid) = recv_ty.ty_adt_def().map(AdtDef::did) - { - if let Some(diag_name) = cx.tcx.get_diagnostic_name(recv_ty_defid) - && matches!(diag_name, sym::Option | sym::Result) - { - return true; - } - - if cx.tcx.is_diagnostic_item(sym::ControlFlow, recv_ty_defid) { - return true; - } + if is_inherent_method_call(cx, expr) { + matches!( + get_type_diagnostic_name(cx, cx.typeck_results().expr_ty(recv)), + Some(sym::Option | sym::Result | sym::ControlFlow) + ) + } else { + is_trait_method(cx, expr, sym::Iterator) } - if is_trait_method(cx, expr, sym::Iterator) { - return true; - } - false } fn adjustments(cx: &LateContext<'_>, expr: &Expr<'_>) -> String { From e21502cf9ed247bbf879132b8c62e423d959bd38 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Tue, 25 Feb 2025 18:41:49 -0500 Subject: [PATCH 052/745] Fill out links_from_incr_cache in cg_clif --- .../rustc_codegen_cranelift/src/driver/aot.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index d1843f90a07d..fb7864ae6124 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -464,22 +464,23 @@ fn reuse_workproduct_for_cgu( err )); } + let obj_out_global_asm = crate::global_asm::add_file_stem_postfix(obj_out_regular.clone(), ".asm"); - let has_global_asm = if let Some(asm_o) = work_product.saved_files.get("asm.o") { + let source_file_global_asm = if let Some(asm_o) = work_product.saved_files.get("asm.o") { let source_file_global_asm = rustc_incremental::in_incr_comp_dir_sess(&tcx.sess, asm_o); if let Err(err) = rustc_fs_util::link_or_copy(&source_file_global_asm, &obj_out_global_asm) { return Err(format!( "unable to copy {} to {}: {}", - source_file_regular.display(), - obj_out_regular.display(), + source_file_global_asm.display(), + obj_out_global_asm.display(), err )); } - true + Some(source_file_global_asm) } else { - false + None }; Ok(ModuleCodegenResult { @@ -491,9 +492,9 @@ fn reuse_workproduct_for_cgu( bytecode: None, assembly: None, llvm_ir: None, - links_from_incr_cache: Vec::new(), + links_from_incr_cache: vec![source_file_regular], }, - module_global_asm: has_global_asm.then(|| CompiledModule { + module_global_asm: source_file_global_asm.map(|source_file| CompiledModule { name: cgu.name().to_string(), kind: ModuleKind::Regular, object: Some(obj_out_global_asm), @@ -501,7 +502,7 @@ fn reuse_workproduct_for_cgu( bytecode: None, assembly: None, llvm_ir: None, - links_from_incr_cache: Vec::new(), + links_from_incr_cache: vec![source_file], }), existing_work_product: Some((cgu.work_product_id(), work_product)), }) @@ -752,6 +753,7 @@ pub(crate) fn run_aot( let metadata_module = if need_metadata_module { Some(emit_metadata_module(tcx, &metadata)) } else { None }; + Box::new(OngoingCodegen { modules, allocator_module, From af9f91696bb3f504a6fc7c235e7eb1999d064acb Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Tue, 25 Feb 2025 18:41:49 -0500 Subject: [PATCH 053/745] Fill out links_from_incr_cache in cg_clif --- src/driver/aot.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index d1843f90a07d..fb7864ae6124 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -464,22 +464,23 @@ fn reuse_workproduct_for_cgu( err )); } + let obj_out_global_asm = crate::global_asm::add_file_stem_postfix(obj_out_regular.clone(), ".asm"); - let has_global_asm = if let Some(asm_o) = work_product.saved_files.get("asm.o") { + let source_file_global_asm = if let Some(asm_o) = work_product.saved_files.get("asm.o") { let source_file_global_asm = rustc_incremental::in_incr_comp_dir_sess(&tcx.sess, asm_o); if let Err(err) = rustc_fs_util::link_or_copy(&source_file_global_asm, &obj_out_global_asm) { return Err(format!( "unable to copy {} to {}: {}", - source_file_regular.display(), - obj_out_regular.display(), + source_file_global_asm.display(), + obj_out_global_asm.display(), err )); } - true + Some(source_file_global_asm) } else { - false + None }; Ok(ModuleCodegenResult { @@ -491,9 +492,9 @@ fn reuse_workproduct_for_cgu( bytecode: None, assembly: None, llvm_ir: None, - links_from_incr_cache: Vec::new(), + links_from_incr_cache: vec![source_file_regular], }, - module_global_asm: has_global_asm.then(|| CompiledModule { + module_global_asm: source_file_global_asm.map(|source_file| CompiledModule { name: cgu.name().to_string(), kind: ModuleKind::Regular, object: Some(obj_out_global_asm), @@ -501,7 +502,7 @@ fn reuse_workproduct_for_cgu( bytecode: None, assembly: None, llvm_ir: None, - links_from_incr_cache: Vec::new(), + links_from_incr_cache: vec![source_file], }), existing_work_product: Some((cgu.work_product_id(), work_product)), }) @@ -752,6 +753,7 @@ pub(crate) fn run_aot( let metadata_module = if need_metadata_module { Some(emit_metadata_module(tcx, &metadata)) } else { None }; + Box::new(OngoingCodegen { modules, allocator_module, From de25d0d1320f4ec86d43b1f35d1df430680f3644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Thu, 27 Feb 2025 09:14:31 +0100 Subject: [PATCH 054/745] Clean up TypeckResults::extract_binding_mode - Remove the `Option` from the result type, as `None` is never returned. - Document the difference from the `BindingMode` in `PatKind::Binding`. --- clippy_utils/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 7fc25e3617d0..c127cdce7a7b 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -1095,7 +1095,6 @@ pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind { pat.each_binding_or_first(&mut |_, id, span, _| match cx .typeck_results() .extract_binding_mode(cx.sess(), id, span) - .unwrap() .0 { ByRef::No if !is_copy(cx, cx.typeck_results().node_type(id)) => { From ac2ddc14af00f2b37e0ba499b35ef31e681aa2ff Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 27 Feb 2025 14:18:38 +0100 Subject: [PATCH 055/745] before_terminator: add some minor clarifying comments --- src/tools/miri/src/machine.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 4ece8f7895de..45764b70dfb6 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1532,7 +1532,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { fn before_terminator(ecx: &mut InterpCx<'tcx, Self>) -> InterpResult<'tcx> { ecx.machine.basic_block_count += 1u64; // a u64 that is only incremented by 1 will "never" overflow ecx.machine.since_gc += 1; - // Possibly report our progress. + // Possibly report our progress. This will point at the terminator we are about to execute. if let Some(report_progress) = ecx.machine.report_progress { if ecx.machine.basic_block_count % u64::from(report_progress) == 0 { ecx.emit_diagnostic(NonHaltingDiagnostic::ProgressReport { @@ -1551,6 +1551,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { } // These are our preemption points. + // (This will only take effect after the terminator has been executed.) ecx.maybe_preempt_active_thread(); // Make sure some time passes. From 18616dcd4fce257e2a994914d8680ea4ed0098fe Mon Sep 17 00:00:00 2001 From: yanglsh Date: Fri, 28 Feb 2025 00:28:45 +0800 Subject: [PATCH 056/745] fix: `map_entry` suggest wrongly when key is not `Copy` --- clippy_lints/src/entry.rs | 47 +++++++++++------ tests/ui/entry_unfixable.rs | 94 +++++++++++++++++++++++++++++++++ tests/ui/entry_unfixable.stderr | 41 ++++++++++++++ 3 files changed, 167 insertions(+), 15 deletions(-) create mode 100644 tests/ui/entry_unfixable.rs create mode 100644 tests/ui/entry_unfixable.stderr diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index f404bc59b3b8..dcfee0b6d3c6 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -1,5 +1,6 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; use clippy_utils::source::{reindent_multiline, snippet_indent, snippet_with_applicability, snippet_with_context}; +use clippy_utils::ty::is_copy; use clippy_utils::visitors::for_each_expr; use clippy_utils::{ SpanlessEq, can_move_expr_to_closure_no_visit, higher, is_expr_final_block_expr, is_expr_used_or_unified, @@ -84,14 +85,21 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass { return; }; + let lint_msg = format!("usage of `contains_key` followed by `insert` on a `{}`", map_ty.name()); let mut app = Applicability::MachineApplicable; let map_str = snippet_with_context(cx, contains_expr.map.span, contains_expr.call_ctxt, "..", &mut app).0; let key_str = snippet_with_context(cx, contains_expr.key.span, contains_expr.call_ctxt, "..", &mut app).0; + let sugg = if let Some(else_expr) = else_expr { let Some(else_search) = find_insert_calls(cx, &contains_expr, else_expr) else { return; }; + if then_search.is_key_used_and_no_copy || else_search.is_key_used_and_no_copy { + span_lint(cx, MAP_ENTRY, expr.span, lint_msg); + return; + } + if then_search.edits.is_empty() && else_search.edits.is_empty() { // No insertions return; @@ -184,15 +192,7 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass { } }; - span_lint_and_sugg( - cx, - MAP_ENTRY, - expr.span, - format!("usage of `contains_key` followed by `insert` on a `{}`", map_ty.name()), - "try", - sugg, - app, - ); + span_lint_and_sugg(cx, MAP_ENTRY, expr.span, lint_msg, "try", sugg, app); } } @@ -354,6 +354,8 @@ struct InsertSearcher<'cx, 'tcx> { key: &'tcx Expr<'tcx>, /// The context of the top level block. All insert calls must be in the same context. ctxt: SyntaxContext, + /// The spanless equality utility used to compare expressions. + spanless_eq: SpanlessEq<'cx, 'tcx>, /// Whether this expression can be safely moved into a closure. allow_insert_closure: bool, /// Whether this expression can use the entry api. @@ -364,6 +366,8 @@ struct InsertSearcher<'cx, 'tcx> { is_single_insert: bool, /// If the visitor has seen the map being used. is_map_used: bool, + /// If the visitor has seen the key being used. + is_key_used: bool, /// The locations where changes need to be made for the suggestion. edits: Vec>, /// A stack of loops the visitor is currently in. @@ -479,11 +483,11 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { } match try_parse_insert(self.cx, expr) { - Some(insert_expr) if SpanlessEq::new(self.cx).eq_expr(self.map, insert_expr.map) => { + Some(insert_expr) if self.spanless_eq.eq_expr(self.map, insert_expr.map) => { self.visit_insert_expr_arguments(&insert_expr); // Multiple inserts, inserts with a different key, and inserts from a macro can't use the entry api. if self.is_map_used - || !SpanlessEq::new(self.cx).eq_expr(self.key, insert_expr.key) + || !self.spanless_eq.eq_expr(self.key, insert_expr.key) || expr.span.ctxt() != self.ctxt { self.can_use_entry = false; @@ -502,9 +506,12 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { self.visit_non_tail_expr(insert_expr.value); self.is_single_insert = is_single_insert; }, - _ if is_any_expr_in_map_used(self.cx, self.map, expr) => { + _ if is_any_expr_in_map_used(self.cx, &mut self.spanless_eq, self.map, expr) => { self.is_map_used = true; }, + _ if self.spanless_eq.eq_expr(self.key, expr) => { + self.is_key_used = true; + }, _ => match expr.kind { ExprKind::If(cond_expr, then_expr, Some(else_expr)) => { self.is_single_insert = false; @@ -568,9 +575,14 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { /// Check if the given expression is used for each sub-expression in the given map. /// For example, in map `a.b.c.my_map`, The expression `a.b.c.my_map`, `a.b.c`, `a.b`, and `a` are /// all checked. -fn is_any_expr_in_map_used<'tcx>(cx: &LateContext<'tcx>, map: &'tcx Expr<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { +fn is_any_expr_in_map_used<'tcx>( + cx: &LateContext<'tcx>, + spanless_eq: &mut SpanlessEq<'_, 'tcx>, + map: &'tcx Expr<'tcx>, + expr: &'tcx Expr<'tcx>, +) -> bool { for_each_expr(cx, map, |e| { - if SpanlessEq::new(cx).eq_expr(e, expr) { + if spanless_eq.eq_expr(e, expr) { return ControlFlow::Break(()); } ControlFlow::Continue(()) @@ -582,6 +594,7 @@ struct InsertSearchResults<'tcx> { edits: Vec>, allow_insert_closure: bool, is_single_insert: bool, + is_key_used_and_no_copy: bool, } impl<'tcx> InsertSearchResults<'tcx> { fn as_single_insertion(&self) -> Option> { @@ -694,11 +707,13 @@ fn find_insert_calls<'tcx>( map: contains_expr.map, key: contains_expr.key, ctxt: expr.span.ctxt(), + spanless_eq: SpanlessEq::new(cx), allow_insert_closure: true, can_use_entry: true, in_tail_pos: true, is_single_insert: true, is_map_used: false, + is_key_used: false, edits: Vec::new(), loops: Vec::new(), locals: HirIdSet::default(), @@ -706,10 +721,12 @@ fn find_insert_calls<'tcx>( s.visit_expr(expr); let allow_insert_closure = s.allow_insert_closure; let is_single_insert = s.is_single_insert; + let is_key_used_and_no_copy = s.is_key_used && !is_copy(cx, cx.typeck_results().expr_ty(contains_expr.key)); let edits = s.edits; s.can_use_entry.then_some(InsertSearchResults { edits, allow_insert_closure, is_single_insert, + is_key_used_and_no_copy, }) } diff --git a/tests/ui/entry_unfixable.rs b/tests/ui/entry_unfixable.rs new file mode 100644 index 000000000000..dbdacf950569 --- /dev/null +++ b/tests/ui/entry_unfixable.rs @@ -0,0 +1,94 @@ +#![allow(unused, clippy::needless_pass_by_value, clippy::collapsible_if)] +#![warn(clippy::map_entry)] +//@no-rustfix + +use std::collections::HashMap; +use std::hash::Hash; + +macro_rules! m { + ($e:expr) => {{ $e }}; +} + +macro_rules! insert { + ($map:expr, $key:expr, $val:expr) => { + $map.insert($key, $val) + }; +} + +mod issue13306 { + use std::collections::HashMap; + + struct Env { + enclosing: Option>, + values: HashMap, + } + + impl Env { + fn assign(&mut self, name: String, value: usize) -> bool { + if !self.values.contains_key(&name) { + //~^ map_entry + self.values.insert(name, value); + true + } else if let Some(enclosing) = &mut self.enclosing { + enclosing.assign(name, value) + } else { + false + } + } + } +} + +fn issue9925(mut hm: HashMap) { + let key = "hello".to_string(); + if hm.contains_key(&key) { + //~^ map_entry + let bval = hm.get_mut(&key).unwrap(); + *bval = false; + } else { + hm.insert(key, true); + } +} + +mod issue9470 { + use std::collections::HashMap; + use std::sync::Mutex; + + struct Interner(i32); + + impl Interner { + const fn new() -> Self { + Interner(0) + } + + fn resolve(&self, name: String) -> Option { + todo!() + } + } + + static INTERNER: Mutex = Mutex::new(Interner::new()); + + struct VM { + stack: Vec, + globals: HashMap, + } + + impl VM { + fn stack_top(&self) -> &i32 { + self.stack.last().unwrap() + } + + fn resolve(&mut self, name: String, value: i32) -> Result<(), String> { + if self.globals.contains_key(&name) { + //~^ map_entry + self.globals.insert(name, value); + } else { + let interner = INTERNER.lock().unwrap(); + return Err(interner.resolve(name).unwrap().to_owned()); + } + + Ok(()) + } + } +} + +fn main() {} diff --git a/tests/ui/entry_unfixable.stderr b/tests/ui/entry_unfixable.stderr new file mode 100644 index 000000000000..9f9956d351b2 --- /dev/null +++ b/tests/ui/entry_unfixable.stderr @@ -0,0 +1,41 @@ +error: usage of `contains_key` followed by `insert` on a `HashMap` + --> tests/ui/entry_unfixable.rs:28:13 + | +LL | / if !self.values.contains_key(&name) { +LL | | +LL | | self.values.insert(name, value); +LL | | true +... | +LL | | false +LL | | } + | |_____________^ + | + = note: `-D clippy::map-entry` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::map_entry)]` + +error: usage of `contains_key` followed by `insert` on a `HashMap` + --> tests/ui/entry_unfixable.rs:43:5 + | +LL | / if hm.contains_key(&key) { +LL | | +LL | | let bval = hm.get_mut(&key).unwrap(); +LL | | *bval = false; +LL | | } else { +LL | | hm.insert(key, true); +LL | | } + | |_____^ + +error: usage of `contains_key` followed by `insert` on a `HashMap` + --> tests/ui/entry_unfixable.rs:81:13 + | +LL | / if self.globals.contains_key(&name) { +LL | | +LL | | self.globals.insert(name, value); +LL | | } else { +LL | | let interner = INTERNER.lock().unwrap(); +LL | | return Err(interner.resolve(name).unwrap().to_owned()); +LL | | } + | |_____________^ + +error: aborting due to 3 previous errors + From b9ca52582bb6a5b73fc633539b267579e82be422 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 28 Feb 2025 16:29:07 +0100 Subject: [PATCH 057/745] =?UTF-8?q?rename=20BackendRepr::Vector=20?= =?UTF-8?q?=E2=86=92=20SimdVector?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/abi/pass_mode.rs | 4 ++-- src/intrinsics/mod.rs | 2 +- src/value_and_place.rs | 8 +++++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/abi/pass_mode.rs b/src/abi/pass_mode.rs index b28c4c9539ce..06d89bc9ea7d 100644 --- a/src/abi/pass_mode.rs +++ b/src/abi/pass_mode.rs @@ -84,7 +84,7 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { AbiParam::new(scalar_to_clif_type(tcx, scalar)), attrs )], - BackendRepr::Vector { .. } => { + BackendRepr::SimdVector { .. } => { let vector_ty = crate::intrinsics::clif_vector_type(tcx, self.layout); smallvec![AbiParam::new(vector_ty)] } @@ -135,7 +135,7 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { BackendRepr::Scalar(scalar) => { (None, vec![AbiParam::new(scalar_to_clif_type(tcx, scalar))]) } - BackendRepr::Vector { .. } => { + BackendRepr::SimdVector { .. } => { let vector_ty = crate::intrinsics::clif_vector_type(tcx, self.layout); (None, vec![AbiParam::new(vector_ty)]) } diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 4d9bed8652cb..6735ae024d1c 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -53,7 +53,7 @@ fn report_atomic_type_validation_error<'tcx>( pub(crate) fn clif_vector_type<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>) -> Type { let (element, count) = match layout.backend_repr { - BackendRepr::Vector { element, count } => (element, count), + BackendRepr::SimdVector { element, count } => (element, count), _ => unreachable!(), }; diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 1b3f86c8405d..cc739fefcd06 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -173,9 +173,11 @@ impl<'tcx> CValue<'tcx> { CValueInner::ByRef(ptr, None) => { let clif_ty = match layout.backend_repr { BackendRepr::Scalar(scalar) => scalar_to_clif_type(fx.tcx, scalar), - BackendRepr::Vector { element, count } => scalar_to_clif_type(fx.tcx, element) - .by(u32::try_from(count).unwrap()) - .unwrap(), + BackendRepr::SimdVector { element, count } => { + scalar_to_clif_type(fx.tcx, element) + .by(u32::try_from(count).unwrap()) + .unwrap() + } _ => unreachable!("{:?}", layout.ty), }; let mut flags = MemFlags::new(); From 4f0e507165ae6ebf3304041324c196a6e5ae801c Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 13 Feb 2025 13:46:30 +0100 Subject: [PATCH 058/745] `incompatible_msrv`: lint function calls with any argument count The lint for function calls was previously restricted to functions taking exactly one argument. This was not documented. Generalizing the lint to an arbitrary number of arguments in the function call requires special casing some macro expansions from the standard library. Macros such as `panic!()` or `assert_eq!()` exist since Rust 1.0.0, but modern stdlib expand those macros into calls to functions introduced in later Rust versions. While it is desirable to lint code inside macros, using MSRV-incompatible functions coming from `core` in macro expansions has been special-cased to not trigger this lint. Also, code coming from compiler desugaring may contain function calls (for example, `a..=b` is now desugared into `RangeInclusive::new(a, b)`. Those should not be linted either as the compiler is allowed to use unstable function calls. --- clippy_lints/src/incompatible_msrv.rs | 26 +++++++++++++++--- tests/ui/incompatible_msrv.rs | 39 +++++++++++++++++++++++++++ tests/ui/incompatible_msrv.stderr | 37 ++++++++++++++++++++++--- 3 files changed, 94 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/incompatible_msrv.rs b/clippy_lints/src/incompatible_msrv.rs index 12dfb14c454d..e55edb1fcaa8 100644 --- a/clippy_lints/src/incompatible_msrv.rs +++ b/clippy_lints/src/incompatible_msrv.rs @@ -4,12 +4,12 @@ use clippy_utils::is_in_test; use clippy_utils::msrvs::Msrv; use rustc_attr_parsing::{RustcVersion, StabilityLevel, StableSince}; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::{Expr, ExprKind, HirId}; +use rustc_hir::{Expr, ExprKind, HirId, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::TyCtxt; use rustc_session::impl_lint_pass; use rustc_span::def_id::DefId; -use rustc_span::{ExpnKind, Span}; +use rustc_span::{ExpnKind, Span, sym}; declare_clippy_lint! { /// ### What it does @@ -93,6 +93,21 @@ impl IncompatibleMsrv { // Intentionally not using `.from_expansion()`, since we do still care about macro expansions return; } + + // Functions coming from `core` while expanding a macro such as `assert*!()` get to cheat too: the + // macros may have existed prior to the checked MSRV, but their expansion with a recent compiler + // might use recent functions or methods. Compiling with an older compiler would not use those. + if span.from_expansion() + && cx.tcx.crate_name(def_id.krate) == sym::core + && span + .ctxt() + .outer_expn_data() + .macro_def_id + .is_some_and(|def_id| cx.tcx.crate_name(def_id.krate) == sym::core) + { + return; + } + if (self.check_in_tests || !is_in_test(cx.tcx, node)) && let Some(current) = self.msrv.current(cx) && let version = self.get_def_id_version(cx.tcx, def_id) @@ -118,8 +133,11 @@ impl<'tcx> LateLintPass<'tcx> for IncompatibleMsrv { self.emit_lint_if_under_msrv(cx, method_did, expr.hir_id, span); } }, - ExprKind::Call(call, [_]) => { - if let ExprKind::Path(qpath) = call.kind + ExprKind::Call(call, _) => { + // Desugaring into function calls by the compiler will use `QPath::LangItem` variants. Those should + // not be linted as they will not be generated in older compilers if the function is not available, + // and the compiler is allowed to call unstable functions. + if let ExprKind::Path(qpath @ (QPath::Resolved(..) | QPath::TypeRelative(..))) = call.kind && let Some(path_def_id) = cx.qpath_res(&qpath, call.hir_id).opt_def_id() { self.emit_lint_if_under_msrv(cx, path_def_id, expr.hir_id, call.span); diff --git a/tests/ui/incompatible_msrv.rs b/tests/ui/incompatible_msrv.rs index b4fea4cae5ed..99101b2bb8f2 100644 --- a/tests/ui/incompatible_msrv.rs +++ b/tests/ui/incompatible_msrv.rs @@ -1,5 +1,6 @@ #![warn(clippy::incompatible_msrv)] #![feature(custom_inner_attributes)] +#![feature(panic_internals)] #![clippy::msrv = "1.3.0"] use std::collections::HashMap; @@ -34,4 +35,42 @@ async fn issue12273(v: impl Future) { v.await; } +fn core_special_treatment(p: bool) { + // Do not lint code coming from `core` macros expanding into `core` function calls + if p { + panic!("foo"); // Do not lint + } + + // But still lint code calling `core` functions directly + if p { + core::panicking::panic("foo"); + //~^ ERROR: is `1.3.0` but this item is stable since `1.6.0` + } + + // Lint code calling `core` from non-`core` macros + macro_rules! my_panic { + ($msg:expr) => { + core::panicking::panic($msg) + }; //~^ ERROR: is `1.3.0` but this item is stable since `1.6.0` + } + my_panic!("foo"); + + // Lint even when the macro comes from `core` and calls `core` functions + assert!(core::panicking::panic("out of luck")); + //~^ ERROR: is `1.3.0` but this item is stable since `1.6.0` +} + +#[clippy::msrv = "1.26.0"] +fn lang_items() { + // Do not lint lang items. `..=` will expand into `RangeInclusive::new()`, which was introduced + // in Rust 1.27.0. + let _ = 1..=3; +} + +#[clippy::msrv = "1.80.0"] +fn issue14212() { + let _ = std::iter::repeat_n((), 5); + //~^ ERROR: is `1.80.0` but this item is stable since `1.82.0` +} + fn main() {} diff --git a/tests/ui/incompatible_msrv.stderr b/tests/ui/incompatible_msrv.stderr index 56c9eae5aafa..5ea2bb9cc58b 100644 --- a/tests/ui/incompatible_msrv.stderr +++ b/tests/ui/incompatible_msrv.stderr @@ -1,5 +1,5 @@ error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.10.0` - --> tests/ui/incompatible_msrv.rs:13:39 + --> tests/ui/incompatible_msrv.rs:14:39 | LL | assert_eq!(map.entry("poneyland").key(), &"poneyland"); | ^^^^^ @@ -8,16 +8,45 @@ LL | assert_eq!(map.entry("poneyland").key(), &"poneyland"); = help: to override `-D warnings` add `#[allow(clippy::incompatible_msrv)]` error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.12.0` - --> tests/ui/incompatible_msrv.rs:17:11 + --> tests/ui/incompatible_msrv.rs:18:11 | LL | v.into_key(); | ^^^^^^^^^^ error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.4.0` - --> tests/ui/incompatible_msrv.rs:21:5 + --> tests/ui/incompatible_msrv.rs:22:5 | LL | sleep(Duration::new(1, 0)); | ^^^^^ -error: aborting due to 3 previous errors +error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.6.0` + --> tests/ui/incompatible_msrv.rs:46:9 + | +LL | core::panicking::panic("foo"); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.6.0` + --> tests/ui/incompatible_msrv.rs:53:13 + | +LL | core::panicking::panic($msg) + | ^^^^^^^^^^^^^^^^^^^^^^ +... +LL | my_panic!("foo"); + | ---------------- in this macro invocation + | + = note: this error originates in the macro `my_panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.6.0` + --> tests/ui/incompatible_msrv.rs:59:13 + | +LL | assert!(core::panicking::panic("out of luck")); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: current MSRV (Minimum Supported Rust Version) is `1.80.0` but this item is stable since `1.82.0` + --> tests/ui/incompatible_msrv.rs:72:13 + | +LL | let _ = std::iter::repeat_n((), 5); + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors From fe01c4499507fc6ba21e07ff9824c14443b308e9 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Fri, 28 Feb 2025 23:20:48 +0100 Subject: [PATCH 059/745] Merge commit '9f9a822509e5ad3e560cbbe830d1013f936fca28' into clippy-subtree-update --- CHANGELOG.md | 59 +- Cargo.toml | 6 +- book/src/development/adding_lints.md | 33 +- book/src/development/basics.md | 2 +- book/src/development/writing_tests.md | 2 +- book/src/lint_configuration.md | 41 +- clippy_config/Cargo.toml | 2 +- clippy_config/src/conf.rs | 30 +- clippy_config/src/types.rs | 89 ++- clippy_dev/src/dogfood.rs | 7 +- clippy_dev/src/fmt.rs | 9 +- clippy_dev/src/lint.rs | 4 +- clippy_dev/src/main.rs | 37 +- clippy_dev/src/new_lint.rs | 85 +-- clippy_dev/src/setup/toolchain.rs | 27 +- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/almost_complete_range.rs | 8 +- clippy_lints/src/approx_const.rs | 10 +- clippy_lints/src/as_conversions.rs | 24 +- clippy_lints/src/assigning_clones.rs | 8 +- clippy_lints/src/attrs/deprecated_cfg_attr.rs | 4 +- .../src/attrs/mixed_attributes_style.rs | 2 +- clippy_lints/src/attrs/mod.rs | 24 +- clippy_lints/src/attrs/repr_attributes.rs | 32 +- clippy_lints/src/await_holding_invalid.rs | 21 +- clippy_lints/src/booleans.rs | 28 +- clippy_lints/src/casts/borrow_as_ptr.rs | 4 +- .../src/casts/cast_abs_to_unsigned.rs | 6 +- clippy_lints/src/casts/cast_lossless.rs | 6 +- clippy_lints/src/casts/cast_sign_loss.rs | 4 +- .../src/casts/cast_slice_different_sizes.rs | 9 +- .../src/casts/cast_slice_from_raw_parts.rs | 6 +- clippy_lints/src/casts/mod.rs | 34 +- clippy_lints/src/casts/ptr_as_ptr.rs | 7 +- clippy_lints/src/casts/ptr_cast_constness.rs | 4 +- clippy_lints/src/checked_conversions.rs | 8 +- clippy_lints/src/copies.rs | 16 +- clippy_lints/src/declared_lints.rs | 11 +- .../src/default_union_representation.rs | 2 +- clippy_lints/src/deprecated_lints.rs | 2 + clippy_lints/src/derivable_impls.rs | 8 +- clippy_lints/src/disallowed_macros.rs | 13 +- clippy_lints/src/disallowed_methods.rs | 14 +- clippy_lints/src/disallowed_types.rs | 24 +- .../src/doc/include_in_doc_without_cfg.rs | 2 +- clippy_lints/src/doc/lazy_continuation.rs | 1 - clippy_lints/src/doc/mod.rs | 118 +++- clippy_lints/src/doc/needless_doctest_main.rs | 2 +- .../src/doc/suspicious_doc_comments.rs | 9 +- .../src/doc/too_long_first_doc_paragraph.rs | 8 +- clippy_lints/src/empty_line_after.rs | 11 +- clippy_lints/src/entry.rs | 26 +- clippy_lints/src/escape.rs | 2 +- clippy_lints/src/eta_reduction.rs | 2 +- clippy_lints/src/excessive_bools.rs | 2 +- clippy_lints/src/format_args.rs | 131 ++++- clippy_lints/src/from_over_into.rs | 10 +- clippy_lints/src/functions/mod.rs | 10 +- clippy_lints/src/functions/must_use.rs | 13 +- clippy_lints/src/functions/result.rs | 10 +- .../src/functions/too_many_arguments.rs | 14 +- clippy_lints/src/if_not_else.rs | 5 +- clippy_lints/src/if_then_some_else_none.rs | 12 +- clippy_lints/src/implicit_saturating_sub.rs | 16 +- clippy_lints/src/incompatible_msrv.rs | 41 +- clippy_lints/src/index_refutable_slice.rs | 6 +- clippy_lints/src/inherent_to_string.rs | 2 +- clippy_lints/src/instant_subtraction.rs | 8 +- .../src/invalid_upcast_comparisons.rs | 3 - clippy_lints/src/large_include_file.rs | 3 +- clippy_lints/src/legacy_numeric_constants.rs | 12 +- clippy_lints/src/lib.rs | 8 +- clippy_lints/src/lifetimes.rs | 137 +++-- clippy_lints/src/lines_filter_map_ok.rs | 18 +- .../literal_string_with_formatting_args.rs | 16 +- clippy_lints/src/loops/explicit_iter_loop.rs | 13 +- clippy_lints/src/loops/manual_flatten.rs | 3 + clippy_lints/src/loops/manual_slice_fill.rs | 20 +- clippy_lints/src/loops/mod.rs | 12 +- clippy_lints/src/loops/same_item_push.rs | 6 +- clippy_lints/src/macro_use.rs | 21 +- clippy_lints/src/manual_async_fn.rs | 1 + clippy_lints/src/manual_bits.rs | 8 +- clippy_lints/src/manual_clamp.rs | 14 +- clippy_lints/src/manual_div_ceil.rs | 11 +- clippy_lints/src/manual_float_methods.rs | 8 +- clippy_lints/src/manual_hash_one.rs | 8 +- clippy_lints/src/manual_is_ascii_check.rs | 10 +- clippy_lints/src/manual_let_else.rs | 2 +- clippy_lints/src/manual_main_separator_str.rs | 8 +- clippy_lints/src/manual_non_exhaustive.rs | 6 +- clippy_lints/src/manual_option_as_slice.rs | 45 +- clippy_lints/src/manual_rem_euclid.rs | 10 +- clippy_lints/src/manual_retain.rs | 26 +- clippy_lints/src/manual_strip.rs | 82 ++- clippy_lints/src/matches/collapsible_match.rs | 8 +- clippy_lints/src/matches/manual_ok_err.rs | 15 +- clippy_lints/src/matches/manual_unwrap_or.rs | 2 +- clippy_lints/src/matches/manual_utils.rs | 24 +- clippy_lints/src/matches/mod.rs | 28 +- clippy_lints/src/matches/redundant_guards.rs | 6 +- .../matches/significant_drop_in_scrutinee.rs | 6 +- clippy_lints/src/mem_replace.rs | 156 +++-- ...se_sensitive_file_extension_comparisons.rs | 5 +- .../src/methods/cloned_instead_of_copied.rs | 6 +- .../src/methods/double_ended_iterator_last.rs | 49 +- clippy_lints/src/methods/err_expect.rs | 7 +- clippy_lints/src/methods/filter_map.rs | 5 +- clippy_lints/src/methods/filter_map_next.rs | 4 +- clippy_lints/src/methods/io_other_error.rs | 37 ++ .../src/methods/is_digit_ascii_radix.rs | 10 +- clippy_lints/src/methods/iter_filter.rs | 5 +- clippy_lints/src/methods/iter_kv_map.rs | 4 +- .../src/methods/manual_c_str_literals.rs | 8 +- clippy_lints/src/methods/manual_contains.rs | 113 ++++ clippy_lints/src/methods/manual_inspect.rs | 6 +- .../src/methods/manual_is_variant_and.rs | 4 +- clippy_lints/src/methods/manual_ok_or.rs | 2 +- clippy_lints/src/methods/manual_repeat_n.rs | 6 +- clippy_lints/src/methods/manual_try_fold.rs | 4 +- clippy_lints/src/methods/map_clone.rs | 6 +- clippy_lints/src/methods/map_unwrap_or.rs | 4 +- .../map_with_unused_argument_over_ranges.rs | 6 +- clippy_lints/src/methods/mod.rs | 191 +++++-- .../src/methods/obfuscated_if_else.rs | 30 +- .../src/methods/option_as_ref_deref.rs | 8 +- .../src/methods/option_map_or_err_ok.rs | 41 -- .../src/methods/option_map_unwrap_or.rs | 8 +- clippy_lints/src/methods/or_fun_call.rs | 2 +- .../src/methods/path_buf_push_overwrite.rs | 2 +- .../src/methods/path_ends_with_ext.rs | 4 +- .../src/methods/range_zip_with_len.rs | 13 +- .../src/methods/read_line_without_trim.rs | 5 +- clippy_lints/src/methods/return_and_then.rs | 2 +- clippy_lints/src/methods/str_splitn.rs | 4 +- .../src/methods/string_lit_chars_any.rs | 6 +- clippy_lints/src/methods/unbuffered_bytes.rs | 25 + .../src/methods/unnecessary_literal_unwrap.rs | 5 +- .../src/methods/unnecessary_map_or.rs | 12 +- .../src/methods/unnecessary_to_owned.rs | 6 +- .../src/methods/unwrap_expect_used.rs | 7 +- clippy_lints/src/methods/useless_asref.rs | 24 +- .../methods/useless_nonzero_new_unchecked.rs | 6 +- clippy_lints/src/min_ident_chars.rs | 3 +- clippy_lints/src/misc.rs | 4 +- clippy_lints/src/missing_const_for_fn.rs | 29 +- .../src/missing_const_for_thread_local.rs | 16 +- clippy_lints/src/mut_reference.rs | 5 +- .../src/needless_borrows_for_generic_args.rs | 10 +- clippy_lints/src/needless_continue.rs | 2 +- clippy_lints/src/needless_pass_by_ref_mut.rs | 2 +- clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_lints/src/no_mangle_with_rust_abi.rs | 2 +- clippy_lints/src/non_copy_const.rs | 16 +- clippy_lints/src/non_expressive_names.rs | 3 +- clippy_lints/src/non_std_lazy_statics.rs | 34 +- clippy_lints/src/operators/manual_midpoint.rs | 64 +++ clippy_lints/src/operators/mod.rs | 30 + clippy_lints/src/panic_unimplemented.rs | 5 +- clippy_lints/src/pass_by_ref_or_value.rs | 2 +- clippy_lints/src/ptr.rs | 2 +- clippy_lints/src/question_mark.rs | 3 +- clippy_lints/src/ranges.rs | 7 +- clippy_lints/src/redundant_else.rs | 10 +- clippy_lints/src/redundant_field_names.rs | 9 +- clippy_lints/src/redundant_locals.rs | 3 +- .../src/redundant_static_lifetimes.rs | 8 +- clippy_lints/src/repeat_vec_with_capacity.rs | 21 +- clippy_lints/src/returns.rs | 7 +- clippy_lints/src/single_option_map.rs | 91 +++ clippy_lints/src/size_of_in_element_count.rs | 2 +- clippy_lints/src/std_instead_of_core.rs | 12 +- clippy_lints/src/string_patterns.rs | 12 +- clippy_lints/src/trait_bounds.rs | 8 +- clippy_lints/src/transmute/mod.rs | 17 +- .../src/transmute/transmute_float_to_int.rs | 4 +- .../src/transmute/transmute_int_to_float.rs | 4 +- .../src/transmute/transmute_num_to_bytes.rs | 5 +- .../src/transmute/transmute_ptr_to_ptr.rs | 6 +- .../src/transmute/transmute_ptr_to_ref.rs | 6 +- clippy_lints/src/tuple_array_conversions.rs | 8 +- clippy_lints/src/types/mod.rs | 71 ++- clippy_lints/src/types/owned_cow.rs | 66 +++ .../src/undocumented_unsafe_blocks.rs | 2 +- clippy_lints/src/unit_types/unit_arg.rs | 5 +- .../src/unnecessary_struct_initialization.rs | 14 +- clippy_lints/src/unnested_or_patterns.rs | 8 +- clippy_lints/src/unused_trait_names.rs | 10 +- clippy_lints/src/use_self.rs | 47 +- .../internal_lints/lint_without_lint_pass.rs | 4 +- .../utils/internal_lints/msrv_attr_impl.rs | 13 +- clippy_lints/src/vec.rs | 6 +- clippy_lints/src/zero_sized_map_values.rs | 17 +- clippy_lints/src/zombie_processes.rs | 10 +- clippy_utils/Cargo.toml | 2 +- clippy_utils/README.md | 2 +- clippy_utils/src/hir_utils.rs | 2 +- clippy_utils/src/lib.rs | 255 ++++++++- clippy_utils/src/macros.rs | 2 + clippy_utils/src/msrvs.rs | 147 +++-- clippy_utils/src/paths.rs | 11 +- clippy_utils/src/qualify_min_const_fn.rs | 123 ++-- clippy_utils/src/source.rs | 56 +- clippy_utils/src/ty/mod.rs | 34 +- lintcheck/src/input.rs | 4 +- rust-toolchain | 2 +- rustc_tools_util/Cargo.toml | 4 +- rustc_tools_util/README.md | 4 +- rustc_tools_util/src/lib.rs | 55 +- tests/compile-test.rs | 22 +- .../lint_groups_priority/fail/Cargo.stderr | 22 +- tests/ui-internal/custom_ice_message.stderr | 2 +- .../ui-internal/invalid_msrv_attr_impl.fixed | 11 +- tests/ui-internal/invalid_msrv_attr_impl.rs | 8 +- .../ui-internal/invalid_msrv_attr_impl.stderr | 26 +- .../absolute_paths_2015.default.stderr | 4 +- .../absolute_paths/absolute_paths_2015.rs | 1 + .../uninlined_format_args.fixed | 6 + .../uninlined_format_args.rs | 6 + .../uninlined_format_args.stderr | 10 +- .../ordering_good.rs | 5 + .../ordering_good_var_1.rs | 1 + .../ordering_mixed.default.stderr | 67 ++- .../ordering_mixed.rs | 17 + .../ordering_mixed_var_1.rs | 8 + .../ordering_mixed_var_1.var_1.stderr | 28 +- .../ordering_only_enum.rs | 1 + .../ordering_only_impl.only_impl.stderr | 6 +- .../ordering_only_impl.rs | 3 + .../ordering_only_trait.only_trait.stderr | 8 +- .../ordering_only_trait.rs | 3 + .../arithmetic_side_effects_allowed.rs | 9 + .../arithmetic_side_effects_allowed.stderr | 16 +- .../array_size_threshold.rs | 2 + .../array_size_threshold.stderr | 2 +- .../await_holding_invalid_type.rs | 3 + .../await_holding_invalid_type.stderr | 4 +- .../await_holding_invalid_type.rs | 2 + .../await_holding_invalid_type.stderr | 11 + .../clippy.toml | 3 + .../borrow_interior_mutable_const/ignore.rs | 1 + ..._incompatible_msrv_in_tests.default.stderr | 11 + ..._incompatible_msrv_in_tests.enabled.stderr | 23 + .../check_incompatible_msrv_in_tests.rs | 31 + .../default/clippy.toml | 1 + .../enabled/clippy.toml | 1 + .../conf_deprecated_key.rs | 1 + tests/ui-toml/dbg_macro/dbg_macro.fixed | 7 + tests/ui-toml/dbg_macro/dbg_macro.rs | 7 + tests/ui-toml/dbg_macro/dbg_macro.stderr | 12 +- .../declare_interior_mutable_const/ignore.rs | 1 + .../disallowed_macros/disallowed_macros.rs | 16 + .../disallowed_macros.stderr | 31 +- .../disallowed_names.rs | 2 + .../disallowed_names.stderr | 2 +- .../disallowed_names.rs | 1 + .../doc_markdown.fixed | 1 + .../doc_valid_idents_append/doc_markdown.rs | 1 + .../doc_markdown.fixed | 3 + .../doc_valid_idents_replace/doc_markdown.rs | 3 + .../doc_markdown.stderr | 2 +- .../duplicated_keys.rs | 1 + .../duplicated_keys.rs | 1 + .../excessive_nesting/excessive_nesting.rs | 37 ++ .../excessive_nesting.stderr | 77 +-- tests/ui-toml/expect_used/clippy.toml | 1 + tests/ui-toml/expect_used/expect_used.rs | 11 + tests/ui-toml/expect_used/expect_used.stderr | 22 +- .../extra_unused_type_parameters.rs | 1 + .../ui-toml/fn_params_excessive_bools/test.rs | 1 + tests/ui-toml/functions_maxlines/test.rs | 4 + tests/ui-toml/functions_maxlines/test.stderr | 10 +- .../conf_no_false_negatives.rs | 1 + tests/ui-toml/ifs_same_cond/ifs_same_cond.rs | 1 + .../indexing_slicing/indexing_slicing.rs | 1 + .../allowed_prefixes/item_name_repetitions.rs | 1 + .../item_name_repetitions.rs | 1 + .../threshold0/item_name_repetitions.rs | 2 + .../ui-toml/large_futures/large_futures.fixed | 1 + tests/ui-toml/large_futures/large_futures.rs | 1 + .../large_include_file/large_include_file.rs | 2 +- .../lint_decimal_readability/test.fixed | 2 + .../ui-toml/lint_decimal_readability/test.rs | 2 + .../lint_decimal_readability/test.stderr | 2 +- .../macro_metavars_in_unsafe/default/test.rs | 29 +- .../min_ident_chars/min_ident_chars.rs | 8 + .../min_ident_chars/min_ident_chars.stderr | 14 +- .../min_rust_version/min_rust_version.fixed | 1 + .../min_rust_version/min_rust_version.rs | 1 + .../conf_missing_enforced_import_rename.fixed | 6 + .../conf_missing_enforced_import_rename.rs | 6 + ...conf_missing_enforced_import_rename.stderr | 10 +- .../module_inception/module_inception.rs | 2 + .../module_inception/module_inception.stderr | 4 +- .../modulo_arithmetic/modulo_arithmetic.rs | 4 + .../modulo_arithmetic.stderr | 6 +- tests/ui-toml/mut_key/mut_key.rs | 1 + .../needless_raw_string_hashes.fixed | 3 + .../needless_raw_string_hashes.rs | 3 + .../needless_raw_string_hashes.stderr | 4 +- .../conf_nonstandard_macro_braces.fixed | 8 + .../conf_nonstandard_macro_braces.rs | 8 + .../conf_nonstandard_macro_braces.stderr | 14 +- tests/ui-toml/panic/panic.rs | 2 + tests/ui-toml/panic/panic.stderr | 2 +- .../path_ends_with_ext/path_ends_with_ext.rs | 2 + tests/ui-toml/print_macro/print_macro.rs | 2 + tests/ui-toml/print_macro/print_macro.stderr | 2 +- .../pub_crate_missing_doc.rs | 7 + .../pub_crate_missing_doc.stderr | 14 +- ...ub_underscore_fields.all_pub_fields.stderr | 12 +- .../pub_underscore_fields.rs | 7 + .../renamed_function_params.default.stderr | 6 +- .../renamed_function_params.extend.stderr | 4 +- .../renamed_function_params.rs | 11 +- .../replaceable_disallowed_types/clippy.toml | 3 + .../replaceable_disallowed_types.fixed | 17 + .../replaceable_disallowed_types.rs | 17 + .../replaceable_disallowed_types.stderr | 11 + tests/ui-toml/semicolon_block/both.fixed | 4 + tests/ui-toml/semicolon_block/both.rs | 4 + tests/ui-toml/semicolon_block/both.stderr | 7 +- .../semicolon_inside_block.fixed | 1 + .../semicolon_block/semicolon_inside_block.rs | 1 + .../semicolon_inside_block.stderr | 1 + .../semicolon_outside_block.fixed | 3 + .../semicolon_outside_block.rs | 3 + .../semicolon_outside_block.stderr | 4 +- .../strict_non_send_fields_in_send_ty/test.rs | 4 + .../test.stderr | 24 +- tests/ui-toml/struct_excessive_bools/test.rs | 1 + .../struct_excessive_bools/test.stderr | 1 + tests/ui-toml/suppress_lint_in_const/test.rs | 6 + .../suppress_lint_in_const/test.stderr | 10 +- .../conf_french_disallowed_name.rs | 7 + .../conf_french_disallowed_name.stderr | 12 +- .../conf_disallowed_methods.rs | 16 +- .../conf_disallowed_methods.stderr | 26 +- .../conf_disallowed_types.rs | 21 + .../conf_disallowed_types.stderr | 40 +- ...conf_inconsistent_struct_constructor.fixed | 5 + .../conf_inconsistent_struct_constructor.rs | 5 + ...onf_inconsistent_struct_constructor.stderr | 16 +- .../clippy.toml | 4 + .../replaceable_disallowed_methods.fixed | 10 + .../replaceable_disallowed_methods.rs | 10 + .../replaceable_disallowed_methods.stderr | 17 + tests/ui-toml/toml_trivially_copy/test.rs | 2 + .../toml_unknown_key/conf_unknown_key.rs | 4 +- .../toml_unknown_key/conf_unknown_key.stderr | 9 + .../undocumented_unsafe_blocks.default.stderr | 75 ++- ...undocumented_unsafe_blocks.disabled.stderr | 95 ++-- .../undocumented_unsafe_blocks.rs | 46 ++ tests/ui-toml/unwrap_used/clippy.toml | 1 + tests/ui-toml/unwrap_used/unwrap_used.fixed | 28 + tests/ui-toml/unwrap_used/unwrap_used.rs | 28 + tests/ui-toml/unwrap_used/unwrap_used.stderr | 52 +- .../ui-toml/unwrap_used/unwrap_used_const.rs | 11 + .../unwrap_used/unwrap_used_const.stderr | 22 + .../upper_case_acronyms.fixed | 13 + .../upper_case_acronyms.rs | 13 + .../upper_case_acronyms.stderr | 24 +- tests/ui-toml/useless_vec/useless_vec.fixed | 1 + tests/ui-toml/useless_vec/useless_vec.rs | 1 + tests/ui-toml/vec_box_sized/test.fixed | 3 + tests/ui-toml/vec_box_sized/test.rs | 3 + tests/ui-toml/vec_box_sized/test.stderr | 4 +- .../zero_single_char_names.rs | 1 + tests/ui/absurd-extreme-comparisons.rs | 56 +- tests/ui/absurd-extreme-comparisons.stderr | 34 +- tests/ui/allow_attributes.fixed | 3 + tests/ui/allow_attributes.rs | 3 + tests/ui/allow_attributes.stderr | 4 +- tests/ui/allow_attributes_without_reason.rs | 5 + .../ui/allow_attributes_without_reason.stderr | 8 +- tests/ui/almost_complete_range.fixed | 27 + tests/ui/almost_complete_range.rs | 27 + tests/ui/almost_complete_range.stderr | 52 +- tests/ui/approx_const.rs | 69 ++- tests/ui/approx_const.stderr | 44 +- tests/ui/arc_with_non_send_sync.rs | 3 + tests/ui/arc_with_non_send_sync.stderr | 4 +- tests/ui/arithmetic_side_effects.rs | 128 +++++ tests/ui/arithmetic_side_effects.stderr | 254 ++++----- tests/ui/as_conversions.rs | 4 +- tests/ui/as_pointer_underscore.fixed | 4 +- tests/ui/as_pointer_underscore.rs | 4 +- tests/ui/as_ptr_cast_mut.rs | 7 +- tests/ui/as_underscore.fixed | 2 + tests/ui/as_underscore.rs | 2 + tests/ui/as_underscore.stderr | 2 +- tests/ui/asm_syntax_not_x86.rs | 1 + tests/ui/asm_syntax_x86.rs | 22 +- tests/ui/asm_syntax_x86.stderr | 14 +- tests/ui/assertions_on_constants.rs | 30 +- tests/ui/assertions_on_constants.stderr | 22 +- tests/ui/assertions_on_result_states.fixed | 7 + tests/ui/assertions_on_result_states.rs | 7 + tests/ui/assertions_on_result_states.stderr | 12 +- tests/ui/assign_ops.fixed | 11 + tests/ui/assign_ops.rs | 11 + tests/ui/assign_ops.stderr | 20 +- tests/ui/assign_ops2.rs | 31 +- tests/ui/assign_ops2.stderr | 16 +- tests/ui/assigning_clones.fixed | 30 + tests/ui/assigning_clones.rs | 30 + tests/ui/assigning_clones.stderr | 58 +- tests/ui/async_yields_async.fixed | 6 + tests/ui/async_yields_async.rs | 6 + tests/ui/async_yields_async.stderr | 10 +- tests/ui/attrs.rs | 8 +- tests/ui/attrs.stderr | 4 +- tests/ui/author.rs | 2 + tests/ui/author/blocks.rs | 1 + tests/ui/author/call.rs | 2 + tests/ui/author/if.rs | 2 + tests/ui/author/issue_3849.rs | 2 + tests/ui/author/loop.rs | 2 + tests/ui/author/macro_in_closure.rs | 2 + tests/ui/author/macro_in_loop.rs | 2 + tests/ui/author/matches.rs | 2 + tests/ui/author/repeat.rs | 2 + tests/ui/author/struct.rs | 2 + tests/ui/await_holding_refcell_ref.rs | 16 +- tests/ui/await_holding_refcell_ref.stderr | 22 +- tests/ui/bind_instead_of_map.fixed | 3 + tests/ui/bind_instead_of_map.rs | 3 + tests/ui/bind_instead_of_map.stderr | 4 +- tests/ui/bind_instead_of_map_multipart.fixed | 5 + tests/ui/bind_instead_of_map_multipart.rs | 5 + tests/ui/bind_instead_of_map_multipart.stderr | 11 +- tests/ui/bit_masks.rs | 48 +- tests/ui/bit_masks.stderr | 26 +- tests/ui/blanket_clippy_restriction_lints.rs | 7 +- .../blanket_clippy_restriction_lints.stderr | 6 +- tests/ui/blocks_in_conditions.fixed | 1 + tests/ui/blocks_in_conditions.rs | 1 + tests/ui/blocks_in_conditions.stderr | 2 +- tests/ui/bool_assert_comparison.fixed | 33 ++ tests/ui/bool_assert_comparison.rs | 33 ++ tests/ui/bool_assert_comparison.stderr | 64 +-- tests/ui/bool_comparison.fixed | 25 + tests/ui/bool_comparison.rs | 25 + tests/ui/bool_comparison.stderr | 48 +- tests/ui/bool_to_int_with_if.fixed | 1 + tests/ui/bool_to_int_with_if.rs | 9 + tests/ui/bool_to_int_with_if.stderr | 24 +- tests/ui/borrow_and_ref_as_ptr.fixed | 2 + tests/ui/borrow_and_ref_as_ptr.rs | 2 + tests/ui/borrow_and_ref_as_ptr.stderr | 2 +- tests/ui/borrow_as_ptr.fixed | 4 + tests/ui/borrow_as_ptr.rs | 4 + tests/ui/borrow_as_ptr.stderr | 6 +- tests/ui/borrow_as_ptr_no_std.fixed | 2 + tests/ui/borrow_as_ptr_no_std.rs | 2 + tests/ui/borrow_as_ptr_no_std.stderr | 2 +- tests/ui/borrow_as_ptr_raw_ref.fixed | 2 + tests/ui/borrow_as_ptr_raw_ref.rs | 2 + tests/ui/borrow_as_ptr_raw_ref.stderr | 2 +- tests/ui/borrow_box.fixed | 24 +- tests/ui/borrow_box.rs | 24 +- tests/ui/borrow_box.stderr | 12 +- tests/ui/borrow_deref_ref.fixed | 4 + tests/ui/borrow_deref_ref.rs | 4 + tests/ui/borrow_deref_ref.stderr | 4 +- tests/ui/borrow_deref_ref_unfixable.rs | 3 +- .../borrow_interior_mutable_const/others.rs | 42 +- .../others.stderr | 26 +- .../projections.rs | 42 ++ .../projections.stderr | 44 ++ .../borrow_interior_mutable_const/traits.rs | 51 +- .../traits.stderr | 58 +- tests/ui/box_collection.rs | 18 +- tests/ui/box_default.fixed | 10 + tests/ui/box_default.rs | 10 + tests/ui/box_default.stderr | 18 +- tests/ui/box_default_no_std.rs | 2 + tests/ui/boxed_local.rs | 11 +- tests/ui/boxed_local.stderr | 2 +- .../branches_sharing_code/false_positives.rs | 2 + .../branches_sharing_code/shared_at_bottom.rs | 25 +- .../shared_at_bottom.stderr | 16 +- .../ui/branches_sharing_code/shared_at_top.rs | 18 +- .../shared_at_top.stderr | 17 +- .../shared_at_top_and_bottom.rs | 15 +- .../shared_at_top_and_bottom.stderr | 25 +- .../branches_sharing_code/valid_if_blocks.rs | 10 +- tests/ui/builtin_type_shadow.rs | 4 +- tests/ui/builtin_type_shadow.stderr | 3 +- tests/ui/byte_char_slices.fixed | 5 + tests/ui/byte_char_slices.rs | 5 + tests/ui/byte_char_slices.stderr | 8 +- tests/ui/bytecount.rs | 6 +- tests/ui/bytes_count_to_len.fixed | 10 +- tests/ui/bytes_count_to_len.rs | 10 +- tests/ui/bytes_count_to_len.stderr | 6 +- tests/ui/bytes_nth.fixed | 3 + tests/ui/bytes_nth.rs | 3 + tests/ui/bytes_nth.stderr | 4 +- ...sensitive_file_extension_comparisons.fixed | 6 + ...se_sensitive_file_extension_comparisons.rs | 6 + ...ensitive_file_extension_comparisons.stderr | 10 +- tests/ui/cast.rs | 229 +++++--- tests/ui/cast.stderr | 180 +++--- tests/ui/cast_abs_to_unsigned.fixed | 18 + tests/ui/cast_abs_to_unsigned.rs | 18 + tests/ui/cast_abs_to_unsigned.stderr | 42 +- tests/ui/cast_alignment.rs | 11 +- tests/ui/cast_alignment.stderr | 2 +- tests/ui/cast_enum_constructor.rs | 7 +- tests/ui/cast_lossless_bool.fixed | 15 + tests/ui/cast_lossless_bool.rs | 15 + tests/ui/cast_lossless_bool.stderr | 28 +- tests/ui/cast_lossless_float.fixed | 13 + tests/ui/cast_lossless_float.rs | 13 + tests/ui/cast_lossless_float.stderr | 24 +- tests/ui/cast_lossless_integer.fixed | 27 + tests/ui/cast_lossless_integer.rs | 27 + tests/ui/cast_lossless_integer.stderr | 78 +-- tests/ui/cast_nan_to_int.rs | 22 +- tests/ui/cast_nan_to_int.stderr | 6 +- tests/ui/cast_raw_slice_pointer_cast.fixed | 7 + tests/ui/cast_raw_slice_pointer_cast.rs | 7 + tests/ui/cast_raw_slice_pointer_cast.stderr | 12 +- tests/ui/cast_size.32bit.stderr | 83 +-- tests/ui/cast_size.64bit.stderr | 36 +- tests/ui/cast_size.rs | 23 +- tests/ui/cast_slice_different_sizes.rs | 40 +- tests/ui/cast_slice_different_sizes.stderr | 29 +- tests/ui/cfg_attr_cargo_clippy.fixed | 21 +- tests/ui/cfg_attr_cargo_clippy.rs | 21 +- tests/ui/cfg_attr_cargo_clippy.stderr | 12 +- tests/ui/cfg_attr_rustfmt.fixed | 3 + tests/ui/cfg_attr_rustfmt.rs | 3 + tests/ui/cfg_attr_rustfmt.stderr | 4 +- tests/ui/cfg_not_test.rs | 5 + tests/ui/cfg_not_test.stderr | 8 +- tests/ui/char_lit_as_u8.rs | 3 +- tests/ui/char_lit_as_u8_suggestions.fixed | 4 + tests/ui/char_lit_as_u8_suggestions.rs | 4 + tests/ui/char_lit_as_u8_suggestions.stderr | 6 +- tests/ui/checked_conversions.fixed | 17 + tests/ui/checked_conversions.rs | 17 + tests/ui/checked_conversions.stderr | 32 +- .../ui/checked_unwrap/complex_conditionals.rs | 56 +- .../complex_conditionals.stderr | 38 +- .../complex_conditionals_nested.rs | 4 +- .../ui/checked_unwrap/simple_conditionals.rs | 58 +- .../checked_unwrap/simple_conditionals.stderr | 50 +- tests/ui/clear_with_drain.fixed | 21 + tests/ui/clear_with_drain.rs | 21 + tests/ui/clear_with_drain.stderr | 40 +- tests/ui/clone_on_copy.fixed | 10 + tests/ui/clone_on_copy.rs | 10 + tests/ui/clone_on_copy.stderr | 16 +- tests/ui/clone_on_copy_impl.rs | 2 + tests/ui/cloned_instead_of_copied.fixed | 10 + tests/ui/cloned_instead_of_copied.rs | 10 + tests/ui/cloned_instead_of_copied.stderr | 14 +- tests/ui/cmp_null.fixed | 15 +- tests/ui/cmp_null.rs | 15 +- tests/ui/cmp_null.stderr | 6 +- .../ui/cmp_owned/asymmetric_partial_eq.fixed | 6 + tests/ui/cmp_owned/asymmetric_partial_eq.rs | 6 + .../ui/cmp_owned/asymmetric_partial_eq.stderr | 10 +- tests/ui/cmp_owned/comparison_flip.fixed | 2 + tests/ui/cmp_owned/comparison_flip.rs | 2 + tests/ui/cmp_owned/comparison_flip.stderr | 2 +- tests/ui/cmp_owned/with_suggestion.fixed | 6 + tests/ui/cmp_owned/with_suggestion.rs | 6 + tests/ui/cmp_owned/with_suggestion.stderr | 10 +- tests/ui/cmp_owned/without_suggestion.rs | 7 +- tests/ui/cmp_owned/without_suggestion.stderr | 4 +- tests/ui/cognitive_complexity.rs | 59 +- tests/ui/cognitive_complexity.stderr | 38 +- tests/ui/cognitive_complexity_attr_used.rs | 3 +- tests/ui/collapsible_else_if.fixed | 8 + tests/ui/collapsible_else_if.rs | 8 + tests/ui/collapsible_else_if.stderr | 14 +- tests/ui/collapsible_if.fixed | 9 + tests/ui/collapsible_if.rs | 9 + tests/ui/collapsible_if.stderr | 16 +- tests/ui/collapsible_match.rs | 31 +- tests/ui/collapsible_match.stderr | 48 +- tests/ui/collapsible_match2.rs | 9 +- tests/ui/collapsible_match2.stderr | 11 +- tests/ui/collapsible_str_replace.fixed | 13 + tests/ui/collapsible_str_replace.rs | 14 + tests/ui/collapsible_str_replace.stderr | 27 +- tests/ui/collection_is_never_read.rs | 61 +- tests/ui/collection_is_never_read.stderr | 36 +- tests/ui/comparison_chain.rs | 24 +- tests/ui/comparison_chain.stderr | 28 +- tests/ui/comparison_to_empty.fixed | 13 + tests/ui/comparison_to_empty.rs | 13 + tests/ui/comparison_to_empty.stderr | 24 +- tests/ui/const_comparisons.rs | 83 ++- tests/ui/const_comparisons.stderr | 56 +- tests/ui/const_is_empty.rs | 70 ++- tests/ui/const_is_empty.stderr | 40 +- tests/ui/copy_iterator.rs | 4 +- tests/ui/crashes/associated-constant-ice.rs | 1 + tests/ui/crashes/cc_seme.rs | 1 + ... elidable_lifetime_names_impl_trait.fixed} | 6 +- ... => elidable_lifetime_names_impl_trait.rs} | 6 +- ...elidable_lifetime_names_impl_trait.stderr} | 10 +- tests/ui/crashes/enum-glob-import-crate.rs | 2 + tests/ui/crashes/ice-10148.rs | 1 + tests/ui/crashes/ice-10508a.rs | 20 + tests/ui/crashes/ice-10508b.rs | 26 + tests/ui/crashes/ice-10508c.rs | 9 + tests/ui/crashes/ice-10972-tait.rs | 1 + tests/ui/crashes/ice-11065.rs | 2 + tests/ui/crashes/ice-11230.fixed | 2 + tests/ui/crashes/ice-11230.rs | 2 + tests/ui/crashes/ice-11230.stderr | 2 +- tests/ui/crashes/ice-11337.rs | 2 + tests/ui/crashes/ice-11422.fixed | 1 + tests/ui/crashes/ice-11422.rs | 1 + tests/ui/crashes/ice-11755.rs | 2 + tests/ui/crashes/ice-11803.rs | 2 + tests/ui/crashes/ice-11939.rs | 2 + tests/ui/crashes/ice-12253.rs | 2 + tests/ui/crashes/ice-12491.fixed | 1 + tests/ui/crashes/ice-12491.rs | 1 + tests/ui/crashes/ice-12585.rs | 2 + tests/ui/crashes/ice-12616.fixed | 1 + tests/ui/crashes/ice-12616.rs | 1 + tests/ui/crashes/ice-13862.rs | 2 + tests/ui/crashes/ice-14303.rs | 12 + tests/ui/crashes/ice-14325.rs | 17 + tests/ui/crashes/ice-1588.rs | 2 + tests/ui/crashes/ice-1782.rs | 2 + tests/ui/crashes/ice-1969.rs | 2 + tests/ui/crashes/ice-2499.rs | 2 + tests/ui/crashes/ice-2594.rs | 2 + tests/ui/crashes/ice-2727.rs | 1 + tests/ui/crashes/ice-2760.rs | 2 + tests/ui/crashes/ice-2774.fixed | 4 +- tests/ui/crashes/ice-2774.rs | 4 +- tests/ui/crashes/ice-2862.rs | 1 + tests/ui/crashes/ice-2865.rs | 2 + tests/ui/crashes/ice-3151.rs | 1 + tests/ui/crashes/ice-3462.rs | 2 + tests/ui/crashes/ice-360.rs | 8 +- tests/ui/crashes/ice-3717.fixed | 3 +- tests/ui/crashes/ice-3717.rs | 3 +- tests/ui/crashes/ice-3717.stderr | 1 + tests/ui/crashes/ice-3741.rs | 1 + tests/ui/crashes/ice-3747.rs | 1 + tests/ui/crashes/ice-3969.rs | 11 +- tests/ui/crashes/ice-3969.stderr | 8 +- tests/ui/crashes/ice-4121.rs | 2 + tests/ui/crashes/ice-4545.rs | 2 + tests/ui/crashes/ice-4579.rs | 2 + tests/ui/crashes/ice-4671.rs | 2 + tests/ui/crashes/ice-4727.rs | 2 + tests/ui/crashes/ice-4760.rs | 2 + tests/ui/crashes/ice-4775.rs | 2 + tests/ui/crashes/ice-4968.rs | 1 + tests/ui/crashes/ice-5207.rs | 1 + tests/ui/crashes/ice-5223.rs | 1 + tests/ui/crashes/ice-5238.rs | 1 + tests/ui/crashes/ice-5389.rs | 2 + tests/ui/crashes/ice-5579.rs | 2 + tests/ui/crashes/ice-5835.1.fixed | 11 + tests/ui/crashes/ice-5835.2.fixed | 13 + tests/ui/crashes/ice-5835.fixed | 3 +- tests/ui/crashes/ice-5835.rs | 3 +- tests/ui/crashes/ice-5835.stderr | 2 +- tests/ui/crashes/ice-5872.fixed | 3 +- tests/ui/crashes/ice-5872.rs | 3 +- tests/ui/crashes/ice-5944.rs | 2 + tests/ui/crashes/ice-6139.rs | 2 + tests/ui/crashes/ice-6153.rs | 2 + tests/ui/crashes/ice-6179.rs | 1 + tests/ui/crashes/ice-6250.rs | 2 + tests/ui/crashes/ice-6251.rs | 3 + tests/ui/crashes/ice-6252.rs | 3 + tests/ui/crashes/ice-6252.stderr | 4 +- tests/ui/crashes/ice-6254.rs | 1 + tests/ui/crashes/ice-6332.rs | 2 + tests/ui/crashes/ice-6539.rs | 1 + tests/ui/crashes/ice-6792.rs | 1 + tests/ui/crashes/ice-6793.rs | 1 + tests/ui/crashes/ice-6840.rs | 1 + tests/ui/crashes/ice-700.rs | 2 + tests/ui/crashes/ice-7012.rs | 2 + tests/ui/crashes/ice-7126.rs | 1 + tests/ui/crashes/ice-7169.fixed | 3 +- tests/ui/crashes/ice-7169.rs | 3 +- tests/ui/crashes/ice-7231.rs | 2 + tests/ui/crashes/ice-7272.rs | 1 + tests/ui/crashes/ice-7340.rs | 2 + tests/ui/crashes/ice-7410.rs | 1 + tests/ui/crashes/ice-7423.rs | 2 + tests/ui/crashes/ice-7868.rs | 1 + tests/ui/crashes/ice-7869.rs | 2 +- tests/ui/crashes/ice-7934.rs | 2 + tests/ui/crashes/ice-8250.fixed | 4 +- tests/ui/crashes/ice-8250.rs | 4 +- tests/ui/crashes/ice-8386.rs | 2 + tests/ui/crashes/ice-8681.rs | 1 + tests/ui/crashes/ice-8821.rs | 2 + tests/ui/crashes/ice-8850.fixed | 7 +- tests/ui/crashes/ice-8850.rs | 7 +- tests/ui/crashes/ice-8850.stderr | 4 +- tests/ui/crashes/ice-9041.rs | 3 +- tests/ui/crashes/ice-9238.rs | 2 + tests/ui/crashes/ice-9242.rs | 2 + tests/ui/crashes/ice-9405.rs | 2 + tests/ui/crashes/ice-9405.stderr | 2 +- tests/ui/crashes/ice-9414.rs | 2 + tests/ui/crashes/ice-9445.rs | 1 + tests/ui/crashes/ice-9459.rs | 2 + tests/ui/crashes/ice-9463.rs | 3 +- tests/ui/crashes/ice-9625.rs | 2 + tests/ui/crashes/ice-9746.rs | 1 + tests/ui/crashes/ice-rust-107877.rs | 2 + tests/ui/crashes/ice_exact_size.rs | 2 + tests/ui/crashes/if_same_then_else.rs | 2 + tests/ui/crashes/implements-trait.rs | 2 + tests/ui/crashes/inherent_impl.rs | 2 + tests/ui/crashes/issue-825.rs | 2 + tests/ui/crashes/issues_loop_mut_cond.rs | 2 + tests/ui/crashes/match_same_arms_const.rs | 2 + tests/ui/crashes/needless_borrow_fp.rs | 2 + .../needless_pass_by_value-w-late-bound.fixed | 2 +- .../needless_pass_by_value-w-late-bound.rs | 2 +- tests/ui/crashes/regressions.rs | 2 + tests/ui/crashes/returns.rs | 1 + tests/ui/crashes/shadow.rs | 2 + tests/ui/crashes/single-match-else.rs | 2 + .../crashes/third-party/conf_allowlisted.rs | 2 + tests/ui/crashes/trivial_bounds.rs | 2 + .../ui/crashes/unreachable-array-or-slice.rs | 1 + .../crashes/used_underscore_binding_macro.rs | 2 + tests/ui/crate_in_macro_def.fixed | 1 + tests/ui/crate_in_macro_def.rs | 1 + .../entrypoint_recursion.rs | 1 + tests/ui/crate_level_checks/no_std_swap.rs | 4 +- .../crate_level_checks/std_main_recursion.rs | 2 +- tests/ui/create_dir.fixed | 2 + tests/ui/create_dir.rs | 2 + tests/ui/create_dir.stderr | 2 +- tests/ui/dbg_macro/dbg_macro.fixed | 47 +- tests/ui/dbg_macro/dbg_macro.rs | 47 +- tests/ui/dbg_macro/dbg_macro.stderr | 34 +- tests/ui/dbg_macro/dbg_macro_unfixable.rs | 9 +- tests/ui/dbg_macro/dbg_macro_unfixable.stderr | 10 +- tests/ui/debug_assert_with_mut_call.rs | 86 ++- tests/ui/debug_assert_with_mut_call.stderr | 54 +- tests/ui/decimal_literal_representation.fixed | 7 + tests/ui/decimal_literal_representation.rs | 7 + .../ui/decimal_literal_representation.stderr | 12 +- .../declare_interior_mutable_const/enums.rs | 35 +- .../enums.stderr | 23 +- .../declare_interior_mutable_const/others.rs | 11 +- .../others.stderr | 8 +- .../declare_interior_mutable_const/traits.rs | 38 +- .../traits.stderr | 22 +- .../ui/default_constructed_unit_structs.fixed | 6 + tests/ui/default_constructed_unit_structs.rs | 6 + .../default_constructed_unit_structs.stderr | 10 +- tests/ui/default_instead_of_iter_empty.fixed | 3 + tests/ui/default_instead_of_iter_empty.rs | 3 + tests/ui/default_instead_of_iter_empty.stderr | 4 +- ...default_instead_of_iter_empty_no_std.fixed | 2 + .../default_instead_of_iter_empty_no_std.rs | 2 + ...efault_instead_of_iter_empty_no_std.stderr | 2 +- tests/ui/default_numeric_fallback_f64.fixed | 23 + tests/ui/default_numeric_fallback_f64.rs | 23 + tests/ui/default_numeric_fallback_f64.stderr | 44 +- tests/ui/default_numeric_fallback_i32.fixed | 28 + tests/ui/default_numeric_fallback_i32.rs | 28 + tests/ui/default_numeric_fallback_i32.stderr | 54 +- tests/ui/default_trait_access.fixed | 8 + tests/ui/default_trait_access.rs | 8 + tests/ui/default_trait_access.stderr | 14 +- tests/ui/default_union_representation.rs | 8 +- tests/ui/deprecated.rs | 1 + tests/ui/deprecated.stderr | 8 +- tests/ui/deref_addrof.fixed | 11 + tests/ui/deref_addrof.rs | 11 + tests/ui/deref_addrof.stderr | 20 +- tests/ui/deref_addrof_double_trigger.rs | 7 +- tests/ui/deref_addrof_double_trigger.stderr | 4 +- tests/ui/deref_addrof_macro.rs | 1 + tests/ui/deref_by_slicing.fixed | 14 + tests/ui/deref_by_slicing.rs | 14 + tests/ui/deref_by_slicing.stderr | 18 +- tests/ui/derivable_impls.fixed | 34 ++ tests/ui/derivable_impls.rs | 60 ++ tests/ui/derivable_impls.stderr | 73 ++- tests/ui/derive.rs | 15 +- tests/ui/derive.stderr | 56 +- tests/ui/derive_ord_xor_partial_ord.rs | 12 +- tests/ui/derive_ord_xor_partial_ord.stderr | 22 +- tests/ui/derive_partial_eq_without_eq.fixed | 17 +- tests/ui/derive_partial_eq_without_eq.rs | 17 +- tests/ui/derive_partial_eq_without_eq.stderr | 32 +- tests/ui/derived_hash_with_manual_eq.rs | 6 +- tests/ui/derived_hash_with_manual_eq.stderr | 6 +- tests/ui/disallowed_names.rs | 36 +- tests/ui/disallowed_names.stderr | 24 +- tests/ui/disallowed_script_idents.rs | 5 +- tests/ui/disallowed_script_idents.stderr | 2 +- tests/ui/diverging_sub_expression.rs | 33 +- tests/ui/diverging_sub_expression.stderr | 16 +- tests/ui/doc/doc-fixable.fixed | 34 ++ tests/ui/doc/doc-fixable.rs | 34 ++ tests/ui/doc/doc-fixable.stderr | 64 +-- tests/ui/doc/doc_include_without_cfg.fixed | 6 +- tests/ui/doc/doc_include_without_cfg.rs | 6 +- tests/ui/doc/doc_include_without_cfg.stderr | 2 +- .../ui/doc/doc_nested_refdef_list_item.fixed | 8 + tests/ui/doc/doc_nested_refdef_list_item.rs | 8 + .../ui/doc/doc_nested_refdef_list_item.stderr | 26 +- tests/ui/doc/footnote_issue_13183.rs | 1 + tests/ui/doc/issue_12795.fixed | 8 +- tests/ui/doc/issue_12795.rs | 8 +- tests/ui/doc/issue_1832.rs | 1 + tests/ui/doc/issue_902.rs | 1 + tests/ui/doc/issue_9473.fixed | 1 + tests/ui/doc/issue_9473.rs | 1 + tests/ui/doc/link_adjacent.fixed | 52 ++ tests/ui/doc/link_adjacent.rs | 52 ++ tests/ui/doc/link_adjacent.stderr | 134 +++++ tests/ui/doc/needless_doctest_main.rs | 2 + tests/ui/doc/unbalanced_ticks.rs | 21 +- tests/ui/doc_errors.rs | 21 +- tests/ui/doc_errors.stderr | 10 +- tests/ui/doc_link_with_quotes.rs | 5 +- tests/ui/doc_link_with_quotes.stderr | 2 +- tests/ui/doc_unsafe.rs | 6 + tests/ui/doc_unsafe.stderr | 10 +- tests/ui/double_comparison.fixed | 8 + tests/ui/double_comparison.rs | 8 + tests/ui/double_comparison.stderr | 14 +- tests/ui/double_ended_iterator_last.fixed | 43 +- tests/ui/double_ended_iterator_last.rs | 43 +- tests/ui/double_ended_iterator_last.stderr | 75 ++- .../double_ended_iterator_last_unfixable.rs | 23 + ...ouble_ended_iterator_last_unfixable.stderr | 33 ++ tests/ui/double_must_use.rs | 12 +- tests/ui/double_must_use.stderr | 6 +- tests/ui/double_parens.rs | 20 +- tests/ui/double_parens.stderr | 10 +- tests/ui/drain_collect.fixed | 10 + tests/ui/drain_collect.rs | 10 + tests/ui/drain_collect.stderr | 26 +- tests/ui/drain_collect_nostd.fixed | 1 + tests/ui/drain_collect_nostd.rs | 1 + tests/ui/drop_non_drop.rs | 6 +- tests/ui/drop_non_drop.stderr | 4 +- tests/ui/duplicate_underscore_argument.rs | 4 +- tests/ui/duration_subsec.fixed | 5 + tests/ui/duration_subsec.rs | 5 + tests/ui/duration_subsec.stderr | 8 +- tests/ui/eager_transmute.fixed | 17 + tests/ui/eager_transmute.rs | 17 + tests/ui/eager_transmute.stderr | 32 +- tests/ui/elidable_lifetime_names.fixed | 194 +++++++ tests/ui/elidable_lifetime_names.rs | 194 +++++++ tests/ui/elidable_lifetime_names.stderr | 162 ++++++ tests/ui/else_if_without_else.rs | 12 +- tests/ui/else_if_without_else.stderr | 10 +- tests/ui/empty_docs.rs | 9 + tests/ui/empty_docs.stderr | 16 +- tests/ui/empty_drop.rs | 2 + tests/ui/empty_drop.stderr | 4 +- tests/ui/empty_enum.rs | 2 +- .../empty_enum_variants_with_brackets.fixed | 14 +- tests/ui/empty_enum_variants_with_brackets.rs | 14 +- .../empty_enum_variants_with_brackets.stderr | 6 +- tests/ui/empty_enum_without_never_type.rs | 2 + .../ui/empty_line_after/doc_comments.1.fixed | 1 + .../ui/empty_line_after/doc_comments.2.fixed | 4 +- tests/ui/empty_line_after/doc_comments.rs | 1 + tests/ui/empty_line_after/doc_comments.stderr | 5 + tests/ui/empty_loop.rs | 3 + tests/ui/empty_loop.stderr | 4 +- tests/ui/empty_loop_no_std.rs | 2 +- tests/ui/empty_structs_with_brackets.fixed | 2 + tests/ui/empty_structs_with_brackets.rs | 2 + tests/ui/empty_structs_with_brackets.stderr | 2 +- tests/ui/endian_bytes.rs | 86 +++ tests/ui/endian_bytes.stderr | 170 +++--- tests/ui/entry.fixed | 40 ++ tests/ui/entry.rs | 42 ++ tests/ui/entry.stderr | 48 +- tests/ui/entry_btree.fixed | 1 + tests/ui/entry_btree.rs | 1 + tests/ui/entry_btree.stderr | 2 + tests/ui/entry_with_else.fixed | 7 + tests/ui/entry_with_else.rs | 7 + tests/ui/entry_with_else.stderr | 26 +- tests/ui/enum_clike_unportable_variant.rs | 19 +- tests/ui/enum_clike_unportable_variant.stderr | 16 +- tests/ui/enum_glob_use.fixed | 3 + tests/ui/enum_glob_use.rs | 3 + tests/ui/enum_glob_use.stderr | 4 +- tests/ui/enum_variants.rs | 33 +- tests/ui/enum_variants.stderr | 28 +- tests/ui/eprint_with_newline.fixed | 25 +- tests/ui/eprint_with_newline.rs | 25 +- tests/ui/eprint_with_newline.stderr | 14 +- tests/ui/eq_op.rs | 78 ++- tests/ui/eq_op.stderr | 54 +- tests/ui/eq_op_macros.rs | 28 +- tests/ui/eq_op_macros.stderr | 22 +- tests/ui/equatable_if_let.fixed | 14 + tests/ui/equatable_if_let.rs | 14 + tests/ui/equatable_if_let.stderr | 26 +- tests/ui/erasing_op.rs | 15 +- tests/ui/erasing_op.stderr | 6 +- tests/ui/err_expect.fixed | 2 + tests/ui/err_expect.rs | 2 + tests/ui/err_expect.stderr | 2 +- tests/ui/error_impl_error.rs | 8 +- tests/ui/eta.fixed | 38 ++ tests/ui/eta.rs | 38 ++ tests/ui/eta.stderr | 68 +-- tests/ui/eta_nostd.fixed | 1 + tests/ui/eta_nostd.rs | 1 + tests/ui/excessive_precision.fixed | 16 + tests/ui/excessive_precision.rs | 16 + tests/ui/excessive_precision.stderr | 30 +- tests/ui/exhaustive_items.fixed | 3 + tests/ui/exhaustive_items.rs | 3 + tests/ui/exhaustive_items.stderr | 7 +- tests/ui/exit1.rs | 3 +- tests/ui/exit2.rs | 3 +- tests/ui/exit3.rs | 2 + tests/ui/expect.rs | 7 +- tests/ui/expect.stderr | 2 +- tests/ui/expect_fun_call.fixed | 15 + tests/ui/expect_fun_call.rs | 15 + tests/ui/expect_fun_call.stderr | 28 +- tests/ui/expect_tool_lint_rfc_2383.rs | 3 + tests/ui/expect_tool_lint_rfc_2383.stderr | 12 +- tests/ui/explicit_auto_deref.fixed | 49 ++ tests/ui/explicit_auto_deref.rs | 49 ++ tests/ui/explicit_auto_deref.stderr | 90 +-- tests/ui/explicit_counter_loop.rs | 30 +- tests/ui/explicit_counter_loop.stderr | 16 +- tests/ui/explicit_deref_methods.fixed | 12 + tests/ui/explicit_deref_methods.rs | 12 + tests/ui/explicit_deref_methods.stderr | 22 +- tests/ui/explicit_into_iter_loop.fixed | 6 + tests/ui/explicit_into_iter_loop.rs | 6 + tests/ui/explicit_into_iter_loop.stderr | 10 +- tests/ui/explicit_iter_loop.fixed | 18 + tests/ui/explicit_iter_loop.rs | 18 + tests/ui/explicit_iter_loop.stderr | 34 +- tests/ui/explicit_write.fixed | 13 + tests/ui/explicit_write.rs | 13 + tests/ui/explicit_write.stderr | 24 +- tests/ui/extend_with_drain.fixed | 4 + tests/ui/extend_with_drain.rs | 4 + tests/ui/extend_with_drain.stderr | 6 +- tests/ui/extra_unused_lifetimes.rs | 7 + tests/ui/extra_unused_lifetimes.stderr | 12 +- tests/ui/extra_unused_type_parameters.fixed | 8 + tests/ui/extra_unused_type_parameters.rs | 8 + tests/ui/extra_unused_type_parameters.stderr | 14 +- .../extra_unused_type_parameters_unfixable.rs | 6 +- tests/ui/fallible_impl_from.rs | 12 +- tests/ui/fallible_impl_from.stderr | 24 +- tests/ui/field_reassign_with_default.rs | 11 + tests/ui/field_reassign_with_default.stderr | 58 +- tests/ui/field_scoped_visibility_modifiers.rs | 3 + .../field_scoped_visibility_modifiers.stderr | 4 +- tests/ui/filetype_is_file.rs | 9 +- tests/ui/filetype_is_file.stderr | 4 +- tests/ui/filter_map_bool_then.fixed | 10 + tests/ui/filter_map_bool_then.rs | 10 + tests/ui/filter_map_bool_then.stderr | 18 +- tests/ui/filter_map_identity.fixed | 62 +- tests/ui/filter_map_identity.rs | 60 +- tests/ui/filter_map_identity.stderr | 84 +-- tests/ui/filter_map_next.rs | 5 +- tests/ui/filter_map_next.stderr | 3 - tests/ui/filter_map_next_fixable.fixed | 2 + tests/ui/filter_map_next_fixable.rs | 2 + tests/ui/filter_map_next_fixable.stderr | 2 +- tests/ui/find_map.rs | 2 + tests/ui/flat_map_identity.fixed | 3 + tests/ui/flat_map_identity.rs | 3 + tests/ui/flat_map_identity.stderr | 4 +- tests/ui/flat_map_option.fixed | 2 + tests/ui/flat_map_option.rs | 2 + tests/ui/flat_map_option.stderr | 2 +- tests/ui/float_arithmetic.rs | 48 +- tests/ui/float_arithmetic.stderr | 32 +- tests/ui/float_cmp.rs | 15 +- tests/ui/float_cmp.stderr | 10 +- tests/ui/float_cmp_const.rs | 21 +- tests/ui/float_cmp_const.stderr | 14 +- tests/ui/float_equality_without_abs.rs | 31 +- tests/ui/float_equality_without_abs.stderr | 18 +- tests/ui/floating_point_abs.fixed | 8 + tests/ui/floating_point_abs.rs | 8 + tests/ui/floating_point_abs.stderr | 14 +- tests/ui/floating_point_arithmetic_nostd.rs | 2 + tests/ui/floating_point_exp.fixed | 5 + tests/ui/floating_point_exp.rs | 5 + tests/ui/floating_point_exp.stderr | 8 +- tests/ui/floating_point_hypot.fixed | 3 + tests/ui/floating_point_hypot.rs | 3 + tests/ui/floating_point_hypot.stderr | 4 +- tests/ui/floating_point_log.fixed | 29 + tests/ui/floating_point_log.rs | 29 + tests/ui/floating_point_log.stderr | 144 ++--- tests/ui/floating_point_logbase.fixed | 5 + tests/ui/floating_point_logbase.rs | 5 + tests/ui/floating_point_logbase.stderr | 8 +- tests/ui/floating_point_mul_add.fixed | 13 + tests/ui/floating_point_mul_add.rs | 13 + tests/ui/floating_point_mul_add.stderr | 24 +- tests/ui/floating_point_powf.fixed | 32 ++ tests/ui/floating_point_powf.rs | 32 ++ tests/ui/floating_point_powf.stderr | 62 +- tests/ui/floating_point_powi.fixed | 14 + tests/ui/floating_point_powi.rs | 14 + tests/ui/floating_point_powi.stderr | 26 +- tests/ui/floating_point_rad.fixed | 8 + tests/ui/floating_point_rad.rs | 8 + tests/ui/floating_point_rad.stderr | 14 +- tests/ui/fn_to_numeric_cast.32bit.stderr | 46 +- tests/ui/fn_to_numeric_cast.64bit.stderr | 46 +- tests/ui/fn_to_numeric_cast.rs | 32 +- tests/ui/fn_to_numeric_cast_any.rs | 45 +- tests/ui/fn_to_numeric_cast_any.stderr | 30 +- tests/ui/for_kv_map.fixed | 19 +- tests/ui/for_kv_map.rs | 19 +- tests/ui/for_kv_map.stderr | 8 +- tests/ui/forget_non_drop.rs | 5 +- tests/ui/format.fixed | 14 + tests/ui/format.rs | 15 + tests/ui/format.stderr | 29 +- tests/ui/format_args.fixed | 30 +- tests/ui/format_args.rs | 30 +- tests/ui/format_args.stderr | 54 +- tests/ui/format_args_unfixable.rs | 79 ++- tests/ui/format_args_unfixable.stderr | 48 +- tests/ui/format_collect.rs | 7 +- tests/ui/format_collect.stderr | 6 +- tests/ui/format_push_string.rs | 13 +- tests/ui/format_push_string.stderr | 10 +- tests/ui/formatting.rs | 30 +- tests/ui/formatting.stderr | 10 +- tests/ui/four_forward_slashes.fixed | 6 +- tests/ui/four_forward_slashes.rs | 6 +- tests/ui/four_forward_slashes.stderr | 21 +- .../ui/four_forward_slashes_first_line.fixed | 1 + tests/ui/four_forward_slashes_first_line.rs | 1 + .../ui/four_forward_slashes_first_line.stderr | 3 +- tests/ui/from_iter_instead_of_collect.fixed | 15 + tests/ui/from_iter_instead_of_collect.rs | 15 + tests/ui/from_iter_instead_of_collect.stderr | 28 +- tests/ui/from_over_into.fixed | 7 + tests/ui/from_over_into.rs | 7 + tests/ui/from_over_into.stderr | 19 +- tests/ui/from_over_into_unfixable.rs | 12 +- tests/ui/from_over_into_unfixable.stderr | 6 +- tests/ui/from_raw_with_void_ptr.rs | 10 +- tests/ui/from_str_radix_10.fixed | 22 +- tests/ui/from_str_radix_10.rs | 22 +- tests/ui/from_str_radix_10.stderr | 12 +- tests/ui/functions.rs | 43 +- tests/ui/functions.stderr | 24 +- tests/ui/functions_maxlines.rs | 4 +- tests/ui/future_not_send.rs | 22 +- tests/ui/future_not_send.stderr | 40 +- tests/ui/get_first.fixed | 14 +- tests/ui/get_first.rs | 14 +- tests/ui/get_first.stderr | 8 +- tests/ui/get_last_with_len.fixed | 6 + tests/ui/get_last_with_len.rs | 6 + tests/ui/get_last_with_len.stderr | 10 +- tests/ui/get_unwrap.fixed | 30 + tests/ui/get_unwrap.rs | 30 + tests/ui/get_unwrap.stderr | 56 +- tests/ui/identity_op.fixed | 180 ++++-- tests/ui/identity_op.rs | 180 ++++-- tests/ui/identity_op.stderr | 124 ++-- tests/ui/if_let_mutex.edition2021.stderr | 8 +- tests/ui/if_let_mutex.rs | 2 + tests/ui/if_not_else.fixed | 10 +- tests/ui/if_not_else.rs | 10 +- tests/ui/if_not_else.stderr | 23 +- tests/ui/if_not_else_bittest.rs | 2 + tests/ui/if_same_then_else.rs | 11 +- tests/ui/if_same_then_else2.rs | 12 +- tests/ui/if_then_some_else_none.fixed | 5 +- tests/ui/if_then_some_else_none.rs | 14 +- tests/ui/if_then_some_else_none.stderr | 22 +- tests/ui/ifs_same_cond.rs | 9 +- tests/ui/impl.rs | 11 +- tests/ui/impl.stderr | 13 +- tests/ui/impl_trait_in_params.rs | 11 +- tests/ui/impl_trait_in_params.stderr | 6 +- tests/ui/implicit_clone.fixed | 11 + tests/ui/implicit_clone.rs | 11 + tests/ui/implicit_clone.stderr | 20 +- tests/ui/implicit_hasher.fixed | 9 + tests/ui/implicit_hasher.rs | 9 + tests/ui/implicit_hasher.stderr | 23 +- tests/ui/implicit_return.fixed | 16 + tests/ui/implicit_return.rs | 16 + tests/ui/implicit_return.stderr | 30 +- tests/ui/implicit_saturating_add.rs | 24 + tests/ui/implicit_saturating_add.stderr | 204 ++++--- tests/ui/implicit_saturating_sub.rs | 24 + tests/ui/implicit_saturating_sub.stderr | 110 ++-- tests/ui/implied_bounds_in_impls.fixed | 23 + tests/ui/implied_bounds_in_impls.rs | 23 + tests/ui/implied_bounds_in_impls.stderr | 44 +- tests/ui/incompatible_msrv.rs | 7 +- tests/ui/incompatible_msrv.stderr | 4 +- tests/ui/inconsistent_digit_grouping.fixed | 10 + tests/ui/inconsistent_digit_grouping.rs | 10 + tests/ui/inconsistent_digit_grouping.stderr | 10 +- .../ui/inconsistent_struct_constructor.fixed | 2 + tests/ui/inconsistent_struct_constructor.rs | 2 + .../ui/inconsistent_struct_constructor.stderr | 2 +- .../if_let_slice_binding.fixed | 29 +- .../if_let_slice_binding.rs | 29 +- .../if_let_slice_binding.stderr | 28 +- tests/ui/indexing_slicing_index.rs | 6 + tests/ui/indexing_slicing_index.stderr | 26 +- tests/ui/indexing_slicing_slice.rs | 36 +- tests/ui/indexing_slicing_slice.stderr | 22 +- tests/ui/ineffective_open_options.fixed | 6 +- tests/ui/ineffective_open_options.rs | 6 +- tests/ui/ineffective_open_options.stderr | 2 +- tests/ui/inefficient_to_string.fixed | 6 + tests/ui/inefficient_to_string.rs | 6 + tests/ui/inefficient_to_string.stderr | 10 +- tests/ui/infallible_destructuring_match.rs | 4 + .../ui/infallible_destructuring_match.stderr | 10 +- tests/ui/infinite_iter.rs | 39 +- tests/ui/infinite_iter.stderr | 28 +- tests/ui/infinite_loop.rs | 44 +- tests/ui/infinite_loops.rs | 39 +- tests/ui/infinite_loops.stderr | 37 +- tests/ui/inherent_to_string.rs | 6 +- tests/ui/inherent_to_string.stderr | 4 +- tests/ui/init_numbered_fields.fixed | 1 + tests/ui/init_numbered_fields.rs | 3 + tests/ui/init_numbered_fields.stderr | 6 +- tests/ui/inline_fn_without_body.fixed | 3 + tests/ui/inline_fn_without_body.rs | 3 + tests/ui/inline_fn_without_body.stderr | 10 +- tests/ui/inspect_for_each.rs | 3 +- tests/ui/inspect_for_each.stderr | 1 + tests/ui/int_plus_one.fixed | 4 + tests/ui/int_plus_one.rs | 4 + tests/ui/int_plus_one.stderr | 6 +- tests/ui/integer_division.rs | 9 +- tests/ui/integer_division.stderr | 4 +- tests/ui/integer_division_remainder_used.rs | 9 + .../ui/integer_division_remainder_used.stderr | 16 +- tests/ui/into_iter_on_ref.fixed | 78 ++- tests/ui/into_iter_on_ref.rs | 78 ++- tests/ui/into_iter_on_ref.stderr | 50 +- tests/ui/into_iter_without_iter.rs | 11 +- tests/ui/into_iter_without_iter.stderr | 2 +- tests/ui/invalid_null_ptr_usage.fixed | 22 + tests/ui/invalid_null_ptr_usage.rs | 22 + tests/ui/invalid_null_ptr_usage.stderr | 42 +- tests/ui/invalid_null_ptr_usage_no_std.fixed | 22 + tests/ui/invalid_null_ptr_usage_no_std.rs | 22 + tests/ui/invalid_null_ptr_usage_no_std.stderr | 42 +- tests/ui/invalid_upcast_comparisons.rs | 78 ++- tests/ui/invalid_upcast_comparisons.stderr | 50 +- tests/ui/io_other_error.fixed | 55 ++ tests/ui/io_other_error.rs | 55 ++ tests/ui/io_other_error.stderr | 52 ++ tests/ui/is_digit_ascii_radix.fixed | 3 + tests/ui/is_digit_ascii_radix.rs | 3 + tests/ui/is_digit_ascii_radix.stderr | 4 +- tests/ui/issue-111399.rs | 2 + tests/ui/issue-7447.rs | 6 +- tests/ui/issue_2356.fixed | 1 + tests/ui/issue_2356.rs | 1 + tests/ui/issue_4266.rs | 10 +- tests/ui/issue_4266.stderr | 2 +- tests/ui/items_after_statement.rs | 8 +- tests/ui/items_after_statement.stderr | 4 +- .../after_proc_macros.rs | 1 + .../imported_module.rs | 1 + .../items_after_test_module/in_submodule.rs | 1 + .../multiple_modules.rs | 2 + .../items_after_test_module/root_module.fixed | 1 + .../ui/items_after_test_module/root_module.rs | 1 + tests/ui/iter_cloned_collect.fixed | 4 + tests/ui/iter_cloned_collect.rs | 5 + tests/ui/iter_cloned_collect.stderr | 9 +- tests/ui/iter_count.fixed | 25 + tests/ui/iter_count.rs | 25 + tests/ui/iter_count.stderr | 48 +- tests/ui/iter_filter_is_ok.fixed | 27 +- tests/ui/iter_filter_is_ok.rs | 27 +- tests/ui/iter_filter_is_ok.stderr | 30 +- tests/ui/iter_filter_is_some.fixed | 23 +- tests/ui/iter_filter_is_some.rs | 23 +- tests/ui/iter_filter_is_some.stderr | 18 +- tests/ui/iter_kv_map.fixed | 54 +- tests/ui/iter_kv_map.rs | 54 +- tests/ui/iter_kv_map.stderr | 142 ++--- tests/ui/iter_next_loop.rs | 1 + tests/ui/iter_next_slice.fixed | 4 + tests/ui/iter_next_slice.rs | 4 + tests/ui/iter_next_slice.stderr | 6 +- tests/ui/iter_not_returning_iterator.rs | 9 +- tests/ui/iter_not_returning_iterator.stderr | 2 +- tests/ui/iter_nth.fixed | 8 + tests/ui/iter_nth.rs | 8 + tests/ui/iter_nth.stderr | 14 +- tests/ui/iter_nth_zero.fixed | 3 + tests/ui/iter_nth_zero.rs | 3 + tests/ui/iter_nth_zero.stderr | 4 +- tests/ui/iter_on_empty_collections.fixed | 7 + tests/ui/iter_on_empty_collections.rs | 7 + tests/ui/iter_on_empty_collections.stderr | 12 +- tests/ui/iter_on_single_items.fixed | 6 + tests/ui/iter_on_single_items.rs | 6 + tests/ui/iter_on_single_items.stderr | 10 +- tests/ui/iter_out_of_bounds.rs | 31 +- tests/ui/iter_out_of_bounds.stderr | 26 +- tests/ui/iter_over_hash_type.rs | 13 + tests/ui/iter_over_hash_type.stderr | 65 ++- tests/ui/iter_overeager_cloned.fixed | 19 + tests/ui/iter_overeager_cloned.rs | 19 + tests/ui/iter_overeager_cloned.stderr | 37 +- tests/ui/iter_skip_next.fixed | 7 + tests/ui/iter_skip_next.rs | 7 + tests/ui/iter_skip_next.stderr | 12 +- tests/ui/iter_skip_next_unfixable.rs | 7 +- tests/ui/iter_skip_next_unfixable.stderr | 8 +- tests/ui/iter_skip_zero.fixed | 5 + tests/ui/iter_skip_zero.rs | 5 + tests/ui/iter_skip_zero.stderr | 8 +- tests/ui/iter_with_drain.fixed | 6 + tests/ui/iter_with_drain.rs | 6 + tests/ui/iter_with_drain.stderr | 10 +- tests/ui/iter_without_into_iter.rs | 14 +- tests/ui/iter_without_into_iter.stderr | 8 +- tests/ui/iterator_step_by_zero.rs | 18 +- tests/ui/iterator_step_by_zero.stderr | 10 +- tests/ui/join_absolute_paths.rs | 8 +- tests/ui/large_const_arrays.fixed | 10 + tests/ui/large_const_arrays.rs | 10 + tests/ui/large_const_arrays.stderr | 18 +- tests/ui/large_digit_groups.fixed | 5 + tests/ui/large_digit_groups.rs | 5 + tests/ui/large_digit_groups.stderr | 8 +- tests/ui/large_enum_variant.32bit.stderr | 199 ++++--- tests/ui/large_enum_variant.64bit.stderr | 170 ++++-- tests/ui/large_enum_variant.rs | 101 +++- tests/ui/large_futures.fixed | 19 +- tests/ui/large_futures.rs | 19 +- tests/ui/large_futures.stderr | 14 +- tests/ui/large_stack_frames.rs | 12 +- tests/ui/large_stack_frames.stderr | 6 +- tests/ui/large_types_passed_by_value.rs | 8 + tests/ui/large_types_passed_by_value.stderr | 14 +- tests/ui/legacy_numeric_constants.fixed | 1 + tests/ui/legacy_numeric_constants.rs | 1 + tests/ui/legacy_numeric_constants.stderr | 32 +- .../ui/legacy_numeric_constants_unfixable.rs | 1 + .../legacy_numeric_constants_unfixable.stderr | 18 +- tests/ui/len_without_is_empty.rs | 48 +- tests/ui/len_without_is_empty.stderr | 40 +- tests/ui/len_zero.fixed | 27 + tests/ui/len_zero.rs | 27 + tests/ui/len_zero.stderr | 52 +- tests/ui/len_zero_ranges.fixed | 2 + tests/ui/len_zero_ranges.rs | 2 + tests/ui/len_zero_ranges.stderr | 2 +- tests/ui/let_and_return.edition2021.fixed | 264 +++++++++ tests/ui/let_and_return.edition2021.stderr | 152 +++++ tests/ui/let_and_return.edition2024.fixed | 264 +++++++++ tests/ui/let_and_return.edition2024.stderr | 228 ++++++++ tests/ui/let_and_return.fixed | 10 + tests/ui/let_and_return.rs | 39 +- tests/ui/let_if_seq.rs | 15 +- tests/ui/let_if_seq.stderr | 6 +- tests/ui/let_underscore_future.rs | 7 +- tests/ui/let_underscore_future.stderr | 4 +- tests/ui/let_underscore_must_use.rs | 29 +- tests/ui/let_underscore_must_use.stderr | 22 +- tests/ui/let_underscore_untyped.rs | 5 + tests/ui/let_underscore_untyped.stderr | 16 +- tests/ui/let_unit.fixed | 4 + tests/ui/let_unit.rs | 4 + tests/ui/let_unit.stderr | 14 +- tests/ui/let_with_type_underscore.rs | 5 + tests/ui/let_with_type_underscore.stderr | 16 +- tests/ui/lines_filter_map_ok.fixed | 13 + tests/ui/lines_filter_map_ok.rs | 13 + tests/ui/lines_filter_map_ok.stderr | 20 +- tests/ui/linkedlist.rs | 23 +- tests/ui/linkedlist.stderr | 16 +- .../ui/literal_string_with_formatting_arg.rs | 31 +- .../literal_string_with_formatting_arg.stderr | 40 +- tests/ui/literals.rs | 59 +- tests/ui/literals.stderr | 36 +- tests/ui/lossy_float_literal.fixed | 11 + tests/ui/lossy_float_literal.rs | 11 + tests/ui/lossy_float_literal.stderr | 20 +- tests/ui/macro_use_imports.fixed | 4 + tests/ui/macro_use_imports.rs | 4 + tests/ui/macro_use_imports.stderr | 6 +- tests/ui/macro_use_imports_expect.rs | 1 + tests/ui/manual_arithmetic_check-2.rs | 16 +- tests/ui/manual_arithmetic_check-2.stderr | 20 +- tests/ui/manual_arithmetic_check.fixed | 12 +- tests/ui/manual_arithmetic_check.rs | 10 +- tests/ui/manual_arithmetic_check.stderr | 6 +- tests/ui/manual_assert.edition2018.stderr | 136 ++++- tests/ui/manual_assert.edition2021.stderr | 136 ++++- tests/ui/manual_assert.rs | 10 + tests/ui/manual_async_fn.fixed | 26 + tests/ui/manual_async_fn.rs | 39 ++ tests/ui/manual_async_fn.stderr | 24 +- tests/ui/manual_bits.fixed | 29 + tests/ui/manual_bits.rs | 29 + tests/ui/manual_bits.stderr | 56 +- .../manual_c_str_literals.edition2021.fixed | 14 + .../manual_c_str_literals.edition2021.stderr | 26 +- tests/ui/manual_c_str_literals.rs | 14 + tests/ui/manual_clamp.fixed | 69 ++- tests/ui/manual_clamp.rs | 133 +++-- tests/ui/manual_clamp.stderr | 64 +-- tests/ui/manual_contains.fixed | 98 ++++ tests/ui/manual_contains.rs | 98 ++++ tests/ui/manual_contains.stderr | 77 +++ tests/ui/manual_div_ceil.fixed | 26 +- tests/ui/manual_div_ceil.rs | 26 +- tests/ui/manual_div_ceil.stderr | 30 +- tests/ui/manual_div_ceil_with_feature.fixed | 23 + tests/ui/manual_div_ceil_with_feature.rs | 23 + tests/ui/manual_div_ceil_with_feature.stderr | 44 +- tests/ui/manual_filter.rs | 15 + tests/ui/manual_filter.stderr | 55 +- tests/ui/manual_filter_map.fixed | 14 + tests/ui/manual_filter_map.rs | 29 + tests/ui/manual_filter_map.stderr | 87 +-- tests/ui/manual_find.rs | 8 +- tests/ui/manual_find_fixable.rs | 12 + tests/ui/manual_find_fixable.stderr | 34 +- tests/ui/manual_find_map.fixed | 17 + tests/ui/manual_find_map.rs | 30 + tests/ui/manual_find_map.stderr | 87 +-- tests/ui/manual_flatten.rs | 27 +- tests/ui/manual_flatten.stderr | 65 +-- tests/ui/manual_float_methods.rs | 7 + tests/ui/manual_float_methods.stderr | 12 +- tests/ui/manual_hash_one.fixed | 4 + tests/ui/manual_hash_one.rs | 4 + tests/ui/manual_hash_one.stderr | 6 +- tests/ui/manual_ignore_case_cmp.fixed | 49 ++ tests/ui/manual_ignore_case_cmp.rs | 49 ++ tests/ui/manual_ignore_case_cmp.stderr | 532 +++++++++--------- tests/ui/manual_inspect.fixed | 13 + tests/ui/manual_inspect.rs | 13 + tests/ui/manual_inspect.stderr | 47 +- tests/ui/manual_instant_elapsed.fixed | 3 + tests/ui/manual_instant_elapsed.rs | 3 + tests/ui/manual_instant_elapsed.stderr | 2 +- tests/ui/manual_is_ascii_check.fixed | 29 + tests/ui/manual_is_ascii_check.rs | 29 + tests/ui/manual_is_ascii_check.stderr | 56 +- tests/ui/manual_is_power_of_two.fixed | 6 + tests/ui/manual_is_power_of_two.rs | 6 + tests/ui/manual_is_power_of_two.stderr | 10 +- tests/ui/manual_is_variant_and.fixed | 5 + tests/ui/manual_is_variant_and.rs | 8 + tests/ui/manual_is_variant_and.stderr | 22 +- tests/ui/manual_let_else.rs | 81 ++- tests/ui/manual_let_else.stderr | 93 +-- tests/ui/manual_let_else_match.rs | 21 +- tests/ui/manual_let_else_match.stderr | 19 +- tests/ui/manual_let_else_question_mark.fixed | 5 + tests/ui/manual_let_else_question_mark.rs | 7 + tests/ui/manual_let_else_question_mark.stderr | 14 +- tests/ui/manual_main_separator_str.fixed | 4 + tests/ui/manual_main_separator_str.rs | 4 + tests/ui/manual_main_separator_str.stderr | 6 +- tests/ui/manual_map_option.fixed | 11 +- tests/ui/manual_map_option.rs | 26 + tests/ui/manual_map_option.stderr | 69 ++- tests/ui/manual_map_option_2.fixed | 91 ++- tests/ui/manual_map_option_2.rs | 104 +++- tests/ui/manual_map_option_2.stderr | 50 +- tests/ui/manual_memcpy/with_loop_counters.rs | 34 +- .../manual_memcpy/with_loop_counters.stderr | 31 +- .../ui/manual_memcpy/without_loop_counters.rs | 55 +- .../without_loop_counters.stderr | 49 +- tests/ui/manual_midpoint.fixed | 74 +++ tests/ui/manual_midpoint.rs | 74 +++ tests/ui/manual_midpoint.stderr | 65 +++ tests/ui/manual_next_back.fixed | 2 + tests/ui/manual_next_back.rs | 2 + tests/ui/manual_next_back.stderr | 2 +- tests/ui/manual_non_exhaustive_enum.rs | 1 + tests/ui/manual_non_exhaustive_enum.stderr | 3 +- tests/ui/manual_ok_err.fixed | 9 + tests/ui/manual_ok_err.rs | 13 + tests/ui/manual_ok_err.stderr | 28 +- tests/ui/manual_ok_or.fixed | 3 + tests/ui/manual_ok_or.rs | 4 + tests/ui/manual_ok_or.stderr | 21 +- tests/ui/manual_option_as_slice.rs | 1 + tests/ui/manual_option_as_slice.stderr | 11 +- tests/ui/manual_pattern_char_comparison.fixed | 10 + tests/ui/manual_pattern_char_comparison.rs | 10 + .../ui/manual_pattern_char_comparison.stderr | 18 +- tests/ui/manual_range_patterns.fixed | 19 + tests/ui/manual_range_patterns.rs | 19 + tests/ui/manual_range_patterns.stderr | 36 +- tests/ui/manual_rem_euclid.fixed | 10 + tests/ui/manual_rem_euclid.rs | 10 + tests/ui/manual_rem_euclid.stderr | 18 +- tests/ui/manual_repeat_n.fixed | 5 + tests/ui/manual_repeat_n.rs | 5 + tests/ui/manual_repeat_n.stderr | 8 +- tests/ui/manual_retain.fixed | 36 ++ tests/ui/manual_retain.rs | 38 ++ tests/ui/manual_retain.stderr | 76 +-- tests/ui/manual_rotate.fixed | 11 + tests/ui/manual_rotate.rs | 11 + tests/ui/manual_rotate.stderr | 20 +- tests/ui/manual_saturating_arithmetic.fixed | 19 + tests/ui/manual_saturating_arithmetic.rs | 24 + tests/ui/manual_saturating_arithmetic.stderr | 51 +- tests/ui/manual_slice_fill.fixed | 26 +- tests/ui/manual_slice_fill.rs | 30 +- tests/ui/manual_slice_fill.stderr | 10 +- tests/ui/manual_slice_size_calculation.fixed | 17 + tests/ui/manual_slice_size_calculation.rs | 17 + tests/ui/manual_slice_size_calculation.stderr | 16 +- tests/ui/manual_split_once.fixed | 19 + tests/ui/manual_split_once.rs | 19 + tests/ui/manual_split_once.stderr | 54 +- tests/ui/manual_str_repeat.fixed | 10 + tests/ui/manual_str_repeat.rs | 10 + tests/ui/manual_str_repeat.stderr | 18 +- tests/ui/manual_string_new.fixed | 9 + tests/ui/manual_string_new.rs | 9 + tests/ui/manual_string_new.stderr | 16 +- tests/ui/manual_strip.rs | 37 +- tests/ui/manual_strip.stderr | 75 ++- tests/ui/manual_strip_fixable.fixed | 15 + tests/ui/manual_strip_fixable.rs | 17 + tests/ui/manual_strip_fixable.stderr | 40 ++ tests/ui/manual_swap_auto_fix.rs | 12 +- tests/ui/manual_swap_auto_fix.stderr | 22 +- tests/ui/manual_try_fold.rs | 4 + tests/ui/manual_try_fold.stderr | 6 +- tests/ui/manual_unwrap_or.rs | 16 + tests/ui/manual_unwrap_or.stderr | 48 +- tests/ui/manual_unwrap_or_default.rs | 17 +- tests/ui/manual_unwrap_or_default.stderr | 9 +- .../ui/manual_unwrap_or_default_unfixable.rs | 4 + .../manual_unwrap_or_default_unfixable.stderr | 7 +- tests/ui/manual_while_let_some.fixed | 7 + tests/ui/manual_while_let_some.rs | 7 + tests/ui/manual_while_let_some.stderr | 12 +- tests/ui/many_single_char_names.rs | 12 +- tests/ui/map_all_any_identity.fixed | 1 + tests/ui/map_all_any_identity.rs | 1 + tests/ui/map_all_any_identity.stderr | 2 +- tests/ui/map_clone.fixed | 37 +- tests/ui/map_clone.rs | 37 +- tests/ui/map_clone.stderr | 28 +- tests/ui/map_collect_result_unit.fixed | 2 + tests/ui/map_collect_result_unit.rs | 2 + tests/ui/map_collect_result_unit.stderr | 2 +- tests/ui/map_err.rs | 2 +- tests/ui/map_flatten.rs | 16 +- tests/ui/map_flatten.stderr | 23 +- tests/ui/map_flatten_fixable.fixed | 9 + tests/ui/map_flatten_fixable.rs | 9 + tests/ui/map_flatten_fixable.stderr | 20 +- tests/ui/map_identity.fixed | 11 + tests/ui/map_identity.rs | 13 + tests/ui/map_identity.stderr | 26 +- tests/ui/map_unit_fn.rs | 2 + tests/ui/map_unwrap_or.rs | 15 + tests/ui/map_unwrap_or.stderr | 40 +- tests/ui/map_unwrap_or_fixable.rs | 2 + tests/ui/map_unwrap_or_fixable.stderr | 6 +- ...map_with_unused_argument_over_ranges.fixed | 18 + .../map_with_unused_argument_over_ranges.rs | 18 + ...ap_with_unused_argument_over_ranges.stderr | 36 +- ...th_unused_argument_over_ranges_nostd.fixed | 1 + ..._with_unused_argument_over_ranges_nostd.rs | 1 + tests/ui/match_as_ref.rs | 3 + tests/ui/match_as_ref.stderr | 7 +- tests/ui/match_bool.fixed | 6 + tests/ui/match_bool.rs | 34 +- tests/ui/match_bool.stderr | 21 +- tests/ui/match_expr_like_matches_macro.fixed | 14 + tests/ui/match_expr_like_matches_macro.rs | 14 + tests/ui/match_expr_like_matches_macro.stderr | 26 +- tests/ui/match_on_vec_items.rs | 17 +- tests/ui/match_on_vec_items.stderr | 14 +- tests/ui/match_overlapping_arm.rs | 16 +- tests/ui/match_ref_pats.fixed | 5 + tests/ui/match_ref_pats.rs | 5 + tests/ui/match_ref_pats.stderr | 14 +- tests/ui/match_result_ok.fixed | 3 + tests/ui/match_result_ok.rs | 3 + tests/ui/match_result_ok.stderr | 4 +- tests/ui/match_same_arms.rs | 22 +- tests/ui/match_same_arms.stderr | 25 +- tests/ui/match_same_arms2.fixed | 37 +- tests/ui/match_same_arms2.rs | 37 +- tests/ui/match_same_arms2.stderr | 31 +- tests/ui/match_same_arms_non_exhaustive.fixed | 4 +- tests/ui/match_same_arms_non_exhaustive.rs | 4 +- tests/ui/match_single_binding.rs | 24 + tests/ui/match_single_binding.stderr | 72 ++- tests/ui/match_single_binding2.fixed | 1 + tests/ui/match_single_binding2.rs | 4 + tests/ui/match_single_binding2.stderr | 11 +- tests/ui/match_str_case_mismatch.fixed | 7 + tests/ui/match_str_case_mismatch.rs | 7 + tests/ui/match_str_case_mismatch.stderr | 12 +- tests/ui/match_wild_err_arm.rs | 13 +- tests/ui/match_wild_err_arm.stderr | 6 +- .../match_wildcard_for_single_variants.fixed | 10 + .../ui/match_wildcard_for_single_variants.rs | 10 + .../match_wildcard_for_single_variants.stderr | 18 +- tests/ui/mem_forget.rs | 12 +- tests/ui/mem_forget.stderr | 6 +- tests/ui/mem_replace.fixed | 50 ++ tests/ui/mem_replace.rs | 50 ++ tests/ui/mem_replace.stderr | 81 ++- tests/ui/mem_replace_macro.rs | 1 + tests/ui/mem_replace_no_std.fixed | 7 + tests/ui/mem_replace_no_std.rs | 7 + tests/ui/mem_replace_no_std.stderr | 12 +- tests/ui/methods.rs | 3 + tests/ui/methods.stderr | 6 +- tests/ui/methods_fixable.fixed | 1 + tests/ui/methods_fixable.rs | 1 + tests/ui/methods_unfixable.rs | 2 +- tests/ui/min_ident_chars.rs | 32 ++ tests/ui/min_ident_chars.stderr | 62 +- tests/ui/min_max.rs | 35 +- tests/ui/min_max.stderr | 22 +- tests/ui/min_rust_version_attr.rs | 12 +- tests/ui/mismatching_type_param_order.rs | 20 +- tests/ui/misnamed_getters.fixed | 55 +- tests/ui/misnamed_getters.rs | 55 +- tests/ui/misnamed_getters.stderr | 121 ++-- tests/ui/missing_asserts_for_indexing.fixed | 28 +- tests/ui/missing_asserts_for_indexing.rs | 28 +- tests/ui/missing_asserts_for_indexing.stderr | 46 +- .../missing_asserts_for_indexing_unfixable.rs | 15 +- ...sing_asserts_for_indexing_unfixable.stderr | 43 +- .../ui/missing_const_for_fn/cant_be_const.rs | 1 + .../missing_const_for_fn/could_be_const.fixed | 47 +- .../ui/missing_const_for_fn/could_be_const.rs | 47 +- .../could_be_const.stderr | 50 +- tests/ui/missing_const_for_thread_local.fixed | 14 +- tests/ui/missing_const_for_thread_local.rs | 14 +- .../ui/missing_const_for_thread_local.stderr | 4 +- tests/ui/missing_doc.rs | 14 + tests/ui/missing_doc.stderr | 32 +- tests/ui/missing_doc_crate.rs | 2 + tests/ui/missing_doc_crate_missing.rs | 3 +- tests/ui/missing_doc_impl.rs | 7 + tests/ui/missing_doc_impl.stderr | 17 +- tests/ui/missing_fields_in_debug.rs | 9 +- tests/ui/missing_fields_in_debug.stderr | 20 +- tests/ui/missing_inline.rs | 17 +- tests/ui/missing_inline.stderr | 8 +- tests/ui/missing_inline_executable.rs | 2 + tests/ui/missing_inline_proc_macro.rs | 2 + tests/ui/missing_panics_doc.rs | 12 + tests/ui/missing_panics_doc.stderr | 46 +- tests/ui/missing_spin_loop.fixed | 6 + tests/ui/missing_spin_loop.rs | 6 + tests/ui/missing_spin_loop.stderr | 10 +- tests/ui/missing_spin_loop_no_std.fixed | 1 + tests/ui/missing_spin_loop_no_std.rs | 1 + tests/ui/missing_trait_methods.rs | 8 +- tests/ui/missing_trait_methods.stderr | 32 +- tests/ui/mistyped_literal_suffix.fixed | 23 + tests/ui/mistyped_literal_suffix.rs | 23 + tests/ui/mistyped_literal_suffix.stderr | 30 +- .../auxiliary/submodule.rs | 1 - .../ui/mixed_attributes_style/global_allow.rs | 3 +- .../mixed_attributes_style/mod_declaration.rs | 2 + .../mod_declaration.stderr | 1 - tests/ui/mixed_read_write_in_expression.rs | 10 +- .../ui/mixed_read_write_in_expression.stderr | 10 +- tests/ui/module_inception.rs | 13 +- tests/ui/module_inception.stderr | 7 +- tests/ui/module_name_repetitions.rs | 17 +- tests/ui/module_name_repetitions.stderr | 8 +- tests/ui/modulo_arithmetic_float.rs | 59 +- tests/ui/modulo_arithmetic_float.stderr | 24 +- tests/ui/modulo_arithmetic_integral.rs | 60 +- tests/ui/modulo_arithmetic_integral.stderr | 28 +- tests/ui/modulo_arithmetic_integral_const.rs | 66 ++- .../modulo_arithmetic_integral_const.stderr | 24 +- tests/ui/modulo_one.rs | 22 +- tests/ui/modulo_one.stderr | 26 +- .../ui/msrv_attributes_without_early_lints.rs | 14 + tests/ui/multi_assignments.rs | 17 +- tests/ui/multi_assignments.stderr | 6 +- tests/ui/multiple_bound_locations.rs | 12 +- tests/ui/multiple_unsafe_ops_per_block.rs | 8 + tests/ui/multiple_unsafe_ops_per_block.stderr | 64 ++- tests/ui/must_use_candidates.fixed | 5 + tests/ui/must_use_candidates.rs | 5 + tests/ui/must_use_candidates.stderr | 8 +- tests/ui/must_use_unit.fixed | 4 +- tests/ui/must_use_unit.rs | 4 +- tests/ui/must_use_unit.stderr | 4 +- ...it_12320.rs => must_use_unit_unfixable.rs} | 8 +- ....stderr => must_use_unit_unfixable.stderr} | 12 +- tests/ui/mut_from_ref.rs | 17 +- tests/ui/mut_from_ref.stderr | 20 +- tests/ui/mut_key.rs | 43 +- tests/ui/mut_key.stderr | 24 +- tests/ui/mut_mut.rs | 9 + tests/ui/mut_mut.stderr | 16 +- tests/ui/mut_mutex_lock.fixed | 2 + tests/ui/mut_mutex_lock.rs | 2 + tests/ui/mut_mutex_lock.stderr | 2 +- tests/ui/mut_range_bound.rs | 25 +- tests/ui/mut_range_bound.stderr | 12 +- tests/ui/mut_reference.rs | 8 +- tests/ui/mutex_atomic.rs | 34 +- tests/ui/mutex_atomic.stderr | 18 +- tests/ui/needless_arbitrary_self_type.fixed | 8 + tests/ui/needless_arbitrary_self_type.rs | 8 + tests/ui/needless_arbitrary_self_type.stderr | 14 +- ...edless_arbitrary_self_type_unfixable.fixed | 1 + .../needless_arbitrary_self_type_unfixable.rs | 1 + tests/ui/needless_as_bytes.fixed | 4 + tests/ui/needless_as_bytes.rs | 4 + tests/ui/needless_as_bytes.stderr | 14 +- tests/ui/needless_bitwise_bool.fixed | 1 + tests/ui/needless_bitwise_bool.rs | 1 + tests/ui/needless_bool/fixable.fixed | 24 + tests/ui/needless_bool/fixable.rs | 24 + tests/ui/needless_bool/fixable.stderr | 46 +- tests/ui/needless_bool/simple.rs | 4 + tests/ui/needless_bool/simple.stderr | 6 +- tests/ui/needless_bool_assign.fixed | 4 + tests/ui/needless_bool_assign.rs | 4 + tests/ui/needless_bool_assign.stderr | 8 +- tests/ui/needless_borrow.fixed | 32 +- tests/ui/needless_borrow.rs | 32 +- tests/ui/needless_borrow.stderr | 54 +- tests/ui/needless_borrow_pat.fixed | 32 +- tests/ui/needless_borrow_pat.rs | 32 +- tests/ui/needless_borrow_pat.stderr | 22 +- tests/ui/needless_borrowed_ref.fixed | 17 + tests/ui/needless_borrowed_ref.rs | 17 + tests/ui/needless_borrowed_ref.stderr | 34 +- .../needless_borrows_for_generic_args.fixed | 13 + tests/ui/needless_borrows_for_generic_args.rs | 13 + .../needless_borrows_for_generic_args.stderr | 20 +- tests/ui/needless_character_iteration.fixed | 18 +- tests/ui/needless_character_iteration.rs | 24 +- tests/ui/needless_character_iteration.stderr | 18 +- tests/ui/needless_collect.fixed | 27 +- tests/ui/needless_collect.rs | 27 +- tests/ui/needless_collect.stderr | 38 +- tests/ui/needless_collect_indirect.rs | 49 +- tests/ui/needless_collect_indirect.stderr | 87 +-- tests/ui/needless_continue.rs | 31 +- tests/ui/needless_continue.stderr | 42 +- tests/ui/needless_doc_main.rs | 1 - tests/ui/needless_doc_main.stderr | 7 +- tests/ui/needless_else.fixed | 1 + tests/ui/needless_else.rs | 1 + tests/ui/needless_for_each_fixable.fixed | 8 + tests/ui/needless_for_each_fixable.rs | 8 + tests/ui/needless_for_each_fixable.stderr | 30 +- tests/ui/needless_for_each_unfixable.rs | 4 +- tests/ui/needless_for_each_unfixable.stderr | 2 +- tests/ui/needless_if.fixed | 7 + tests/ui/needless_if.rs | 7 + tests/ui/needless_if.stderr | 16 +- tests/ui/needless_late_init.fixed | 16 + tests/ui/needless_late_init.rs | 16 + tests/ui/needless_late_init.stderr | 87 +-- tests/ui/needless_lifetimes.fixed | 231 ++------ tests/ui/needless_lifetimes.rs | 231 ++------ tests/ui/needless_lifetimes.stderr | 264 ++------- tests/ui/needless_match.fixed | 3 + tests/ui/needless_match.rs | 14 + tests/ui/needless_match.stderr | 42 +- tests/ui/needless_maybe_sized.fixed | 20 + tests/ui/needless_maybe_sized.rs | 20 + tests/ui/needless_maybe_sized.stderr | 76 +-- tests/ui/needless_option_as_deref.fixed | 16 + tests/ui/needless_option_as_deref.rs | 16 + tests/ui/needless_option_as_deref.stderr | 4 +- tests/ui/needless_option_take.fixed | 19 +- tests/ui/needless_option_take.rs | 19 +- tests/ui/needless_option_take.stderr | 14 +- .../needless_parens_on_range_literals.fixed | 6 + tests/ui/needless_parens_on_range_literals.rs | 6 + .../needless_parens_on_range_literals.stderr | 8 +- tests/ui/needless_pass_by_ref_mut.rs | 76 ++- tests/ui/needless_pass_by_ref_mut.stderr | 66 +-- tests/ui/needless_pass_by_ref_mut2.fixed | 6 +- tests/ui/needless_pass_by_ref_mut2.rs | 6 +- tests/ui/needless_pass_by_ref_mut2.stderr | 2 +- tests/ui/needless_pass_by_value.rs | 53 +- tests/ui/needless_pass_by_value.stderr | 46 +- tests/ui/needless_pass_by_value_proc_macro.rs | 2 + tests/ui/needless_pub_self.fixed | 3 + tests/ui/needless_pub_self.rs | 3 + tests/ui/needless_pub_self.stderr | 4 +- tests/ui/needless_question_mark.fixed | 15 + tests/ui/needless_question_mark.rs | 15 + tests/ui/needless_question_mark.stderr | 28 +- tests/ui/needless_range_loop.rs | 43 +- tests/ui/needless_range_loop.stderr | 24 +- tests/ui/needless_range_loop2.rs | 25 +- tests/ui/needless_range_loop2.stderr | 12 +- tests/ui/needless_raw_string.fixed | 10 + tests/ui/needless_raw_string.rs | 10 + tests/ui/needless_raw_string.stderr | 23 +- tests/ui/needless_raw_string_hashes.fixed | 18 + tests/ui/needless_raw_string_hashes.rs | 18 + tests/ui/needless_raw_string_hashes.stderr | 39 +- tests/ui/needless_return.fixed | 54 ++ tests/ui/needless_return.rs | 55 +- tests/ui/needless_return.stderr | 124 ++-- .../needless_return_with_question_mark.fixed | 1 + .../ui/needless_return_with_question_mark.rs | 1 + .../needless_return_with_question_mark.stderr | 2 +- tests/ui/needless_splitn.fixed | 13 + tests/ui/needless_splitn.rs | 13 + tests/ui/needless_splitn.stderr | 24 +- tests/ui/needless_update.rs | 3 +- tests/ui/neg_cmp_op_on_partial_ord.rs | 9 +- tests/ui/neg_cmp_op_on_partial_ord.stderr | 6 +- tests/ui/neg_multiply.fixed | 8 + tests/ui/neg_multiply.rs | 8 + tests/ui/neg_multiply.stderr | 14 +- tests/ui/never_loop.rs | 49 +- tests/ui/never_loop.stderr | 61 +- tests/ui/new_ret_no_self.rs | 34 +- tests/ui/new_ret_no_self.stderr | 56 +- tests/ui/new_ret_no_self_overflow.rs | 1 + tests/ui/new_without_default.fixed | 24 +- tests/ui/new_without_default.rs | 24 +- tests/ui/new_without_default.stderr | 22 +- tests/ui/no_effect.rs | 82 ++- tests/ui/no_effect.stderr | 52 +- tests/ui/no_effect_async_fn.rs | 8 +- tests/ui/no_effect_replace.rs | 23 +- tests/ui/no_effect_replace.stderr | 12 +- tests/ui/no_effect_return.rs | 20 +- tests/ui/no_effect_return.stderr | 6 +- tests/ui/no_mangle_with_rust_abi.rs | 12 +- tests/ui/no_mangle_with_rust_abi.stderr | 10 +- tests/ui/no_mangle_with_rust_abi_2021.rs | 11 +- tests/ui/no_mangle_with_rust_abi_2021.stderr | 8 +- tests/ui/non_canonical_clone_impl.rs | 4 + tests/ui/non_canonical_clone_impl.stderr | 10 +- tests/ui/non_canonical_partial_ord_impl.fixed | 2 + tests/ui/non_canonical_partial_ord_impl.rs | 2 + .../ui/non_canonical_partial_ord_impl.stderr | 4 +- ...n_canonical_partial_ord_impl_fully_qual.rs | 2 + ...nonical_partial_ord_impl_fully_qual.stderr | 4 +- tests/ui/non_expressive_names.rs | 18 +- tests/ui/non_expressive_names.stderr | 10 +- tests/ui/non_minimal_cfg.fixed | 4 + tests/ui/non_minimal_cfg.rs | 4 + tests/ui/non_minimal_cfg.stderr | 6 +- tests/ui/non_minimal_cfg2.rs | 1 + tests/ui/non_minimal_cfg2.stderr | 2 +- tests/ui/non_octal_unix_permissions.fixed | 4 + tests/ui/non_octal_unix_permissions.rs | 4 + tests/ui/non_octal_unix_permissions.stderr | 6 +- .../non_std_lazy_static_no_std.rs | 1 + .../non_std_lazy_static_other_once_cell.rs | 1 + tests/ui/non_zero_suggestions.fixed | 12 +- tests/ui/non_zero_suggestions.rs | 12 +- tests/ui/non_zero_suggestions_unfixable.rs | 7 +- .../ui/non_zero_suggestions_unfixable.stderr | 2 +- tests/ui/nonminimal_bool.rs | 81 ++- tests/ui/nonminimal_bool.stderr | 62 +- tests/ui/nonminimal_bool_methods.fixed | 93 ++- tests/ui/nonminimal_bool_methods.rs | 93 ++- tests/ui/nonminimal_bool_methods.stderr | 80 +-- tests/ui/nonminimal_bool_methods_unfixable.rs | 4 +- tests/ui/obfuscated_if_else.fixed | 61 +- tests/ui/obfuscated_if_else.rs | 61 +- tests/ui/obfuscated_if_else.stderr | 92 ++- tests/ui/octal_escapes.rs | 23 +- tests/ui/octal_escapes.stderr | 20 +- tests/ui/ok_expect.rs | 14 +- tests/ui/ok_expect.stderr | 8 +- tests/ui/only_used_in_recursion.rs | 44 +- tests/ui/only_used_in_recursion.stderr | 62 +- tests/ui/only_used_in_recursion2.rs | 15 +- tests/ui/only_used_in_recursion2.stderr | 18 +- tests/ui/op_ref.fixed | 11 +- tests/ui/op_ref.rs | 11 +- tests/ui/op_ref.stderr | 4 +- tests/ui/open_options.rs | 21 +- tests/ui/open_options.stderr | 10 +- tests/ui/open_options_fixable.fixed | 2 +- tests/ui/open_options_fixable.rs | 2 +- tests/ui/option_as_ref_cloned.fixed | 3 + tests/ui/option_as_ref_cloned.rs | 3 + tests/ui/option_as_ref_cloned.stderr | 4 +- tests/ui/option_as_ref_deref.fixed | 17 + tests/ui/option_as_ref_deref.rs | 18 + tests/ui/option_as_ref_deref.stderr | 35 +- tests/ui/option_env_unwrap.rs | 8 + tests/ui/option_env_unwrap.stderr | 12 +- tests/ui/option_filter_map.fixed | 17 +- tests/ui/option_filter_map.rs | 21 +- tests/ui/option_filter_map.stderr | 14 +- tests/ui/option_if_let_else.fixed | 14 + tests/ui/option_if_let_else.rs | 26 + tests/ui/option_if_let_else.stderr | 98 ++-- tests/ui/option_map_or_err_ok.fixed | 7 - tests/ui/option_map_or_err_ok.rs | 7 - tests/ui/option_map_or_err_ok.stderr | 11 - tests/ui/option_map_or_none.fixed | 4 + tests/ui/option_map_or_none.rs | 5 + tests/ui/option_map_or_none.stderr | 11 +- tests/ui/option_map_unit_fn_fixable.fixed | 19 + tests/ui/option_map_unit_fn_fixable.rs | 19 + tests/ui/option_map_unit_fn_fixable.stderr | 36 +- tests/ui/option_map_unit_fn_unfixable.rs | 4 + tests/ui/option_map_unit_fn_unfixable.stderr | 6 +- tests/ui/or_fun_call.fixed | 52 +- tests/ui/or_fun_call.rs | 52 +- tests/ui/or_fun_call.stderr | 76 +-- tests/ui/or_then_unwrap.fixed | 6 + tests/ui/or_then_unwrap.rs | 6 + tests/ui/or_then_unwrap.stderr | 4 +- tests/ui/out_of_bounds_indexing/issue-3102.rs | 6 +- tests/ui/out_of_bounds_indexing/simple.rs | 18 +- tests/ui/out_of_bounds_indexing/simple.stderr | 8 +- tests/ui/overly_complex_bool_expr.fixed | 15 +- tests/ui/overly_complex_bool_expr.rs | 15 +- tests/ui/overly_complex_bool_expr.stderr | 16 +- tests/ui/owned_cow.fixed | 23 + tests/ui/owned_cow.rs | 23 + tests/ui/owned_cow.stderr | 41 ++ tests/ui/panic_in_result_fn.rs | 5 +- tests/ui/panic_in_result_fn.stderr | 3 +- tests/ui/panic_in_result_fn_assertions.rs | 6 +- .../ui/panic_in_result_fn_debug_assertions.rs | 2 + tests/ui/panicking_macros.rs | 51 +- tests/ui/panicking_macros.stderr | 28 +- tests/ui/panicking_overflow_checks.rs | 18 +- tests/ui/panicking_overflow_checks.stderr | 10 +- tests/ui/partial_pub_fields.rs | 8 +- tests/ui/partialeq_ne_impl.rs | 4 +- tests/ui/partialeq_to_none.fixed | 15 + tests/ui/partialeq_to_none.rs | 15 + tests/ui/partialeq_to_none.stderr | 30 +- tests/ui/path_buf_push_overwrite.fixed | 1 + tests/ui/path_buf_push_overwrite.rs | 1 + tests/ui/path_ends_with_ext.fixed | 4 +- tests/ui/path_ends_with_ext.rs | 4 +- tests/ui/pathbuf_init_then_push.rs | 12 +- tests/ui/pathbuf_init_then_push.stderr | 10 +- tests/ui/pattern_type_mismatch/mutability.rs | 4 +- .../pattern_alternatives.rs | 8 +- .../pattern_alternatives.stderr | 4 +- .../pattern_type_mismatch/pattern_structs.rs | 22 +- .../pattern_structs.stderr | 14 +- .../pattern_type_mismatch/pattern_tuples.rs | 27 +- .../pattern_tuples.stderr | 18 +- tests/ui/pattern_type_mismatch/syntax.rs | 18 +- tests/ui/pattern_type_mismatch/syntax.stderr | 12 +- tests/ui/patterns.fixed | 3 + tests/ui/patterns.rs | 3 + tests/ui/patterns.stderr | 4 +- tests/ui/permissions_set_readonly_false.rs | 4 +- tests/ui/pointers_in_nomem_asm_block.rs | 7 +- tests/ui/pointers_in_nomem_asm_block.stderr | 4 +- tests/ui/precedence.fixed | 7 + tests/ui/precedence.rs | 7 + tests/ui/precedence.stderr | 12 +- tests/ui/precedence_bits.fixed | 4 + tests/ui/precedence_bits.rs | 4 + tests/ui/precedence_bits.stderr | 6 +- tests/ui/print.rs | 19 +- tests/ui/print.stderr | 14 +- tests/ui/print_in_format_impl.rs | 22 +- tests/ui/print_in_format_impl.stderr | 10 +- tests/ui/print_literal.fixed | 32 +- tests/ui/print_literal.rs | 32 +- tests/ui/print_literal.stderr | 35 +- tests/ui/print_stderr.rs | 7 +- tests/ui/print_stdout_build_script.rs | 1 + tests/ui/print_with_newline.fixed | 25 +- tests/ui/print_with_newline.rs | 25 +- tests/ui/print_with_newline.stderr | 14 +- tests/ui/println_empty_string.fixed | 4 + tests/ui/println_empty_string.rs | 4 + tests/ui/println_empty_string.stderr | 6 +- tests/ui/ptr_arg.rs | 75 ++- tests/ui/ptr_arg.stderr | 57 +- tests/ui/ptr_as_ptr.fixed | 33 ++ tests/ui/ptr_as_ptr.rs | 33 ++ tests/ui/ptr_as_ptr.stderr | 82 +-- tests/ui/ptr_cast_constness.fixed | 13 + tests/ui/ptr_cast_constness.rs | 13 + tests/ui/ptr_cast_constness.stderr | 24 +- tests/ui/ptr_eq.fixed | 2 + tests/ui/ptr_eq.rs | 2 + tests/ui/ptr_eq.stderr | 2 +- tests/ui/ptr_eq_no_std.fixed | 2 + tests/ui/ptr_eq_no_std.rs | 2 + tests/ui/ptr_eq_no_std.stderr | 2 +- tests/ui/ptr_offset_with_cast.fixed | 2 + tests/ui/ptr_offset_with_cast.rs | 2 + tests/ui/ptr_offset_with_cast.stderr | 2 +- tests/ui/pub_use.rs | 2 +- tests/ui/pub_with_shorthand.fixed | 4 + tests/ui/pub_with_shorthand.rs | 4 + tests/ui/pub_with_shorthand.stderr | 6 +- tests/ui/pub_without_shorthand.fixed | 3 + tests/ui/pub_without_shorthand.rs | 3 + tests/ui/pub_without_shorthand.stderr | 4 +- tests/ui/question_mark.fixed | 2 + tests/ui/question_mark.rs | 22 + tests/ui/question_mark.stderr | 62 +- tests/ui/question_mark_used.rs | 3 +- tests/ui/range.fixed | 19 + tests/ui/range.rs | 4 +- tests/ui/range.stderr | 4 +- tests/ui/range_contains.fixed | 21 + tests/ui/range_contains.rs | 21 + tests/ui/range_contains.stderr | 40 +- tests/ui/range_plus_minus_one.fixed | 9 + tests/ui/range_plus_minus_one.rs | 9 + tests/ui/range_plus_minus_one.stderr | 16 +- tests/ui/rc_buffer.fixed | 8 + tests/ui/rc_buffer.rs | 8 + tests/ui/rc_buffer.stderr | 14 +- tests/ui/rc_buffer_arc.fixed | 8 + tests/ui/rc_buffer_arc.rs | 8 + tests/ui/rc_buffer_arc.stderr | 14 +- tests/ui/rc_buffer_redefined_string.rs | 2 + tests/ui/rc_clone_in_vec_init/arc.rs | 16 +- tests/ui/rc_clone_in_vec_init/arc.stderr | 12 +- tests/ui/rc_clone_in_vec_init/rc.rs | 16 +- tests/ui/rc_clone_in_vec_init/rc.stderr | 12 +- tests/ui/rc_clone_in_vec_init/weak.rs | 31 +- tests/ui/rc_clone_in_vec_init/weak.stderr | 18 +- tests/ui/rc_mutex.rs | 10 +- tests/ui/rc_mutex.stderr | 4 +- tests/ui/read_line_without_trim.fixed | 7 + tests/ui/read_line_without_trim.rs | 7 + tests/ui/read_line_without_trim.stderr | 24 +- tests/ui/read_zero_byte_vec.rs | 1 + tests/ui/read_zero_byte_vec.stderr | 22 +- tests/ui/readonly_write_lock.fixed | 7 +- tests/ui/readonly_write_lock.rs | 7 +- tests/ui/recursive_format_impl.rs | 21 +- tests/ui/recursive_format_impl.stderr | 18 +- tests/ui/redundant_allocation.rs | 69 +-- tests/ui/redundant_allocation.stderr | 38 +- tests/ui/redundant_allocation_fixable.fixed | 12 + tests/ui/redundant_allocation_fixable.rs | 12 + tests/ui/redundant_allocation_fixable.stderr | 22 +- tests/ui/redundant_as_str.fixed | 2 + tests/ui/redundant_as_str.rs | 2 + tests/ui/redundant_as_str.stderr | 2 +- tests/ui/redundant_async_block.fixed | 10 + tests/ui/redundant_async_block.rs | 10 + tests/ui/redundant_async_block.stderr | 26 +- tests/ui/redundant_at_rest_pattern.fixed | 6 + tests/ui/redundant_at_rest_pattern.rs | 6 + tests/ui/redundant_at_rest_pattern.stderr | 10 +- tests/ui/redundant_clone.fixed | 15 + tests/ui/redundant_clone.rs | 15 + tests/ui/redundant_clone.stderr | 56 +- tests/ui/redundant_closure_call_early.rs | 5 +- tests/ui/redundant_closure_call_early.stderr | 2 +- tests/ui/redundant_closure_call_fixable.fixed | 17 + tests/ui/redundant_closure_call_fixable.rs | 17 + .../ui/redundant_closure_call_fixable.stderr | 36 +- tests/ui/redundant_closure_call_late.rs | 8 +- tests/ui/redundant_closure_call_late.stderr | 2 +- tests/ui/redundant_else.fixed | 21 +- tests/ui/redundant_else.rs | 21 +- tests/ui/redundant_else.stderr | 26 +- tests/ui/redundant_field_names.fixed | 10 +- tests/ui/redundant_field_names.rs | 10 +- tests/ui/redundant_field_names.stderr | 16 +- tests/ui/redundant_guards.fixed | 28 + tests/ui/redundant_guards.rs | 28 + tests/ui/redundant_guards.stderr | 58 +- tests/ui/redundant_locals.rs | 14 + tests/ui/redundant_locals.stderr | 108 ++-- ...edundant_pattern_matching_drop_order.fixed | 22 + .../redundant_pattern_matching_drop_order.rs | 22 + ...dundant_pattern_matching_drop_order.stderr | 42 +- ...dundant_pattern_matching_if_let_true.fixed | 7 + .../redundant_pattern_matching_if_let_true.rs | 7 + ...undant_pattern_matching_if_let_true.stderr | 12 +- .../redundant_pattern_matching_ipaddr.fixed | 14 + tests/ui/redundant_pattern_matching_ipaddr.rs | 20 + .../redundant_pattern_matching_ipaddr.stderr | 44 +- .../redundant_pattern_matching_option.fixed | 23 + tests/ui/redundant_pattern_matching_option.rs | 32 ++ .../redundant_pattern_matching_option.stderr | 69 ++- .../ui/redundant_pattern_matching_poll.fixed | 15 + tests/ui/redundant_pattern_matching_poll.rs | 20 + .../ui/redundant_pattern_matching_poll.stderr | 43 +- .../redundant_pattern_matching_result.fixed | 18 + tests/ui/redundant_pattern_matching_result.rs | 28 + .../redundant_pattern_matching_result.stderr | 64 ++- tests/ui/redundant_pub_crate.fixed | 29 + tests/ui/redundant_pub_crate.rs | 29 + tests/ui/redundant_pub_crate.stderr | 30 +- tests/ui/redundant_slicing.fixed | 5 + tests/ui/redundant_slicing.rs | 5 + tests/ui/redundant_slicing.stderr | 4 +- tests/ui/redundant_static_lifetimes.fixed | 18 + tests/ui/redundant_static_lifetimes.rs | 18 + tests/ui/redundant_static_lifetimes.stderr | 34 +- .../ui/redundant_static_lifetimes_multiple.rs | 21 +- ...redundant_static_lifetimes_multiple.stderr | 16 +- tests/ui/redundant_type_annotations.rs | 37 +- tests/ui/redundant_type_annotations.stderr | 30 +- tests/ui/ref_as_ptr.fixed | 44 ++ tests/ui/ref_as_ptr.rs | 44 ++ tests/ui/ref_as_ptr.stderr | 86 +-- tests/ui/ref_binding_to_reference.rs | 20 +- tests/ui/ref_binding_to_reference.stderr | 13 +- tests/ui/ref_option/ref_option.all.fixed | 17 + tests/ui/ref_option/ref_option.all.stderr | 37 +- tests/ui/ref_option/ref_option.private.fixed | 17 + tests/ui/ref_option/ref_option.private.stderr | 24 +- tests/ui/ref_option/ref_option.rs | 17 + .../ref_option/ref_option_traits.all.stderr | 6 +- .../ref_option_traits.private.stderr | 4 +- tests/ui/ref_option/ref_option_traits.rs | 4 + tests/ui/ref_option_ref.rs | 26 +- tests/ui/ref_option_ref.stderr | 16 +- tests/ui/ref_patterns.rs | 6 +- tests/ui/regex.rs | 7 + tests/ui/regex.stderr | 64 +-- tests/ui/renamed_builtin_attr.fixed | 1 + tests/ui/renamed_builtin_attr.rs | 1 + tests/ui/repeat_once.fixed | 6 + tests/ui/repeat_once.rs | 6 + tests/ui/repeat_once.stderr | 10 +- tests/ui/repeat_vec_with_capacity.fixed | 11 +- tests/ui/repeat_vec_with_capacity.rs | 11 +- tests/ui/repeat_vec_with_capacity_nostd.fixed | 1 + tests/ui/repeat_vec_with_capacity_nostd.rs | 1 + tests/ui/repl_uninit.rs | 13 +- tests/ui/repl_uninit.stderr | 4 +- tests/ui/repr_packed_without_abi.rs | 2 + tests/ui/repr_packed_without_abi.stderr | 4 +- tests/ui/reserve_after_initialization.rs | 3 + tests/ui/reserve_after_initialization.stderr | 7 +- tests/ui/rest_pat_in_fully_bound_structs.rs | 6 +- tests/ui/result_filter_map.rs | 8 +- tests/ui/result_large_err.rs | 36 +- tests/ui/result_large_err.stderr | 22 +- tests/ui/result_map_or_into_option.fixed | 8 +- tests/ui/result_map_or_into_option.rs | 8 +- tests/ui/result_map_or_into_option.stderr | 4 +- tests/ui/result_map_unit_fn_fixable.fixed | 18 + tests/ui/result_map_unit_fn_fixable.rs | 18 + tests/ui/result_map_unit_fn_fixable.stderr | 34 +- tests/ui/result_map_unit_fn_unfixable.rs | 20 +- tests/ui/result_map_unit_fn_unfixable.stderr | 11 +- tests/ui/result_unit_error.rs | 14 +- tests/ui/result_unit_error.stderr | 8 +- tests/ui/result_unit_error_no_std.rs | 1 + tests/ui/return_and_then.fixed | 7 + tests/ui/return_and_then.rs | 7 + tests/ui/return_and_then.stderr | 16 +- tests/ui/return_self_not_must_use.rs | 9 +- tests/ui/return_self_not_must_use.stderr | 6 +- tests/ui/reversed_empty_ranges_fixable.fixed | 4 + tests/ui/reversed_empty_ranges_fixable.rs | 4 + tests/ui/reversed_empty_ranges_fixable.stderr | 6 +- .../reversed_empty_ranges_loops_fixable.fixed | 6 + .../ui/reversed_empty_ranges_loops_fixable.rs | 6 + ...reversed_empty_ranges_loops_fixable.stderr | 10 +- .../reversed_empty_ranges_loops_unfixable.rs | 7 +- tests/ui/reversed_empty_ranges_unfixable.rs | 8 +- tests/ui/same_functions_in_if_condition.rs | 12 +- tests/ui/same_item_push.rs | 12 +- tests/ui/same_name_method.rs | 12 +- tests/ui/search_is_some.rs | 8 + tests/ui/search_is_some.stderr | 20 +- tests/ui/search_is_some_fixable_none.fixed | 57 +- tests/ui/search_is_some_fixable_none.rs | 58 +- tests/ui/search_is_some_fixable_none.stderr | 113 ++-- tests/ui/search_is_some_fixable_some.fixed | 47 +- tests/ui/search_is_some_fixable_some.rs | 50 +- tests/ui/search_is_some_fixable_some.stderr | 95 ++-- tests/ui/seek_from_current.fixed | 1 + tests/ui/seek_from_current.rs | 1 + .../ui/seek_to_start_instead_of_rewind.fixed | 3 + tests/ui/seek_to_start_instead_of_rewind.rs | 3 + .../ui/seek_to_start_instead_of_rewind.stderr | 4 +- tests/ui/self_assignment.rs | 32 +- tests/ui/self_assignment.stderr | 18 +- tests/ui/self_named_constructors.rs | 4 +- tests/ui/semicolon_if_nothing_returned.fixed | 5 + tests/ui/semicolon_if_nothing_returned.rs | 5 + tests/ui/semicolon_if_nothing_returned.stderr | 8 +- tests/ui/semicolon_inside_block.fixed | 4 + tests/ui/semicolon_inside_block.rs | 4 + tests/ui/semicolon_inside_block.stderr | 7 +- tests/ui/semicolon_outside_block.fixed | 6 + tests/ui/semicolon_outside_block.rs | 6 + tests/ui/semicolon_outside_block.stderr | 13 +- tests/ui/serde.rs | 3 +- tests/ui/serde.stderr | 4 +- tests/ui/set_contains_or_insert.rs | 14 + tests/ui/set_contains_or_insert.stderr | 40 +- tests/ui/shadow.rs | 26 + tests/ui/shadow.stderr | 216 +++---- tests/ui/short_circuit_statement.fixed | 19 +- tests/ui/short_circuit_statement.rs | 19 +- tests/ui/short_circuit_statement.stderr | 12 +- tests/ui/should_impl_trait/corner_cases.rs | 2 + tests/ui/should_impl_trait/method_list_1.rs | 45 +- .../ui/should_impl_trait/method_list_1.stderr | 43 +- tests/ui/should_impl_trait/method_list_2.rs | 45 +- .../ui/should_impl_trait/method_list_2.stderr | 43 +- tests/ui/should_panic_without_expect.rs | 1 + tests/ui/significant_drop_in_scrutinee.rs | 87 +-- tests/ui/significant_drop_in_scrutinee.stderr | 68 ++- tests/ui/significant_drop_tightening.fixed | 4 + tests/ui/significant_drop_tightening.rs | 4 + tests/ui/significant_drop_tightening.stderr | 15 +- tests/ui/similar_names.rs | 10 +- tests/ui/single_call_fn.rs | 6 + tests/ui/single_call_fn.stderr | 23 +- tests/ui/single_char_add_str.fixed | 21 + tests/ui/single_char_add_str.rs | 21 + tests/ui/single_char_add_str.stderr | 40 +- tests/ui/single_char_lifetime_names.rs | 12 +- tests/ui/single_char_lifetime_names.stderr | 2 +- tests/ui/single_char_pattern.fixed | 37 ++ tests/ui/single_char_pattern.rs | 37 ++ tests/ui/single_char_pattern.stderr | 68 +-- tests/ui/single_component_path_imports.fixed | 2 + tests/ui/single_component_path_imports.rs | 2 + tests/ui/single_component_path_imports.stderr | 2 +- .../ui/single_component_path_imports_macro.rs | 2 + ...gle_component_path_imports_nested_first.rs | 8 +- ...component_path_imports_nested_first.stderr | 4 +- ...ingle_component_path_imports_self_after.rs | 2 + ...ngle_component_path_imports_self_before.rs | 2 + tests/ui/single_element_loop.fixed | 8 + tests/ui/single_element_loop.rs | 8 + tests/ui/single_element_loop.stderr | 23 +- tests/ui/single_match.fixed | 26 + tests/ui/single_match.rs | 26 + tests/ui/single_match.stderr | 50 +- tests/ui/single_match_else.fixed | 10 + tests/ui/single_match_else.rs | 10 + tests/ui/single_match_else.stderr | 18 +- tests/ui/single_option_map.rs | 72 +++ tests/ui/single_option_map.stderr | 40 ++ tests/ui/single_range_in_vec_init.rs | 10 + tests/ui/single_range_in_vec_init.stderr | 18 +- .../size_of_in_element_count/expressions.rs | 8 +- .../ui/size_of_in_element_count/functions.rs | 50 +- .../size_of_in_element_count/functions.stderr | 36 +- tests/ui/size_of_ref.rs | 7 +- tests/ui/size_of_ref.stderr | 4 +- tests/ui/skip_while_next.rs | 2 + tests/ui/skip_while_next.stderr | 3 +- tests/ui/sliced_string_as_bytes.fixed | 3 + tests/ui/sliced_string_as_bytes.rs | 3 + tests/ui/sliced_string_as_bytes.stderr | 4 +- tests/ui/slow_vector_initialization.rs | 40 +- tests/ui/slow_vector_initialization.stderr | 46 +- tests/ui/stable_sort_primitive.fixed | 7 + tests/ui/stable_sort_primitive.rs | 7 + tests/ui/stable_sort_primitive.stderr | 24 +- tests/ui/starts_ends_with.fixed | 16 + tests/ui/starts_ends_with.rs | 16 + tests/ui/starts_ends_with.stderr | 30 +- tests/ui/std_instead_of_core.fixed | 1 + tests/ui/std_instead_of_core.rs | 1 + tests/ui/str_split.fixed | 10 + tests/ui/str_split.rs | 10 + tests/ui/str_split.stderr | 18 +- tests/ui/str_to_string.fixed | 5 +- tests/ui/str_to_string.rs | 5 +- tests/ui/str_to_string.stderr | 2 +- tests/ui/string_add.rs | 4 +- tests/ui/string_add.stderr | 19 +- tests/ui/string_add_assign.fixed | 3 + tests/ui/string_add_assign.rs | 3 + tests/ui/string_add_assign.stderr | 2 +- tests/ui/string_extend.fixed | 4 + tests/ui/string_extend.rs | 4 + tests/ui/string_extend.stderr | 6 +- tests/ui/string_from_utf8_as_bytes.fixed | 1 + tests/ui/string_from_utf8_as_bytes.rs | 1 + tests/ui/string_lit_as_bytes.fixed | 7 + tests/ui/string_lit_as_bytes.rs | 7 + tests/ui/string_lit_as_bytes.stderr | 12 +- tests/ui/string_lit_chars_any.fixed | 5 + tests/ui/string_lit_chars_any.rs | 5 + tests/ui/string_lit_chars_any.stderr | 8 +- tests/ui/string_slice.rs | 12 +- tests/ui/string_slice.stderr | 4 +- tests/ui/string_to_string.rs | 2 +- tests/ui/strlen_on_c_strings.fixed | 7 + tests/ui/strlen_on_c_strings.rs | 7 + tests/ui/strlen_on_c_strings.stderr | 12 +- tests/ui/struct_excessive_bools.rs | 4 +- tests/ui/struct_fields.rs | 2 + tests/ui/struct_fields.stderr | 2 +- tests/ui/suspicious_arithmetic_impl.rs | 20 +- tests/ui/suspicious_arithmetic_impl.stderr | 16 +- tests/ui/suspicious_command_arg_space.fixed | 6 +- tests/ui/suspicious_command_arg_space.rs | 6 +- tests/ui/suspicious_doc_comments.fixed | 9 + tests/ui/suspicious_doc_comments.rs | 9 + tests/ui/suspicious_doc_comments.stderr | 67 ++- tests/ui/suspicious_doc_comments_unfixable.rs | 9 +- .../suspicious_doc_comments_unfixable.stderr | 2 + tests/ui/suspicious_else_formatting.rs | 10 +- tests/ui/suspicious_else_formatting.stderr | 16 +- tests/ui/suspicious_map.rs | 4 +- tests/ui/suspicious_operation_groupings.fixed | 28 +- tests/ui/suspicious_operation_groupings.rs | 28 +- .../ui/suspicious_operation_groupings.stderr | 58 +- tests/ui/suspicious_splitn.rs | 34 +- tests/ui/suspicious_splitn.stderr | 4 +- tests/ui/suspicious_to_owned.rs | 19 +- tests/ui/suspicious_to_owned.stderr | 8 +- tests/ui/suspicious_unary_op_formatting.rs | 12 +- .../ui/suspicious_unary_op_formatting.stderr | 6 +- tests/ui/suspicious_xor_used_as_pow.rs | 21 +- tests/ui/suspicious_xor_used_as_pow.stderr | 12 +- tests/ui/swap.rs | 17 + tests/ui/swap.stderr | 49 +- tests/ui/swap_ptr_to_ref.fixed | 4 + tests/ui/swap_ptr_to_ref.rs | 4 + tests/ui/swap_ptr_to_ref.stderr | 6 +- tests/ui/swap_ptr_to_ref_unfixable.rs | 9 +- tests/ui/swap_ptr_to_ref_unfixable.stderr | 2 +- .../non_expressive_names_error_recovery.fixed | 9 + .../non_expressive_names_error_recovery.rs | 9 + ...non_expressive_names_error_recovery.stderr | 13 + tests/ui/tabs_in_doc_comments.fixed | 8 + tests/ui/tabs_in_doc_comments.rs | 8 + tests/ui/tabs_in_doc_comments.stderr | 12 +- tests/ui/temporary_assignment.rs | 11 +- tests/ui/temporary_assignment.stderr | 2 +- tests/ui/test_attr_in_doctest.rs | 12 +- tests/ui/test_attr_in_doctest.stderr | 5 +- tests/ui/tests_outside_test_module.rs | 1 + tests/ui/tests_outside_test_module.stderr | 2 +- tests/ui/to_digit_is_some.fixed | 2 + tests/ui/to_digit_is_some.rs | 2 + tests/ui/to_digit_is_some.stderr | 2 +- tests/ui/to_string_trait_impl.rs | 1 + tests/ui/to_string_trait_impl.stderr | 1 + .../ui/too_long_first_doc_paragraph-fix.fixed | 2 + tests/ui/too_long_first_doc_paragraph-fix.rs | 1 + .../too_long_first_doc_paragraph-fix.stderr | 3 + tests/ui/too_long_first_doc_paragraph.rs | 10 + tests/ui/too_long_first_doc_paragraph.stderr | 20 +- tests/ui/toplevel_ref_arg.fixed | 6 + tests/ui/toplevel_ref_arg.rs | 6 + tests/ui/toplevel_ref_arg.stderr | 10 +- tests/ui/toplevel_ref_arg_non_rustfix.rs | 2 + tests/ui/toplevel_ref_arg_non_rustfix.stderr | 2 +- tests/ui/track-diagnostics.rs | 1 + tests/ui/trailing_empty_array.rs | 22 +- tests/ui/trailing_zeros.fixed | 7 +- tests/ui/trailing_zeros.rs | 7 +- tests/ui/trait_duplication_in_bounds.fixed | 9 + tests/ui/trait_duplication_in_bounds.rs | 9 + tests/ui/trait_duplication_in_bounds.stderr | 22 +- .../trait_duplication_in_bounds_unfixable.rs | 18 +- ...ait_duplication_in_bounds_unfixable.stderr | 4 +- tests/ui/transmute.rs | 142 +++-- tests/ui/transmute.stderr | 104 ++-- tests/ui/transmute_32bit.rs | 8 +- tests/ui/transmute_64bit.rs | 5 +- tests/ui/transmute_64bit.stderr | 2 +- tests/ui/transmute_collection.rs | 48 +- tests/ui/transmute_collection.stderr | 30 +- tests/ui/transmute_float_to_int.fixed | 37 +- tests/ui/transmute_float_to_int.rs | 37 +- tests/ui/transmute_float_to_int.stderr | 24 +- tests/ui/transmute_int_to_char.fixed | 6 +- tests/ui/transmute_int_to_char.rs | 6 +- tests/ui/transmute_int_to_char_no_std.fixed | 6 +- tests/ui/transmute_int_to_char_no_std.rs | 6 +- tests/ui/transmute_int_to_non_zero.fixed | 29 +- tests/ui/transmute_int_to_non_zero.rs | 29 +- tests/ui/transmute_int_to_non_zero.stderr | 16 +- tests/ui/transmute_null_to_fn.rs | 16 +- tests/ui/transmute_null_to_fn.stderr | 10 +- tests/ui/transmute_ptr_to_ptr.fixed | 14 + tests/ui/transmute_ptr_to_ptr.rs | 14 + tests/ui/transmute_ptr_to_ptr.stderr | 30 +- tests/ui/transmute_ptr_to_ref.fixed | 22 + tests/ui/transmute_ptr_to_ref.rs | 22 + tests/ui/transmute_ptr_to_ref.stderr | 42 +- tests/ui/transmute_ref_to_ref.rs | 8 +- tests/ui/transmute_ref_to_ref.stderr | 4 +- tests/ui/transmute_ref_to_ref_no_std.rs | 8 +- tests/ui/transmute_ref_to_ref_no_std.stderr | 4 +- tests/ui/transmute_undefined_repr.rs | 41 +- tests/ui/transmute_undefined_repr.stderr | 16 +- .../transmutes_expressible_as_ptr_casts.fixed | 10 + .../ui/transmutes_expressible_as_ptr_casts.rs | 10 + ...transmutes_expressible_as_ptr_casts.stderr | 18 +- tests/ui/transmuting_null.rs | 9 +- tests/ui/trim_split_whitespace.fixed | 16 + tests/ui/trim_split_whitespace.rs | 16 + tests/ui/trim_split_whitespace.stderr | 14 +- tests/ui/trivially_copy_pass_by_ref.rs | 1 + tests/ui/trivially_copy_pass_by_ref.stderr | 30 +- tests/ui/try_err.fixed | 11 + tests/ui/try_err.rs | 11 + tests/ui/try_err.stderr | 20 +- tests/ui/tuple_array_conversions.rs | 10 + tests/ui/tuple_array_conversions.stderr | 18 +- tests/ui/ty_fn_sig.rs | 1 + tests/ui/type_complexity.rs | 37 +- tests/ui/type_complexity.stderr | 16 +- tests/ui/type_id_on_box.fixed | 8 +- tests/ui/type_id_on_box.rs | 8 +- tests/ui/type_id_on_box_unfixable.rs | 4 +- tests/ui/unbuffered_bytes.rs | 41 ++ tests/ui/unbuffered_bytes.stderr | 36 ++ tests/ui/unchecked_duration_subtraction.fixed | 4 + tests/ui/unchecked_duration_subtraction.rs | 4 + .../ui/unchecked_duration_subtraction.stderr | 6 +- tests/ui/unconditional_recursion.rs | 51 +- tests/ui/unconditional_recursion.stderr | 138 +++-- tests/ui/unicode.fixed | 8 + tests/ui/unicode.rs | 8 + tests/ui/unicode.stderr | 18 +- tests/ui/uninhabited_references.rs | 4 + tests/ui/uninhabited_references.stderr | 6 +- tests/ui/uninit.rs | 7 +- tests/ui/uninit.stderr | 4 +- tests/ui/uninit_vec.rs | 36 +- tests/ui/uninit_vec.stderr | 31 +- tests/ui/uninlined_format_args.fixed | 79 +++ tests/ui/uninlined_format_args.rs | 79 +++ tests/ui/uninlined_format_args.stderr | 154 ++--- ...nlined_format_args_panic.edition2018.fixed | 6 + ...nlined_format_args_panic.edition2021.fixed | 6 + ...lined_format_args_panic.edition2021.stderr | 10 +- tests/ui/uninlined_format_args_panic.rs | 6 + tests/ui/unit_arg.rs | 10 + tests/ui/unit_arg.stderr | 29 +- tests/ui/unit_arg_empty_blocks.fixed | 4 + tests/ui/unit_arg_empty_blocks.rs | 4 + tests/ui/unit_arg_empty_blocks.stderr | 6 +- tests/ui/unit_cmp.rs | 15 +- tests/ui/unit_cmp.stderr | 9 +- tests/ui/unit_hash.fixed | 9 +- tests/ui/unit_hash.rs | 9 +- tests/ui/unit_hash.stderr | 4 +- tests/ui/unit_return_expecting_ord.rs | 11 +- tests/ui/unit_return_expecting_ord.stderr | 10 +- tests/ui/unknown_clippy_lints.fixed | 9 + tests/ui/unknown_clippy_lints.rs | 9 + tests/ui/unknown_clippy_lints.stderr | 16 +- tests/ui/unnecessary_box_returns.rs | 11 +- tests/ui/unnecessary_box_returns.stderr | 4 +- tests/ui/unnecessary_cast.fixed | 42 ++ tests/ui/unnecessary_cast.rs | 42 ++ tests/ui/unnecessary_cast.stderr | 80 +-- tests/ui/unnecessary_cast_unfixable.rs | 5 +- tests/ui/unnecessary_cast_unfixable.stderr | 2 +- tests/ui/unnecessary_clippy_cfg.rs | 19 +- tests/ui/unnecessary_clippy_cfg.stderr | 16 +- tests/ui/unnecessary_clone.rs | 25 +- tests/ui/unnecessary_clone.stderr | 14 +- .../ui/unnecessary_fallible_conversions.fixed | 20 +- tests/ui/unnecessary_fallible_conversions.rs | 20 +- tests/ui/unnecessary_filter_map.rs | 15 +- tests/ui/unnecessary_filter_map.stderr | 16 +- tests/ui/unnecessary_find_map.rs | 12 +- tests/ui/unnecessary_find_map.stderr | 10 +- tests/ui/unnecessary_first_then_check.fixed | 7 + tests/ui/unnecessary_first_then_check.rs | 7 + tests/ui/unnecessary_first_then_check.stderr | 12 +- tests/ui/unnecessary_fold.fixed | 16 + tests/ui/unnecessary_fold.rs | 16 + tests/ui/unnecessary_fold.stderr | 30 +- tests/ui/unnecessary_get_then_check.fixed | 30 +- tests/ui/unnecessary_get_then_check.rs | 30 +- tests/ui/unnecessary_get_then_check.stderr | 18 +- tests/ui/unnecessary_iter_cloned.fixed | 15 +- tests/ui/unnecessary_iter_cloned.rs | 15 +- tests/ui/unnecessary_iter_cloned.stderr | 12 +- tests/ui/unnecessary_join.rs | 2 + tests/ui/unnecessary_join.stderr | 4 +- tests/ui/unnecessary_lazy_eval.fixed | 86 ++- tests/ui/unnecessary_lazy_eval.rs | 86 ++- tests/ui/unnecessary_lazy_eval.stderr | 124 ++-- tests/ui/unnecessary_lazy_eval_unfixable.rs | 10 +- .../ui/unnecessary_lazy_eval_unfixable.stderr | 4 +- tests/ui/unnecessary_literal_bound.fixed | 3 + tests/ui/unnecessary_literal_bound.rs | 3 + tests/ui/unnecessary_literal_bound.stderr | 4 +- tests/ui/unnecessary_literal_unwrap.fixed | 54 ++ tests/ui/unnecessary_literal_unwrap.rs | 54 ++ tests/ui/unnecessary_literal_unwrap.stderr | 104 ++-- .../unnecessary_literal_unwrap_unfixable.rs | 140 +++-- ...nnecessary_literal_unwrap_unfixable.stderr | 198 +++---- tests/ui/unnecessary_map_on_constructor.fixed | 8 + tests/ui/unnecessary_map_on_constructor.rs | 8 + .../ui/unnecessary_map_on_constructor.stderr | 14 +- tests/ui/unnecessary_map_or.fixed | 31 + tests/ui/unnecessary_map_or.rs | 32 ++ tests/ui/unnecessary_map_or.stderr | 75 ++- tests/ui/unnecessary_min_or_max.fixed | 17 + tests/ui/unnecessary_min_or_max.rs | 17 + tests/ui/unnecessary_min_or_max.stderr | 32 +- tests/ui/unnecessary_operation.fixed | 19 +- tests/ui/unnecessary_operation.rs | 21 +- tests/ui/unnecessary_operation.stderr | 40 +- .../ui/unnecessary_os_str_debug_formatting.rs | 22 + ...unnecessary_os_str_debug_formatting.stderr | 58 ++ .../ui/unnecessary_owned_empty_strings.fixed | 2 + tests/ui/unnecessary_owned_empty_strings.rs | 2 + .../ui/unnecessary_owned_empty_strings.stderr | 2 +- tests/ui/unnecessary_path_debug_formatting.rs | 43 ++ .../unnecessary_path_debug_formatting.stderr | 85 +++ tests/ui/unnecessary_result_map_or_else.fixed | 9 +- tests/ui/unnecessary_result_map_or_else.rs | 11 +- .../ui/unnecessary_result_map_or_else.stderr | 6 +- tests/ui/unnecessary_safety_comment.rs | 21 +- tests/ui/unnecessary_safety_comment.stderr | 50 +- tests/ui/unnecessary_self_imports.fixed | 2 + tests/ui/unnecessary_self_imports.rs | 2 + tests/ui/unnecessary_self_imports.stderr | 2 +- .../unnecessary_semicolon.edition2021.fixed | 6 +- .../unnecessary_semicolon.edition2021.stderr | 2 +- .../unnecessary_semicolon.edition2024.fixed | 6 +- .../unnecessary_semicolon.edition2024.stderr | 2 +- tests/ui/unnecessary_semicolon.rs | 6 +- tests/ui/unnecessary_sort_by.fixed | 12 + tests/ui/unnecessary_sort_by.rs | 12 + tests/ui/unnecessary_sort_by.stderr | 22 +- tests/ui/unnecessary_sort_by_no_std.fixed | 2 + tests/ui/unnecessary_sort_by_no_std.rs | 2 + tests/ui/unnecessary_sort_by_no_std.stderr | 2 +- .../unnecessary_struct_initialization.fixed | 9 + tests/ui/unnecessary_struct_initialization.rs | 11 + .../unnecessary_struct_initialization.stderr | 22 +- tests/ui/unnecessary_to_owned.fixed | 101 +++- tests/ui/unnecessary_to_owned.rs | 101 +++- tests/ui/unnecessary_to_owned.stderr | 187 +++--- tests/ui/unnecessary_to_owned_on_split.fixed | 25 +- tests/ui/unnecessary_to_owned_on_split.rs | 25 +- tests/ui/unnecessary_to_owned_on_split.stderr | 16 +- tests/ui/unnecessary_unsafety_doc.rs | 7 + tests/ui/unnecessary_unsafety_doc.stderr | 12 +- tests/ui/unnecessary_wraps.rs | 22 +- tests/ui/unnecessary_wraps.stderr | 21 +- tests/ui/unneeded_field_pattern.rs | 3 +- tests/ui/unneeded_struct_pattern.fixed | 55 +- tests/ui/unneeded_struct_pattern.rs | 55 +- tests/ui/unneeded_struct_pattern.stderr | 64 +-- tests/ui/unneeded_wildcard_pattern.fixed | 14 + tests/ui/unneeded_wildcard_pattern.rs | 14 + tests/ui/unneeded_wildcard_pattern.stderr | 26 +- tests/ui/unnested_or_patterns.fixed | 17 + tests/ui/unnested_or_patterns.rs | 17 + tests/ui/unnested_or_patterns.stderr | 32 +- tests/ui/unnested_or_patterns2.fixed | 8 + tests/ui/unnested_or_patterns2.rs | 8 + tests/ui/unnested_or_patterns2.stderr | 14 +- tests/ui/unreadable_literal.fixed | 10 + tests/ui/unreadable_literal.rs | 10 + tests/ui/unreadable_literal.stderr | 12 +- tests/ui/unsafe_removed_from_name.rs | 11 +- tests/ui/unsafe_removed_from_name.stderr | 8 +- tests/ui/unseparated_prefix_literals.fixed | 9 + tests/ui/unseparated_prefix_literals.rs | 9 + tests/ui/unseparated_prefix_literals.stderr | 16 +- tests/ui/unused_async.rs | 11 +- tests/ui/unused_async.stderr | 11 +- tests/ui/unused_enumerate_index.fixed | 8 + tests/ui/unused_enumerate_index.rs | 8 + tests/ui/unused_enumerate_index.stderr | 38 +- tests/ui/unused_format_specs.1.fixed | 19 +- tests/ui/unused_format_specs.2.fixed | 19 +- tests/ui/unused_format_specs.rs | 19 +- tests/ui/unused_format_specs.stderr | 6 +- tests/ui/unused_io_amount.rs | 59 +- tests/ui/unused_io_amount.stderr | 32 +- tests/ui/unused_peekable.rs | 19 +- tests/ui/unused_peekable.stderr | 6 +- tests/ui/unused_result_ok.fixed | 4 + tests/ui/unused_result_ok.rs | 4 + tests/ui/unused_result_ok.stderr | 6 +- tests/ui/unused_rounding.fixed | 5 + tests/ui/unused_rounding.rs | 5 + tests/ui/unused_rounding.stderr | 8 +- tests/ui/unused_self.rs | 27 +- tests/ui/unused_self.stderr | 16 +- tests/ui/unused_trait_names.fixed | 10 + tests/ui/unused_trait_names.rs | 10 + tests/ui/unused_trait_names.stderr | 18 +- tests/ui/unused_unit.fixed | 19 + tests/ui/unused_unit.rs | 19 + tests/ui/unused_unit.stderr | 62 +- tests/ui/unwrap.rs | 7 +- tests/ui/unwrap.stderr | 2 +- tests/ui/unwrap_expect_used.rs | 27 +- tests/ui/unwrap_expect_used.stderr | 10 +- tests/ui/unwrap_in_result.rs | 7 +- tests/ui/unwrap_in_result.stderr | 16 +- tests/ui/unwrap_or.fixed | 5 +- tests/ui/unwrap_or.rs | 5 +- tests/ui/unwrap_or.stderr | 2 +- tests/ui/unwrap_or_else_default.fixed | 16 + tests/ui/unwrap_or_else_default.rs | 16 + tests/ui/unwrap_or_else_default.stderr | 56 +- tests/ui/upper_case_acronyms.fixed | 25 +- tests/ui/upper_case_acronyms.rs | 25 +- tests/ui/upper_case_acronyms.stderr | 22 +- tests/ui/use_self.fixed | 88 +++ tests/ui/use_self.rs | 88 +++ tests/ui/use_self.stderr | 84 +-- tests/ui/use_self_trait.fixed | 17 + tests/ui/use_self_trait.rs | 17 + tests/ui/use_self_trait.stderr | 28 +- tests/ui/used_underscore_binding.rs | 6 + tests/ui/used_underscore_binding.stderr | 20 +- tests/ui/used_underscore_items.rs | 19 + tests/ui/used_underscore_items.stderr | 16 +- tests/ui/useful_asref.rs | 2 + tests/ui/useless_asref.fixed | 64 ++- tests/ui/useless_asref.rs | 64 ++- tests/ui/useless_asref.stderr | 36 +- tests/ui/useless_attribute.fixed | 3 + tests/ui/useless_attribute.rs | 3 + tests/ui/useless_attribute.stderr | 4 +- tests/ui/useless_conversion.fixed | 32 ++ tests/ui/useless_conversion.rs | 32 ++ tests/ui/useless_conversion.stderr | 108 ++-- tests/ui/useless_conversion_try.rs | 25 +- tests/ui/useless_conversion_try.stderr | 16 +- tests/ui/useless_nonzero_new_unchecked.fixed | 10 +- tests/ui/useless_nonzero_new_unchecked.rs | 10 +- tests/ui/vec.fixed | 23 +- tests/ui/vec.rs | 23 +- tests/ui/vec.stderr | 60 +- tests/ui/vec_box_sized.rs | 9 + tests/ui/vec_box_sized.stderr | 16 +- tests/ui/vec_init_then_push.rs | 25 +- tests/ui/vec_init_then_push.stderr | 24 +- tests/ui/vec_resize_to_zero.fixed | 2 +- tests/ui/vec_resize_to_zero.rs | 2 +- tests/ui/verbose_file_reads.rs | 6 +- tests/ui/verbose_file_reads.stderr | 2 +- tests/ui/waker_clone_wake.fixed | 2 + tests/ui/waker_clone_wake.rs | 2 + tests/ui/waker_clone_wake.stderr | 2 +- tests/ui/while_float.rs | 2 + tests/ui/while_float.stderr | 2 +- tests/ui/while_let_loop.rs | 16 +- tests/ui/while_let_loop.stderr | 16 +- tests/ui/while_let_on_iterator.fixed | 28 + tests/ui/while_let_on_iterator.rs | 28 + tests/ui/while_let_on_iterator.stderr | 62 +- tests/ui/wild_in_or_pats.rs | 14 +- tests/ui/wild_in_or_pats.stderr | 10 +- tests/ui/wildcard_enum_match_arm.fixed | 6 + tests/ui/wildcard_enum_match_arm.rs | 6 + tests/ui/wildcard_enum_match_arm.stderr | 10 +- tests/ui/wildcard_imports.fixed | 21 + tests/ui/wildcard_imports.rs | 22 + tests/ui/wildcard_imports.stderr | 43 +- .../wildcard_imports_2021.edition2018.fixed | 21 + .../wildcard_imports_2021.edition2018.stderr | 43 +- .../wildcard_imports_2021.edition2021.fixed | 21 + .../wildcard_imports_2021.edition2021.stderr | 43 +- tests/ui/wildcard_imports_2021.rs | 22 + tests/ui/wildcard_imports_cfgtest.rs | 1 + tests/ui/write_literal.fixed | 35 +- tests/ui/write_literal.rs | 35 +- tests/ui/write_literal.stderr | 27 +- tests/ui/write_literal_2.rs | 44 +- tests/ui/write_literal_2.stderr | 32 +- tests/ui/write_with_newline.fixed | 25 +- tests/ui/write_with_newline.rs | 25 +- tests/ui/write_with_newline.stderr | 14 +- tests/ui/writeln_empty_string.fixed | 2 + tests/ui/writeln_empty_string.rs | 2 + tests/ui/writeln_empty_string.stderr | 2 +- tests/ui/wrong_self_convention.rs | 69 ++- tests/ui/wrong_self_convention.stderr | 44 +- tests/ui/wrong_self_convention2.rs | 5 +- tests/ui/wrong_self_convention2.stderr | 2 +- tests/ui/wrong_self_conventions_mut.rs | 6 +- tests/ui/wrong_self_conventions_mut.stderr | 2 +- tests/ui/zero_div_zero.rs | 12 +- tests/ui/zero_div_zero.stderr | 6 +- tests/ui/zero_offset.rs | 23 +- tests/ui/zero_offset.stderr | 12 +- tests/ui/zero_ptr.fixed | 5 + tests/ui/zero_ptr.rs | 5 + tests/ui/zero_ptr.stderr | 8 +- tests/ui/zero_ptr_no_std.fixed | 3 + tests/ui/zero_ptr_no_std.rs | 3 + tests/ui/zero_ptr_no_std.stderr | 4 +- tests/ui/zero_repeat_side_effects.fixed | 9 + tests/ui/zero_repeat_side_effects.rs | 9 + tests/ui/zero_repeat_side_effects.stderr | 16 +- tests/ui/zero_sized_btreemap_values.rs | 29 +- tests/ui/zero_sized_btreemap_values.stderr | 10 +- tests/ui/zero_sized_hashmap_values.rs | 29 +- tests/ui/zero_sized_hashmap_values.stderr | 10 +- tests/ui/zombie_processes.rs | 8 + tests/ui/zombie_processes.stderr | 30 +- tests/ui/zombie_processes_fixable.fixed | 10 +- tests/ui/zombie_processes_fixable.rs | 10 +- tests/ui/zombie_processes_fixable.stderr | 6 +- .../{literal_string_with_formatting_args}.rs | 48 ++ tests/versioncheck.rs | 6 + 2648 files changed, 35461 insertions(+), 16191 deletions(-) create mode 100644 clippy_lints/src/methods/io_other_error.rs create mode 100644 clippy_lints/src/methods/manual_contains.rs delete mode 100644 clippy_lints/src/methods/option_map_or_err_ok.rs create mode 100644 clippy_lints/src/methods/unbuffered_bytes.rs create mode 100644 clippy_lints/src/operators/manual_midpoint.rs create mode 100644 clippy_lints/src/single_option_map.rs create mode 100644 clippy_lints/src/types/owned_cow.rs create mode 100644 tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.rs create mode 100644 tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.stderr create mode 100644 tests/ui-toml/await_holding_invalid_type_with_replacement/clippy.toml create mode 100644 tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.default.stderr create mode 100644 tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.enabled.stderr create mode 100644 tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.rs create mode 100644 tests/ui-toml/check_incompatible_msrv_in_tests/default/clippy.toml create mode 100644 tests/ui-toml/check_incompatible_msrv_in_tests/enabled/clippy.toml create mode 100644 tests/ui-toml/replaceable_disallowed_types/clippy.toml create mode 100644 tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.fixed create mode 100644 tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.rs create mode 100644 tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.stderr create mode 100644 tests/ui-toml/toml_replaceable_disallowed_methods/clippy.toml create mode 100644 tests/ui-toml/toml_replaceable_disallowed_methods/replaceable_disallowed_methods.fixed create mode 100644 tests/ui-toml/toml_replaceable_disallowed_methods/replaceable_disallowed_methods.rs create mode 100644 tests/ui-toml/toml_replaceable_disallowed_methods/replaceable_disallowed_methods.stderr create mode 100644 tests/ui-toml/unwrap_used/unwrap_used_const.rs create mode 100644 tests/ui-toml/unwrap_used/unwrap_used_const.stderr create mode 100644 tests/ui/borrow_interior_mutable_const/projections.rs create mode 100644 tests/ui/borrow_interior_mutable_const/projections.stderr rename tests/ui/crashes/{needless_lifetimes_impl_trait.fixed => elidable_lifetime_names_impl_trait.fixed} (65%) rename tests/ui/crashes/{needless_lifetimes_impl_trait.rs => elidable_lifetime_names_impl_trait.rs} (66%) rename tests/ui/crashes/{needless_lifetimes_impl_trait.stderr => elidable_lifetime_names_impl_trait.stderr} (67%) create mode 100644 tests/ui/crashes/ice-10508a.rs create mode 100644 tests/ui/crashes/ice-10508b.rs create mode 100644 tests/ui/crashes/ice-10508c.rs create mode 100644 tests/ui/crashes/ice-14303.rs create mode 100644 tests/ui/crashes/ice-14325.rs create mode 100644 tests/ui/crashes/ice-5835.1.fixed create mode 100644 tests/ui/crashes/ice-5835.2.fixed create mode 100644 tests/ui/doc/link_adjacent.fixed create mode 100644 tests/ui/doc/link_adjacent.rs create mode 100644 tests/ui/doc/link_adjacent.stderr create mode 100644 tests/ui/double_ended_iterator_last_unfixable.rs create mode 100644 tests/ui/double_ended_iterator_last_unfixable.stderr create mode 100644 tests/ui/elidable_lifetime_names.fixed create mode 100644 tests/ui/elidable_lifetime_names.rs create mode 100644 tests/ui/elidable_lifetime_names.stderr create mode 100644 tests/ui/io_other_error.fixed create mode 100644 tests/ui/io_other_error.rs create mode 100644 tests/ui/io_other_error.stderr create mode 100644 tests/ui/let_and_return.edition2021.fixed create mode 100644 tests/ui/let_and_return.edition2021.stderr create mode 100644 tests/ui/let_and_return.edition2024.fixed create mode 100644 tests/ui/let_and_return.edition2024.stderr create mode 100644 tests/ui/manual_contains.fixed create mode 100644 tests/ui/manual_contains.rs create mode 100644 tests/ui/manual_contains.stderr create mode 100644 tests/ui/manual_midpoint.fixed create mode 100644 tests/ui/manual_midpoint.rs create mode 100644 tests/ui/manual_midpoint.stderr create mode 100644 tests/ui/manual_strip_fixable.fixed create mode 100644 tests/ui/manual_strip_fixable.rs create mode 100644 tests/ui/manual_strip_fixable.stderr create mode 100644 tests/ui/msrv_attributes_without_early_lints.rs rename tests/ui/{must_use_unit_12320.rs => must_use_unit_unfixable.rs} (62%) rename tests/ui/{must_use_unit_12320.stderr => must_use_unit_unfixable.stderr} (62%) delete mode 100644 tests/ui/option_map_or_err_ok.fixed delete mode 100644 tests/ui/option_map_or_err_ok.rs delete mode 100644 tests/ui/option_map_or_err_ok.stderr create mode 100644 tests/ui/owned_cow.fixed create mode 100644 tests/ui/owned_cow.rs create mode 100644 tests/ui/owned_cow.stderr create mode 100644 tests/ui/range.fixed create mode 100644 tests/ui/single_option_map.rs create mode 100644 tests/ui/single_option_map.stderr create mode 100644 tests/ui/syntax-error-recovery/non_expressive_names_error_recovery.fixed create mode 100644 tests/ui/syntax-error-recovery/non_expressive_names_error_recovery.rs create mode 100644 tests/ui/syntax-error-recovery/non_expressive_names_error_recovery.stderr create mode 100644 tests/ui/unbuffered_bytes.rs create mode 100644 tests/ui/unbuffered_bytes.stderr create mode 100644 tests/ui/unnecessary_os_str_debug_formatting.rs create mode 100644 tests/ui/unnecessary_os_str_debug_formatting.stderr create mode 100644 tests/ui/unnecessary_path_debug_formatting.rs create mode 100644 tests/ui/unnecessary_path_debug_formatting.stderr create mode 100644 tests/ui/{literal_string_with_formatting_args}.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index fa03c953aa59..51441ab9fc0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,53 @@ document. ## Unreleased / Beta / In Rust Nightly -[786fbd6d...master](https://github.com/rust-lang/rust-clippy/compare/786fbd6d...master) +[609cd310...master](https://github.com/rust-lang/rust-clippy/compare/609cd310...master) + +## Rust 1.85 + +Current stable, released 2025-02-20 + +[View all 72 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2024-11-15T19%3A31%3A08Z..2024-12-26T13%3A59%3A48Z+base%3Amaster) + +### New Lints + +* Added [`repr_packed_without_abi`] to `suspicious` + [#13398](https://github.com/rust-lang/rust-clippy/pull/13398) +* Added [`as_pointer_underscore`] to `restriction` + [#13251](https://github.com/rust-lang/rust-clippy/pull/13251) +* Added [`doc_nested_refdefs`] to `suspicious` + [#13707](https://github.com/rust-lang/rust-clippy/pull/13707) +* Added [`literal_string_with_formatting_args`] to `nursery` + [#13410](https://github.com/rust-lang/rust-clippy/pull/13410) +* Added [`doc_include_without_cfg`] to `restriction` + [#13625](https://github.com/rust-lang/rust-clippy/pull/13625) + +### Enhancements + +* [`indexing_slicing`]: Can now be allowed in tests using the [`allow-indexing-slicing-in-tests`] + configuration + [#13854](https://github.com/rust-lang/rust-clippy/pull/13854) +* [`if_let_mutex`]: disable lint from Edition 2024 since + [if_let_rescope](https://github.com/rust-lang/rust/issues/131154) was stabilized + [#13695](https://github.com/rust-lang/rust-clippy/pull/13695) +* [`format_in_format_args`], [`recursive_format_impl`], [`to_string_in_format_args`], + [`uninlined_format_args`], [`unused_format_specs`]: Can now support 3rd party format macros + if they're marked with the `#[clippy::format_args]` attribute + [#9948](https://github.com/rust-lang/rust-clippy/pull/9948) + +### ICE Fixes + +* [`trait_duplication_in_bounds`]: fix ICE on duplicate type or constant bound + [#13722](https://github.com/rust-lang/rust-clippy/pull/13722) + +### Others + +* `clippy_utils` is now published to crates.io. Note that this crate is and will remain unstable. + [#13700](https://github.com/rust-lang/rust-clippy/pull/13700) ## Rust 1.84 -Current stable, released 2025-01-09 +Released 2025-01-09 [View all 84 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2024-10-03T21%3A23%3A58Z..2024-11-14T17%3A41%3A37Z+base%3Amaster) @@ -5530,6 +5572,7 @@ Released 2018-09-13 [`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression [`doc_include_without_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_include_without_cfg [`doc_lazy_continuation`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_lazy_continuation +[`doc_link_code`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_code [`doc_link_with_quotes`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_with_quotes [`doc_markdown`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown [`doc_nested_refdefs`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_nested_refdefs @@ -5549,6 +5592,7 @@ Released 2018-09-13 [`duplicated_attributes`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicated_attributes [`duration_subsec`]: https://rust-lang.github.io/rust-clippy/master/index.html#duration_subsec [`eager_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#eager_transmute +[`elidable_lifetime_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#elidable_lifetime_names [`else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else [`empty_docs`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_docs [`empty_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_drop @@ -5683,6 +5727,7 @@ Released 2018-09-13 [`invalid_utf8_in_unchecked`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_utf8_in_unchecked [`inverted_saturating_sub`]: https://rust-lang.github.io/rust-clippy/master/index.html#inverted_saturating_sub [`invisible_characters`]: https://rust-lang.github.io/rust-clippy/master/index.html#invisible_characters +[`io_other_error`]: https://rust-lang.github.io/rust-clippy/master/index.html#io_other_error [`is_digit_ascii_radix`]: https://rust-lang.github.io/rust-clippy/master/index.html#is_digit_ascii_radix [`items_after_statements`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements [`items_after_test_module`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_test_module @@ -5742,6 +5787,7 @@ Released 2018-09-13 [`manual_bits`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits [`manual_c_str_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_c_str_literals [`manual_clamp`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp +[`manual_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_contains [`manual_div_ceil`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_div_ceil [`manual_filter`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter [`manual_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter_map @@ -5761,6 +5807,7 @@ Released 2018-09-13 [`manual_main_separator_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_main_separator_str [`manual_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_map [`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy +[`manual_midpoint`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_midpoint [`manual_next_back`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_next_back [`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive [`manual_ok_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_err @@ -5812,6 +5859,7 @@ Released 2018-09-13 [`mem_discriminant_non_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_discriminant_non_enum [`mem_forget`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_forget [`mem_replace_option_with_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_option_with_none +[`mem_replace_option_with_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_option_with_some [`mem_replace_with_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default [`mem_replace_with_uninit`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_uninit [`min_ident_chars`]: https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars @@ -5939,6 +5987,7 @@ Released 2018-09-13 [`out_of_bounds_indexing`]: https://rust-lang.github.io/rust-clippy/master/index.html#out_of_bounds_indexing [`overflow_check_conditional`]: https://rust-lang.github.io/rust-clippy/master/index.html#overflow_check_conditional [`overly_complex_bool_expr`]: https://rust-lang.github.io/rust-clippy/master/index.html#overly_complex_bool_expr +[`owned_cow`]: https://rust-lang.github.io/rust-clippy/master/index.html#owned_cow [`panic`]: https://rust-lang.github.io/rust-clippy/master/index.html#panic [`panic_in_result_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#panic_in_result_fn [`panic_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#panic_params @@ -6067,6 +6116,7 @@ Released 2018-09-13 [`single_element_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_element_loop [`single_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match [`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else +[`single_option_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_option_map [`single_range_in_vec_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_range_in_vec_init [`size_of_in_element_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_in_element_count [`size_of_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_ref @@ -6143,6 +6193,7 @@ Released 2018-09-13 [`type_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity [`type_id_on_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_id_on_box [`type_repetition_in_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds +[`unbuffered_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#unbuffered_bytes [`unchecked_duration_subtraction`]: https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction [`unconditional_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#unconditional_recursion [`undocumented_unsafe_blocks`]: https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks @@ -6161,6 +6212,7 @@ Released 2018-09-13 [`unnecessary_box_returns`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns [`unnecessary_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast [`unnecessary_clippy_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_clippy_cfg +[`unnecessary_debug_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_debug_formatting [`unnecessary_fallible_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fallible_conversions [`unnecessary_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_filter_map [`unnecessary_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_find_map @@ -6267,6 +6319,7 @@ Released 2018-09-13 [`accept-comment-above-statement`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-statement [`allow-comparison-to-zero`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-comparison-to-zero [`allow-dbg-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-dbg-in-tests +[`allow-expect-in-consts`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-expect-in-consts [`allow-expect-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-expect-in-tests [`allow-indexing-slicing-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-indexing-slicing-in-tests [`allow-mixed-uninlined-format-args`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-mixed-uninlined-format-args @@ -6275,6 +6328,7 @@ Released 2018-09-13 [`allow-print-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-print-in-tests [`allow-private-module-inception`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-private-module-inception [`allow-renamed-params-for`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-renamed-params-for +[`allow-unwrap-in-consts`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-unwrap-in-consts [`allow-unwrap-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-unwrap-in-tests [`allow-useless-vec-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-useless-vec-in-tests [`allowed-dotfiles`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-dotfiles @@ -6290,6 +6344,7 @@ Released 2018-09-13 [`avoid-breaking-exported-api`]: https://doc.rust-lang.org/clippy/lint_configuration.html#avoid-breaking-exported-api [`await-holding-invalid-types`]: https://doc.rust-lang.org/clippy/lint_configuration.html#await-holding-invalid-types [`cargo-ignore-publish`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cargo-ignore-publish +[`check-incompatible-msrv-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-incompatible-msrv-in-tests [`check-private-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-private-items [`cognitive-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cognitive-complexity-threshold [`disallowed-macros`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-macros diff --git a/Cargo.toml b/Cargo.toml index c9e4f15afbf8..c4588002dc99 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy" # begin autogenerated version -version = "0.1.86" +version = "0.1.87" # end autogenerated version description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" @@ -25,7 +25,7 @@ path = "src/driver.rs" [dependencies] clippy_config = { path = "clippy_config" } clippy_lints = { path = "clippy_lints" } -rustc_tools_util = "0.4.0" +rustc_tools_util = { path = "rustc_tools_util", version = "0.4.2" } tempfile = { version = "3.3", optional = true } termize = "0.1" color-print = "0.3.4" @@ -54,7 +54,7 @@ parking_lot = "0.12" tokio = { version = "1", features = ["io-util"] } [build-dependencies] -rustc_tools_util = "0.4.0" +rustc_tools_util = { path = "rustc_tools_util", version = "0.4.2" } [features] integration = ["tempfile"] diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md index 48506127dee4..0b9010f01071 100644 --- a/book/src/development/adding_lints.md +++ b/book/src/development/adding_lints.md @@ -169,7 +169,7 @@ from the lint to the code of the test file and compare that to the contents of a Use `cargo bless` to automatically generate the `.fixed` file while running the tests. -[rustfix]: https://github.com/rust-lang/rustfix +[rustfix]: https://github.com/rust-lang/cargo/tree/master/crates/rustfix ## Testing manually @@ -460,7 +460,7 @@ pub struct ManualStrip { impl ManualStrip { pub fn new(conf: &'static Conf) -> Self { - Self { msrv: conf.msrv.clone() } + Self { msrv: conf.msrv } } } ``` @@ -469,24 +469,13 @@ The project's MSRV can then be matched against the feature MSRV in the LintPass using the `Msrv::meets` method. ``` rust -if !self.msrv.meets(msrvs::STR_STRIP_PREFIX) { +if !self.msrv.meets(cx, msrvs::STR_STRIP_PREFIX) { return; } ``` -The project's MSRV can also be specified as an attribute, which overrides -the value from `clippy.toml`. This can be accounted for using the -`extract_msrv_attr!(LintContext)` macro and passing -`LateContext`/`EarlyContext`. - -```rust,ignore -impl<'tcx> LateLintPass<'tcx> for ManualStrip { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - ... - } - extract_msrv_attr!(LateContext); -} -``` +Early lint passes should instead use `MsrvStack` coupled with +`extract_msrv_attr!()` Once the `msrv` is added to the lint, a relevant test case should be added to the lint's test file, `tests/ui/manual_strip.rs` in this example. It should @@ -512,8 +501,16 @@ in `clippy_config/src/conf.rs`: ```rust define_Conf! { - /// Lint: LIST, OF, LINTS, . The minimum rust version that the project supports - (msrv: Option = None), + #[lints( + allow_attributes, + allow_attributes_without_reason, + .. + , + .. + unused_trait_names, + use_self, + )] + msrv: Msrv = Msrv::default(), ... } ``` diff --git a/book/src/development/basics.md b/book/src/development/basics.md index 166b6aab9fb3..931e5c3a2942 100644 --- a/book/src/development/basics.md +++ b/book/src/development/basics.md @@ -75,7 +75,7 @@ or if you modify a test file to add a test case. > _Note:_ This command may update more files than you intended. In that case > only commit the files you wanted to update. -[UI test]: https://rustc-dev-guide.rust-lang.org/tests/adding.html#guide-to-the-ui-tests +[UI test]: https://rustc-dev-guide.rust-lang.org/tests/adding.html#ui-test-walkthrough ## `cargo dev` diff --git a/book/src/development/writing_tests.md b/book/src/development/writing_tests.md index 39a5ad966885..d4cca2a72f0b 100644 --- a/book/src/development/writing_tests.md +++ b/book/src/development/writing_tests.md @@ -203,7 +203,7 @@ We'll talk about suggestions more in depth in a [later chapter](emitting_lints.m Use `cargo bless` to automatically generate the `.fixed` file after running the tests. -[`rustfix`]: https://github.com/rust-lang/rustfix +[`rustfix`]: https://github.com/rust-lang/cargo/tree/master/crates/rustfix [`span_lint_and_sugg`]: https://doc.rust-lang.org/beta/nightly-rustc/clippy_utils/diagnostics/fn.span_lint_and_sugg.html ## Testing Manually diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index dab2630a56fc..28b613ea3295 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -71,6 +71,16 @@ Whether `dbg!` should be allowed in test functions or `#[cfg(test)]` * [`dbg_macro`](https://rust-lang.github.io/rust-clippy/master/index.html#dbg_macro) +## `allow-expect-in-consts` +Whether `expect` should be allowed in code always evaluated at compile time + +**Default Value:** `true` + +--- +**Affected lints:** +* [`expect_used`](https://rust-lang.github.io/rust-clippy/master/index.html#expect_used) + + ## `allow-expect-in-tests` Whether `expect` should be allowed in test functions or `#[cfg(test)]` @@ -108,7 +118,7 @@ Whether to allow `r#""#` when `r""` can be used --- **Affected lints:** -* [`unnecessary_raw_string_hashes`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_raw_string_hashes) +* [`needless_raw_string_hashes`](https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes) ## `allow-panic-in-tests` @@ -164,6 +174,16 @@ default configuration of Clippy. By default, any configuration will replace the * [`renamed_function_params`](https://rust-lang.github.io/rust-clippy/master/index.html#renamed_function_params) +## `allow-unwrap-in-consts` +Whether `unwrap` should be allowed in code always evaluated at compile time + +**Default Value:** `true` + +--- +**Affected lints:** +* [`unwrap_used`](https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used) + + ## `allow-unwrap-in-tests` Whether `unwrap` should be allowed in test functions or `#[cfg(test)]` @@ -360,6 +380,7 @@ Suppress lints whenever the suggested change would cause breakage for other crat * [`linkedlist`](https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist) * [`needless_pass_by_ref_mut`](https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut) * [`option_option`](https://rust-lang.github.io/rust-clippy/master/index.html#option_option) +* [`owned_cow`](https://rust-lang.github.io/rust-clippy/master/index.html#owned_cow) * [`rc_buffer`](https://rust-lang.github.io/rust-clippy/master/index.html#rc_buffer) * [`rc_mutex`](https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex) * [`redundant_allocation`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation) @@ -394,6 +415,16 @@ For internal testing only, ignores the current `publish` settings in the Cargo m * [`cargo_common_metadata`](https://rust-lang.github.io/rust-clippy/master/index.html#cargo_common_metadata) +## `check-incompatible-msrv-in-tests` +Whether to check MSRV compatibility in `#[test]` and `#[cfg(test)]` code. + +**Default Value:** `false` + +--- +**Affected lints:** +* [`incompatible_msrv`](https://rust-lang.github.io/rust-clippy/master/index.html#incompatible_msrv) + + ## `check-private-items` Whether to also run the listed lints on private items. @@ -738,15 +769,21 @@ The minimum rust version that the project supports. Defaults to the `rust-versio * [`from_over_into`](https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into) * [`if_then_some_else_none`](https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none) * [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice) +* [`io_other_error`](https://rust-lang.github.io/rust-clippy/master/index.html#io_other_error) * [`iter_kv_map`](https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map) * [`legacy_numeric_constants`](https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants) +* [`lines_filter_map_ok`](https://rust-lang.github.io/rust-clippy/master/index.html#lines_filter_map_ok) * [`manual_bits`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits) * [`manual_c_str_literals`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_c_str_literals) * [`manual_clamp`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp) +* [`manual_div_ceil`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_div_ceil) +* [`manual_flatten`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_flatten) * [`manual_hash_one`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_hash_one) * [`manual_is_ascii_check`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check) * [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else) +* [`manual_midpoint`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_midpoint) * [`manual_non_exhaustive`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive) +* [`manual_option_as_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_option_as_slice) * [`manual_pattern_char_comparison`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_pattern_char_comparison) * [`manual_range_contains`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains) * [`manual_rem_euclid`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid) @@ -761,6 +798,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio * [`map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or) * [`map_with_unused_argument_over_ranges`](https://rust-lang.github.io/rust-clippy/master/index.html#map_with_unused_argument_over_ranges) * [`match_like_matches_macro`](https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro) +* [`mem_replace_option_with_some`](https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_option_with_some) * [`mem_replace_with_default`](https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default) * [`missing_const_for_fn`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn) * [`needless_borrow`](https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow) @@ -770,6 +808,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio * [`ptr_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr) * [`redundant_field_names`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names) * [`redundant_static_lifetimes`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes) +* [`repeat_vec_with_capacity`](https://rust-lang.github.io/rust-clippy/master/index.html#repeat_vec_with_capacity) * [`same_item_push`](https://rust-lang.github.io/rust-clippy/master/index.html#same_item_push) * [`seek_from_current`](https://rust-lang.github.io/rust-clippy/master/index.html#seek_from_current) * [`seek_rewind`](https://rust-lang.github.io/rust-clippy/master/index.html#seek_rewind) diff --git a/clippy_config/Cargo.toml b/clippy_config/Cargo.toml index e473a5839402..934725fccb8e 100644 --- a/clippy_config/Cargo.toml +++ b/clippy_config/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_config" # begin autogenerated version -version = "0.1.86" +version = "0.1.87" # end autogenerated version edition = "2024" publish = false diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index a1591188bee7..a61acbaa96bc 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -1,8 +1,8 @@ use crate::ClippyConfiguration; use crate::types::{ - DisallowedPath, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename, SourceItemOrdering, - SourceItemOrderingCategory, SourceItemOrderingModuleItemGroupings, SourceItemOrderingModuleItemKind, - SourceItemOrderingTraitAssocItemKind, SourceItemOrderingTraitAssocItemKinds, + DisallowedPath, DisallowedPathWithoutReplacement, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, + Rename, SourceItemOrdering, SourceItemOrderingCategory, SourceItemOrderingModuleItemGroupings, + SourceItemOrderingModuleItemKind, SourceItemOrderingTraitAssocItemKind, SourceItemOrderingTraitAssocItemKinds, }; use clippy_utils::msrvs::Msrv; use rustc_errors::Applicability; @@ -288,6 +288,9 @@ define_Conf! { /// Whether `dbg!` should be allowed in test functions or `#[cfg(test)]` #[lints(dbg_macro)] allow_dbg_in_tests: bool = false, + /// Whether `expect` should be allowed in code always evaluated at compile time + #[lints(expect_used)] + allow_expect_in_consts: bool = true, /// Whether `expect` should be allowed in test functions or `#[cfg(test)]` #[lints(expect_used)] allow_expect_in_tests: bool = false, @@ -298,7 +301,7 @@ define_Conf! { #[lints(uninlined_format_args)] allow_mixed_uninlined_format_args: bool = true, /// Whether to allow `r#""#` when `r""` can be used - #[lints(unnecessary_raw_string_hashes)] + #[lints(needless_raw_string_hashes)] allow_one_hash_in_raw_strings: bool = false, /// Whether `panic` should be allowed in test functions or `#[cfg(test)]` #[lints(panic)] @@ -325,6 +328,9 @@ define_Conf! { #[lints(renamed_function_params)] allow_renamed_params_for: Vec = DEFAULT_ALLOWED_TRAITS_WITH_RENAMED_PARAMS.iter().map(ToString::to_string).collect(), + /// Whether `unwrap` should be allowed in code always evaluated at compile time + #[lints(unwrap_used)] + allow_unwrap_in_consts: bool = true, /// Whether `unwrap` should be allowed in test functions or `#[cfg(test)]` #[lints(unwrap_used)] allow_unwrap_in_tests: bool = false, @@ -432,6 +438,7 @@ define_Conf! { linkedlist, needless_pass_by_ref_mut, option_option, + owned_cow, rc_buffer, rc_mutex, redundant_allocation, @@ -448,7 +455,7 @@ define_Conf! { avoid_breaking_exported_api: bool = true, /// The list of types which may not be held across an await point. #[lints(await_holding_invalid_type)] - await_holding_invalid_types: Vec = Vec::new(), + await_holding_invalid_types: Vec = Vec::new(), /// DEPRECATED LINT: BLACKLISTED_NAME. /// /// Use the Disallowed Names lint instead @@ -457,6 +464,9 @@ define_Conf! { /// For internal testing only, ignores the current `publish` settings in the Cargo manifest. #[lints(cargo_common_metadata)] cargo_ignore_publish: bool = false, + /// Whether to check MSRV compatibility in `#[test]` and `#[cfg(test)]` code. + #[lints(incompatible_msrv)] + check_incompatible_msrv_in_tests: bool = false, /// Whether to also run the listed lints on private items. #[lints(missing_errors_doc, missing_panics_doc, missing_safety_doc, unnecessary_safety_doc)] check_private_items: bool = false, @@ -607,15 +617,21 @@ define_Conf! { from_over_into, if_then_some_else_none, index_refutable_slice, + io_other_error, iter_kv_map, legacy_numeric_constants, + lines_filter_map_ok, manual_bits, manual_c_str_literals, manual_clamp, + manual_div_ceil, + manual_flatten, manual_hash_one, manual_is_ascii_check, manual_let_else, + manual_midpoint, manual_non_exhaustive, + manual_option_as_slice, manual_pattern_char_comparison, manual_range_contains, manual_rem_euclid, @@ -630,6 +646,7 @@ define_Conf! { map_unwrap_or, map_with_unused_argument_over_ranges, match_like_matches_macro, + mem_replace_option_with_some, mem_replace_with_default, missing_const_for_fn, needless_borrow, @@ -639,6 +656,7 @@ define_Conf! { ptr_as_ptr, redundant_field_names, redundant_static_lifetimes, + repeat_vec_with_capacity, same_item_push, seek_from_current, seek_rewind, @@ -652,7 +670,7 @@ define_Conf! { unused_trait_names, use_self, )] - msrv: Msrv = Msrv::empty(), + msrv: Msrv = Msrv::default(), /// The minimum size (in bytes) to consider a type for passing by reference instead of by value. #[lints(large_types_passed_by_value)] pass_by_value_size_limit: u64 = 256, diff --git a/clippy_config/src/types.rs b/clippy_config/src/types.rs index c949db9109de..c72291e9799f 100644 --- a/clippy_config/src/types.rs +++ b/clippy_config/src/types.rs @@ -1,6 +1,8 @@ use clippy_utils::def_path_def_ids; +use rustc_errors::{Applicability, Diag}; use rustc_hir::def_id::DefIdMap; use rustc_middle::ty::TyCtxt; +use rustc_span::Span; use serde::de::{self, Deserializer, Visitor}; use serde::{Deserialize, Serialize, ser}; use std::collections::HashMap; @@ -12,37 +14,99 @@ pub struct Rename { pub rename: String, } -#[derive(Debug, Deserialize)] -#[serde(untagged)] -pub enum DisallowedPath { - Simple(String), - WithReason { path: String, reason: Option }, +pub type DisallowedPathWithoutReplacement = DisallowedPath; + +#[derive(Debug, Serialize)] +pub struct DisallowedPath { + path: String, + reason: Option, + replacement: Option, } -impl DisallowedPath { +impl<'de, const REPLACEMENT_ALLOWED: bool> Deserialize<'de> for DisallowedPath { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let enum_ = DisallowedPathEnum::deserialize(deserializer)?; + if !REPLACEMENT_ALLOWED && enum_.replacement().is_some() { + return Err(de::Error::custom("replacement not allowed for this configuration")); + } + Ok(Self { + path: enum_.path().to_owned(), + reason: enum_.reason().map(ToOwned::to_owned), + replacement: enum_.replacement().map(ToOwned::to_owned), + }) + } +} + +// `DisallowedPathEnum` is an implementation detail to enable the `Deserialize` implementation just +// above. `DisallowedPathEnum` is not meant to be used outside of this file. +#[derive(Debug, Deserialize, Serialize)] +#[serde(untagged)] +enum DisallowedPathEnum { + Simple(String), + WithReason { + path: String, + reason: Option, + replacement: Option, + }, +} + +impl DisallowedPath { + pub fn path(&self) -> &str { + &self.path + } + + pub fn diag_amendment(&self, span: Span) -> impl FnOnce(&mut Diag<'_, ()>) + use<'_, REPLACEMENT_ALLOWED> { + move |diag| { + if let Some(replacement) = &self.replacement { + diag.span_suggestion( + span, + self.reason.as_ref().map_or_else(|| String::from("use"), Clone::clone), + replacement, + Applicability::MachineApplicable, + ); + } else if let Some(reason) = &self.reason { + diag.note(reason.clone()); + } + } + } +} + +impl DisallowedPathEnum { pub fn path(&self) -> &str { let (Self::Simple(path) | Self::WithReason { path, .. }) = self; path } - pub fn reason(&self) -> Option<&str> { + fn reason(&self) -> Option<&str> { match &self { Self::WithReason { reason, .. } => reason.as_deref(), Self::Simple(_) => None, } } + + fn replacement(&self) -> Option<&str> { + match &self { + Self::WithReason { replacement, .. } => replacement.as_deref(), + Self::Simple(_) => None, + } + } } /// Creates a map of disallowed items to the reason they were disallowed. -pub fn create_disallowed_map( +pub fn create_disallowed_map( tcx: TyCtxt<'_>, - disallowed: &'static [DisallowedPath], -) -> DefIdMap<(&'static str, Option<&'static str>)> { + disallowed: &'static [DisallowedPath], +) -> DefIdMap<(&'static str, &'static DisallowedPath)> { disallowed .iter() - .map(|x| (x.path(), x.path().split("::").collect::>(), x.reason())) - .flat_map(|(name, path, reason)| def_path_def_ids(tcx, &path).map(move |id| (id, (name, reason)))) + .map(|x| (x.path(), x.path().split("::").collect::>(), x)) + .flat_map(|(name, path, disallowed_path)| { + def_path_def_ids(tcx, &path).map(move |id| (id, (name, disallowed_path))) + }) .collect() } @@ -436,7 +500,6 @@ macro_rules! unimplemented_serialize { } unimplemented_serialize! { - DisallowedPath, Rename, MacroMatcher, } diff --git a/clippy_dev/src/dogfood.rs b/clippy_dev/src/dogfood.rs index 75a4cbd2f92e..05fa24d8d4ee 100644 --- a/clippy_dev/src/dogfood.rs +++ b/clippy_dev/src/dogfood.rs @@ -4,7 +4,8 @@ use std::process::Command; /// # Panics /// /// Panics if unable to run the dogfood test -pub fn dogfood(fix: bool, allow_dirty: bool, allow_staged: bool) { +#[allow(clippy::fn_params_excessive_bools)] +pub fn dogfood(fix: bool, allow_dirty: bool, allow_staged: bool, allow_no_vcs: bool) { let mut cmd = Command::new("cargo"); cmd.current_dir(clippy_project_root()) @@ -25,6 +26,10 @@ pub fn dogfood(fix: bool, allow_dirty: bool, allow_staged: bool) { dogfood_args.push("--allow-staged"); } + if allow_no_vcs { + dogfood_args.push("--allow-no-vcs"); + } + cmd.env("__CLIPPY_DOGFOOD_ARGS", dogfood_args.join(" ")); exit_if_err(cmd.status()); diff --git a/clippy_dev/src/fmt.rs b/clippy_dev/src/fmt.rs index 790dafa811f9..bdddf46a2cb1 100644 --- a/clippy_dev/src/fmt.rs +++ b/clippy_dev/src/fmt.rs @@ -290,8 +290,13 @@ fn run_rustfmt(context: &FmtContext) -> Result<(), Error> { .filter_map(|entry| { let entry = entry.expect("failed to find tests"); let path = entry.path(); - - if path.extension() != Some("rs".as_ref()) || entry.file_name() == "ice-3891.rs" { + if path.extension() != Some("rs".as_ref()) + || path + .components() + .nth_back(1) + .is_some_and(|c| c.as_os_str() == "syntax-error-recovery") + || entry.file_name() == "ice-3891.rs" + { None } else { Some(entry.into_path().into_os_string()) diff --git a/clippy_dev/src/lint.rs b/clippy_dev/src/lint.rs index 125195397e6c..e0e036757d56 100644 --- a/clippy_dev/src/lint.rs +++ b/clippy_dev/src/lint.rs @@ -2,7 +2,7 @@ use crate::utils::{cargo_clippy_path, exit_if_err}; use std::process::{self, Command}; use std::{env, fs}; -pub fn run<'a>(path: &str, args: impl Iterator) { +pub fn run<'a>(path: &str, edition: &str, args: impl Iterator) { let is_file = match fs::metadata(path) { Ok(metadata) => metadata.is_file(), Err(e) => { @@ -17,7 +17,7 @@ pub fn run<'a>(path: &str, args: impl Iterator) { .args(["run", "--bin", "clippy-driver", "--"]) .args(["-L", "./target/debug"]) .args(["-Z", "no-codegen"]) - .args(["--edition", "2021"]) + .args(["--edition", edition]) .arg(path) .args(args) // Prevent rustc from creating `rustc-ice-*` files the console output is enough. diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 56ed60256f16..074dea4ab77b 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -17,7 +17,8 @@ fn main() { fix, allow_dirty, allow_staged, - } => dogfood::dogfood(fix, allow_dirty, allow_staged), + allow_no_vcs, + } => dogfood::dogfood(fix, allow_dirty, allow_staged, allow_no_vcs), DevCommand::Fmt { check, verbose } => fmt::run(check, verbose), DevCommand::UpdateLints { print_only, check } => { if print_only { @@ -34,7 +35,7 @@ fn main() { category, r#type, msrv, - } => match new_lint::create(&pass, &name, &category, r#type.as_deref(), msrv) { + } => match new_lint::create(pass, &name, &category, r#type.as_deref(), msrv) { Ok(()) => update_lints::update(utils::UpdateMode::Change), Err(e) => eprintln!("Unable to create lint: {e}"), }, @@ -53,7 +54,12 @@ fn main() { setup::git_hook::install_hook(force_override); } }, - SetupSubcommand::Toolchain { force, release, name } => setup::toolchain::create(force, release, &name), + SetupSubcommand::Toolchain { + standalone, + force, + release, + name, + } => setup::toolchain::create(standalone, force, release, &name), SetupSubcommand::VscodeTasks { remove, force_override } => { if remove { setup::vscode::remove_tasks(); @@ -68,7 +74,7 @@ fn main() { RemoveSubcommand::VscodeTasks => setup::vscode::remove_tasks(), }, DevCommand::Serve { port, lint } => serve::run(port, lint), - DevCommand::Lint { path, args } => lint::run(&path, args.iter()), + DevCommand::Lint { path, edition, args } => lint::run(&path, &edition, args.iter()), DevCommand::RenameLint { old_name, new_name, @@ -106,6 +112,9 @@ enum DevCommand { #[arg(long, requires = "fix")] /// Fix code even if the working directory has staged changes allow_staged: bool, + #[arg(long, requires = "fix")] + /// Fix code even if a VCS was not detected + allow_no_vcs: bool, }, /// Run rustfmt on all projects and tests Fmt { @@ -138,9 +147,9 @@ enum DevCommand { #[command(name = "new_lint")] /// Create a new lint and run `cargo dev update_lints` NewLint { - #[arg(short, long, value_parser = ["early", "late"], conflicts_with = "type", default_value = "late")] + #[arg(short, long, conflicts_with = "type", default_value = "late")] /// Specify whether the lint runs during the early or late pass - pass: String, + pass: new_lint::Pass, #[arg( short, long, @@ -206,6 +215,9 @@ enum DevCommand { /// cargo dev lint file.rs -- -W clippy::pedantic {n} /// cargo dev lint ~/my-project -- -- -W clippy::pedantic Lint { + /// The Rust edition to use + #[arg(long, default_value = "2024")] + edition: String, /// The path to a file or package directory to lint path: String, /// Pass extra arguments to cargo/clippy-driver @@ -264,14 +276,25 @@ enum SetupSubcommand { force_override: bool, }, /// Install a rustup toolchain pointing to the local clippy build + /// + /// This creates a toolchain with symlinks pointing at + /// `target/.../{clippy-driver,cargo-clippy}`, rebuilds of the project will be reflected in the + /// created toolchain unless `--standalone` is passed Toolchain { + #[arg(long, short)] + /// Create a standalone toolchain by copying the clippy binaries instead + /// of symlinking them + /// + /// Use this for example to create a toolchain, make a small change and then make another + /// toolchain with a different name in order to easily compare the two + standalone: bool, #[arg(long, short)] /// Override an existing toolchain force: bool, #[arg(long, short)] /// Point to --release clippy binary release: bool, - #[arg(long, default_value = "clippy")] + #[arg(long, short, default_value = "clippy")] /// Name of the toolchain name: String, }, diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index cc4b26867a20..96e12706c9e2 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -1,14 +1,28 @@ use crate::utils::{clippy_project_root, clippy_version}; +use clap::ValueEnum; use indoc::{formatdoc, writedoc}; -use std::fmt; -use std::fmt::Write as _; +use std::fmt::{self, Write as _}; use std::fs::{self, OpenOptions}; -use std::io::prelude::*; -use std::io::{self, ErrorKind}; +use std::io::{self, Write as _}; use std::path::{Path, PathBuf}; +#[derive(Clone, Copy, PartialEq, ValueEnum)] +pub enum Pass { + Early, + Late, +} + +impl fmt::Display for Pass { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + Pass::Early => "early", + Pass::Late => "late", + }) + } +} + struct LintData<'a> { - pass: &'a str, + pass: Pass, name: &'a str, category: &'a str, ty: Option<&'a str>, @@ -25,7 +39,7 @@ impl Context for io::Result { Ok(t) => Ok(t), Err(e) => { let message = format!("{}: {e}", text.as_ref()); - Err(io::Error::new(ErrorKind::Other, message)) + Err(io::Error::other(message)) }, } } @@ -36,7 +50,7 @@ impl Context for io::Result { /// # Errors /// /// This function errors out if the files couldn't be created or written to. -pub fn create(pass: &str, name: &str, category: &str, mut ty: Option<&str>, msrv: bool) -> io::Result<()> { +pub fn create(pass: Pass, name: &str, category: &str, mut ty: Option<&str>, msrv: bool) -> io::Result<()> { if category == "cargo" && ty.is_none() { // `cargo` is a special category, these lints should always be in `clippy_lints/src/cargo` ty = Some("cargo"); @@ -57,7 +71,7 @@ pub fn create(pass: &str, name: &str, category: &str, mut ty: Option<&str>, msrv add_lint(&lint, msrv).context("Unable to add lint to clippy_lints/src/lib.rs")?; } - if pass == "early" { + if pass == Pass::Early { println!( "\n\ NOTE: Use a late pass unless you need something specific from\n\ @@ -137,23 +151,17 @@ fn add_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> { let mut lib_rs = fs::read_to_string(path).context("reading")?; let comment_start = lib_rs.find("// add lints here,").expect("Couldn't find comment"); + let ctor_arg = if lint.pass == Pass::Late { "_" } else { "" }; + let lint_pass = lint.pass; + let module_name = lint.name; + let camel_name = to_camel_case(lint.name); let new_lint = if enable_msrv { format!( "store.register_{lint_pass}_pass(move |{ctor_arg}| Box::new({module_name}::{camel_name}::new(conf)));\n ", - lint_pass = lint.pass, - ctor_arg = if lint.pass == "late" { "_" } else { "" }, - module_name = lint.name, - camel_name = to_camel_case(lint.name), ) } else { - format!( - "store.register_{lint_pass}_pass(|{ctor_arg}| Box::new({module_name}::{camel_name}));\n ", - lint_pass = lint.pass, - ctor_arg = if lint.pass == "late" { "_" } else { "" }, - module_name = lint.name, - camel_name = to_camel_case(lint.name), - ) + format!("store.register_{lint_pass}_pass(|{ctor_arg}| Box::new({module_name}::{camel_name}));\n ",) }; lib_rs.insert_str(comment_start, &new_lint); @@ -243,11 +251,16 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String { let mut result = String::new(); let (pass_type, pass_lifetimes, pass_import, context_import) = match lint.pass { - "early" => ("EarlyLintPass", "", "use rustc_ast::ast::*;", "EarlyContext"), - "late" => ("LateLintPass", "<'_>", "use rustc_hir::*;", "LateContext"), - _ => { - unreachable!("`pass_type` should only ever be `early` or `late`!"); - }, + Pass::Early => ("EarlyLintPass", "", "use rustc_ast::ast::*;", "EarlyContext"), + Pass::Late => ("LateLintPass", "<'_>", "use rustc_hir::*;", "LateContext"), + }; + let (msrv_ty, msrv_ctor, extract_msrv) = match lint.pass { + Pass::Early => ( + "MsrvStack", + "MsrvStack::new(conf.msrv)", + "\n extract_msrv_attr!();\n", + ), + Pass::Late => ("Msrv", "conf.msrv", ""), }; let lint_name = lint.name; @@ -259,10 +272,10 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String { let _: fmt::Result = writedoc!( result, r" - use clippy_utils::msrvs::{{self, Msrv}}; + use clippy_utils::msrvs::{{self, {msrv_ty}}}; use clippy_config::Conf; {pass_import} - use rustc_lint::{{{context_import}, {pass_type}, LintContext}}; + use rustc_lint::{{{context_import}, {pass_type}}}; use rustc_session::impl_lint_pass; " @@ -286,20 +299,18 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String { result, r" pub struct {name_camel} {{ - msrv: Msrv, + msrv: {msrv_ty}, }} impl {name_camel} {{ pub fn new(conf: &'static Conf) -> Self {{ - Self {{ msrv: conf.msrv.clone() }} + Self {{ msrv: {msrv_ctor} }} }} }} impl_lint_pass!({name_camel} => [{name_upper}]); - impl {pass_type}{pass_lifetimes} for {name_camel} {{ - extract_msrv_attr!({context_import}); - }} + impl {pass_type}{pass_lifetimes} for {name_camel} {{{extract_msrv}}} // TODO: Add MSRV level to `clippy_config/src/msrvs.rs` if needed. // TODO: Update msrv config comment in `clippy_config/src/conf.rs` @@ -376,9 +387,9 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R let mod_file_path = ty_dir.join("mod.rs"); let context_import = setup_mod_file(&mod_file_path, lint)?; - let pass_lifetimes = match context_import { - "LateContext" => "<'_>", - _ => "", + let (pass_lifetimes, msrv_ty, msrv_ref, msrv_cx) = match context_import { + "LateContext" => ("<'_>", "Msrv", "", "cx, "), + _ => ("", "MsrvStack", "&", ""), }; let name_upper = lint.name.to_uppercase(); @@ -388,14 +399,14 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R let _: fmt::Result = writedoc!( lint_file_contents, r#" - use clippy_utils::msrvs::{{self, Msrv}}; + use clippy_utils::msrvs::{{self, {msrv_ty}}}; use rustc_lint::{{{context_import}, LintContext}}; use super::{name_upper}; // TODO: Adjust the parameters as necessary - pub(super) fn check(cx: &{context_import}{pass_lifetimes}, msrv: &Msrv) {{ - if !msrv.meets(todo!("Add a new entry in `clippy_utils/src/msrvs`")) {{ + pub(super) fn check(cx: &{context_import}{pass_lifetimes}, msrv: {msrv_ref}{msrv_ty}) {{ + if !msrv.meets({msrv_cx}todo!("Add a new entry in `clippy_utils/src/msrvs`")) {{ return; }} todo!(); diff --git a/clippy_dev/src/setup/toolchain.rs b/clippy_dev/src/setup/toolchain.rs index 8d98c6c92d9d..2966629cf70a 100644 --- a/clippy_dev/src/setup/toolchain.rs +++ b/clippy_dev/src/setup/toolchain.rs @@ -3,11 +3,14 @@ use std::env::current_dir; use std::ffi::OsStr; use std::fs; use std::path::{Path, PathBuf}; +use std::process::Command; use walkdir::WalkDir; +use crate::utils::exit_if_err; + use super::verify_inside_clippy_dir; -pub fn create(force: bool, release: bool, name: &str) { +pub fn create(standalone: bool, force: bool, release: bool, name: &str) { if !verify_inside_clippy_dir() { return; } @@ -48,14 +51,22 @@ pub fn create(force: bool, release: bool, name: &str) { } } - symlink_bin("cargo-clippy", &dest, release); - symlink_bin("clippy-driver", &dest, release); + let status = Command::new("cargo") + .arg("build") + .args(release.then_some("--release")) + .status(); + exit_if_err(status); + + install_bin("cargo-clippy", &dest, standalone, release); + install_bin("clippy-driver", &dest, standalone, release); println!("Created toolchain {name}, use it in other projects with e.g. `cargo +{name} clippy`"); - println!("Note: This will need to be re-run whenever the Clippy `rust-toolchain` changes"); + if !standalone { + println!("Note: This will need to be re-run whenever the Clippy `rust-toolchain` changes"); + } } -fn symlink_bin(bin: &str, dest: &Path, release: bool) { +fn install_bin(bin: &str, dest: &Path, standalone: bool, release: bool) { #[cfg(windows)] use std::os::windows::fs::symlink_file as symlink; @@ -71,5 +82,9 @@ fn symlink_bin(bin: &str, dest: &Path, release: bool) { let mut dest = dest.to_path_buf(); dest.extend(["bin", &file_name]); - symlink(src, dest).unwrap(); + if standalone { + fs::copy(src, dest).unwrap(); + } else { + symlink(src, dest).unwrap(); + } } diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index c62a7ec783b6..54347043a13d 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin autogenerated version -version = "0.1.86" +version = "0.1.87" # end autogenerated version description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" diff --git a/clippy_lints/src/almost_complete_range.rs b/clippy_lints/src/almost_complete_range.rs index 0f7f779e8ea7..4f55968d5625 100644 --- a/clippy_lints/src/almost_complete_range.rs +++ b/clippy_lints/src/almost_complete_range.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::msrvs::{self, MsrvStack}; use clippy_utils::source::{trim_span, walk_span_to_context}; use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits}; use rustc_errors::Applicability; @@ -31,12 +31,12 @@ declare_clippy_lint! { impl_lint_pass!(AlmostCompleteRange => [ALMOST_COMPLETE_RANGE]); pub struct AlmostCompleteRange { - msrv: Msrv, + msrv: MsrvStack, } impl AlmostCompleteRange { pub fn new(conf: &'static Conf) -> Self { Self { - msrv: conf.msrv.clone(), + msrv: MsrvStack::new(conf.msrv), } } } @@ -96,7 +96,7 @@ impl EarlyLintPass for AlmostCompleteRange { } } - extract_msrv_attr!(EarlyContext); + extract_msrv_attr!(); } fn is_incomplete_range(start: &Expr, end: &Expr) -> bool { diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index 95f64b74044b..9ae746c13b26 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -69,13 +69,11 @@ pub struct ApproxConstant { impl ApproxConstant { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } -impl<'tcx> LateLintPass<'tcx> for ApproxConstant { +impl LateLintPass<'_> for ApproxConstant { fn check_lit(&mut self, cx: &LateContext<'_>, _hir_id: HirId, lit: &Lit, _negated: bool) { match lit.node { LitKind::Float(s, LitFloatType::Suffixed(fty)) => match fty { @@ -89,8 +87,6 @@ impl<'tcx> LateLintPass<'tcx> for ApproxConstant { _ => (), } } - - extract_msrv_attr!(LateContext); } impl ApproxConstant { @@ -98,7 +94,7 @@ impl ApproxConstant { let s = s.as_str(); if s.parse::().is_ok() { for &(constant, name, min_digits, msrv) in &KNOWN_CONSTS { - if is_approx_const(constant, s, min_digits) && msrv.is_none_or(|msrv| self.msrv.meets(msrv)) { + if is_approx_const(constant, s, min_digits) && msrv.is_none_or(|msrv| self.msrv.meets(cx, msrv)) { span_lint_and_help( cx, APPROX_CONSTANT, diff --git a/clippy_lints/src/as_conversions.rs b/clippy_lints/src/as_conversions.rs index 847653ed6e98..78102772927c 100644 --- a/clippy_lints/src/as_conversions.rs +++ b/clippy_lints/src/as_conversions.rs @@ -9,12 +9,24 @@ declare_clippy_lint! { /// Checks for usage of `as` conversions. /// /// Note that this lint is specialized in linting *every single* use of `as` - /// regardless of whether good alternatives exist or not. - /// If you want more precise lints for `as`, please consider using these separate lints: - /// `unnecessary_cast`, `cast_lossless/cast_possible_truncation/cast_possible_wrap/cast_precision_loss/cast_sign_loss`, - /// `fn_to_numeric_cast(_with_truncation)`, `char_lit_as_u8`, `ref_to_mut` and `ptr_as_ptr`. - /// There is a good explanation the reason why this lint should work in this way and how it is useful - /// [in this issue](https://github.com/rust-lang/rust-clippy/issues/5122). + /// regardless of whether good alternatives exist or not. If you want more + /// precise lints for `as`, please consider using these separate lints: + /// + /// - clippy::cast_lossless + /// - clippy::cast_possible_truncation + /// - clippy::cast_possible_wrap + /// - clippy::cast_precision_loss + /// - clippy::cast_sign_loss + /// - clippy::char_lit_as_u8 + /// - clippy::fn_to_numeric_cast + /// - clippy::fn_to_numeric_cast_with_truncation + /// - clippy::ptr_as_ptr + /// - clippy::unnecessary_cast + /// - invalid_reference_casting + /// + /// There is a good explanation the reason why this lint should work in this + /// way and how it is useful [in this + /// issue](https://github.com/rust-lang/rust-clippy/issues/5122). /// /// ### Why restrict this? /// `as` conversions will perform many kinds of diff --git a/clippy_lints/src/assigning_clones.rs b/clippy_lints/src/assigning_clones.rs index 348495f97a27..ab34af7c3174 100644 --- a/clippy_lints/src/assigning_clones.rs +++ b/clippy_lints/src/assigning_clones.rs @@ -59,9 +59,7 @@ pub struct AssigningClones { impl AssigningClones { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -90,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones { sym::clone if is_diag_trait_item(cx, fn_id, sym::Clone) => CloneTrait::Clone, _ if fn_name.as_str() == "to_owned" && is_diag_trait_item(cx, fn_id, sym::ToOwned) - && self.msrv.meets(msrvs::CLONE_INTO) => + && self.msrv.meets(cx, msrvs::CLONE_INTO) => { CloneTrait::ToOwned }, @@ -143,8 +141,6 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones { ); } } - - extract_msrv_attr!(LateContext); } /// Checks if the data being cloned borrows from the place that is being assigned to: diff --git a/clippy_lints/src/attrs/deprecated_cfg_attr.rs b/clippy_lints/src/attrs/deprecated_cfg_attr.rs index 3a462018e3e0..cd38aed26a3e 100644 --- a/clippy_lints/src/attrs/deprecated_cfg_attr.rs +++ b/clippy_lints/src/attrs/deprecated_cfg_attr.rs @@ -1,12 +1,12 @@ use super::{Attribute, DEPRECATED_CFG_ATTR, DEPRECATED_CLIPPY_CFG_ATTR, unnecessary_clippy_cfg}; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::msrvs::{self, MsrvStack}; use rustc_ast::AttrStyle; use rustc_errors::Applicability; use rustc_lint::EarlyContext; use rustc_span::sym; -pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &Msrv) { +pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &MsrvStack) { // check cfg_attr if attr.has_name(sym::cfg_attr) && let Some(items) = attr.meta_item_list() diff --git a/clippy_lints/src/attrs/mixed_attributes_style.rs b/clippy_lints/src/attrs/mixed_attributes_style.rs index 5a26ba8bf932..d71c8e9894bf 100644 --- a/clippy_lints/src/attrs/mixed_attributes_style.rs +++ b/clippy_lints/src/attrs/mixed_attributes_style.rs @@ -1,4 +1,3 @@ -use std::sync::Arc; use super::MIXED_ATTRIBUTES_STYLE; use clippy_utils::diagnostics::span_lint; use rustc_ast::{AttrKind, AttrStyle, Attribute}; @@ -6,6 +5,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_lint::{EarlyContext, LintContext}; use rustc_span::source_map::SourceMap; use rustc_span::{SourceFile, Span, Symbol}; +use std::sync::Arc; #[derive(Hash, PartialEq, Eq)] enum SimpleAttrKind { diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs index 92efd1a4ddcd..2b59c218d57a 100644 --- a/clippy_lints/src/attrs/mod.rs +++ b/clippy_lints/src/attrs/mod.rs @@ -14,7 +14,7 @@ mod useless_attribute; mod utils; use clippy_config::Conf; -use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::msrvs::{self, Msrv, MsrvStack}; use rustc_ast::{self as ast, Attribute, MetaItemInner, MetaItemKind}; use rustc_hir::{ImplItem, Item, TraitItem}; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; @@ -305,7 +305,7 @@ declare_clippy_lint! { /// header_version: u16 /// } /// ``` - #[clippy::version = "1.84.0"] + #[clippy::version = "1.85.0"] pub REPR_PACKED_WITHOUT_ABI, suspicious, "ensures that `repr(packed)` always comes with a qualified ABI" @@ -459,9 +459,7 @@ impl_lint_pass!(Attributes => [ impl Attributes { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -471,7 +469,7 @@ impl<'tcx> LateLintPass<'tcx> for Attributes { if is_relevant_item(cx, item) { inline_always::check(cx, item.span, item.ident.name, attrs); } - repr_attributes::check(cx, item.span, attrs, &self.msrv); + repr_attributes::check(cx, item.span, attrs, self.msrv); } fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) { @@ -485,18 +483,16 @@ impl<'tcx> LateLintPass<'tcx> for Attributes { inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id())); } } - - extract_msrv_attr!(LateContext); } pub struct EarlyAttributes { - msrv: Msrv, + msrv: MsrvStack, } impl EarlyAttributes { pub fn new(conf: &'static Conf) -> Self { Self { - msrv: conf.msrv.clone(), + msrv: MsrvStack::new(conf.msrv), } } } @@ -515,17 +511,17 @@ impl EarlyLintPass for EarlyAttributes { non_minimal_cfg::check(cx, attr); } - extract_msrv_attr!(EarlyContext); + extract_msrv_attr!(); } pub struct PostExpansionEarlyAttributes { - msrv: Msrv, + msrv: MsrvStack, } impl PostExpansionEarlyAttributes { pub fn new(conf: &'static Conf) -> Self { Self { - msrv: conf.msrv.clone(), + msrv: MsrvStack::new(conf.msrv), } } } @@ -589,5 +585,5 @@ impl EarlyLintPass for PostExpansionEarlyAttributes { duplicated_attributes::check(cx, &item.attrs); } - extract_msrv_attr!(EarlyContext); + extract_msrv_attr!(); } diff --git a/clippy_lints/src/attrs/repr_attributes.rs b/clippy_lints/src/attrs/repr_attributes.rs index 6cc47596bbb6..e5cfbaf952a7 100644 --- a/clippy_lints/src/attrs/repr_attributes.rs +++ b/clippy_lints/src/attrs/repr_attributes.rs @@ -1,33 +1,37 @@ -use rustc_attr_parsing::{find_attr, AttributeKind, ReprAttr}; +use rustc_attr_parsing::{AttributeKind, ReprAttr, find_attr}; use rustc_hir::Attribute; use rustc_lint::LateContext; use rustc_span::Span; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::msrvs; +use clippy_utils::msrvs::{self, Msrv}; use super::REPR_PACKED_WITHOUT_ABI; -pub(super) fn check(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute], msrv: &msrvs::Msrv) { - if msrv.meets(msrvs::REPR_RUST) { - check_packed(cx, item_span, attrs); - } -} - -fn check_packed(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute]) { +pub(super) fn check(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute], msrv: Msrv) { if let Some(reprs) = find_attr!(attrs, AttributeKind::Repr(r) => r) { - let packed_span = reprs.iter().find(|(r, _)| matches!(r, ReprAttr::ReprPacked(..))).map(|(_, s)| *s); + let packed_span = reprs + .iter() + .find(|(r, _)| matches!(r, ReprAttr::ReprPacked(..))) + .map(|(_, s)| *s); - if let Some(packed_span) = packed_span && !reprs.iter().any(|(x, _)| *x == ReprAttr::ReprC || *x == ReprAttr::ReprRust) { + if let Some(packed_span) = packed_span + && !reprs + .iter() + .any(|(x, _)| *x == ReprAttr::ReprC || *x == ReprAttr::ReprRust) + && msrv.meets(cx, msrvs::REPR_RUST) + { span_lint_and_then( cx, REPR_PACKED_WITHOUT_ABI, item_span, "item uses `packed` representation without ABI-qualification", |diag| { - diag.warn("unqualified `#[repr(packed)]` defaults to `#[repr(Rust, packed)]`, which has no stable ABI") - .help("qualify the desired ABI explicity via `#[repr(C, packed)]` or `#[repr(Rust, packed)]`") - .span_label(packed_span, "`packed` representation set here"); + diag.warn( + "unqualified `#[repr(packed)]` defaults to `#[repr(Rust, packed)]`, which has no stable ABI", + ) + .help("qualify the desired ABI explicity via `#[repr(C, packed)]` or `#[repr(Rust, packed)]`") + .span_label(packed_span, "`packed` representation set here"); }, ); } diff --git a/clippy_lints/src/await_holding_invalid.rs b/clippy_lints/src/await_holding_invalid.rs index 2eb0566bf9a6..92a0c7f9acbc 100644 --- a/clippy_lints/src/await_holding_invalid.rs +++ b/clippy_lints/src/await_holding_invalid.rs @@ -1,5 +1,5 @@ use clippy_config::Conf; -use clippy_config::types::create_disallowed_map; +use clippy_config::types::{DisallowedPathWithoutReplacement, create_disallowed_map}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::{match_def_path, paths}; use rustc_hir as hir; @@ -174,7 +174,7 @@ declare_clippy_lint! { impl_lint_pass!(AwaitHolding => [AWAIT_HOLDING_LOCK, AWAIT_HOLDING_REFCELL_REF, AWAIT_HOLDING_INVALID_TYPE]); pub struct AwaitHolding { - def_ids: DefIdMap<(&'static str, Option<&'static str>)>, + def_ids: DefIdMap<(&'static str, &'static DisallowedPathWithoutReplacement)>, } impl AwaitHolding { @@ -247,25 +247,26 @@ impl AwaitHolding { ); }, ); - } else if let Some(&(path, reason)) = self.def_ids.get(&adt.did()) { - emit_invalid_type(cx, ty_cause.source_info.span, path, reason); + } else if let Some(&(path, disallowed_path)) = self.def_ids.get(&adt.did()) { + emit_invalid_type(cx, ty_cause.source_info.span, path, disallowed_path); } } } } } -fn emit_invalid_type(cx: &LateContext<'_>, span: Span, path: &'static str, reason: Option<&'static str>) { +fn emit_invalid_type( + cx: &LateContext<'_>, + span: Span, + path: &'static str, + disallowed_path: &'static DisallowedPathWithoutReplacement, +) { span_lint_and_then( cx, AWAIT_HOLDING_INVALID_TYPE, span, format!("holding a disallowed type across an await point `{path}`"), - |diag| { - if let Some(reason) = reason { - diag.note(reason); - } - }, + disallowed_path.diag_amendment(span), ); } diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index f30f16997d76..48b5d4da8886 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -3,6 +3,7 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; use clippy_utils::eq_expr_value; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::SpanRangeExt; +use clippy_utils::sugg::Sugg; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; use rustc_ast::ast::LitKind; use rustc_attr_parsing::RustcVersion; @@ -84,9 +85,7 @@ pub struct NonminimalBool { impl NonminimalBool { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -102,7 +101,7 @@ impl<'tcx> LateLintPass<'tcx> for NonminimalBool { _: Span, _: LocalDefId, ) { - NonminimalBoolVisitor { cx, msrv: &self.msrv }.visit_body(body); + NonminimalBoolVisitor { cx, msrv: self.msrv }.visit_body(body); } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { @@ -119,8 +118,6 @@ impl<'tcx> LateLintPass<'tcx> for NonminimalBool { _ => {}, } } - - extract_msrv_attr!(LateContext); } fn inverted_bin_op_eq_str(op: BinOpKind) -> Option<&'static str> { @@ -197,7 +194,7 @@ fn check_inverted_bool_in_condition( ); } -fn check_simplify_not(cx: &LateContext<'_>, msrv: &Msrv, expr: &Expr<'_>) { +fn check_simplify_not(cx: &LateContext<'_>, msrv: Msrv, expr: &Expr<'_>) { if let ExprKind::Unary(UnOp::Not, inner) = &expr.kind && !expr.span.from_expansion() && !inner.span.from_expansion() @@ -233,7 +230,7 @@ fn check_simplify_not(cx: &LateContext<'_>, msrv: &Msrv, expr: &Expr<'_>) { struct NonminimalBoolVisitor<'a, 'tcx> { cx: &'a LateContext<'tcx>, - msrv: &'a Msrv, + msrv: Msrv, } use quine_mc_cluskey::Bool; @@ -326,7 +323,7 @@ impl<'v> Hir2Qmm<'_, '_, 'v> { struct SuggestContext<'a, 'tcx, 'v> { terminals: &'v [&'v Expr<'v>], cx: &'a LateContext<'tcx>, - msrv: &'a Msrv, + msrv: Msrv, output: String, } @@ -353,7 +350,8 @@ impl SuggestContext<'_, '_, '_> { self.output.push_str(&str); } else { self.output.push('!'); - self.output.push_str(&terminal.span.get_source_text(self.cx)?); + self.output + .push_str(&Sugg::hir_opt(self.cx, terminal)?.maybe_par().to_string()); } }, True | False | Not(_) => { @@ -396,7 +394,7 @@ impl SuggestContext<'_, '_, '_> { } } -fn simplify_not(cx: &LateContext<'_>, curr_msrv: &Msrv, expr: &Expr<'_>) -> Option { +fn simplify_not(cx: &LateContext<'_>, curr_msrv: Msrv, expr: &Expr<'_>) -> Option { match &expr.kind { ExprKind::Binary(binop, lhs, rhs) => { if !implements_ord(cx, lhs) { @@ -438,7 +436,9 @@ fn simplify_not(cx: &LateContext<'_>, curr_msrv: &Msrv, expr: &Expr<'_>) -> Opti .iter() .copied() .flat_map(|(msrv, a, b)| vec![(msrv, a, b), (msrv, b, a)]) - .find(|&(msrv, a, _)| msrv.is_none_or(|msrv| curr_msrv.meets(msrv)) && a == path.ident.name.as_str()) + .find(|&(msrv, a, _)| { + a == path.ident.name.as_str() && msrv.is_none_or(|msrv| curr_msrv.meets(cx, msrv)) + }) .and_then(|(_, _, neg_method)| { let negated_args = args .iter() @@ -467,7 +467,7 @@ fn simplify_not(cx: &LateContext<'_>, curr_msrv: &Msrv, expr: &Expr<'_>) -> Opti } } -fn suggest(cx: &LateContext<'_>, msrv: &Msrv, suggestion: &Bool, terminals: &[&Expr<'_>]) -> String { +fn suggest(cx: &LateContext<'_>, msrv: Msrv, suggestion: &Bool, terminals: &[&Expr<'_>]) -> String { let mut suggest_context = SuggestContext { terminals, cx, @@ -553,7 +553,7 @@ impl<'tcx> NonminimalBoolVisitor<'_, 'tcx> { _ => simplified.push(Bool::Not(Box::new(simple.clone()))), } let simple_negated = simple_negate(simple); - if simplified.iter().any(|s| *s == simple_negated) { + if simplified.contains(&simple_negated) { continue; } simplified.push(simple_negated); diff --git a/clippy_lints/src/casts/borrow_as_ptr.rs b/clippy_lints/src/casts/borrow_as_ptr.rs index 6057144bc6a4..d143629da3a0 100644 --- a/clippy_lints/src/casts/borrow_as_ptr.rs +++ b/clippy_lints/src/casts/borrow_as_ptr.rs @@ -16,7 +16,7 @@ pub(super) fn check<'tcx>( expr: &'tcx Expr<'_>, cast_expr: &'tcx Expr<'_>, cast_to: &'tcx Ty<'_>, - msrv: &Msrv, + msrv: Msrv, ) -> bool { if matches!(cast_to.kind, TyKind::Ptr(_)) && let ExprKind::AddrOf(BorrowKind::Ref, mutability, e) = cast_expr.kind @@ -34,7 +34,7 @@ pub(super) fn check<'tcx>( return false; } - let (suggestion, span) = if msrv.meets(msrvs::RAW_REF_OP) { + let (suggestion, span) = if msrv.meets(cx, msrvs::RAW_REF_OP) { let operator_kind = match mutability { Mutability::Not => "const", Mutability::Mut => "mut", diff --git a/clippy_lints/src/casts/cast_abs_to_unsigned.rs b/clippy_lints/src/casts/cast_abs_to_unsigned.rs index ae433773193a..8b3529e84fc6 100644 --- a/clippy_lints/src/casts/cast_abs_to_unsigned.rs +++ b/clippy_lints/src/casts/cast_abs_to_unsigned.rs @@ -14,13 +14,13 @@ pub(super) fn check( cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>, - msrv: &Msrv, + msrv: Msrv, ) { - if msrv.meets(msrvs::UNSIGNED_ABS) - && let ty::Int(from) = cast_from.kind() + if let ty::Int(from) = cast_from.kind() && let ty::Uint(to) = cast_to.kind() && let ExprKind::MethodCall(method_path, receiver, [], _) = cast_expr.kind && method_path.ident.name.as_str() == "abs" + && msrv.meets(cx, msrvs::UNSIGNED_ABS) { let span = if from.bit_width() == to.bit_width() { expr.span diff --git a/clippy_lints/src/casts/cast_lossless.rs b/clippy_lints/src/casts/cast_lossless.rs index c326a0d935c7..3ae43732dc03 100644 --- a/clippy_lints/src/casts/cast_lossless.rs +++ b/clippy_lints/src/casts/cast_lossless.rs @@ -19,7 +19,7 @@ pub(super) fn check( cast_from: Ty<'_>, cast_to: Ty<'_>, cast_to_hir: &rustc_hir::Ty<'_>, - msrv: &Msrv, + msrv: Msrv, ) { if !should_lint(cx, cast_from, cast_to, msrv) { return; @@ -70,7 +70,7 @@ pub(super) fn check( ); } -fn should_lint(cx: &LateContext<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>, msrv: &Msrv) -> bool { +fn should_lint(cx: &LateContext<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>, msrv: Msrv) -> bool { // Do not suggest using From in consts/statics until it is valid to do so (see #2267). if is_in_const_context(cx) { return false; @@ -96,7 +96,7 @@ fn should_lint(cx: &LateContext<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>, msrv: & }; !is_isize_or_usize(cast_from) && from_nbits < to_nbits }, - (false, true) if matches!(cast_from.kind(), ty::Bool) && msrv.meets(msrvs::FROM_BOOL) => true, + (false, true) if matches!(cast_from.kind(), ty::Bool) && msrv.meets(cx, msrvs::FROM_BOOL) => true, (_, _) => { matches!(cast_from.kind(), ty::Float(FloatTy::F32)) && matches!(cast_to.kind(), ty::Float(FloatTy::F64)) }, diff --git a/clippy_lints/src/casts/cast_sign_loss.rs b/clippy_lints/src/casts/cast_sign_loss.rs index 45045e58ac75..c8abf9dac9af 100644 --- a/clippy_lints/src/casts/cast_sign_loss.rs +++ b/clippy_lints/src/casts/cast_sign_loss.rs @@ -142,11 +142,11 @@ fn expr_sign<'cx, 'tcx>(cx: &LateContext<'cx>, mut expr: &'tcx Expr<'tcx>, ty: i expr = recv; } - if METHODS_POW.iter().any(|&name| method_name == name) + if METHODS_POW.contains(&method_name) && let [arg] = args { return pow_call_result_sign(cx, caller, arg); - } else if METHODS_RET_POSITIVE.iter().any(|&name| method_name == name) { + } else if METHODS_RET_POSITIVE.contains(&method_name) { return Sign::ZeroOrPositive; } } diff --git a/clippy_lints/src/casts/cast_slice_different_sizes.rs b/clippy_lints/src/casts/cast_slice_different_sizes.rs index 030c2d322db6..c48f253606dc 100644 --- a/clippy_lints/src/casts/cast_slice_different_sizes.rs +++ b/clippy_lints/src/casts/cast_slice_different_sizes.rs @@ -9,12 +9,7 @@ use rustc_middle::ty::{self, Ty, TypeAndMut}; use super::CAST_SLICE_DIFFERENT_SIZES; -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: &Msrv) { - // suggestion is invalid if `ptr::slice_from_raw_parts` does not exist - if !msrv.meets(msrvs::PTR_SLICE_RAW_PARTS) { - return; - } - +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: Msrv) { // if this cast is the child of another cast expression then don't emit something for it, the full // chain will be analyzed if is_child_of_cast(cx, expr) { @@ -30,7 +25,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: &Msrv if let (Ok(from_layout), Ok(to_layout)) = (cx.layout_of(start_ty.ty), cx.layout_of(end_ty.ty)) { let from_size = from_layout.size.bytes(); let to_size = to_layout.size.bytes(); - if from_size != to_size && from_size != 0 && to_size != 0 { + if from_size != to_size && from_size != 0 && to_size != 0 && msrv.meets(cx, msrvs::PTR_SLICE_RAW_PARTS) { span_lint_and_then( cx, CAST_SLICE_DIFFERENT_SIZES, diff --git a/clippy_lints/src/casts/cast_slice_from_raw_parts.rs b/clippy_lints/src/casts/cast_slice_from_raw_parts.rs index c3bc5c0c9f2a..46b0c88d3fed 100644 --- a/clippy_lints/src/casts/cast_slice_from_raw_parts.rs +++ b/clippy_lints/src/casts/cast_slice_from_raw_parts.rs @@ -23,9 +23,8 @@ fn raw_parts_kind(cx: &LateContext<'_>, did: DefId) -> Option { } } -pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_to: Ty<'_>, msrv: &Msrv) { - if msrv.meets(msrvs::PTR_SLICE_RAW_PARTS) - && let ty::RawPtr(ptrty, _) = cast_to.kind() +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_to: Ty<'_>, msrv: Msrv) { + if let ty::RawPtr(ptrty, _) = cast_to.kind() && let ty::Slice(_) = ptrty.kind() && let ExprKind::Call(fun, [ptr_arg, len_arg]) = cast_expr.peel_blocks().kind && let ExprKind::Path(ref qpath) = fun.kind @@ -33,6 +32,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, && let Some(rpk) = raw_parts_kind(cx, fun_def_id) && let ctxt = expr.span.ctxt() && cast_expr.span.ctxt() == ctxt + && msrv.meets(cx, msrvs::PTR_SLICE_RAW_PARTS) { let func = match rpk { RawPartsKind::Immutable => "from_raw_parts", diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index 521bd394901a..dc2a1fa85bf5 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -134,8 +134,14 @@ declare_clippy_lint! { /// /// ### Example /// ```no_run - /// u32::MAX as i32; // will yield a value of `-1` + /// let _ = u32::MAX as i32; // will yield a value of `-1` /// ``` + /// + /// Use instead: + /// ```no_run + /// let _ = i32::try_from(u32::MAX).ok(); + /// ``` + /// #[clippy::version = "pre 1.29.0"] pub CAST_POSSIBLE_WRAP, pedantic, @@ -747,7 +753,7 @@ declare_clippy_lint! { /// t as *const T as usize /// } /// ``` - #[clippy::version = "1.81.0"] + #[clippy::version = "1.85.0"] pub AS_POINTER_UNDERSCORE, restriction, "detects `as *mut _` and `as *const _` conversion" @@ -759,9 +765,7 @@ pub struct Casts { impl Casts { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -811,8 +815,8 @@ impl<'tcx> LateLintPass<'tcx> for Casts { if !expr.span.from_expansion() && unnecessary_cast::check(cx, expr, cast_from_expr, cast_from, cast_to) { return; } - cast_slice_from_raw_parts::check(cx, expr, cast_from_expr, cast_to, &self.msrv); - ptr_cast_constness::check(cx, expr, cast_from_expr, cast_from, cast_to, &self.msrv); + cast_slice_from_raw_parts::check(cx, expr, cast_from_expr, cast_to, self.msrv); + ptr_cast_constness::check(cx, expr, cast_from_expr, cast_from, cast_to, self.msrv); as_ptr_cast_mut::check(cx, expr, cast_from_expr, cast_to); fn_to_numeric_cast_any::check(cx, expr, cast_from_expr, cast_from, cast_to); fn_to_numeric_cast::check(cx, expr, cast_from_expr, cast_from, cast_to); @@ -825,29 +829,27 @@ impl<'tcx> LateLintPass<'tcx> for Casts { cast_possible_wrap::check(cx, expr, cast_from, cast_to); cast_precision_loss::check(cx, expr, cast_from, cast_to); cast_sign_loss::check(cx, expr, cast_from_expr, cast_from, cast_to); - cast_abs_to_unsigned::check(cx, expr, cast_from_expr, cast_from, cast_to, &self.msrv); + cast_abs_to_unsigned::check(cx, expr, cast_from_expr, cast_from, cast_to, self.msrv); cast_nan_to_int::check(cx, expr, cast_from_expr, cast_from, cast_to); } - cast_lossless::check(cx, expr, cast_from_expr, cast_from, cast_to, cast_to_hir, &self.msrv); + cast_lossless::check(cx, expr, cast_from_expr, cast_from, cast_to, cast_to_hir, self.msrv); cast_enum_constructor::check(cx, expr, cast_from_expr, cast_from); } as_underscore::check(cx, expr, cast_to_hir); as_pointer_underscore::check(cx, cast_to, cast_to_hir); - let was_borrow_as_ptr_emitted = self.msrv.meets(msrvs::BORROW_AS_PTR) - && borrow_as_ptr::check(cx, expr, cast_from_expr, cast_to_hir, &self.msrv); - if self.msrv.meets(msrvs::PTR_FROM_REF) && !was_borrow_as_ptr_emitted { + let was_borrow_as_ptr_emitted = self.msrv.meets(cx, msrvs::BORROW_AS_PTR) + && borrow_as_ptr::check(cx, expr, cast_from_expr, cast_to_hir, self.msrv); + if !was_borrow_as_ptr_emitted && self.msrv.meets(cx, msrvs::PTR_FROM_REF) { ref_as_ptr::check(cx, expr, cast_from_expr, cast_to_hir); } } cast_ptr_alignment::check(cx, expr); char_lit_as_u8::check(cx, expr); - ptr_as_ptr::check(cx, expr, &self.msrv); - cast_slice_different_sizes::check(cx, expr, &self.msrv); + ptr_as_ptr::check(cx, expr, self.msrv); + cast_slice_different_sizes::check(cx, expr, self.msrv); ptr_cast_constness::check_null_ptr_cast_method(cx, expr); } - - extract_msrv_attr!(LateContext); } diff --git a/clippy_lints/src/casts/ptr_as_ptr.rs b/clippy_lints/src/casts/ptr_as_ptr.rs index bdc389d39dd3..d57e391b55d5 100644 --- a/clippy_lints/src/casts/ptr_as_ptr.rs +++ b/clippy_lints/src/casts/ptr_as_ptr.rs @@ -26,11 +26,7 @@ impl OmitFollowedCastReason<'_> { } } -pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) { - if !msrv.meets(msrvs::POINTER_CAST) { - return; - } - +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: Msrv) { if let ExprKind::Cast(cast_expr, cast_to_hir_ty) = expr.kind && let (cast_from, cast_to) = (cx.typeck_results().expr_ty(cast_expr), cx.typeck_results().expr_ty(expr)) && let ty::RawPtr(_, from_mutbl) = cast_from.kind() @@ -40,6 +36,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) { // The `U` in `pointer::cast` have to be `Sized` // as explained here: https://github.com/rust-lang/rust/issues/60602. && to_pointee_ty.is_sized(cx.tcx, cx.typing_env()) + && msrv.meets(cx, msrvs::POINTER_CAST) { let mut app = Applicability::MachineApplicable; let turbofish = match &cast_to_hir_ty.kind { diff --git a/clippy_lints/src/casts/ptr_cast_constness.rs b/clippy_lints/src/casts/ptr_cast_constness.rs index 945c05ee9436..cad9c1df273f 100644 --- a/clippy_lints/src/casts/ptr_cast_constness.rs +++ b/clippy_lints/src/casts/ptr_cast_constness.rs @@ -16,7 +16,7 @@ pub(super) fn check<'tcx>( cast_expr: &Expr<'_>, cast_from: Ty<'tcx>, cast_to: Ty<'tcx>, - msrv: &Msrv, + msrv: Msrv, ) { if let ty::RawPtr(from_ty, from_mutbl) = cast_from.kind() && let ty::RawPtr(to_ty, to_mutbl) = cast_to.kind() @@ -52,7 +52,7 @@ pub(super) fn check<'tcx>( return; } - if msrv.meets(msrvs::POINTER_CAST_CONSTNESS) { + if msrv.meets(cx, msrvs::POINTER_CAST_CONSTNESS) { let sugg = Sugg::hir(cx, cast_expr, "_"); let constness = match *to_mutbl { Mutability::Not => "const", diff --git a/clippy_lints/src/checked_conversions.rs b/clippy_lints/src/checked_conversions.rs index 9516af7334d7..b36c8662289c 100644 --- a/clippy_lints/src/checked_conversions.rs +++ b/clippy_lints/src/checked_conversions.rs @@ -39,9 +39,7 @@ pub struct CheckedConversions { impl CheckedConversions { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -65,7 +63,6 @@ impl LateLintPass<'_> for CheckedConversions { } && !item.span.in_external_macro(cx.sess().source_map()) && !is_in_const_context(cx) - && self.msrv.meets(msrvs::TRY_FROM) && let Some(cv) = match op2 { // todo: check for case signed -> larger unsigned == only x >= 0 None => check_upper_bound(lt1, gt1).filter(|cv| cv.cvt == ConversionType::FromUnsigned), @@ -79,6 +76,7 @@ impl LateLintPass<'_> for CheckedConversions { }, } && let Some(to_type) = cv.to_type + && self.msrv.meets(cx, msrvs::TRY_FROM) { let mut applicability = Applicability::MachineApplicable; let snippet = snippet_with_applicability(cx, cv.expr_to_cast.span, "_", &mut applicability); @@ -93,8 +91,6 @@ impl LateLintPass<'_> for CheckedConversions { ); } } - - extract_msrv_attr!(LateContext); } /// Contains the result of a tried conversion check diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 89808d38b9f3..03ed9c657b30 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -18,7 +18,6 @@ use rustc_session::impl_lint_pass; use rustc_span::hygiene::walk_chain; use rustc_span::source_map::SourceMap; use rustc_span::{Span, Symbol}; -use std::borrow::Cow; declare_clippy_lint! { /// ### What it does @@ -130,11 +129,6 @@ declare_clippy_lint! { /// ### Why is this bad? /// Duplicate code is less maintainable. /// - /// ### Known problems - /// * The lint doesn't check if the moved expressions modify values that are being used in - /// the if condition. The suggestion can in that case modify the behavior of the program. - /// See [rust-clippy#7452](https://github.com/rust-lang/rust-clippy/issues/7452) - /// /// ### Example /// ```ignore /// let foo = if … { @@ -248,18 +242,18 @@ fn lint_branches_sharing_code<'tcx>( let first_line_span = first_line_of_span(cx, expr.span); let replace_span = first_line_span.with_hi(span.hi()); let cond_span = first_line_span.until(first_block.span); - let cond_snippet = reindent_multiline(snippet(cx, cond_span, "_"), false, None); + let cond_snippet = reindent_multiline(&snippet(cx, cond_span, "_"), false, None); let cond_indent = indent_of(cx, cond_span); - let moved_snippet = reindent_multiline(snippet(cx, span, "_"), true, None); + let moved_snippet = reindent_multiline(&snippet(cx, span, "_"), true, None); let suggestion = moved_snippet.to_string() + "\n" + &cond_snippet + "{"; - let suggestion = reindent_multiline(Cow::Borrowed(&suggestion), true, cond_indent); + let suggestion = reindent_multiline(&suggestion, true, cond_indent); (replace_span, suggestion.to_string()) }); let end_suggestion = res.end_span(last_block, sm).map(|span| { - let moved_snipped = reindent_multiline(snippet(cx, span, "_"), true, None); + let moved_snipped = reindent_multiline(&snippet(cx, span, "_"), true, None); let indent = indent_of(cx, expr.span.shrink_to_hi()); let suggestion = "}\n".to_string() + &moved_snipped; - let suggestion = reindent_multiline(Cow::Borrowed(&suggestion), true, indent); + let suggestion = reindent_multiline(&suggestion, true, indent); let span = span.with_hi(last_block.span.hi()); // Improve formatting if the inner block has indention (i.e. normal Rust formatting) diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 5c5978b55598..0834618499c7 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -139,6 +139,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::disallowed_types::DISALLOWED_TYPES_INFO, crate::doc::DOC_INCLUDE_WITHOUT_CFG_INFO, crate::doc::DOC_LAZY_CONTINUATION_INFO, + crate::doc::DOC_LINK_CODE_INFO, crate::doc::DOC_LINK_WITH_QUOTES_INFO, crate::doc::DOC_MARKDOWN_INFO, crate::doc::DOC_NESTED_REFDEFS_INFO, @@ -192,6 +193,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::format_args::FORMAT_IN_FORMAT_ARGS_INFO, crate::format_args::TO_STRING_IN_FORMAT_ARGS_INFO, crate::format_args::UNINLINED_FORMAT_ARGS_INFO, + crate::format_args::UNNECESSARY_DEBUG_FORMATTING_INFO, crate::format_args::UNUSED_FORMAT_SPECS_INFO, crate::format_impl::PRINT_IN_FORMAT_IMPL_INFO, crate::format_impl::RECURSIVE_FORMAT_IMPL_INFO, @@ -272,6 +274,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::let_underscore::LET_UNDERSCORE_MUST_USE_INFO, crate::let_underscore::LET_UNDERSCORE_UNTYPED_INFO, crate::let_with_type_underscore::LET_WITH_TYPE_UNDERSCORE_INFO, + crate::lifetimes::ELIDABLE_LIFETIME_NAMES_INFO, crate::lifetimes::EXTRA_UNUSED_LIFETIMES_INFO, crate::lifetimes::NEEDLESS_LIFETIMES_INFO, crate::lines_filter_map_ok::LINES_FILTER_MAP_OK_INFO, @@ -362,6 +365,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::matches::WILDCARD_ENUM_MATCH_ARM_INFO, crate::matches::WILDCARD_IN_OR_PATTERNS_INFO, crate::mem_replace::MEM_REPLACE_OPTION_WITH_NONE_INFO, + crate::mem_replace::MEM_REPLACE_OPTION_WITH_SOME_INFO, crate::mem_replace::MEM_REPLACE_WITH_DEFAULT_INFO, crate::mem_replace::MEM_REPLACE_WITH_UNINIT_INFO, crate::methods::BIND_INSTEAD_OF_MAP_INFO, @@ -398,6 +402,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::methods::INEFFICIENT_TO_STRING_INFO, crate::methods::INSPECT_FOR_EACH_INFO, crate::methods::INTO_ITER_ON_REF_INFO, + crate::methods::IO_OTHER_ERROR_INFO, crate::methods::IS_DIGIT_ASCII_RADIX_INFO, crate::methods::ITERATOR_STEP_BY_ZERO_INFO, crate::methods::ITER_CLONED_COLLECT_INFO, @@ -416,6 +421,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::methods::ITER_SKIP_ZERO_INFO, crate::methods::ITER_WITH_DRAIN_INFO, crate::methods::JOIN_ABSOLUTE_PATHS_INFO, + crate::methods::MANUAL_CONTAINS_INFO, crate::methods::MANUAL_C_STR_LITERALS_INFO, crate::methods::MANUAL_FILTER_MAP_INFO, crate::methods::MANUAL_FIND_MAP_INFO, @@ -452,7 +458,6 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::methods::OPTION_AS_REF_CLONED_INFO, crate::methods::OPTION_AS_REF_DEREF_INFO, crate::methods::OPTION_FILTER_MAP_INFO, - crate::methods::OPTION_MAP_OR_ERR_OK_INFO, crate::methods::OPTION_MAP_OR_NONE_INFO, crate::methods::OR_FUN_CALL_INFO, crate::methods::OR_THEN_UNWRAP_INFO, @@ -483,6 +488,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::methods::SUSPICIOUS_SPLITN_INFO, crate::methods::SUSPICIOUS_TO_OWNED_INFO, crate::methods::TYPE_ID_ON_BOX_INFO, + crate::methods::UNBUFFERED_BYTES_INFO, crate::methods::UNINIT_ASSUMED_INIT_INFO, crate::methods::UNIT_HASH_INFO, crate::methods::UNNECESSARY_FALLIBLE_CONVERSIONS_INFO, @@ -602,6 +608,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::operators::IMPOSSIBLE_COMPARISONS_INFO, crate::operators::INEFFECTIVE_BIT_MASK_INFO, crate::operators::INTEGER_DIVISION_INFO, + crate::operators::MANUAL_MIDPOINT_INFO, crate::operators::MISREFACTORED_ASSIGN_OP_INFO, crate::operators::MODULO_ARITHMETIC_INFO, crate::operators::MODULO_ONE_INFO, @@ -684,6 +691,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::single_call_fn::SINGLE_CALL_FN_INFO, crate::single_char_lifetime_names::SINGLE_CHAR_LIFETIME_NAMES_INFO, crate::single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS_INFO, + crate::single_option_map::SINGLE_OPTION_MAP_INFO, crate::single_range_in_vec_init::SINGLE_RANGE_IN_VEC_INIT_INFO, crate::size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT_INFO, crate::size_of_ref::SIZE_OF_REF_INFO, @@ -741,6 +749,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::types::BOX_COLLECTION_INFO, crate::types::LINKEDLIST_INFO, crate::types::OPTION_OPTION_INFO, + crate::types::OWNED_COW_INFO, crate::types::RC_BUFFER_INFO, crate::types::RC_MUTEX_INFO, crate::types::REDUNDANT_ALLOCATION_INFO, diff --git a/clippy_lints/src/default_union_representation.rs b/clippy_lints/src/default_union_representation.rs index 6e6d81db11c0..085ed9222c91 100644 --- a/clippy_lints/src/default_union_representation.rs +++ b/clippy_lints/src/default_union_representation.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use rustc_attr_parsing::{find_attr, AttributeKind, ReprAttr}; +use rustc_attr_parsing::{AttributeKind, ReprAttr, find_attr}; use rustc_hir::{HirId, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf; diff --git a/clippy_lints/src/deprecated_lints.rs b/clippy_lints/src/deprecated_lints.rs index 5604172d6f30..0031da406f17 100644 --- a/clippy_lints/src/deprecated_lints.rs +++ b/clippy_lints/src/deprecated_lints.rs @@ -40,6 +40,8 @@ declare_with_version! { DEPRECATED(DEPRECATED_VERSION): &[(&str, &str)] = &[ ("clippy::pub_enum_variant_names", "`clippy::enum_variant_names` now covers this case via the `avoid-breaking-exported-api` config"), #[clippy::version = "1.54.0"] ("clippy::wrong_pub_self_convention", "`clippy::wrong_self_convention` now covers this case via the `avoid-breaking-exported-api` config"), + #[clippy::version = "1.86.0"] + ("clippy::option_map_or_err_ok", "`clippy::manual_ok_or` covers this case"), // end deprecated lints. used by `cargo dev deprecate_lint` ]} diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs index bb445e0155f6..66a3e5e3d3c7 100644 --- a/clippy_lints/src/derivable_impls.rs +++ b/clippy_lints/src/derivable_impls.rs @@ -62,9 +62,7 @@ pub struct DerivableImpls { impl DerivableImpls { pub fn new(conf: &'static Conf) -> Self { - DerivableImpls { - msrv: conf.msrv.clone(), - } + DerivableImpls { msrv: conf.msrv } } } @@ -205,11 +203,9 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls { { if adt_def.is_struct() { check_struct(cx, item, self_ty, func_expr, adt_def, args, cx.tcx.typeck_body(*b)); - } else if adt_def.is_enum() && self.msrv.meets(msrvs::DEFAULT_ENUM_ATTRIBUTE) { + } else if adt_def.is_enum() && self.msrv.meets(cx, msrvs::DEFAULT_ENUM_ATTRIBUTE) { check_enum(cx, item, func_expr, adt_def); } } } - - extract_msrv_attr!(LateContext); } diff --git a/clippy_lints/src/disallowed_macros.rs b/clippy_lints/src/disallowed_macros.rs index 6de16e306c9a..4b8a689e9947 100644 --- a/clippy_lints/src/disallowed_macros.rs +++ b/clippy_lints/src/disallowed_macros.rs @@ -1,10 +1,9 @@ use clippy_config::Conf; -use clippy_config::types::create_disallowed_map; +use clippy_config::types::{DisallowedPath, create_disallowed_map}; use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::macros::macro_backtrace; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::Diag; use rustc_hir::def_id::DefIdMap; use rustc_hir::{ AmbigArg, Expr, ExprKind, ForeignItem, HirId, ImplItem, Item, ItemKind, OwnerId, Pat, Path, Stmt, TraitItem, Ty, @@ -60,7 +59,7 @@ declare_clippy_lint! { } pub struct DisallowedMacros { - disallowed: DefIdMap<(&'static str, Option<&'static str>)>, + disallowed: DefIdMap<(&'static str, &'static DisallowedPath)>, seen: FxHashSet, // Track the most recently seen node that can have a `derive` attribute. // Needed to use the correct lint level. @@ -91,13 +90,9 @@ impl DisallowedMacros { return; } - if let Some(&(path, reason)) = self.disallowed.get(&mac.def_id) { + if let Some(&(path, disallowed_path)) = self.disallowed.get(&mac.def_id) { let msg = format!("use of a disallowed macro `{path}`"); - let add_note = |diag: &mut Diag<'_, _>| { - if let Some(reason) = reason { - diag.note(reason); - } - }; + let add_note = disallowed_path.diag_amendment(mac.span); if matches!(mac.kind, MacroKind::Derive) && let Some(derive_src) = derive_src { diff --git a/clippy_lints/src/disallowed_methods.rs b/clippy_lints/src/disallowed_methods.rs index c4ed118b7c9f..149cf1cf2def 100644 --- a/clippy_lints/src/disallowed_methods.rs +++ b/clippy_lints/src/disallowed_methods.rs @@ -1,5 +1,5 @@ use clippy_config::Conf; -use clippy_config::types::create_disallowed_map; +use clippy_config::types::{DisallowedPath, create_disallowed_map}; use clippy_utils::diagnostics::span_lint_and_then; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefIdMap; @@ -31,6 +31,8 @@ declare_clippy_lint! { /// # When using an inline table, can add a `reason` for why the method /// # is disallowed. /// { path = "std::vec::Vec::leak", reason = "no leaking memory" }, + /// # Can also add a `replacement` that will be offered as a suggestion. + /// { path = "std::sync::Mutex::new", reason = "prefer faster & simpler non-poisonable mutex", replacement = "parking_lot::Mutex::new" }, /// ] /// ``` /// @@ -56,7 +58,7 @@ declare_clippy_lint! { } pub struct DisallowedMethods { - disallowed: DefIdMap<(&'static str, Option<&'static str>)>, + disallowed: DefIdMap<(&'static str, &'static DisallowedPath)>, } impl DisallowedMethods { @@ -83,17 +85,13 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedMethods { }, _ => return, }; - if let Some(&(path, reason)) = self.disallowed.get(&id) { + if let Some(&(path, disallowed_path)) = self.disallowed.get(&id) { span_lint_and_then( cx, DISALLOWED_METHODS, span, format!("use of a disallowed method `{path}`"), - |diag| { - if let Some(reason) = reason { - diag.note(reason); - } - }, + disallowed_path.diag_amendment(span), ); } } diff --git a/clippy_lints/src/disallowed_types.rs b/clippy_lints/src/disallowed_types.rs index 947677e14bd0..3659946b7042 100644 --- a/clippy_lints/src/disallowed_types.rs +++ b/clippy_lints/src/disallowed_types.rs @@ -1,4 +1,5 @@ use clippy_config::Conf; +use clippy_config::types::DisallowedPath; use clippy_utils::diagnostics::span_lint_and_then; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::Res; @@ -31,6 +32,8 @@ declare_clippy_lint! { /// # When using an inline table, can add a `reason` for why the type /// # is disallowed. /// { path = "std::net::Ipv4Addr", reason = "no IPv4 allowed" }, + /// # Can also add a `replacement` that will be offered as a suggestion. + /// { path = "std::sync::Mutex", reason = "prefer faster & simpler non-poisonable mutex", replacement = "parking_lot::Mutex" }, /// ] /// ``` /// @@ -51,24 +54,23 @@ declare_clippy_lint! { } pub struct DisallowedTypes { - def_ids: DefIdMap<(&'static str, Option<&'static str>)>, - prim_tys: FxHashMap)>, + def_ids: DefIdMap<(&'static str, &'static DisallowedPath)>, + prim_tys: FxHashMap, } impl DisallowedTypes { pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self { let mut def_ids = DefIdMap::default(); let mut prim_tys = FxHashMap::default(); - for x in &conf.disallowed_types { - let path: Vec<_> = x.path().split("::").collect::>(); - let reason = x.reason(); + for disallowed_path in &conf.disallowed_types { + let path: Vec<_> = disallowed_path.path().split("::").collect::>(); for res in clippy_utils::def_path_res(tcx, &path) { match res { Res::Def(_, id) => { - def_ids.insert(id, (x.path(), reason)); + def_ids.insert(id, (disallowed_path.path(), disallowed_path)); }, Res::PrimTy(ty) => { - prim_tys.insert(ty, (x.path(), reason)); + prim_tys.insert(ty, (disallowed_path.path(), disallowed_path)); }, _ => {}, } @@ -78,7 +80,7 @@ impl DisallowedTypes { } fn check_res_emit(&self, cx: &LateContext<'_>, res: &Res, span: Span) { - let (path, reason) = match res { + let (path, disallowed_path) = match res { Res::Def(_, did) if let Some(&x) = self.def_ids.get(did) => x, Res::PrimTy(prim) if let Some(&x) = self.prim_tys.get(prim) => x, _ => return, @@ -88,11 +90,7 @@ impl DisallowedTypes { DISALLOWED_TYPES, span, format!("use of a disallowed type `{path}`"), - |diag| { - if let Some(reason) = reason { - diag.note(reason); - } - }, + disallowed_path.diag_amendment(span), ); } } diff --git a/clippy_lints/src/doc/include_in_doc_without_cfg.rs b/clippy_lints/src/doc/include_in_doc_without_cfg.rs index aa29705cf938..bca1cd03bb7e 100644 --- a/clippy_lints/src/doc/include_in_doc_without_cfg.rs +++ b/clippy_lints/src/doc/include_in_doc_without_cfg.rs @@ -1,8 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_opt; +use rustc_ast::{AttrArgs, AttrKind, AttrStyle, Attribute}; use rustc_errors::Applicability; use rustc_lint::EarlyContext; -use rustc_ast::{Attribute, AttrKind, AttrArgs, AttrStyle}; use super::DOC_INCLUDE_WITHOUT_CFG; diff --git a/clippy_lints/src/doc/lazy_continuation.rs b/clippy_lints/src/doc/lazy_continuation.rs index 2577324f23df..8aeb835fe393 100644 --- a/clippy_lints/src/doc/lazy_continuation.rs +++ b/clippy_lints/src/doc/lazy_continuation.rs @@ -16,7 +16,6 @@ fn map_container_to_text(c: &super::Container) -> &'static str { } } -// TODO: Adjust the parameters as necessary pub(super) fn check( cx: &LateContext<'_>, doc: &str, diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index 42192801af7c..0296ff13112f 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -82,6 +82,28 @@ declare_clippy_lint! { "presence of `_`, `::` or camel-case outside backticks in documentation" } +declare_clippy_lint! { + /// ### What it does + /// Checks for links with code directly adjacent to code text: + /// `` [`MyItem`]`<`[`u32`]`>` ``. + /// + /// ### Why is this bad? + /// It can be written more simply using HTML-style `` tags. + /// + /// ### Example + /// ```no_run + /// //! [`first`](x)`second` + /// ``` + /// Use instead: + /// ```no_run + /// //! [first](x)second + /// ``` + #[clippy::version = "1.86.0"] + pub DOC_LINK_CODE, + nursery, + "link with code back-to-back with other code" +} + declare_clippy_lint! { /// ### What it does /// Checks for the doc comments of publicly visible @@ -453,7 +475,7 @@ declare_clippy_lint! { /// /// and this line is overindented. /// # fn foo() {} /// ``` - #[clippy::version = "1.80.0"] + #[clippy::version = "1.86.0"] pub DOC_OVERINDENTED_LIST_ITEMS, style, "ensure list items are not overindented" @@ -513,7 +535,7 @@ declare_clippy_lint! { /// ```no_run /// #![cfg_attr(doc, doc = include_str!("some_file.md"))] /// ``` - #[clippy::version = "1.84.0"] + #[clippy::version = "1.85.0"] pub DOC_INCLUDE_WITHOUT_CFG, restriction, "check if files included in documentation are behind `cfg(doc)`" @@ -539,7 +561,7 @@ declare_clippy_lint! { /// //! /// //! [link]: destination (for link reference definition) /// ``` - #[clippy::version = "1.84.0"] + #[clippy::version = "1.85.0"] pub DOC_NESTED_REFDEFS, suspicious, "link reference defined in list item or quote" @@ -560,6 +582,7 @@ impl Documentation { } impl_lint_pass!(Documentation => [ + DOC_LINK_CODE, DOC_LINK_WITH_QUOTES, DOC_MARKDOWN, DOC_NESTED_REFDEFS, @@ -577,7 +600,6 @@ impl_lint_pass!(Documentation => [ DOC_INCLUDE_WITHOUT_CFG, ]); - impl EarlyLintPass for Documentation { fn check_attributes(&mut self, cx: &EarlyContext<'_>, attrs: &[rustc_ast::Attribute]) { include_in_doc_without_cfg::check(cx, attrs); @@ -717,7 +739,7 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet, attrs: &[ let (fragments, _) = attrs_to_doc_fragments( attrs.iter().filter_map(|attr| { - if !attr.doc_str_and_comment_kind().is_some() || attr.span().in_external_macro(cx.sess().source_map()) { + if attr.doc_str_and_comment_kind().is_none() || attr.span().in_external_macro(cx.sess().source_map()) { None } else { Some((attr, None)) @@ -747,6 +769,21 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet, attrs: &[ let mut cb = fake_broken_link_callback; + check_for_code_clusters( + cx, + pulldown_cmark::Parser::new_with_broken_link_callback( + &doc, + main_body_opts() - Options::ENABLE_SMART_PUNCTUATION, + Some(&mut cb), + ) + .into_offset_iter(), + &doc, + Fragments { + doc: &doc, + fragments: &fragments, + }, + ); + // disable smart punctuation to pick up ['link'] more easily let opts = main_body_opts() - Options::ENABLE_SMART_PUNCTUATION; let parser = pulldown_cmark::Parser::new_with_broken_link_callback(&doc, opts, Some(&mut cb)); @@ -770,6 +807,66 @@ enum Container { List(usize), } +/// Scan the documentation for code links that are back-to-back with code spans. +/// +/// This is done separately from the rest of the docs, because that makes it easier to produce +/// the correct messages. +fn check_for_code_clusters<'a, Events: Iterator, Range)>>( + cx: &LateContext<'_>, + events: Events, + doc: &str, + fragments: Fragments<'_>, +) { + let mut events = events.peekable(); + let mut code_starts_at = None; + let mut code_ends_at = None; + let mut code_includes_link = false; + while let Some((event, range)) = events.next() { + match event { + Start(Link { .. }) if matches!(events.peek(), Some((Code(_), _range))) => { + if code_starts_at.is_some() { + code_ends_at = Some(range.end); + } else { + code_starts_at = Some(range.start); + } + code_includes_link = true; + // skip the nested "code", because we're already handling it here + let _ = events.next(); + }, + Code(_) => { + if code_starts_at.is_some() { + code_ends_at = Some(range.end); + } else { + code_starts_at = Some(range.start); + } + }, + End(TagEnd::Link) => {}, + _ => { + if let Some(start) = code_starts_at + && let Some(end) = code_ends_at + && code_includes_link + { + if let Some(span) = fragments.span(cx, start..end) { + span_lint_and_then(cx, DOC_LINK_CODE, span, "code link adjacent to code text", |diag| { + let sugg = format!("{}", doc[start..end].replace('`', "")); + diag.span_suggestion_verbose( + span, + "wrap the entire group in `` tags", + sugg, + Applicability::MaybeIncorrect, + ); + diag.help("separate code snippets will be shown with a gap"); + }); + } + } + code_includes_link = false; + code_starts_at = None; + code_ends_at = None; + }, + } + } +} + /// Checks parsed documentation. /// This walks the "events" (think sections of markdown) produced by `pulldown_cmark`, /// so lints here will generally access that information. @@ -912,7 +1009,12 @@ fn check_doc<'a, Events: Iterator, Range range.start { + start - range.start + } else { + 0 + } } } else { 0 @@ -1092,6 +1194,10 @@ impl<'tcx> Visitor<'tcx> for FindPanicUnwrap<'_, 'tcx> { #[expect(clippy::range_plus_one)] // inclusive ranges aren't the same type fn looks_like_refdef(doc: &str, range: Range) -> Option> { + if range.end < range.start { + return None; + } + let offset = range.start; let mut iterator = doc.as_bytes()[range].iter().copied().enumerate(); let mut start = None; diff --git a/clippy_lints/src/doc/needless_doctest_main.rs b/clippy_lints/src/doc/needless_doctest_main.rs index ce5beab24bfa..3008082c2329 100644 --- a/clippy_lints/src/doc/needless_doctest_main.rs +++ b/clippy_lints/src/doc/needless_doctest_main.rs @@ -1,6 +1,6 @@ use std::ops::Range; -use std::{io, thread}; use std::sync::Arc; +use std::{io, thread}; use crate::doc::{NEEDLESS_DOCTEST_MAIN, TEST_ATTR_IN_DOCTEST}; use clippy_utils::diagnostics::span_lint; diff --git a/clippy_lints/src/doc/suspicious_doc_comments.rs b/clippy_lints/src/doc/suspicious_doc_comments.rs index bfc36deea7b2..9637546b8680 100644 --- a/clippy_lints/src/doc/suspicious_doc_comments.rs +++ b/clippy_lints/src/doc/suspicious_doc_comments.rs @@ -1,9 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_then; use rustc_ast::AttrStyle; use rustc_ast::token::CommentKind; +use rustc_attr_parsing::AttributeKind; use rustc_errors::Applicability; use rustc_hir::Attribute; -use rustc_attr_parsing::AttributeKind; use rustc_lint::LateContext; use rustc_span::Span; @@ -37,7 +37,12 @@ fn collect_doc_replacements(attrs: &[Attribute]) -> Vec<(Span, String)> { attrs .iter() .filter_map(|attr| { - if let Attribute::Parsed(AttributeKind::DocComment{ style: AttrStyle::Outer, kind, comment, ..}) = attr + if let Attribute::Parsed(AttributeKind::DocComment { + style: AttrStyle::Outer, + kind, + comment, + .. + }) = attr && let Some(com) = comment.as_str().strip_prefix('!') { let sugg = match kind { diff --git a/clippy_lints/src/doc/too_long_first_doc_paragraph.rs b/clippy_lints/src/doc/too_long_first_doc_paragraph.rs index 1eda73a96727..dc6cbb425430 100644 --- a/clippy_lints/src/doc/too_long_first_doc_paragraph.rs +++ b/clippy_lints/src/doc/too_long_first_doc_paragraph.rs @@ -1,6 +1,6 @@ +use rustc_attr_parsing::AttributeKind; use rustc_errors::Applicability; use rustc_hir::{Attribute, Item, ItemKind}; -use rustc_attr_parsing::AttributeKind; use rustc_lint::LateContext; use clippy_utils::diagnostics::span_lint_and_then; @@ -44,7 +44,7 @@ pub(super) fn check( let mut should_suggest_empty_doc = false; for attr in attrs { - if let Attribute::Parsed(AttributeKind::DocComment {span, comment, ..}) = attr { + if let Attribute::Parsed(AttributeKind::DocComment { span, comment, .. }) = attr { spans.push(span); let doc = comment.as_str(); let doc = doc.trim(); @@ -52,7 +52,11 @@ pub(super) fn check( // We make this suggestion only if the first doc line ends with a punctuation // because it might just need to add an empty line with `///`. should_suggest_empty_doc = doc.ends_with('.') || doc.ends_with('!') || doc.ends_with('?'); + } else if spans.len() == 2 { + // We make this suggestion only if the second doc line is not empty. + should_suggest_empty_doc &= !doc.is_empty(); } + let len = doc.chars().count(); if len >= first_paragraph_len { break; diff --git a/clippy_lints/src/empty_line_after.rs b/clippy_lints/src/empty_line_after.rs index 578ff6e38a6a..80c2b03c41cf 100644 --- a/clippy_lints/src/empty_line_after.rs +++ b/clippy_lints/src/empty_line_after.rs @@ -289,10 +289,13 @@ impl EmptyLineAfter { format!("empty {lines} after {kind_desc}"), |diag| { let info = self.items.last().unwrap(); - diag.span_label(info.span, match kind { - StopKind::Attr => format!("the attribute applies to this {}", info.kind), - StopKind::Doc(_) => format!("the comment documents this {}", info.kind), - }); + diag.span_label( + info.span, + match kind { + StopKind::Attr => format!("the attribute applies to this {}", info.kind), + StopKind::Doc(_) => format!("the comment documents this {}", info.kind), + }, + ); diag.multipart_suggestion_with_style( format!("if the empty {lines} {are} unintentional, remove {them}"), diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 2bec4f2f99e5..f404bc59b3b8 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -1,5 +1,6 @@ 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::visitors::for_each_expr; use clippy_utils::{ SpanlessEq, can_move_expr_to_closure_no_visit, higher, is_expr_final_block_expr, is_expr_used_or_unified, peel_hir_expr_while, @@ -7,11 +8,12 @@ use clippy_utils::{ use core::fmt::{self, Write}; use rustc_errors::Applicability; use rustc_hir::hir_id::HirIdSet; -use rustc_hir::intravisit::{Visitor, walk_expr}; +use rustc_hir::intravisit::{Visitor, walk_body, walk_expr}; 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::{DUMMY_SP, Span, SyntaxContext, sym}; +use std::ops::ControlFlow; declare_clippy_lint! { /// ### What it does @@ -135,8 +137,8 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass { format!( "match {map_str}.entry({key_str}) {{\n{indent_str} {entry}::{then_entry} => {}\n\ {indent_str} {entry}::{else_entry} => {}\n{indent_str}}}", - reindent_multiline(then_str.into(), true, Some(4 + indent_str.len())), - reindent_multiline(else_str.into(), true, Some(4 + indent_str.len())), + reindent_multiline(&then_str, true, Some(4 + indent_str.len())), + reindent_multiline(&else_str, true, Some(4 + indent_str.len())), entry = map_ty.entry_path(), ) } @@ -329,7 +331,7 @@ impl<'tcx> Edit<'tcx> { if let Self::Insertion(i) = self { Some(i) } else { None } } } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] struct Insertion<'tcx> { call: &'tcx Expr<'tcx>, value: &'tcx Expr<'tcx>, @@ -500,7 +502,7 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { self.visit_non_tail_expr(insert_expr.value); self.is_single_insert = is_single_insert; }, - _ if SpanlessEq::new(self.cx).eq_expr(self.map, expr) => { + _ if is_any_expr_in_map_used(self.cx, self.map, expr) => { self.is_map_used = true; }, _ => match expr.kind { @@ -542,6 +544,7 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { ExprKind::InlineAsm(_) => { self.can_use_entry = false; }, + ExprKind::Closure(closure) => walk_body(self, self.cx.tcx.hir_body(closure.body)), _ => { self.allow_insert_closure &= !self.in_tail_pos; self.allow_insert_closure &= @@ -562,6 +565,19 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { } } +/// Check if the given expression is used for each sub-expression in the given map. +/// For example, in map `a.b.c.my_map`, The expression `a.b.c.my_map`, `a.b.c`, `a.b`, and `a` are +/// all checked. +fn is_any_expr_in_map_used<'tcx>(cx: &LateContext<'tcx>, map: &'tcx Expr<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { + for_each_expr(cx, map, |e| { + if SpanlessEq::new(cx).eq_expr(e, expr) { + return ControlFlow::Break(()); + } + ControlFlow::Continue(()) + }) + .is_some() +} + struct InsertSearchResults<'tcx> { edits: Vec>, allow_insert_closure: bool, diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 0c06c9117d73..8d1e893cb1af 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -1,5 +1,6 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_hir; +use rustc_abi::ExternAbi; use rustc_hir::{AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node, Pat, PatKind, intravisit}; use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; use rustc_lint::{LateContext, LateLintPass}; @@ -10,7 +11,6 @@ use rustc_session::impl_lint_pass; use rustc_span::Span; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::kw; -use rustc_abi::ExternAbi; pub struct BoxedLocal { too_large_for_stack: u64, diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index d1782d582f4d..645f93068496 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -6,6 +6,7 @@ use clippy_utils::usage::{local_used_after_expr, local_used_in}; use clippy_utils::{ get_path_from_caller_to_method_type, is_adjusted, is_no_std_crate, path_to_local, path_to_local_id, }; +use rustc_abi::ExternAbi; use rustc_errors::Applicability; use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, GenericArgs, Param, PatKind, QPath, Safety, TyKind}; use rustc_infer::infer::TyCtxtInferExt; @@ -15,7 +16,6 @@ use rustc_middle::ty::{ }; use rustc_session::declare_lint_pass; use rustc_span::symbol::sym; -use rustc_abi::ExternAbi; use rustc_trait_selection::error_reporting::InferCtxtErrorExt as _; declare_clippy_lint! { diff --git a/clippy_lints/src/excessive_bools.rs b/clippy_lints/src/excessive_bools.rs index 15afe3e8c145..54a1ac21c85c 100644 --- a/clippy_lints/src/excessive_bools.rs +++ b/clippy_lints/src/excessive_bools.rs @@ -1,13 +1,13 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::{get_parent_as_impl, has_repr_attr, is_bool}; +use rustc_abi::ExternAbi; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, FnDecl, Item, ItemKind, TraitFn, TraitItem, TraitItemKind, Ty}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::Span; use rustc_span::def_id::LocalDefId; -use rustc_abi::ExternAbi; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs index da5825b7ab21..fc5f76179f90 100644 --- a/clippy_lints/src/format_args.rs +++ b/clippy_lints/src/format_args.rs @@ -1,26 +1,28 @@ use arrayvec::ArrayVec; use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; -use clippy_utils::is_diag_trait_item; use clippy_utils::macros::{ FormatArgsStorage, FormatParamUsage, MacroCall, find_format_arg_expr, format_arg_removal_span, format_placeholder_format_span, is_assert_macro, is_format_macro, is_panic, matching_root_macro_call, root_macro_call_first_node, }; use clippy_utils::msrvs::{self, Msrv}; -use clippy_utils::source::SpanRangeExt; +use clippy_utils::source::{SpanRangeExt, snippet}; use clippy_utils::ty::{implements_trait, is_type_lang_item}; +use clippy_utils::{is_diag_trait_item, is_from_proc_macro}; use itertools::Itertools; use rustc_ast::{ FormatArgPosition, FormatArgPositionKind, FormatArgsPiece, FormatArgumentKind, FormatCount, FormatOptions, FormatPlaceholder, FormatTrait, }; +use rustc_attr_parsing::RustcVersion; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; use rustc_errors::SuggestionStyle::{CompletelyHidden, ShowCode}; use rustc_hir::{Expr, ExprKind, LangItem}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::ty::Ty; use rustc_middle::ty::adjustment::{Adjust, Adjustment}; +use rustc_middle::ty::{List, Ty, TyCtxt}; use rustc_session::impl_lint_pass; use rustc_span::edition::Edition::Edition2021; use rustc_span::{Span, Symbol, sym}; @@ -50,6 +52,36 @@ declare_clippy_lint! { "`format!` used in a macro that does formatting" } +declare_clippy_lint! { + /// ### What it does + /// Checks for `Debug` formatting (`{:?}`) applied to an `OsStr` or `Path`. + /// + /// ### Why is this bad? + /// Rust doesn't guarantee what `Debug` formatting looks like, and it could + /// change in the future. `OsStr`s and `Path`s can be `Display` formatted + /// using their `display` methods. + /// + /// Furthermore, with `Debug` formatting, certain characters are escaped. + /// Thus, a `Debug` formatted `Path` is less likely to be clickable. + /// + /// ### Example + /// ```no_run + /// # use std::path::Path; + /// let path = Path::new("..."); + /// println!("The path is {:?}", path); + /// ``` + /// Use instead: + /// ```no_run + /// # use std::path::Path; + /// let path = Path::new("…"); + /// println!("The path is {}", path.display()); + /// ``` + #[clippy::version = "1.87.0"] + pub UNNECESSARY_DEBUG_FORMATTING, + pedantic, + "`Debug` formatting applied to an `OsStr` or `Path` when `.display()` is available" +} + declare_clippy_lint! { /// ### What it does /// Checks for [`ToString::to_string`](https://doc.rust-lang.org/std/string/trait.ToString.html#tymethod.to_string) @@ -162,31 +194,35 @@ declare_clippy_lint! { "use of a format specifier that has no effect" } -impl_lint_pass!(FormatArgs => [ +impl_lint_pass!(FormatArgs<'_> => [ FORMAT_IN_FORMAT_ARGS, TO_STRING_IN_FORMAT_ARGS, UNINLINED_FORMAT_ARGS, + UNNECESSARY_DEBUG_FORMATTING, UNUSED_FORMAT_SPECS, ]); #[allow(clippy::struct_field_names)] -pub struct FormatArgs { +pub struct FormatArgs<'tcx> { format_args: FormatArgsStorage, msrv: Msrv, ignore_mixed: bool, + ty_msrv_map: FxHashMap, Option>, } -impl FormatArgs { - pub fn new(conf: &'static Conf, format_args: FormatArgsStorage) -> Self { +impl<'tcx> FormatArgs<'tcx> { + pub fn new(tcx: TyCtxt<'tcx>, conf: &'static Conf, format_args: FormatArgsStorage) -> Self { + let ty_msrv_map = make_ty_msrv_map(tcx); Self { format_args, - msrv: conf.msrv.clone(), + msrv: conf.msrv, ignore_mixed: conf.allow_mixed_uninlined_format_args, + ty_msrv_map, } } } -impl<'tcx> LateLintPass<'tcx> for FormatArgs { +impl<'tcx> LateLintPass<'tcx> for FormatArgs<'tcx> { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if let Some(macro_call) = root_macro_call_first_node(cx, expr) && is_format_macro(cx, macro_call.def_id) @@ -198,17 +234,17 @@ impl<'tcx> LateLintPass<'tcx> for FormatArgs { macro_call: ¯o_call, format_args, ignore_mixed: self.ignore_mixed, + msrv: &self.msrv, + ty_msrv_map: &self.ty_msrv_map, }; linter.check_templates(); - if self.msrv.meets(msrvs::FORMAT_ARGS_CAPTURE) { + if self.msrv.meets(cx, msrvs::FORMAT_ARGS_CAPTURE) { linter.check_uninlined_args(); } } } - - extract_msrv_attr!(LateContext); } struct FormatArgsExpr<'a, 'tcx> { @@ -217,9 +253,11 @@ struct FormatArgsExpr<'a, 'tcx> { macro_call: &'a MacroCall, format_args: &'a rustc_ast::FormatArgs, ignore_mixed: bool, + msrv: &'a Msrv, + ty_msrv_map: &'a FxHashMap, Option>, } -impl FormatArgsExpr<'_, '_> { +impl<'tcx> FormatArgsExpr<'_, 'tcx> { fn check_templates(&self) { for piece in &self.format_args.template { if let FormatArgsPiece::Placeholder(placeholder) = piece @@ -237,6 +275,11 @@ impl FormatArgsExpr<'_, '_> { self.check_format_in_format_args(name, arg_expr); self.check_to_string_in_format_args(name, arg_expr); } + + if placeholder.format_trait == FormatTrait::Debug { + let name = self.cx.tcx.item_name(self.macro_call.def_id); + self.check_unnecessary_debug_formatting(name, arg_expr); + } } } } @@ -439,6 +482,33 @@ impl FormatArgsExpr<'_, '_> { } } + fn check_unnecessary_debug_formatting(&self, name: Symbol, value: &Expr<'tcx>) { + let cx = self.cx; + if !value.span.from_expansion() + && !is_from_proc_macro(cx, value) + && let ty = cx.typeck_results().expr_ty(value) + && self.can_display_format(ty) + { + let snippet = snippet(cx.sess(), value.span, ".."); + span_lint_and_then( + cx, + UNNECESSARY_DEBUG_FORMATTING, + value.span, + format!("unnecessary `Debug` formatting in `{name}!` args"), + |diag| { + diag.help(format!( + "use `Display` formatting and change this to `{snippet}.display()`" + )); + diag.note( + "switching to `Display` formatting will change how the value is shown; \ + escaped characters will no longer be escaped and surrounding quotes will \ + be removed", + ); + }, + ); + } + } + fn format_arg_positions(&self) -> impl Iterator { self.format_args.template.iter().flat_map(|piece| match piece { FormatArgsPiece::Placeholder(placeholder) => { @@ -465,6 +535,41 @@ impl FormatArgsExpr<'_, '_> { .at_most_one() .is_err() } + + fn can_display_format(&self, ty: Ty<'tcx>) -> bool { + let ty = ty.peel_refs(); + + if let Some(msrv) = self.ty_msrv_map.get(&ty) + && msrv.is_none_or(|msrv| self.msrv.meets(self.cx, msrv)) + { + return true; + } + + // Even if `ty` is not in `self.ty_msrv_map`, check whether `ty` implements `Deref` with + // a `Target` that is in `self.ty_msrv_map`. + if let Some(deref_trait_id) = self.cx.tcx.lang_items().deref_trait() + && implements_trait(self.cx, ty, deref_trait_id, &[]) + && let Some(target_ty) = self.cx.get_associated_type(ty, deref_trait_id, "Target") + && let Some(msrv) = self.ty_msrv_map.get(&target_ty) + && msrv.is_none_or(|msrv| self.msrv.meets(self.cx, msrv)) + { + return true; + } + + false + } +} + +fn make_ty_msrv_map(tcx: TyCtxt<'_>) -> FxHashMap, Option> { + [(sym::OsStr, Some(msrvs::OS_STR_DISPLAY)), (sym::Path, None)] + .into_iter() + .filter_map(|(name, feature)| { + tcx.get_diagnostic_item(name).map(|def_id| { + let ty = Ty::new_adt(tcx, tcx.adt_def(def_id), List::empty()); + (ty, feature) + }) + }) + .collect() } fn count_needed_derefs<'tcx, I>(mut ty: Ty<'tcx>, mut iter: I) -> (usize, Ty<'tcx>) diff --git a/clippy_lints/src/from_over_into.rs b/clippy_lints/src/from_over_into.rs index 41bf6e81916a..6da5567d9c70 100644 --- a/clippy_lints/src/from_over_into.rs +++ b/clippy_lints/src/from_over_into.rs @@ -58,9 +58,7 @@ pub struct FromOverInto { impl FromOverInto { pub fn new(conf: &'static Conf) -> Self { - FromOverInto { - msrv: conf.msrv.clone(), - } + FromOverInto { msrv: conf.msrv } } } @@ -77,12 +75,12 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto { && let Some(into_trait_seg) = hir_trait_ref.path.segments.last() // `impl Into for self_ty` && let Some(GenericArgs { args: [GenericArg::Type(target_ty)], .. }) = into_trait_seg.args - && self.msrv.meets(msrvs::RE_REBALANCING_COHERENCE) && span_is_local(item.span) && let Some(middle_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id) - .map(ty::EarlyBinder::instantiate_identity) + .map(ty::EarlyBinder::instantiate_identity) && cx.tcx.is_diagnostic_item(sym::Into, middle_trait_ref.def_id) && !matches!(middle_trait_ref.args.type_at(1).kind(), ty::Alias(ty::Opaque, _)) + && self.msrv.meets(cx, msrvs::RE_REBALANCING_COHERENCE) { span_lint_and_then( cx, @@ -114,8 +112,6 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto { ); } } - - extract_msrv_attr!(LateContext); } /// Finds the occurrences of `Self` and `self` diff --git a/clippy_lints/src/functions/mod.rs b/clippy_lints/src/functions/mod.rs index 243eb5cbfd40..5f3fc5100e75 100644 --- a/clippy_lints/src/functions/mod.rs +++ b/clippy_lints/src/functions/mod.rs @@ -471,7 +471,7 @@ impl Functions { .iter() .flat_map(|p| def_path_def_ids(tcx, &p.split("::").collect::>())) .collect(), - msrv: conf.msrv.clone(), + msrv: conf.msrv, } } } @@ -521,12 +521,12 @@ impl<'tcx> LateLintPass<'tcx> for Functions { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { must_use::check_item(cx, item); - result::check_item(cx, item, self.large_error_threshold, &self.msrv); + result::check_item(cx, item, self.large_error_threshold, self.msrv); } fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) { must_use::check_impl_item(cx, item); - result::check_impl_item(cx, item, self.large_error_threshold, &self.msrv); + result::check_impl_item(cx, item, self.large_error_threshold, self.msrv); impl_trait_in_params::check_impl_item(cx, item); renamed_function_params::check_impl_item(cx, item, &self.trait_ids); } @@ -535,10 +535,8 @@ impl<'tcx> LateLintPass<'tcx> for Functions { too_many_arguments::check_trait_item(cx, item, self.too_many_arguments_threshold); not_unsafe_ptr_arg_deref::check_trait_item(cx, item); must_use::check_trait_item(cx, item); - result::check_trait_item(cx, item, self.large_error_threshold, &self.msrv); + result::check_trait_item(cx, item, self.large_error_threshold, self.msrv); impl_trait_in_params::check_trait_item(cx, item, self.avoid_breaking_exported_api); ref_option::check_trait_item(cx, item, self.avoid_breaking_exported_api); } - - extract_msrv_attr!(LateContext); } diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs index 0ed4426d6e92..f1c9657f2240 100644 --- a/clippy_lints/src/functions/must_use.rs +++ b/clippy_lints/src/functions/must_use.rs @@ -118,18 +118,23 @@ fn check_needless_must_use( fn_header_span, "this unit-returning function has a `#[must_use]` attribute", |diag| { - diag.span_suggestion(attr.span(), "remove the attribute", "", Applicability::MachineApplicable); + diag.span_suggestion( + attr.span(), + "remove the attribute", + "", + Applicability::MachineApplicable, + ); }, ); } else { // When there are multiple attributes, it is not sufficient to simply make `must_use` empty, see // issue #12320. // FIXME(jdonszelmann): this used to give a machine-applicable fix. However, it was super fragile, - // honestly looked incorrect, and is a little hard to support for a little bit now. Some day this could be - // re-added. + // honestly looked incorrect, and is a little hard to support for a little bit now. Some day this + // could be re-added. span_lint_and_help( cx, - DOUBLE_MUST_USE, + MUST_USE_UNIT, fn_header_span, "this unit-returning function has a `#[must_use]` attribute", Some(attr.span()), diff --git a/clippy_lints/src/functions/result.rs b/clippy_lints/src/functions/result.rs index 74d365a72556..cade56f58226 100644 --- a/clippy_lints/src/functions/result.rs +++ b/clippy_lints/src/functions/result.rs @@ -34,7 +34,7 @@ fn result_err_ty<'tcx>( } } -pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::Item<'tcx>, large_err_threshold: u64, msrv: &Msrv) { +pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::Item<'tcx>, large_err_threshold: u64, msrv: Msrv) { if let hir::ItemKind::Fn { ref sig, .. } = item.kind && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.owner_id.def_id, item.span) { @@ -50,7 +50,7 @@ pub(super) fn check_impl_item<'tcx>( cx: &LateContext<'tcx>, item: &hir::ImplItem<'tcx>, large_err_threshold: u64, - msrv: &Msrv, + msrv: Msrv, ) { // Don't lint if method is a trait's implementation, we can't do anything about those if let hir::ImplItemKind::Fn(ref sig, _) = item.kind @@ -69,7 +69,7 @@ pub(super) fn check_trait_item<'tcx>( cx: &LateContext<'tcx>, item: &hir::TraitItem<'tcx>, large_err_threshold: u64, - msrv: &Msrv, + msrv: Msrv, ) { if let hir::TraitItemKind::Fn(ref sig, _) = item.kind { let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); @@ -82,8 +82,8 @@ pub(super) fn check_trait_item<'tcx>( } } -fn check_result_unit_err(cx: &LateContext<'_>, err_ty: Ty<'_>, fn_header_span: Span, msrv: &Msrv) { - if err_ty.is_unit() && (!is_no_std_crate(cx) || msrv.meets(msrvs::ERROR_IN_CORE)) { +fn check_result_unit_err(cx: &LateContext<'_>, err_ty: Ty<'_>, fn_header_span: Span, msrv: Msrv) { + if err_ty.is_unit() && (!is_no_std_crate(cx) || msrv.meets(cx, msrvs::ERROR_IN_CORE)) { span_lint_and_help( cx, RESULT_UNIT_ERR, diff --git a/clippy_lints/src/functions/too_many_arguments.rs b/clippy_lints/src/functions/too_many_arguments.rs index f17f687719f2..05dc47f6fe58 100644 --- a/clippy_lints/src/functions/too_many_arguments.rs +++ b/clippy_lints/src/functions/too_many_arguments.rs @@ -1,7 +1,7 @@ +use rustc_abi::ExternAbi; use rustc_hir::{self as hir, intravisit}; use rustc_lint::LateContext; use rustc_span::Span; -use rustc_abi::ExternAbi; use clippy_utils::diagnostics::span_lint; use clippy_utils::is_trait_impl_item; @@ -23,11 +23,19 @@ pub(super) fn check_fn( intravisit::FnKind::Method( _, &hir::FnSig { - header: hir::FnHeader { abi: ExternAbi::Rust, .. }, + header: hir::FnHeader { + abi: ExternAbi::Rust, .. + }, .. }, ) - | intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: ExternAbi::Rust, .. }) => check_arg_number( + | intravisit::FnKind::ItemFn( + _, + _, + hir::FnHeader { + abi: ExternAbi::Rust, .. + }, + ) => check_arg_number( cx, decl, span.with_hi(decl.output.span().hi()), diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index 2806d4d0e5d6..45f9aa0a53e4 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -7,7 +7,6 @@ use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::Span; -use std::borrow::Cow; declare_clippy_lint! { /// ### What it does @@ -107,7 +106,7 @@ fn make_sugg<'a>( els_span: Span, default: &'a str, indent_relative_to: Option, -) -> Cow<'a, str> { +) -> String { let cond_inner_snip = snippet(sess, cond_inner, default); let els_snip = snippet(sess, els_span, default); let indent = indent_relative_to.and_then(|s| indent_of(sess, s)); @@ -130,5 +129,5 @@ fn make_sugg<'a>( _ => String::new(), }; - reindent_multiline(suggestion.into(), true, indent) + reindent_multiline(&suggestion, true, indent) } diff --git a/clippy_lints/src/if_then_some_else_none.rs b/clippy_lints/src/if_then_some_else_none.rs index 51e2944e6f99..fbbd33efd02d 100644 --- a/clippy_lints/src/if_then_some_else_none.rs +++ b/clippy_lints/src/if_then_some_else_none.rs @@ -54,9 +54,7 @@ pub struct IfThenSomeElseNone { impl IfThenSomeElseNone { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -79,10 +77,10 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone { && !is_else_clause(cx.tcx, expr) && !is_in_const_context(cx) && !expr.span.in_external_macro(cx.sess().source_map()) - && self.msrv.meets(msrvs::BOOL_THEN) + && self.msrv.meets(cx, msrvs::BOOL_THEN) && !contains_return(then_block.stmts) { - let method_name = if switch_to_eager_eval(cx, expr) && self.msrv.meets(msrvs::BOOL_THEN_SOME) { + let method_name = if switch_to_eager_eval(cx, expr) && self.msrv.meets(cx, msrvs::BOOL_THEN_SOME) { "then_some" } else { "then" @@ -94,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone { expr.span, format!("this could be simplified with `bool::{method_name}`"), |diag| { - let mut app = Applicability::Unspecified; + let mut app = Applicability::MachineApplicable; let cond_snip = Sugg::hir_with_context(cx, cond, expr.span.ctxt(), "[condition]", &mut app) .maybe_par() .to_string(); @@ -120,6 +118,4 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone { ); } } - - extract_msrv_attr!(LateContext); } diff --git a/clippy_lints/src/implicit_saturating_sub.rs b/clippy_lints/src/implicit_saturating_sub.rs index 152d506a7c00..f2d16ff2e564 100644 --- a/clippy_lints/src/implicit_saturating_sub.rs +++ b/clippy_lints/src/implicit_saturating_sub.rs @@ -83,9 +83,7 @@ impl_lint_pass!(ImplicitSaturatingSub => [IMPLICIT_SATURATING_SUB, INVERTED_SATU impl ImplicitSaturatingSub { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -108,12 +106,10 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { && let ExprKind::Binary(ref cond_op, cond_left, cond_right) = cond.kind { check_manual_check( - cx, expr, cond_op, cond_left, cond_right, if_block, else_block, &self.msrv, + cx, expr, cond_op, cond_left, cond_right, if_block, else_block, self.msrv, ); } } - - extract_msrv_attr!(LateContext); } #[allow(clippy::too_many_arguments)] @@ -125,7 +121,7 @@ fn check_manual_check<'tcx>( right_hand: &Expr<'tcx>, if_block: &Expr<'tcx>, else_block: &Expr<'tcx>, - msrv: &Msrv, + msrv: Msrv, ) { let ty = cx.typeck_results().expr_ty(left_hand); if ty.is_numeric() && !ty.is_signed() { @@ -178,7 +174,7 @@ fn check_gt( little_var: &Expr<'_>, if_block: &Expr<'_>, else_block: &Expr<'_>, - msrv: &Msrv, + msrv: Msrv, is_composited: bool, ) { if let Some(big_var) = Var::new(big_var) @@ -221,7 +217,7 @@ fn check_subtraction( little_var: Var, if_block: &Expr<'_>, else_block: &Expr<'_>, - msrv: &Msrv, + msrv: Msrv, is_composited: bool, ) { let if_block = peel_blocks(if_block); @@ -258,7 +254,7 @@ fn check_subtraction( // if `snippet_opt` fails, it won't try the next conditions. if let Some(big_var_snippet) = snippet_opt(cx, big_var.span) && let Some(little_var_snippet) = snippet_opt(cx, little_var.span) - && (!is_in_const_context(cx) || msrv.meets(msrvs::SATURATING_SUB_CONST)) + && (!is_in_const_context(cx) || msrv.meets(cx, msrvs::SATURATING_SUB_CONST)) { let sugg = format!( "{}{big_var_snippet}.saturating_sub({little_var_snippet}){}", diff --git a/clippy_lints/src/incompatible_msrv.rs b/clippy_lints/src/incompatible_msrv.rs index b10206dcd05e..12dfb14c454d 100644 --- a/clippy_lints/src/incompatible_msrv.rs +++ b/clippy_lints/src/incompatible_msrv.rs @@ -42,6 +42,7 @@ declare_clippy_lint! { pub struct IncompatibleMsrv { msrv: Msrv, is_above_msrv: FxHashMap, + check_in_tests: bool, } impl_lint_pass!(IncompatibleMsrv => [INCOMPATIBLE_MSRV]); @@ -49,8 +50,9 @@ impl_lint_pass!(IncompatibleMsrv => [INCOMPATIBLE_MSRV]); impl IncompatibleMsrv { pub fn new(conf: &'static Conf) -> Self { Self { - msrv: conf.msrv.clone(), + msrv: conf.msrv, is_above_msrv: FxHashMap::default(), + check_in_tests: conf.check_incompatible_msrv_in_tests, } } @@ -86,39 +88,30 @@ impl IncompatibleMsrv { // We don't check local items since their MSRV is supposed to always be valid. return; } - let version = self.get_def_id_version(cx.tcx, def_id); - if self.msrv.meets(version) || is_in_test(cx.tcx, node) { - return; - } if let ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) = span.ctxt().outer_expn_data().kind { // Desugared expressions get to cheat and stability is ignored. // Intentionally not using `.from_expansion()`, since we do still care about macro expansions return; } - self.emit_lint_for(cx, span, version); - } - - fn emit_lint_for(&self, cx: &LateContext<'_>, span: Span, version: RustcVersion) { - span_lint( - cx, - INCOMPATIBLE_MSRV, - span, - format!( - "current MSRV (Minimum Supported Rust Version) is `{}` but this item is stable since `{version}`", - self.msrv - ), - ); + if (self.check_in_tests || !is_in_test(cx.tcx, node)) + && let Some(current) = self.msrv.current(cx) + && let version = self.get_def_id_version(cx.tcx, def_id) + && version > current + { + span_lint( + cx, + INCOMPATIBLE_MSRV, + span, + format!( + "current MSRV (Minimum Supported Rust Version) is `{current}` but this item is stable since `{version}`" + ), + ); + } } } impl<'tcx> LateLintPass<'tcx> for IncompatibleMsrv { - extract_msrv_attr!(LateContext); - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - if self.msrv.current().is_none() { - // If there is no MSRV, then no need to check anything... - return; - } match expr.kind { ExprKind::MethodCall(_, _, _, span) => { if let Some(method_did) = cx.typeck_results().type_dependent_def_id(expr.hir_id) { diff --git a/clippy_lints/src/index_refutable_slice.rs b/clippy_lints/src/index_refutable_slice.rs index deac51ab4c49..d53e139de014 100644 --- a/clippy_lints/src/index_refutable_slice.rs +++ b/clippy_lints/src/index_refutable_slice.rs @@ -62,7 +62,7 @@ impl IndexRefutableSlice { pub fn new(conf: &'static Conf) -> Self { Self { max_suggested_slice: conf.max_suggested_slice_pattern_length, - msrv: conf.msrv.clone(), + msrv: conf.msrv, } } } @@ -74,19 +74,17 @@ impl<'tcx> LateLintPass<'tcx> for IndexRefutableSlice { if let Some(IfLet { let_pat, if_then, .. }) = IfLet::hir(cx, expr) && (!expr.span.from_expansion() || is_expn_of(expr.span, "if_chain").is_some()) && !is_lint_allowed(cx, INDEX_REFUTABLE_SLICE, expr.hir_id) - && self.msrv.meets(msrvs::SLICE_PATTERNS) && let found_slices = find_slice_values(cx, let_pat) && !found_slices.is_empty() && let filtered_slices = filter_lintable_slices(cx, found_slices, self.max_suggested_slice, if_then) && !filtered_slices.is_empty() + && self.msrv.meets(cx, msrvs::SLICE_PATTERNS) { for slice in filtered_slices.values() { lint_slice(cx, slice); } } } - - extract_msrv_attr!(LateContext); } fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxIndexMap { diff --git a/clippy_lints/src/inherent_to_string.rs b/clippy_lints/src/inherent_to_string.rs index c58e8773e3a2..1d582fb0223e 100644 --- a/clippy_lints/src/inherent_to_string.rs +++ b/clippy_lints/src/inherent_to_string.rs @@ -1,11 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::ty::{implements_trait, is_type_lang_item}; use clippy_utils::{return_ty, trait_ref_of_method}; +use rustc_abi::ExternAbi; use rustc_hir::{GenericParamKind, ImplItem, ImplItemKind, LangItem}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::sym; -use rustc_abi::ExternAbi; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/instant_subtraction.rs b/clippy_lints/src/instant_subtraction.rs index f4e41dc826b0..4ae1119ab3a2 100644 --- a/clippy_lints/src/instant_subtraction.rs +++ b/clippy_lints/src/instant_subtraction.rs @@ -70,9 +70,7 @@ pub struct InstantSubtraction { impl InstantSubtraction { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -99,14 +97,12 @@ impl LateLintPass<'_> for InstantSubtraction { print_manual_instant_elapsed_sugg(cx, expr, sugg); } else if ty::is_type_diagnostic_item(cx, rhs_ty, sym::Duration) && !expr.span.from_expansion() - && self.msrv.meets(msrvs::TRY_FROM) + && self.msrv.meets(cx, msrvs::TRY_FROM) { print_unchecked_duration_subtraction_sugg(cx, lhs, rhs, expr); } } } - - extract_msrv_attr!(LateContext); } fn is_instant_now_call(cx: &LateContext<'_>, expr_block: &'_ Expr<'_>) -> bool { diff --git a/clippy_lints/src/invalid_upcast_comparisons.rs b/clippy_lints/src/invalid_upcast_comparisons.rs index 1929fbded3b5..b42664340d1c 100644 --- a/clippy_lints/src/invalid_upcast_comparisons.rs +++ b/clippy_lints/src/invalid_upcast_comparisons.rs @@ -22,9 +22,6 @@ declare_clippy_lint! { /// will mistakenly imply that it is possible for `x` to be outside the range of /// `u8`. /// - /// ### Known problems - /// https://github.com/rust-lang/rust-clippy/issues/886 - /// /// ### Example /// ```no_run /// let x: u8 = 1; diff --git a/clippy_lints/src/large_include_file.rs b/clippy_lints/src/large_include_file.rs index 53dc070833b5..621a2af1d322 100644 --- a/clippy_lints/src/large_include_file.rs +++ b/clippy_lints/src/large_include_file.rs @@ -2,9 +2,8 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::macros::root_macro_call_first_node; use clippy_utils::source::snippet_opt; -use rustc_ast::LitKind; +use rustc_ast::{AttrArgs, AttrKind, Attribute, LitKind}; use rustc_hir::{Expr, ExprKind}; -use rustc_ast::{Attribute, AttrArgs, AttrKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::sym; diff --git a/clippy_lints/src/legacy_numeric_constants.rs b/clippy_lints/src/legacy_numeric_constants.rs index 6f2ce04e8f8e..3939318bee6e 100644 --- a/clippy_lints/src/legacy_numeric_constants.rs +++ b/clippy_lints/src/legacy_numeric_constants.rs @@ -39,9 +39,7 @@ pub struct LegacyNumericConstants { impl LegacyNumericConstants { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -52,9 +50,9 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { // Integer modules are "TBD" deprecated, and the contents are too, // so lint on the `use` statement directly. if let ItemKind::Use(path, kind @ (UseKind::Single | UseKind::Glob)) = item.kind - && self.msrv.meets(msrvs::NUMERIC_ASSOCIATED_CONSTANTS) && !item.span.in_external_macro(cx.sess().source_map()) && let Some(def_id) = path.res[0].opt_def_id() + && self.msrv.meets(cx, msrvs::NUMERIC_ASSOCIATED_CONSTANTS) { let module = if is_integer_module(cx, def_id) { true @@ -137,8 +135,8 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { return; }; - if self.msrv.meets(msrvs::NUMERIC_ASSOCIATED_CONSTANTS) - && !expr.span.in_external_macro(cx.sess().source_map()) + if !expr.span.in_external_macro(cx.sess().source_map()) + && self.msrv.meets(cx, msrvs::NUMERIC_ASSOCIATED_CONSTANTS) && !is_from_proc_macro(cx, expr) { span_lint_hir_and_then(cx, LEGACY_NUMERIC_CONSTANTS, expr.hir_id, span, msg, |diag| { @@ -151,8 +149,6 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { }); } } - - extract_msrv_attr!(LateContext); } fn is_integer_module(cx: &LateContext<'_>, did: DefId) -> bool { diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 177f83921cd5..cc3d972f017b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -340,6 +340,7 @@ mod significant_drop_tightening; mod single_call_fn; mod single_char_lifetime_names; mod single_component_path_imports; +mod single_option_map; mod single_range_in_vec_init; mod size_of_in_element_count; mod size_of_ref; @@ -841,7 +842,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(move |_| Box::new(non_send_fields_in_send_ty::NonSendFieldInSendTy::new(conf))); store.register_late_pass(move |_| Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks::new(conf))); let format_args = format_args_storage.clone(); - store.register_late_pass(move |_| Box::new(format_args::FormatArgs::new(conf, format_args.clone()))); + store.register_late_pass(move |tcx| Box::new(format_args::FormatArgs::new(tcx, conf, format_args.clone()))); store.register_late_pass(|_| Box::new(trailing_empty_array::TrailingEmptyArray)); store.register_early_pass(|| Box::new(octal_escapes::OctalEscapes)); store.register_late_pass(|_| Box::new(needless_late_init::NeedlessLateInit)); @@ -904,7 +905,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(move |_| Box::new(manual_main_separator_str::ManualMainSeparatorStr::new(conf))); store.register_late_pass(|_| Box::new(unnecessary_struct_initialization::UnnecessaryStruct)); store.register_late_pass(move |_| Box::new(unnecessary_box_returns::UnnecessaryBoxReturns::new(conf))); - store.register_late_pass(|_| Box::new(lines_filter_map_ok::LinesFilterMapOk)); + store.register_late_pass(move |_| Box::new(lines_filter_map_ok::LinesFilterMapOk::new(conf))); store.register_late_pass(|_| Box::new(tests_outside_test_module::TestsOutsideTestModule)); store.register_late_pass(|_| Box::new(manual_slice_size_calculation::ManualSliceSizeCalculation)); store.register_early_pass(move || Box::new(excessive_nesting::ExcessiveNesting::new(conf))); @@ -948,7 +949,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::>::default()); store.register_late_pass(|_| Box::new(iter_over_hash_type::IterOverHashType)); store.register_late_pass(|_| Box::new(impl_hash_with_borrow_str_and_bytes::ImplHashWithBorrowStrBytes)); - store.register_late_pass(|_| Box::new(repeat_vec_with_capacity::RepeatVecWithCapacity)); + store.register_late_pass(move |_| Box::new(repeat_vec_with_capacity::RepeatVecWithCapacity::new(conf))); store.register_late_pass(|_| Box::new(uninhabited_references::UninhabitedReferences)); store.register_late_pass(|_| Box::new(ineffective_open_options::IneffectiveOpenOptions)); store.register_late_pass(|_| Box::::default()); @@ -982,5 +983,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::::default()); store.register_late_pass(move |_| Box::new(non_std_lazy_statics::NonStdLazyStatic::new(conf))); store.register_late_pass(|_| Box::new(manual_option_as_slice::ManualOptionAsSlice::new(conf))); + store.register_late_pass(|_| Box::new(single_option_map::SingleOptionMap)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index f08812017b9c..3dd2de1fafc7 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -38,8 +38,8 @@ declare_clippy_lint! { /// them leads to more readable code. /// /// ### Known problems - /// - We bail out if the function has a `where` clause where lifetimes - /// are mentioned due to potential false positives. + /// This lint ignores functions with `where` clauses that reference + /// lifetimes to prevent false positives. /// /// ### Example /// ```no_run @@ -62,6 +62,38 @@ declare_clippy_lint! { would allow omitting them" } +declare_clippy_lint! { + /// ### What it does + /// Checks for lifetime annotations which can be replaced with anonymous lifetimes (`'_`). + /// + /// ### Why is this bad? + /// The additional lifetimes can make the code look more complicated. + /// + /// ### Known problems + /// This lint ignores functions with `where` clauses that reference + /// lifetimes to prevent false positives. + /// + /// ### Example + /// ```no_run + /// # use std::str::Chars; + /// fn f<'a>(x: &'a str) -> Chars<'a> { + /// x.chars() + /// } + /// ``` + /// + /// Use instead: + /// ```no_run + /// # use std::str::Chars; + /// fn f(x: &str) -> Chars<'_> { + /// x.chars() + /// } + /// ``` + #[clippy::version = "1.84.0"] + pub ELIDABLE_LIFETIME_NAMES, + pedantic, + "lifetime name that can be replaced with the anonymous lifetime" +} + declare_clippy_lint! { /// ### What it does /// Checks for lifetimes in generics that are never used @@ -98,13 +130,15 @@ pub struct Lifetimes { impl Lifetimes { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } -impl_lint_pass!(Lifetimes => [NEEDLESS_LIFETIMES, EXTRA_UNUSED_LIFETIMES]); +impl_lint_pass!(Lifetimes => [ + NEEDLESS_LIFETIMES, + ELIDABLE_LIFETIME_NAMES, + EXTRA_UNUSED_LIFETIMES, +]); impl<'tcx> LateLintPass<'tcx> for Lifetimes { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { @@ -115,7 +149,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes { .. } = item.kind { - check_fn_inner(cx, sig, Some(id), None, generics, item.span, true, &self.msrv); + check_fn_inner(cx, sig, Some(id), None, generics, item.span, true, self.msrv); } else if let ItemKind::Impl(impl_) = item.kind { if !item.span.from_expansion() { report_extra_impl_lifetimes(cx, impl_); @@ -134,7 +168,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes { item.generics, item.span, report_extra_lifetimes, - &self.msrv, + self.msrv, ); } } @@ -145,11 +179,9 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes { TraitFn::Required(sig) => (None, Some(sig)), TraitFn::Provided(id) => (Some(id), None), }; - check_fn_inner(cx, sig, body, trait_sig, item.generics, item.span, true, &self.msrv); + check_fn_inner(cx, sig, body, trait_sig, item.generics, item.span, true, self.msrv); } } - - extract_msrv_attr!(LateContext); } #[allow(clippy::too_many_arguments)] @@ -161,7 +193,7 @@ fn check_fn_inner<'tcx>( generics: &'tcx Generics<'_>, span: Span, report_extra_lifetimes: bool, - msrv: &Msrv, + msrv: Msrv, ) { if span.in_external_macro(cx.sess().source_map()) || has_where_lifetimes(cx, generics) { return; @@ -234,7 +266,7 @@ fn could_use_elision<'tcx>( body: Option, trait_sig: Option<&[Ident]>, named_generics: &'tcx [GenericParam<'_>], - msrv: &Msrv, + msrv: Msrv, ) -> Option<(Vec, Vec)> { // There are two scenarios where elision works: // * no output references, all input references have different LT @@ -352,17 +384,12 @@ fn allowed_lts_from(named_generics: &[GenericParam<'_>]) -> FxIndexSet( - cx: &LateContext<'tcx>, - func: &FnDecl<'tcx>, - ident: Option, - msrv: &Msrv, -) -> bool { - if !msrv.meets(msrvs::EXPLICIT_SELF_TYPE_ELISION) - && let Some(ident) = ident +fn non_elidable_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident: Option, msrv: Msrv) -> bool { + if let Some(ident) = ident && ident.name == kw::SelfLower && !func.implicit_self.has_implicit_self() && let Some(self_ty) = func.inputs.first() + && !msrv.meets(cx, msrvs::EXPLICIT_SELF_TYPE_ELISION) { let mut visitor = RefVisitor::new(cx); visitor.visit_ty_unambig(self_ty); @@ -746,6 +773,15 @@ fn report_elidable_impl_lifetimes<'tcx>( report_elidable_lifetimes(cx, impl_.generics, &elidable_lts, &usages, true); } +#[derive(Copy, Clone)] +enum ElidableUsage { + /// Used in a ref (`&'a T`), can be removed + Ref(Span), + /// Used as a generic param (`T<'a>`) or an impl lifetime (`impl T + 'a`), can be replaced + /// with `'_` + Other(Span), +} + /// Generate diagnostic messages for elidable lifetimes. fn report_elidable_lifetimes( cx: &LateContext<'_>, @@ -763,9 +799,29 @@ fn report_elidable_lifetimes( .collect::>() .join(", "); + let elidable_usages: Vec = usages + .iter() + .filter(|usage| named_lifetime(usage).is_some_and(|id| elidable_lts.contains(&id))) + .map(|usage| match cx.tcx.parent_hir_node(usage.hir_id) { + Node::Ty(Ty { + kind: TyKind::Ref(..), .. + }) => ElidableUsage::Ref(usage.ident.span), + _ => ElidableUsage::Other(usage.ident.span), + }) + .collect(); + + let lint = if elidable_usages + .iter() + .any(|usage| matches!(usage, ElidableUsage::Other(_))) + { + ELIDABLE_LIFETIME_NAMES + } else { + NEEDLESS_LIFETIMES + }; + span_lint_and_then( cx, - NEEDLESS_LIFETIMES, + lint, elidable_lts .iter() .map(|<| cx.tcx.def_span(lt)) @@ -785,7 +841,7 @@ fn report_elidable_lifetimes( return; } - if let Some(suggestions) = elision_suggestions(cx, generics, elidable_lts, usages) { + if let Some(suggestions) = elision_suggestions(cx, generics, elidable_lts, &elidable_usages) { diag.multipart_suggestion("elide the lifetimes", suggestions, Applicability::MachineApplicable); } }, @@ -796,7 +852,7 @@ fn elision_suggestions( cx: &LateContext<'_>, generics: &Generics<'_>, elidable_lts: &[LocalDefId], - usages: &[Lifetime], + usages: &[ElidableUsage], ) -> Option> { let explicit_params = generics .params @@ -836,26 +892,21 @@ fn elision_suggestions( .collect::>>()? }; - suggestions.extend( - usages - .iter() - .filter(|usage| named_lifetime(usage).is_some_and(|id| elidable_lts.contains(&id))) - .map(|usage| { - match cx.tcx.parent_hir_node(usage.hir_id) { - Node::Ty(Ty { - kind: TyKind::Ref(..), .. - }) => { - // expand `&'a T` to `&'a T` - // ^^ ^^^ - let span = cx.sess().source_map().span_extend_while_whitespace(usage.ident.span); + suggestions.extend(usages.iter().map(|&usage| { + match usage { + ElidableUsage::Ref(span) => { + // expand `&'a T` to `&'a T` + // ^^ ^^^ + let span = cx.sess().source_map().span_extend_while_whitespace(span); - (span, String::new()) - }, - // `T<'a>` and `impl Foo + 'a` should be replaced by `'_` - _ => (usage.ident.span, String::from("'_")), - } - }), - ); + (span, String::new()) + }, + ElidableUsage::Other(span) => { + // `T<'a>` and `impl Foo + 'a` should be replaced by `'_` + (span, String::from("'_")) + }, + } + })); Some(suggestions) } diff --git a/clippy_lints/src/lines_filter_map_ok.rs b/clippy_lints/src/lines_filter_map_ok.rs index f022598651b7..d8af44233d3e 100644 --- a/clippy_lints/src/lines_filter_map_ok.rs +++ b/clippy_lints/src/lines_filter_map_ok.rs @@ -1,12 +1,24 @@ +use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::ty::is_type_diagnostic_item; 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}; -use rustc_session::declare_lint_pass; +use rustc_session::impl_lint_pass; use rustc_span::sym; +pub struct LinesFilterMapOk { + msrv: Msrv, +} + +impl LinesFilterMapOk { + pub fn new(conf: &Conf) -> Self { + Self { msrv: conf.msrv } + } +} + declare_clippy_lint! { /// ### What it does /// Checks for usage of `lines.filter_map(Result::ok)` or `lines.flat_map(Result::ok)` @@ -55,7 +67,8 @@ declare_clippy_lint! { suspicious, "filtering `std::io::Lines` with `filter_map()`, `flat_map()`, or `flatten()` might cause an infinite loop" } -declare_lint_pass!(LinesFilterMapOk => [LINES_FILTER_MAP_OK]); + +impl_lint_pass!(LinesFilterMapOk => [LINES_FILTER_MAP_OK]); impl LateLintPass<'_> for LinesFilterMapOk { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { @@ -65,6 +78,7 @@ impl LateLintPass<'_> for LinesFilterMapOk { && matches!(fm_method_str, "filter_map" | "flat_map" | "flatten") && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty_adjusted(fm_receiver), sym::IoLines) && should_lint(cx, fm_args, fm_method_str) + && self.msrv.meets(cx, msrvs::MAP_WHILE) { span_lint_and_then( cx, diff --git a/clippy_lints/src/literal_string_with_formatting_args.rs b/clippy_lints/src/literal_string_with_formatting_args.rs index a957c0e22a29..975e6833a35f 100644 --- a/clippy_lints/src/literal_string_with_formatting_args.rs +++ b/clippy_lints/src/literal_string_with_formatting_args.rs @@ -7,6 +7,7 @@ use rustc_session::declare_lint_pass; use rustc_span::{BytePos, Span}; use clippy_utils::diagnostics::span_lint; +use clippy_utils::is_from_proc_macro; use clippy_utils::mir::enclosing_mir; declare_clippy_lint! { @@ -79,9 +80,9 @@ fn emit_lint(cx: &LateContext<'_>, expr: &Expr<'_>, spans: &[(Span, Option for LiteralStringWithFormattingArg { - fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { - if expr.span.from_expansion() { +impl<'tcx> LateLintPass<'tcx> for LiteralStringWithFormattingArg { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { + if expr.span.from_expansion() || expr.span.is_dummy() { return; } if let ExprKind::Lit(lit) = expr.kind { @@ -95,6 +96,9 @@ impl LateLintPass<'_> for LiteralStringWithFormattingArg { }, _ => return, }; + if is_from_proc_macro(cx, expr) { + return; + } let fmt_str = symbol.as_str(); let lo = expr.span.lo(); let mut current = fmt_str; @@ -124,7 +128,11 @@ impl LateLintPass<'_> for LiteralStringWithFormattingArg { pos.start += diff_len; pos.end += diff_len; - let start = fmt_str[..pos.start].rfind('{').unwrap_or(pos.start); + let mut start = pos.start; + while start < fmt_str.len() && !fmt_str.is_char_boundary(start) { + start += 1; + } + let start = fmt_str[..start].rfind('{').unwrap_or(start); // If this is a unicode character escape, we don't want to lint. if start > 1 && fmt_str[..start].ends_with("\\u") { continue; diff --git a/clippy_lints/src/loops/explicit_iter_loop.rs b/clippy_lints/src/loops/explicit_iter_loop.rs index 06cf901bfb23..412c78cc8041 100644 --- a/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/clippy_lints/src/loops/explicit_iter_loop.rs @@ -17,7 +17,7 @@ pub(super) fn check( cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr<'_>, - msrv: &Msrv, + msrv: Msrv, enforce_iter_loop_reborrow: bool, ) { let Some((adjust, ty)) = is_ref_iterable(cx, self_arg, call_expr, enforce_iter_loop_reborrow, msrv) else { @@ -26,10 +26,11 @@ pub(super) fn check( if let ty::Array(_, count) = *ty.peel_refs().kind() { if !ty.is_ref() { - if !msrv.meets(msrvs::ARRAY_INTO_ITERATOR) { + if !msrv.meets(cx, msrvs::ARRAY_INTO_ITERATOR) { return; } - } else if count.try_to_target_usize(cx.tcx).is_none_or(|x| x > 32) && !msrv.meets(msrvs::ARRAY_IMPL_ANY_LEN) { + } else if count.try_to_target_usize(cx.tcx).is_none_or(|x| x > 32) && !msrv.meets(cx, msrvs::ARRAY_IMPL_ANY_LEN) + { return; } } @@ -106,7 +107,7 @@ fn is_ref_iterable<'tcx>( self_arg: &Expr<'_>, call_expr: &Expr<'_>, enforce_iter_loop_reborrow: bool, - msrv: &Msrv, + msrv: Msrv, ) -> Option<(AdjustKind, Ty<'tcx>)> { let typeck = cx.typeck_results(); if let Some(trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator) @@ -126,8 +127,8 @@ fn is_ref_iterable<'tcx>( let self_ty = typeck.expr_ty(self_arg); let self_is_copy = is_copy(cx, self_ty); - if !msrv.meets(msrvs::BOX_INTO_ITER) - && is_type_lang_item(cx, self_ty.peel_refs(), rustc_hir::LangItem::OwnedBox) + if is_type_lang_item(cx, self_ty.peel_refs(), rustc_hir::LangItem::OwnedBox) + && !msrv.meets(cx, msrvs::BOX_INTO_ITER) { return None; } diff --git a/clippy_lints/src/loops/manual_flatten.rs b/clippy_lints/src/loops/manual_flatten.rs index 366c310592f5..9b6f97b9a2eb 100644 --- a/clippy_lints/src/loops/manual_flatten.rs +++ b/clippy_lints/src/loops/manual_flatten.rs @@ -1,6 +1,7 @@ use super::MANUAL_FLATTEN; use super::utils::make_iterator_snippet; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::visitors::is_local_used; use clippy_utils::{higher, path_to_local_id, peel_blocks_with_stmt}; use rustc_errors::Applicability; @@ -18,6 +19,7 @@ pub(super) fn check<'tcx>( arg: &'tcx Expr<'_>, body: &'tcx Expr<'_>, span: Span, + msrv: Msrv, ) { let inner_expr = peel_blocks_with_stmt(body); if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else: None, .. }) @@ -34,6 +36,7 @@ pub(super) fn check<'tcx>( && (some_ctor || ok_ctor) // Ensure expr in `if let` is not used afterwards && !is_local_used(cx, if_then, pat_hir_id) + && msrv.meets(cx, msrvs::ITER_FLATTEN) { let if_let_type = if some_ctor { "Some" } else { "Ok" }; // Prepare the error message diff --git a/clippy_lints/src/loops/manual_slice_fill.rs b/clippy_lints/src/loops/manual_slice_fill.rs index 7c6564235796..343f7c5d2d12 100644 --- a/clippy_lints/src/loops/manual_slice_fill.rs +++ b/clippy_lints/src/loops/manual_slice_fill.rs @@ -1,9 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::eager_or_lazy::switch_to_eager_eval; -use clippy_utils::macros::span_is_local; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{HasSession, snippet_with_applicability}; use clippy_utils::ty::implements_trait; +use clippy_utils::visitors::is_local_used; use clippy_utils::{higher, peel_blocks_with_stmt, span_contains_comment}; use rustc_ast::ast::LitKind; use rustc_ast::{RangeLimits, UnOp}; @@ -24,12 +24,8 @@ pub(super) fn check<'tcx>( arg: &'tcx Expr<'_>, body: &'tcx Expr<'_>, expr: &'tcx Expr<'_>, - msrv: &Msrv, + msrv: Msrv, ) { - if !msrv.meets(msrvs::SLICE_FILL) { - return; - } - // `for _ in 0..slice.len() { slice[_] = value; }` if let Some(higher::Range { start: Some(start), @@ -43,7 +39,7 @@ pub(super) fn check<'tcx>( && let ExprKind::Block(..) = body.kind // Check if the body is an assignment to a slice element. && let ExprKind::Assign(assignee, assignval, _) = peel_blocks_with_stmt(body).kind - && let ExprKind::Index(slice, _, _) = assignee.kind + && let ExprKind::Index(slice, idx, _) = assignee.kind // Check if `len()` is used for the range end. && let ExprKind::MethodCall(path, recv,..) = end.kind && path.ident.name == sym::len @@ -54,10 +50,14 @@ pub(super) fn check<'tcx>( && !assignval.span.from_expansion() // It is generally not equivalent to use the `fill` method if `assignval` can have side effects && switch_to_eager_eval(cx, assignval) - && span_is_local(assignval.span) // The `fill` method requires that the slice's element type implements the `Clone` trait. && let Some(clone_trait) = cx.tcx.lang_items().clone_trait() && implements_trait(cx, cx.typeck_results().expr_ty(slice), clone_trait, &[]) + // https://github.com/rust-lang/rust-clippy/issues/14192 + && let ExprKind::Path(Resolved(_, idx_path)) = idx.kind + && let Res::Local(idx_hir) = idx_path.res + && !is_local_used(cx, assignval, idx_hir) + && msrv.meets(cx, msrvs::SLICE_FILL) { sugg(cx, body, expr, slice.span, assignval.span); } @@ -73,10 +73,12 @@ pub(super) fn check<'tcx>( && local == pat.hir_id && !assignval.span.from_expansion() && switch_to_eager_eval(cx, assignval) - && span_is_local(assignval.span) + // `assignval` must not reference the iterator + && !is_local_used(cx, assignval, local) // The `fill` method cannot be used if the slice's element type does not implement the `Clone` trait. && let Some(clone_trait) = cx.tcx.lang_items().clone_trait() && implements_trait(cx, cx.typeck_results().expr_ty(recv), clone_trait, &[]) + && msrv.meets(cx, msrvs::SLICE_FILL) { sugg(cx, body, expr, recv_path.span, assignval.span); } diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs index cdc8c18c3b74..ed725a039891 100644 --- a/clippy_lints/src/loops/mod.rs +++ b/clippy_lints/src/loops/mod.rs @@ -747,7 +747,7 @@ pub struct Loops { impl Loops { pub fn new(conf: &'static Conf) -> Self { Self { - msrv: conf.msrv.clone(), + msrv: conf.msrv, enforce_iter_loop_reborrow: conf.enforce_iter_loop_reborrow, } } @@ -832,8 +832,6 @@ impl<'tcx> LateLintPass<'tcx> for Loops { manual_while_let_some::check(cx, condition, body, span); } } - - extract_msrv_attr!(LateContext); } impl Loops { @@ -850,7 +848,7 @@ impl Loops { ) { let is_manual_memcpy_triggered = manual_memcpy::check(cx, pat, arg, body, expr); if !is_manual_memcpy_triggered { - manual_slice_fill::check(cx, pat, arg, body, expr, &self.msrv); + manual_slice_fill::check(cx, pat, arg, body, expr, self.msrv); needless_range_loop::check(cx, pat, arg, body, expr); explicit_counter_loop::check(cx, pat, arg, body, expr, label); } @@ -858,8 +856,8 @@ impl Loops { for_kv_map::check(cx, pat, arg, body); mut_range_bound::check(cx, arg, body); single_element_loop::check(cx, pat, arg, body, expr); - same_item_push::check(cx, pat, arg, body, expr, &self.msrv); - manual_flatten::check(cx, pat, arg, body, span); + same_item_push::check(cx, pat, arg, body, expr, self.msrv); + manual_flatten::check(cx, pat, arg, body, span, self.msrv); manual_find::check(cx, pat, arg, body, span, expr); unused_enumerate_index::check(cx, pat, arg, body); } @@ -868,7 +866,7 @@ impl Loops { if let ExprKind::MethodCall(method, self_arg, [], _) = arg.kind { match method.ident.as_str() { "iter" | "iter_mut" => { - explicit_iter_loop::check(cx, self_arg, arg, &self.msrv, self.enforce_iter_loop_reborrow); + explicit_iter_loop::check(cx, self_arg, arg, self.msrv, self.enforce_iter_loop_reborrow); }, "into_iter" => { explicit_into_iter_loop::check(cx, self_arg, arg); diff --git a/clippy_lints/src/loops/same_item_push.rs b/clippy_lints/src/loops/same_item_push.rs index c27e930c99a5..661b4b590d8f 100644 --- a/clippy_lints/src/loops/same_item_push.rs +++ b/clippy_lints/src/loops/same_item_push.rs @@ -20,14 +20,14 @@ pub(super) fn check<'tcx>( _: &'tcx Expr<'_>, body: &'tcx Expr<'_>, _: &'tcx Expr<'_>, - msrv: &Msrv, + msrv: Msrv, ) { - fn emit_lint(cx: &LateContext<'_>, vec: &Expr<'_>, pushed_item: &Expr<'_>, ctxt: SyntaxContext, msrv: &Msrv) { + fn emit_lint(cx: &LateContext<'_>, vec: &Expr<'_>, pushed_item: &Expr<'_>, ctxt: SyntaxContext, msrv: Msrv) { let mut app = Applicability::Unspecified; let vec_str = snippet_with_context(cx, vec.span, ctxt, "", &mut app).0; let item_str = snippet_with_context(cx, pushed_item.span, ctxt, "", &mut app).0; - let secondary_help = if msrv.meets(msrvs::REPEAT_N) + let secondary_help = if msrv.meets(cx, msrvs::REPEAT_N) && let Some(std_or_core) = std_or_core(cx) { format!("or `{vec_str}.extend({std_or_core}::iter::repeat_n({item_str}, SIZE))`") diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs index 165e8c2ea05a..20be22850b76 100644 --- a/clippy_lints/src/macro_use.rs +++ b/clippy_lints/src/macro_use.rs @@ -21,7 +21,21 @@ declare_clippy_lint! { /// ### Example /// ```rust,ignore /// #[macro_use] - /// use some_macro; + /// extern crate some_crate; + /// + /// fn main() { + /// some_macro!(); + /// } + /// ``` + /// + /// Use instead: + /// + /// ```rust,ignore + /// use some_crate::some_macro; + /// + /// fn main() { + /// some_macro!(); + /// } /// ``` #[clippy::version = "1.44.0"] pub MACRO_USE_IMPORTS, @@ -103,11 +117,6 @@ impl LateLintPass<'_> for MacroUseImports { self.push_unique_macro_pat_ty(cx, item.span); } } - fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &hir::Attribute) { - if attr.span().from_expansion() { - self.push_unique_macro(cx, attr.span()); - } - } fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) { if expr.span.from_expansion() { self.push_unique_macro(cx, expr.span); diff --git a/clippy_lints/src/manual_async_fn.rs b/clippy_lints/src/manual_async_fn.rs index 6f3a7d8cccc8..abd1ac954cda 100644 --- a/clippy_lints/src/manual_async_fn.rs +++ b/clippy_lints/src/manual_async_fn.rs @@ -62,6 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn { && let Some(closure_body) = desugared_async_block(cx, block) && let Node::Item(Item {vis_span, ..}) | Node::ImplItem(ImplItem {vis_span, ..}) = cx.tcx.hir_node_by_def_id(fn_def_id) + && !span.from_expansion() { let header_span = span.with_hi(ret_ty.span.hi()); diff --git a/clippy_lints/src/manual_bits.rs b/clippy_lints/src/manual_bits.rs index 17e25635ce10..39c4857b3e87 100644 --- a/clippy_lints/src/manual_bits.rs +++ b/clippy_lints/src/manual_bits.rs @@ -40,9 +40,7 @@ pub struct ManualBits { impl ManualBits { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -53,7 +51,6 @@ impl<'tcx> LateLintPass<'tcx> for ManualBits { if let ExprKind::Binary(bin_op, left_expr, right_expr) = expr.kind && let BinOpKind::Mul = &bin_op.node && !expr.span.from_expansion() - && self.msrv.meets(msrvs::MANUAL_BITS) && let ctxt = expr.span.ctxt() && left_expr.span.ctxt() == ctxt && right_expr.span.ctxt() == ctxt @@ -61,6 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualBits { && matches!(resolved_ty.kind(), ty::Int(_) | ty::Uint(_)) && let ExprKind::Lit(lit) = &other_expr.kind && let LitKind::Int(Pu128(8), _) = lit.node + && self.msrv.meets(cx, msrvs::INTEGER_BITS) { let mut app = Applicability::MachineApplicable; let ty_snip = snippet_with_context(cx, real_ty_span, ctxt, "..", &mut app).0; @@ -77,8 +75,6 @@ impl<'tcx> LateLintPass<'tcx> for ManualBits { ); } } - - extract_msrv_attr!(LateContext); } fn get_one_size_of_ty<'tcx>( diff --git a/clippy_lints/src/manual_clamp.rs b/clippy_lints/src/manual_clamp.rs index 484a7ba256bd..50c8331eebab 100644 --- a/clippy_lints/src/manual_clamp.rs +++ b/clippy_lints/src/manual_clamp.rs @@ -99,9 +99,7 @@ pub struct ManualClamp { impl ManualClamp { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -144,30 +142,28 @@ struct InputMinMax<'tcx> { impl<'tcx> LateLintPass<'tcx> for ManualClamp { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - if !self.msrv.meets(msrvs::CLAMP) { - return; - } if !expr.span.from_expansion() && !is_in_const_context(cx) { let suggestion = is_if_elseif_else_pattern(cx, expr) .or_else(|| is_max_min_pattern(cx, expr)) .or_else(|| is_call_max_min_pattern(cx, expr)) .or_else(|| is_match_pattern(cx, expr)) .or_else(|| is_if_elseif_pattern(cx, expr)); - if let Some(suggestion) = suggestion { + if let Some(suggestion) = suggestion + && self.msrv.meets(cx, msrvs::CLAMP) + { maybe_emit_suggestion(cx, &suggestion); } } } fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) { - if !self.msrv.meets(msrvs::CLAMP) || is_in_const_context(cx) { + if is_in_const_context(cx) || !self.msrv.meets(cx, msrvs::CLAMP) { return; } for suggestion in is_two_if_pattern(cx, block) { maybe_emit_suggestion(cx, &suggestion); } } - extract_msrv_attr!(LateContext); } fn maybe_emit_suggestion<'tcx>(cx: &LateContext<'tcx>, suggestion: &ClampSuggestion<'tcx>) { diff --git a/clippy_lints/src/manual_div_ceil.rs b/clippy_lints/src/manual_div_ceil.rs index 04357cdd8f66..9c1419175d55 100644 --- a/clippy_lints/src/manual_div_ceil.rs +++ b/clippy_lints/src/manual_div_ceil.rs @@ -49,9 +49,7 @@ pub struct ManualDivCeil { impl ManualDivCeil { #[must_use] pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -59,10 +57,6 @@ impl_lint_pass!(ManualDivCeil => [MANUAL_DIV_CEIL]); impl<'tcx> LateLintPass<'tcx> for ManualDivCeil { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { - if !self.msrv.meets(msrvs::MANUAL_DIV_CEIL) { - return; - } - let mut applicability = Applicability::MachineApplicable; if let ExprKind::Binary(div_op, div_lhs, div_rhs) = expr.kind @@ -70,6 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualDivCeil { && check_int_ty_and_feature(cx, div_lhs) && check_int_ty_and_feature(cx, div_rhs) && let ExprKind::Binary(inner_op, inner_lhs, inner_rhs) = div_lhs.kind + && self.msrv.meets(cx, msrvs::MANUAL_DIV_CEIL) { // (x + (y - 1)) / y if let ExprKind::Binary(sub_op, sub_lhs, sub_rhs) = inner_rhs.kind @@ -122,8 +117,6 @@ impl<'tcx> LateLintPass<'tcx> for ManualDivCeil { } } } - - extract_msrv_attr!(LateContext); } /// Checks if two expressions represent non-zero integer literals such that `small_expr + 1 == diff --git a/clippy_lints/src/manual_float_methods.rs b/clippy_lints/src/manual_float_methods.rs index 2a5aa12d126c..bd2785fea270 100644 --- a/clippy_lints/src/manual_float_methods.rs +++ b/clippy_lints/src/manual_float_methods.rs @@ -90,9 +90,7 @@ pub struct ManualFloatMethods { impl ManualFloatMethods { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -144,7 +142,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods { && !expr.span.in_external_macro(cx.sess().source_map()) && ( is_not_const(cx.tcx, cx.tcx.hir_enclosing_body_owner(expr.hir_id).into()) - || self.msrv.meets(msrvs::CONST_FLOAT_CLASSIFY) + || self.msrv.meets(cx, msrvs::CONST_FLOAT_CLASSIFY) ) && let [first, second, const_1, const_2] = exprs && let ecx = ConstEvalCtxt::new(cx) @@ -202,8 +200,6 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods { }); } } - - extract_msrv_attr!(LateContext); } fn is_infinity(constant: &Constant<'_>) -> bool { diff --git a/clippy_lints/src/manual_hash_one.rs b/clippy_lints/src/manual_hash_one.rs index 7e092d11f1b4..f71264a93ca8 100644 --- a/clippy_lints/src/manual_hash_one.rs +++ b/clippy_lints/src/manual_hash_one.rs @@ -53,9 +53,7 @@ pub struct ManualHashOne { impl ManualHashOne { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -98,7 +96,7 @@ impl LateLintPass<'_> for ManualHashOne { && let ExprKind::MethodCall(seg, _, [], _) = finish_expr.kind && seg.ident.name.as_str() == "finish" - && self.msrv.meets(msrvs::BUILD_HASHER_HASH_ONE) + && self.msrv.meets(cx, msrvs::BUILD_HASHER_HASH_ONE) { span_lint_hir_and_then( cx, @@ -129,6 +127,4 @@ impl LateLintPass<'_> for ManualHashOne { ); } } - - extract_msrv_attr!(LateContext); } diff --git a/clippy_lints/src/manual_is_ascii_check.rs b/clippy_lints/src/manual_is_ascii_check.rs index 38106277a88f..faf01a276a13 100644 --- a/clippy_lints/src/manual_is_ascii_check.rs +++ b/clippy_lints/src/manual_is_ascii_check.rs @@ -64,9 +64,7 @@ pub struct ManualIsAsciiCheck { impl ManualIsAsciiCheck { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -91,11 +89,11 @@ enum CharRange { impl<'tcx> LateLintPass<'tcx> for ManualIsAsciiCheck { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if !self.msrv.meets(msrvs::IS_ASCII_DIGIT) { + if !self.msrv.meets(cx, msrvs::IS_ASCII_DIGIT) { return; } - if is_in_const_context(cx) && !self.msrv.meets(msrvs::IS_ASCII_DIGIT_CONST) { + if is_in_const_context(cx) && !self.msrv.meets(cx, msrvs::IS_ASCII_DIGIT_CONST) { return; } @@ -119,8 +117,6 @@ impl<'tcx> LateLintPass<'tcx> for ManualIsAsciiCheck { check_is_ascii(cx, expr.span, arg, &range, ty_sugg); } } - - extract_msrv_attr!(LateContext); } fn get_ty_sugg<'tcx>(cx: &LateContext<'tcx>, arg: &Expr<'_>) -> Option<(Span, Ty<'tcx>)> { diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs index 3643b8c4425e..47939767212e 100644 --- a/clippy_lints/src/manual_let_else.rs +++ b/clippy_lints/src/manual_let_else.rs @@ -53,8 +53,8 @@ impl<'tcx> QuestionMark { && local.ty.is_none() && init.span.eq_ctxt(stmt.span) && let Some(if_let_or_match) = IfLetOrMatch::parse(cx, init) - && self.msrv.meets(msrvs::LET_ELSE) && !stmt.span.in_external_macro(cx.sess().source_map()) + && self.msrv.meets(cx, msrvs::LET_ELSE) { match if_let_or_match { IfLetOrMatch::IfLet(if_let_expr, let_pat, if_then, if_else, ..) => { diff --git a/clippy_lints/src/manual_main_separator_str.rs b/clippy_lints/src/manual_main_separator_str.rs index b7563a2508d0..f54ccf2c87b0 100644 --- a/clippy_lints/src/manual_main_separator_str.rs +++ b/clippy_lints/src/manual_main_separator_str.rs @@ -39,9 +39,7 @@ pub struct ManualMainSeparatorStr { impl ManualMainSeparatorStr { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -55,10 +53,10 @@ impl LateLintPass<'_> for ManualMainSeparatorStr { && let ExprKind::Path(QPath::Resolved(None, path)) = receiver.kind && 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) && 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() + && self.msrv.meets(cx, msrvs::PATH_MAIN_SEPARATOR_STR) { span_lint_and_sugg( cx, @@ -71,6 +69,4 @@ impl LateLintPass<'_> for ManualMainSeparatorStr { ); } } - - extract_msrv_attr!(LateContext); } diff --git a/clippy_lints/src/manual_non_exhaustive.rs b/clippy_lints/src/manual_non_exhaustive.rs index 83d8a5093906..496e0660d4f9 100644 --- a/clippy_lints/src/manual_non_exhaustive.rs +++ b/clippy_lints/src/manual_non_exhaustive.rs @@ -71,7 +71,7 @@ pub struct ManualNonExhaustive { impl ManualNonExhaustive { pub fn new(conf: &'static Conf) -> Self { Self { - msrv: conf.msrv.clone(), + msrv: conf.msrv, constructed_enum_variants: FxHashSet::default(), potential_enums: Vec::new(), } @@ -82,7 +82,7 @@ impl_lint_pass!(ManualNonExhaustive => [MANUAL_NON_EXHAUSTIVE]); impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - if !self.msrv.meets(msrvs::NON_EXHAUSTIVE) || !cx.effective_visibilities.is_exported(item.owner_id.def_id) { + if !cx.effective_visibilities.is_exported(item.owner_id.def_id) || !self.msrv.meets(cx, msrvs::NON_EXHAUSTIVE) { return; } @@ -171,6 +171,4 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive { ); } } - - extract_msrv_attr!(LateContext); } diff --git a/clippy_lints/src/manual_option_as_slice.rs b/clippy_lints/src/manual_option_as_slice.rs index e4360518b66e..8dee29b2a0b5 100644 --- a/clippy_lints/src/manual_option_as_slice.rs +++ b/clippy_lints/src/manual_option_as_slice.rs @@ -1,5 +1,6 @@ use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; +use clippy_utils::msrvs::Msrv; use clippy_utils::{is_none_arm, msrvs, peel_hir_expr_refs}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; @@ -40,31 +41,21 @@ declare_clippy_lint! { } pub struct ManualOptionAsSlice { - msrv: msrvs::Msrv, + msrv: Msrv, } impl ManualOptionAsSlice { pub fn new(conf: &Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } impl_lint_pass!(ManualOptionAsSlice => [MANUAL_OPTION_AS_SLICE]); impl LateLintPass<'_> for ManualOptionAsSlice { - extract_msrv_attr!(LateContext); - fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { let span = expr.span; - if span.from_expansion() - || !self.msrv.meets(if clippy_utils::is_in_const_context(cx) { - msrvs::CONST_OPTION_AS_SLICE - } else { - msrvs::OPTION_AS_SLICE - }) - { + if span.from_expansion() { return; } match expr.kind { @@ -72,7 +63,7 @@ impl LateLintPass<'_> for ManualOptionAsSlice { if is_none_arm(cx, arm2) && check_arms(cx, arm2, arm1) || is_none_arm(cx, arm1) && check_arms(cx, arm1, arm2) { - check_as_ref(cx, scrutinee, span); + check_as_ref(cx, scrutinee, span, self.msrv); } }, ExprKind::If(cond, then, Some(other)) => { @@ -81,23 +72,23 @@ impl LateLintPass<'_> for ManualOptionAsSlice { && check_some_body(cx, binding, then) && is_empty_slice(cx, other.peel_blocks()) { - check_as_ref(cx, let_expr.init, span); + check_as_ref(cx, let_expr.init, span, self.msrv); } }, ExprKind::MethodCall(seg, callee, [], _) => { if seg.ident.name.as_str() == "unwrap_or_default" { - check_map(cx, callee, span); + check_map(cx, callee, span, self.msrv); } }, ExprKind::MethodCall(seg, callee, [or], _) => match seg.ident.name.as_str() { "unwrap_or" => { if is_empty_slice(cx, or) { - check_map(cx, callee, span); + check_map(cx, callee, span, self.msrv); } }, "unwrap_or_else" => { if returns_empty_slice(cx, or) { - check_map(cx, callee, span); + check_map(cx, callee, span, self.msrv); } }, _ => {}, @@ -105,12 +96,12 @@ impl LateLintPass<'_> for ManualOptionAsSlice { ExprKind::MethodCall(seg, callee, [or_else, map], _) => match seg.ident.name.as_str() { "map_or" => { if is_empty_slice(cx, or_else) && is_slice_from_ref(cx, map) { - check_as_ref(cx, callee, span); + check_as_ref(cx, callee, span, self.msrv); } }, "map_or_else" => { if returns_empty_slice(cx, or_else) && is_slice_from_ref(cx, map) { - check_as_ref(cx, callee, span); + check_as_ref(cx, callee, span, self.msrv); } }, _ => {}, @@ -120,20 +111,28 @@ impl LateLintPass<'_> for ManualOptionAsSlice { } } -fn check_map(cx: &LateContext<'_>, map: &Expr<'_>, span: Span) { +fn check_map(cx: &LateContext<'_>, map: &Expr<'_>, span: Span, msrv: Msrv) { if let ExprKind::MethodCall(seg, callee, [mapping], _) = map.kind && seg.ident.name == sym::map && is_slice_from_ref(cx, mapping) { - check_as_ref(cx, callee, span); + check_as_ref(cx, callee, span, msrv); } } -fn check_as_ref(cx: &LateContext<'_>, expr: &Expr<'_>, span: Span) { +fn check_as_ref(cx: &LateContext<'_>, expr: &Expr<'_>, span: Span, msrv: Msrv) { if let ExprKind::MethodCall(seg, callee, [], _) = expr.kind && seg.ident.name == sym::as_ref && let ty::Adt(adtdef, ..) = cx.typeck_results().expr_ty(callee).kind() && cx.tcx.is_diagnostic_item(sym::Option, adtdef.did()) + && msrv.meets( + cx, + if clippy_utils::is_in_const_context(cx) { + msrvs::CONST_OPTION_AS_SLICE + } else { + msrvs::OPTION_AS_SLICE + }, + ) { if let Some(snippet) = clippy_utils::source::snippet_opt(cx, callee.span) { span_lint_and_sugg( diff --git a/clippy_lints/src/manual_rem_euclid.rs b/clippy_lints/src/manual_rem_euclid.rs index 469b4b7cf89f..41e07e26bff0 100644 --- a/clippy_lints/src/manual_rem_euclid.rs +++ b/clippy_lints/src/manual_rem_euclid.rs @@ -39,9 +39,7 @@ pub struct ManualRemEuclid { impl ManualRemEuclid { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -60,8 +58,6 @@ impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid { && add_lhs.span.ctxt() == ctxt && add_rhs.span.ctxt() == ctxt && !expr.span.in_external_macro(cx.sess().source_map()) - && self.msrv.meets(msrvs::REM_EUCLID) - && (self.msrv.meets(msrvs::REM_EUCLID_CONST) || !is_in_const_context(cx)) && let Some(const1) = check_for_unsigned_int_constant(cx, rem_rhs) && let Some((const2, add_other)) = check_for_either_unsigned_int_constant(cx, add_lhs, add_rhs) && let ExprKind::Binary(rem2_op, rem2_lhs, rem2_rhs) = add_other.kind @@ -73,6 +69,8 @@ impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid { && const2 == const3 && rem2_lhs.span.ctxt() == ctxt && rem2_rhs.span.ctxt() == ctxt + && self.msrv.meets(cx, msrvs::REM_EUCLID) + && (self.msrv.meets(cx, msrvs::REM_EUCLID_CONST) || !is_in_const_context(cx)) { // Apply only to params or locals with annotated types match cx.tcx.parent_hir_node(hir_id) { @@ -99,8 +97,6 @@ impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid { ); } } - - extract_msrv_attr!(LateContext); } // Checks if either the left or right expressions can be an unsigned int constant and returns that diff --git a/clippy_lints/src/manual_retain.rs b/clippy_lints/src/manual_retain.rs index 0a4e756096e9..16dd1ad4e478 100644 --- a/clippy_lints/src/manual_retain.rs +++ b/clippy_lints/src/manual_retain.rs @@ -50,9 +50,7 @@ pub struct ManualRetain { impl ManualRetain { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -66,13 +64,11 @@ impl<'tcx> LateLintPass<'tcx> for ManualRetain { && let Some(collect_def_id) = cx.typeck_results().type_dependent_def_id(collect_expr.hir_id) && cx.tcx.is_diagnostic_item(sym::iterator_collect_fn, collect_def_id) { - check_into_iter(cx, left_expr, target_expr, expr.span, &self.msrv); - check_iter(cx, left_expr, target_expr, expr.span, &self.msrv); - check_to_owned(cx, left_expr, target_expr, expr.span, &self.msrv); + check_into_iter(cx, left_expr, target_expr, expr.span, self.msrv); + check_iter(cx, left_expr, target_expr, expr.span, self.msrv); + check_to_owned(cx, left_expr, target_expr, expr.span, self.msrv); } } - - extract_msrv_attr!(LateContext); } fn check_into_iter( @@ -80,7 +76,7 @@ fn check_into_iter( left_expr: &hir::Expr<'_>, target_expr: &hir::Expr<'_>, parent_expr_span: Span, - msrv: &Msrv, + msrv: Msrv, ) { if let hir::ExprKind::MethodCall(_, into_iter_expr, [_], _) = &target_expr.kind && let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id) @@ -123,7 +119,7 @@ fn check_iter( left_expr: &hir::Expr<'_>, target_expr: &hir::Expr<'_>, parent_expr_span: Span, - msrv: &Msrv, + msrv: Msrv, ) { if let hir::ExprKind::MethodCall(_, filter_expr, [], _) = &target_expr.kind && let Some(copied_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id) @@ -181,10 +177,9 @@ fn check_to_owned( left_expr: &hir::Expr<'_>, target_expr: &hir::Expr<'_>, parent_expr_span: Span, - msrv: &Msrv, + msrv: Msrv, ) { - if msrv.meets(msrvs::STRING_RETAIN) - && let hir::ExprKind::MethodCall(_, filter_expr, [], _) = &target_expr.kind + if let hir::ExprKind::MethodCall(_, filter_expr, [], _) = &target_expr.kind && let Some(to_owned_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id) && cx.tcx.is_diagnostic_item(sym::to_owned_method, to_owned_def_id) && let hir::ExprKind::MethodCall(_, chars_expr, [_], _) = &filter_expr.kind @@ -200,6 +195,7 @@ fn check_to_owned( && let hir::ExprKind::Closure(closure) = closure_expr.kind && let filter_body = cx.tcx.hir_body(closure.body) && let [filter_params] = filter_body.params + && msrv.meets(cx, msrvs::STRING_RETAIN) { if let hir::PatKind::Ref(pat, _) = filter_params.pat.kind { make_span_lint_and_sugg( @@ -253,7 +249,7 @@ fn match_acceptable_sym(cx: &LateContext<'_>, collect_def_id: DefId) -> bool { .any(|&method| cx.tcx.is_diagnostic_item(method, collect_def_id)) } -fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, msrv: &Msrv) -> bool { +fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, msrv: Msrv) -> bool { let ty = cx.typeck_results().expr_ty(expr).peel_refs(); let required = match get_type_diagnostic_name(cx, ty) { Some(sym::BinaryHeap) => msrvs::BINARY_HEAP_RETAIN, @@ -264,7 +260,7 @@ fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, msrv: &Msrv Some(sym::Vec | sym::VecDeque) => return true, _ => return false, }; - msrv.meets(required) + msrv.meets(cx, required) } fn match_map_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { diff --git a/clippy_lints/src/manual_strip.rs b/clippy_lints/src/manual_strip.rs index d69384a2cb70..9e911e61f196 100644 --- a/clippy_lints/src/manual_strip.rs +++ b/clippy_lints/src/manual_strip.rs @@ -2,19 +2,21 @@ use clippy_config::Conf; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::msrvs::{self, Msrv}; -use clippy_utils::source::snippet; +use clippy_utils::source::snippet_with_applicability; use clippy_utils::usage::mutated_variables; use clippy_utils::{eq_expr_value, higher}; +use rustc_ast::BindingMode; use rustc_ast::ast::LitKind; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; use rustc_hir::def::Res; -use rustc_hir::intravisit::{Visitor, walk_expr}; -use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_hir::intravisit::{Visitor, walk_expr, walk_pat}; +use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, Node, PatKind}; +use rustc_lint::{LateContext, LateLintPass, LintContext as _}; use rustc_middle::ty; use rustc_session::impl_lint_pass; use rustc_span::source_map::Spanned; -use rustc_span::{Span, sym}; +use rustc_span::{Symbol, sym}; use std::iter; declare_clippy_lint! { @@ -54,9 +56,7 @@ pub struct ManualStrip { impl ManualStrip { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -73,7 +73,6 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip { if let Some(higher::If { cond, then, .. }) = higher::If::hir(expr) && let ExprKind::MethodCall(_, target_arg, [pattern], _) = cond.kind && let ExprKind::Path(target_path) = &target_arg.kind - && 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 cx.tcx.is_diagnostic_item(sym::str_starts_with, method_def_id) { @@ -95,18 +94,37 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip { return; } - let strippings = find_stripping(cx, strip_kind, target_res, pattern, then); - if !strippings.is_empty() { + let (strippings, bindings) = find_stripping(cx, strip_kind, target_res, pattern, then); + if !strippings.is_empty() && self.msrv.meets(cx, msrvs::STR_STRIP_PREFIX) { let kind_word = match strip_kind { StripKind::Prefix => "prefix", StripKind::Suffix => "suffix", }; let test_span = expr.span.until(then.span); + + // If the first use is a simple `let` statement, reuse its identifier in the `if let Some(…)` and + // remove the `let` statement as long as the identifier is never bound again within the lexical + // scope of interest. + let (ident_name, let_stmt_span, skip, mut app) = if let Node::LetStmt(let_stmt) = + cx.tcx.parent_hir_node(strippings[0].hir_id) + && let PatKind::Binding(BindingMode::NONE, _, ident, None) = &let_stmt.pat.kind + && bindings.get(&ident.name) == Some(&1) + { + ( + ident.name.as_str(), + Some(cx.sess().source_map().span_extend_while_whitespace(let_stmt.span)), + 1, + Applicability::MachineApplicable, + ) + } else { + ("", None, 0, Applicability::HasPlaceholders) + }; + span_lint_and_then( cx, MANUAL_STRIP, - strippings[0], + strippings[0].span, format!("stripping a {kind_word} manually"), |diag| { diag.span_note(test_span, format!("the {kind_word} was tested here")); @@ -115,22 +133,26 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip { iter::once(( test_span, format!( - "if let Some() = {}.strip_{kind_word}({}) ", - snippet(cx, target_arg.span, ".."), - snippet(cx, pattern.span, "..") + "if let Some({ident_name}) = {}.strip_{kind_word}({}) ", + snippet_with_applicability(cx, target_arg.span, "_", &mut app), + snippet_with_applicability(cx, pattern.span, "_", &mut app) ), )) - .chain(strippings.into_iter().map(|span| (span, "".into()))) + .chain(let_stmt_span.map(|span| (span, String::new()))) + .chain( + strippings + .into_iter() + .skip(skip) + .map(|expr| (expr.span, ident_name.into())), + ) .collect(), - Applicability::HasPlaceholders, + app, ); }, ); } } } - - extract_msrv_attr!(LateContext); } // Returns `Some(arg)` if `expr` matches `arg.len()` and `None` otherwise. @@ -188,19 +210,21 @@ fn peel_ref<'a>(expr: &'a Expr<'_>) -> &'a Expr<'a> { /// Find expressions where `target` is stripped using the length of `pattern`. /// We'll suggest replacing these expressions with the result of the `strip_{prefix,suffix}` /// method. +/// Also, all bindings found during the visit are counted and returned. fn find_stripping<'tcx>( cx: &LateContext<'tcx>, strip_kind: StripKind, target: Res, pattern: &'tcx Expr<'_>, - expr: &'tcx Expr<'_>, -) -> Vec { + expr: &'tcx Expr<'tcx>, +) -> (Vec<&'tcx Expr<'tcx>>, FxHashMap) { struct StrippingFinder<'a, 'tcx> { cx: &'a LateContext<'tcx>, strip_kind: StripKind, target: Res, pattern: &'tcx Expr<'tcx>, - results: Vec, + results: Vec<&'tcx Expr<'tcx>>, + bindings: FxHashMap, } impl<'tcx> Visitor<'tcx> for StrippingFinder<'_, 'tcx> { @@ -215,7 +239,7 @@ fn find_stripping<'tcx>( match (self.strip_kind, start, end) { (StripKind::Prefix, Some(start), None) => { if eq_pattern_length(self.cx, self.pattern, start) { - self.results.push(ex.span); + self.results.push(ex); return; } }, @@ -232,7 +256,7 @@ fn find_stripping<'tcx>( && self.cx.qpath_res(left_path, left_arg.hir_id) == self.target && eq_pattern_length(self.cx, self.pattern, right) { - self.results.push(ex.span); + self.results.push(ex); return; } }, @@ -242,6 +266,13 @@ fn find_stripping<'tcx>( walk_expr(self, ex); } + + fn visit_pat(&mut self, pat: &'tcx rustc_hir::Pat<'tcx>) -> Self::Result { + if let PatKind::Binding(_, _, ident, _) = pat.kind { + *self.bindings.entry(ident.name).or_default() += 1; + } + walk_pat(self, pat); + } } let mut finder = StrippingFinder { @@ -250,7 +281,8 @@ fn find_stripping<'tcx>( target, pattern, results: vec![], + bindings: FxHashMap::default(), }; walk_expr(&mut finder, expr); - finder.results + (finder.results, finder.bindings) } diff --git a/clippy_lints/src/matches/collapsible_match.rs b/clippy_lints/src/matches/collapsible_match.rs index 97e8423695d9..6f446bf95658 100644 --- a/clippy_lints/src/matches/collapsible_match.rs +++ b/clippy_lints/src/matches/collapsible_match.rs @@ -14,7 +14,7 @@ use rustc_span::Span; use super::{COLLAPSIBLE_MATCH, pat_contains_disallowed_or}; -pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], msrv: &Msrv) { +pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], msrv: Msrv) { if let Some(els_arm) = arms.iter().rfind(|arm| arm_is_wild_like(cx, arm)) { for arm in arms { check_arm(cx, true, arm.pat, arm.body, arm.guard, Some(els_arm.body), msrv); @@ -27,7 +27,7 @@ pub(super) fn check_if_let<'tcx>( pat: &'tcx Pat<'_>, body: &'tcx Expr<'_>, else_expr: Option<&'tcx Expr<'_>>, - msrv: &Msrv, + msrv: Msrv, ) { check_arm(cx, false, pat, body, None, else_expr, msrv); } @@ -39,7 +39,7 @@ fn check_arm<'tcx>( outer_then_body: &'tcx Expr<'tcx>, outer_guard: Option<&'tcx Expr<'tcx>>, outer_else_body: Option<&'tcx Expr<'tcx>>, - msrv: &Msrv, + msrv: Msrv, ) { let inner_expr = peel_blocks_with_stmt(outer_then_body); if let Some(inner) = IfLetOrMatch::parse(cx, inner_expr) @@ -60,7 +60,7 @@ fn check_arm<'tcx>( // match expression must be a local binding // match { .. } && let Some(binding_id) = path_to_local(peel_ref_operators(cx, inner_scrutinee)) - && !pat_contains_disallowed_or(inner_then_pat, msrv) + && !pat_contains_disallowed_or(cx, inner_then_pat, msrv) // the binding must come from the pattern of the containing match arm // .... => match { .. } && let (Some(binding_span), is_innermost_parent_pat_struct) diff --git a/clippy_lints/src/matches/manual_ok_err.rs b/clippy_lints/src/matches/manual_ok_err.rs index 3deaaf96c1e8..576e42a564c2 100644 --- a/clippy_lints/src/matches/manual_ok_err.rs +++ b/clippy_lints/src/matches/manual_ok_err.rs @@ -1,7 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::{indent_of, reindent_multiline}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::option_arg_ty; -use clippy_utils::{is_res_lang_ctor, path_res, peel_blocks, span_contains_comment}; +use clippy_utils::{get_parent_expr, is_res_lang_ctor, path_res, peel_blocks, span_contains_comment}; use rustc_ast::BindingMode; use rustc_errors::Applicability; use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr}; @@ -132,13 +133,23 @@ fn apply_lint(cx: &LateContext<'_>, expr: &Expr<'_>, scrutinee: &Expr<'_>, is_ok Applicability::MachineApplicable }; let scrut = Sugg::hir_with_applicability(cx, scrutinee, "..", &mut app).maybe_par(); + let sugg = format!("{scrut}.{method}()"); + // If the expression being expanded is the `if …` part of an `else if …`, it must be blockified. + let sugg = if let Some(parent_expr) = get_parent_expr(cx, expr) + && let ExprKind::If(_, _, Some(else_part)) = parent_expr.kind + && else_part.hir_id == expr.hir_id + { + reindent_multiline(&format!("{{\n {sugg}\n}}"), true, indent_of(cx, parent_expr.span)) + } else { + sugg + }; span_lint_and_sugg( cx, MANUAL_OK_ERR, expr.span, format!("manual implementation of `{method}`"), "replace with", - format!("{scrut}.{method}()"), + sugg, app, ); } diff --git a/clippy_lints/src/matches/manual_unwrap_or.rs b/clippy_lints/src/matches/manual_unwrap_or.rs index b69294d567d1..2bf7ec8ab7dd 100644 --- a/clippy_lints/src/matches/manual_unwrap_or.rs +++ b/clippy_lints/src/matches/manual_unwrap_or.rs @@ -117,7 +117,7 @@ fn lint<'tcx>( or_body_snippet: &str, indent: usize, ) { - let reindented_or_body = reindent_multiline(or_body_snippet.into(), true, Some(indent)); + let reindented_or_body = reindent_multiline(or_body_snippet, true, Some(indent)); let mut app = Applicability::MachineApplicable; let suggestion = sugg::Sugg::hir_with_context(cx, scrutinee, expr.span.ctxt(), "..", &mut app).maybe_par(); diff --git a/clippy_lints/src/matches/manual_utils.rs b/clippy_lints/src/matches/manual_utils.rs index 2ad55d9bf1fd..09440c396ee1 100644 --- a/clippy_lints/src/matches/manual_utils.rs +++ b/clippy_lints/src/matches/manual_utils.rs @@ -4,8 +4,8 @@ use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::{is_copy, is_type_diagnostic_item, peel_mid_ty_refs_is_mutable, type_is_unsafe_function}; use clippy_utils::{ - CaptureKind, can_move_expr_to_closure, is_else_clause, is_lint_allowed, is_res_lang_ctor, path_res, - path_to_local_id, peel_blocks, peel_hir_expr_refs, peel_hir_expr_while, + CaptureKind, can_move_expr_to_closure, expr_requires_coercion, is_else_clause, is_lint_allowed, is_res_lang_ctor, + path_res, path_to_local_id, peel_blocks, peel_hir_expr_refs, peel_hir_expr_while, }; use rustc_ast::util::parser::ExprPrecedence; use rustc_errors::Applicability; @@ -73,7 +73,7 @@ where } // `map` won't perform any adjustments. - if !cx.typeck_results().expr_adjustments(some_expr.expr).is_empty() { + if expr_requires_coercion(cx, expr) { return None; } @@ -124,6 +124,12 @@ where }; let closure_expr_snip = some_expr.to_snippet_with_context(cx, expr_ctxt, &mut app); + let closure_body = if some_expr.needs_unsafe_block { + format!("unsafe {}", closure_expr_snip.blockify()) + } else { + closure_expr_snip.to_string() + }; + let body_str = if let PatKind::Binding(annotation, id, some_binding, None) = some_pat.kind { if !some_expr.needs_unsafe_block && let Some(func) = can_pass_as_func(cx, id, some_expr.expr) @@ -145,20 +151,12 @@ where "" }; - if some_expr.needs_unsafe_block { - format!("|{annotation}{some_binding}| unsafe {{ {closure_expr_snip} }}") - } else { - format!("|{annotation}{some_binding}| {closure_expr_snip}") - } + format!("|{annotation}{some_binding}| {closure_body}") } } else if !is_wild_none && explicit_ref.is_none() { // TODO: handle explicit reference annotations. let pat_snip = snippet_with_context(cx, some_pat.span, expr_ctxt, "..", &mut app).0; - if some_expr.needs_unsafe_block { - format!("|{pat_snip}| unsafe {{ {closure_expr_snip} }}") - } else { - format!("|{pat_snip}| {closure_expr_snip}") - } + format!("|{pat_snip}| {closure_body}") } else { // Refutable bindings and mixed reference annotations can't be handled by `map`. return None; diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs index 9ca914af281b..35caa7d1f3a6 100644 --- a/clippy_lints/src/matches/mod.rs +++ b/clippy_lints/src/matches/mod.rs @@ -1014,7 +1014,7 @@ pub struct Matches { impl Matches { pub fn new(conf: &'static Conf) -> Self { Self { - msrv: conf.msrv.clone(), + msrv: conf.msrv, infallible_destructuring_match_linted: false, } } @@ -1073,7 +1073,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches { significant_drop_in_scrutinee::check_match(cx, expr, ex, arms, source); } - collapsible_match::check_match(cx, arms, &self.msrv); + collapsible_match::check_match(cx, arms, self.msrv); if !from_expansion { // These don't depend on a relationship between multiple arms match_wild_err_arm::check(cx, ex, arms); @@ -1086,7 +1086,9 @@ impl<'tcx> LateLintPass<'tcx> for Matches { if !from_expansion && !contains_cfg_arm(cx, expr, ex, arms) { if source == MatchSource::Normal { - if !(self.msrv.meets(msrvs::MATCHES_MACRO) && match_like_matches::check_match(cx, expr, ex, arms)) { + if !(self.msrv.meets(cx, msrvs::MATCHES_MACRO) + && match_like_matches::check_match(cx, expr, ex, arms)) + { match_same_arms::check(cx, arms); } @@ -1120,7 +1122,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches { needless_match::check_match(cx, ex, arms, expr); match_on_vec_items::check(cx, ex); match_str_case_mismatch::check(cx, ex, arms); - redundant_guards::check(cx, arms, &self.msrv); + redundant_guards::check(cx, arms, self.msrv); if !is_in_const_context(cx) { manual_unwrap_or::check_match(cx, expr, ex, arms); @@ -1138,11 +1140,11 @@ impl<'tcx> LateLintPass<'tcx> for Matches { match_ref_pats::check(cx, ex, arms.iter().map(|el| el.pat), expr); } } else if let Some(if_let) = higher::IfLet::hir(cx, expr) { - collapsible_match::check_if_let(cx, if_let.let_pat, if_let.if_then, if_let.if_else, &self.msrv); + collapsible_match::check_if_let(cx, if_let.let_pat, if_let.if_then, if_let.if_else, self.msrv); significant_drop_in_scrutinee::check_if_let(cx, expr, if_let.let_expr, if_let.if_then, if_let.if_else); if !from_expansion { if let Some(else_expr) = if_let.if_else { - if self.msrv.meets(msrvs::MATCHES_MACRO) { + if self.msrv.meets(cx, msrvs::MATCHES_MACRO) { match_like_matches::check_if_let( cx, expr, @@ -1208,8 +1210,6 @@ impl<'tcx> LateLintPass<'tcx> for Matches { fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) { rest_pat_in_fully_bound_struct::check(cx, pat); } - - extract_msrv_attr!(LateContext); } /// Checks if there are any arms with a `#[cfg(..)]` attribute. @@ -1274,16 +1274,12 @@ fn contains_cfg_arm(cx: &LateContext<'_>, e: &Expr<'_>, scrutinee: &Expr<'_>, ar } /// Checks if `pat` contains OR patterns that cannot be nested due to a too low MSRV. -fn pat_contains_disallowed_or(pat: &Pat<'_>, msrv: &Msrv) -> bool { - if msrv.meets(msrvs::OR_PATTERNS) { - return false; - } - - let mut result = false; +fn pat_contains_disallowed_or(cx: &LateContext<'_>, pat: &Pat<'_>, msrv: Msrv) -> bool { + let mut contains_or = false; pat.walk(|p| { let is_or = matches!(p.kind, PatKind::Or(_)); - result |= is_or; + contains_or |= is_or; !is_or }); - result + contains_or && !msrv.meets(cx, msrvs::OR_PATTERNS) } diff --git a/clippy_lints/src/matches/redundant_guards.rs b/clippy_lints/src/matches/redundant_guards.rs index dfc0513add93..ab53ad98572e 100644 --- a/clippy_lints/src/matches/redundant_guards.rs +++ b/clippy_lints/src/matches/redundant_guards.rs @@ -16,7 +16,7 @@ use std::ops::ControlFlow; use super::{REDUNDANT_GUARDS, pat_contains_disallowed_or}; -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>], msrv: &Msrv) { +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>], msrv: Msrv) { for outer_arm in arms { let Some(guard) = outer_arm.guard else { continue; @@ -26,7 +26,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>], msrv: if let ExprKind::Match(scrutinee, [arm, _], MatchSource::Normal) = guard.kind && matching_root_macro_call(cx, guard.span, sym::matches_macro).is_some() && let Some(binding) = get_pat_binding(cx, scrutinee, outer_arm) - && !pat_contains_disallowed_or(arm.pat, msrv) + && !pat_contains_disallowed_or(cx, arm.pat, msrv) { let pat_span = match (arm.pat.kind, binding.byref_ident) { (PatKind::Ref(pat, _), Some(_)) => pat.span, @@ -45,7 +45,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>], msrv: // `Some(x) if let Some(2) = x` else if let ExprKind::Let(let_expr) = guard.kind && let Some(binding) = get_pat_binding(cx, let_expr.init, outer_arm) - && !pat_contains_disallowed_or(let_expr.pat, msrv) + && !pat_contains_disallowed_or(cx, let_expr.pat, msrv) { let pat_span = match (let_expr.pat.kind, binding.byref_ident) { (PatKind::Ref(pat, _), Some(_)) => pat.span, diff --git a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs index 35f2e780d2e2..37bac561a6e0 100644 --- a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs +++ b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs @@ -199,7 +199,7 @@ impl<'a, 'tcx> SigDropChecker<'a, 'tcx> { return false; } - let result = match ty.kind() { + match ty.kind() { rustc_middle::ty::Adt(adt, args) => { // if some field has significant drop, adt.all_fields() @@ -223,9 +223,7 @@ impl<'a, 'tcx> SigDropChecker<'a, 'tcx> { rustc_middle::ty::Tuple(tys) => tys.iter().any(|ty| self.has_sig_drop_attr_impl(ty)), rustc_middle::ty::Array(ty, _) | rustc_middle::ty::Slice(ty) => self.has_sig_drop_attr_impl(*ty), _ => false, - }; - - result + } } } diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index 41528c5dee3a..a0919947b3fc 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -8,7 +8,7 @@ use clippy_utils::{ is_default_equivalent, is_expr_used_or_unified, is_res_lang_ctor, path_res, peel_ref_operators, std_or_core, }; use rustc_errors::Applicability; -use rustc_hir::LangItem::OptionNone; +use rustc_hir::LangItem::{OptionNone, OptionSome}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; @@ -43,6 +43,31 @@ declare_clippy_lint! { "replacing an `Option` with `None` instead of `take()`" } +declare_clippy_lint! { + /// ### What it does + /// Checks for `mem::replace()` on an `Option` with `Some(…)`. + /// + /// ### Why is this bad? + /// `Option` already has the method `replace()` for + /// taking its current value (Some(…) or None) and replacing it with + /// `Some(…)`. + /// + /// ### Example + /// ```no_run + /// let mut an_option = Some(0); + /// let replaced = std::mem::replace(&mut an_option, Some(1)); + /// ``` + /// Is better expressed with: + /// ```no_run + /// let mut an_option = Some(0); + /// let taken = an_option.replace(1); + /// ``` + #[clippy::version = "1.86.0"] + pub MEM_REPLACE_OPTION_WITH_SOME, + style, + "replacing an `Option` with `Some` instead of `replace()`" +} + declare_clippy_lint! { /// ### What it does /// Checks for `mem::replace(&mut _, mem::uninitialized())` @@ -101,28 +126,67 @@ declare_clippy_lint! { } impl_lint_pass!(MemReplace => - [MEM_REPLACE_OPTION_WITH_NONE, MEM_REPLACE_WITH_UNINIT, MEM_REPLACE_WITH_DEFAULT]); + [MEM_REPLACE_OPTION_WITH_NONE, MEM_REPLACE_OPTION_WITH_SOME, MEM_REPLACE_WITH_UNINIT, MEM_REPLACE_WITH_DEFAULT]); -fn check_replace_option_with_none(cx: &LateContext<'_>, dest: &Expr<'_>, expr_span: Span) { - // Since this is a late pass (already type-checked), - // and we already know that the second argument is an - // `Option`, we do not need to check the first - // argument's type. All that's left is to get - // the replacee's expr after peeling off the `&mut` - let sugg_expr = peel_ref_operators(cx, dest); - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - MEM_REPLACE_OPTION_WITH_NONE, - expr_span, - "replacing an `Option` with `None`", - "consider `Option::take()` instead", - format!( - "{}.take()", - Sugg::hir_with_context(cx, sugg_expr, expr_span.ctxt(), "", &mut applicability).maybe_par() - ), - applicability, - ); +fn check_replace_option_with_none(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) -> bool { + if is_res_lang_ctor(cx, path_res(cx, src), OptionNone) { + // Since this is a late pass (already type-checked), + // and we already know that the second argument is an + // `Option`, we do not need to check the first + // argument's type. All that's left is to get + // the replacee's expr after peeling off the `&mut` + let sugg_expr = peel_ref_operators(cx, dest); + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + MEM_REPLACE_OPTION_WITH_NONE, + expr_span, + "replacing an `Option` with `None`", + "consider `Option::take()` instead", + format!( + "{}.take()", + Sugg::hir_with_context(cx, sugg_expr, expr_span.ctxt(), "", &mut applicability).maybe_par() + ), + applicability, + ); + true + } else { + false + } +} + +fn check_replace_option_with_some( + cx: &LateContext<'_>, + src: &Expr<'_>, + dest: &Expr<'_>, + expr_span: Span, + msrv: Msrv, +) -> bool { + if let ExprKind::Call(src_func, [src_arg]) = src.kind + && is_res_lang_ctor(cx, path_res(cx, src_func), OptionSome) + && msrv.meets(cx, msrvs::OPTION_REPLACE) + { + // We do not have to check for a `const` context here, because `core::mem::replace()` and + // `Option::replace()` have been const-stabilized simultaneously in version 1.83.0. + let sugg_expr = peel_ref_operators(cx, dest); + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + MEM_REPLACE_OPTION_WITH_SOME, + expr_span, + "replacing an `Option` with `Some(..)`", + "consider `Option::replace()` instead", + format!( + "{}.replace({})", + Sugg::hir_with_context(cx, sugg_expr, expr_span.ctxt(), "_", &mut applicability).maybe_par(), + snippet_with_applicability(cx, src_arg.span, "_", &mut applicability) + ), + applicability, + ); + true + } else { + false + } } fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) { @@ -181,27 +245,35 @@ fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<' } } -fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) { - // disable lint for primitives - let expr_type = cx.typeck_results().expr_ty_adjusted(src); - if is_non_aggregate_primitive_type(expr_type) { - return; - } - if is_default_equivalent(cx, src) && !expr_span.in_external_macro(cx.tcx.sess.source_map()) { - let Some(top_crate) = std_or_core(cx) else { return }; +fn check_replace_with_default( + cx: &LateContext<'_>, + src: &Expr<'_>, + dest: &Expr<'_>, + expr: &Expr<'_>, + msrv: Msrv, +) -> bool { + if is_expr_used_or_unified(cx.tcx, expr) + // disable lint for primitives + && let expr_type = cx.typeck_results().expr_ty_adjusted(src) + && !is_non_aggregate_primitive_type(expr_type) + && is_default_equivalent(cx, src) + && !expr.span.in_external_macro(cx.tcx.sess.source_map()) + && let Some(top_crate) = std_or_core(cx) + && msrv.meets(cx, msrvs::MEM_TAKE) + { span_lint_and_then( cx, MEM_REPLACE_WITH_DEFAULT, - expr_span, + expr.span, format!( "replacing a value of type `T` with `T::default()` is better expressed using `{top_crate}::mem::take`" ), |diag| { - if !expr_span.from_expansion() { + if !expr.span.from_expansion() { let suggestion = format!("{top_crate}::mem::take({})", snippet(cx, dest.span, "")); diag.span_suggestion( - expr_span, + expr.span, "consider using", suggestion, Applicability::MachineApplicable, @@ -209,6 +281,9 @@ fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr< } }, ); + true + } else { + false } } @@ -218,9 +293,7 @@ pub struct MemReplace { impl MemReplace { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -233,13 +306,12 @@ impl<'tcx> LateLintPass<'tcx> for MemReplace { && cx.tcx.is_diagnostic_item(sym::mem_replace, def_id) { // Check that second argument is `Option::None` - if is_res_lang_ctor(cx, path_res(cx, src), OptionNone) { - check_replace_option_with_none(cx, dest, expr.span); - } else if self.msrv.meets(msrvs::MEM_TAKE) && is_expr_used_or_unified(cx.tcx, expr) { - check_replace_with_default(cx, src, dest, expr.span); + if !check_replace_option_with_none(cx, src, dest, expr.span) + && !check_replace_option_with_some(cx, src, dest, expr.span, self.msrv) + && !check_replace_with_default(cx, src, dest, expr, self.msrv) + { + check_replace_with_uninit(cx, src, dest, expr.span); } - check_replace_with_uninit(cx, src, dest, expr.span); } } - extract_msrv_attr!(LateContext); } diff --git a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs index 76bdbe55e2f3..18568e3661fe 100644 --- a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs +++ b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs @@ -57,14 +57,13 @@ pub(super) fn check<'tcx>( }; let suggestion_source = reindent_multiline( - format!( + &format!( "std::path::Path::new({}) .extension() .map_or(false, |ext| ext.eq_ignore_ascii_case(\"{}\"))", recv_source, ext_str.strip_prefix('.').unwrap() - ) - .into(), + ), true, Some(indent_of(cx, call_span).unwrap_or(0) + 4), ); diff --git a/clippy_lints/src/methods/cloned_instead_of_copied.rs b/clippy_lints/src/methods/cloned_instead_of_copied.rs index 223a960b800e..f50fb627b89a 100644 --- a/clippy_lints/src/methods/cloned_instead_of_copied.rs +++ b/clippy_lints/src/methods/cloned_instead_of_copied.rs @@ -10,16 +10,16 @@ use rustc_span::{Span, sym}; use super::CLONED_INSTEAD_OF_COPIED; -pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span: Span, msrv: &Msrv) { +pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span: Span, msrv: Msrv) { let recv_ty = cx.typeck_results().expr_ty_adjusted(recv); let inner_ty = match recv_ty.kind() { // `Option` -> `T` ty::Adt(adt, subst) - if cx.tcx.is_diagnostic_item(sym::Option, adt.did()) && msrv.meets(msrvs::OPTION_COPIED) => + if cx.tcx.is_diagnostic_item(sym::Option, adt.did()) && msrv.meets(cx, msrvs::OPTION_COPIED) => { subst.type_at(0) }, - _ if is_trait_method(cx, expr, sym::Iterator) && msrv.meets(msrvs::ITERATOR_COPIED) => { + _ if is_trait_method(cx, expr, sym::Iterator) && msrv.meets(cx, msrvs::ITERATOR_COPIED) => { match get_iterator_item_ty(cx, recv_ty) { // ::Item Some(ty) => ty, diff --git a/clippy_lints/src/methods/double_ended_iterator_last.rs b/clippy_lints/src/methods/double_ended_iterator_last.rs index 208172980c9f..e82211bbf3ef 100644 --- a/clippy_lints/src/methods/double_ended_iterator_last.rs +++ b/clippy_lints/src/methods/double_ended_iterator_last.rs @@ -1,8 +1,8 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::is_trait_method; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::ty::implements_trait; +use clippy_utils::{is_mutable, is_trait_method, path_to_local}; use rustc_errors::Applicability; -use rustc_hir::Expr; +use rustc_hir::{Expr, Node, PatKind}; use rustc_lint::LateContext; use rustc_middle::ty::Instance; use rustc_span::{Span, sym}; @@ -28,14 +28,47 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, self_expr: &'_ Exp // if the resolved method is the same as the provided definition && fn_def.def_id() == last_def.def_id { - span_lint_and_sugg( + let mut sugg = vec![(call_span, String::from("next_back()"))]; + let mut dont_apply = false; + // if `self_expr` is a reference, it is mutable because it is used for `.last()` + if !(is_mutable(cx, self_expr) || self_type.is_ref()) { + if let Some(hir_id) = path_to_local(self_expr) + && let Node::Pat(pat) = cx.tcx.hir_node(hir_id) + && let PatKind::Binding(_, _, ident, _) = pat.kind + { + sugg.push((ident.span.shrink_to_lo(), String::from("mut "))); + } else { + // If we can't make the binding mutable, make the suggestion `Unspecified` to prevent it from being + // automatically applied, and add a complementary help message. + dont_apply = true; + } + } + span_lint_and_then( cx, DOUBLE_ENDED_ITERATOR_LAST, - call_span, + expr.span, "called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator", - "try", - "next_back()".to_string(), - Applicability::MachineApplicable, + |diag| { + let expr_ty = cx.typeck_results().expr_ty(expr); + let droppable_elements = expr_ty.has_significant_drop(cx.tcx, cx.typing_env()); + diag.multipart_suggestion( + "try", + sugg, + if dont_apply { + Applicability::Unspecified + } else if droppable_elements { + Applicability::MaybeIncorrect + } else { + Applicability::MachineApplicable + }, + ); + if droppable_elements { + diag.note("this change will alter drop order which may be undesirable"); + } + if dont_apply { + diag.span_note(self_expr.span, "this must be made mutable to use `.next_back()`"); + } + }, ); } } diff --git a/clippy_lints/src/methods/err_expect.rs b/clippy_lints/src/methods/err_expect.rs index f2786efa44cb..91ddaca07d8b 100644 --- a/clippy_lints/src/methods/err_expect.rs +++ b/clippy_lints/src/methods/err_expect.rs @@ -14,19 +14,16 @@ pub(super) fn check( recv: &rustc_hir::Expr<'_>, expect_span: Span, err_span: Span, - msrv: &Msrv, + msrv: Msrv, ) { if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result) - // Test the version to make sure the lint can be showed (expect_err has been - // introduced in rust 1.17.0 : https://github.com/rust-lang/rust/pull/38982) - && msrv.meets(msrvs::EXPECT_ERR) - // Grabs the `Result` type && let result_type = cx.typeck_results().expr_ty(recv) // Tests if the T type in a `Result` is not None && let Some(data_type) = get_data_type(cx, result_type) // Tests if the T type in a `Result` implements debug && has_debug_impl(cx, data_type) + && msrv.meets(cx, msrvs::EXPECT_ERR) { span_lint_and_sugg( cx, diff --git a/clippy_lints/src/methods/filter_map.rs b/clippy_lints/src/methods/filter_map.rs index 5b9df6c2bfdd..ae300cd5fe56 100644 --- a/clippy_lints/src/methods/filter_map.rs +++ b/clippy_lints/src/methods/filter_map.rs @@ -12,7 +12,6 @@ use rustc_lint::LateContext; use rustc_middle::ty::adjustment::Adjust; use rustc_span::Span; use rustc_span::symbol::{Ident, Symbol, sym}; -use std::borrow::Cow; use super::{MANUAL_FILTER_MAP, MANUAL_FIND_MAP, OPTION_FILTER_MAP, RESULT_FILTER_MAP}; @@ -302,7 +301,7 @@ pub(super) fn check( filter_span.with_hi(expr.span.hi()), "`filter` for `Some` followed by `unwrap`", "consider using `flatten` instead", - reindent_multiline(Cow::Borrowed("flatten()"), true, indent_of(cx, map_span)).into_owned(), + reindent_multiline("flatten()", true, indent_of(cx, map_span)), Applicability::MachineApplicable, ); @@ -316,7 +315,7 @@ pub(super) fn check( filter_span.with_hi(expr.span.hi()), "`filter` for `Ok` followed by `unwrap`", "consider using `flatten` instead", - reindent_multiline(Cow::Borrowed("flatten()"), true, indent_of(cx, map_span)).into_owned(), + reindent_multiline("flatten()", true, indent_of(cx, map_span)), Applicability::MachineApplicable, ); diff --git a/clippy_lints/src/methods/filter_map_next.rs b/clippy_lints/src/methods/filter_map_next.rs index 3f89e5931487..9f3c346042ff 100644 --- a/clippy_lints/src/methods/filter_map_next.rs +++ b/clippy_lints/src/methods/filter_map_next.rs @@ -14,10 +14,10 @@ pub(super) fn check<'tcx>( expr: &'tcx hir::Expr<'_>, recv: &'tcx hir::Expr<'_>, arg: &'tcx hir::Expr<'_>, - msrv: &Msrv, + msrv: Msrv, ) { if is_trait_method(cx, expr, sym::Iterator) { - if !msrv.meets(msrvs::ITERATOR_FIND_MAP) { + if !msrv.meets(cx, msrvs::ITERATOR_FIND_MAP) { return; } diff --git a/clippy_lints/src/methods/io_other_error.rs b/clippy_lints/src/methods/io_other_error.rs new file mode 100644 index 000000000000..4659e9e163fe --- /dev/null +++ b/clippy_lints/src/methods/io_other_error.rs @@ -0,0 +1,37 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind, QPath}; +use rustc_lint::LateContext; + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, path: &Expr<'_>, args: &[Expr<'_>], msrv: Msrv) { + if let [error_kind, error] = args + && !expr.span.from_expansion() + && !error_kind.span.from_expansion() + && clippy_utils::is_expr_path_def_path(cx, path, &clippy_utils::paths::IO_ERROR_NEW) + && clippy_utils::is_expr_path_def_path( + cx, + clippy_utils::expr_or_init(cx, error_kind), + &clippy_utils::paths::IO_ERRORKIND_OTHER, + ) + && let ExprKind::Path(QPath::TypeRelative(_, new_segment)) = path.kind + && msrv.meets(cx, msrvs::IO_ERROR_OTHER) + { + span_lint_and_then( + cx, + super::IO_OTHER_ERROR, + expr.span, + "this can be `std::io::Error::other(_)`", + |diag| { + diag.multipart_suggestion_verbose( + "use `std::io::Error::other`", + vec![ + (new_segment.ident.span, "other".to_owned()), + (error_kind.span.until(error.span), String::new()), + ], + Applicability::MachineApplicable, + ); + }, + ); + } +} diff --git a/clippy_lints/src/methods/is_digit_ascii_radix.rs b/clippy_lints/src/methods/is_digit_ascii_radix.rs index d8bb9e377a0c..9c32e9ac539d 100644 --- a/clippy_lints/src/methods/is_digit_ascii_radix.rs +++ b/clippy_lints/src/methods/is_digit_ascii_radix.rs @@ -12,12 +12,8 @@ pub(super) fn check<'tcx>( expr: &'tcx Expr<'_>, self_arg: &'tcx Expr<'_>, radix: &'tcx Expr<'_>, - msrv: &Msrv, + msrv: Msrv, ) { - if !msrv.meets(msrvs::IS_ASCII_DIGIT) { - return; - } - if !cx.typeck_results().expr_ty_adjusted(self_arg).peel_refs().is_char() { return; } @@ -30,6 +26,10 @@ pub(super) fn check<'tcx>( }; let mut applicability = Applicability::MachineApplicable; + if !msrv.meets(cx, msrvs::IS_ASCII_DIGIT) { + return; + } + span_lint_and_sugg( cx, IS_DIGIT_ASCII_RADIX, diff --git a/clippy_lints/src/methods/iter_filter.rs b/clippy_lints/src/methods/iter_filter.rs index 76a0c0061e52..bafabec7e069 100644 --- a/clippy_lints/src/methods/iter_filter.rs +++ b/clippy_lints/src/methods/iter_filter.rs @@ -12,7 +12,6 @@ use rustc_hir as hir; use rustc_hir::QPath; use rustc_span::Span; use rustc_span::symbol::{Ident, Symbol, sym}; -use std::borrow::Cow; /// /// Returns true if the expression is a method call to `method_name` @@ -181,7 +180,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, filter_arg: &hir filter_span.with_hi(expr.span.hi()), "`filter` for `is_ok` on iterator over `Result`s", "consider using `flatten` instead", - reindent_multiline(Cow::Borrowed("flatten()"), true, indent_of(cx, filter_span)).into_owned(), + reindent_multiline("flatten()", true, indent_of(cx, filter_span)), Applicability::HasPlaceholders, ), Some(FilterType::IsSome) => span_lint_and_sugg( @@ -190,7 +189,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, filter_arg: &hir filter_span.with_hi(expr.span.hi()), "`filter` for `is_some` on iterator over `Option`", "consider using `flatten` instead", - reindent_multiline(Cow::Borrowed("flatten()"), true, indent_of(cx, filter_span)).into_owned(), + reindent_multiline("flatten()", true, indent_of(cx, filter_span)), Applicability::HasPlaceholders, ), } diff --git a/clippy_lints/src/methods/iter_kv_map.rs b/clippy_lints/src/methods/iter_kv_map.rs index 518041177e92..94415fc91061 100644 --- a/clippy_lints/src/methods/iter_kv_map.rs +++ b/clippy_lints/src/methods/iter_kv_map.rs @@ -20,9 +20,9 @@ pub(super) fn check<'tcx>( expr: &'tcx Expr<'tcx>, // .iter().map(|(_, v_| v)) recv: &'tcx Expr<'tcx>, // hashmap m_arg: &'tcx Expr<'tcx>, // |(_, v)| v - msrv: &Msrv, + msrv: Msrv, ) { - if map_type == "into_iter" && !msrv.meets(msrvs::INTO_KEYS) { + if map_type == "into_iter" && !msrv.meets(cx, msrvs::INTO_KEYS) { return; } if !expr.span.from_expansion() diff --git a/clippy_lints/src/methods/manual_c_str_literals.rs b/clippy_lints/src/methods/manual_c_str_literals.rs index e1ebca0b09df..0274e31b4c33 100644 --- a/clippy_lints/src/methods/manual_c_str_literals.rs +++ b/clippy_lints/src/methods/manual_c_str_literals.rs @@ -22,7 +22,7 @@ pub(super) fn check_as_ptr<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, receiver: &'tcx Expr<'tcx>, - msrv: &Msrv, + msrv: Msrv, ) { if let ExprKind::Lit(lit) = receiver.kind && let LitKind::ByteStr(_, StrStyle::Cooked) | LitKind::Str(_, StrStyle::Cooked) = lit.node @@ -32,7 +32,7 @@ pub(super) fn check_as_ptr<'tcx>( |parent| matches!(parent.kind, ExprKind::Call(func, _) if is_c_str_function(cx, func).is_some()), ) && let Some(sugg) = rewrite_as_cstr(cx, lit.span) - && msrv.meets(msrvs::C_STR_LITERALS) + && msrv.meets(cx, msrvs::C_STR_LITERALS) { span_lint_and_sugg( cx, @@ -65,11 +65,11 @@ fn is_c_str_function(cx: &LateContext<'_>, func: &Expr<'_>) -> Option { /// - `CStr::from_bytes_with_nul(..)` /// - `CStr::from_bytes_with_nul_unchecked(..)` /// - `CStr::from_ptr(..)` -pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, func: &Expr<'_>, args: &[Expr<'_>], msrv: &Msrv) { +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, func: &Expr<'_>, args: &[Expr<'_>], msrv: Msrv) { if let Some(fn_name) = is_c_str_function(cx, func) && let [arg] = args && cx.tcx.sess.edition() >= Edition2021 - && msrv.meets(msrvs::C_STR_LITERALS) + && msrv.meets(cx, msrvs::C_STR_LITERALS) { match fn_name.as_str() { name @ ("from_bytes_with_nul" | "from_bytes_with_nul_unchecked") diff --git a/clippy_lints/src/methods/manual_contains.rs b/clippy_lints/src/methods/manual_contains.rs new file mode 100644 index 000000000000..8ba0f835d3dd --- /dev/null +++ b/clippy_lints/src/methods/manual_contains.rs @@ -0,0 +1,113 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::eager_or_lazy::switch_to_eager_eval; +use clippy_utils::peel_hir_pat_refs; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::sugg::Sugg; +use rustc_ast::UnOp; +use rustc_errors::Applicability; +use rustc_hir::def::Res; +use rustc_hir::{BinOpKind, Body, Expr, ExprKind, HirId, QPath}; +use rustc_lint::LateContext; +use rustc_middle::ty::{self}; +use rustc_span::source_map::Spanned; + +use super::MANUAL_CONTAINS; + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, closure_arg: &Expr<'_>) { + let mut app = Applicability::MachineApplicable; + + if !expr.span.from_expansion() + // check if `iter().any()` can be replaced with `contains()` + && let ExprKind::Closure(closure) = closure_arg.kind + && let Body{params: [param],value} = cx.tcx.hir_body(closure.body) + && let ExprKind::Binary(op, lhs, rhs) = value.kind + && let (peeled_ref_pat, _) = peel_hir_pat_refs(param.pat) + && let Some((snip,snip_expr)) = can_replace_with_contains(cx, op, lhs, rhs, peeled_ref_pat.hir_id, &mut app) + && let ref_type = cx.typeck_results().expr_ty_adjusted(recv) + && let ty::Ref(_, inner_type, _) = ref_type.kind() + && let ty::Slice(slice_type) = inner_type.kind() + && *slice_type == cx.typeck_results().expr_ty(snip_expr) + { + span_lint_and_sugg( + cx, + MANUAL_CONTAINS, + expr.span, + "using `contains()` instead of `iter().any()` is more efficient", + "try", + format!( + "{}.contains({})", + snippet_with_applicability(cx, recv.span, "_", &mut app), + snip + ), + app, + ); + } +} + +enum EligibleArg { + IsClosureArg, + ContainsArg(String), +} + +fn try_get_eligible_arg<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'tcx>, + closure_arg_id: HirId, + applicability: &mut Applicability, +) -> Option<(EligibleArg, &'tcx Expr<'tcx>)> { + let mut get_snippet = |expr: &Expr<'_>, needs_borrow: bool| { + let sugg = Sugg::hir_with_applicability(cx, expr, "_", applicability); + EligibleArg::ContainsArg((if needs_borrow { sugg.addr() } else { sugg }).to_string()) + }; + + match expr.kind { + ExprKind::Path(QPath::Resolved(_, path)) => { + if path.res == Res::Local(closure_arg_id) { + Some((EligibleArg::IsClosureArg, expr)) + } else { + Some((get_snippet(expr, true), expr)) + } + }, + ExprKind::Unary(UnOp::Deref, inner) => { + if let ExprKind::Path(QPath::Resolved(_, path)) = inner.kind { + if path.res == Res::Local(closure_arg_id) { + Some((EligibleArg::IsClosureArg, expr)) + } else { + Some((get_snippet(inner, false), expr)) + } + } else { + None + } + }, + _ => { + if switch_to_eager_eval(cx, expr) { + Some((get_snippet(expr, true), expr)) + } else { + None + } + }, + } +} + +fn can_replace_with_contains<'tcx>( + cx: &LateContext<'tcx>, + bin_op: Spanned, + left_expr: &'tcx Expr<'tcx>, + right_expr: &'tcx Expr<'tcx>, + closure_arg_id: HirId, + applicability: &mut Applicability, +) -> Option<(String, &'tcx Expr<'tcx>)> { + if bin_op.node != BinOpKind::Eq { + return None; + } + + let left_candidate = try_get_eligible_arg(cx, left_expr, closure_arg_id, applicability)?; + let right_candidate = try_get_eligible_arg(cx, right_expr, closure_arg_id, applicability)?; + match (left_candidate, right_candidate) { + ((EligibleArg::IsClosureArg, _), (EligibleArg::ContainsArg(snip), candidate_expr)) + | ((EligibleArg::ContainsArg(snip), candidate_expr), (EligibleArg::IsClosureArg, _)) => { + Some((snip, candidate_expr)) + }, + _ => None, + } +} diff --git a/clippy_lints/src/methods/manual_inspect.rs b/clippy_lints/src/methods/manual_inspect.rs index 09ccb386a20b..173ebcb7020b 100644 --- a/clippy_lints/src/methods/manual_inspect.rs +++ b/clippy_lints/src/methods/manual_inspect.rs @@ -14,14 +14,14 @@ use rustc_span::{DUMMY_SP, Span, Symbol, sym}; use super::MANUAL_INSPECT; #[expect(clippy::too_many_lines)] -pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name: &str, name_span: Span, msrv: &Msrv) { +pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name: &str, name_span: Span, msrv: Msrv) { if let ExprKind::Closure(c) = arg.kind && matches!(c.kind, ClosureKind::Closure) && let typeck = cx.typeck_results() && let Some(fn_id) = typeck.type_dependent_def_id(expr.hir_id) && (is_diag_trait_item(cx, fn_id, sym::Iterator) - || (msrv.meets(msrvs::OPTION_RESULT_INSPECT) - && (is_diag_item_method(cx, fn_id, sym::Option) || is_diag_item_method(cx, fn_id, sym::Result)))) + || ((is_diag_item_method(cx, fn_id, sym::Option) || is_diag_item_method(cx, fn_id, sym::Result)) + && msrv.meets(cx, msrvs::OPTION_RESULT_INSPECT))) && let body = cx.tcx.hir_body(c.body) && let [param] = body.params && let PatKind::Binding(BindingMode(ByRef::No, Mutability::Not), arg_id, _, None) = param.pat.kind diff --git a/clippy_lints/src/methods/manual_is_variant_and.rs b/clippy_lints/src/methods/manual_is_variant_and.rs index 90e502f244fa..40aad03960c4 100644 --- a/clippy_lints/src/methods/manual_is_variant_and.rs +++ b/clippy_lints/src/methods/manual_is_variant_and.rs @@ -14,7 +14,7 @@ pub(super) fn check<'tcx>( map_recv: &'tcx rustc_hir::Expr<'_>, map_arg: &'tcx rustc_hir::Expr<'_>, map_span: Span, - msrv: &Msrv, + msrv: Msrv, ) { // Don't lint if: @@ -36,7 +36,7 @@ pub(super) fn check<'tcx>( } // 4. msrv doesn't meet `OPTION_RESULT_IS_VARIANT_AND` - if !msrv.meets(msrvs::OPTION_RESULT_IS_VARIANT_AND) { + if !msrv.meets(cx, msrvs::OPTION_RESULT_IS_VARIANT_AND) { return; } diff --git a/clippy_lints/src/methods/manual_ok_or.rs b/clippy_lints/src/methods/manual_ok_or.rs index 8265c93bfe9f..c286c5faaed3 100644 --- a/clippy_lints/src/methods/manual_ok_or.rs +++ b/clippy_lints/src/methods/manual_ok_or.rs @@ -27,7 +27,7 @@ pub(super) fn check<'tcx>( && let Some(err_arg_snippet) = err_arg.span.get_source_text(cx) && let Some(indent) = indent_of(cx, expr.span) { - let reindented_err_arg_snippet = reindent_multiline(err_arg_snippet.as_str().into(), true, Some(indent + 4)); + let reindented_err_arg_snippet = reindent_multiline(err_arg_snippet.as_str(), true, Some(indent + 4)); span_lint_and_sugg( cx, MANUAL_OK_OR, diff --git a/clippy_lints/src/methods/manual_repeat_n.rs b/clippy_lints/src/methods/manual_repeat_n.rs index 6e09bf132aa1..83b57cca17bf 100644 --- a/clippy_lints/src/methods/manual_repeat_n.rs +++ b/clippy_lints/src/methods/manual_repeat_n.rs @@ -14,16 +14,16 @@ pub(super) fn check<'tcx>( expr: &'tcx Expr<'tcx>, repeat_expr: &Expr<'_>, take_arg: &Expr<'_>, - msrv: &Msrv, + msrv: Msrv, ) { - if msrv.meets(msrvs::REPEAT_N) - && !expr.span.from_expansion() + if !expr.span.from_expansion() && is_trait_method(cx, expr, sym::Iterator) && let ExprKind::Call(_, [repeat_arg]) = repeat_expr.kind && let Some(def_id) = fn_def_id(cx, repeat_expr) && cx.tcx.is_diagnostic_item(sym::iter_repeat, def_id) && !expr_use_ctxt(cx, expr).is_ty_unified && let Some(std_or_core) = std_or_core(cx) + && msrv.meets(cx, msrvs::REPEAT_N) { let mut app = Applicability::MachineApplicable; span_lint_and_sugg( diff --git a/clippy_lints/src/methods/manual_try_fold.rs b/clippy_lints/src/methods/manual_try_fold.rs index a56378b5b73a..23dba47f60f4 100644 --- a/clippy_lints/src/methods/manual_try_fold.rs +++ b/clippy_lints/src/methods/manual_try_fold.rs @@ -17,10 +17,9 @@ pub(super) fn check<'tcx>( init: &Expr<'_>, acc: &Expr<'_>, fold_span: Span, - msrv: &Msrv, + msrv: Msrv, ) { if !fold_span.in_external_macro(cx.sess().source_map()) - && msrv.meets(msrvs::ITERATOR_TRY_FOLD) && is_trait_method(cx, expr, sym::Iterator) && let init_ty = cx.typeck_results().expr_ty(init) && let Some(try_trait) = cx.tcx.lang_items().try_trait() @@ -29,6 +28,7 @@ pub(super) fn check<'tcx>( && let ExprKind::Path(qpath) = path.kind && let Res::Def(DefKind::Ctor(_, _), _) = cx.qpath_res(&qpath, path.hir_id) && let ExprKind::Closure(closure) = acc.kind + && msrv.meets(cx, msrvs::ITERATOR_TRY_FOLD) && !is_from_proc_macro(cx, expr) && let Some(args_snip) = closure .fn_arg_span diff --git a/clippy_lints/src/methods/map_clone.rs b/clippy_lints/src/methods/map_clone.rs index b2705e1ffc2d..128b3695f48b 100644 --- a/clippy_lints/src/methods/map_clone.rs +++ b/clippy_lints/src/methods/map_clone.rs @@ -41,7 +41,7 @@ fn should_run_lint(cx: &LateContext<'_>, e: &hir::Expr<'_>, method_id: DefId) -> true } -pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>, msrv: &Msrv) { +pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>, msrv: Msrv) { if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) && should_run_lint(cx, e, method_id) { @@ -169,10 +169,10 @@ fn lint_path(cx: &LateContext<'_>, replace: Span, root: Span, is_copy: bool) { ); } -fn lint_explicit_closure(cx: &LateContext<'_>, replace: Span, root: Span, is_copy: bool, msrv: &Msrv) { +fn lint_explicit_closure(cx: &LateContext<'_>, replace: Span, root: Span, is_copy: bool, msrv: Msrv) { let mut applicability = Applicability::MachineApplicable; - let (message, sugg_method) = if is_copy && msrv.meets(msrvs::ITERATOR_COPIED) { + let (message, sugg_method) = if is_copy && msrv.meets(cx, msrvs::ITERATOR_COPIED) { ("you are using an explicit closure for copying elements", "copied") } else { ("you are using an explicit closure for cloning elements", "cloned") diff --git a/clippy_lints/src/methods/map_unwrap_or.rs b/clippy_lints/src/methods/map_unwrap_or.rs index 428da0cf107e..df5a0de3392b 100644 --- a/clippy_lints/src/methods/map_unwrap_or.rs +++ b/clippy_lints/src/methods/map_unwrap_or.rs @@ -19,13 +19,13 @@ pub(super) fn check<'tcx>( recv: &'tcx hir::Expr<'_>, map_arg: &'tcx hir::Expr<'_>, unwrap_arg: &'tcx hir::Expr<'_>, - msrv: &Msrv, + msrv: Msrv, ) -> bool { // lint if the caller of `map()` is an `Option` or a `Result`. let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option); let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result); - if is_result && !msrv.meets(msrvs::RESULT_MAP_OR_ELSE) { + if is_result && !msrv.meets(cx, msrvs::RESULT_MAP_OR_ELSE) { return false; } diff --git a/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs b/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs index 35dd7c082c90..6cf0936c598f 100644 --- a/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs +++ b/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs @@ -62,7 +62,7 @@ pub(super) fn check( ex: &Expr<'_>, receiver: &Expr<'_>, arg: &Expr<'_>, - msrv: &Msrv, + msrv: Msrv, method_call_span: Span, ) { let mut applicability = Applicability::MaybeIncorrect; @@ -82,7 +82,7 @@ pub(super) fn check( let use_take; if eager_or_lazy::switch_to_eager_eval(cx, body_expr) { - if msrv.meets(msrvs::REPEAT_N) { + if msrv.meets(cx, msrvs::REPEAT_N) { method_to_use_name = "repeat_n"; let body_snippet = snippet_with_applicability(cx, body_expr.span, "..", &mut applicability); new_span = (arg.span, format!("{body_snippet}, {count}")); @@ -93,7 +93,7 @@ pub(super) fn check( new_span = (arg.span, body_snippet.to_string()); use_take = true; } - } else if msrv.meets(msrvs::REPEAT_WITH) { + } else if msrv.meets(cx, msrvs::REPEAT_WITH) { method_to_use_name = "repeat_with"; new_span = (param.span, String::new()); use_take = true; diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index b58e8ba32e78..94d3657d9f12 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -36,6 +36,7 @@ mod implicit_clone; mod inefficient_to_string; mod inspect_for_each; mod into_iter_on_ref; +mod io_other_error; mod is_digit_ascii_radix; mod is_empty; mod iter_cloned_collect; @@ -54,6 +55,7 @@ mod iter_with_drain; mod iterator_step_by_zero; mod join_absolute_paths; mod manual_c_str_literals; +mod manual_contains; mod manual_inspect; mod manual_is_variant_and; mod manual_next_back; @@ -82,7 +84,6 @@ mod ok_expect; mod open_options; mod option_as_ref_cloned; mod option_as_ref_deref; -mod option_map_or_err_ok; mod option_map_or_none; mod option_map_unwrap_or; mod or_fun_call; @@ -114,6 +115,7 @@ mod suspicious_map; mod suspicious_splitn; mod suspicious_to_owned; mod type_id_on_box; +mod unbuffered_bytes; mod uninit_assumed_init; mod unit_hash; mod unnecessary_fallible_conversions; @@ -2642,7 +2644,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.49.0"] pub MANUAL_OK_OR, - pedantic, + style, "finds patterns that can be encoded more concisely with `Option::ok_or`" } @@ -3784,31 +3786,6 @@ declare_clippy_lint! { "calls to `Path::join` which will overwrite the original path" } -declare_clippy_lint! { - /// ### What it does - /// Checks for usage of `_.map_or(Err(_), Ok)`. - /// - /// ### Why is this bad? - /// Readability, this can be written more concisely as - /// `_.ok_or(_)`. - /// - /// ### Example - /// ```no_run - /// # let opt = Some(1); - /// opt.map_or(Err("error"), Ok); - /// ``` - /// - /// Use instead: - /// ```no_run - /// # let opt = Some(1); - /// opt.ok_or("error"); - /// ``` - #[clippy::version = "1.76.0"] - pub OPTION_MAP_OR_ERR_OK, - style, - "using `Option.map_or(Err(_), Ok)`, which is more succinctly expressed as `Option.ok_or(_)`" -} - declare_clippy_lint! { /// ### What it does /// Checks for iterators of `Result`s using `.filter(Result::is_ok).map(Result::unwrap)` that may @@ -4433,11 +4410,88 @@ declare_clippy_lint! { "using `Option::and_then` or `Result::and_then` to chain a computation that returns an `Option` or a `Result`" } +declare_clippy_lint! { + /// ### What it does + /// Checks for calls to `Read::bytes` on types which don't implement `BufRead`. + /// + /// ### Why is this bad? + /// The default implementation calls `read` for each byte, which can be very inefficient for data that’s not in memory, such as `File`. + /// + /// ### Example + /// ```no_run + /// use std::io::Read; + /// use std::fs::File; + /// let file = File::open("./bytes.txt").unwrap(); + /// file.bytes(); + /// ``` + /// Use instead: + /// ```no_run + /// use std::io::{BufReader, Read}; + /// use std::fs::File; + /// let file = BufReader::new(std::fs::File::open("./bytes.txt").unwrap()); + /// file.bytes(); + /// ``` + #[clippy::version = "1.86.0"] + pub UNBUFFERED_BYTES, + perf, + "calling .bytes() is very inefficient when data is not in memory" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of `iter().any()` on slices when it can be replaced with `contains()` and suggests doing so. + /// + /// ### Why is this bad? + /// `contains()` is more concise and idiomatic, sometimes more fast. + /// + /// ### Example + /// ```no_run + /// fn foo(values: &[u8]) -> bool { + /// values.iter().any(|&v| v == 10) + /// } + /// ``` + /// Use instead: + /// ```no_run + /// fn foo(values: &[u8]) -> bool { + /// values.contains(&10) + /// } + /// ``` + #[clippy::version = "1.86.0"] + pub MANUAL_CONTAINS, + perf, + "unnecessary `iter().any()` on slices that can be replaced with `contains()`" +} + +declare_clippy_lint! { + /// This lint warns on calling `io::Error::new(..)` with a kind of + /// `io::ErrorKind::Other`. + /// + /// ### Why is this bad? + /// Since Rust 1.74, there's the `io::Error::other(_)` shortcut. + /// + /// ### Example + /// ```no_run + /// use std::io; + /// let _ = io::Error::new(io::ErrorKind::Other, "bad".to_string()); + /// ``` + /// Use instead: + /// ```no_run + /// let _ = std::io::Error::other("bad".to_string()); + /// ``` + #[clippy::version = "1.86.0"] + pub IO_OTHER_ERROR, + style, + "calling `std::io::Error::new(std::io::ErrorKind::Other, _)`" +} + +#[expect(clippy::struct_excessive_bools)] pub struct Methods { avoid_breaking_exported_api: bool, msrv: Msrv, allow_expect_in_tests: bool, allow_unwrap_in_tests: bool, + allow_expect_in_consts: bool, + allow_unwrap_in_consts: bool, allowed_dotfiles: FxHashSet<&'static str>, format_args: FormatArgsStorage, } @@ -4449,9 +4503,11 @@ impl Methods { Self { avoid_breaking_exported_api: conf.avoid_breaking_exported_api, - msrv: conf.msrv.clone(), + msrv: conf.msrv, allow_expect_in_tests: conf.allow_expect_in_tests, allow_unwrap_in_tests: conf.allow_unwrap_in_tests, + allow_expect_in_consts: conf.allow_expect_in_consts, + allow_unwrap_in_consts: conf.allow_unwrap_in_consts, allowed_dotfiles, format_args, } @@ -4580,7 +4636,6 @@ impl_lint_pass!(Methods => [ WAKER_CLONE_WAKE, UNNECESSARY_FALLIBLE_CONVERSIONS, JOIN_ABSOLUTE_PATHS, - OPTION_MAP_OR_ERR_OK, RESULT_FILTER_MAP, ITER_FILTER_IS_SOME, ITER_FILTER_IS_OK, @@ -4603,6 +4658,9 @@ impl_lint_pass!(Methods => [ MANUAL_REPEAT_N, SLICED_STRING_AS_BYTES, RETURN_AND_THEN, + UNBUFFERED_BYTES, + MANUAL_CONTAINS, + IO_OTHER_ERROR, ]); /// Extracts a method call name, args, and `Span` of the method name. @@ -4630,8 +4688,9 @@ impl<'tcx> LateLintPass<'tcx> for Methods { ExprKind::Call(func, args) => { from_iter_instead_of_collect::check(cx, expr, args, func); unnecessary_fallible_conversions::check_function(cx, expr, func); - manual_c_str_literals::check(cx, expr, func, args, &self.msrv); - useless_nonzero_new_unchecked::check(cx, expr, func, args, &self.msrv); + manual_c_str_literals::check(cx, expr, func, args, self.msrv); + useless_nonzero_new_unchecked::check(cx, expr, func, args, self.msrv); + io_other_error::check(cx, expr, func, args, self.msrv); }, ExprKind::MethodCall(method_call, receiver, args, _) => { let method_span = method_call.ident.span; @@ -4650,7 +4709,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { inefficient_to_string::check(cx, expr, method_call.ident.name, receiver, args); single_char_add_str::check(cx, expr, receiver, args); into_iter_on_ref::check(cx, expr, method_span, method_call.ident.name, receiver); - unnecessary_to_owned::check(cx, expr, method_call.ident.name, receiver, args, &self.msrv); + unnecessary_to_owned::check(cx, expr, method_call.ident.name, receiver, args, self.msrv); }, ExprKind::Binary(op, lhs, rhs) if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne => { let mut info = BinaryExprInfo { @@ -4796,8 +4855,6 @@ impl<'tcx> LateLintPass<'tcx> for Methods { ); } } - - extract_msrv_attr!(LateContext); } impl Methods { @@ -4855,11 +4912,14 @@ impl Methods { && let body = cx.tcx.hir_body(arg.body) && let [param] = body.params => { - string_lit_chars_any::check(cx, expr, recv, param, peel_blocks(body.value), &self.msrv); + string_lit_chars_any::check(cx, expr, recv, param, peel_blocks(body.value), self.msrv); }, Some(("map", _, [map_arg], _, map_call_span)) => { map_all_any_identity::check(cx, expr, recv, map_call_span, map_arg, call_span, arg, "any"); }, + Some(("iter", iter_recv, ..)) => { + manual_contains::check(cx, expr, iter_recv, arg); + }, _ => {}, } }, @@ -4876,11 +4936,12 @@ impl Methods { sliced_string_as_bytes::check(cx, expr, recv); }, ("as_mut", []) => useless_asref::check(cx, expr, "as_mut", recv), - ("as_ptr", []) => manual_c_str_literals::check_as_ptr(cx, expr, recv, &self.msrv), + ("as_ptr", []) => manual_c_str_literals::check_as_ptr(cx, expr, recv, self.msrv), ("as_ref", []) => useless_asref::check(cx, expr, "as_ref", recv), ("assume_init", []) => uninit_assumed_init::check(cx, expr, recv), + ("bytes", []) => unbuffered_bytes::check(cx, expr, recv), ("cloned", []) => { - cloned_instead_of_copied::check(cx, expr, recv, span, &self.msrv); + cloned_instead_of_copied::check(cx, expr, recv, span, self.msrv); option_as_ref_cloned::check(cx, recv, span); }, ("collect", []) if is_trait_method(cx, expr, sym::Iterator) => { @@ -4894,7 +4955,7 @@ impl Methods { format_collect::check(cx, expr, m_arg, m_ident_span); }, Some(("take", take_self_arg, [take_arg], _, _)) => { - if self.msrv.meets(msrvs::STR_REPEAT) { + if self.msrv.meets(cx, msrvs::STR_REPEAT) { manual_str_repeat::check(cx, expr, recv, take_self_arg, take_arg); } }, @@ -4933,19 +4994,20 @@ impl Methods { if let ExprKind::MethodCall(.., span) = expr.kind { case_sensitive_file_extension_comparisons::check(cx, expr, span, recv, arg); } - path_ends_with_ext::check(cx, recv, arg, expr, &self.msrv, &self.allowed_dotfiles); + path_ends_with_ext::check(cx, recv, arg, expr, self.msrv, &self.allowed_dotfiles); }, ("expect", [_]) => { match method_call(recv) { Some(("ok", recv, [], _, _)) => ok_expect::check(cx, expr, recv), Some(("err", recv, [], err_span, _)) => { - err_expect::check(cx, expr, recv, span, err_span, &self.msrv); + err_expect::check(cx, expr, recv, span, err_span, self.msrv); }, _ => unwrap_expect_used::check( cx, expr, recv, false, + self.allow_expect_in_consts, self.allow_expect_in_tests, unwrap_expect_used::Variant::Expect, ), @@ -4959,6 +5021,7 @@ impl Methods { expr, recv, true, + self.allow_expect_in_consts, self.allow_expect_in_tests, unwrap_expect_used::Variant::Expect, ); @@ -4979,7 +5042,7 @@ impl Methods { false, ); } - if self.msrv.meets(msrvs::ITER_FLATTEN) { + if self.msrv.meets(cx, msrvs::ITER_FLATTEN) { // use the sourcemap to get the span of the closure iter_filter::check(cx, expr, arg, span); } @@ -5027,7 +5090,7 @@ impl Methods { _ => {}, }, ("fold", [init, acc]) => { - manual_try_fold::check(cx, expr, init, acc, call_span, &self.msrv); + manual_try_fold::check(cx, expr, init, acc, call_span, self.msrv); unnecessary_fold::check(cx, expr, init, acc, span); }, ("for_each", [arg]) => { @@ -5068,7 +5131,7 @@ impl Methods { is_empty::check(cx, expr, recv); }, ("is_file", []) => filetype_is_file::check(cx, expr, recv), - ("is_digit", [radix]) => is_digit_ascii_radix::check(cx, expr, recv, radix, &self.msrv), + ("is_digit", [radix]) => is_digit_ascii_radix::check(cx, expr, recv, radix, self.msrv), ("is_none", []) => check_is_some_is_none(cx, expr, recv, call_span, false), ("is_some", []) => check_is_some_is_none(cx, expr, recv, call_span, true), ("iter" | "iter_mut" | "into_iter", []) => { @@ -5105,11 +5168,11 @@ impl Methods { (name @ ("map" | "map_err"), [m_arg]) => { if name == "map" { unused_enumerate_index::check(cx, expr, recv, m_arg); - map_clone::check(cx, expr, recv, m_arg, &self.msrv); - map_with_unused_argument_over_ranges::check(cx, expr, recv, m_arg, &self.msrv, span); + map_clone::check(cx, expr, recv, m_arg, self.msrv); + map_with_unused_argument_over_ranges::check(cx, expr, recv, m_arg, self.msrv, span); match method_call(recv) { Some((map_name @ ("iter" | "into_iter"), recv2, _, _, _)) => { - iter_kv_map::check(cx, map_name, expr, recv2, m_arg, &self.msrv); + iter_kv_map::check(cx, map_name, expr, recv2, m_arg, self.msrv); }, Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check( cx, @@ -5126,8 +5189,8 @@ impl Methods { } if let Some((name, recv2, args, span2, _)) = method_call(recv) { match (name, args) { - ("as_mut", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, true, &self.msrv), - ("as_ref", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, false, &self.msrv), + ("as_mut", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, true, self.msrv), + ("as_ref", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, false, self.msrv), ("filter", [f_arg]) => { filter_map::check(cx, expr, recv2, f_arg, span2, recv, m_arg, span, false); }, @@ -5138,7 +5201,7 @@ impl Methods { } } map_identity::check(cx, expr, recv, m_arg, name, span); - manual_inspect::check(cx, expr, m_arg, name, span, &self.msrv); + manual_inspect::check(cx, expr, m_arg, name, span, self.msrv); crate::useless_conversion::check_function_application(cx, expr, recv, m_arg); }, ("map_break" | "map_continue", [m_arg]) => { @@ -5147,8 +5210,7 @@ impl Methods { ("map_or", [def, map]) => { option_map_or_none::check(cx, expr, recv, def, map); manual_ok_or::check(cx, expr, recv, def, map); - option_map_or_err_ok::check(cx, expr, recv, def, map); - unnecessary_map_or::check(cx, expr, recv, def, map, span, &self.msrv); + unnecessary_map_or::check(cx, expr, recv, def, map, span, self.msrv); }, ("map_or_else", [def, map]) => { result_map_or_else_none::check(cx, expr, recv, def, map); @@ -5166,7 +5228,7 @@ impl Methods { false, ), ("filter", [arg]) => filter_next::check(cx, expr, recv2, arg), - ("filter_map", [arg]) => filter_map_next::check(cx, expr, recv2, arg, &self.msrv), + ("filter_map", [arg]) => filter_map_next::check(cx, expr, recv2, arg, self.msrv), ("iter", []) => iter_next_slice::check(cx, expr, recv2), ("skip", [arg]) => iter_skip_next::check(cx, expr, recv2, arg), ("skip_while", [_]) => skip_while_next::check(cx, expr), @@ -5222,7 +5284,7 @@ impl Methods { no_effect_replace::check(cx, expr, arg1, arg2); // Check for repeated `str::replace` calls to perform `collapsible_str_replace` lint - if self.msrv.meets(msrvs::PATTERN_TRAIT_CHAR_ARRAY) + if self.msrv.meets(cx, msrvs::PATTERN_TRAIT_CHAR_ARRAY) && name == "replace" && let Some(("replace", ..)) = method_call(recv) { @@ -5233,10 +5295,10 @@ impl Methods { vec_resize_to_zero::check(cx, expr, count_arg, default_arg, span); }, ("seek", [arg]) => { - if self.msrv.meets(msrvs::SEEK_FROM_CURRENT) { + if self.msrv.meets(cx, msrvs::SEEK_FROM_CURRENT) { seek_from_current::check(cx, expr, recv, arg); } - if self.msrv.meets(msrvs::SEEK_REWIND) { + if self.msrv.meets(cx, msrvs::SEEK_REWIND) { seek_to_start_instead_of_rewind::check(cx, expr, recv, arg, span); } }, @@ -5270,7 +5332,7 @@ impl Methods { ("splitn" | "rsplitn", [count_arg, pat_arg]) => { if let Some(Constant::Int(count)) = ConstEvalCtxt::new(cx).eval(count_arg) { suspicious_splitn::check(cx, name, expr, recv, count); - str_splitn::check(cx, name, expr, recv, pat_arg, count, &self.msrv); + str_splitn::check(cx, name, expr, recv, pat_arg, count, self.msrv); } }, ("splitn_mut" | "rsplitn_mut", [count_arg, _]) => { @@ -5281,7 +5343,7 @@ impl Methods { ("step_by", [arg]) => iterator_step_by_zero::check(cx, expr, arg), ("take", [arg]) => { iter_out_of_bounds::check_take(cx, expr, recv, arg); - manual_repeat_n::check(cx, expr, recv, arg, &self.msrv); + manual_repeat_n::check(cx, expr, recv, arg, self.msrv); if let Some(("cloned", recv2, [], _span2, _)) = method_call(recv) { iter_overeager_cloned::check( cx, @@ -5295,7 +5357,7 @@ impl Methods { }, ("take", []) => needless_option_take::check(cx, expr, recv), ("then", [arg]) => { - if !self.msrv.meets(msrvs::BOOL_THEN_SOME) { + if !self.msrv.meets(cx, msrvs::BOOL_THEN_SOME) { return; } unnecessary_lazy_eval::check(cx, expr, recv, arg, "then_some"); @@ -5333,6 +5395,7 @@ impl Methods { expr, recv, false, + self.allow_unwrap_in_consts, self.allow_unwrap_in_tests, unwrap_expect_used::Variant::Unwrap, ); @@ -5344,6 +5407,7 @@ impl Methods { expr, recv, true, + self.allow_unwrap_in_consts, self.allow_unwrap_in_tests, unwrap_expect_used::Variant::Unwrap, ); @@ -5354,10 +5418,10 @@ impl Methods { manual_saturating_arithmetic::check(cx, expr, lhs, rhs, u_arg, &arith["checked_".len()..]); }, Some(("map", m_recv, [m_arg], span, _)) => { - option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span, &self.msrv); + option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span, self.msrv); }, Some((then_method @ ("then" | "then_some"), t_recv, [t_arg], _, _)) => { - obfuscated_if_else::check(cx, expr, t_recv, t_arg, u_arg, then_method); + obfuscated_if_else::check(cx, expr, t_recv, t_arg, u_arg, then_method, "unwrap_or"); }, _ => {}, } @@ -5365,7 +5429,7 @@ impl Methods { }, ("unwrap_or_default", []) => { if let Some(("map", m_recv, [arg], span, _)) = method_call(recv) { - manual_is_variant_and::check(cx, expr, m_recv, arg, span, &self.msrv); + manual_is_variant_and::check(cx, expr, m_recv, arg, span, self.msrv); } unnecessary_literal_unwrap::check(cx, expr, recv, name, args); }, @@ -5375,7 +5439,10 @@ impl Methods { ("unwrap_or_else", [u_arg]) => { match method_call(recv) { Some(("map", recv, [map_arg], _, _)) - if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, &self.msrv) => {}, + if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, self.msrv) => {}, + Some((then_method @ ("then" | "then_some"), t_recv, [t_arg], _, _)) => { + obfuscated_if_else::check(cx, expr, t_recv, t_arg, u_arg, then_method, "unwrap_or_else"); + }, _ => { unnecessary_lazy_eval::check(cx, expr, recv, u_arg, "unwrap_or"); }, diff --git a/clippy_lints/src/methods/obfuscated_if_else.rs b/clippy_lints/src/methods/obfuscated_if_else.rs index e0905374ddaa..9a5ffdeaf4e8 100644 --- a/clippy_lints/src/methods/obfuscated_if_else.rs +++ b/clippy_lints/src/methods/obfuscated_if_else.rs @@ -1,6 +1,7 @@ use super::OBFUSCATED_IF_ELSE; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::eager_or_lazy::switch_to_eager_eval; +use clippy_utils::get_parent_expr; use clippy_utils::source::snippet_with_applicability; use clippy_utils::sugg::Sugg; use rustc_errors::Applicability; @@ -15,6 +16,7 @@ pub(super) fn check<'tcx>( then_arg: &'tcx hir::Expr<'_>, unwrap_arg: &'tcx hir::Expr<'_>, then_method_name: &str, + unwrap_method_name: &str, ) { let recv_ty = cx.typeck_results().expr_ty(then_recv); @@ -31,16 +33,40 @@ pub(super) fn check<'tcx>( snippet_with_applicability(cx, body.value.span, "..", &mut applicability) }, "then_some" => snippet_with_applicability(cx, then_arg.span, "..", &mut applicability), - _ => String::new().into(), + _ => return, + }; + + // FIXME: Add `unwrap_or_else` symbol + let els = match unwrap_method_name { + "unwrap_or" => snippet_with_applicability(cx, unwrap_arg.span, "..", &mut applicability), + "unwrap_or_else" if let ExprKind::Closure(closure) = unwrap_arg.kind => { + let body = cx.tcx.hir_body(closure.body); + snippet_with_applicability(cx, body.value.span, "..", &mut applicability) + }, + "unwrap_or_else" if let ExprKind::Path(_) = unwrap_arg.kind => { + snippet_with_applicability(cx, unwrap_arg.span, "_", &mut applicability) + "()" + }, + _ => return, }; let sugg = format!( "if {} {{ {} }} else {{ {} }}", Sugg::hir_with_applicability(cx, then_recv, "..", &mut applicability), if_then, - snippet_with_applicability(cx, unwrap_arg.span, "..", &mut applicability) + els ); + // To be parsed as an expression, the `if { … } else { … }` as the left operand of a binary operator + // requires parentheses. + let sugg = if let Some(parent_expr) = get_parent_expr(cx, expr) + && let ExprKind::Binary(_, left, _) = parent_expr.kind + && left.hir_id == expr.hir_id + { + format!("({sugg})") + } else { + sugg + }; + span_lint_and_sugg( cx, OBFUSCATED_IF_ELSE, diff --git a/clippy_lints/src/methods/option_as_ref_deref.rs b/clippy_lints/src/methods/option_as_ref_deref.rs index 469fcccbe4f6..63ee922acfa0 100644 --- a/clippy_lints/src/methods/option_as_ref_deref.rs +++ b/clippy_lints/src/methods/option_as_ref_deref.rs @@ -18,12 +18,8 @@ pub(super) fn check( as_ref_recv: &hir::Expr<'_>, map_arg: &hir::Expr<'_>, is_mut: bool, - msrv: &Msrv, + msrv: Msrv, ) { - if !msrv.meets(msrvs::OPTION_AS_DEREF) { - return; - } - let same_mutability = |m| (is_mut && m == &hir::Mutability::Mut) || (!is_mut && m == &hir::Mutability::Not); let option_ty = cx.typeck_results().expr_ty(as_ref_recv); @@ -93,7 +89,7 @@ pub(super) fn check( _ => false, }; - if is_deref { + if is_deref && msrv.meets(cx, msrvs::OPTION_AS_DEREF) { let current_method = if is_mut { format!(".as_mut().map({})", snippet(cx, map_arg.span, "..")) } else { diff --git a/clippy_lints/src/methods/option_map_or_err_ok.rs b/clippy_lints/src/methods/option_map_or_err_ok.rs deleted file mode 100644 index 4e424d4c066a..000000000000 --- a/clippy_lints/src/methods/option_map_or_err_ok.rs +++ /dev/null @@ -1,41 +0,0 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet; -use clippy_utils::ty::is_type_diagnostic_item; -use clippy_utils::{is_res_lang_ctor, path_res}; -use rustc_errors::Applicability; -use rustc_hir::LangItem::{ResultErr, ResultOk}; -use rustc_hir::{Expr, ExprKind}; -use rustc_lint::LateContext; -use rustc_span::symbol::sym; - -use super::OPTION_MAP_OR_ERR_OK; - -pub(super) fn check<'tcx>( - cx: &LateContext<'tcx>, - expr: &'tcx Expr<'tcx>, - recv: &'tcx Expr<'_>, - or_expr: &'tcx Expr<'_>, - map_expr: &'tcx Expr<'_>, -) { - // We check that it's called on an `Option` type. - if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option) - // We check that first we pass an `Err`. - && let ExprKind::Call(call, &[arg]) = or_expr.kind - && is_res_lang_ctor(cx, path_res(cx, call), ResultErr) - // And finally we check that it is mapped as `Ok`. - && is_res_lang_ctor(cx, path_res(cx, map_expr), ResultOk) - { - let msg = "called `map_or(Err(_), Ok)` on an `Option` value"; - let self_snippet = snippet(cx, recv.span, ".."); - let err_snippet = snippet(cx, arg.span, ".."); - span_lint_and_sugg( - cx, - OPTION_MAP_OR_ERR_OK, - expr.span, - msg, - "consider using `ok_or`", - format!("{self_snippet}.ok_or({err_snippet})"), - Applicability::MachineApplicable, - ); - } -} diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs index b1107d8cc72f..4ba8e0109042 100644 --- a/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -24,7 +24,7 @@ pub(super) fn check<'tcx>( unwrap_recv: &rustc_hir::Expr<'_>, unwrap_arg: &'tcx rustc_hir::Expr<'_>, map_span: Span, - msrv: &Msrv, + msrv: Msrv, ) { // lint if the caller of `map()` is an `Option` if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option) { @@ -71,9 +71,9 @@ pub(super) fn check<'tcx>( } // is_some_and is stabilised && `unwrap_or` argument is false; suggest `is_some_and` instead - let suggest_is_some_and = msrv.meets(msrvs::OPTION_RESULT_IS_VARIANT_AND) - && matches!(&unwrap_arg.kind, ExprKind::Lit(lit) - if matches!(lit.node, rustc_ast::LitKind::Bool(false))); + let suggest_is_some_and = matches!(&unwrap_arg.kind, ExprKind::Lit(lit) + if matches!(lit.node, rustc_ast::LitKind::Bool(false))) + && msrv.meets(cx, msrvs::OPTION_RESULT_IS_VARIANT_AND); let mut applicability = Applicability::MachineApplicable; // get snippet for unwrap_or() diff --git a/clippy_lints/src/methods/or_fun_call.rs b/clippy_lints/src/methods/or_fun_call.rs index 69f933fee68f..c03420a5143e 100644 --- a/clippy_lints/src/methods/or_fun_call.rs +++ b/clippy_lints/src/methods/or_fun_call.rs @@ -104,7 +104,7 @@ pub(super) fn check<'tcx>( if (is_new(fun) && output_type_implements_default(fun)) || match call_expr { Some(call_expr) => is_default_equivalent(cx, call_expr), - None => is_default_equivalent_call(cx, fun) || closure_body_returns_empty_to_string(cx, fun), + None => is_default_equivalent_call(cx, fun, None) || closure_body_returns_empty_to_string(cx, fun), } { span_lint_and_sugg( diff --git a/clippy_lints/src/methods/path_buf_push_overwrite.rs b/clippy_lints/src/methods/path_buf_push_overwrite.rs index 2d3007e50b81..38d9c5f16778 100644 --- a/clippy_lints/src/methods/path_buf_push_overwrite.rs +++ b/clippy_lints/src/methods/path_buf_push_overwrite.rs @@ -28,7 +28,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t "calling `push` with '/' or '\\' (file system root) will overwrite the previous path definition", "try", format!("\"{}\"", pushed_path_lit.trim_start_matches(['/', '\\'])), - Applicability::MachineApplicable, + Applicability::MaybeIncorrect, ); } } diff --git a/clippy_lints/src/methods/path_ends_with_ext.rs b/clippy_lints/src/methods/path_ends_with_ext.rs index b3811a335e1a..d3f513e7abd2 100644 --- a/clippy_lints/src/methods/path_ends_with_ext.rs +++ b/clippy_lints/src/methods/path_ends_with_ext.rs @@ -20,7 +20,7 @@ pub(super) fn check( recv: &Expr<'_>, path: &Expr<'_>, expr: &Expr<'_>, - msrv: &Msrv, + msrv: Msrv, allowed_dotfiles: &FxHashSet<&'static str>, ) { if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv).peel_refs(), sym::Path) @@ -33,7 +33,7 @@ pub(super) fn check( && path.chars().all(char::is_alphanumeric) { let mut sugg = snippet(cx, recv.span, "..").into_owned(); - if msrv.meets(msrvs::OPTION_RESULT_IS_VARIANT_AND) { + if msrv.meets(cx, msrvs::OPTION_RESULT_IS_VARIANT_AND) { let _ = write!(sugg, r#".extension().is_some_and(|ext| ext == "{path}")"#); } else { let _ = write!(sugg, r#".extension().map_or(false, |ext| ext == "{path}")"#); diff --git a/clippy_lints/src/methods/range_zip_with_len.rs b/clippy_lints/src/methods/range_zip_with_len.rs index f4d206c5307c..3a5e32172086 100644 --- a/clippy_lints/src/methods/range_zip_with_len.rs +++ b/clippy_lints/src/methods/range_zip_with_len.rs @@ -1,6 +1,7 @@ -use clippy_utils::diagnostics::span_lint; +use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; use clippy_utils::{SpanlessEq, higher, is_integer_const, is_trait_method}; +use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::LateContext; use rustc_span::sym; @@ -20,14 +21,14 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &' && let ExprKind::Path(QPath::Resolved(_, len_path)) = len_recv.kind && SpanlessEq::new(cx).eq_path_segments(iter_path.segments, len_path.segments) { - span_lint( + span_lint_and_sugg( cx, RANGE_ZIP_WITH_LEN, expr.span, - format!( - "it is more idiomatic to use `{}.iter().enumerate()`", - snippet(cx, recv.span, "_") - ), + "using `.zip()` with a range and `.len()`", + "try", + format!("{}.iter().enumerate()", snippet(cx, recv.span, "_")), + Applicability::MachineApplicable, ); } } diff --git a/clippy_lints/src/methods/read_line_without_trim.rs b/clippy_lints/src/methods/read_line_without_trim.rs index 82e66a0500a8..c9251c1b8497 100644 --- a/clippy_lints/src/methods/read_line_without_trim.rs +++ b/clippy_lints/src/methods/read_line_without_trim.rs @@ -1,11 +1,10 @@ use std::ops::ControlFlow; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::paths::STDIN; +use clippy_utils::get_parent_expr; use clippy_utils::source::snippet; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::visitors::for_each_local_use_after_expr; -use clippy_utils::{get_parent_expr, match_def_path}; use rustc_ast::LitKind; use rustc_errors::Applicability; use rustc_hir::def::Res; @@ -34,7 +33,7 @@ fn parse_fails_on_trailing_newline(ty: Ty<'_>) -> bool { pub fn check(cx: &LateContext<'_>, call: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<'_>) { if let Some(recv_adt) = cx.typeck_results().expr_ty(recv).ty_adt_def() - && match_def_path(cx, recv_adt.did(), &STDIN) + && cx.tcx.is_diagnostic_item(sym::Stdin, recv_adt.did()) && let ExprKind::Path(QPath::Resolved(_, path)) = arg.peel_borrows().kind && let Res::Local(local_id) = path.res { diff --git a/clippy_lints/src/methods/return_and_then.rs b/clippy_lints/src/methods/return_and_then.rs index 68ffa81a2781..e8861935d421 100644 --- a/clippy_lints/src/methods/return_and_then.rs +++ b/clippy_lints/src/methods/return_and_then.rs @@ -60,7 +60,7 @@ pub(super) fn check<'tcx>( "let {} = {}?;\n{}", arg_snip, recv_snip, - reindent_multiline(inner.into(), false, indent_of(cx, expr.span)) + reindent_multiline(inner, false, indent_of(cx, expr.span)) ); span_lint_and_sugg(cx, RETURN_AND_THEN, expr.span, msg, "try", sugg, applicability); diff --git a/clippy_lints/src/methods/str_splitn.rs b/clippy_lints/src/methods/str_splitn.rs index 8389c2e3f982..4ccefb7ec9d7 100644 --- a/clippy_lints/src/methods/str_splitn.rs +++ b/clippy_lints/src/methods/str_splitn.rs @@ -23,7 +23,7 @@ pub(super) fn check( self_arg: &Expr<'_>, pat_arg: &Expr<'_>, count: u128, - msrv: &Msrv, + msrv: Msrv, ) { if count < 2 || !cx.typeck_results().expr_ty_adjusted(self_arg).peel_refs().is_str() { return; @@ -33,7 +33,7 @@ pub(super) fn check( IterUsageKind::Nth(n) => count > n + 1, IterUsageKind::NextTuple => count > 2, }; - let manual = count == 2 && msrv.meets(msrvs::STR_SPLIT_ONCE); + let manual = count == 2 && msrv.meets(cx, msrvs::STR_SPLIT_ONCE); match parse_iter_usage(cx, expr.span.ctxt(), cx.tcx.hir_parent_iter(expr.hir_id)) { Some(usage) if needless(usage.kind) => lint_needless(cx, method_name, expr, self_arg, pat_arg), diff --git a/clippy_lints/src/methods/string_lit_chars_any.rs b/clippy_lints/src/methods/string_lit_chars_any.rs index cb719b34b1f0..f0f9d30d3000 100644 --- a/clippy_lints/src/methods/string_lit_chars_any.rs +++ b/clippy_lints/src/methods/string_lit_chars_any.rs @@ -17,10 +17,9 @@ pub(super) fn check<'tcx>( recv: &Expr<'_>, param: &'tcx Param<'tcx>, body: &Expr<'_>, - msrv: &Msrv, + msrv: Msrv, ) { - if msrv.meets(msrvs::MATCHES_MACRO) - && is_trait_method(cx, expr, sym::Iterator) + if is_trait_method(cx, expr, sym::Iterator) && let PatKind::Binding(_, arg, _, _) = param.pat.kind && let ExprKind::Lit(lit_kind) = recv.kind && let LitKind::Str(val, _) = lit_kind.node @@ -33,6 +32,7 @@ pub(super) fn check<'tcx>( (false, true) => lhs, _ => return, } + && msrv.meets(cx, msrvs::MATCHES_MACRO) && !is_from_proc_macro(cx, expr) && let Some(scrutinee_snip) = scrutinee.span.get_source_text(cx) { diff --git a/clippy_lints/src/methods/unbuffered_bytes.rs b/clippy_lints/src/methods/unbuffered_bytes.rs new file mode 100644 index 000000000000..dd5566f8c8ba --- /dev/null +++ b/clippy_lints/src/methods/unbuffered_bytes.rs @@ -0,0 +1,25 @@ +use super::UNBUFFERED_BYTES; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::is_trait_method; +use clippy_utils::ty::implements_trait; +use rustc_hir as hir; +use rustc_lint::LateContext; +use rustc_span::sym; + +pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) { + // Lint if the `.bytes()` call is from the `Read` trait and the implementor is not buffered. + if is_trait_method(cx, expr, sym::IoRead) + && let Some(buf_read) = cx.tcx.get_diagnostic_item(sym::IoBufRead) + && let ty = cx.typeck_results().expr_ty_adjusted(recv) + && !implements_trait(cx, ty, buf_read, &[]) + { + span_lint_and_help( + cx, + UNBUFFERED_BYTES, + expr.span, + "calling .bytes() is very inefficient when data is not in memory", + None, + "consider using `BufReader`", + ); + } +} diff --git a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs index 00690aca6d13..fa3a29e36670 100644 --- a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs +++ b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs @@ -98,10 +98,7 @@ pub(super) fn check( ]), ("None", "unwrap_or_else", _) => match args[0].kind { hir::ExprKind::Closure(hir::Closure { body, .. }) => Some(vec![ - ( - expr.span.with_hi(cx.tcx.hir_body(*body).value.span.lo()), - String::new(), - ), + (expr.span.with_hi(cx.tcx.hir_body(*body).value.span.lo()), String::new()), (expr.span.with_lo(args[0].span.hi()), String::new()), ]), _ => None, diff --git a/clippy_lints/src/methods/unnecessary_map_or.rs b/clippy_lints/src/methods/unnecessary_map_or.rs index 5f88a7fd31f2..d7bd522ddab9 100644 --- a/clippy_lints/src/methods/unnecessary_map_or.rs +++ b/clippy_lints/src/methods/unnecessary_map_or.rs @@ -4,7 +4,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::eager_or_lazy::switch_to_eager_eval; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::sugg::{Sugg, make_binop}; -use clippy_utils::ty::{get_type_diagnostic_name, implements_trait}; +use clippy_utils::ty::{get_type_diagnostic_name, implements_trait, is_copy}; use clippy_utils::visitors::is_local_used; use clippy_utils::{get_parent_expr, is_from_proc_macro, path_to_local_id}; use rustc_ast::LitKind::Bool; @@ -42,7 +42,7 @@ pub(super) fn check<'a>( def: &Expr<'_>, map: &Expr<'_>, method_span: Span, - msrv: &Msrv, + msrv: Msrv, ) { let ExprKind::Lit(def_kind) = def.kind else { return; @@ -81,9 +81,11 @@ pub(super) fn check<'a>( && (path_to_local_id(l, hir_id) ^ path_to_local_id(r, hir_id)) && !is_local_used(cx, non_binding_location, hir_id) && let typeck_results = cx.typeck_results() - && typeck_results.expr_ty(l) == typeck_results.expr_ty(r) + && let l_ty = typeck_results.expr_ty(l) + && l_ty == typeck_results.expr_ty(r) && let Some(partial_eq) = cx.tcx.get_diagnostic_item(sym::PartialEq) && implements_trait(cx, recv_ty, partial_eq, &[recv_ty.into()]) + && is_copy(cx, l_ty) { let wrap = variant.variant_name(); @@ -117,14 +119,14 @@ pub(super) fn check<'a>( .into_string(); (vec![(expr.span, sugg)], "a standard comparison", app) - } else if !def_bool && msrv.meets(msrvs::OPTION_RESULT_IS_VARIANT_AND) { + } else if !def_bool && msrv.meets(cx, msrvs::OPTION_RESULT_IS_VARIANT_AND) { let suggested_name = variant.method_name(); ( vec![(method_span, suggested_name.into()), (ext_def_span, String::default())], suggested_name, Applicability::MachineApplicable, ) - } else if def_bool && matches!(variant, Variant::Some) && msrv.meets(msrvs::IS_NONE_OR) { + } else if def_bool && matches!(variant, Variant::Some) && msrv.meets(cx, msrvs::IS_NONE_OR) { ( vec![(method_span, "is_none_or".into()), (ext_def_span, String::default())], "is_none_or", diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index ea134c057053..a71b3659fd24 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -31,7 +31,7 @@ pub fn check<'tcx>( method_name: Symbol, receiver: &'tcx Expr<'_>, args: &'tcx [Expr<'_>], - msrv: &Msrv, + msrv: Msrv, ) { if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) && args.is_empty() @@ -207,7 +207,7 @@ fn check_into_iter_call_arg( expr: &Expr<'_>, method_name: Symbol, receiver: &Expr<'_>, - msrv: &Msrv, + msrv: Msrv, ) -> bool { if let Some(parent) = get_parent_expr(cx, expr) && let Some(callee_def_id) = fn_def_id(cx, parent) @@ -224,7 +224,7 @@ fn check_into_iter_call_arg( return true; } - let cloned_or_copied = if is_copy(cx, item_ty) && msrv.meets(msrvs::ITERATOR_COPIED) { + let cloned_or_copied = if is_copy(cx, item_ty) && msrv.meets(cx, msrvs::ITERATOR_COPIED) { "copied" } else { "cloned" diff --git a/clippy_lints/src/methods/unwrap_expect_used.rs b/clippy_lints/src/methods/unwrap_expect_used.rs index 5b0bd0f716ab..027215e3b4d7 100644 --- a/clippy_lints/src/methods/unwrap_expect_used.rs +++ b/clippy_lints/src/methods/unwrap_expect_used.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::ty::{is_never_like, is_type_diagnostic_item}; -use clippy_utils::{is_in_test, is_lint_allowed}; +use clippy_utils::{is_in_test, is_inside_always_const_context, is_lint_allowed}; use rustc_hir::Expr; use rustc_lint::{LateContext, Lint}; use rustc_middle::ty; @@ -39,6 +39,7 @@ pub(super) fn check( expr: &Expr<'_>, recv: &Expr<'_>, is_err: bool, + allow_unwrap_in_consts: bool, allow_unwrap_in_tests: bool, variant: Variant, ) { @@ -65,6 +66,10 @@ pub(super) fn check( return; } + if allow_unwrap_in_consts && is_inside_always_const_context(cx.tcx, expr.hir_id) { + return; + } + span_lint_and_then( cx, variant.lint(), diff --git a/clippy_lints/src/methods/useless_asref.rs b/clippy_lints/src/methods/useless_asref.rs index 19152362fb5f..0cbf6004be3a 100644 --- a/clippy_lints/src/methods/useless_asref.rs +++ b/clippy_lints/src/methods/useless_asref.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::ty::{should_call_clone_as_function, walk_ptrs_ty_depth}; +use clippy_utils::ty::{implements_trait, should_call_clone_as_function, walk_ptrs_ty_depth}; use clippy_utils::{ get_parent_expr, is_diag_trait_item, match_def_path, path_to_local_id, peel_blocks, strip_pat_refs, }; @@ -55,12 +55,19 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str, let (base_res_ty, res_depth) = walk_ptrs_ty_depth(res_ty); let (base_rcv_ty, rcv_depth) = walk_ptrs_ty_depth(rcv_ty); if base_rcv_ty == base_res_ty && rcv_depth >= res_depth { - // allow the `as_ref` or `as_mut` if it is followed by another method call - if let Some(parent) = get_parent_expr(cx, expr) - && let hir::ExprKind::MethodCall(segment, ..) = parent.kind - && segment.ident.span != expr.span - { - return; + if let Some(parent) = get_parent_expr(cx, expr) { + // allow the `as_ref` or `as_mut` if it is followed by another method call + if let hir::ExprKind::MethodCall(segment, ..) = parent.kind + && segment.ident.span != expr.span + { + return; + } + + // allow the `as_ref` or `as_mut` if they belong to a closure that changes + // the number of references + if matches!(parent.kind, hir::ExprKind::Closure(..)) && rcv_depth != res_depth { + return; + } } let mut applicability = Applicability::MachineApplicable; @@ -94,6 +101,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str, && is_calling_clone(cx, arg) // And that we are not recommending recv.clone() over Arc::clone() or similar && !should_call_clone_as_function(cx, rcv_ty) + // https://github.com/rust-lang/rust-clippy/issues/12357 + && let Some(clone_trait) = cx.tcx.lang_items().clone_trait() + && implements_trait(cx, cx.typeck_results().expr_ty(recvr), clone_trait, &[]) { lint_as_ref_clone(cx, expr.span.with_hi(parent.span.hi()), recvr, call_name); } diff --git a/clippy_lints/src/methods/useless_nonzero_new_unchecked.rs b/clippy_lints/src/methods/useless_nonzero_new_unchecked.rs index 0bd50429c09d..22df1f3f485e 100644 --- a/clippy_lints/src/methods/useless_nonzero_new_unchecked.rs +++ b/clippy_lints/src/methods/useless_nonzero_new_unchecked.rs @@ -10,13 +10,13 @@ use rustc_span::sym; use super::USELESS_NONZERO_NEW_UNCHECKED; -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, func: &Expr<'tcx>, args: &[Expr<'_>], msrv: &Msrv) { - if msrv.meets(msrvs::CONST_UNWRAP) - && let ExprKind::Path(QPath::TypeRelative(ty, segment)) = func.kind +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, func: &Expr<'tcx>, args: &[Expr<'_>], msrv: Msrv) { + if let ExprKind::Path(QPath::TypeRelative(ty, segment)) = func.kind && segment.ident.name == sym::new_unchecked && let [init_arg] = args && is_inside_always_const_context(cx.tcx, expr.hir_id) && is_type_diagnostic_item(cx, cx.typeck_results().node_type(ty.hir_id), sym::NonZero) + && msrv.meets(cx, msrvs::CONST_UNWRAP) { let mut app = Applicability::MachineApplicable; let ty_str = snippet_with_applicability(cx, ty.span, "_", &mut app); diff --git a/clippy_lints/src/min_ident_chars.rs b/clippy_lints/src/min_ident_chars.rs index e5801124db48..00ea9bba0d19 100644 --- a/clippy_lints/src/min_ident_chars.rs +++ b/clippy_lints/src/min_ident_chars.rs @@ -121,8 +121,7 @@ impl Visitor<'_> for IdentVisitor<'_, '_> { // Check whether the node is part of a `use` statement. We don't want to emit a warning if the user // has no control over the type. let usenode = opt_as_use_node(node).or_else(|| { - cx - .tcx + cx.tcx .hir_parent_iter(hir_id) .find_map(|(_, node)| opt_as_use_node(node)) }); diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index fca416d9e64c..693d1a8dd764 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -7,7 +7,6 @@ use clippy_utils::{ }; use rustc_errors::Applicability; use rustc_hir::def::Res; -use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::intravisit::FnKind; use rustc_hir::{ BinOpKind, BindingMode, Body, ByRef, Expr, ExprKind, FnDecl, Mutability, PatKind, QPath, Stmt, StmtKind, @@ -286,7 +285,8 @@ fn used_underscore_items<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if name.starts_with('_') && !name.starts_with("__") && !definition_span.from_expansion() - && def_id.krate == LOCAL_CRATE + && def_id.is_local() + && !cx.tcx.is_foreign_item(def_id) { span_lint_and_then( cx, diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs index 8d751c2c0acb..38a19dd2999b 100644 --- a/clippy_lints/src/missing_const_for_fn.rs +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -1,9 +1,9 @@ - use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::qualify_min_const_fn::is_min_const_fn; use clippy_utils::{fn_has_unsatisfiable_preds, is_entrypoint_fn, is_from_proc_macro, is_in_test, trait_ref_of_method}; +use rustc_abi::ExternAbi; use rustc_errors::Applicability; use rustc_hir::def_id::CRATE_DEF_ID; use rustc_hir::intravisit::FnKind; @@ -13,7 +13,6 @@ use rustc_middle::ty; use rustc_session::impl_lint_pass; use rustc_span::Span; use rustc_span::def_id::LocalDefId; -use rustc_abi::ExternAbi; declare_clippy_lint! { /// ### What it does @@ -81,9 +80,7 @@ pub struct MissingConstForFn { impl MissingConstForFn { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -102,10 +99,6 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { return; } - if !self.msrv.meets(msrvs::CONST_IF_MATCH) { - return; - } - if span.in_external_macro(cx.tcx.sess.source_map()) || is_entrypoint_fn(cx, def_id.to_def_id()) { return; } @@ -124,7 +117,9 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { .iter() .any(|param| matches!(param.kind, GenericParamKind::Const { .. })); - if already_const(header) || has_const_generic_params || !could_be_const_with_abi(&self.msrv, header.abi) + if already_const(header) + || has_const_generic_params + || !could_be_const_with_abi(cx, self.msrv, header.abi) { return; } @@ -153,13 +148,17 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { } } + if !self.msrv.meets(cx, msrvs::CONST_IF_MATCH) { + return; + } + if is_from_proc_macro(cx, &(&kind, body, hir_id, span)) { return; } let mir = cx.tcx.optimized_mir(def_id); - if let Ok(()) = is_min_const_fn(cx.tcx, mir, &self.msrv) + if let Ok(()) = is_min_const_fn(cx, mir, self.msrv) && let hir::Node::Item(hir::Item { vis_span, .. }) | hir::Node::ImplItem(hir::ImplItem { vis_span, .. }) = cx.tcx.hir_node_by_def_id(def_id) { @@ -174,8 +173,6 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { }); } } - - extract_msrv_attr!(LateContext); } // We don't have to lint on something that's already `const` @@ -184,13 +181,13 @@ fn already_const(header: hir::FnHeader) -> bool { header.constness == Constness::Const } -fn could_be_const_with_abi(msrv: &Msrv, abi: ExternAbi) -> bool { +fn could_be_const_with_abi(cx: &LateContext<'_>, msrv: Msrv, abi: ExternAbi) -> bool { match abi { ExternAbi::Rust => true, // `const extern "C"` was stabilized after 1.62.0 - ExternAbi::C { unwind: false } => msrv.meets(msrvs::CONST_EXTERN_C_FN), + ExternAbi::C { unwind: false } => msrv.meets(cx, msrvs::CONST_EXTERN_C_FN), // Rest ABIs are still unstable and need the `const_extern_fn` feature enabled. - _ => msrv.meets(msrvs::CONST_EXTERN_FN), + _ => msrv.meets(cx, msrvs::CONST_EXTERN_FN), } } diff --git a/clippy_lints/src/missing_const_for_thread_local.rs b/clippy_lints/src/missing_const_for_thread_local.rs index d4181c677afd..ea74940828a1 100644 --- a/clippy_lints/src/missing_const_for_thread_local.rs +++ b/clippy_lints/src/missing_const_for_thread_local.rs @@ -49,9 +49,7 @@ pub struct MissingConstForThreadLocal { impl MissingConstForThreadLocal { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -91,11 +89,11 @@ fn is_unreachable(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { } #[inline] -fn initializer_can_be_made_const(cx: &LateContext<'_>, defid: rustc_span::def_id::DefId, msrv: &Msrv) -> bool { +fn initializer_can_be_made_const(cx: &LateContext<'_>, defid: rustc_span::def_id::DefId, msrv: Msrv) -> bool { // Building MIR for `fn`s with unsatisfiable preds results in ICE. if !fn_has_unsatisfiable_preds(cx, defid) && let mir = cx.tcx.optimized_mir(defid) - && let Ok(()) = is_min_const_fn(cx.tcx, mir, msrv) + && let Ok(()) = is_min_const_fn(cx, mir, msrv) { return true; } @@ -113,8 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForThreadLocal { local_defid: rustc_span::def_id::LocalDefId, ) { let defid = local_defid.to_def_id(); - if self.msrv.meets(msrvs::THREAD_LOCAL_CONST_INIT) - && is_thread_local_initializer(cx, fn_kind, span).unwrap_or(false) + if is_thread_local_initializer(cx, fn_kind, span).unwrap_or(false) // Some implementations of `thread_local!` include an initializer fn. // In the case of a const initializer, the init fn is also const, // so we can skip the lint in that case. This occurs only on some @@ -131,11 +128,12 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForThreadLocal { // https://github.com/rust-lang/rust-clippy/issues/12637 // we ensure that this is reachable before we check in mir && !is_unreachable(cx, ret_expr) - && initializer_can_be_made_const(cx, defid, &self.msrv) + && initializer_can_be_made_const(cx, defid, self.msrv) // we know that the function is const-qualifiable, so now // we need only to get the initializer expression to span-lint it. && let initializer_snippet = snippet(cx, ret_expr.span, "thread_local! { ... }") && initializer_snippet != "thread_local! { ... }" + && self.msrv.meets(cx, msrvs::THREAD_LOCAL_CONST_INIT) { span_lint_and_sugg( cx, @@ -148,6 +146,4 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForThreadLocal { ); } } - - extract_msrv_attr!(LateContext); } diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index c382fb8fce1b..2fd1049f42e1 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -54,8 +54,9 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed { ); } }, - ExprKind::MethodCall(path, receiver, arguments, _) => { - let def_id = cx.typeck_results().type_dependent_def_id(e.hir_id).unwrap(); + ExprKind::MethodCall(path, receiver, arguments, _) + if let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) => + { let args = cx.typeck_results().node_args(e.hir_id); let method_type = cx.tcx.type_of(def_id).instantiate(cx.tcx, args); check_arguments( diff --git a/clippy_lints/src/needless_borrows_for_generic_args.rs b/clippy_lints/src/needless_borrows_for_generic_args.rs index ea1d7e5d4382..f686cc912ddb 100644 --- a/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -72,7 +72,7 @@ impl NeedlessBorrowsForGenericArgs<'_> { pub fn new(conf: &'static Conf) -> Self { Self { possible_borrowers: Vec::new(), - msrv: conf.msrv.clone(), + msrv: conf.msrv, } } } @@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowsForGenericArgs<'tcx> { i, param_ty, expr, - &self.msrv, + self.msrv, ) && count != 0 { @@ -142,8 +142,6 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowsForGenericArgs<'tcx> { self.possible_borrowers.pop(); } } - - extract_msrv_attr!(LateContext); } fn path_has_args(p: &QPath<'_>) -> bool { @@ -172,7 +170,7 @@ fn needless_borrow_count<'tcx>( arg_index: usize, param_ty: ParamTy, mut expr: &Expr<'tcx>, - msrv: &Msrv, + msrv: Msrv, ) -> usize { let destruct_trait_def_id = cx.tcx.lang_items().destruct_trait(); let sized_trait_def_id = cx.tcx.lang_items().sized_trait(); @@ -273,7 +271,7 @@ fn needless_borrow_count<'tcx>( && let ty::Param(param_ty) = trait_predicate.self_ty().kind() && let GenericArgKind::Type(ty) = args_with_referent_ty[param_ty.index as usize].unpack() && ty.is_array() - && !msrv.meets(msrvs::ARRAY_INTO_ITERATOR) + && !msrv.meets(cx, msrvs::ARRAY_INTO_ITERATOR) { return false; } diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 05b31fc84b9b..b8601f77e249 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -356,7 +356,7 @@ fn suggestion_snippet_for_continue_inside_else(cx: &EarlyContext<'_>, data: &Lin .iter() .map(|stmt| { let span = cx.sess().source_map().stmt_span(stmt.span, data.loop_block.span); - let snip = snippet_block(cx, span, "..", None).into_owned(); + let snip = snippet_block(cx, span, "..", None); snip.lines() .map(|line| format!("{}{line}", " ".repeat(indent))) .collect::>() diff --git a/clippy_lints/src/needless_pass_by_ref_mut.rs b/clippy_lints/src/needless_pass_by_ref_mut.rs index 36a0738cbc95..d5c5679c990d 100644 --- a/clippy_lints/src/needless_pass_by_ref_mut.rs +++ b/clippy_lints/src/needless_pass_by_ref_mut.rs @@ -5,6 +5,7 @@ use clippy_utils::source::snippet; use clippy_utils::visitors::for_each_expr; use clippy_utils::{inherits_cfg, is_from_proc_macro, is_self}; use core::ops::ControlFlow; +use rustc_abi::ExternAbi; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; @@ -20,7 +21,6 @@ use rustc_session::impl_lint_pass; use rustc_span::Span; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::kw; -use rustc_abi::ExternAbi; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 40c65d1ef9e8..380cc380ad0f 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -5,6 +5,7 @@ use clippy_utils::source::{SpanRangeExt, snippet}; use clippy_utils::ty::{ implements_trait, implements_trait_with_env_from_iter, is_copy, is_type_diagnostic_item, is_type_lang_item, }; +use rustc_abi::ExternAbi; use rustc_errors::{Applicability, Diag}; use rustc_hir::intravisit::FnKind; use rustc_hir::{ @@ -19,7 +20,6 @@ use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::kw; use rustc_span::{Span, sym}; -use rustc_abi::ExternAbi; use rustc_trait_selection::traits; use rustc_trait_selection::traits::misc::type_allowed_to_implement_copy; diff --git a/clippy_lints/src/no_mangle_with_rust_abi.rs b/clippy_lints/src/no_mangle_with_rust_abi.rs index 6eca3f12cf25..1baa3cb2f0fd 100644 --- a/clippy_lints/src/no_mangle_with_rust_abi.rs +++ b/clippy_lints/src/no_mangle_with_rust_abi.rs @@ -1,11 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::{snippet, snippet_with_applicability}; +use rustc_abi::ExternAbi; use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::{BytePos, Pos}; -use rustc_abi::ExternAbi; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 4007ca88a00e..d4da12451f18 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -180,7 +180,9 @@ impl<'tcx> NonCopyConst<'tcx> { fn is_value_unfrozen_raw_inner(cx: &LateContext<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> bool { // No branch that we check (yet) should continue if val isn't a branch - let Some(val) = val.try_to_branch() else { return false }; + let Some(branched_val) = val.try_to_branch() else { + return false; + }; match *ty.kind() { // the fact that we have to dig into every structs to search enums // leads us to the point checking `UnsafeCell` directly is the only option. @@ -188,11 +190,11 @@ impl<'tcx> NonCopyConst<'tcx> { // As of 2022-09-08 miri doesn't track which union field is active so there's no safe way to check the // contained value. ty::Adt(def, ..) if def.is_union() => false, - ty::Array(ty, _) => val + ty::Array(ty, _) => branched_val .iter() .any(|field| Self::is_value_unfrozen_raw_inner(cx, *field, ty)), ty::Adt(def, args) if def.is_enum() => { - let Some((&variant_valtree, fields)) = val.split_first() else { + let Some((&variant_valtree, fields)) = branched_val.split_first() else { return false; }; let variant_index = variant_valtree.unwrap_leaf(); @@ -208,14 +210,18 @@ impl<'tcx> NonCopyConst<'tcx> { ) .any(|(field, ty)| Self::is_value_unfrozen_raw_inner(cx, field, ty)) }, - ty::Adt(def, args) => val + ty::Adt(def, args) => branched_val .iter() .zip(def.non_enum_variant().fields.iter().map(|field| field.ty(cx.tcx, args))) .any(|(field, ty)| Self::is_value_unfrozen_raw_inner(cx, *field, ty)), - ty::Tuple(tys) => val + ty::Tuple(tys) => branched_val .iter() .zip(tys) .any(|(field, ty)| Self::is_value_unfrozen_raw_inner(cx, *field, ty)), + ty::Alias(ty::Projection, _) => match cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty) { + Ok(normalized_ty) if ty != normalized_ty => Self::is_value_unfrozen_raw_inner(cx, val, normalized_ty), + _ => false, + }, _ => false, } } diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 1a3b43cbb10a..c5873589b26f 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -208,7 +208,8 @@ impl SimilarNamesNameVisitor<'_, '_, '_> { fn check_ident(&mut self, ident: Ident) { let interned_name = ident.name.as_str(); - if interned_name.chars().any(char::is_uppercase) { + // name can be empty if it comes from recovery + if interned_name.chars().any(char::is_uppercase) || interned_name.is_empty() { return; } if interned_name.chars().all(|c| c.is_ascii_digit() || c == '_') { diff --git a/clippy_lints/src/non_std_lazy_statics.rs b/clippy_lints/src/non_std_lazy_statics.rs index 774a182d089f..a82365f94318 100644 --- a/clippy_lints/src/non_std_lazy_statics.rs +++ b/clippy_lints/src/non_std_lazy_statics.rs @@ -1,8 +1,8 @@ use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; -use clippy_utils::msrvs::Msrv; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::visitors::for_each_expr; -use clippy_utils::{def_path_def_ids, fn_def_id, path_def_id}; +use clippy_utils::{def_path_def_ids, fn_def_id, is_no_std_crate, path_def_id}; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; @@ -75,7 +75,7 @@ impl NonStdLazyStatic { #[must_use] pub fn new(conf: &'static Conf) -> Self { Self { - msrv: conf.msrv.clone(), + msrv: conf.msrv, lazy_static_lazy_static: Vec::new(), once_cell_crate: Vec::new(), once_cell_sync_lazy: Vec::new(), @@ -89,23 +89,12 @@ impl NonStdLazyStatic { impl_lint_pass!(NonStdLazyStatic => [NON_STD_LAZY_STATICS]); -/// Return if current MSRV does not meet the requirement for `lazy_cell` feature, -/// or current context has `no_std` attribute. -macro_rules! ensure_prerequisite { - ($msrv:expr, $cx:ident) => { - if !$msrv.meets(clippy_utils::msrvs::LAZY_CELL) || clippy_utils::is_no_std_crate($cx) { - return; - } - }; +fn can_use_lazy_cell(cx: &LateContext<'_>, msrv: Msrv) -> bool { + msrv.meets(cx, msrvs::LAZY_CELL) && !is_no_std_crate(cx) } impl<'hir> LateLintPass<'hir> for NonStdLazyStatic { - extract_msrv_attr!(LateContext); - fn check_crate(&mut self, cx: &LateContext<'hir>) { - // Do not lint if current crate does not support `LazyLock`. - ensure_prerequisite!(self.msrv, cx); - // Fetch def_ids for external paths self.lazy_static_lazy_static = def_path_def_ids(cx.tcx, &["lazy_static", "lazy_static"]).collect(); self.once_cell_sync_lazy = def_path_def_ids(cx.tcx, &["once_cell", "sync", "Lazy"]).collect(); @@ -123,11 +112,10 @@ impl<'hir> LateLintPass<'hir> for NonStdLazyStatic { } fn check_item(&mut self, cx: &LateContext<'hir>, item: &Item<'hir>) { - ensure_prerequisite!(self.msrv, cx); - if let ItemKind::Static(..) = item.kind && let Some(macro_call) = clippy_utils::macros::root_macro_call(item.span) && self.lazy_static_lazy_static.contains(¯o_call.def_id) + && can_use_lazy_cell(cx, self.msrv) { span_lint( cx, @@ -142,14 +130,14 @@ impl<'hir> LateLintPass<'hir> for NonStdLazyStatic { return; } - if let Some(lazy_info) = LazyInfo::from_item(self, cx, item) { + if let Some(lazy_info) = LazyInfo::from_item(self, cx, item) + && can_use_lazy_cell(cx, self.msrv) + { self.lazy_type_defs.insert(item.owner_id.to_def_id(), lazy_info); } } fn check_expr(&mut self, cx: &LateContext<'hir>, expr: &Expr<'hir>) { - ensure_prerequisite!(self.msrv, cx); - // All functions in the `FUNCTION_REPLACEMENTS` have only one args if let ExprKind::Call(callee, [arg]) = expr.kind && let Some(call_def_id) = fn_def_id(cx, expr) @@ -163,8 +151,6 @@ impl<'hir> LateLintPass<'hir> for NonStdLazyStatic { } fn check_ty(&mut self, cx: &LateContext<'hir>, ty: &'hir rustc_hir::Ty<'hir, rustc_hir::AmbigArg>) { - ensure_prerequisite!(self.msrv, cx); - // Record if types from `once_cell` besides `sync::Lazy` are used. if let rustc_hir::TyKind::Path(qpath) = ty.peel_refs().kind && let Some(ty_def_id) = cx.qpath_res(&qpath, ty.hir_id).opt_def_id() @@ -178,8 +164,6 @@ impl<'hir> LateLintPass<'hir> for NonStdLazyStatic { } fn check_crate_post(&mut self, cx: &LateContext<'hir>) { - ensure_prerequisite!(self.msrv, cx); - if !self.uses_other_once_cell_types { for (_, lazy_info) in &self.lazy_type_defs { lazy_info.lint(cx, &self.sugg_map); diff --git a/clippy_lints/src/operators/manual_midpoint.rs b/clippy_lints/src/operators/manual_midpoint.rs new file mode 100644 index 000000000000..81721a9f2af5 --- /dev/null +++ b/clippy_lints/src/operators/manual_midpoint.rs @@ -0,0 +1,64 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::sugg::Sugg; +use clippy_utils::{is_float_literal, is_integer_literal}; +use rustc_ast::BinOpKind; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_middle::ty::{self, Ty}; + +use super::MANUAL_MIDPOINT; + +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'_>, + op: BinOpKind, + left: &'tcx Expr<'_>, + right: &'tcx Expr<'_>, + msrv: Msrv, +) { + if !left.span.from_expansion() + && !right.span.from_expansion() + && op == BinOpKind::Div + && (is_integer_literal(right, 2) || is_float_literal(right, 2.0)) + && let Some((ll_expr, lr_expr)) = add_operands(left) + && add_operands(ll_expr).is_none() && add_operands(lr_expr).is_none() + && let left_ty = cx.typeck_results().expr_ty_adjusted(ll_expr) + && let right_ty = cx.typeck_results().expr_ty_adjusted(lr_expr) + && left_ty == right_ty + // Do not lint on `(_+1)/2` and `(1+_)/2`, it is likely a `div_ceil()` operation + && !is_integer_literal(ll_expr, 1) && !is_integer_literal(lr_expr, 1) + && is_midpoint_implemented(cx, left_ty, msrv) + { + let mut app = Applicability::MachineApplicable; + let left_sugg = Sugg::hir_with_context(cx, ll_expr, expr.span.ctxt(), "..", &mut app); + let right_sugg = Sugg::hir_with_context(cx, lr_expr, expr.span.ctxt(), "..", &mut app); + let sugg = format!("{left_ty}::midpoint({left_sugg}, {right_sugg})"); + span_lint_and_sugg( + cx, + MANUAL_MIDPOINT, + expr.span, + "manual implementation of `midpoint` which can overflow", + format!("use `{left_ty}::midpoint` instead"), + sugg, + app, + ); + } +} + +/// Return the left and right operands if `expr` represents an addition +fn add_operands<'e, 'tcx>(expr: &'e Expr<'tcx>) -> Option<(&'e Expr<'tcx>, &'e Expr<'tcx>)> { + match expr.kind { + ExprKind::Binary(op, left, right) if op.node == BinOpKind::Add => Some((left, right)), + _ => None, + } +} + +fn is_midpoint_implemented(cx: &LateContext<'_>, ty: Ty<'_>, msrv: Msrv) -> bool { + match ty.kind() { + ty::Uint(_) | ty::Float(_) => msrv.meets(cx, msrvs::UINT_FLOAT_MIDPOINT), + ty::Int(_) => msrv.meets(cx, msrvs::INT_MIDPOINT), + _ => false, + } +} diff --git a/clippy_lints/src/operators/mod.rs b/clippy_lints/src/operators/mod.rs index 9ad32c2bd396..80459945094e 100644 --- a/clippy_lints/src/operators/mod.rs +++ b/clippy_lints/src/operators/mod.rs @@ -11,6 +11,7 @@ mod float_cmp; mod float_equality_without_abs; mod identity_op; mod integer_division; +mod manual_midpoint; mod misrefactored_assign_op; mod modulo_arithmetic; mod modulo_one; @@ -24,6 +25,7 @@ mod verbose_bit_mask; pub(crate) mod arithmetic_side_effects; use clippy_config::Conf; +use clippy_utils::msrvs::Msrv; use rustc_hir::{Body, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; @@ -834,10 +836,35 @@ declare_clippy_lint! { "explicit self-assignment" } +declare_clippy_lint! { + /// ### What it does + /// Checks for manual implementation of `midpoint`. + /// + /// ### Why is this bad? + /// Using `(x + y) / 2` might cause an overflow on the intermediate + /// addition result. + /// + /// ### Example + /// ```no_run + /// # let a: u32 = 0; + /// let c = (a + 10) / 2; + /// ``` + /// Use instead: + /// ```no_run + /// # let a: u32 = 0; + /// let c = u32::midpoint(a, 10); + /// ``` + #[clippy::version = "1.87.0"] + pub MANUAL_MIDPOINT, + pedantic, + "manual implementation of `midpoint` which can overflow" +} + pub struct Operators { arithmetic_context: numeric_arithmetic::Context, verbose_bit_mask_threshold: u64, modulo_arithmetic_allow_comparison_to_zero: bool, + msrv: Msrv, } impl Operators { pub fn new(conf: &'static Conf) -> Self { @@ -845,6 +872,7 @@ impl Operators { arithmetic_context: numeric_arithmetic::Context::default(), verbose_bit_mask_threshold: conf.verbose_bit_mask_threshold, modulo_arithmetic_allow_comparison_to_zero: conf.allow_comparison_to_zero, + msrv: conf.msrv, } } } @@ -876,6 +904,7 @@ impl_lint_pass!(Operators => [ NEEDLESS_BITWISE_BOOL, PTR_EQ, SELF_ASSIGNMENT, + MANUAL_MIDPOINT, ]); impl<'tcx> LateLintPass<'tcx> for Operators { @@ -893,6 +922,7 @@ impl<'tcx> LateLintPass<'tcx> for Operators { identity_op::check(cx, e, op.node, lhs, rhs); needless_bitwise_bool::check(cx, e, op.node, lhs, rhs); ptr_eq::check(cx, e, op.node, lhs, rhs); + manual_midpoint::check(cx, e, op.node, lhs, rhs, self.msrv); } self.arithmetic_context.check_binary(cx, e, op.node, lhs, rhs); bit_mask::check(cx, e, op.node, lhs, rhs); diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index c9bdeed660e2..39ae9967e016 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -1,11 +1,12 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint; +use clippy_utils::is_in_test; use clippy_utils::macros::{is_panic, root_macro_call_first_node}; -use clippy_utils::{is_in_test, match_def_path, paths}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; +use rustc_span::sym; pub struct PanicUnimplemented { allow_panic_in_tests: bool, @@ -137,7 +138,7 @@ impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented { } else if let ExprKind::Call(func, [_]) = expr.kind && let ExprKind::Path(QPath::Resolved(None, expr_path)) = func.kind && let Res::Def(DefKind::Fn, def_id) = expr_path.res - && match_def_path(cx, def_id, &paths::PANIC_ANY) + && cx.tcx.is_diagnostic_item(sym::panic_any, def_id) { if cx.tcx.hir_is_inside_const_context(expr.hir_id) || self.allow_panic_in_tests && is_in_test(cx.tcx, expr.hir_id) diff --git a/clippy_lints/src/pass_by_ref_or_value.rs b/clippy_lints/src/pass_by_ref_or_value.rs index 73c31b83b51f..49bc56083468 100644 --- a/clippy_lints/src/pass_by_ref_or_value.rs +++ b/clippy_lints/src/pass_by_ref_or_value.rs @@ -6,6 +6,7 @@ use clippy_utils::source::snippet; use clippy_utils::ty::{for_each_top_level_late_bound_region, is_copy}; use clippy_utils::{is_self, is_self_ty}; use core::ops::ControlFlow; +use rustc_abi::ExternAbi; use rustc_ast::attr; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; @@ -19,7 +20,6 @@ use rustc_middle::ty::{self, RegionKind, TyCtxt}; use rustc_session::impl_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::{Span, sym}; -use rustc_abi::ExternAbi; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index ef4948a05b7f..dae0709a5404 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -4,6 +4,7 @@ use clippy_utils::sugg::Sugg; use clippy_utils::visitors::contains_unsafe_block; use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_id, path_to_local, std_or_core}; use hir::LifetimeName; +use rustc_abi::ExternAbi; use rustc_errors::{Applicability, MultiSpan}; use rustc_hir::hir_id::{HirId, HirIdMap}; use rustc_hir::intravisit::{Visitor, walk_expr}; @@ -19,7 +20,6 @@ use rustc_middle::ty::{self, Binder, ClauseKind, ExistentialPredicate, List, Pre use rustc_session::declare_lint_pass; use rustc_span::symbol::Symbol; use rustc_span::{Span, sym}; -use rustc_abi::ExternAbi; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use std::{fmt, iter}; diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index ffc3b86c502e..4f5f3eb6c15a 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -68,7 +68,7 @@ impl_lint_pass!(QuestionMark => [QUESTION_MARK, MANUAL_LET_ELSE]); impl QuestionMark { pub fn new(conf: &'static Conf) -> Self { Self { - msrv: conf.msrv.clone(), + msrv: conf.msrv, matches_behaviour: conf.matches_for_let_else, try_block_depth_stack: Vec::new(), inferred_ret_closure_stack: 0, @@ -543,5 +543,4 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMark { .expect("blocks are always part of bodies and must have a depth") -= 1; } } - extract_msrv_attr!(LateContext); } diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 1b0c0a4956f7..cc423eca74fb 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -166,9 +166,7 @@ pub struct Ranges { impl Ranges { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -182,7 +180,7 @@ impl_lint_pass!(Ranges => [ impl<'tcx> LateLintPass<'tcx> for Ranges { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::Binary(ref op, l, r) = expr.kind { - if self.msrv.meets(msrvs::RANGE_CONTAINS) { + if self.msrv.meets(cx, msrvs::RANGE_CONTAINS) { check_possible_range_contains(cx, op.node, l, r, expr, expr.span); } } @@ -191,7 +189,6 @@ impl<'tcx> LateLintPass<'tcx> for Ranges { check_inclusive_range_minus_one(cx, expr); check_reversed_empty_range(cx, expr); } - extract_msrv_attr!(LateContext); } fn check_possible_range_contains( diff --git a/clippy_lints/src/redundant_else.rs b/clippy_lints/src/redundant_else.rs index a1b5a3aff323..a3be16ed858e 100644 --- a/clippy_lints/src/redundant_else.rs +++ b/clippy_lints/src/redundant_else.rs @@ -6,7 +6,6 @@ use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::declare_lint_pass; use rustc_span::Span; -use std::borrow::Cow; declare_clippy_lint! { /// ### What it does @@ -163,14 +162,9 @@ fn extract_else_block(mut block: &str) -> String { block.trim_end().to_string() } -fn make_sugg<'a>( - cx: &EarlyContext<'_>, - els_span: Span, - default: &'a str, - indent_relative_to: Option, -) -> Cow<'a, str> { +fn make_sugg(cx: &EarlyContext<'_>, els_span: Span, default: &str, indent_relative_to: Option) -> String { let extracted = extract_else_block(&snippet(cx, els_span, default)); let indent = indent_relative_to.and_then(|s| indent_of(cx, s)); - reindent_multiline(extracted.into(), false, indent) + reindent_multiline(&extracted, false, indent) } diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index 707abc008a86..feefe10f57d7 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::msrvs::{self, MsrvStack}; use rustc_ast::ast::{Expr, ExprKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; @@ -36,13 +36,13 @@ declare_clippy_lint! { } pub struct RedundantFieldNames { - msrv: Msrv, + msrv: MsrvStack, } impl RedundantFieldNames { pub fn new(conf: &'static Conf) -> Self { Self { - msrv: conf.msrv.clone(), + msrv: MsrvStack::new(conf.msrv), } } } @@ -80,5 +80,6 @@ impl EarlyLintPass for RedundantFieldNames { } } } - extract_msrv_attr!(EarlyContext); + + extract_msrv_attr!(); } diff --git a/clippy_lints/src/redundant_locals.rs b/clippy_lints/src/redundant_locals.rs index f3ccc9e38f4d..defb6684cffb 100644 --- a/clippy_lints/src/redundant_locals.rs +++ b/clippy_lints/src/redundant_locals.rs @@ -123,6 +123,5 @@ fn find_binding(pat: &Pat<'_>, name: Ident) -> Option { /// Check if a rebinding of a local changes the effect of assignments to the binding. fn affects_assignments(cx: &LateContext<'_>, mutability: Mutability, bind: HirId, rebind: HirId) -> bool { // the binding is mutable and the rebinding is in a different scope than the original binding - mutability == Mutability::Mut - && cx.tcx.hir_get_enclosing_scope(bind) != cx.tcx.hir_get_enclosing_scope(rebind) + mutability == Mutability::Mut && cx.tcx.hir_get_enclosing_scope(bind) != cx.tcx.hir_get_enclosing_scope(rebind) } diff --git a/clippy_lints/src/redundant_static_lifetimes.rs b/clippy_lints/src/redundant_static_lifetimes.rs index 06c854338066..b4e1f70d1535 100644 --- a/clippy_lints/src/redundant_static_lifetimes.rs +++ b/clippy_lints/src/redundant_static_lifetimes.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::msrvs::{self, MsrvStack}; use clippy_utils::source::snippet; use rustc_ast::ast::{ConstItem, Item, ItemKind, StaticItem, Ty, TyKind}; use rustc_errors::Applicability; @@ -35,13 +35,13 @@ declare_clippy_lint! { } pub struct RedundantStaticLifetimes { - msrv: Msrv, + msrv: MsrvStack, } impl RedundantStaticLifetimes { pub fn new(conf: &'static Conf) -> Self { Self { - msrv: conf.msrv.clone(), + msrv: MsrvStack::new(conf.msrv), } } } @@ -115,5 +115,5 @@ impl EarlyLintPass for RedundantStaticLifetimes { } } - extract_msrv_attr!(EarlyContext); + extract_msrv_attr!(); } diff --git a/clippy_lints/src/repeat_vec_with_capacity.rs b/clippy_lints/src/repeat_vec_with_capacity.rs index 5dddf9263a35..8805687efccf 100644 --- a/clippy_lints/src/repeat_vec_with_capacity.rs +++ b/clippy_lints/src/repeat_vec_with_capacity.rs @@ -1,15 +1,27 @@ +use clippy_config::Conf; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::VecArgs; use clippy_utils::macros::matching_root_macro_call; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; use clippy_utils::{expr_or_init, fn_def_id, std_or_core}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::declare_lint_pass; +use rustc_session::impl_lint_pass; use rustc_span::{Span, sym}; +pub struct RepeatVecWithCapacity { + msrv: Msrv, +} + +impl RepeatVecWithCapacity { + pub fn new(conf: &'static Conf) -> Self { + Self { msrv: conf.msrv } + } +} + declare_clippy_lint! { /// ### What it does /// Looks for patterns such as `vec![Vec::with_capacity(x); n]` or `iter::repeat(Vec::with_capacity(x))`. @@ -48,7 +60,7 @@ declare_clippy_lint! { "repeating a `Vec::with_capacity` expression which does not retain capacity" } -declare_lint_pass!(RepeatVecWithCapacity => [REPEAT_VEC_WITH_CAPACITY]); +impl_lint_pass!(RepeatVecWithCapacity => [REPEAT_VEC_WITH_CAPACITY]); fn emit_lint(cx: &LateContext<'_>, span: Span, kind: &str, note: &'static str, sugg_msg: &'static str, sugg: String) { span_lint_and_then( @@ -87,13 +99,14 @@ fn check_vec_macro(cx: &LateContext<'_>, expr: &Expr<'_>) { } /// Checks `iter::repeat(Vec::with_capacity(x))` -fn check_repeat_fn(cx: &LateContext<'_>, expr: &Expr<'_>) { +fn check_repeat_fn(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: Msrv) { 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| cx.tcx.is_diagnostic_item(sym::vec_with_capacity, did)) && !repeat_expr.span.from_expansion() && let Some(exec_context) = std_or_core(cx) + && msrv.meets(cx, msrvs::REPEAT_WITH) { emit_lint( cx, @@ -112,6 +125,6 @@ fn check_repeat_fn(cx: &LateContext<'_>, expr: &Expr<'_>) { impl LateLintPass<'_> for RepeatVecWithCapacity { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { check_vec_macro(cx, expr); - check_repeat_fn(cx, expr); + check_repeat_fn(cx, expr, self.msrv); } } diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 152739c2973b..3ba6d6284592 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; use clippy_utils::source::{SpanRangeExt, snippet_with_context}; use clippy_utils::sugg::has_enclosing_paren; -use clippy_utils::visitors::{Descend, for_each_expr}; +use clippy_utils::visitors::for_each_expr; use clippy_utils::{ binary_expr_needs_parentheses, fn_def_id, is_from_proc_macro, is_inside_let_else, is_res_lang_ctor, leaks_droppable_temporary_with_limited_lifetime, path_res, path_to_local_id, span_contains_cfg, @@ -21,6 +21,7 @@ use rustc_middle::ty::adjustment::Adjust; use rustc_middle::ty::{self, GenericArgKind, Ty}; use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; +use rustc_span::edition::Edition; use rustc_span::{BytePos, Pos, Span, sym}; use std::borrow::Cow; use std::fmt::Display; @@ -234,7 +235,7 @@ impl<'tcx> LateLintPass<'tcx> for Return { && let Some(initexpr) = &local.init && let PatKind::Binding(_, local_id, _, _) = local.pat.kind && path_to_local_id(retexpr, local_id) - && !last_statement_borrows(cx, initexpr) + && (cx.sess().edition() >= Edition::Edition2024 || !last_statement_borrows(cx, initexpr)) && !initexpr.span.in_external_macro(cx.sess().source_map()) && !retexpr.span.in_external_macro(cx.sess().source_map()) && !local.span.from_expansion() @@ -482,7 +483,7 @@ fn last_statement_borrows<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { ControlFlow::Break(()) } else { - ControlFlow::Continue(Descend::from(!e.span.from_expansion())) + ControlFlow::Continue(()) } }) .is_some() diff --git a/clippy_lints/src/single_option_map.rs b/clippy_lints/src/single_option_map.rs new file mode 100644 index 000000000000..1fb54950612a --- /dev/null +++ b/clippy_lints/src/single_option_map.rs @@ -0,0 +1,91 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{path_res, peel_blocks}; +use rustc_hir::def::Res; +use rustc_hir::def_id::LocalDefId; +use rustc_hir::intravisit::FnKind; +use rustc_hir::{Body, ExprKind, FnDecl, FnRetTy}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::declare_lint_pass; +use rustc_span::{Span, sym}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for functions with method calls to `.map(_)` on an arg + /// of type `Option` as the outermost expression. + /// + /// ### Why is this bad? + /// Taking and returning an `Option` may require additional + /// `Some(_)` and `unwrap` if all you have is a `T`. + /// + /// ### Example + /// ```no_run + /// fn double(param: Option) -> Option { + /// param.map(|x| x * 2) + /// } + /// ``` + /// Use instead: + /// ```no_run + /// fn double(param: u32) -> u32 { + /// param * 2 + /// } + /// ``` + #[clippy::version = "1.86.0"] + pub SINGLE_OPTION_MAP, + nursery, + "Checks for functions with method calls to `.map(_)` on an arg of type `Option` as the outermost expression." +} + +declare_lint_pass!(SingleOptionMap => [SINGLE_OPTION_MAP]); + +impl<'tcx> LateLintPass<'tcx> for SingleOptionMap { + fn check_fn( + &mut self, + cx: &LateContext<'tcx>, + kind: FnKind<'tcx>, + decl: &'tcx FnDecl<'tcx>, + body: &'tcx Body<'tcx>, + span: Span, + _fn_def: LocalDefId, + ) { + if let FnRetTy::Return(_ret) = decl.output + && matches!(kind, FnKind::ItemFn(_, _, _) | FnKind::Method(_, _)) + { + let func_body = peel_blocks(body.value); + if let ExprKind::MethodCall(method_name, callee, args, _span) = func_body.kind + && method_name.ident.name == sym::map + && let callee_type = cx.typeck_results().expr_ty(callee) + && is_type_diagnostic_item(cx, callee_type, sym::Option) + && let ExprKind::Path(_path) = callee.kind + && let Res::Local(_id) = path_res(cx, callee) + && matches!(path_res(cx, callee), Res::Local(_id)) + && !matches!(args[0].kind, ExprKind::Path(_)) + { + if let ExprKind::Closure(closure) = args[0].kind { + let Body { params: [..], value } = cx.tcx.hir_body(closure.body); + if let ExprKind::Call(func, f_args) = value.kind + && matches!(func.kind, ExprKind::Path(_)) + && f_args.iter().all(|arg| matches!(arg.kind, ExprKind::Path(_))) + { + return; + } else if let ExprKind::MethodCall(_segment, receiver, method_args, _span) = value.kind + && matches!(receiver.kind, ExprKind::Path(_)) + && method_args.iter().all(|arg| matches!(arg.kind, ExprKind::Path(_))) + && method_args.iter().all(|arg| matches!(path_res(cx, arg), Res::Local(_))) + { + return; + } + } + + span_lint_and_help( + cx, + SINGLE_OPTION_MAP, + span, + "`fn` that only maps over argument", + None, + "move the `.map` to the caller or to an `_opt` function", + ); + } + } + } +} diff --git a/clippy_lints/src/size_of_in_element_count.rs b/clippy_lints/src/size_of_in_element_count.rs index b22c638fc363..dc19236011bd 100644 --- a/clippy_lints/src/size_of_in_element_count.rs +++ b/clippy_lints/src/size_of_in_element_count.rs @@ -99,7 +99,7 @@ fn get_pointee_ty_and_count_expr<'tcx>( if let ExprKind::MethodCall(method_path, ptr_self, [.., count], _) = expr.kind // Find calls to copy_{from,to}{,_nonoverlapping} && let method_ident = method_path.ident.as_str() - && METHODS.iter().any(|m| *m == method_ident) + && METHODS.contains(&method_ident) // Get the pointee type && let ty::RawPtr(pointee_ty, _) = diff --git a/clippy_lints/src/std_instead_of_core.rs b/clippy_lints/src/std_instead_of_core.rs index 59c13a1e2c53..d68ac8bab128 100644 --- a/clippy_lints/src/std_instead_of_core.rs +++ b/clippy_lints/src/std_instead_of_core.rs @@ -99,7 +99,7 @@ impl StdReexports { pub fn new(conf: &'static Conf) -> Self { Self { prev_span: Span::default(), - msrv: conf.msrv.clone(), + msrv: conf.msrv, } } } @@ -110,7 +110,7 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports { fn check_path(&mut self, cx: &LateContext<'tcx>, path: &Path<'tcx>, _: HirId) { if let Res::Def(_, def_id) = path.res && let Some(first_segment) = get_first_segment(path) - && is_stable(cx, def_id, &self.msrv) + && is_stable(cx, def_id, self.msrv) && !path.span.in_external_macro(cx.sess().source_map()) && !is_from_proc_macro(cx, &first_segment.ident) { @@ -153,8 +153,6 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports { } } } - - extract_msrv_attr!(LateContext); } /// Returns the first named segment of a [`Path`]. @@ -174,7 +172,7 @@ fn get_first_segment<'tcx>(path: &Path<'tcx>) -> Option<&'tcx PathSegment<'tcx>> /// or now stable moves that were once unstable. /// /// Does not catch individually moved items -fn is_stable(cx: &LateContext<'_>, mut def_id: DefId, msrv: &Msrv) -> bool { +fn is_stable(cx: &LateContext<'_>, mut def_id: DefId, msrv: Msrv) -> bool { loop { if let Some(stability) = cx.tcx.lookup_stability(def_id) && let StabilityLevel::Stable { @@ -183,8 +181,8 @@ fn is_stable(cx: &LateContext<'_>, mut def_id: DefId, msrv: &Msrv) -> bool { } = stability.level { let stable = match since { - StableSince::Version(v) => msrv.meets(v), - StableSince::Current => msrv.current().is_none(), + StableSince::Version(v) => msrv.meets(cx, v), + StableSince::Current => msrv.current(cx).is_none(), StableSince::Err => false, }; diff --git a/clippy_lints/src/string_patterns.rs b/clippy_lints/src/string_patterns.rs index 694ad4f6347b..5c95dfe83473 100644 --- a/clippy_lints/src/string_patterns.rs +++ b/clippy_lints/src/string_patterns.rs @@ -77,9 +77,7 @@ pub struct StringPatterns { impl StringPatterns { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -136,7 +134,7 @@ fn get_char_span<'tcx>(cx: &'_ LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Optio } } -fn check_manual_pattern_char_comparison(cx: &LateContext<'_>, method_arg: &Expr<'_>, msrv: &Msrv) { +fn check_manual_pattern_char_comparison(cx: &LateContext<'_>, method_arg: &Expr<'_>, msrv: Msrv) { if let ExprKind::Closure(closure) = method_arg.kind && let body = cx.tcx.hir_body(closure.body) && let Some(PatKind::Binding(_, binding, ..)) = body.params.first().map(|p| p.pat.kind) @@ -192,7 +190,7 @@ fn check_manual_pattern_char_comparison(cx: &LateContext<'_>, method_arg: &Expr< { return; } - if set_char_spans.len() > 1 && !msrv.meets(msrvs::PATTERN_TRAIT_CHAR_ARRAY) { + if set_char_spans.len() > 1 && !msrv.meets(cx, msrvs::PATTERN_TRAIT_CHAR_ARRAY) { return; } span_lint_and_then( @@ -238,9 +236,7 @@ impl<'tcx> LateLintPass<'tcx> for StringPatterns { { check_single_char_pattern_lint(cx, arg); - check_manual_pattern_char_comparison(cx, arg, &self.msrv); + check_manual_pattern_char_comparison(cx, arg, self.msrv); } } - - extract_msrv_attr!(LateContext); } diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index cbf7b126632e..f961e1c4d1a3 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -95,7 +95,7 @@ impl TraitBounds { pub fn new(conf: &'static Conf) -> Self { Self { max_trait_bounds: conf.max_trait_bounds, - msrv: conf.msrv.clone(), + msrv: conf.msrv, } } } @@ -223,17 +223,15 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { } } } - - extract_msrv_attr!(LateContext); } impl TraitBounds { /// Is the given bound a `?Sized` bound, and is combining it (i.e. `T: X + ?Sized`) an error on /// this MSRV? See for details. fn cannot_combine_maybe_bound(&self, cx: &LateContext<'_>, bound: &GenericBound<'_>) -> bool { - if !self.msrv.meets(msrvs::MAYBE_BOUND_IN_WHERE) - && let GenericBound::Trait(tr) = bound + if let GenericBound::Trait(tr) = bound && let BoundPolarity::Maybe(_) = tr.modifiers.polarity + && !self.msrv.meets(cx, msrvs::MAYBE_BOUND_IN_WHERE) { cx.tcx.lang_items().get(LangItem::Sized) == tr.trait_ref.path.res.opt_def_id() } else { diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index 1cb0f837227d..f2da8d35cb4f 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -49,7 +49,6 @@ declare_clippy_lint! { "transmutes that are confusing at best, undefined behavior at worst and always useless" } -// FIXME: Move this to `complexity` again, after #5343 is fixed declare_clippy_lint! { /// ### What it does /// Checks for transmutes to the original type of the object @@ -599,9 +598,7 @@ impl_lint_pass!(Transmute => [ ]); impl Transmute { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } impl<'tcx> LateLintPass<'tcx> for Transmute { @@ -633,16 +630,16 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { | crosspointer_transmute::check(cx, e, from_ty, to_ty) | transmuting_null::check(cx, e, arg, to_ty) | transmute_null_to_fn::check(cx, e, arg, to_ty) - | transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, arg, path, &self.msrv) + | transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, arg, path, self.msrv) | missing_transmute_annotations::check(cx, path, from_ty, to_ty, e.hir_id) | transmute_int_to_char::check(cx, e, from_ty, to_ty, arg, const_context) | transmute_ref_to_ref::check(cx, e, from_ty, to_ty, arg, const_context) - | transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg, &self.msrv) + | transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg, self.msrv) | transmute_int_to_bool::check(cx, e, from_ty, to_ty, arg) - | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg, const_context, &self.msrv) + | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg, const_context, self.msrv) | transmute_int_to_non_zero::check(cx, e, from_ty, to_ty, arg) - | transmute_float_to_int::check(cx, e, from_ty, to_ty, arg, const_context, &self.msrv) - | transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg, const_context, &self.msrv) + | transmute_float_to_int::check(cx, e, from_ty, to_ty, arg, const_context, self.msrv) + | transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg, const_context, self.msrv) | (unsound_collection_transmute::check(cx, e, from_ty, to_ty) || transmute_undefined_repr::check(cx, e, from_ty, to_ty)) | (eager_transmute::check(cx, e, arg, from_ty, to_ty)); @@ -652,6 +649,4 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { } } } - - extract_msrv_attr!(LateContext); } diff --git a/clippy_lints/src/transmute/transmute_float_to_int.rs b/clippy_lints/src/transmute/transmute_float_to_int.rs index f0b8abf9af66..f2c757952af3 100644 --- a/clippy_lints/src/transmute/transmute_float_to_int.rs +++ b/clippy_lints/src/transmute/transmute_float_to_int.rs @@ -17,11 +17,11 @@ pub(super) fn check<'tcx>( to_ty: Ty<'tcx>, mut arg: &'tcx Expr<'_>, const_context: bool, - msrv: &Msrv, + msrv: Msrv, ) -> bool { match (&from_ty.kind(), &to_ty.kind()) { (ty::Float(float_ty), ty::Int(_) | ty::Uint(_)) - if !const_context || msrv.meets(msrvs::CONST_FLOAT_BITS_CONV) => + if !const_context || msrv.meets(cx, msrvs::CONST_FLOAT_BITS_CONV) => { span_lint_and_then( cx, diff --git a/clippy_lints/src/transmute/transmute_int_to_float.rs b/clippy_lints/src/transmute/transmute_int_to_float.rs index e5b9aea6423a..aaa95396b4b4 100644 --- a/clippy_lints/src/transmute/transmute_int_to_float.rs +++ b/clippy_lints/src/transmute/transmute_int_to_float.rs @@ -16,10 +16,10 @@ pub(super) fn check<'tcx>( to_ty: Ty<'tcx>, arg: &'tcx Expr<'_>, const_context: bool, - msrv: &Msrv, + msrv: Msrv, ) -> bool { match (&from_ty.kind(), &to_ty.kind()) { - (ty::Int(_) | ty::Uint(_), ty::Float(_)) if !const_context || msrv.meets(msrvs::CONST_FLOAT_BITS_CONV) => { + (ty::Int(_) | ty::Uint(_), ty::Float(_)) if !const_context || msrv.meets(cx, msrvs::CONST_FLOAT_BITS_CONV) => { span_lint_and_then( cx, TRANSMUTE_INT_TO_FLOAT, diff --git a/clippy_lints/src/transmute/transmute_num_to_bytes.rs b/clippy_lints/src/transmute/transmute_num_to_bytes.rs index 6d828bad9b32..d72be270b731 100644 --- a/clippy_lints/src/transmute/transmute_num_to_bytes.rs +++ b/clippy_lints/src/transmute/transmute_num_to_bytes.rs @@ -16,14 +16,15 @@ pub(super) fn check<'tcx>( to_ty: Ty<'tcx>, arg: &'tcx Expr<'_>, const_context: bool, - msrv: &Msrv, + msrv: Msrv, ) -> bool { match (&from_ty.kind(), &to_ty.kind()) { (ty::Int(_) | ty::Uint(_) | ty::Float(_), ty::Array(arr_ty, _)) => { if !matches!(arr_ty.kind(), ty::Uint(UintTy::U8)) { return false; } - if matches!(from_ty.kind(), ty::Float(_)) && const_context && !msrv.meets(msrvs::CONST_FLOAT_BITS_CONV) { + if matches!(from_ty.kind(), ty::Float(_)) && const_context && !msrv.meets(cx, msrvs::CONST_FLOAT_BITS_CONV) + { return false; } diff --git a/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs b/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs index c4a2e20fa9d3..fcc763763bd2 100644 --- a/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs +++ b/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs @@ -15,7 +15,7 @@ pub(super) fn check<'tcx>( from_ty: Ty<'tcx>, to_ty: Ty<'tcx>, arg: &'tcx Expr<'_>, - msrv: &Msrv, + msrv: Msrv, ) -> bool { match (from_ty.kind(), to_ty.kind()) { (ty::RawPtr(from_pointee_ty, from_mutbl), ty::RawPtr(to_pointee_ty, to_mutbl)) => { @@ -28,7 +28,7 @@ pub(super) fn check<'tcx>( if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) { if from_mutbl == to_mutbl && to_pointee_ty.is_sized(cx.tcx, cx.typing_env()) - && msrv.meets(msrvs::POINTER_CAST) + && msrv.meets(cx, msrvs::POINTER_CAST) { diag.span_suggestion_verbose( e.span, @@ -43,7 +43,7 @@ pub(super) fn check<'tcx>( _ => None, } && !from_pointee_ty.has_erased_regions() - && msrv.meets(msrvs::POINTER_CAST_CONSTNESS) + && msrv.meets(cx, msrvs::POINTER_CAST_CONSTNESS) { diag.span_suggestion_verbose( e.span, diff --git a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs index ef18633d945f..45ee83c78ab6 100644 --- a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs +++ b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs @@ -17,7 +17,7 @@ pub(super) fn check<'tcx>( to_ty: Ty<'tcx>, arg: &'tcx Expr<'_>, path: &'tcx Path<'_>, - msrv: &Msrv, + msrv: Msrv, ) -> bool { match (&from_ty.kind(), &to_ty.kind()) { (ty::RawPtr(from_ptr_ty, _), ty::Ref(_, to_ref_ty, mutbl)) => { @@ -37,7 +37,7 @@ pub(super) fn check<'tcx>( let sugg = if let Some(ty) = get_explicit_type(path) { let ty_snip = snippet_with_applicability(cx, ty.span, "..", &mut app); - if msrv.meets(msrvs::POINTER_CAST) { + if msrv.meets(cx, msrvs::POINTER_CAST) { format!("{deref}{}.cast::<{ty_snip}>()", arg.maybe_par()) } else if from_ptr_ty.has_erased_regions() { sugg::make_unop(deref, arg.as_ty(format!("{cast} () as {cast} {ty_snip}"))).to_string() @@ -46,7 +46,7 @@ pub(super) fn check<'tcx>( } } else if *from_ptr_ty == *to_ref_ty { if from_ptr_ty.has_erased_regions() { - if msrv.meets(msrvs::POINTER_CAST) { + if msrv.meets(cx, msrvs::POINTER_CAST) { format!("{deref}{}.cast::<{to_ref_ty}>()", arg.maybe_par()) } else { sugg::make_unop(deref, arg.as_ty(format!("{cast} () as {cast} {to_ref_ty}"))) diff --git a/clippy_lints/src/tuple_array_conversions.rs b/clippy_lints/src/tuple_array_conversions.rs index c7aefc65f707..95ce19975c7e 100644 --- a/clippy_lints/src/tuple_array_conversions.rs +++ b/clippy_lints/src/tuple_array_conversions.rs @@ -47,15 +47,13 @@ pub struct TupleArrayConversions { } impl TupleArrayConversions { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } impl LateLintPass<'_> for TupleArrayConversions { fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - if expr.span.in_external_macro(cx.sess().source_map()) || !self.msrv.meets(msrvs::TUPLE_ARRAY_CONVERSIONS) { + if expr.span.in_external_macro(cx.sess().source_map()) || !self.msrv.meets(cx, msrvs::TUPLE_ARRAY_CONVERSIONS) { return; } @@ -65,8 +63,6 @@ impl LateLintPass<'_> for TupleArrayConversions { _ => {}, } } - - extract_msrv_attr!(LateContext); } fn check_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, elements: &'tcx [Expr<'tcx>]) { diff --git a/clippy_lints/src/types/mod.rs b/clippy_lints/src/types/mod.rs index 71e6e75c1bd3..151a6f67437c 100644 --- a/clippy_lints/src/types/mod.rs +++ b/clippy_lints/src/types/mod.rs @@ -2,6 +2,7 @@ mod borrowed_box; mod box_collection; mod linked_list; mod option_option; +mod owned_cow; mod rc_buffer; mod rc_mutex; mod redundant_allocation; @@ -355,13 +356,63 @@ declare_clippy_lint! { "usage of `Rc>`" } +declare_clippy_lint! { + /// ### What it does + /// Detects needlessly owned `Cow` types. + /// + /// ### Why is this bad? + /// The borrowed types are usually more flexible, in that e.g. a + /// `Cow<'_, str>` can accept both `&str` and `String` while + /// `Cow<'_, String>` can only accept `&String` and `String`. In + /// particular, `&str` is more general, because it allows for string + /// literals while `&String` can only be borrowed from a heap-owned + /// `String`). + /// + /// ### Known Problems + /// The lint does not check for usage of the type. There may be external + /// interfaces that require the use of an owned type. + /// + /// At least the `CString` type also has a different API than `CStr`: The + /// former has an `as_bytes` method which the latter calls `to_bytes`. + /// There is no guarantee that other types won't gain additional methods + /// leading to a similar mismatch. + /// + /// In addition, the lint only checks for the known problematic types + /// `String`, `Vec<_>`, `CString`, `OsString` and `PathBuf`. Custom types + /// that implement `ToOwned` will not be detected. + /// + /// ### Example + /// ```no_run + /// let wrogn: std::borrow::Cow<'_, Vec>; + /// ``` + /// Use instead: + /// ```no_run + /// let right: std::borrow::Cow<'_, [u8]>; + /// ``` + #[clippy::version = "1.85.0"] + pub OWNED_COW, + style, + "needlessly owned Cow type" +} + pub struct Types { vec_box_size_threshold: u64, type_complexity_threshold: u64, avoid_breaking_exported_api: bool, } -impl_lint_pass!(Types => [BOX_COLLECTION, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX, REDUNDANT_ALLOCATION, RC_BUFFER, RC_MUTEX, TYPE_COMPLEXITY]); +impl_lint_pass!(Types => [ + BOX_COLLECTION, + VEC_BOX, + OPTION_OPTION, + LINKEDLIST, + BORROWED_BOX, + REDUNDANT_ALLOCATION, + RC_BUFFER, + RC_MUTEX, + TYPE_COMPLEXITY, + OWNED_COW +]); impl<'tcx> LateLintPass<'tcx> for Types { fn check_fn( @@ -373,11 +424,10 @@ impl<'tcx> LateLintPass<'tcx> for Types { _: Span, def_id: LocalDefId, ) { - let is_in_trait_impl = if let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id( - cx.tcx - .hir_get_parent_item(cx.tcx.local_def_id_to_hir_id(def_id)) - .def_id, - ) { + let is_in_trait_impl = if let hir::Node::Item(item) = cx + .tcx + .hir_node_by_def_id(cx.tcx.hir_get_parent_item(cx.tcx.local_def_id_to_hir_id(def_id)).def_id) + { matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. })) } else { false @@ -560,6 +610,7 @@ impl Types { triggered |= option_option::check(cx, hir_ty, qpath, def_id); triggered |= linked_list::check(cx, hir_ty, def_id); triggered |= rc_mutex::check(cx, hir_ty, qpath, def_id); + triggered |= owned_cow::check(cx, qpath, def_id); if triggered { return; @@ -611,6 +662,14 @@ impl Types { QPath::LangItem(..) => {}, } }, + TyKind::Path(ref qpath) => { + let res = cx.qpath_res(qpath, hir_ty.hir_id); + if let Some(def_id) = res.opt_def_id() + && self.is_type_change_allowed(context) + { + owned_cow::check(cx, qpath, def_id); + } + }, TyKind::Ref(lt, ref mut_ty) => { context.is_nested_call = true; if !borrowed_box::check(cx, hir_ty, lt, mut_ty) { diff --git a/clippy_lints/src/types/owned_cow.rs b/clippy_lints/src/types/owned_cow.rs new file mode 100644 index 000000000000..8933994d1855 --- /dev/null +++ b/clippy_lints/src/types/owned_cow.rs @@ -0,0 +1,66 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_opt; +use rustc_errors::Applicability; +use rustc_hir::def_id::DefId; +use rustc_hir::{self as hir}; +use rustc_lint::LateContext; +use rustc_span::{Span, sym}; + +pub(super) fn check(cx: &LateContext<'_>, qpath: &hir::QPath<'_>, def_id: DefId) -> bool { + if cx.tcx.is_diagnostic_item(sym::Cow, def_id) + && let hir::QPath::Resolved(_, path) = qpath + && let [.., last_seg] = path.segments + && let Some(args) = last_seg.args + && let [_lt, carg] = args.args + && let hir::GenericArg::Type(cty) = carg + && let Some((span, repl)) = replacement(cx, cty.as_unambig_ty()) + { + span_lint_and_sugg( + cx, + super::OWNED_COW, + span, + "needlessly owned Cow type", + "use", + repl, + Applicability::Unspecified, + ); + return true; + } + false +} + +fn replacement(cx: &LateContext<'_>, cty: &hir::Ty<'_>) -> Option<(Span, String)> { + if clippy_utils::is_path_lang_item(cx, cty, hir::LangItem::String) { + return Some((cty.span, "str".into())); + } + if clippy_utils::is_path_diagnostic_item(cx, cty, sym::Vec) { + return if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = cty.kind + && let [.., last_seg] = path.segments + && let Some(args) = last_seg.args + && let [t, ..] = args.args + && let Some(snip) = snippet_opt(cx, t.span()) + { + Some((cty.span, format!("[{snip}]"))) + } else { + None + }; + } + if clippy_utils::is_path_diagnostic_item(cx, cty, sym::cstring_type) { + return Some(( + cty.span, + (if clippy_utils::is_no_std_crate(cx) { + "core::ffi::CStr" + } else { + "std::ffi::CStr" + }) + .into(), + )); + } + // Neither OsString nor PathBuf are available outside std + for (diag, repl) in [(sym::OsString, "std::ffi::OsStr"), (sym::PathBuf, "std::path::Path")] { + if clippy_utils::is_path_diagnostic_item(cx, cty, diag) { + return Some((cty.span, repl.into())); + } + } + None +} diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index 16916e3aaad5..746bf018bcc3 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -1,5 +1,5 @@ -use std::sync::Arc; use std::ops::ControlFlow; +use std::sync::Arc; use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; diff --git a/clippy_lints/src/unit_types/unit_arg.rs b/clippy_lints/src/unit_types/unit_arg.rs index 47d6fe7db766..019ae16ca859 100644 --- a/clippy_lints/src/unit_types/unit_arg.rs +++ b/clippy_lints/src/unit_types/unit_arg.rs @@ -177,7 +177,7 @@ fn fmt_stmts_and_call( stmts_and_call.push(call_snippet_with_replacements); stmts_and_call = stmts_and_call .into_iter() - .map(|v| reindent_multiline(v.into(), true, Some(call_expr_indent)).into_owned()) + .map(|v| reindent_multiline(&v, true, Some(call_expr_indent))) .collect(); let mut stmts_and_call_snippet = stmts_and_call.join(&format!("{}{}", ";\n", " ".repeat(call_expr_indent))); @@ -185,8 +185,7 @@ fn fmt_stmts_and_call( let parent_node = cx.tcx.parent_hir_node(call_expr.hir_id); if !matches!(parent_node, Node::Block(_)) && !matches!(parent_node, Node::Stmt(_)) { let block_indent = call_expr_indent + 4; - stmts_and_call_snippet = - reindent_multiline(stmts_and_call_snippet.into(), true, Some(block_indent)).into_owned(); + stmts_and_call_snippet = reindent_multiline(&stmts_and_call_snippet, true, Some(block_indent)); stmts_and_call_snippet = format!( "{{\n{}{}\n{}}}", " ".repeat(block_indent), diff --git a/clippy_lints/src/unnecessary_struct_initialization.rs b/clippy_lints/src/unnecessary_struct_initialization.rs index 1df229c330eb..5792b6b3178d 100644 --- a/clippy_lints/src/unnecessary_struct_initialization.rs +++ b/clippy_lints/src/unnecessary_struct_initialization.rs @@ -1,8 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; use clippy_utils::ty::is_copy; -use clippy_utils::{get_parent_expr, path_to_local}; -use rustc_hir::{BindingMode, Expr, ExprField, ExprKind, Node, PatKind, Path, QPath, StructTailExpr, UnOp}; +use clippy_utils::{get_parent_expr, is_mutable, path_to_local}; +use rustc_hir::{Expr, ExprField, ExprKind, Path, QPath, StructTailExpr, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; @@ -157,16 +157,6 @@ fn same_path_in_all_fields<'tcx>( } } -fn is_mutable(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - if let Some(hir_id) = path_to_local(expr) - && let Node::Pat(pat) = cx.tcx.hir_node(hir_id) - { - matches!(pat.kind, PatKind::Binding(BindingMode::MUT, ..)) - } else { - true - } -} - fn check_references(cx: &LateContext<'_>, expr_a: &Expr<'_>, expr_b: &Expr<'_>) -> bool { if let Some(parent) = get_parent_expr(cx, expr_a) && let parent_ty = cx.typeck_results().expr_ty_adjusted(parent) diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs index 8923484bb58f..f43715d6752e 100644 --- a/clippy_lints/src/unnested_or_patterns.rs +++ b/clippy_lints/src/unnested_or_patterns.rs @@ -3,7 +3,7 @@ use clippy_config::Conf; use clippy_utils::ast_utils::{eq_field_pat, eq_id, eq_maybe_qself, eq_pat, eq_path}; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::msrvs::{self, MsrvStack}; use clippy_utils::over; use rustc_ast::PatKind::*; use rustc_ast::mut_visit::*; @@ -48,13 +48,13 @@ declare_clippy_lint! { } pub struct UnnestedOrPatterns { - msrv: Msrv, + msrv: MsrvStack, } impl UnnestedOrPatterns { pub fn new(conf: &'static Conf) -> Self { Self { - msrv: conf.msrv.clone(), + msrv: MsrvStack::new(conf.msrv), } } } @@ -88,7 +88,7 @@ impl EarlyLintPass for UnnestedOrPatterns { } } - extract_msrv_attr!(EarlyContext); + extract_msrv_attr!(); } fn lint_unnested_or_patterns(cx: &EarlyContext<'_>, pat: &Pat) { diff --git a/clippy_lints/src/unused_trait_names.rs b/clippy_lints/src/unused_trait_names.rs index f83415834351..2577f1ceaa2c 100644 --- a/clippy_lints/src/unused_trait_names.rs +++ b/clippy_lints/src/unused_trait_names.rs @@ -51,9 +51,7 @@ pub struct UnusedTraitNames { impl UnusedTraitNames { pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } + Self { msrv: conf.msrv } } } @@ -61,8 +59,7 @@ impl_lint_pass!(UnusedTraitNames => [UNUSED_TRAIT_NAMES]); impl<'tcx> LateLintPass<'tcx> for UnusedTraitNames { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { - if self.msrv.meets(msrvs::UNDERSCORE_IMPORTS) - && !item.span.in_external_macro(cx.sess().source_map()) + if !item.span.in_external_macro(cx.sess().source_map()) && let ItemKind::Use(path, UseKind::Single) = item.kind // Ignore imports that already use Underscore && item.ident.name != kw::Underscore @@ -74,6 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedTraitNames { && cx.tcx.visibility(item.owner_id.def_id) == Visibility::Restricted(module.to_def_id()) && let Some(last_segment) = path.segments.last() && let Some(snip) = snippet_opt(cx, last_segment.ident.span) + && self.msrv.meets(cx, msrvs::UNDERSCORE_IMPORTS) && !is_from_proc_macro(cx, &last_segment.ident) { let complete_span = last_segment.ident.span.to(item.ident.span); @@ -88,6 +86,4 @@ impl<'tcx> LateLintPass<'tcx> for UnusedTraitNames { ); } } - - extract_msrv_attr!(LateContext); } diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 47ce2243aa09..743f54ca993a 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -2,7 +2,7 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_from_proc_macro; use clippy_utils::msrvs::{self, Msrv}; -use clippy_utils::ty::same_type_and_consts; +use clippy_utils::ty::{same_type_and_consts, ty_from_hir_ty}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def::{CtorOf, DefKind, Res}; @@ -12,7 +12,6 @@ use rustc_hir::{ self as hir, AmbigArg, Expr, ExprKind, FnRetTy, FnSig, GenericArgsParentheses, GenericParam, GenericParamKind, HirId, Impl, ImplItemKind, Item, ItemKind, Pat, PatExpr, PatExprKind, PatKind, Path, QPath, Ty, TyKind, }; -use rustc_hir_analysis::lower_ty; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty as MiddleTy; use rustc_session::impl_lint_pass; @@ -63,7 +62,7 @@ pub struct UseSelf { impl UseSelf { pub fn new(conf: &'static Conf) -> Self { Self { - msrv: conf.msrv.clone(), + msrv: conf.msrv, stack: Vec::new(), } } @@ -73,7 +72,6 @@ impl UseSelf { enum StackItem { Check { impl_id: LocalDefId, - in_body: u32, types_to_skip: FxHashSet, }, NoCheck, @@ -96,8 +94,8 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { .as_ref() .is_none_or(|params| params.parenthesized == GenericArgsParentheses::No) && !item.span.from_expansion() + // expensive, should be last check && !is_from_proc_macro(cx, item) - // expensive, should be last check { // Self cannot be used inside const generic parameters let types_to_skip = generics @@ -117,7 +115,6 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { .collect(); StackItem::Check { impl_id: item.owner_id.def_id, - in_body: 0, types_to_skip, } } else { @@ -131,6 +128,11 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { } fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) { + // Checking items of `impl Self` blocks in which macro expands into. + if impl_item.span.from_expansion() { + self.stack.push(StackItem::NoCheck); + return; + } // We want to skip types in trait `impl`s that aren't declared as `Self` in the trait // declaration. The collection of those types is all this method implementation does. if let ImplItemKind::Fn(FnSig { decl, .. }, ..) = impl_item.kind @@ -186,27 +188,18 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { } } - fn check_body(&mut self, _: &LateContext<'_>, _: &hir::Body<'_>) { - // `lower_ty` cannot be called in `Body`s or it will panic (sometimes). But in bodies - // we can use `cx.typeck_results.node_type(..)` to get the `ty::Ty` from a `hir::Ty`. - // However the `node_type()` method can *only* be called in bodies. - if let Some(&mut StackItem::Check { ref mut in_body, .. }) = self.stack.last_mut() { - *in_body = in_body.saturating_add(1); - } - } - - fn check_body_post(&mut self, _: &LateContext<'_>, _: &hir::Body<'_>) { - if let Some(&mut StackItem::Check { ref mut in_body, .. }) = self.stack.last_mut() { - *in_body = in_body.saturating_sub(1); + fn check_impl_item_post(&mut self, _: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) { + if impl_item.span.from_expansion() + && let Some(StackItem::NoCheck) = self.stack.last() + { + self.stack.pop(); } } fn check_ty(&mut self, cx: &LateContext<'tcx>, hir_ty: &Ty<'tcx, AmbigArg>) { if !hir_ty.span.from_expansion() - && self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS) && let Some(&StackItem::Check { impl_id, - in_body, ref types_to_skip, }) = self.stack.last() && let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind @@ -215,18 +208,14 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Def(DefKind::TyParam, _) ) && !types_to_skip.contains(&hir_ty.hir_id) - && let ty = if in_body > 0 { - cx.typeck_results().node_type(hir_ty.hir_id) - } else { - // We don't care about ignoring infer vars here - lower_ty(cx.tcx, hir_ty.as_unambig_ty()) - } + && let ty = ty_from_hir_ty(cx, hir_ty.as_unambig_ty()) && let impl_ty = cx.tcx.type_of(impl_id).instantiate_identity() && same_type_and_consts(ty, impl_ty) // Ensure the type we encounter and the one from the impl have the same lifetime parameters. It may be that // the lifetime parameters of `ty` are elided (`impl<'a> Foo<'a> { fn new() -> Self { Foo{..} } }`, in // which case we must still trigger the lint. && (has_no_lifetime(ty) || same_lifetimes(ty, impl_ty)) + && self.msrv.meets(cx, msrvs::TYPE_ALIAS_ENUM_VARIANTS) { span_lint(cx, hir_ty.span); } @@ -234,9 +223,9 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { if !expr.span.from_expansion() - && self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS) && let Some(&StackItem::Check { impl_id, .. }) = self.stack.last() && cx.typeck_results().expr_ty(expr) == cx.tcx.type_of(impl_id).instantiate_identity() + && self.msrv.meets(cx, msrvs::TYPE_ALIAS_ENUM_VARIANTS) { } else { return; @@ -255,19 +244,17 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { fn check_pat(&mut self, cx: &LateContext<'_>, pat: &Pat<'_>) { if !pat.span.from_expansion() - && self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS) && let Some(&StackItem::Check { impl_id, .. }) = self.stack.last() // get the path from the pattern && let PatKind::Expr(&PatExpr { kind: PatExprKind::Path(QPath::Resolved(_, path)), .. }) | PatKind::TupleStruct(QPath::Resolved(_, path), _, _) | PatKind::Struct(QPath::Resolved(_, path), _, _) = pat.kind && cx.typeck_results().pat_ty(pat) == cx.tcx.type_of(impl_id).instantiate_identity() + && self.msrv.meets(cx, msrvs::TYPE_ALIAS_ENUM_VARIANTS) { check_path(cx, path); } } - - extract_msrv_attr!(LateContext); } #[derive(Default)] diff --git a/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs index d6f10f1e4b80..89b4c48b8b11 100644 --- a/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs +++ b/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs @@ -249,7 +249,7 @@ fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<' pub(super) fn extract_clippy_version_value(cx: &LateContext<'_>, item: &'_ Item<'_>) -> Option { let attrs = cx.tcx.hir().attrs(item.hir_id()); attrs.iter().find_map(|attr| { - if let hir::AttrKind::Normal(attr_kind) = &attr.kind + if let hir::Attribute::Unparsed(attr_kind) = &attr // Identify attribute && let [tool_name, attr_name] = &attr_kind.path.segments[..] && tool_name.name == sym::clippy @@ -278,6 +278,6 @@ impl<'tcx> Visitor<'tcx> for LintCollector<'_, 'tcx> { } fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { - self.cx.tcx.hir() + self.cx.tcx } } diff --git a/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs b/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs index 686922461530..558acacb9724 100644 --- a/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs +++ b/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs @@ -30,8 +30,7 @@ impl LateLintPass<'_> for MsrvAttrImpl { .tcx .impl_trait_ref(item.owner_id) .map(EarlyBinder::instantiate_identity) - && let is_late_pass = match_def_path(cx, trait_ref.def_id, &paths::LATE_LINT_PASS) - && (is_late_pass || match_def_path(cx, trait_ref.def_id, &paths::EARLY_LINT_PASS)) + && match_def_path(cx, trait_ref.def_id, &paths::EARLY_LINT_PASS) && let ty::Adt(self_ty_def, _) = trait_ref.self_ty().kind() && self_ty_def.is_struct() && self_ty_def.all_fields().any(|f| { @@ -40,20 +39,18 @@ impl LateLintPass<'_> for MsrvAttrImpl { .instantiate_identity() .walk() .filter(|t| matches!(t.unpack(), GenericArgKind::Type(_))) - .any(|t| match_type(cx, t.expect_ty(), &paths::MSRV)) + .any(|t| match_type(cx, t.expect_ty(), &paths::MSRV_STACK)) }) && !items.iter().any(|item| item.ident.name.as_str() == "check_attributes") { - let context = if is_late_pass { "LateContext" } else { "EarlyContext" }; - let lint_pass = if is_late_pass { "LateLintPass" } else { "EarlyLintPass" }; let span = cx.sess().source_map().span_through_char(item.span, '{'); span_lint_and_sugg( cx, MISSING_MSRV_ATTR_IMPL, span, - format!("`extract_msrv_attr!` macro missing from `{lint_pass}` implementation"), - format!("add `extract_msrv_attr!({context})` to the `{lint_pass}` implementation"), - format!("{}\n extract_msrv_attr!({context});", snippet(cx, span, "..")), + "`extract_msrv_attr!` macro missing from `EarlyLintPass` implementation", + "add `extract_msrv_attr!()` to the `EarlyLintPass` implementation", + format!("{}\n extract_msrv_attr!();", snippet(cx, span, "..")), Applicability::MachineApplicable, ); } diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 03c667846b61..3346b15dae9c 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -27,7 +27,7 @@ impl UselessVec { pub fn new(conf: &'static Conf) -> Self { Self { too_large_for_stack: conf.too_large_for_stack, - msrv: conf.msrv.clone(), + msrv: conf.msrv, span_to_lint_map: BTreeMap::new(), allow_in_test: conf.allow_useless_vec_in_tests, } @@ -111,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { }, // search for `for _ in vec![...]` Node::Expr(Expr { span, .. }) - if span.is_desugaring(DesugaringKind::ForLoop) && self.msrv.meets(msrvs::ARRAY_INTO_ITERATOR) => + if span.is_desugaring(DesugaringKind::ForLoop) && self.msrv.meets(cx, msrvs::ARRAY_INTO_ITERATOR) => { let suggest_slice = suggest_type(expr); self.check_vec_macro(cx, &vec_args, callsite, expr.hir_id, suggest_slice); @@ -149,8 +149,6 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { } } } - - extract_msrv_attr!(LateContext); } impl UselessVec { diff --git a/clippy_lints/src/zero_sized_map_values.rs b/clippy_lints/src/zero_sized_map_values.rs index 4c9a7f0e16de..f6948be7f67a 100644 --- a/clippy_lints/src/zero_sized_map_values.rs +++ b/clippy_lints/src/zero_sized_map_values.rs @@ -1,10 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::ty::{is_normalizable, is_type_diagnostic_item}; +use clippy_utils::ty::{is_normalizable, is_type_diagnostic_item, ty_from_hir_ty}; use rustc_hir::{self as hir, AmbigArg, HirId, ItemKind, Node}; -use rustc_hir_analysis::lower_ty; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf as _; -use rustc_middle::ty::{self, Ty, TypeVisitableExt}; +use rustc_middle::ty::{self, TypeVisitableExt}; use rustc_session::declare_lint_pass; use rustc_span::sym; @@ -82,15 +81,3 @@ fn in_trait_impl(cx: &LateContext<'_>, hir_id: HirId) -> bool { } false } - -fn ty_from_hir_ty<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { - cx.maybe_typeck_results() - .and_then(|results| { - if results.hir_owner == hir_ty.hir_id.owner { - results.node_type_opt(hir_ty.hir_id) - } else { - None - } - }) - .unwrap_or_else(|| lower_ty(cx.tcx, hir_ty)) -} diff --git a/clippy_lints/src/zombie_processes.rs b/clippy_lints/src/zombie_processes.rs index 9bd00b1e5c8c..7667db469689 100644 --- a/clippy_lints/src/zombie_processes.rs +++ b/clippy_lints/src/zombie_processes.rs @@ -1,6 +1,6 @@ use ControlFlow::{Break, Continue}; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::{fn_def_id, get_enclosing_block, match_any_def_paths, match_def_path, path_to_local_id, paths}; +use clippy_utils::{fn_def_id, get_enclosing_block, path_to_local_id}; use rustc_ast::Mutability; use rustc_ast::visit::visit_opt; use rustc_errors::Applicability; @@ -58,7 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for ZombieProcesses { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if let ExprKind::Call(..) | ExprKind::MethodCall(..) = expr.kind && let Some(child_adt) = cx.typeck_results().expr_ty(expr).ty_adt_def() - && match_def_path(cx, child_adt.did(), &paths::CHILD) + && cx.tcx.is_diagnostic_item(sym::Child, child_adt.did()) { match cx.tcx.parent_hir_node(expr.hir_id) { Node::LetStmt(local) @@ -178,8 +178,8 @@ impl<'tcx> Visitor<'tcx> for WaitFinder<'_, 'tcx> { Node::Expr(expr) if let ExprKind::AddrOf(_, Mutability::Not, _) = expr.kind => {}, Node::Expr(expr) if let Some(fn_did) = fn_def_id(self.cx, expr) - && match_any_def_paths(self.cx, fn_did, &[&paths::CHILD_ID, &paths::CHILD_KILL]).is_some() => { - }, + && (self.cx.tcx.is_diagnostic_item(sym::child_id, fn_did) + || self.cx.tcx.is_diagnostic_item(sym::child_kill, fn_did)) => {}, // Conservatively assume that all other kinds of nodes call `.wait()` somehow. _ => return Break(MaybeWait(ex.span)), @@ -353,7 +353,7 @@ fn check<'tcx>(cx: &LateContext<'tcx>, spawn_expr: &'tcx Expr<'tcx>, cause: Caus /// Checks if the given expression exits the process. fn is_exit_expression(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { fn_def_id(cx, expr).is_some_and(|fn_did| { - cx.tcx.is_diagnostic_item(sym::process_exit, fn_did) || match_def_path(cx, fn_did, &paths::ABORT) + cx.tcx.is_diagnostic_item(sym::process_exit, fn_did) || cx.tcx.is_diagnostic_item(sym::process_abort, fn_did) }) } diff --git a/clippy_utils/Cargo.toml b/clippy_utils/Cargo.toml index 68b7e1592e2e..ba4bb1d177c5 100644 --- a/clippy_utils/Cargo.toml +++ b/clippy_utils/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_utils" # begin autogenerated version -version = "0.1.86" +version = "0.1.87" # end autogenerated version edition = "2024" description = "Helpful tools for writing lints, provided as they are used in Clippy" diff --git a/clippy_utils/README.md b/clippy_utils/README.md index 41f3b1cbd507..5dd31b52f880 100644 --- a/clippy_utils/README.md +++ b/clippy_utils/README.md @@ -8,7 +8,7 @@ This crate is only guaranteed to build with this `nightly` toolchain: ``` -nightly-2025-02-06 +nightly-2025-02-27 ``` diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index 0ac675345ae0..4bd86a253351 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -970,7 +970,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { }, InlineAsmOperand::SymFn { expr } => { self.hash_expr(expr); - } + }, InlineAsmOperand::Const { anon_const } => { self.hash_body(anon_const.body); }, diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index a3a75464fcbd..d850cc410008 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -39,6 +39,7 @@ extern crate rustc_data_structures; extern crate rustc_driver; extern crate rustc_errors; extern crate rustc_hir; +extern crate rustc_hir_analysis; extern crate rustc_hir_typeck; extern crate rustc_index; extern crate rustc_infer; @@ -91,8 +92,9 @@ use std::iter::{once, repeat_n}; use std::sync::{Mutex, MutexGuard, OnceLock}; use itertools::Itertools; +use rustc_abi::Integer; use rustc_ast::ast::{self, LitKind, RangeLimits}; -use rustc_attr_parsing::{find_attr, AttributeKind}; +use rustc_attr_parsing::{AttributeKind, find_attr}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::packed::Pu128; use rustc_data_structures::unhash::UnhashMap; @@ -106,24 +108,24 @@ use rustc_hir::{ self as hir, Arm, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind, ConstContext, Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat, - PatExpr, PatExprKind, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, + PatExpr, PatExprKind, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitFn, TraitItem, TraitItemKind, TraitItemRef, TraitRef, TyKind, UnOp, def, }; use rustc_lexer::{TokenKind, tokenize}; use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_middle::hir::place::PlaceBase; +use rustc_middle::mir::{AggregateKind, Operand, RETURN_PLACE, Rvalue, StatementKind, TerminatorKind}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ self as rustc_ty, Binder, BorrowKind, ClosureKind, EarlyBinder, FloatTy, GenericArgKind, GenericArgsRef, IntTy, Ty, - TyCtxt, TypeVisitableExt, UintTy, UpvarCapture, + TyCtxt, TypeFlags, TypeVisitableExt, UintTy, UpvarCapture, }; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{Ident, Symbol, kw}; use rustc_span::{InnerSpan, Span, sym}; -use rustc_abi::Integer; use visitors::{Visitable, for_each_unconsumed_temporary}; use crate::consts::{ConstEvalCtxt, Constant, mir_to_const}; @@ -134,24 +136,13 @@ use rustc_middle::hir::nested_filter; #[macro_export] macro_rules! extract_msrv_attr { - (LateContext) => { - fn check_attributes(&mut self, cx: &rustc_lint::LateContext<'_>, attrs: &[rustc_hir::Attribute]) { + () => { + fn check_attributes(&mut self, cx: &rustc_lint::EarlyContext<'_>, attrs: &[rustc_ast::ast::Attribute]) { let sess = rustc_lint::LintContext::sess(cx); self.msrv.check_attributes(sess, attrs); } - fn check_attributes_post(&mut self, cx: &rustc_lint::LateContext<'_>, attrs: &[rustc_hir::Attribute]) { - let sess = rustc_lint::LintContext::sess(cx); - self.msrv.check_attributes_post(sess, attrs); - } - }; - (EarlyContext) => { - fn check_attributes(&mut self, cx: &rustc_lint::EarlyContext<'_>, attrs: &[rustc_ast::Attribute]) { - let sess = rustc_lint::LintContext::sess(cx); - self.msrv.check_attributes(sess, attrs); - } - - fn check_attributes_post(&mut self, cx: &rustc_lint::EarlyContext<'_>, attrs: &[rustc_ast::Attribute]) { + fn check_attributes_post(&mut self, cx: &rustc_lint::EarlyContext<'_>, attrs: &[rustc_ast::ast::Attribute]) { let sess = rustc_lint::LintContext::sess(cx); self.msrv.check_attributes_post(sess, attrs); } @@ -914,22 +905,101 @@ fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath< } /// Returns true if the expr is equal to `Default::default` when evaluated. -pub fn is_default_equivalent_call(cx: &LateContext<'_>, repl_func: &Expr<'_>) -> bool { +pub fn is_default_equivalent_call( + cx: &LateContext<'_>, + repl_func: &Expr<'_>, + whole_call_expr: Option<&Expr<'_>>, +) -> bool { if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind && let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id() && (is_diag_trait_item(cx, repl_def_id, sym::Default) || is_default_equivalent_ctor(cx, repl_def_id, repl_func_qpath)) { - true - } else { - false + return true; } + + // Get the type of the whole method call expression, find the exact method definition, look at + // its body and check if it is similar to the corresponding `Default::default()` body. + let Some(e) = whole_call_expr else { return false }; + let Some(default_fn_def_id) = cx.tcx.get_diagnostic_item(sym::default_fn) else { + return false; + }; + let Some(ty) = cx.tcx.typeck(e.hir_id.owner.def_id).expr_ty_adjusted_opt(e) else { + return false; + }; + let args = rustc_ty::GenericArgs::for_item(cx.tcx, default_fn_def_id, |param, _| { + if let rustc_ty::GenericParamDefKind::Lifetime = param.kind { + cx.tcx.lifetimes.re_erased.into() + } else if param.index == 0 && param.name == kw::SelfUpper { + ty.into() + } else { + param.to_error(cx.tcx) + } + }); + let instance = rustc_ty::Instance::try_resolve(cx.tcx, cx.typing_env(), default_fn_def_id, args); + + let Ok(Some(instance)) = instance else { return false }; + if let rustc_ty::InstanceKind::Item(def) = instance.def + && !cx.tcx.is_mir_available(def) + { + return false; + } + let ExprKind::Path(ref repl_func_qpath) = repl_func.kind else { + return false; + }; + let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id() else { + return false; + }; + + // Get the MIR Body for the `::default()` function. + // If it is a value or call (either fn or ctor), we compare its `DefId` against the one for the + // resolution of the expression we had in the path. This lets us identify, for example, that + // the body of ` as Default>::default()` is a `Vec::new()`, and the field was being + // initialized to `Vec::new()` as well. + let body = cx.tcx.instance_mir(instance.def); + for block_data in body.basic_blocks.iter() { + if block_data.statements.len() == 1 + && let StatementKind::Assign(assign) = &block_data.statements[0].kind + && assign.0.local == RETURN_PLACE + && let Rvalue::Aggregate(kind, _places) = &assign.1 + && let AggregateKind::Adt(did, variant_index, _, _, _) = &**kind + && let def = cx.tcx.adt_def(did) + && let variant = &def.variant(*variant_index) + && variant.fields.is_empty() + && let Some((_, did)) = variant.ctor + && did == repl_def_id + { + return true; + } else if block_data.statements.is_empty() + && let Some(term) = &block_data.terminator + { + match &term.kind { + TerminatorKind::Call { + func: Operand::Constant(c), + .. + } if let rustc_ty::FnDef(did, _args) = c.ty().kind() + && *did == repl_def_id => + { + return true; + }, + TerminatorKind::TailCall { + func: Operand::Constant(c), + .. + } if let rustc_ty::FnDef(did, _args) = c.ty().kind() + && *did == repl_def_id => + { + return true; + }, + _ => {}, + } + } + } + false } -/// Returns true if the expr is equal to `Default::default()` of it's type when evaluated. +/// Returns true if the expr is equal to `Default::default()` of its type when evaluated. /// -/// It doesn't cover all cases, for example indirect function calls (some of std -/// functions are supported) but it is the best we have. +/// It doesn't cover all cases, like struct literals, but it is a close approximation. pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { match &e.kind { ExprKind::Lit(lit) => match lit.node { @@ -950,7 +1020,7 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { false } }, - ExprKind::Call(repl_func, []) => is_default_equivalent_call(cx, repl_func), + ExprKind::Call(repl_func, []) => is_default_equivalent_call(cx, repl_func, Some(e)), ExprKind::Call(from_func, [arg]) => is_default_equivalent_from(cx, from_func, arg), ExprKind::Path(qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, e.hir_id), OptionNone), ExprKind::AddrOf(rustc_hir::BorrowKind::Ref, _, expr) => matches!(expr.kind, ExprKind::Array([])), @@ -1419,6 +1489,10 @@ pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio | Node::ImplItem(&ImplItem { kind: ImplItemKind::Fn(_, eid), .. + }) + | Node::TraitItem(&TraitItem { + kind: TraitItemKind::Fn(_, TraitFn::Provided(eid)), + .. }) => match cx.tcx.hir_body(eid).value.kind { ExprKind::Block(block, _) => Some(block), _ => None, @@ -1665,6 +1739,17 @@ pub fn is_integer_literal(expr: &Expr<'_>, value: u128) -> bool { false } +/// Checks whether the given expression is a constant literal of the given value. +pub fn is_float_literal(expr: &Expr<'_>, value: f64) -> bool { + if let ExprKind::Lit(spanned) = expr.kind + && let LitKind::Float(v, _) = spanned.node + { + v.as_str().parse() == Ok(value) + } else { + false + } +} + /// Returns `true` if the given `Expr` has been coerced before. /// /// Examples of coercions can be found in the Nomicon at @@ -1969,8 +2054,7 @@ pub fn any_parent_has_attr(tcx: TyCtxt<'_>, node: HirId, symbol: Symbol) -> bool /// Checks if the given HIR node is inside an `impl` block with the `automatically_derived` /// attribute. pub fn in_automatically_derived(tcx: TyCtxt<'_>, id: HirId) -> bool { - tcx - .hir_parent_owner_iter(id) + tcx.hir_parent_owner_iter(id) .filter(|(_, node)| matches!(node, OwnerNode::Item(item) if matches!(item.kind, ItemKind::Impl(_)))) .any(|(id, _)| { has_attr( @@ -2616,9 +2700,7 @@ pub fn is_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool { /// Checks if any parent node of `HirId` has `#[cfg(test)]` attribute applied pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool { - tcx - .hir_parent_id_iter(id) - .any(|parent_id| is_cfg_test(tcx, parent_id)) + tcx.hir_parent_id_iter(id).any(|parent_id| is_cfg_test(tcx, parent_id)) } /// Checks if the node is in a `#[test]` function or has any parent node marked `#[cfg(test)]` @@ -3502,3 +3584,114 @@ pub fn leaks_droppable_temporary_with_limited_lifetime<'tcx>(cx: &LateContext<'t }) .is_break() } + +/// Returns true if the specified `expr` requires coercion, +/// meaning that it either has a coercion or propagates a coercion from one of its sub expressions. +/// +/// Similar to [`is_adjusted`], this not only checks if an expression's type was adjusted, +/// but also going through extra steps to see if it fits the description of [coercion sites]. +/// +/// You should used this when you want to avoid suggesting replacing an expression that is currently +/// a coercion site or coercion propagating expression with one that is not. +/// +/// [coercion sites]: https://doc.rust-lang.org/stable/reference/type-coercions.html#coercion-sites +pub fn expr_requires_coercion<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> bool { + let expr_ty_is_adjusted = cx + .typeck_results() + .expr_adjustments(expr) + .iter() + // ignore `NeverToAny` adjustments, such as `panic!` call. + .any(|adj| !matches!(adj.kind, Adjust::NeverToAny)); + if expr_ty_is_adjusted { + return true; + } + + // Identify coercion sites and recursively check if those sites + // actually have type adjustments. + match expr.kind { + ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args, _) if let Some(def_id) = fn_def_id(cx, expr) => { + let fn_sig = cx.tcx.fn_sig(def_id).instantiate_identity(); + + if !fn_sig.output().skip_binder().has_type_flags(TypeFlags::HAS_TY_PARAM) { + return false; + } + + let self_arg_count = usize::from(matches!(expr.kind, ExprKind::MethodCall(..))); + let mut args_with_ty_param = { + fn_sig + .inputs() + .skip_binder() + .iter() + .skip(self_arg_count) + .zip(args) + .filter_map(|(arg_ty, arg)| { + if arg_ty.has_type_flags(TypeFlags::HAS_TY_PARAM) { + Some(arg) + } else { + None + } + }) + }; + args_with_ty_param.any(|arg| expr_requires_coercion(cx, arg)) + }, + // Struct/union initialization. + ExprKind::Struct(qpath, _, _) => { + let res = cx.typeck_results().qpath_res(qpath, expr.hir_id); + if let Some((_, v_def)) = adt_and_variant_of_res(cx, res) { + let rustc_ty::Adt(_, generic_args) = cx.typeck_results().expr_ty_adjusted(expr).kind() else { + // This should never happen, but when it does, not linting is the better option. + return true; + }; + v_def + .fields + .iter() + .any(|field| field.ty(cx.tcx, generic_args).has_type_flags(TypeFlags::HAS_TY_PARAM)) + } else { + false + } + }, + // Function results, including the final line of a block or a `return` expression. + ExprKind::Block( + &Block { + expr: Some(ret_expr), .. + }, + _, + ) + | ExprKind::Ret(Some(ret_expr)) => expr_requires_coercion(cx, ret_expr), + + // ===== Coercion-propagation expressions ===== + ExprKind::Array(elems) | ExprKind::Tup(elems) => elems.iter().any(|elem| expr_requires_coercion(cx, elem)), + // Array but with repeating syntax. + ExprKind::Repeat(rep_elem, _) => expr_requires_coercion(cx, rep_elem), + // Others that may contain coercion sites. + ExprKind::If(_, then, maybe_else) => { + expr_requires_coercion(cx, then) || maybe_else.is_some_and(|e| expr_requires_coercion(cx, e)) + }, + ExprKind::Match(_, arms, _) => arms + .iter() + .map(|arm| arm.body) + .any(|body| expr_requires_coercion(cx, body)), + _ => false, + } +} + +/// Returns `true` if `expr` designates a mutable static, a mutable local binding, or an expression +/// that can be owned. +pub fn is_mutable(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + if let Some(hir_id) = path_to_local(expr) + && let Node::Pat(pat) = cx.tcx.hir_node(hir_id) + { + matches!(pat.kind, PatKind::Binding(BindingMode::MUT, ..)) + } else if let ExprKind::Path(p) = &expr.kind + && let Some(mutability) = cx + .qpath_res(p, expr.hir_id) + .opt_def_id() + .and_then(|id| cx.tcx.static_mutability(id)) + { + mutability == Mutability::Mut + } else if let ExprKind::Field(parent, _) = expr.kind { + is_mutable(cx, parent) + } else { + true + } +} diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs index 9ce0fd8318f1..3ce2cdfebe96 100644 --- a/clippy_utils/src/macros.rs +++ b/clippy_utils/src/macros.rs @@ -30,6 +30,8 @@ const FORMAT_MACRO_DIAG_ITEMS: &[Symbol] = &[ sym::print_macro, sym::println_macro, sym::std_panic_macro, + sym::todo_macro, + sym::unimplemented_macro, sym::write_macro, sym::writeln_macro, ]; diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 24f73b9df268..5bb2b12988a6 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -1,11 +1,14 @@ +use rustc_ast::Attribute; use rustc_ast::attr::AttributeExt; use rustc_attr_parsing::{RustcVersion, parse_version}; +use rustc_lint::LateContext; use rustc_session::Session; use rustc_span::{Symbol, sym}; use serde::Deserialize; -use smallvec::{SmallVec, smallvec}; -use std::fmt; +use smallvec::SmallVec; +use std::iter::once; +use std::sync::atomic::{AtomicBool, Ordering}; macro_rules! msrv_aliases { ($($major:literal,$minor:literal,$patch:literal { @@ -19,6 +22,8 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { + 1,87,0 { OS_STR_DISPLAY, INT_MIDPOINT } + 1,85,0 { UINT_FLOAT_MIDPOINT } 1,84,0 { CONST_OPTION_AS_SLICE } 1,83,0 { CONST_EXTERN_FN, CONST_FLOAT_BITS_CONV, CONST_FLOAT_CLASSIFY, CONST_MUT_REFS, CONST_UNWRAP } 1,82,0 { IS_NONE_OR, REPEAT_N, RAW_REF_OP } @@ -27,7 +32,7 @@ msrv_aliases! { 1,77,0 { C_STR_LITERALS } 1,76,0 { PTR_FROM_REF, OPTION_RESULT_INSPECT } 1,75,0 { OPTION_AS_SLICE } - 1,74,0 { REPR_RUST } + 1,74,0 { REPR_RUST, IO_ERROR_OTHER } 1,73,0 { MANUAL_DIV_CEIL } 1,71,0 { TUPLE_ARRAY_CONVERSIONS, BUILD_HASHER_HASH_ONE } 1,70,0 { OPTION_RESULT_IS_VARIANT_AND, BINARY_HEAP_RETAIN } @@ -37,10 +42,11 @@ msrv_aliases! { 1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE, CONST_EXTERN_C_FN } 1,59,0 { THREAD_LOCAL_CONST_INIT } 1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY, CONST_RAW_PTR_DEREF } + 1,57,0 { MAP_WHILE } 1,56,0 { CONST_FN_UNION } 1,55,0 { SEEK_REWIND } 1,54,0 { INTO_KEYS } - 1,53,0 { OR_PATTERNS, MANUAL_BITS, BTREE_MAP_RETAIN, BTREE_SET_RETAIN, ARRAY_INTO_ITERATOR } + 1,53,0 { OR_PATTERNS, INTEGER_BITS, BTREE_MAP_RETAIN, BTREE_SET_RETAIN, ARRAY_INTO_ITERATOR } 1,52,0 { STR_SPLIT_ONCE, REM_EUCLID_CONST } 1,51,0 { BORROW_AS_PTR, SEEK_FROM_CURRENT, UNSIGNED_ABS } 1,50,0 { BOOL_THEN, CLAMP, SLICE_FILL } @@ -57,6 +63,7 @@ msrv_aliases! { 1,35,0 { OPTION_COPIED, RANGE_CONTAINS } 1,34,0 { TRY_FROM } 1,33,0 { UNDERSCORE_IMPORTS } + 1,31,0 { OPTION_REPLACE } 1,30,0 { ITERATOR_FIND_MAP, TOOL_ATTRIBUTES } 1,29,0 { ITER_FLATTEN } 1,28,0 { FROM_BOOL, REPEAT_WITH } @@ -69,21 +76,15 @@ msrv_aliases! { 1,15,0 { MAYBE_BOUND_IN_WHERE } } -/// Tracks the current MSRV from `clippy.toml`, `Cargo.toml` or set via `#[clippy::msrv]` -#[derive(Debug, Clone)] -pub struct Msrv { - stack: SmallVec<[RustcVersion; 2]>, -} +/// `#[clippy::msrv]` attributes are rarely used outside of Clippy's test suite, as a basic +/// optimization we can skip traversing the HIR in [`Msrv::meets`] if we never saw an MSRV attribute +/// during the early lint passes +static SEEN_MSRV_ATTR: AtomicBool = AtomicBool::new(false); -impl fmt::Display for Msrv { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if let Some(msrv) = self.current() { - write!(f, "{msrv}") - } else { - f.write_str("1.0.0") - } - } -} +/// Tracks the current MSRV from `clippy.toml`, `Cargo.toml` or set via `#[clippy::msrv]` in late +/// lint passes, use [`MsrvStack`] for early passes +#[derive(Copy, Clone, Debug, Default)] +pub struct Msrv(Option); impl<'de> Deserialize<'de> for Msrv { fn deserialize(deserializer: D) -> Result @@ -92,14 +93,36 @@ impl<'de> Deserialize<'de> for Msrv { { let v = String::deserialize(deserializer)?; parse_version(Symbol::intern(&v)) - .map(|v| Msrv { stack: smallvec![v] }) + .map(|v| Self(Some(v))) .ok_or_else(|| serde::de::Error::custom("not a valid Rust version")) } } impl Msrv { - pub fn empty() -> Msrv { - Msrv { stack: SmallVec::new() } + /// Returns the MSRV at the current node + /// + /// If the crate being linted uses an `#[clippy::msrv]` attribute this will search the parent + /// nodes for that attribute, prefer to run this check after cheaper pattern matching operations + pub fn current(self, cx: &LateContext<'_>) -> Option { + if SEEN_MSRV_ATTR.load(Ordering::Relaxed) { + let start = cx.last_node_with_lint_attrs; + if let Some(msrv_attr) = once(start) + .chain(cx.tcx.hir_parent_id_iter(start)) + .find_map(|id| parse_attrs(cx.tcx.sess, cx.tcx.hir().attrs(id))) + { + return Some(msrv_attr); + } + } + + self.0 + } + + /// Checks if a required version from [this module](self) is met at the current node + /// + /// If the crate being linted uses an `#[clippy::msrv]` attribute this will search the parent + /// nodes for that attribute, prefer to run this check after cheaper pattern matching operations + pub fn meets(self, cx: &LateContext<'_>, required: RustcVersion) -> bool { + self.current(cx).is_none_or(|msrv| msrv >= required) } pub fn read_cargo(&mut self, sess: &Session) { @@ -107,8 +130,8 @@ impl Msrv { .ok() .and_then(|v| parse_version(Symbol::intern(&v))); - match (self.current(), cargo_msrv) { - (None, Some(cargo_msrv)) => self.stack = smallvec![cargo_msrv], + match (self.0, cargo_msrv) { + (None, Some(cargo_msrv)) => self.0 = Some(cargo_msrv), (Some(clippy_msrv), Some(cargo_msrv)) => { if clippy_msrv != cargo_msrv { sess.dcx().warn(format!( @@ -119,6 +142,21 @@ impl Msrv { _ => {}, } } +} + +/// Tracks the current MSRV from `clippy.toml`, `Cargo.toml` or set via `#[clippy::msrv]` in early +/// lint passes, use [`Msrv`] for late passes +#[derive(Debug, Clone)] +pub struct MsrvStack { + stack: SmallVec<[RustcVersion; 2]>, +} + +impl MsrvStack { + pub fn new(initial: Msrv) -> Self { + Self { + stack: SmallVec::from_iter(initial.0), + } + } pub fn current(&self) -> Option { self.stack.last().copied() @@ -128,42 +166,43 @@ impl Msrv { self.current().is_none_or(|msrv| msrv >= required) } - fn parse_attr(sess: &Session, attrs: &[impl AttributeExt]) -> Option { - let sym_msrv = Symbol::intern("msrv"); - let mut msrv_attrs = attrs.iter().filter(|attr| attr.path_matches(&[sym::clippy, sym_msrv])); - - if let Some(msrv_attr) = msrv_attrs.next() { - if let Some(duplicate) = msrv_attrs.next_back() { - sess.dcx() - .struct_span_err(duplicate.span(), "`clippy::msrv` is defined multiple times") - .with_span_note(msrv_attr.span(), "first definition found here") - .emit(); - } - - if let Some(msrv) = msrv_attr.value_str() { - if let Some(version) = parse_version(msrv) { - return Some(version); - } - - sess.dcx() - .span_err(msrv_attr.span(), format!("`{msrv}` is not a valid Rust version")); - } else { - sess.dcx().span_err(msrv_attr.span(), "bad clippy attribute"); - } - } - - None - } - - pub fn check_attributes(&mut self, sess: &Session, attrs: &[impl AttributeExt]) { - if let Some(version) = Self::parse_attr(sess, attrs) { + pub fn check_attributes(&mut self, sess: &Session, attrs: &[Attribute]) { + if let Some(version) = parse_attrs(sess, attrs) { + SEEN_MSRV_ATTR.store(true, Ordering::Relaxed); self.stack.push(version); } } - pub fn check_attributes_post(&mut self, sess: &Session, attrs: &[impl AttributeExt]) { - if Self::parse_attr(sess, attrs).is_some() { + pub fn check_attributes_post(&mut self, sess: &Session, attrs: &[Attribute]) { + if parse_attrs(sess, attrs).is_some() { self.stack.pop(); } } } + +fn parse_attrs(sess: &Session, attrs: &[impl AttributeExt]) -> Option { + let sym_msrv = Symbol::intern("msrv"); + let mut msrv_attrs = attrs.iter().filter(|attr| attr.path_matches(&[sym::clippy, sym_msrv])); + + if let Some(msrv_attr) = msrv_attrs.next() { + if let Some(duplicate) = msrv_attrs.next_back() { + sess.dcx() + .struct_span_err(duplicate.span(), "`clippy::msrv` is defined multiple times") + .with_span_note(msrv_attr.span(), "first definition found here") + .emit(); + } + + if let Some(msrv) = msrv_attr.value_str() { + if let Some(version) = parse_version(msrv) { + return Some(version); + } + + sess.dcx() + .span_err(msrv_attr.span(), format!("`{msrv}` is not a valid Rust version")); + } else { + sess.dcx().span_err(msrv_attr.span(), "bad clippy attribute"); + } + } + + None +} diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs index f15fffc09e8d..51d06ad9b1aa 100644 --- a/clippy_utils/src/paths.rs +++ b/clippy_utils/src/paths.rs @@ -19,7 +19,6 @@ pub const IDENT: [&str; 3] = ["rustc_span", "symbol", "Ident"]; pub const IDENT_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Ident", "as_str"]; 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"]; @@ -28,16 +27,12 @@ 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 ABORT: [&str; 3] = ["std", "process", "abort"]; -pub const CHILD: [&str; 3] = ["std", "process", "Child"]; -pub const CHILD_ID: [&str; 4] = ["std", "process", "Child", "id"]; -pub const CHILD_KILL: [&str; 4] = ["std", "process", "Child", "kill"]; -pub const PANIC_ANY: [&str; 3] = ["std", "panic", "panic_any"]; pub const CHAR_IS_ASCII: [&str; 5] = ["core", "char", "methods", "", "is_ascii"]; -pub const STDIN: [&str; 4] = ["std", "io", "stdio", "Stdin"]; +pub const IO_ERROR_NEW: [&str; 5] = ["std", "io", "error", "Error", "new"]; +pub const IO_ERRORKIND_OTHER: [&str; 5] = ["std", "io", "error", "ErrorKind", "Other"]; // Paths in clippy itself -pub const MSRV: [&str; 3] = ["clippy_utils", "msrvs", "Msrv"]; +pub const MSRV_STACK: [&str; 3] = ["clippy_utils", "msrvs", "MsrvStack"]; // Paths in external crates #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index c7890f33f27e..8e6f4d4a317e 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -11,6 +11,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::Obligation; +use rustc_lint::LateContext; use rustc_middle::mir::{ Body, CastKind, NonDivergingIntrinsic, NullOp, Operand, Place, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, @@ -25,16 +26,16 @@ use std::borrow::Cow; type McfResult = Result<(), (Span, Cow<'static, str>)>; -pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) -> McfResult { +pub fn is_min_const_fn<'tcx>(cx: &LateContext<'tcx>, body: &Body<'tcx>, msrv: Msrv) -> McfResult { let def_id = body.source.def_id(); for local in &body.local_decls { - check_ty(tcx, local.ty, local.source_info.span, msrv)?; + check_ty(cx, local.ty, local.source_info.span, msrv)?; } // impl trait is gone in MIR, so check the return type manually check_ty( - tcx, - tcx.fn_sig(def_id).instantiate_identity().output().skip_binder(), + cx, + cx.tcx.fn_sig(def_id).instantiate_identity().output().skip_binder(), body.local_decls.iter().next().unwrap().source_info.span, msrv, )?; @@ -43,16 +44,16 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) // Cleanup blocks are ignored entirely by const eval, so we can too: // https://github.com/rust-lang/rust/blob/1dea922ea6e74f99a0e97de5cdb8174e4dea0444/compiler/rustc_const_eval/src/transform/check_consts/check.rs#L382 if !bb.is_cleanup { - check_terminator(tcx, body, bb.terminator(), msrv)?; + check_terminator(cx, body, bb.terminator(), msrv)?; for stmt in &bb.statements { - check_statement(tcx, body, def_id, stmt, msrv)?; + check_statement(cx, body, def_id, stmt, msrv)?; } } } Ok(()) } -fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, msrv: &Msrv) -> McfResult { +fn check_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, msrv: Msrv) -> McfResult { for arg in ty.walk() { let ty = match arg.unpack() { GenericArgKind::Type(ty) => ty, @@ -63,7 +64,7 @@ fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, msrv: &Msrv) -> M }; match ty.kind() { - ty::Ref(_, _, hir::Mutability::Mut) if !msrv.meets(msrvs::CONST_MUT_REFS) => { + ty::Ref(_, _, hir::Mutability::Mut) if !msrv.meets(cx, msrvs::CONST_MUT_REFS) => { return Err((span, "mutable references in const fn are unstable".into())); }, ty::Alias(ty::Opaque, ..) => return Err((span, "`impl Trait` in const fn is unstable".into())), @@ -82,7 +83,7 @@ fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, msrv: &Msrv) -> M )); }, ty::ExistentialPredicate::Trait(trait_ref) => { - if Some(trait_ref.def_id) != tcx.lang_items().sized_trait() { + if Some(trait_ref.def_id) != cx.tcx.lang_items().sized_trait() { return Err(( span, "trait bounds other than `Sized` \ @@ -101,19 +102,19 @@ fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, msrv: &Msrv) -> M } fn check_rvalue<'tcx>( - tcx: TyCtxt<'tcx>, + cx: &LateContext<'tcx>, body: &Body<'tcx>, def_id: DefId, rvalue: &Rvalue<'tcx>, span: Span, - msrv: &Msrv, + msrv: Msrv, ) -> McfResult { match rvalue { Rvalue::ThreadLocalRef(_) => Err((span, "cannot access thread local storage in const fn".into())), Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) => { - check_place(tcx, *place, span, body, msrv) + check_place(cx, *place, span, body, msrv) }, - Rvalue::CopyForDeref(place) => check_place(tcx, *place, span, body, msrv), + Rvalue::CopyForDeref(place) => check_place(cx, *place, span, body, msrv), Rvalue::Repeat(operand, _) | Rvalue::Use(operand) | Rvalue::WrapUnsafeBinder(operand, _) @@ -128,7 +129,7 @@ fn check_rvalue<'tcx>( | CastKind::PointerCoercion(PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer, _), operand, _, - ) => check_operand(tcx, operand, span, body, msrv), + ) => check_operand(cx, operand, span, body, msrv), Rvalue::Cast( CastKind::PointerCoercion( PointerCoercion::UnsafeFnPointer @@ -144,9 +145,11 @@ fn check_rvalue<'tcx>( // We cannot allow this for now. return Err((span, "unsizing casts are only allowed for references right now".into())); }; - let unsized_ty = tcx.struct_tail_for_codegen(pointee_ty, ty::TypingEnv::post_analysis(tcx, def_id)); + let unsized_ty = cx + .tcx + .struct_tail_for_codegen(pointee_ty, ty::TypingEnv::post_analysis(cx.tcx, def_id)); if let ty::Slice(_) | ty::Str = unsized_ty.kind() { - check_operand(tcx, op, span, body, msrv)?; + check_operand(cx, op, span, body, msrv)?; // Casting/coercing things to slices is fine. Ok(()) } else { @@ -167,9 +170,9 @@ fn check_rvalue<'tcx>( )), // binops are fine on integers Rvalue::BinaryOp(_, box (lhs, rhs)) => { - check_operand(tcx, lhs, span, body, msrv)?; - check_operand(tcx, rhs, span, body, msrv)?; - let ty = lhs.ty(body, tcx); + check_operand(cx, lhs, span, body, msrv)?; + check_operand(cx, rhs, span, body, msrv)?; + let ty = lhs.ty(body, cx.tcx); if ty.is_integral() || ty.is_bool() || ty.is_char() { Ok(()) } else { @@ -185,16 +188,16 @@ fn check_rvalue<'tcx>( ) | Rvalue::ShallowInitBox(_, _) => Ok(()), Rvalue::UnaryOp(_, operand) => { - let ty = operand.ty(body, tcx); + let ty = operand.ty(body, cx.tcx); if ty.is_integral() || ty.is_bool() { - check_operand(tcx, operand, span, body, msrv) + check_operand(cx, operand, span, body, msrv) } else { Err((span, "only int and `bool` operations are stable in const fn".into())) } }, Rvalue::Aggregate(_, operands) => { for operand in operands { - check_operand(tcx, operand, span, body, msrv)?; + check_operand(cx, operand, span, body, msrv)?; } Ok(()) }, @@ -202,33 +205,33 @@ fn check_rvalue<'tcx>( } fn check_statement<'tcx>( - tcx: TyCtxt<'tcx>, + cx: &LateContext<'tcx>, body: &Body<'tcx>, def_id: DefId, statement: &Statement<'tcx>, - msrv: &Msrv, + msrv: Msrv, ) -> McfResult { let span = statement.source_info.span; match &statement.kind { StatementKind::Assign(box (place, rval)) => { - check_place(tcx, *place, span, body, msrv)?; - check_rvalue(tcx, body, def_id, rval, span, msrv) + check_place(cx, *place, span, body, msrv)?; + check_rvalue(cx, body, def_id, rval, span, msrv) }, - StatementKind::FakeRead(box (_, place)) => check_place(tcx, *place, span, body, msrv), + StatementKind::FakeRead(box (_, place)) => check_place(cx, *place, span, body, msrv), // just an assignment StatementKind::SetDiscriminant { place, .. } | StatementKind::Deinit(place) => { - check_place(tcx, **place, span, body, msrv) + check_place(cx, **place, span, body, msrv) }, - StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => check_operand(tcx, op, span, body, msrv), + StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => check_operand(cx, op, span, body, msrv), StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping( rustc_middle::mir::CopyNonOverlapping { dst, src, count }, )) => { - check_operand(tcx, dst, span, body, msrv)?; - check_operand(tcx, src, span, body, msrv)?; - check_operand(tcx, count, span, body, msrv) + check_operand(cx, dst, span, body, msrv)?; + check_operand(cx, src, span, body, msrv)?; + check_operand(cx, count, span, body, msrv) }, // These are all NOPs StatementKind::StorageLive(_) @@ -244,16 +247,16 @@ fn check_statement<'tcx>( } fn check_operand<'tcx>( - tcx: TyCtxt<'tcx>, + cx: &LateContext<'tcx>, operand: &Operand<'tcx>, span: Span, body: &Body<'tcx>, - msrv: &Msrv, + msrv: Msrv, ) -> McfResult { match operand { Operand::Move(place) => { if !place.projection.as_ref().is_empty() - && !is_ty_const_destruct(tcx, place.ty(&body.local_decls, tcx).ty, body) + && !is_ty_const_destruct(cx.tcx, place.ty(&body.local_decls, cx.tcx).ty, body) { return Err(( span, @@ -261,29 +264,35 @@ fn check_operand<'tcx>( )); } - check_place(tcx, *place, span, body, msrv) + check_place(cx, *place, span, body, msrv) }, - Operand::Copy(place) => check_place(tcx, *place, span, body, msrv), - Operand::Constant(c) => match c.check_static_ptr(tcx) { + Operand::Copy(place) => check_place(cx, *place, span, body, msrv), + Operand::Constant(c) => match c.check_static_ptr(cx.tcx) { Some(_) => Err((span, "cannot access `static` items in const fn".into())), None => Ok(()), }, } } -fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'tcx>, msrv: &Msrv) -> McfResult { +fn check_place<'tcx>( + cx: &LateContext<'tcx>, + place: Place<'tcx>, + span: Span, + body: &Body<'tcx>, + msrv: Msrv, +) -> McfResult { for (base, elem) in place.as_ref().iter_projections() { match elem { ProjectionElem::Field(..) => { - if base.ty(body, tcx).ty.is_union() && !msrv.meets(msrvs::CONST_FN_UNION) { + if base.ty(body, cx.tcx).ty.is_union() && !msrv.meets(cx, msrvs::CONST_FN_UNION) { return Err((span, "accessing union fields is unstable".into())); } }, - ProjectionElem::Deref => match base.ty(body, tcx).ty.kind() { + ProjectionElem::Deref => match base.ty(body, cx.tcx).ty.kind() { ty::RawPtr(_, hir::Mutability::Mut) => { return Err((span, "dereferencing raw mut pointer in const fn is unstable".into())); }, - ty::RawPtr(_, hir::Mutability::Not) if !msrv.meets(msrvs::CONST_RAW_PTR_DEREF) => { + ty::RawPtr(_, hir::Mutability::Not) if !msrv.meets(cx, msrvs::CONST_RAW_PTR_DEREF) => { return Err((span, "dereferencing raw const pointer in const fn is unstable".into())); }, _ => (), @@ -302,10 +311,10 @@ fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &B } fn check_terminator<'tcx>( - tcx: TyCtxt<'tcx>, + cx: &LateContext<'tcx>, body: &Body<'tcx>, terminator: &Terminator<'tcx>, - msrv: &Msrv, + msrv: Msrv, ) -> McfResult { let span = terminator.source_info.span; match &terminator.kind { @@ -317,7 +326,7 @@ fn check_terminator<'tcx>( | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Unreachable => Ok(()), TerminatorKind::Drop { place, .. } => { - if !is_ty_const_destruct(tcx, place.ty(&body.local_decls, tcx).ty, body) { + if !is_ty_const_destruct(cx.tcx, place.ty(&body.local_decls, cx.tcx).ty, body) { return Err(( span, "cannot drop locals with a non constant destructor in const fn".into(), @@ -325,7 +334,7 @@ fn check_terminator<'tcx>( } Ok(()) }, - TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body, msrv), + TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(cx, discr, span, body, msrv), TerminatorKind::CoroutineDrop | TerminatorKind::Yield { .. } => { Err((span, "const fn coroutines are unstable".into())) }, @@ -339,9 +348,9 @@ fn check_terminator<'tcx>( fn_span: _, } | TerminatorKind::TailCall { func, args, fn_span: _ } => { - let fn_ty = func.ty(body, tcx); + let fn_ty = func.ty(body, cx.tcx); if let ty::FnDef(fn_def_id, _) = *fn_ty.kind() { - if !is_stable_const_fn(tcx, fn_def_id, msrv) { + if !is_stable_const_fn(cx, fn_def_id, msrv) { return Err(( span, format!( @@ -356,17 +365,17 @@ fn check_terminator<'tcx>( // within const fns. `transmute` is allowed in all other const contexts. // This won't really scale to more intrinsics or functions. Let's allow const // transmutes in const fn before we add more hacks to this. - if tcx.is_intrinsic(fn_def_id, sym::transmute) { + if cx.tcx.is_intrinsic(fn_def_id, sym::transmute) { return Err(( span, "can only call `transmute` from const items, not `const fn`".into(), )); } - check_operand(tcx, func, span, body, msrv)?; + check_operand(cx, func, span, body, msrv)?; for arg in args { - check_operand(tcx, &arg.node, span, body, msrv)?; + check_operand(cx, &arg.node, span, body, msrv)?; } Ok(()) } else { @@ -379,14 +388,14 @@ fn check_terminator<'tcx>( msg: _, target: _, unwind: _, - } => check_operand(tcx, cond, span, body, msrv), + } => check_operand(cx, cond, span, body, msrv), TerminatorKind::InlineAsm { .. } => Err((span, "cannot use inline assembly in const fn".into())), } } -fn is_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool { - tcx.is_const_fn(def_id) - && tcx.lookup_const_stability(def_id).is_none_or(|const_stab| { +fn is_stable_const_fn(cx: &LateContext<'_>, def_id: DefId, msrv: Msrv) -> bool { + cx.tcx.is_const_fn(def_id) + && cx.tcx.lookup_const_stability(def_id).is_none_or(|const_stab| { if let rustc_attr_parsing::StabilityLevel::Stable { since, .. } = const_stab.level { // Checking MSRV is manually necessary because `rustc` has no such concept. This entire // function could be removed if `rustc` provided a MSRV-aware version of `is_stable_const_fn`. @@ -398,10 +407,10 @@ fn is_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool { StableSince::Err => return false, }; - msrv.meets(const_stab_rust_version) + msrv.meets(cx, const_stab_rust_version) } else { // Unstable const fn, check if the feature is enabled. - tcx.features().enabled(const_stab.feature) && msrv.current().is_none() + cx.tcx.features().enabled(const_stab.feature) && msrv.current(cx).is_none() } }) } diff --git a/clippy_utils/src/source.rs b/clippy_utils/src/source.rs index c6a038f7e0cf..80066e9702d3 100644 --- a/clippy_utils/src/source.rs +++ b/clippy_utils/src/source.rs @@ -294,7 +294,7 @@ impl SourceFileRange { } } -/// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`. +/// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block` with no label. pub fn expr_block( sess: &impl HasSession, expr: &Expr<'_>, @@ -305,10 +305,10 @@ pub fn expr_block( ) -> String { let (code, from_macro) = snippet_block_with_context(sess, expr.span, outer, default, indent_relative_to, app); if !from_macro - && let ExprKind::Block(block, _) = expr.kind + && let ExprKind::Block(block, None) = expr.kind && block.rules != BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) { - format!("{code}") + code } else { // FIXME: add extra indent for the unsafe blocks: // original code: unsafe { ... } @@ -421,11 +421,10 @@ pub fn position_before_rarrow(s: &str) -> Option { } /// Reindent a multiline string with possibility of ignoring the first line. -#[expect(clippy::needless_pass_by_value)] -pub fn reindent_multiline(s: Cow<'_, str>, ignore_first: bool, indent: Option) -> Cow<'_, str> { - let s_space = reindent_multiline_inner(&s, ignore_first, indent, ' '); +pub fn reindent_multiline(s: &str, ignore_first: bool, indent: Option) -> String { + let s_space = reindent_multiline_inner(s, ignore_first, indent, ' '); let s_tab = reindent_multiline_inner(&s_space, ignore_first, indent, '\t'); - reindent_multiline_inner(&s_tab, ignore_first, indent, ' ').into() + reindent_multiline_inner(&s_tab, ignore_first, indent, ' ') } fn reindent_multiline_inner(s: &str, ignore_first: bool, indent: Option, ch: char) -> String { @@ -553,42 +552,37 @@ pub fn snippet_opt(sess: &impl HasSession, span: Span) -> Option { /// } // aligned with `if` /// ``` /// Note that the first line of the snippet always has 0 indentation. -pub fn snippet_block<'a>( - sess: &impl HasSession, - span: Span, - default: &'a str, - indent_relative_to: Option, -) -> Cow<'a, str> { +pub fn snippet_block(sess: &impl HasSession, span: Span, default: &str, indent_relative_to: Option) -> String { let snip = snippet(sess, span, default); let indent = indent_relative_to.and_then(|s| indent_of(sess, s)); - reindent_multiline(snip, true, indent) + reindent_multiline(&snip, true, indent) } /// Same as `snippet_block`, but adapts the applicability level by the rules of /// `snippet_with_applicability`. -pub fn snippet_block_with_applicability<'a>( +pub fn snippet_block_with_applicability( sess: &impl HasSession, span: Span, - default: &'a str, + default: &str, indent_relative_to: Option, applicability: &mut Applicability, -) -> Cow<'a, str> { +) -> String { let snip = snippet_with_applicability(sess, span, default, applicability); let indent = indent_relative_to.and_then(|s| indent_of(sess, s)); - reindent_multiline(snip, true, indent) + reindent_multiline(&snip, true, indent) } -pub fn snippet_block_with_context<'a>( +pub fn snippet_block_with_context( sess: &impl HasSession, span: Span, outer: SyntaxContext, - default: &'a str, + default: &str, indent_relative_to: Option, app: &mut Applicability, -) -> (Cow<'a, str>, bool) { +) -> (String, bool) { let (snip, from_macro) = snippet_with_context(sess, span, outer, default, app); let indent = indent_relative_to.and_then(|s| indent_of(sess, s)); - (reindent_multiline(snip, true, indent), from_macro) + (reindent_multiline(&snip, true, indent), from_macro) } /// Same as `snippet_with_applicability`, but first walks the span up to the given context. @@ -749,11 +743,11 @@ mod test { #[test] fn test_reindent_multiline_single_line() { - assert_eq!("", reindent_multiline("".into(), false, None)); - assert_eq!("...", reindent_multiline("...".into(), false, None)); - assert_eq!("...", reindent_multiline(" ...".into(), false, None)); - assert_eq!("...", reindent_multiline("\t...".into(), false, None)); - assert_eq!("...", reindent_multiline("\t\t...".into(), false, None)); + assert_eq!("", reindent_multiline("", false, None)); + assert_eq!("...", reindent_multiline("...", false, None)); + assert_eq!("...", reindent_multiline(" ...", false, None)); + assert_eq!("...", reindent_multiline("\t...", false, None)); + assert_eq!("...", reindent_multiline("\t\t...", false, None)); } #[test] @@ -768,7 +762,7 @@ mod test { y } else { z - }".into(), false, None)); + }", false, None)); assert_eq!("\ if x { \ty @@ -778,7 +772,7 @@ mod test { \ty } else { \tz - }".into(), false, None)); + }", false, None)); } #[test] @@ -795,7 +789,7 @@ mod test { } else { z - }".into(), false, None)); + }", false, None)); } #[test] @@ -811,6 +805,6 @@ mod test { y } else { z - }".into(), true, Some(8))); + }", true, Some(8))); } } diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index 8eef6a7f57ed..2611fb8a78d8 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -11,6 +11,7 @@ use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{Expr, FnDecl, LangItem, TyKind}; +use rustc_hir_analysis::lower_ty; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; use rustc_middle::mir::ConstValue; @@ -36,6 +37,19 @@ use crate::{def_path_def_ids, match_def_path, path_res}; mod type_certainty; pub use type_certainty::expr_type_is_certain; +/// Lower a [`hir::Ty`] to a [`rustc_middle::Ty`]. +pub fn ty_from_hir_ty<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { + cx.maybe_typeck_results() + .and_then(|results| { + if results.hir_owner == hir_ty.hir_id.owner { + results.node_type_opt(hir_ty.hir_id) + } else { + None + } + }) + .unwrap_or_else(|| lower_ty(cx.tcx, hir_ty)) +} + /// Checks if the given type implements copy. pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { cx.type_is_copy_modulo_regions(ty) @@ -351,20 +365,26 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { /// Checks if `Ty` is normalizable. This function is useful /// to avoid crashes on `layout_of`. pub fn is_normalizable<'tcx>(cx: &LateContext<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { - is_normalizable_helper(cx, param_env, ty, &mut FxHashMap::default()) + is_normalizable_helper(cx, param_env, ty, 0, &mut FxHashMap::default()) } fn is_normalizable_helper<'tcx>( cx: &LateContext<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>, + depth: usize, cache: &mut FxHashMap, bool>, ) -> bool { if let Some(&cached_result) = cache.get(&ty) { return cached_result; } - // prevent recursive loops, false-negative is better than endless loop leading to stack overflow - cache.insert(ty, false); + if !cx.tcx.recursion_limit().value_within_limit(depth) { + return false; + } + // Prevent recursive loops by answering `true` to recursive requests with the same + // type. This will be adjusted when the outermost call analyzes all the type + // components. + cache.insert(ty, true); let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode()); let cause = ObligationCause::dummy(); let result = if infcx.at(&cause, param_env).query_normalize(ty).is_ok() { @@ -373,11 +393,11 @@ fn is_normalizable_helper<'tcx>( variant .fields .iter() - .all(|field| is_normalizable_helper(cx, param_env, field.ty(cx.tcx, args), cache)) + .all(|field| is_normalizable_helper(cx, param_env, field.ty(cx.tcx, args), depth + 1, cache)) }), _ => ty.walk().all(|generic_arg| match generic_arg.unpack() { GenericArgKind::Type(inner_ty) if inner_ty != ty => { - is_normalizable_helper(cx, param_env, inner_ty, cache) + is_normalizable_helper(cx, param_env, inner_ty, depth + 1, cache) }, _ => true, // if inner_ty == ty, we've already checked it }), @@ -1227,6 +1247,10 @@ impl<'tcx> InteriorMut<'tcx> { .find_map(|f| self.interior_mut_ty_chain(cx, f.ty(cx.tcx, args))) } }, + ty::Alias(ty::Projection, _) => match cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty) { + Ok(normalized_ty) if ty != normalized_ty => self.interior_mut_ty_chain(cx, normalized_ty), + _ => None, + }, _ => None, }; diff --git a/lintcheck/src/input.rs b/lintcheck/src/input.rs index 3383d50fa02c..83eb0a577d6b 100644 --- a/lintcheck/src/input.rs +++ b/lintcheck/src/input.rs @@ -288,11 +288,11 @@ impl CrateWithSource { // as a result of this filter. let dest_crate_root = PathBuf::from(LINTCHECK_SOURCES).join(name); if dest_crate_root.exists() { - println!("Deleting existing directory at {dest_crate_root:?}"); + println!("Deleting existing directory at `{}`", dest_crate_root.display()); fs::remove_dir_all(&dest_crate_root).unwrap(); } - println!("Copying {path:?} to {dest_crate_root:?}"); + println!("Copying `{}` to `{}`", path.display(), dest_crate_root.display()); for entry in WalkDir::new(path).into_iter().filter_entry(|e| !is_cache_dir(e)) { let entry = entry.unwrap(); diff --git a/rust-toolchain b/rust-toolchain index ab760287e83a..a4931499c802 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,6 +1,6 @@ [toolchain] # begin autogenerated nightly -channel = "nightly-2025-02-06" +channel = "nightly-2025-02-27" # end autogenerated nightly components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] profile = "minimal" diff --git a/rustc_tools_util/Cargo.toml b/rustc_tools_util/Cargo.toml index cba025639482..716b1ed61443 100644 --- a/rustc_tools_util/Cargo.toml +++ b/rustc_tools_util/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "rustc_tools_util" -version = "0.4.0" +version = "0.4.2" description = "small helper to generate version information for git packages" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" license = "MIT OR Apache-2.0" keywords = ["rustc", "tool", "git", "version", "hash"] categories = ["development-tools"] -edition = "2024" +edition = "2021" # Keep this, for this crate's MSRV to stay low [dependencies] diff --git a/rustc_tools_util/README.md b/rustc_tools_util/README.md index 1b11dfe06191..ff4ca6f830e6 100644 --- a/rustc_tools_util/README.md +++ b/rustc_tools_util/README.md @@ -13,10 +13,10 @@ build = "build.rs" List rustc_tools_util as regular AND build dependency. ````toml [dependencies] -rustc_tools_util = "0.4.0" +rustc_tools_util = "0.4.2" [build-dependencies] -rustc_tools_util = "0.4.0" +rustc_tools_util = "0.4.2" ```` In `build.rs`, generate the data in your `main()` diff --git a/rustc_tools_util/src/lib.rs b/rustc_tools_util/src/lib.rs index 16be02f4a40f..423154a69fa0 100644 --- a/rustc_tools_util/src/lib.rs +++ b/rustc_tools_util/src/lib.rs @@ -28,9 +28,8 @@ macro_rules! get_version_info { }}; } -/// This macro can be used in `build.rs` to automatically set the needed -/// environment values, namely `GIT_HASH`, `COMMIT_DATE` and -/// `RUSTC_RELEASE_CHANNEL` +/// This macro can be used in `build.rs` to automatically set the needed environment values, namely +/// `GIT_HASH`, `COMMIT_DATE` and `RUSTC_RELEASE_CHANNEL` #[macro_export] macro_rules! setup_version_info { () => {{ @@ -43,7 +42,11 @@ macro_rules! setup_version_info { "cargo:rustc-env=COMMIT_DATE={}", $crate::get_commit_date().unwrap_or_default() ); - println!("cargo:rustc-env=RUSTC_RELEASE_CHANNEL={}", $crate::get_channel()); + let compiler_version = $crate::get_compiler_version(); + println!( + "cargo:rustc-env=RUSTC_RELEASE_CHANNEL={}", + $crate::get_channel(compiler_version) + ); }}; } @@ -87,16 +90,17 @@ impl std::fmt::Debug for VersionInfo { "VersionInfo {{ crate_name: \"{}\", major: {}, minor: {}, patch: {}", self.crate_name, self.major, self.minor, self.patch, )?; - if self.commit_hash.is_some() { - write!( - f, - ", commit_hash: \"{}\", commit_date: \"{}\" }}", - self.commit_hash.clone().unwrap_or_default().trim(), - self.commit_date.clone().unwrap_or_default().trim() - )?; - } else { - write!(f, " }}")?; + if let Some(ref commit_hash) = self.commit_hash { + write!(f, ", commit_hash: \"{}\"", commit_hash.trim(),)?; } + if let Some(ref commit_date) = self.commit_date { + write!(f, ", commit_date: \"{}\"", commit_date.trim())?; + } + if let Some(ref host_compiler) = self.host_compiler { + write!(f, ", host_compiler: \"{}\"", host_compiler.trim())?; + } + + write!(f, " }}")?; Ok(()) } @@ -152,22 +156,27 @@ pub fn get_commit_date() -> Option { } #[must_use] -pub fn get_channel() -> String { +pub fn get_compiler_version() -> Option { + get_output("rustc", &["-V"]) +} + +#[must_use] +pub fn get_channel(compiler_version: Option) -> String { if let Ok(channel) = std::env::var("CFG_RELEASE_CHANNEL") { return channel; } // if that failed, try to ask rustc -V, do some parsing and find out - if let Some(rustc_output) = get_output("rustc", &["-V"]) { + if let Some(rustc_output) = compiler_version { if rustc_output.contains("beta") { return String::from("beta"); - } else if rustc_output.contains("stable") { - return String::from("stable"); + } else if rustc_output.contains("nightly") { + return String::from("nightly"); } } - // default to nightly - String::from("nightly") + // default to stable + String::from("stable") } #[cfg(test)] @@ -179,17 +188,19 @@ mod test { let vi = get_version_info!(); assert_eq!(vi.major, 0); assert_eq!(vi.minor, 4); - assert_eq!(vi.patch, 0); + assert_eq!(vi.patch, 2); assert_eq!(vi.crate_name, "rustc_tools_util"); // hard to make positive tests for these since they will always change assert!(vi.commit_hash.is_none()); assert!(vi.commit_date.is_none()); + + assert!(vi.host_compiler.is_none()); } #[test] fn test_display_local() { let vi = get_version_info!(); - assert_eq!(vi.to_string(), "rustc_tools_util 0.4.0"); + assert_eq!(vi.to_string(), "rustc_tools_util 0.4.2"); } #[test] @@ -198,7 +209,7 @@ mod test { let s = format!("{vi:?}"); assert_eq!( s, - "VersionInfo { crate_name: \"rustc_tools_util\", major: 0, minor: 4, patch: 0 }" + "VersionInfo { crate_name: \"rustc_tools_util\", major: 0, minor: 4, patch: 2 }" ); } } diff --git a/tests/compile-test.rs b/tests/compile-test.rs index d1b1a1d23232..f44cf7a7c25a 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -139,7 +139,7 @@ impl TestContext { } } - fn base_config(&self, test_dir: &str) -> Config { + fn base_config(&self, test_dir: &str, mandatory_annotations: bool) -> Config { let target_dir = PathBuf::from(var_os("CARGO_TARGET_DIR").unwrap_or_else(|| "target".into())); let mut config = Config { output_conflict_handling: OutputConflictHandling::Error, @@ -153,7 +153,11 @@ impl TestContext { }; let defaults = config.comment_defaults.base(); defaults.exit_status = None.into(); - defaults.require_annotations = None.into(); + if mandatory_annotations { + defaults.require_annotations = Some(Spanned::dummy(true)).into(); + } else { + defaults.require_annotations = None.into(); + } defaults.diagnostic_code_prefix = Some(Spanned::dummy("clippy::".into())).into(); defaults.set_custom("rustfix", RustfixMode::Everything); if let Some(collector) = self.diagnostic_collector.clone() { @@ -197,7 +201,7 @@ impl TestContext { } fn run_ui(cx: &TestContext) { - let mut config = cx.base_config("ui"); + let mut config = cx.base_config("ui", true); config .program .envs @@ -216,7 +220,7 @@ fn run_internal_tests(cx: &TestContext) { if !RUN_INTERNAL_TESTS { return; } - let mut config = cx.base_config("ui-internal"); + let mut config = cx.base_config("ui-internal", false); config.bless_command = Some("cargo uitest --features internal -- -- --bless".into()); ui_test::run_tests_generic( @@ -229,7 +233,7 @@ fn run_internal_tests(cx: &TestContext) { } fn run_ui_toml(cx: &TestContext) { - let mut config = cx.base_config("ui-toml"); + let mut config = cx.base_config("ui-toml", true); config .comment_defaults @@ -259,7 +263,7 @@ fn run_ui_cargo(cx: &TestContext) { return; } - let mut config = cx.base_config("ui-cargo"); + let mut config = cx.base_config("ui-cargo", false); config.program.input_file_flag = CommandBuilder::cargo().input_file_flag; config.program.out_dir_flag = CommandBuilder::cargo().out_dir_flag; config.program.args = vec!["clippy".into(), "--color".into(), "never".into(), "--quiet".into()]; @@ -379,13 +383,15 @@ fn ui_cargo_toml_metadata() { .map(|component| component.as_os_str().to_string_lossy().replace('-', "_")) .any(|s| *s == name) || path.starts_with(&cargo_common_metadata_path), - "{path:?} has incorrect package name" + "`{}` has incorrect package name", + path.display(), ); let publish = package.get("publish").and_then(toml::Value::as_bool).unwrap_or(true); assert!( !publish || publish_exceptions.contains(&path.parent().unwrap().to_path_buf()), - "{path:?} lacks `publish = false`" + "`{}` lacks `publish = false`", + path.display(), ); } } diff --git a/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr b/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr index 4fe7f6f7a9ed..059427d8ee0f 100644 --- a/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr +++ b/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr @@ -11,8 +11,9 @@ error: lint group `rust_2018_idioms` has the same priority (0) as a lint = note: `#[deny(clippy::lint_groups_priority)]` on by default help: to have lints override the group set `rust_2018_idioms` to a lower priority | -7 | rust_2018_idioms = { level = "warn", priority = -1 } - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +7 - rust_2018_idioms = "warn" +7 + rust_2018_idioms = { level = "warn", priority = -1 } + | error: lint group `unused` has the same priority (0) as a lint --> Cargo.toml:10:1 @@ -27,7 +28,7 @@ error: lint group `unused` has the same priority (0) as a lint help: to have lints override the group set `unused` to a lower priority | 10 | unused = { level = "deny", priority = -1 } - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | +++++++++++++++ error: lint group `pedantic` has the same priority (-1) as a lint --> Cargo.toml:15:1 @@ -40,8 +41,9 @@ error: lint group `pedantic` has the same priority (-1) as a lint = note: the order of the lints in the table is ignored by Cargo help: to have lints override the group set `pedantic` to a lower priority | -15 | pedantic = { level = "warn", priority = -2 } - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +15 - pedantic = { level = "warn", priority = -1 } +15 + pedantic = { level = "warn", priority = -2 } + | error: lint group `rust_2018_idioms` has the same priority (0) as a lint --> Cargo.toml:19:1 @@ -54,8 +56,9 @@ error: lint group `rust_2018_idioms` has the same priority (0) as a lint = note: the order of the lints in the table is ignored by Cargo help: to have lints override the group set `rust_2018_idioms` to a lower priority | -19 | rust_2018_idioms = { level = "warn", priority = -1 } - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +19 - rust_2018_idioms = "warn" +19 + rust_2018_idioms = { level = "warn", priority = -1 } + | error: lint group `pedantic` has the same priority (0) as a lint --> Cargo.toml:23:1 @@ -68,7 +71,8 @@ error: lint group `pedantic` has the same priority (0) as a lint = note: the order of the lints in the table is ignored by Cargo help: to have lints override the group set `pedantic` to a lower priority | -23 | pedantic = { level = "warn", priority = -1 } - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +23 - pedantic = "warn" +23 + pedantic = { level = "warn", priority = -1 } + | error: could not compile `fail` (lib) due to 5 previous errors diff --git a/tests/ui-internal/custom_ice_message.stderr b/tests/ui-internal/custom_ice_message.stderr index ae5d8ef1d0b5..801b0f340de9 100644 --- a/tests/ui-internal/custom_ice_message.stderr +++ b/tests/ui-internal/custom_ice_message.stderr @@ -14,7 +14,7 @@ note: rustc running on note: compiler flags: -Z ui-testing -Z deduplicate-diagnostics=no query stack during panic: -#0 [early_lint_checks] perform lints prior to macro expansion +#0 [early_lint_checks] perform lints prior to AST lowering #1 [hir_crate] getting the crate HIR ... and 3 other queries... use `env RUST_BACKTRACE=1` to see the full query stack note: Clippy version: foo diff --git a/tests/ui-internal/invalid_msrv_attr_impl.fixed b/tests/ui-internal/invalid_msrv_attr_impl.fixed index 928596d08091..7011ef518f20 100644 --- a/tests/ui-internal/invalid_msrv_attr_impl.fixed +++ b/tests/ui-internal/invalid_msrv_attr_impl.fixed @@ -9,7 +9,7 @@ extern crate rustc_middle; #[macro_use] extern crate rustc_session; use clippy_utils::extract_msrv_attr; -use clippy_utils::msrvs::Msrv; +use clippy_utils::msrvs::MsrvStack; use rustc_hir::Expr; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; @@ -20,18 +20,13 @@ declare_lint! { } struct Pass { - msrv: Msrv, + msrv: MsrvStack, } impl_lint_pass!(Pass => [TEST_LINT]); -impl LateLintPass<'_> for Pass { - extract_msrv_attr!(LateContext); - fn check_expr(&mut self, _: &LateContext<'_>, _: &Expr<'_>) {} -} - impl EarlyLintPass for Pass { - extract_msrv_attr!(EarlyContext); + extract_msrv_attr!(); fn check_expr(&mut self, _: &EarlyContext<'_>, _: &rustc_ast::Expr) {} } diff --git a/tests/ui-internal/invalid_msrv_attr_impl.rs b/tests/ui-internal/invalid_msrv_attr_impl.rs index 50b28648ccc9..323061decd23 100644 --- a/tests/ui-internal/invalid_msrv_attr_impl.rs +++ b/tests/ui-internal/invalid_msrv_attr_impl.rs @@ -9,7 +9,7 @@ extern crate rustc_middle; #[macro_use] extern crate rustc_session; use clippy_utils::extract_msrv_attr; -use clippy_utils::msrvs::Msrv; +use clippy_utils::msrvs::MsrvStack; use rustc_hir::Expr; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; @@ -20,15 +20,11 @@ declare_lint! { } struct Pass { - msrv: Msrv, + msrv: MsrvStack, } impl_lint_pass!(Pass => [TEST_LINT]); -impl LateLintPass<'_> for Pass { - fn check_expr(&mut self, _: &LateContext<'_>, _: &Expr<'_>) {} -} - impl EarlyLintPass for Pass { fn check_expr(&mut self, _: &EarlyContext<'_>, _: &rustc_ast::Expr) {} } diff --git a/tests/ui-internal/invalid_msrv_attr_impl.stderr b/tests/ui-internal/invalid_msrv_attr_impl.stderr index aa649c627a16..0a7636313eff 100644 --- a/tests/ui-internal/invalid_msrv_attr_impl.stderr +++ b/tests/ui-internal/invalid_msrv_attr_impl.stderr @@ -1,8 +1,8 @@ -error: `extract_msrv_attr!` macro missing from `LateLintPass` implementation +error: `extract_msrv_attr!` macro missing from `EarlyLintPass` implementation --> tests/ui-internal/invalid_msrv_attr_impl.rs:28:1 | -LL | impl LateLintPass<'_> for Pass { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl EarlyLintPass for Pass { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> tests/ui-internal/invalid_msrv_attr_impl.rs:1:9 @@ -10,23 +10,11 @@ note: the lint level is defined here LL | #![deny(clippy::internal)] | ^^^^^^^^^^^^^^^^ = note: `#[deny(clippy::missing_msrv_attr_impl)]` implied by `#[deny(clippy::internal)]` -help: add `extract_msrv_attr!(LateContext)` to the `LateLintPass` implementation +help: add `extract_msrv_attr!()` to the `EarlyLintPass` implementation | -LL + impl LateLintPass<'_> for Pass { -LL + extract_msrv_attr!(LateContext); +LL ~ impl EarlyLintPass for Pass { +LL + extract_msrv_attr!(); | -error: `extract_msrv_attr!` macro missing from `EarlyLintPass` implementation - --> tests/ui-internal/invalid_msrv_attr_impl.rs:32:1 - | -LL | impl EarlyLintPass for Pass { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: add `extract_msrv_attr!(EarlyContext)` to the `EarlyLintPass` implementation - | -LL + impl EarlyLintPass for Pass { -LL + extract_msrv_attr!(EarlyContext); - | - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui-toml/absolute_paths/absolute_paths_2015.default.stderr b/tests/ui-toml/absolute_paths/absolute_paths_2015.default.stderr index 6fc495f01808..b946514454aa 100644 --- a/tests/ui-toml/absolute_paths/absolute_paths_2015.default.stderr +++ b/tests/ui-toml/absolute_paths/absolute_paths_2015.default.stderr @@ -1,11 +1,11 @@ error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths_2015.rs:15:13 + --> tests/ui-toml/absolute_paths/absolute_paths_2015.rs:16:13 | LL | let _ = ::m1::m2::X; | ^^^^^^^^^^^ | note: the lint level is defined here - --> tests/ui-toml/absolute_paths/absolute_paths_2015.rs:6:9 + --> tests/ui-toml/absolute_paths/absolute_paths_2015.rs:7:9 | LL | #![deny(clippy::absolute_paths)] | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/absolute_paths/absolute_paths_2015.rs b/tests/ui-toml/absolute_paths/absolute_paths_2015.rs index 033c47809191..86981f979556 100644 --- a/tests/ui-toml/absolute_paths/absolute_paths_2015.rs +++ b/tests/ui-toml/absolute_paths/absolute_paths_2015.rs @@ -1,6 +1,7 @@ //@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 +//@[allow_crates]check-pass //@edition:2015 #![deny(clippy::absolute_paths)] diff --git a/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.fixed b/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.fixed index c04543da94b9..e12a94a4b205 100644 --- a/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.fixed +++ b/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.fixed @@ -7,8 +7,14 @@ fn main() { let local_opt: Option = Some(3); println!("val='{local_i32}'"); + //~^ uninlined_format_args println!("Hello x is {local_f64:.local_i32$}"); + //~^ uninlined_format_args + //~| print_literal println!("Hello {local_i32} is {local_f64:.*}", 5); + //~^ uninlined_format_args println!("Hello {local_i32} is {local_f64:.*}", 5); + //~^ uninlined_format_args println!("{local_i32}, {}", local_opt.unwrap()); + //~^ uninlined_format_args } diff --git a/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs b/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs index 813830d80b83..ad5aec133e91 100644 --- a/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs +++ b/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs @@ -7,8 +7,14 @@ fn main() { let local_opt: Option = Some(3); println!("val='{}'", local_i32); + //~^ uninlined_format_args println!("Hello {} is {:.*}", "x", local_i32, local_f64); + //~^ uninlined_format_args + //~| print_literal println!("Hello {} is {:.*}", local_i32, 5, local_f64); + //~^ uninlined_format_args println!("Hello {} is {2:.*}", local_i32, 5, local_f64); + //~^ uninlined_format_args println!("{}, {}", local_i32, local_opt.unwrap()); + //~^ uninlined_format_args } diff --git a/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr b/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr index 73ef620bd12e..3ffe61b8ed72 100644 --- a/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr +++ b/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr @@ -13,7 +13,7 @@ LL + println!("val='{local_i32}'"); | error: variables can be used directly in the `format!` string - --> tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs:10:5 + --> tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs:11:5 | LL | println!("Hello {} is {:.*}", "x", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + println!("Hello {} is {local_f64:.local_i32$}", "x"); | error: literal with an empty format string - --> tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs:10:35 + --> tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs:11:35 | LL | println!("Hello {} is {:.*}", "x", local_i32, local_f64); | ^^^ @@ -39,7 +39,7 @@ LL + println!("Hello x is {:.*}", local_i32, local_f64); | error: variables can be used directly in the `format!` string - --> tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs:11:5 + --> tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs:14:5 | LL | println!("Hello {} is {:.*}", local_i32, 5, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -51,7 +51,7 @@ LL + println!("Hello {local_i32} is {local_f64:.*}", 5); | error: variables can be used directly in the `format!` string - --> tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs:12:5 + --> tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs:16:5 | LL | println!("Hello {} is {2:.*}", local_i32, 5, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -63,7 +63,7 @@ LL + println!("Hello {local_i32} is {local_f64:.*}", 5); | error: variables can be used directly in the `format!` string - --> tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs:13:5 + --> tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs:18:5 | LL | println!("{}, {}", local_i32, local_opt.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs index e9bcc30c15e0..05eb40506db4 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs @@ -5,6 +5,11 @@ //@[bad_conf_1] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_1 //@[bad_conf_2] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_2 //@[bad_conf_3] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_3 +//@[default] check-pass +//@[default_exp] check-pass +//@[bad_conf_1] error-in-other-file: +//@[bad_conf_2] error-in-other-file: +//@[bad_conf_3] error-in-other-file: #![allow(dead_code)] #![warn(clippy::arbitrary_source_item_ordering)] diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_good_var_1.rs b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good_var_1.rs index 0fccbd4790bc..fb2d2e64bcea 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_good_var_1.rs +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good_var_1.rs @@ -1,6 +1,7 @@ //@aux-build:../../ui/auxiliary/proc_macros.rs //@revisions: var_1 //@[var_1] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/var_1 +//@check-pass #![allow(dead_code)] #![warn(clippy::arbitrary_source_item_ordering)] diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr index ee2868869deb..3605952bddc9 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr @@ -1,11 +1,11 @@ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:21:14 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:22:14 | LL | use std::rc::Weak; | ^^^^ | note: should be placed before `SNAKE_CASE` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:19:7 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:20:7 | LL | const SNAKE_CASE: &str = "zzzzzzzz"; | ^^^^^^^^^^ @@ -13,18 +13,18 @@ LL | const SNAKE_CASE: &str = "zzzzzzzz"; = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]` error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:64:1 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:67:1 | LL | / impl CloneSelf for StructOrdered { +LL | | LL | | fn clone_self(&self) -> Self { LL | | Self { -LL | | a: true, ... | LL | | } | |_^ | note: should be placed before the following item - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:54:1 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:57:1 | LL | / impl Default for StructOrdered { LL | | fn default() -> Self { @@ -35,55 +35,54 @@ LL | | } | |_^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:136:7 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:145:7 | LL | const ZIS_SHOULD_BE_REALLY_EARLY: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before `TraitUnorderedItemKinds` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:124:7 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:132:7 | LL | trait TraitUnorderedItemKinds { | ^^^^^^^^^^^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:151:1 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:163:1 | LL | impl BasicEmptyTrait for StructOrdered {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before the following item - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:138:1 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:148:1 | LL | / impl TraitUnordered for StructUnordered { LL | | const A: bool = false; LL | | const C: bool = false; LL | | const B: bool = false; ... | -LL | | fn b() {} LL | | } | |_^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:170:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:184:5 | LL | mod this_is_in_the_wrong_position { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before `main` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:165:4 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:179:4 | LL | fn main() { | ^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:178:7 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:194:7 | LL | const ZIS_SHOULD_BE_EVEN_EARLIER: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before `ZisShouldBeBeforeZeMainFn` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:176:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:192:8 | LL | struct ZisShouldBeBeforeZeMainFn; | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -101,121 +100,121 @@ LL | const BEFORE: i8 = 0; | ^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:38:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:40:5 | LL | B, | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:37:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:39:5 | LL | C, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:88:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:92:5 | LL | b: bool, | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:87:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:91:5 | LL | c: bool, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:96:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:101:5 | LL | b: bool, | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:95:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:100:5 | LL | c: bool, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:115:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:121:11 | LL | const B: bool; | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:114:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:120:11 | LL | const C: bool; | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:121:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:128:8 | LL | fn b(); | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:120:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:127:8 | LL | fn c(); | ^ error: incorrect ordering of trait items (defined order: [Const, Type, Fn]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:127:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:135:5 | LL | const A: bool; | ^^^^^^^^^^^^^^ | note: should be placed before `SomeType` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:125:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:133:5 | LL | type SomeType; | ^^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:141:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:151:11 | LL | const B: bool = false; | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:140:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:150:11 | LL | const C: bool = false; | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:147:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:158:8 | LL | fn b() {} | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:146:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:157:8 | LL | fn c() {} | ^ error: incorrect ordering of impl items (defined order: [Const, Type, Fn]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:156:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:169:5 | LL | const A: bool = false; | ^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before `SomeType` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:154:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:167:5 | LL | type SomeType = (); | ^^^^^^^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:172:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:187:11 | LL | const A: i8 = 1; | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:171:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:186:11 | LL | const C: i8 = 0; | ^ diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs index 2765bf935b7c..9e65a9cca0da 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs @@ -10,6 +10,7 @@ mod i_am_just_right { const BEFORE: i8 = 0; const AFTER: i8 = 0; + //~^ arbitrary_source_item_ordering } // Use statements should not be linted internally - this is normally auto-sorted using rustfmt. @@ -19,6 +20,7 @@ use std::sync::{Arc, Barrier, RwLock}; const SNAKE_CASE: &str = "zzzzzzzz"; use std::rc::Weak; +//~^ arbitrary_source_item_ordering trait BasicEmptyTrait {} @@ -36,6 +38,7 @@ enum EnumUnordered { A, C, B, + //~^ arbitrary_source_item_ordering } #[allow(clippy::arbitrary_source_item_ordering)] @@ -62,6 +65,7 @@ impl Default for StructOrdered { } impl CloneSelf for StructOrdered { + //~^ arbitrary_source_item_ordering fn clone_self(&self) -> Self { Self { a: true, @@ -86,6 +90,7 @@ struct StructUnordered { a: bool, c: bool, b: bool, + //~^ arbitrary_source_item_ordering d: bool, } @@ -94,6 +99,7 @@ struct StructUnorderedGeneric { a: bool, c: bool, b: bool, + //~^ arbitrary_source_item_ordering d: bool, } @@ -113,18 +119,21 @@ trait TraitUnordered { const A: bool; const C: bool; const B: bool; + //~^ arbitrary_source_item_ordering type SomeType; fn a(); fn c(); fn b(); + //~^ arbitrary_source_item_ordering } trait TraitUnorderedItemKinds { type SomeType; const A: bool; + //~^ arbitrary_source_item_ordering const B: bool; const C: bool; @@ -134,26 +143,31 @@ trait TraitUnorderedItemKinds { } const ZIS_SHOULD_BE_REALLY_EARLY: () = (); +//~^ arbitrary_source_item_ordering impl TraitUnordered for StructUnordered { const A: bool = false; const C: bool = false; const B: bool = false; + //~^ arbitrary_source_item_ordering type SomeType = (); fn a() {} fn c() {} fn b() {} + //~^ arbitrary_source_item_ordering } // Trait impls should be located just after the type they implement it for. impl BasicEmptyTrait for StructOrdered {} +//~^ arbitrary_source_item_ordering impl TraitUnorderedItemKinds for StructUnordered { type SomeType = (); const A: bool = false; + //~^ arbitrary_source_item_ordering const B: bool = false; const C: bool = false; @@ -168,14 +182,17 @@ fn main() { /// Note that the linting pass is stopped before recursing into this module. mod this_is_in_the_wrong_position { + //~^ arbitrary_source_item_ordering const C: i8 = 0; const A: i8 = 1; + //~^ arbitrary_source_item_ordering } #[derive(Default, std::clone::Clone)] struct ZisShouldBeBeforeZeMainFn; const ZIS_SHOULD_BE_EVEN_EARLIER: () = (); +//~^ arbitrary_source_item_ordering #[cfg(test)] mod test { diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs index 44902336573c..96b2fb16f8f5 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs @@ -103,20 +103,24 @@ impl TraitUnordered for StructUnordered { fn a() {} fn c() {} fn b() {} + //~^ arbitrary_source_item_ordering type SomeType = (); const A: bool = false; const C: bool = false; const B: bool = false; + //~^ arbitrary_source_item_ordering } impl TraitUnorderedItemKinds for StructUnordered { const A: bool = false; type SomeType = (); + //~^ arbitrary_source_item_ordering fn a() {} + //~^ arbitrary_source_item_ordering } struct StructUnorderedGeneric { @@ -143,20 +147,24 @@ trait TraitUnordered { fn a(); fn c(); fn b(); + //~^ arbitrary_source_item_ordering type SomeType; const A: bool; const C: bool; const B: bool; + //~^ arbitrary_source_item_ordering } trait TraitUnorderedItemKinds { const A: bool; type SomeType; + //~^ arbitrary_source_item_ordering fn a(); + //~^ arbitrary_source_item_ordering } #[derive(std::clone::Clone, Default)] diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.var_1.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.var_1.stderr index f31f7f68c17e..730f12c38a0d 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.var_1.stderr +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.var_1.stderr @@ -13,85 +13,85 @@ LL | fn c() {} = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]` error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:111:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:112:11 | LL | const B: bool = false; | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:110:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:111:11 | LL | const C: bool = false; | ^ error: incorrect ordering of impl items (defined order: [Fn, Type, Const]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:117:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:119:5 | LL | type SomeType = (); | ^^^^^^^^^^^^^^^^^^^ | note: should be placed before `A` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:115:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:117:5 | LL | const A: bool = false; | ^^^^^^^^^^^^^^^^^^^^^^ error: incorrect ordering of impl items (defined order: [Fn, Type, Const]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:119:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:122:5 | LL | fn a() {} | ^^^^^^^^^ | note: should be placed before `SomeType` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:117:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:119:5 | LL | type SomeType = (); | ^^^^^^^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:145:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:149:8 | LL | fn b(); | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:144:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:148:8 | LL | fn c(); | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:151:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:156:11 | LL | const B: bool; | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:150:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:155:11 | LL | const C: bool; | ^ error: incorrect ordering of trait items (defined order: [Fn, Type, Const]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:157:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:163:5 | LL | type SomeType; | ^^^^^^^^^^^^^^ | note: should be placed before `A` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:155:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:161:5 | LL | const A: bool; | ^^^^^^^^^^^^^^ error: incorrect ordering of trait items (defined order: [Fn, Type, Const]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:159:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:166:5 | LL | fn a(); | ^^^^^^^ | note: should be placed before `SomeType` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:157:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:163:5 | LL | type SomeType; | ^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs index e8002c4a1633..4e8ed5e550a3 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs @@ -20,6 +20,7 @@ enum EnumOrdered { enum EnumUnordered { B, A, + //~^ arbitrary_source_item_ordering } trait TraitUnordered { diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.only_impl.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.only_impl.stderr index 40348ecbdae1..77596ba23946 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.only_impl.stderr +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.only_impl.stderr @@ -13,7 +13,7 @@ LL | fn b() {} = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]` error: incorrect ordering of impl items (defined order: [Const, Type, Fn]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:45:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:46:5 | LL | type SomeType = i8; | ^^^^^^^^^^^^^^^^^^^ @@ -25,13 +25,13 @@ LL | fn a() {} | ^^^^^^^^^ error: incorrect ordering of impl items (defined order: [Const, Type, Fn]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:47:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:49:5 | LL | const A: bool = true; | ^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before `SomeType` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:45:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:46:5 | LL | type SomeType = i8; | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs index bd969c865b5a..56e2e188be6a 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs @@ -41,10 +41,13 @@ trait TraitUnordered { impl BasicTrait for StructUnordered { fn b() {} fn a() {} + //~^ arbitrary_source_item_ordering type SomeType = i8; + //~^ arbitrary_source_item_ordering const A: bool = true; + //~^ arbitrary_source_item_ordering } trait TraitUnorderedItemKinds { diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.only_trait.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.only_trait.stderr index 9b86ebd48e3d..3d903330be8f 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.only_trait.stderr +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.only_trait.stderr @@ -13,25 +13,25 @@ LL | const B: bool; = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]` error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:37:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:38:8 | LL | fn a(); | ^ | note: should be placed before `b` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:36:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:37:8 | LL | fn b(); | ^ error: incorrect ordering of trait items (defined order: [Const, Type, Fn]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:43:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:45:5 | LL | const A: bool; | ^^^^^^^^^^^^^^ | note: should be placed before `SomeType` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:41:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:43:5 | LL | type SomeType; | ^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs index 979a52ecb100..d885a20ca50a 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs @@ -30,17 +30,20 @@ enum EnumUnordered { trait TraitUnordered { const B: bool; const A: bool; + //~^ arbitrary_source_item_ordering type SomeType; fn b(); fn a(); + //~^ arbitrary_source_item_ordering } trait TraitUnorderedItemKinds { type SomeType; const A: bool; + //~^ arbitrary_source_item_ordering fn a(); } diff --git a/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs b/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs index 33f7c8ba8042..01a84a526c09 100644 --- a/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs +++ b/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs @@ -67,6 +67,7 @@ fn lhs_and_rhs_are_equal() { let _ = Bar + Bar; // not on the list let _ = Baz + Baz; + //~^ arithmetic_side_effects } fn lhs_is_different() { @@ -78,13 +79,16 @@ fn lhs_is_different() { let _ = 1i32 + Bar; // not on the list let _ = 1i32 + Baz; + //~^ arithmetic_side_effects // not on the list let _ = 1i64 + Foo; + //~^ arithmetic_side_effects // is implicitly on the list let _ = 1i64 + Bar; // not on the list let _ = 1i64 + Baz; + //~^ arithmetic_side_effects } fn rhs_is_different() { @@ -96,13 +100,16 @@ fn rhs_is_different() { let _ = Bar + 1i32; // not on the list let _ = Baz + 1i32; + //~^ arithmetic_side_effects // not on the list let _ = Foo + 1i64; + //~^ arithmetic_side_effects // is implicitly on the list let _ = Bar + 1i64; // not on the list let _ = Baz + 1i64; + //~^ arithmetic_side_effects } fn unary() { @@ -112,8 +119,10 @@ fn unary() { let _ = -Foo; // not on the list let _ = -Bar; + //~^ arithmetic_side_effects // not on the list let _ = -Baz; + //~^ arithmetic_side_effects } fn main() {} diff --git a/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr b/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr index 3c5216023b54..93efcc01c88f 100644 --- a/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr +++ b/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr @@ -8,49 +8,49 @@ LL | let _ = Baz + Baz; = help: to override `-D warnings` add `#[allow(clippy::arithmetic_side_effects)]` error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs:80:13 + --> tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs:81:13 | LL | let _ = 1i32 + Baz; | ^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs:83:13 + --> tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs:85:13 | LL | let _ = 1i64 + Foo; | ^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs:87:13 + --> tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs:90:13 | LL | let _ = 1i64 + Baz; | ^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs:98:13 + --> tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs:102:13 | LL | let _ = Baz + 1i32; | ^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs:101:13 + --> tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs:106:13 | LL | let _ = Foo + 1i64; | ^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs:105:13 + --> tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs:111:13 | LL | let _ = Baz + 1i64; | ^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs:114:13 + --> tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs:121:13 | LL | let _ = -Bar; | ^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs:116:13 + --> tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs:124:13 | LL | let _ = -Baz; | ^^^^ diff --git a/tests/ui-toml/array_size_threshold/array_size_threshold.rs b/tests/ui-toml/array_size_threshold/array_size_threshold.rs index d36159e12639..b8652137378e 100644 --- a/tests/ui-toml/array_size_threshold/array_size_threshold.rs +++ b/tests/ui-toml/array_size_threshold/array_size_threshold.rs @@ -2,9 +2,11 @@ #![warn(clippy::large_const_arrays, clippy::large_stack_arrays)] //@no-rustfix const ABOVE: [u8; 11] = [0; 11]; +//~^ large_const_arrays const BELOW: [u8; 10] = [0; 10]; fn main() { let above = [0u8; 11]; + //~^ large_stack_arrays let below = [0u8; 10]; } diff --git a/tests/ui-toml/array_size_threshold/array_size_threshold.stderr b/tests/ui-toml/array_size_threshold/array_size_threshold.stderr index 41cb85b67df8..c962e8094076 100644 --- a/tests/ui-toml/array_size_threshold/array_size_threshold.stderr +++ b/tests/ui-toml/array_size_threshold/array_size_threshold.stderr @@ -10,7 +10,7 @@ LL | const ABOVE: [u8; 11] = [0; 11]; = help: to override `-D warnings` add `#[allow(clippy::large_const_arrays)]` error: allocating a local array larger than 10 bytes - --> tests/ui-toml/array_size_threshold/array_size_threshold.rs:8:17 + --> tests/ui-toml/array_size_threshold/array_size_threshold.rs:9:17 | LL | let above = [0u8; 11]; | ^^^^^^^^^ diff --git a/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs b/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs index 868cf00a8d46..6a9a49324db9 100644 --- a/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs +++ b/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs @@ -3,11 +3,13 @@ use std::net::Ipv4Addr; async fn bad() -> u32 { let _x = String::from("hello"); + //~^ await_holding_invalid_type baz().await } async fn bad_reason() -> u32 { let x = Ipv4Addr::new(127, 0, 0, 1); + //~^ await_holding_invalid_type let y = baz().await; let _x = x; y @@ -31,6 +33,7 @@ async fn baz() -> u32 { fn block_bad() -> impl std::future::Future { async move { let _x = String::from("hi!"); + //~^ await_holding_invalid_type baz().await } } diff --git a/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr b/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr index 39b8634be109..deb7f49db9e1 100644 --- a/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr +++ b/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr @@ -9,13 +9,13 @@ LL | let _x = String::from("hello"); = help: to override `-D warnings` add `#[allow(clippy::await_holding_invalid_type)]` error: holding a disallowed type across an await point `std::net::Ipv4Addr` - --> tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs:10:9 + --> tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs:11:9 | LL | let x = Ipv4Addr::new(127, 0, 0, 1); | ^ error: holding a disallowed type across an await point `std::string::String` - --> tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs:33:13 + --> tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs:35:13 | LL | let _x = String::from("hi!"); | ^^ diff --git a/tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.rs b/tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.rs new file mode 100644 index 000000000000..b5a1f3def61e --- /dev/null +++ b/tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.rs @@ -0,0 +1,2 @@ +//@error-in-other-file: +fn main() {} diff --git a/tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.stderr b/tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.stderr new file mode 100644 index 000000000000..86e30409af06 --- /dev/null +++ b/tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.stderr @@ -0,0 +1,11 @@ +error: error reading Clippy's configuration file: replacement not allowed for this configuration + --> $DIR/tests/ui-toml/await_holding_invalid_type_with_replacement/clippy.toml:1:31 + | +LL | await-holding-invalid-types = [ + | _______________________________^ +LL | | { path = "std::string::String", replacement = "std::net::Ipv4Addr" }, +LL | | ] + | |_^ + +error: aborting due to 1 previous error + diff --git a/tests/ui-toml/await_holding_invalid_type_with_replacement/clippy.toml b/tests/ui-toml/await_holding_invalid_type_with_replacement/clippy.toml new file mode 100644 index 000000000000..f6bc59672ed7 --- /dev/null +++ b/tests/ui-toml/await_holding_invalid_type_with_replacement/clippy.toml @@ -0,0 +1,3 @@ +await-holding-invalid-types = [ + { path = "std::string::String", replacement = "std::net::Ipv4Addr" }, +] diff --git a/tests/ui-toml/borrow_interior_mutable_const/ignore.rs b/tests/ui-toml/borrow_interior_mutable_const/ignore.rs index 79c7cef6ce1b..0514419fd189 100644 --- a/tests/ui-toml/borrow_interior_mutable_const/ignore.rs +++ b/tests/ui-toml/borrow_interior_mutable_const/ignore.rs @@ -1,4 +1,5 @@ //@compile-flags: --crate-name borrow_interior_mutable_const_ignore +//@check-pass #![warn(clippy::borrow_interior_mutable_const)] #![allow(clippy::declare_interior_mutable_const)] diff --git a/tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.default.stderr b/tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.default.stderr new file mode 100644 index 000000000000..2a6170b0bcdc --- /dev/null +++ b/tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.default.stderr @@ -0,0 +1,11 @@ +error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.4.0` + --> tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.rs:14:5 + | +LL | sleep(Duration::new(1, 0)) + | ^^^^^ + | + = note: `-D clippy::incompatible-msrv` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::incompatible_msrv)]` + +error: aborting due to 1 previous error + diff --git a/tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.enabled.stderr b/tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.enabled.stderr new file mode 100644 index 000000000000..8a85d38fba3c --- /dev/null +++ b/tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.enabled.stderr @@ -0,0 +1,23 @@ +error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.4.0` + --> tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.rs:14:5 + | +LL | sleep(Duration::new(1, 0)) + | ^^^^^ + | + = note: `-D clippy::incompatible-msrv` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::incompatible_msrv)]` + +error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.4.0` + --> tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.rs:20:5 + | +LL | sleep(Duration::new(1, 0)); + | ^^^^^ + +error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.4.0` + --> tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.rs:28:9 + | +LL | sleep(Duration::new(1, 0)); + | ^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.rs b/tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.rs new file mode 100644 index 000000000000..fed5f350b722 --- /dev/null +++ b/tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.rs @@ -0,0 +1,31 @@ +//@compile-flags: --test +//@revisions: default enabled +//@[enabled] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/check_incompatible_msrv_in_tests/enabled +//@[default] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/check_incompatible_msrv_in_tests/default + +#![warn(clippy::incompatible_msrv)] +#![feature(custom_inner_attributes)] +#![clippy::msrv = "1.3.0"] + +use std::thread::sleep; +use std::time::Duration; + +fn main() { + sleep(Duration::new(1, 0)) + //~^ incompatible_msrv +} + +#[test] +fn test() { + sleep(Duration::new(1, 0)); + //~[enabled]^ incompatible_msrv +} + +#[cfg(test)] +mod tests { + use super::*; + fn helper() { + sleep(Duration::new(1, 0)); + //~[enabled]^ incompatible_msrv + } +} diff --git a/tests/ui-toml/check_incompatible_msrv_in_tests/default/clippy.toml b/tests/ui-toml/check_incompatible_msrv_in_tests/default/clippy.toml new file mode 100644 index 000000000000..1d13759aceb7 --- /dev/null +++ b/tests/ui-toml/check_incompatible_msrv_in_tests/default/clippy.toml @@ -0,0 +1 @@ +# default config has check-incompatible-msrv-in-tests as false diff --git a/tests/ui-toml/check_incompatible_msrv_in_tests/enabled/clippy.toml b/tests/ui-toml/check_incompatible_msrv_in_tests/enabled/clippy.toml new file mode 100644 index 000000000000..c56af6c82186 --- /dev/null +++ b/tests/ui-toml/check_incompatible_msrv_in_tests/enabled/clippy.toml @@ -0,0 +1 @@ +check-incompatible-msrv-in-tests = true diff --git a/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.rs b/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.rs index 7f1c512d7c97..ecb43dc34a8a 100644 --- a/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.rs +++ b/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.rs @@ -4,6 +4,7 @@ fn main() {} #[warn(clippy::cognitive_complexity)] fn cognitive_complexity() { + //~^ cognitive_complexity let x = vec![1, 2, 3]; for i in x { if i == 1 { diff --git a/tests/ui-toml/dbg_macro/dbg_macro.fixed b/tests/ui-toml/dbg_macro/dbg_macro.fixed index d42b29ba21a6..a91414559324 100644 --- a/tests/ui-toml/dbg_macro/dbg_macro.fixed +++ b/tests/ui-toml/dbg_macro/dbg_macro.fixed @@ -4,20 +4,27 @@ fn foo(n: u32) -> u32 { if let Some(n) = n.checked_sub(4) { n } else { n } + //~^ dbg_macro } fn factorial(n: u32) -> u32 { if n <= 1 { + //~^ dbg_macro 1 + //~^ dbg_macro } else { n * factorial(n - 1) + //~^ dbg_macro } } fn main() { 42; + //~^ dbg_macro foo(3) + factorial(4); + //~^ dbg_macro (1, 2, 3, 4, 5); + //~^ dbg_macro } #[test] diff --git a/tests/ui-toml/dbg_macro/dbg_macro.rs b/tests/ui-toml/dbg_macro/dbg_macro.rs index bd189b1576f9..6565f2e3cf7c 100644 --- a/tests/ui-toml/dbg_macro/dbg_macro.rs +++ b/tests/ui-toml/dbg_macro/dbg_macro.rs @@ -4,20 +4,27 @@ fn foo(n: u32) -> u32 { if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n } + //~^ dbg_macro } fn factorial(n: u32) -> u32 { if dbg!(n <= 1) { + //~^ dbg_macro dbg!(1) + //~^ dbg_macro } else { dbg!(n * factorial(n - 1)) + //~^ dbg_macro } } fn main() { dbg!(42); + //~^ dbg_macro foo(3) + dbg!(factorial(4)); + //~^ dbg_macro dbg!(1, 2, 3, 4, 5); + //~^ dbg_macro } #[test] diff --git a/tests/ui-toml/dbg_macro/dbg_macro.stderr b/tests/ui-toml/dbg_macro/dbg_macro.stderr index f0d7104a57dd..4587d28c3f34 100644 --- a/tests/ui-toml/dbg_macro/dbg_macro.stderr +++ b/tests/ui-toml/dbg_macro/dbg_macro.stderr @@ -13,7 +13,7 @@ LL + if let Some(n) = n.checked_sub(4) { n } else { n } | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui-toml/dbg_macro/dbg_macro.rs:10:8 + --> tests/ui-toml/dbg_macro/dbg_macro.rs:11:8 | LL | if dbg!(n <= 1) { | ^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + if n <= 1 { | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui-toml/dbg_macro/dbg_macro.rs:11:9 + --> tests/ui-toml/dbg_macro/dbg_macro.rs:13:9 | LL | dbg!(1) | ^^^^^^^ @@ -37,7 +37,7 @@ LL + 1 | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui-toml/dbg_macro/dbg_macro.rs:13:9 + --> tests/ui-toml/dbg_macro/dbg_macro.rs:16:9 | LL | dbg!(n * factorial(n - 1)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + n * factorial(n - 1) | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui-toml/dbg_macro/dbg_macro.rs:18:5 + --> tests/ui-toml/dbg_macro/dbg_macro.rs:22:5 | LL | dbg!(42); | ^^^^^^^^ @@ -61,7 +61,7 @@ LL + 42; | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui-toml/dbg_macro/dbg_macro.rs:19:14 + --> tests/ui-toml/dbg_macro/dbg_macro.rs:24:14 | LL | foo(3) + dbg!(factorial(4)); | ^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + foo(3) + factorial(4); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui-toml/dbg_macro/dbg_macro.rs:20:5 + --> tests/ui-toml/dbg_macro/dbg_macro.rs:26:5 | LL | dbg!(1, 2, 3, 4, 5); | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/declare_interior_mutable_const/ignore.rs b/tests/ui-toml/declare_interior_mutable_const/ignore.rs index 6385cf4f852f..49ffc7a939de 100644 --- a/tests/ui-toml/declare_interior_mutable_const/ignore.rs +++ b/tests/ui-toml/declare_interior_mutable_const/ignore.rs @@ -1,4 +1,5 @@ //@compile-flags: --crate-name declare_interior_mutable_const_ignore +//@check-pass #![warn(clippy::declare_interior_mutable_const)] #![allow(clippy::borrow_interior_mutable_const)] diff --git a/tests/ui-toml/disallowed_macros/disallowed_macros.rs b/tests/ui-toml/disallowed_macros/disallowed_macros.rs index e63a99e74cbb..cfe19606ef4a 100644 --- a/tests/ui-toml/disallowed_macros/disallowed_macros.rs +++ b/tests/ui-toml/disallowed_macros/disallowed_macros.rs @@ -11,38 +11,54 @@ use serde::Serialize; fn main() { println!("one"); + //~^ disallowed_macros println!("two"); + //~^ disallowed_macros cfg!(unix); + //~^ disallowed_macros vec![1, 2, 3]; + //~^ disallowed_macros #[derive(Serialize)] + //~^ disallowed_macros struct Derive; let _ = macros::expr!(); + //~^ disallowed_macros macros::stmt!(); + //~^ disallowed_macros let macros::pat!() = 1; + //~^ disallowed_macros let _: macros::ty!() = ""; + //~^ disallowed_macros macros::item!(); + //~^ disallowed_macros let _ = macros::binop!(1); + //~^ disallowed_macros eprintln!("allowed"); } macros::attr! { +//~^ disallowed_macros struct S; } impl S { macros::item!(); + //~^ disallowed_macros } trait Y { macros::item!(); + //~^ disallowed_macros } impl Y for S { macros::item!(); + //~^ disallowed_macros } #[derive(Derive)] +//~^ disallowed_macros struct Foo; diff --git a/tests/ui-toml/disallowed_macros/disallowed_macros.stderr b/tests/ui-toml/disallowed_macros/disallowed_macros.stderr index 6a6c6168a1f5..589995fa87d9 100644 --- a/tests/ui-toml/disallowed_macros/disallowed_macros.stderr +++ b/tests/ui-toml/disallowed_macros/disallowed_macros.stderr @@ -1,5 +1,5 @@ error: use of a disallowed macro `serde::Serialize` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:18:14 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:22:14 | LL | #[derive(Serialize)] | ^^^^^^^^^ @@ -9,15 +9,16 @@ LL | #[derive(Serialize)] = help: to override `-D warnings` add `#[allow(clippy::disallowed_macros)]` error: use of a disallowed macro `macros::attr` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:31:1 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:42:1 | LL | / macros::attr! { +LL | | LL | | struct S; LL | | } | |_^ error: use of a disallowed macro `proc_macros::Derive` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:47:10 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:62:10 | LL | #[derive(Derive)] | ^^^^^^ @@ -29,73 +30,73 @@ LL | println!("one"); | ^^^^^^^^^^^^^^^ error: use of a disallowed macro `std::println` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:14:5 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:15:5 | LL | println!("two"); | ^^^^^^^^^^^^^^^ error: use of a disallowed macro `std::cfg` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:15:5 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:17:5 | LL | cfg!(unix); | ^^^^^^^^^^ error: use of a disallowed macro `std::vec` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:16:5 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:19:5 | LL | vec![1, 2, 3]; | ^^^^^^^^^^^^^ error: use of a disallowed macro `macros::expr` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:21:13 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:26:13 | LL | let _ = macros::expr!(); | ^^^^^^^^^^^^^^^ error: use of a disallowed macro `macros::stmt` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:22:5 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:28:5 | LL | macros::stmt!(); | ^^^^^^^^^^^^^^^ error: use of a disallowed macro `macros::pat` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:23:9 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:30:9 | LL | let macros::pat!() = 1; | ^^^^^^^^^^^^^^ error: use of a disallowed macro `macros::ty` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:24:12 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:32:12 | LL | let _: macros::ty!() = ""; | ^^^^^^^^^^^^^ error: use of a disallowed macro `macros::item` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:25:5 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:34:5 | LL | macros::item!(); | ^^^^^^^^^^^^^^^ error: use of a disallowed macro `macros::binop` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:26:13 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:36:13 | LL | let _ = macros::binop!(1); | ^^^^^^^^^^^^^^^^^ error: use of a disallowed macro `macros::item` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:36:5 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:48:5 | LL | macros::item!(); | ^^^^^^^^^^^^^^^ error: use of a disallowed macro `macros::item` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:40:5 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:53:5 | LL | macros::item!(); | ^^^^^^^^^^^^^^^ error: use of a disallowed macro `macros::item` - --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:44:5 + --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:58:5 | LL | macros::item!(); | ^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/disallowed_names_append/disallowed_names.rs b/tests/ui-toml/disallowed_names_append/disallowed_names.rs index 61ae8de8e335..ea7e31a119dc 100644 --- a/tests/ui-toml/disallowed_names_append/disallowed_names.rs +++ b/tests/ui-toml/disallowed_names_append/disallowed_names.rs @@ -3,8 +3,10 @@ fn main() { // `foo` is part of the default configuration let foo = "bar"; + //~^ disallowed_names // `ducks` was unrightfully disallowed let ducks = ["quack", "quack"]; + //~^ disallowed_names // `fox` is okay let fox = ["what", "does", "the", "fox", "say", "?"]; } diff --git a/tests/ui-toml/disallowed_names_append/disallowed_names.stderr b/tests/ui-toml/disallowed_names_append/disallowed_names.stderr index e6481c9cc63b..6b7a3fbd8c8d 100644 --- a/tests/ui-toml/disallowed_names_append/disallowed_names.stderr +++ b/tests/ui-toml/disallowed_names_append/disallowed_names.stderr @@ -8,7 +8,7 @@ LL | let foo = "bar"; = help: to override `-D warnings` add `#[allow(clippy::disallowed_names)]` error: use of a disallowed/placeholder name `ducks` - --> tests/ui-toml/disallowed_names_append/disallowed_names.rs:7:9 + --> tests/ui-toml/disallowed_names_append/disallowed_names.rs:8:9 | LL | let ducks = ["quack", "quack"]; | ^^^^^ diff --git a/tests/ui-toml/disallowed_names_replace/disallowed_names.rs b/tests/ui-toml/disallowed_names_replace/disallowed_names.rs index 61ae8de8e335..dd79795d76a2 100644 --- a/tests/ui-toml/disallowed_names_replace/disallowed_names.rs +++ b/tests/ui-toml/disallowed_names_replace/disallowed_names.rs @@ -5,6 +5,7 @@ fn main() { let foo = "bar"; // `ducks` was unrightfully disallowed let ducks = ["quack", "quack"]; + //~^ disallowed_names // `fox` is okay let fox = ["what", "does", "the", "fox", "say", "?"]; } diff --git a/tests/ui-toml/doc_valid_idents_append/doc_markdown.fixed b/tests/ui-toml/doc_valid_idents_append/doc_markdown.fixed index f16e138da2be..e295712e85f4 100644 --- a/tests/ui-toml/doc_valid_idents_append/doc_markdown.fixed +++ b/tests/ui-toml/doc_valid_idents_append/doc_markdown.fixed @@ -7,6 +7,7 @@ fn allowed_name() {} fn default_name() {} /// `TestItemThingyOfCoolness` might sound cool but is not on the list and should be linted. +//~^ doc_markdown fn unknown_name() {} fn main() {} diff --git a/tests/ui-toml/doc_valid_idents_append/doc_markdown.rs b/tests/ui-toml/doc_valid_idents_append/doc_markdown.rs index 327a592e9cad..192652a7f65b 100644 --- a/tests/ui-toml/doc_valid_idents_append/doc_markdown.rs +++ b/tests/ui-toml/doc_valid_idents_append/doc_markdown.rs @@ -7,6 +7,7 @@ fn allowed_name() {} fn default_name() {} /// TestItemThingyOfCoolness might sound cool but is not on the list and should be linted. +//~^ doc_markdown fn unknown_name() {} fn main() {} diff --git a/tests/ui-toml/doc_valid_idents_replace/doc_markdown.fixed b/tests/ui-toml/doc_valid_idents_replace/doc_markdown.fixed index af6ec675e81b..48a6f5fe61e6 100644 --- a/tests/ui-toml/doc_valid_idents_replace/doc_markdown.fixed +++ b/tests/ui-toml/doc_valid_idents_replace/doc_markdown.fixed @@ -4,9 +4,12 @@ fn allowed_name() {} /// `OAuth` and `LaTeX` are inside Clippy's default list. +//~^ doc_markdown +//~| doc_markdown fn default_name() {} /// `TestItemThingyOfCoolness` might sound cool but is not on the list and should be linted. +//~^ doc_markdown fn unknown_name() {} fn main() {} diff --git a/tests/ui-toml/doc_valid_idents_replace/doc_markdown.rs b/tests/ui-toml/doc_valid_idents_replace/doc_markdown.rs index 327a592e9cad..f700c1ab0336 100644 --- a/tests/ui-toml/doc_valid_idents_replace/doc_markdown.rs +++ b/tests/ui-toml/doc_valid_idents_replace/doc_markdown.rs @@ -4,9 +4,12 @@ fn allowed_name() {} /// OAuth and LaTeX are inside Clippy's default list. +//~^ doc_markdown +//~| doc_markdown fn default_name() {} /// TestItemThingyOfCoolness might sound cool but is not on the list and should be linted. +//~^ doc_markdown fn unknown_name() {} fn main() {} diff --git a/tests/ui-toml/doc_valid_idents_replace/doc_markdown.stderr b/tests/ui-toml/doc_valid_idents_replace/doc_markdown.stderr index 9f2d7cf54e0d..e06b958a1b37 100644 --- a/tests/ui-toml/doc_valid_idents_replace/doc_markdown.stderr +++ b/tests/ui-toml/doc_valid_idents_replace/doc_markdown.stderr @@ -25,7 +25,7 @@ LL + /// OAuth and `LaTeX` are inside Clippy's default list. | error: item in documentation is missing backticks - --> tests/ui-toml/doc_valid_idents_replace/doc_markdown.rs:9:5 + --> tests/ui-toml/doc_valid_idents_replace/doc_markdown.rs:11:5 | LL | /// TestItemThingyOfCoolness might sound cool but is not on the list and should be linted. | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.rs b/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.rs index f328e4d9d04c..b5a1f3def61e 100644 --- a/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.rs +++ b/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.rs @@ -1 +1,2 @@ +//@error-in-other-file: fn main() {} diff --git a/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.rs b/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.rs index f328e4d9d04c..b5a1f3def61e 100644 --- a/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.rs +++ b/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.rs @@ -1 +1,2 @@ +//@error-in-other-file: fn main() {} diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.rs b/tests/ui-toml/excessive_nesting/excessive_nesting.rs index 858aab528a91..205cd8ba4ee8 100644 --- a/tests/ui-toml/excessive_nesting/excessive_nesting.rs +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.rs @@ -23,6 +23,7 @@ static X: u32 = { let y = { let z = { let w = { 3 }; + //~^ excessive_nesting w }; z @@ -69,6 +70,7 @@ impl A { struct C; impl C { + //~^ excessive_nesting pub fn c() {} } } @@ -83,6 +85,7 @@ trait Lol { fn bb() { fn cc() { let x = { 1 }; // not a warning, but cc is + //~^ excessive_nesting } let x = { 1 }; // warning @@ -100,6 +103,7 @@ pub mod a { pub mod c { pub mod d { pub mod e { + //~^ excessive_nesting pub mod f {} } // not here } // only warning should be here @@ -113,13 +117,17 @@ fn main() { let a = A; a_but_not({{{{{{{{0}}}}}}}}); + //~^ excessive_nesting a.a({{{{{{{{{0}}}}}}}}}); + //~^ excessive_nesting (0, {{{{{{{1}}}}}}}); + //~^ excessive_nesting if true { if true { if true { if true { + //~^ excessive_nesting if true { } @@ -132,6 +140,7 @@ fn main() { let x = (|| { let y = (|| { let z = (|| { + //~^ excessive_nesting let w = { 3 }; w })(); @@ -151,38 +160,64 @@ fn main() { // this is a mess, but that's intentional let mut y = 1; y += {{{{{5}}}}}; + //~^ excessive_nesting let z = y + {{{{{{{{{5}}}}}}}}}; + //~^ excessive_nesting [0, {{{{{{{{{{0}}}}}}}}}}]; + //~^ excessive_nesting let mut xx = [0; {{{{{{{{100}}}}}}}}]; + //~^ excessive_nesting xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; + //~^ excessive_nesting &mut {{{{{{{{{{y}}}}}}}}}}; + //~^ excessive_nesting for i in {{{{xx}}}} {{{{{{{{}}}}}}}} + //~^ excessive_nesting + //~| excessive_nesting while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} + //~^ excessive_nesting + //~| excessive_nesting while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} + //~^ excessive_nesting + //~| excessive_nesting let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; + //~^ excessive_nesting {{{{1;}}}}..{{{{{{3}}}}}}; + //~^ excessive_nesting + //~| excessive_nesting {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; + //~^ excessive_nesting + //~| excessive_nesting ..{{{{{{{5}}}}}}}; + //~^ excessive_nesting ..={{{{{3}}}}}; + //~^ excessive_nesting {{{{{1;}}}}}..; + //~^ excessive_nesting loop { break {{{{1}}}} }; + //~^ excessive_nesting loop {{{{{{}}}}}} + //~^ excessive_nesting match {{{{{{true}}}}}} { + //~^ excessive_nesting true => {{{{}}}}, + //~^ excessive_nesting false => {{{{}}}}, + //~^ excessive_nesting } { { { { + //~^ excessive_nesting println!("warning! :)"); } } @@ -192,10 +227,12 @@ fn main() { async fn b() -> u32 { async fn c() -> u32 {{{{{{{0}}}}}}} + //~^ excessive_nesting c().await } async fn a() { {{{{b().await}}}}; + //~^ excessive_nesting } diff --git a/tests/ui-toml/excessive_nesting/excessive_nesting.stderr b/tests/ui-toml/excessive_nesting/excessive_nesting.stderr index 9cf6fc66757d..bc2c4b8612ec 100644 --- a/tests/ui-toml/excessive_nesting/excessive_nesting.stderr +++ b/tests/ui-toml/excessive_nesting/excessive_nesting.stderr @@ -9,9 +9,10 @@ LL | let w = { 3 }; = help: to override `-D warnings` add `#[allow(clippy::excessive_nesting)]` error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:71:17 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:72:17 | LL | / impl C { +LL | | LL | | pub fn c() {} LL | | } | |_________________^ @@ -19,7 +20,7 @@ LL | | } = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:85:25 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:87:25 | LL | let x = { 1 }; // not a warning, but cc is | ^^^^^ @@ -27,9 +28,10 @@ LL | let x = { 1 }; // not a warning, but cc is = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:102:17 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:105:17 | LL | / pub mod e { +LL | | LL | | pub mod f {} LL | | } // not here | |_________________^ @@ -37,7 +39,7 @@ LL | | } // not here = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:115:18 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:119:18 | LL | a_but_not({{{{{{{{0}}}}}}}}); | ^^^^^^^^^^^ @@ -45,7 +47,7 @@ LL | a_but_not({{{{{{{{0}}}}}}}}); = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:116:12 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:121:12 | LL | a.a({{{{{{{{{0}}}}}}}}}); | ^^^^^^^^^^^^^ @@ -53,7 +55,7 @@ LL | a.a({{{{{{{{{0}}}}}}}}}); = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:117:12 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:123:12 | LL | (0, {{{{{{{1}}}}}}}); | ^^^^^^^^^ @@ -61,10 +63,11 @@ LL | (0, {{{{{{{1}}}}}}}); = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:122:25 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:129:25 | LL | if true { | _________________________^ +LL | | LL | | if true { ... | LL | | } @@ -73,10 +76,11 @@ LL | | } = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:134:29 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:142:29 | LL | let z = (|| { | _____________________________^ +LL | | LL | | let w = { 3 }; LL | | w LL | | })(); @@ -85,7 +89,7 @@ LL | | })(); = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:153:13 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:162:13 | LL | y += {{{{{5}}}}}; | ^^^^^ @@ -93,7 +97,7 @@ LL | y += {{{{{5}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:154:20 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:164:20 | LL | let z = y + {{{{{{{{{5}}}}}}}}}; | ^^^^^^^^^^^^^ @@ -101,7 +105,7 @@ LL | let z = y + {{{{{{{{{5}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:155:12 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:166:12 | LL | [0, {{{{{{{{{{0}}}}}}}}}}]; | ^^^^^^^^^^^^^^^ @@ -109,7 +113,7 @@ LL | [0, {{{{{{{{{{0}}}}}}}}}}]; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:156:25 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:168:25 | LL | let mut xx = [0; {{{{{{{{100}}}}}}}}]; | ^^^^^^^^^^^^^ @@ -117,7 +121,7 @@ LL | let mut xx = [0; {{{{{{{{100}}}}}}}}]; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:157:11 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:170:11 | LL | xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -125,7 +129,7 @@ LL | xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}]; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:158:13 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:172:13 | LL | &mut {{{{{{{{{{y}}}}}}}}}}; | ^^^^^^^^^^^^^^^ @@ -133,7 +137,7 @@ LL | &mut {{{{{{{{{{y}}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:160:17 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:175:17 | LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} | ^^^^ @@ -141,7 +145,7 @@ LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:160:28 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:175:28 | LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} | ^^^^^^^^^^ @@ -149,7 +153,7 @@ LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:162:28 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:179:28 | LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} | ^^^^^^^^^^^^^ @@ -157,7 +161,7 @@ LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:162:48 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:179:48 | LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} | ^^^^^^^^ @@ -165,7 +169,7 @@ LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:164:14 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:183:14 | LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} | ^^^^^^^^^^^^^^ @@ -173,7 +177,7 @@ LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:164:35 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:183:35 | LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} | ^^^^^^^^^^^^ @@ -181,7 +185,7 @@ LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:166:23 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:187:23 | LL | let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -189,7 +193,7 @@ LL | let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} }; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:168:8 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:190:8 | LL | {{{{1;}}}}..{{{{{{3}}}}}}; | ^^^^ @@ -197,7 +201,7 @@ LL | {{{{1;}}}}..{{{{{{3}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:168:20 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:190:20 | LL | {{{{1;}}}}..{{{{{{3}}}}}}; | ^^^^^^^ @@ -205,7 +209,7 @@ LL | {{{{1;}}}}..{{{{{{3}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:169:8 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:193:8 | LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; | ^^^^ @@ -213,7 +217,7 @@ LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:169:21 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:193:21 | LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -221,7 +225,7 @@ LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:170:10 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:196:10 | LL | ..{{{{{{{5}}}}}}}; | ^^^^^^^^^ @@ -229,7 +233,7 @@ LL | ..{{{{{{{5}}}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:171:11 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:198:11 | LL | ..={{{{{3}}}}}; | ^^^^^ @@ -237,7 +241,7 @@ LL | ..={{{{{3}}}}}; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:172:8 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:200:8 | LL | {{{{{1;}}}}}..; | ^^^^^^ @@ -245,7 +249,7 @@ LL | {{{{{1;}}}}}..; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:174:20 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:203:20 | LL | loop { break {{{{1}}}} }; | ^^^^^ @@ -253,7 +257,7 @@ LL | loop { break {{{{1}}}} }; = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:175:13 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:205:13 | LL | loop {{{{{{}}}}}} | ^^^^^^ @@ -261,7 +265,7 @@ LL | loop {{{{{{}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:177:14 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:208:14 | LL | match {{{{{{true}}}}}} { | ^^^^^^^^^^ @@ -269,7 +273,7 @@ LL | match {{{{{{true}}}}}} { = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:178:20 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:210:20 | LL | true => {{{{}}}}, | ^^ @@ -277,7 +281,7 @@ LL | true => {{{{}}}}, = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:179:21 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:212:21 | LL | false => {{{{}}}}, | ^^ @@ -285,9 +289,10 @@ LL | false => {{{{}}}}, = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:185:17 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:219:17 | LL | / { +LL | | LL | | println!("warning! :)"); LL | | } | |_________________^ @@ -295,7 +300,7 @@ LL | | } = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:194:28 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:229:28 | LL | async fn c() -> u32 {{{{{{{0}}}}}}} | ^^^^^^^^^ @@ -303,7 +308,7 @@ LL | async fn c() -> u32 {{{{{{{0}}}}}}} = help: try refactoring your code to minimize nesting error: this block is too nested - --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:200:8 + --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:236:8 | LL | {{{{b().await}}}}; | ^^^^^^^^^^^ diff --git a/tests/ui-toml/expect_used/clippy.toml b/tests/ui-toml/expect_used/clippy.toml index 6933b8164195..895de8357cf7 100644 --- a/tests/ui-toml/expect_used/clippy.toml +++ b/tests/ui-toml/expect_used/clippy.toml @@ -1 +1,2 @@ +allow-expect-in-consts = false allow-expect-in-tests = true diff --git a/tests/ui-toml/expect_used/expect_used.rs b/tests/ui-toml/expect_used/expect_used.rs index 206788e19f02..9955c9b6baa1 100644 --- a/tests/ui-toml/expect_used/expect_used.rs +++ b/tests/ui-toml/expect_used/expect_used.rs @@ -1,20 +1,31 @@ //@compile-flags: --test +//@no-rustfix #![warn(clippy::expect_used)] #![allow(clippy::unnecessary_literal_unwrap)] fn expect_option() { let opt = Some(0); let _ = opt.expect(""); + //~^ expect_used } fn expect_result() { let res: Result = Ok(0); let _ = res.expect(""); + //~^ expect_used } fn main() { expect_option(); expect_result(); + + const SOME: Option = Some(3); + const UNWRAPPED: i32 = SOME.expect("Not three?"); + //~^ expect_used + const { + SOME.expect("Still not three?"); + //~^ expect_used + } } #[test] diff --git a/tests/ui-toml/expect_used/expect_used.stderr b/tests/ui-toml/expect_used/expect_used.stderr index 81691f8ac6c0..3bb471e6dfcc 100644 --- a/tests/ui-toml/expect_used/expect_used.stderr +++ b/tests/ui-toml/expect_used/expect_used.stderr @@ -1,5 +1,5 @@ error: used `expect()` on an `Option` value - --> tests/ui-toml/expect_used/expect_used.rs:7:13 + --> tests/ui-toml/expect_used/expect_used.rs:8:13 | LL | let _ = opt.expect(""); | ^^^^^^^^^^^^^^ @@ -9,12 +9,28 @@ LL | let _ = opt.expect(""); = help: to override `-D warnings` add `#[allow(clippy::expect_used)]` error: used `expect()` on a `Result` value - --> tests/ui-toml/expect_used/expect_used.rs:12:13 + --> tests/ui-toml/expect_used/expect_used.rs:14:13 | LL | let _ = res.expect(""); | ^^^^^^^^^^^^^^ | = note: if this value is an `Err`, it will panic -error: aborting due to 2 previous errors +error: used `expect()` on an `Option` value + --> tests/ui-toml/expect_used/expect_used.rs:23:28 + | +LL | const UNWRAPPED: i32 = SOME.expect("Not three?"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: if this value is `None`, it will panic + +error: used `expect()` on an `Option` value + --> tests/ui-toml/expect_used/expect_used.rs:26:9 + | +LL | SOME.expect("Still not three?"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: if this value is `None`, it will panic + +error: aborting due to 4 previous errors diff --git a/tests/ui-toml/extra_unused_type_parameters/extra_unused_type_parameters.rs b/tests/ui-toml/extra_unused_type_parameters/extra_unused_type_parameters.rs index 5655232455cb..1256c93c0fa1 100644 --- a/tests/ui-toml/extra_unused_type_parameters/extra_unused_type_parameters.rs +++ b/tests/ui-toml/extra_unused_type_parameters/extra_unused_type_parameters.rs @@ -1,3 +1,4 @@ +//@check-pass pub struct S; impl S { diff --git a/tests/ui-toml/fn_params_excessive_bools/test.rs b/tests/ui-toml/fn_params_excessive_bools/test.rs index 42897b389edf..af8b8a7991ab 100644 --- a/tests/ui-toml/fn_params_excessive_bools/test.rs +++ b/tests/ui-toml/fn_params_excessive_bools/test.rs @@ -2,5 +2,6 @@ fn f(_: bool) {} fn g(_: bool, _: bool) {} +//~^ fn_params_excessive_bools fn main() {} diff --git a/tests/ui-toml/functions_maxlines/test.rs b/tests/ui-toml/functions_maxlines/test.rs index 4ac0378544c7..09d76a9b2657 100644 --- a/tests/ui-toml/functions_maxlines/test.rs +++ b/tests/ui-toml/functions_maxlines/test.rs @@ -17,18 +17,21 @@ fn many_comments_but_one_line_of_code() { // This should be considered two and a fail. fn too_many_lines() { + //~^ too_many_lines println!("This is bad."); println!("This is bad."); } // This should only fail once (#7517). async fn async_too_many_lines() { + //~^ too_many_lines println!("This is bad."); println!("This is bad."); } // This should fail only once, without failing on the closure. fn closure_too_many_lines() { + //~^ too_many_lines let _ = { println!("This is bad."); println!("This is bad."); @@ -51,6 +54,7 @@ fn comment_after_code() { // This should fail since it is technically two lines. #[rustfmt::skip] fn comment_before_code() { +//~^ too_many_lines let _ = "test"; /* This comment extends to the front of the code but this line should still count. */ let _ = 5; diff --git a/tests/ui-toml/functions_maxlines/test.stderr b/tests/ui-toml/functions_maxlines/test.stderr index cb188a868c44..14a49cb76c1c 100644 --- a/tests/ui-toml/functions_maxlines/test.stderr +++ b/tests/ui-toml/functions_maxlines/test.stderr @@ -2,6 +2,7 @@ error: this function has too many lines (2/1) --> tests/ui-toml/functions_maxlines/test.rs:19:1 | LL | / fn too_many_lines() { +LL | | LL | | println!("This is bad."); LL | | println!("This is bad."); LL | | } @@ -11,18 +12,20 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::too_many_lines)]` error: this function has too many lines (4/1) - --> tests/ui-toml/functions_maxlines/test.rs:25:1 + --> tests/ui-toml/functions_maxlines/test.rs:26:1 | LL | / async fn async_too_many_lines() { +LL | | LL | | println!("This is bad."); LL | | println!("This is bad."); LL | | } | |_^ error: this function has too many lines (4/1) - --> tests/ui-toml/functions_maxlines/test.rs:31:1 + --> tests/ui-toml/functions_maxlines/test.rs:33:1 | LL | / fn closure_too_many_lines() { +LL | | LL | | let _ = { LL | | println!("This is bad."); LL | | println!("This is bad."); @@ -31,9 +34,10 @@ LL | | } | |_^ error: this function has too many lines (2/1) - --> tests/ui-toml/functions_maxlines/test.rs:53:1 + --> tests/ui-toml/functions_maxlines/test.rs:56:1 | LL | / fn comment_before_code() { +LL | | LL | | let _ = "test"; LL | | /* This comment extends to the front of LL | | the code but this line should still count. */ let _ = 5; diff --git a/tests/ui-toml/good_toml_no_false_negatives/conf_no_false_negatives.rs b/tests/ui-toml/good_toml_no_false_negatives/conf_no_false_negatives.rs index f328e4d9d04c..9763a0977801 100644 --- a/tests/ui-toml/good_toml_no_false_negatives/conf_no_false_negatives.rs +++ b/tests/ui-toml/good_toml_no_false_negatives/conf_no_false_negatives.rs @@ -1 +1,2 @@ +//@check-pass fn main() {} diff --git a/tests/ui-toml/ifs_same_cond/ifs_same_cond.rs b/tests/ui-toml/ifs_same_cond/ifs_same_cond.rs index 4882416c414a..e953a2a4e90b 100644 --- a/tests/ui-toml/ifs_same_cond/ifs_same_cond.rs +++ b/tests/ui-toml/ifs_same_cond/ifs_same_cond.rs @@ -13,6 +13,7 @@ fn issue10272() { if x.get() { } else if !x.take() { } else if x.get() { + //~^ ifs_same_cond } else { } } diff --git a/tests/ui-toml/indexing_slicing/indexing_slicing.rs b/tests/ui-toml/indexing_slicing/indexing_slicing.rs index 0a0da88ea1fa..dd741be91d29 100644 --- a/tests/ui-toml/indexing_slicing/indexing_slicing.rs +++ b/tests/ui-toml/indexing_slicing/indexing_slicing.rs @@ -6,6 +6,7 @@ fn main() { let x = [1, 2, 3, 4]; let index: usize = 1; &x[index..]; + //~^ indexing_slicing } #[cfg(test)] diff --git a/tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.rs b/tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.rs index 2ae673a6def0..d6b0a3017920 100644 --- a/tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.rs +++ b/tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.rs @@ -7,6 +7,7 @@ pub mod foo { // this line should produce a warning: pub fn to_foo() {} + //~^ module_name_repetitions // but this line shouldn't pub fn bar_foo() {} diff --git a/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.rs b/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.rs index dbd61992c0d6..347430f3d2f9 100644 --- a/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.rs +++ b/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.rs @@ -7,6 +7,7 @@ pub mod foo { // this line should produce a warning: pub fn something_foo() {} + //~^ module_name_repetitions // but none of the following should: pub fn bar_foo() {} diff --git a/tests/ui-toml/item_name_repetitions/threshold0/item_name_repetitions.rs b/tests/ui-toml/item_name_repetitions/threshold0/item_name_repetitions.rs index b633dcbd19e4..f05e2410f7e2 100644 --- a/tests/ui-toml/item_name_repetitions/threshold0/item_name_repetitions.rs +++ b/tests/ui-toml/item_name_repetitions/threshold0/item_name_repetitions.rs @@ -1,3 +1,5 @@ +//@check-pass + struct Data {} enum Actions {} diff --git a/tests/ui-toml/large_futures/large_futures.fixed b/tests/ui-toml/large_futures/large_futures.fixed index 7dea9fb95b4b..17d6553a283b 100644 --- a/tests/ui-toml/large_futures/large_futures.fixed +++ b/tests/ui-toml/large_futures/large_futures.fixed @@ -16,6 +16,7 @@ pub async fn should_not_warn() { pub async fn bar() { Box::pin(should_warn()).await; + //~^ large_futures async { let x = [0u8; 1024]; diff --git a/tests/ui-toml/large_futures/large_futures.rs b/tests/ui-toml/large_futures/large_futures.rs index 4158df8b5ff5..bc601227e562 100644 --- a/tests/ui-toml/large_futures/large_futures.rs +++ b/tests/ui-toml/large_futures/large_futures.rs @@ -16,6 +16,7 @@ pub async fn should_not_warn() { pub async fn bar() { should_warn().await; + //~^ large_futures async { let x = [0u8; 1024]; diff --git a/tests/ui-toml/large_include_file/large_include_file.rs b/tests/ui-toml/large_include_file/large_include_file.rs index 184c6d17ba41..685ef1689e72 100644 --- a/tests/ui-toml/large_include_file/large_include_file.rs +++ b/tests/ui-toml/large_include_file/large_include_file.rs @@ -2,7 +2,7 @@ #![allow(clippy::literal_string_with_formatting_args)] // Good -const GOOD_INCLUDE_BYTES: &[u8; 68] = include_bytes!("../../ui/author.rs"); +const GOOD_INCLUDE_BYTES: &[u8; 84] = include_bytes!("../../ui/author.rs"); const GOOD_INCLUDE_STR: &str = include_str!("../../ui/author.rs"); #[allow(clippy::large_include_file)] diff --git a/tests/ui-toml/lint_decimal_readability/test.fixed b/tests/ui-toml/lint_decimal_readability/test.fixed index f013153f5166..2d76824128bf 100644 --- a/tests/ui-toml/lint_decimal_readability/test.fixed +++ b/tests/ui-toml/lint_decimal_readability/test.fixed @@ -17,7 +17,9 @@ fn main() { // due to clippy::inconsistent-digit-grouping let _fail1 = 100_200_300.123_456_789; + //~^ inconsistent_digit_grouping // fail due to the integer part let _fail2 = 100_200_300.300_200_100; + //~^ unreadable_literal } diff --git a/tests/ui-toml/lint_decimal_readability/test.rs b/tests/ui-toml/lint_decimal_readability/test.rs index bd5110138c8c..b42e31085217 100644 --- a/tests/ui-toml/lint_decimal_readability/test.rs +++ b/tests/ui-toml/lint_decimal_readability/test.rs @@ -17,7 +17,9 @@ fn main() { // due to clippy::inconsistent-digit-grouping let _fail1 = 100_200_300.123456789; + //~^ inconsistent_digit_grouping // fail due to the integer part let _fail2 = 100200300.300200100; + //~^ unreadable_literal } diff --git a/tests/ui-toml/lint_decimal_readability/test.stderr b/tests/ui-toml/lint_decimal_readability/test.stderr index 766722d35ab7..c4e164c67ed8 100644 --- a/tests/ui-toml/lint_decimal_readability/test.stderr +++ b/tests/ui-toml/lint_decimal_readability/test.stderr @@ -8,7 +8,7 @@ LL | let _fail1 = 100_200_300.123456789; = help: to override `-D warnings` add `#[allow(clippy::inconsistent_digit_grouping)]` error: long literal lacking separators - --> tests/ui-toml/lint_decimal_readability/test.rs:22:18 + --> tests/ui-toml/lint_decimal_readability/test.rs:23:18 | LL | let _fail2 = 100200300.300200100; | ^^^^^^^^^^^^^^^^^^^ help: consider: `100_200_300.300_200_100` diff --git a/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs b/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs index 3dafea56514d..2465fe45645f 100644 --- a/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs +++ b/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs @@ -17,7 +17,7 @@ macro_rules! allow_works { macro_rules! simple { ($v:expr) => { unsafe { - //~^ ERROR: this macro expands metavariables in an unsafe block + //~^ macro_metavars_in_unsafe dbg!($v); } }; @@ -28,7 +28,7 @@ macro_rules! simple { macro_rules! raw_symbol { ($r#mod:expr, $r#unsafe:expr) => { unsafe { - //~^ ERROR: this macro expands metavariables in an unsafe block + //~^ macro_metavars_in_unsafe $r#mod; } $r#unsafe; @@ -40,7 +40,7 @@ macro_rules! multilevel_unsafe { ($v:expr) => { unsafe { unsafe { - //~^ ERROR: this macro expands metavariables in an unsafe block + //~^ macro_metavars_in_unsafe $v; } } @@ -65,7 +65,7 @@ macro_rules! in_function_with_unsafe { unsafe { fn f() { unsafe { - //~^ ERROR: this macro expands metavariables in an unsafe block + //~^ macro_metavars_in_unsafe $v; } } @@ -93,7 +93,7 @@ macro_rules! const_generic_in_struct { const M: i32 = { 1; unsafe { $inside_unsafe } - //~^ ERROR: this macro expands metavariables in an unsafe block + //~^ macro_metavars_in_unsafe }, const N: i32 = { $outside_unsafe }, >; @@ -108,7 +108,7 @@ macro_rules! fn_with_const_generic { fn f() { $outside_unsafe; unsafe { - //~^ ERROR: this macro expands metavariables in an unsafe block + //~^ macro_metavars_in_unsafe $inside_unsafe; } } @@ -120,7 +120,7 @@ macro_rules! fn_with_const_generic { macro_rules! variables { ($inside_unsafe:expr, $outside_unsafe:expr) => { unsafe { - //~^ ERROR: this macro expands metavariables in an unsafe block + //~^ macro_metavars_in_unsafe $inside_unsafe; let inside_unsafe = 1; inside_unsafe; @@ -135,7 +135,7 @@ macro_rules! variables { macro_rules! multiple_matchers { ($inside_unsafe:expr, $outside_unsafe:expr) => { unsafe { - //~^ ERROR: this macro expands metavariables in an unsafe block + //~^ macro_metavars_in_unsafe $inside_unsafe; } $outside_unsafe; @@ -144,7 +144,7 @@ macro_rules! multiple_matchers { $( $v; unsafe { - //~^ ERROR: this macro expands metavariables in an unsafe block + //~^ macro_metavars_in_unsafe $x; } );+ @@ -156,11 +156,11 @@ macro_rules! multiple_unsafe_blocks { ($w:expr, $x:expr, $y:expr) => { $w; unsafe { - //~^ ERROR: this macro expands metavariables in an unsafe block + //~^ macro_metavars_in_unsafe $x; } unsafe { - //~^ ERROR: this macro expands metavariables in an unsafe block + //~^ macro_metavars_in_unsafe $x; $y; } @@ -169,7 +169,7 @@ macro_rules! multiple_unsafe_blocks { pub macro macro2_0($v:expr) { unsafe { - //~^ ERROR: this macro expands metavariables in an unsafe block + //~^ macro_metavars_in_unsafe $v; } } @@ -220,7 +220,7 @@ macro_rules! unsafe_from_root_ctxt { macro_rules! nested_macro_helper { ($v:expr) => {{ unsafe { - //~^ ERROR: this macro expands metavariables in an unsafe block + //~^ macro_metavars_in_unsafe $v; } }}; @@ -230,7 +230,7 @@ macro_rules! nested_macro_helper { macro_rules! nested_macros { ($v:expr, $v2:expr) => {{ unsafe { - //~^ ERROR: this macro expands metavariables in an unsafe block + //~^ macro_metavars_in_unsafe nested_macro_helper!($v); $v; } @@ -243,6 +243,7 @@ pub mod issue13219 { ($e:expr) => { // Metavariable in a block tail expression unsafe { $e } + //~^ macro_metavars_in_unsafe }; } pub fn f(p: *const i32) -> i32 { diff --git a/tests/ui-toml/min_ident_chars/min_ident_chars.rs b/tests/ui-toml/min_ident_chars/min_ident_chars.rs index ded3c72c3e04..385e23d69bcd 100644 --- a/tests/ui-toml/min_ident_chars/min_ident_chars.rs +++ b/tests/ui-toml/min_ident_chars/min_ident_chars.rs @@ -4,19 +4,27 @@ extern crate extern_types; use extern_types::{Aaa, LONGER, M, N as W}; +//~^ min_ident_chars pub const N: u32 = 0; +//~^ min_ident_chars pub const LONG: u32 = 32; struct Owo { Uwu: u128, aaa: Aaa, + //~^ min_ident_chars } fn main() { let wha = 1; let vvv = 1; + //~^ min_ident_chars let uuu = 1; + //~^ min_ident_chars let (mut a, mut b) = (1, 2); + //~^ min_ident_chars + //~| min_ident_chars for i in 0..1000 {} + //~^ min_ident_chars } diff --git a/tests/ui-toml/min_ident_chars/min_ident_chars.stderr b/tests/ui-toml/min_ident_chars/min_ident_chars.stderr index 63a057aca279..be795f4daff2 100644 --- a/tests/ui-toml/min_ident_chars/min_ident_chars.stderr +++ b/tests/ui-toml/min_ident_chars/min_ident_chars.stderr @@ -8,43 +8,43 @@ LL | use extern_types::{Aaa, LONGER, M, N as W}; = help: to override `-D warnings` add `#[allow(clippy::min_ident_chars)]` error: this ident is too short (1 <= 3) - --> tests/ui-toml/min_ident_chars/min_ident_chars.rs:8:11 + --> tests/ui-toml/min_ident_chars/min_ident_chars.rs:9:11 | LL | pub const N: u32 = 0; | ^ error: this ident is too short (3 <= 3) - --> tests/ui-toml/min_ident_chars/min_ident_chars.rs:13:5 + --> tests/ui-toml/min_ident_chars/min_ident_chars.rs:15:5 | LL | aaa: Aaa, | ^^^ error: this ident is too short (3 <= 3) - --> tests/ui-toml/min_ident_chars/min_ident_chars.rs:18:9 + --> tests/ui-toml/min_ident_chars/min_ident_chars.rs:21:9 | LL | let vvv = 1; | ^^^ error: this ident is too short (3 <= 3) - --> tests/ui-toml/min_ident_chars/min_ident_chars.rs:19:9 + --> tests/ui-toml/min_ident_chars/min_ident_chars.rs:23:9 | LL | let uuu = 1; | ^^^ error: this ident is too short (1 <= 3) - --> tests/ui-toml/min_ident_chars/min_ident_chars.rs:20:14 + --> tests/ui-toml/min_ident_chars/min_ident_chars.rs:25:14 | LL | let (mut a, mut b) = (1, 2); | ^ error: this ident is too short (1 <= 3) - --> tests/ui-toml/min_ident_chars/min_ident_chars.rs:20:21 + --> tests/ui-toml/min_ident_chars/min_ident_chars.rs:25:21 | LL | let (mut a, mut b) = (1, 2); | ^ error: this ident is too short (1 <= 3) - --> tests/ui-toml/min_ident_chars/min_ident_chars.rs:21:9 + --> tests/ui-toml/min_ident_chars/min_ident_chars.rs:28:9 | LL | for i in 0..1000 {} | ^ diff --git a/tests/ui-toml/min_rust_version/min_rust_version.fixed b/tests/ui-toml/min_rust_version/min_rust_version.fixed index 497f783087a1..685f77b7efe8 100644 --- a/tests/ui-toml/min_rust_version/min_rust_version.fixed +++ b/tests/ui-toml/min_rust_version/min_rust_version.fixed @@ -72,6 +72,7 @@ fn check_index_refutable_slice() { fn map_clone_suggest_copied() { // This should still trigger the lint but suggest `cloned()` instead of `copied()` let _: Option = Some(&16).cloned(); + //~^ map_clone } fn borrow_as_ptr() { diff --git a/tests/ui-toml/min_rust_version/min_rust_version.rs b/tests/ui-toml/min_rust_version/min_rust_version.rs index 6e7874108a34..0bf073af8903 100644 --- a/tests/ui-toml/min_rust_version/min_rust_version.rs +++ b/tests/ui-toml/min_rust_version/min_rust_version.rs @@ -72,6 +72,7 @@ fn check_index_refutable_slice() { fn map_clone_suggest_copied() { // This should still trigger the lint but suggest `cloned()` instead of `copied()` let _: Option = Some(&16).map(|b| *b); + //~^ map_clone } fn borrow_as_ptr() { diff --git a/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.fixed b/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.fixed index a6072111dc06..3e882f496985 100644 --- a/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.fixed +++ b/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.fixed @@ -3,14 +3,20 @@ use std::alloc as colla; use std::option::Option as Maybe; use std::process::{Child as Kid, exit as goodbye}; +//~^ missing_enforced_import_renames use std::thread::sleep as thread_sleep; +//~^ missing_enforced_import_renames #[rustfmt::skip] use std::{ any::{type_name as ident, Any}, + //~^ missing_enforced_import_renames clone as foo, + //~^ missing_enforced_import_renames sync :: Mutex as StdMutie, + //~^ missing_enforced_import_renames }; fn main() { use std::collections::BTreeMap as Map; + //~^ missing_enforced_import_renames } diff --git a/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs b/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs index c2b61aab5b3c..32255af5117f 100644 --- a/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs +++ b/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs @@ -3,14 +3,20 @@ use std::alloc as colla; use std::option::Option as Maybe; use std::process::{Child as Kid, exit as wrong_exit}; +//~^ missing_enforced_import_renames use std::thread::sleep; +//~^ missing_enforced_import_renames #[rustfmt::skip] use std::{ any::{type_name, Any}, + //~^ missing_enforced_import_renames clone, + //~^ missing_enforced_import_renames sync :: Mutex, + //~^ missing_enforced_import_renames }; fn main() { use std::collections::BTreeMap as OopsWrongRename; + //~^ missing_enforced_import_renames } diff --git a/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr b/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr index d3bb07ec47fd..982b144eb872 100644 --- a/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr +++ b/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr @@ -8,31 +8,31 @@ LL | use std::process::{Child as Kid, exit as wrong_exit}; = help: to override `-D warnings` add `#[allow(clippy::missing_enforced_import_renames)]` error: this import should be renamed - --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:6:1 + --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:7:1 | LL | use std::thread::sleep; | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `use std::thread::sleep as thread_sleep` error: this import should be renamed - --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:9:11 + --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:11:11 | LL | any::{type_name, Any}, | ^^^^^^^^^ help: try: `type_name as ident` error: this import should be renamed - --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:10:5 + --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:13:5 | LL | clone, | ^^^^^ help: try: `clone as foo` error: this import should be renamed - --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:11:5 + --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:15:5 | LL | sync :: Mutex, | ^^^^^^^^^^^^^ help: try: `sync :: Mutex as StdMutie` error: this import should be renamed - --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:15:5 + --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:20:5 | LL | use std::collections::BTreeMap as OopsWrongRename; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `use std::collections::BTreeMap as Map` diff --git a/tests/ui-toml/module_inception/module_inception.rs b/tests/ui-toml/module_inception/module_inception.rs index cd495c884a43..94866a7e81bf 100644 --- a/tests/ui-toml/module_inception/module_inception.rs +++ b/tests/ui-toml/module_inception/module_inception.rs @@ -4,11 +4,13 @@ pub mod foo2 { pub mod bar2 { pub mod bar2 { + //~^ module_inception pub mod foo2 {} } pub mod foo2 {} } pub mod foo2 { + //~^ module_inception pub mod bar2 {} } } diff --git a/tests/ui-toml/module_inception/module_inception.stderr b/tests/ui-toml/module_inception/module_inception.stderr index 75e78c829226..efef1d010233 100644 --- a/tests/ui-toml/module_inception/module_inception.stderr +++ b/tests/ui-toml/module_inception/module_inception.stderr @@ -2,6 +2,7 @@ error: module has the same name as its containing module --> tests/ui-toml/module_inception/module_inception.rs:6:9 | LL | / pub mod bar2 { +LL | | LL | | pub mod foo2 {} LL | | } | |_________^ @@ -10,9 +11,10 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::module_inception)]` error: module has the same name as its containing module - --> tests/ui-toml/module_inception/module_inception.rs:11:5 + --> tests/ui-toml/module_inception/module_inception.rs:12:5 | LL | / pub mod foo2 { +LL | | LL | | pub mod bar2 {} LL | | } | |_____^ diff --git a/tests/ui-toml/modulo_arithmetic/modulo_arithmetic.rs b/tests/ui-toml/modulo_arithmetic/modulo_arithmetic.rs index 27d27564baf3..7e42f095cbba 100644 --- a/tests/ui-toml/modulo_arithmetic/modulo_arithmetic.rs +++ b/tests/ui-toml/modulo_arithmetic/modulo_arithmetic.rs @@ -4,7 +4,11 @@ fn main() { let a = -1; let b = 2; let c = a % b == 0; + //~^ modulo_arithmetic let c = a % b != 0; + //~^ modulo_arithmetic let c = 0 == a % b; + //~^ modulo_arithmetic let c = 0 != a % b; + //~^ modulo_arithmetic } diff --git a/tests/ui-toml/modulo_arithmetic/modulo_arithmetic.stderr b/tests/ui-toml/modulo_arithmetic/modulo_arithmetic.stderr index 8d01b66522c6..02286f66f4d1 100644 --- a/tests/ui-toml/modulo_arithmetic/modulo_arithmetic.stderr +++ b/tests/ui-toml/modulo_arithmetic/modulo_arithmetic.stderr @@ -10,7 +10,7 @@ LL | let c = a % b == 0; = help: to override `-D warnings` add `#[allow(clippy::modulo_arithmetic)]` error: you are using modulo operator on types that might have different signs - --> tests/ui-toml/modulo_arithmetic/modulo_arithmetic.rs:7:13 + --> tests/ui-toml/modulo_arithmetic/modulo_arithmetic.rs:8:13 | LL | let c = a % b != 0; | ^^^^^ @@ -19,7 +19,7 @@ LL | let c = a % b != 0; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on types that might have different signs - --> tests/ui-toml/modulo_arithmetic/modulo_arithmetic.rs:8:18 + --> tests/ui-toml/modulo_arithmetic/modulo_arithmetic.rs:10:18 | LL | let c = 0 == a % b; | ^^^^^ @@ -28,7 +28,7 @@ LL | let c = 0 == a % b; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on types that might have different signs - --> tests/ui-toml/modulo_arithmetic/modulo_arithmetic.rs:9:18 + --> tests/ui-toml/modulo_arithmetic/modulo_arithmetic.rs:12:18 | LL | let c = 0 != a % b; | ^^^^^ diff --git a/tests/ui-toml/mut_key/mut_key.rs b/tests/ui-toml/mut_key/mut_key.rs index 3a8e3741e20c..b23c2340b7d6 100644 --- a/tests/ui-toml/mut_key/mut_key.rs +++ b/tests/ui-toml/mut_key/mut_key.rs @@ -1,4 +1,5 @@ //@compile-flags: --crate-name mut_key +//@check-pass #![warn(clippy::mutable_key_type)] diff --git a/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.fixed b/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.fixed index fd20bdff6e25..6b386046efa7 100644 --- a/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.fixed +++ b/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.fixed @@ -4,6 +4,9 @@ fn main() { r#"\aaa"#; r#"\aaa"#; + //~^ needless_raw_string_hashes r#"Hello "world"!"#; + //~^ needless_raw_string_hashes r####" "### "## "# "####; + //~^ needless_raw_string_hashes } diff --git a/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.rs b/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.rs index 3c6c24637006..f928e590d45c 100644 --- a/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.rs +++ b/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.rs @@ -4,6 +4,9 @@ fn main() { r#"\aaa"#; r##"\aaa"##; + //~^ needless_raw_string_hashes r##"Hello "world"!"##; + //~^ needless_raw_string_hashes r######" "### "## "# "######; + //~^ needless_raw_string_hashes } diff --git a/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.stderr b/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.stderr index 421ad66e4c96..43d02837c6cc 100644 --- a/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.stderr +++ b/tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.stderr @@ -13,7 +13,7 @@ LL + r#"\aaa"#; | error: unnecessary hashes around raw string literal - --> tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.rs:7:5 + --> tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.rs:8:5 | LL | r##"Hello "world"!"##; | ^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + r#"Hello "world"!"#; | error: unnecessary hashes around raw string literal - --> tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.rs:8:5 + --> tests/ui-toml/needless_raw_string_hashes_one_allowed/needless_raw_string_hashes.rs:10:5 | LL | r######" "### "## "# "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed b/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed index 673106f0b12d..8da607ec6584 100644 --- a/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed +++ b/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed @@ -16,6 +16,7 @@ proc_macro_derive::foo_bar!(); macro_rules! test { () => { vec![0, 0, 0] + //~^ nonstandard_macro_braces }; } @@ -41,10 +42,15 @@ macro_rules! printlnfoo { #[rustfmt::skip] fn main() { let _ = vec![1, 2, 3]; + //~^ nonstandard_macro_braces let _ = format!("ugh {} stop being such a good compiler", "hello"); + //~^ nonstandard_macro_braces let _ = matches!({}, ()); + //~^ nonstandard_macro_braces let _ = quote!{let x = 1;}; + //~^ nonstandard_macro_braces let _ = quote::quote!{match match match}; + //~^ nonstandard_macro_braces let _ = test!(); // trigger when macro def is inside our own crate let _ = vec![1,2,3]; @@ -54,8 +60,10 @@ fn main() { let _ = test2!["{}{}{}", 1, 2, 3]; let _: type_pos![usize] = vec![]; + //~^ nonstandard_macro_braces eprint!["test if user config overrides defaults"]; + //~^ nonstandard_macro_braces printlnfoo!["test if printlnfoo is triggered by println"]; } diff --git a/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs b/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs index b9c69037be07..e35844a209fa 100644 --- a/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs +++ b/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs @@ -16,6 +16,7 @@ proc_macro_derive::foo_bar!(); macro_rules! test { () => { vec!{0, 0, 0} + //~^ nonstandard_macro_braces }; } @@ -41,10 +42,15 @@ macro_rules! printlnfoo { #[rustfmt::skip] fn main() { let _ = vec! {1, 2, 3}; + //~^ nonstandard_macro_braces let _ = format!["ugh {} stop being such a good compiler", "hello"]; + //~^ nonstandard_macro_braces let _ = matches!{{}, ()}; + //~^ nonstandard_macro_braces let _ = quote!(let x = 1;); + //~^ nonstandard_macro_braces let _ = quote::quote!(match match match); + //~^ nonstandard_macro_braces let _ = test!(); // trigger when macro def is inside our own crate let _ = vec![1,2,3]; @@ -54,8 +60,10 @@ fn main() { let _ = test2!["{}{}{}", 1, 2, 3]; let _: type_pos!(usize) = vec![]; + //~^ nonstandard_macro_braces eprint!("test if user config overrides defaults"); + //~^ nonstandard_macro_braces printlnfoo!["test if printlnfoo is triggered by println"]; } diff --git a/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.stderr b/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.stderr index c2c76e444cfe..fda6addc7aa3 100644 --- a/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.stderr +++ b/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.stderr @@ -1,5 +1,5 @@ error: use of irregular braces for `vec!` macro - --> tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs:43:13 + --> tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs:44:13 | LL | let _ = vec! {1, 2, 3}; | ^^^^^^^^^^^^^^ help: consider writing: `vec![1, 2, 3]` @@ -8,25 +8,25 @@ LL | let _ = vec! {1, 2, 3}; = help: to override `-D warnings` add `#[allow(clippy::nonstandard_macro_braces)]` error: use of irregular braces for `format!` macro - --> tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs:44:13 + --> tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs:46:13 | LL | let _ = format!["ugh {} stop being such a good compiler", "hello"]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `format!("ugh {} stop being such a good compiler", "hello")` error: use of irregular braces for `matches!` macro - --> tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs:45:13 + --> tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs:48:13 | LL | let _ = matches!{{}, ()}; | ^^^^^^^^^^^^^^^^ help: consider writing: `matches!({}, ())` error: use of irregular braces for `quote!` macro - --> tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs:46:13 + --> tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs:50:13 | LL | let _ = quote!(let x = 1;); | ^^^^^^^^^^^^^^^^^^ help: consider writing: `quote!{let x = 1;}` error: use of irregular braces for `quote::quote!` macro - --> tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs:47:13 + --> tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs:52:13 | LL | let _ = quote::quote!(match match match); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `quote::quote!{match match match}` @@ -43,13 +43,13 @@ LL | let _ = test!(); // trigger when macro def is inside our own crate = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) error: use of irregular braces for `type_pos!` macro - --> tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs:56:12 + --> tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs:62:12 | LL | let _: type_pos!(usize) = vec![]; | ^^^^^^^^^^^^^^^^ help: consider writing: `type_pos![usize]` error: use of irregular braces for `eprint!` macro - --> tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs:58:5 + --> tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs:65:5 | LL | eprint!("test if user config overrides defaults"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `eprint!["test if user config overrides defaults"]` diff --git a/tests/ui-toml/panic/panic.rs b/tests/ui-toml/panic/panic.rs index b6264c950e45..7bdc896453d8 100644 --- a/tests/ui-toml/panic/panic.rs +++ b/tests/ui-toml/panic/panic.rs @@ -10,11 +10,13 @@ fn main() { match a { Enam::A => {}, _ => panic!(""), + //~^ panic } } fn issue_13292() { panic_any("should lint") + //~^ panic } #[test] diff --git a/tests/ui-toml/panic/panic.stderr b/tests/ui-toml/panic/panic.stderr index a034207d919f..5dfecfe51ddb 100644 --- a/tests/ui-toml/panic/panic.stderr +++ b/tests/ui-toml/panic/panic.stderr @@ -8,7 +8,7 @@ LL | _ => panic!(""), = help: to override `-D warnings` add `#[allow(clippy::panic)]` error: `panic_any` should not be present in production code - --> tests/ui-toml/panic/panic.rs:17:5 + --> tests/ui-toml/panic/panic.rs:18:5 | LL | panic_any("should lint") | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/path_ends_with_ext/path_ends_with_ext.rs b/tests/ui-toml/path_ends_with_ext/path_ends_with_ext.rs index a34b15f4ac9a..455623cec43e 100644 --- a/tests/ui-toml/path_ends_with_ext/path_ends_with_ext.rs +++ b/tests/ui-toml/path_ends_with_ext/path_ends_with_ext.rs @@ -1,3 +1,5 @@ +//@check-pass + #![warn(clippy::path_ends_with_ext)] use std::path::Path; diff --git a/tests/ui-toml/print_macro/print_macro.rs b/tests/ui-toml/print_macro/print_macro.rs index 3a8b30cca36a..74f3ba7e7fa9 100644 --- a/tests/ui-toml/print_macro/print_macro.rs +++ b/tests/ui-toml/print_macro/print_macro.rs @@ -4,7 +4,9 @@ fn foo(n: u32) { print!("{n}"); + //~^ print_stdout eprint!("{n}"); + //~^ print_stderr } #[test] diff --git a/tests/ui-toml/print_macro/print_macro.stderr b/tests/ui-toml/print_macro/print_macro.stderr index fea11107c7ca..835af7ef8c72 100644 --- a/tests/ui-toml/print_macro/print_macro.stderr +++ b/tests/ui-toml/print_macro/print_macro.stderr @@ -8,7 +8,7 @@ LL | print!("{n}"); = help: to override `-D warnings` add `#[allow(clippy::print_stdout)]` error: use of `eprint!` - --> tests/ui-toml/print_macro/print_macro.rs:7:5 + --> tests/ui-toml/print_macro/print_macro.rs:8:5 | LL | eprint!("{n}"); | ^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs b/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs index cd53f5044599..6a1d2b51abc8 100644 --- a/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs +++ b/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs @@ -11,9 +11,11 @@ mod my_mod { /// some docs pub(crate) fn crate_with_docs() {} pub(crate) fn crate_no_docs() {} + //~^ missing_docs_in_private_items /// some docs pub(super) fn super_with_docs() {} pub(super) fn super_no_docs() {} + //~^ missing_docs_in_private_items mod my_sub { /// some docs @@ -22,6 +24,7 @@ mod my_mod { /// some docs pub(crate) fn sub_crate_with_docs() {} pub(crate) fn sub_crate_no_docs() {} + //~^ missing_docs_in_private_items /// some docs pub(super) fn sub_super_with_docs() {} pub(super) fn sub_super_no_docs() {} @@ -32,15 +35,18 @@ mod my_mod { /// some docs pub(crate) crate_field_with_docs: (), pub(crate) crate_field_no_docs: (), + //~^ missing_docs_in_private_items /// some docs priv_field_with_docs: (), priv_field_no_docs: (), } pub(crate) struct CrateStructNoDocs { + //~^ missing_docs_in_private_items /// some docs pub(crate) crate_field_with_docs: (), pub(crate) crate_field_no_docs: (), + //~^ missing_docs_in_private_items /// some docs priv_field_with_docs: (), priv_field_no_docs: (), @@ -50,6 +56,7 @@ mod my_mod { /// some docs type CrateTypedefWithDocs = String; type CrateTypedefNoDocs = String; +//~^ missing_docs_in_private_items /// some docs pub type PubTypedefWithDocs = String; pub type PubTypedefNoDocs = String; diff --git a/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.stderr b/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.stderr index 9cf79fccb60b..0d70276de42d 100644 --- a/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.stderr +++ b/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.stderr @@ -8,43 +8,43 @@ LL | pub(crate) fn crate_no_docs() {} = help: to override `-D warnings` add `#[allow(clippy::missing_docs_in_private_items)]` error: missing documentation for a function - --> tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs:16:5 + --> tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs:17:5 | LL | pub(super) fn super_no_docs() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs:24:9 + --> tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs:26:9 | LL | pub(crate) fn sub_crate_no_docs() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a struct field - --> tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs:34:9 + --> tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs:37:9 | LL | pub(crate) crate_field_no_docs: (), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a struct - --> tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs:40:5 + --> tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs:44:5 | LL | / pub(crate) struct CrateStructNoDocs { +LL | | LL | | /// some docs LL | | pub(crate) crate_field_with_docs: (), -LL | | pub(crate) crate_field_no_docs: (), ... | LL | | priv_field_no_docs: (), LL | | } | |_____^ error: missing documentation for a struct field - --> tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs:43:9 + --> tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs:48:9 | LL | pub(crate) crate_field_no_docs: (), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a type alias - --> tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs:52:1 + --> tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs:58:1 | LL | type CrateTypedefNoDocs = String; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.all_pub_fields.stderr b/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.all_pub_fields.stderr index dd1035e53fa9..335ff403d062 100644 --- a/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.all_pub_fields.stderr +++ b/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.all_pub_fields.stderr @@ -9,7 +9,7 @@ LL | pub _b: u8, = help: to override `-D warnings` add `#[allow(clippy::pub_underscore_fields)]` error: field marked as public but also inferred as unused because it's prefixed with `_` - --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:23:13 + --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:24:13 | LL | pub(in crate::inner) _f: Option<()>, | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | pub(in crate::inner) _f: Option<()>, = help: consider removing the underscore, or making the field private error: field marked as public but also inferred as unused because it's prefixed with `_` - --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:27:13 + --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:29:13 | LL | pub _g: String, | ^^^^^^ @@ -25,7 +25,7 @@ LL | pub _g: String, = help: consider removing the underscore, or making the field private error: field marked as public but also inferred as unused because it's prefixed with `_` - --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:34:9 + --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:37:9 | LL | pub _a: usize, | ^^^^^^ @@ -33,7 +33,7 @@ LL | pub _a: usize, = help: consider removing the underscore, or making the field private error: field marked as public but also inferred as unused because it's prefixed with `_` - --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:41:9 + --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:45:9 | LL | pub _c: i64, | ^^^^^^ @@ -41,7 +41,7 @@ LL | pub _c: i64, = help: consider removing the underscore, or making the field private error: field marked as public but also inferred as unused because it's prefixed with `_` - --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:44:9 + --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:49:9 | LL | pub _e: Option, | ^^^^^^ @@ -49,7 +49,7 @@ LL | pub _e: Option, = help: consider removing the underscore, or making the field private error: field marked as public but also inferred as unused because it's prefixed with `_` - --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:57:9 + --> tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs:63:9 | LL | pub(crate) _b: Option, | ^^^^^^^^^^^^^ diff --git a/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs b/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs index 4ee8dbb88347..2c1d3cf23647 100644 --- a/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs +++ b/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs @@ -13,6 +13,7 @@ pub mod inner { pub struct PubSuper { pub(super) a: usize, pub _b: u8, + //~^ pub_underscore_fields _c: i32, pub _mark: marker::PhantomData, } @@ -21,10 +22,12 @@ pub mod inner { pub struct PubModVisibility { pub(in crate::inner) e: bool, pub(in crate::inner) _f: Option<()>, + //~[all_pub_fields]^ pub_underscore_fields } struct PrivateStructPubField { pub _g: String, + //~[all_pub_fields]^ pub_underscore_fields } } } @@ -32,6 +35,7 @@ pub mod inner { fn main() { pub struct StructWithOneViolation { pub _a: usize, + //~[all_pub_fields]^ pub_underscore_fields } // should handle structs with multiple violations @@ -39,9 +43,11 @@ fn main() { a: u8, _b: usize, pub _c: i64, + //~[all_pub_fields]^ pub_underscore_fields #[doc(hidden)] pub d: String, pub _e: Option, + //~[all_pub_fields]^ pub_underscore_fields } // shouldn't warn on anonymous fields @@ -55,6 +61,7 @@ fn main() { pub struct PubCrate { pub(crate) a: String, pub(crate) _b: Option, + //~[all_pub_fields]^ pub_underscore_fields } // shouldn't warn on fields named pub diff --git a/tests/ui-toml/renamed_function_params/renamed_function_params.default.stderr b/tests/ui-toml/renamed_function_params/renamed_function_params.default.stderr index de9f17520ff7..7fdaa4420450 100644 --- a/tests/ui-toml/renamed_function_params/renamed_function_params.default.stderr +++ b/tests/ui-toml/renamed_function_params/renamed_function_params.default.stderr @@ -20,13 +20,13 @@ LL | fn foo(&self, i_dont_wanna_use_your_name: u8) {} // only lint in `exten | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using the default name: `val` error: renamed function parameter of trait impl - --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:55:31 + --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:57:31 | LL | fn hash(&self, states: &mut H) { | ^^^^^^ help: consider using the default name: `state` error: renamed function parameters of trait impl - --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:59:30 + --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:61:30 | LL | fn hash_slice(date: &[Self], states: &mut H) { | ^^^^ ^^^^^^ @@ -38,7 +38,7 @@ LL + fn hash_slice(data: &[Self], state: &mut H) { | error: renamed function parameter of trait impl - --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:80:18 + --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:82:18 | LL | fn add(self, b: B) -> C { | ^ help: consider using the default name: `rhs` diff --git a/tests/ui-toml/renamed_function_params/renamed_function_params.extend.stderr b/tests/ui-toml/renamed_function_params/renamed_function_params.extend.stderr index bdc4eeaad80f..d670026b5411 100644 --- a/tests/ui-toml/renamed_function_params/renamed_function_params.extend.stderr +++ b/tests/ui-toml/renamed_function_params/renamed_function_params.extend.stderr @@ -14,13 +14,13 @@ LL | fn ne(&self, rhs: &Self) -> bool { | ^^^ help: consider using the default name: `other` error: renamed function parameter of trait impl - --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:55:31 + --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:57:31 | LL | fn hash(&self, states: &mut H) { | ^^^^^^ help: consider using the default name: `state` error: renamed function parameters of trait impl - --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:59:30 + --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:61:30 | LL | fn hash_slice(date: &[Self], states: &mut H) { | ^^^^ ^^^^^^ diff --git a/tests/ui-toml/renamed_function_params/renamed_function_params.rs b/tests/ui-toml/renamed_function_params/renamed_function_params.rs index f3eb910abbd6..26ca1d860947 100644 --- a/tests/ui-toml/renamed_function_params/renamed_function_params.rs +++ b/tests/ui-toml/renamed_function_params/renamed_function_params.rs @@ -28,11 +28,11 @@ impl std::convert::From for String { } impl PartialEq for B { fn eq(&self, rhs: &Self) -> bool { - //~^ ERROR: renamed function parameter of trait impl + //~^ renamed_function_params self.0 == rhs.0 } fn ne(&self, rhs: &Self) -> bool { - //~^ ERROR: renamed function parameter of trait impl + //~^ renamed_function_params self.0 != rhs.0 } } @@ -46,6 +46,8 @@ trait MyTrait { impl MyTrait for B { fn foo(&self, i_dont_wanna_use_your_name: u8) {} // only lint in `extend` + // + //~[default]^^ renamed_function_params fn bar(_a: u8, _: u8) {} fn baz(self, val: u8) {} fn quz(&self, val: u8) {} @@ -53,11 +55,11 @@ impl MyTrait for B { impl Hash for B { fn hash(&self, states: &mut H) { - //~^ ERROR: renamed function parameter of trait impl + //~^ renamed_function_params self.0.hash(states); } fn hash_slice(date: &[Self], states: &mut H) { - //~^ ERROR: renamed function parameters of trait impl + //~^ renamed_function_params for d in date { d.hash(states); } @@ -78,6 +80,7 @@ enum C { impl std::ops::Add for C { type Output = C; fn add(self, b: B) -> C { + //~[default]^ renamed_function_params // only lint in `extend` C::B(b.0) } diff --git a/tests/ui-toml/replaceable_disallowed_types/clippy.toml b/tests/ui-toml/replaceable_disallowed_types/clippy.toml new file mode 100644 index 000000000000..a08a2f00f506 --- /dev/null +++ b/tests/ui-toml/replaceable_disallowed_types/clippy.toml @@ -0,0 +1,3 @@ +disallowed-types = [ + { path = "std::string::String", replacement = "wrapper::String" }, +] diff --git a/tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.fixed b/tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.fixed new file mode 100644 index 000000000000..f0dab64d78c6 --- /dev/null +++ b/tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.fixed @@ -0,0 +1,17 @@ +#![warn(clippy::disallowed_types)] + +#[allow(clippy::disallowed_types)] +mod wrapper { + pub struct String(std::string::String); + + impl From<&str> for String { + fn from(value: &str) -> Self { + Self(std::string::String::from(value)) + } + } +} + +fn main() { + let _ = wrapper::String::from("x"); + //~^ disallowed_types +} diff --git a/tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.rs b/tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.rs new file mode 100644 index 000000000000..2585e6f90fc4 --- /dev/null +++ b/tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.rs @@ -0,0 +1,17 @@ +#![warn(clippy::disallowed_types)] + +#[allow(clippy::disallowed_types)] +mod wrapper { + pub struct String(std::string::String); + + impl From<&str> for String { + fn from(value: &str) -> Self { + Self(std::string::String::from(value)) + } + } +} + +fn main() { + let _ = String::from("x"); + //~^ disallowed_types +} diff --git a/tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.stderr b/tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.stderr new file mode 100644 index 000000000000..bb63e6970a16 --- /dev/null +++ b/tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.stderr @@ -0,0 +1,11 @@ +error: use of a disallowed type `std::string::String` + --> tests/ui-toml/replaceable_disallowed_types/replaceable_disallowed_types.rs:15:13 + | +LL | let _ = String::from("x"); + | ^^^^^^ help: use: `wrapper::String` + | + = note: `-D clippy::disallowed-types` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::disallowed_types)]` + +error: aborting due to 1 previous error + diff --git a/tests/ui-toml/semicolon_block/both.fixed b/tests/ui-toml/semicolon_block/both.fixed index 306cd23c8239..33f490fad6e8 100644 --- a/tests/ui-toml/semicolon_block/both.fixed +++ b/tests/ui-toml/semicolon_block/both.fixed @@ -40,12 +40,15 @@ fn main() { unsafe { unit_fn_block() }; { unit_fn_block() }; + //~^ semicolon_outside_block unsafe { unit_fn_block() }; + //~^ semicolon_outside_block { unit_fn_block(); }; unsafe { unit_fn_block(); }; { + //~^ semicolon_inside_block unit_fn_block(); unit_fn_block(); } @@ -60,6 +63,7 @@ fn main() { { m!(()) }; { m!(()) }; + //~^ semicolon_outside_block { m!(()); }; m!(0); m!(1); diff --git a/tests/ui-toml/semicolon_block/both.rs b/tests/ui-toml/semicolon_block/both.rs index b9f012cfbb0d..8e650979e6c9 100644 --- a/tests/ui-toml/semicolon_block/both.rs +++ b/tests/ui-toml/semicolon_block/both.rs @@ -40,12 +40,15 @@ fn main() { unsafe { unit_fn_block() }; { unit_fn_block(); } + //~^ semicolon_outside_block unsafe { unit_fn_block(); } + //~^ semicolon_outside_block { unit_fn_block(); }; unsafe { unit_fn_block(); }; { + //~^ semicolon_inside_block unit_fn_block(); unit_fn_block() }; @@ -60,6 +63,7 @@ fn main() { { m!(()) }; { m!(()); } + //~^ semicolon_outside_block { m!(()); }; m!(0); m!(1); diff --git a/tests/ui-toml/semicolon_block/both.stderr b/tests/ui-toml/semicolon_block/both.stderr index 7d7749b282f0..c2aad39b6832 100644 --- a/tests/ui-toml/semicolon_block/both.stderr +++ b/tests/ui-toml/semicolon_block/both.stderr @@ -13,7 +13,7 @@ LL + { unit_fn_block() }; | error: consider moving the `;` outside the block for consistent formatting - --> tests/ui-toml/semicolon_block/both.rs:43:5 + --> tests/ui-toml/semicolon_block/both.rs:44:5 | LL | unsafe { unit_fn_block(); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,9 +25,10 @@ LL + unsafe { unit_fn_block() }; | error: consider moving the `;` inside the block for consistent formatting - --> tests/ui-toml/semicolon_block/both.rs:48:5 + --> tests/ui-toml/semicolon_block/both.rs:50:5 | LL | / { +LL | | LL | | unit_fn_block(); LL | | unit_fn_block() LL | | }; @@ -42,7 +43,7 @@ LL ~ } | error: consider moving the `;` outside the block for consistent formatting - --> tests/ui-toml/semicolon_block/both.rs:62:5 + --> tests/ui-toml/semicolon_block/both.rs:65:5 | LL | { m!(()); } | ^^^^^^^^^^^ diff --git a/tests/ui-toml/semicolon_block/semicolon_inside_block.fixed b/tests/ui-toml/semicolon_block/semicolon_inside_block.fixed index 5b7f8e00c7a0..7b1af090e933 100644 --- a/tests/ui-toml/semicolon_block/semicolon_inside_block.fixed +++ b/tests/ui-toml/semicolon_block/semicolon_inside_block.fixed @@ -45,6 +45,7 @@ fn main() { unsafe { unit_fn_block(); }; { + //~^ semicolon_inside_block unit_fn_block(); unit_fn_block(); } diff --git a/tests/ui-toml/semicolon_block/semicolon_inside_block.rs b/tests/ui-toml/semicolon_block/semicolon_inside_block.rs index 3a81661cd16f..e243d4514da2 100644 --- a/tests/ui-toml/semicolon_block/semicolon_inside_block.rs +++ b/tests/ui-toml/semicolon_block/semicolon_inside_block.rs @@ -45,6 +45,7 @@ fn main() { unsafe { unit_fn_block(); }; { + //~^ semicolon_inside_block unit_fn_block(); unit_fn_block() }; diff --git a/tests/ui-toml/semicolon_block/semicolon_inside_block.stderr b/tests/ui-toml/semicolon_block/semicolon_inside_block.stderr index b1638e40206d..4d4e43f6b9c1 100644 --- a/tests/ui-toml/semicolon_block/semicolon_inside_block.stderr +++ b/tests/ui-toml/semicolon_block/semicolon_inside_block.stderr @@ -2,6 +2,7 @@ error: consider moving the `;` inside the block for consistent formatting --> tests/ui-toml/semicolon_block/semicolon_inside_block.rs:47:5 | LL | / { +LL | | LL | | unit_fn_block(); LL | | unit_fn_block() LL | | }; diff --git a/tests/ui-toml/semicolon_block/semicolon_outside_block.fixed b/tests/ui-toml/semicolon_block/semicolon_outside_block.fixed index 14604eaea7e4..f6aa49fc8868 100644 --- a/tests/ui-toml/semicolon_block/semicolon_outside_block.fixed +++ b/tests/ui-toml/semicolon_block/semicolon_outside_block.fixed @@ -39,7 +39,9 @@ fn main() { unsafe { unit_fn_block() }; { unit_fn_block() }; + //~^ semicolon_outside_block unsafe { unit_fn_block() }; + //~^ semicolon_outside_block { unit_fn_block(); }; unsafe { unit_fn_block(); }; @@ -59,6 +61,7 @@ fn main() { { m!(()) }; { m!(()) }; + //~^ semicolon_outside_block { m!(()); }; m!(0); m!(1); diff --git a/tests/ui-toml/semicolon_block/semicolon_outside_block.rs b/tests/ui-toml/semicolon_block/semicolon_outside_block.rs index c767201469ab..0d25a29627fb 100644 --- a/tests/ui-toml/semicolon_block/semicolon_outside_block.rs +++ b/tests/ui-toml/semicolon_block/semicolon_outside_block.rs @@ -39,7 +39,9 @@ fn main() { unsafe { unit_fn_block() }; { unit_fn_block(); } + //~^ semicolon_outside_block unsafe { unit_fn_block(); } + //~^ semicolon_outside_block { unit_fn_block(); }; unsafe { unit_fn_block(); }; @@ -59,6 +61,7 @@ fn main() { { m!(()) }; { m!(()); } + //~^ semicolon_outside_block { m!(()); }; m!(0); m!(1); diff --git a/tests/ui-toml/semicolon_block/semicolon_outside_block.stderr b/tests/ui-toml/semicolon_block/semicolon_outside_block.stderr index 7bcb63a6abbb..18400da07a89 100644 --- a/tests/ui-toml/semicolon_block/semicolon_outside_block.stderr +++ b/tests/ui-toml/semicolon_block/semicolon_outside_block.stderr @@ -13,7 +13,7 @@ LL + { unit_fn_block() }; | error: consider moving the `;` outside the block for consistent formatting - --> tests/ui-toml/semicolon_block/semicolon_outside_block.rs:42:5 + --> tests/ui-toml/semicolon_block/semicolon_outside_block.rs:43:5 | LL | unsafe { unit_fn_block(); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + unsafe { unit_fn_block() }; | error: consider moving the `;` outside the block for consistent formatting - --> tests/ui-toml/semicolon_block/semicolon_outside_block.rs:61:5 + --> tests/ui-toml/semicolon_block/semicolon_outside_block.rs:63:5 | LL | { m!(()); } | ^^^^^^^^^^^ diff --git a/tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs b/tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs index 90c2439dc34f..08a8e1186d5c 100644 --- a/tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs +++ b/tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs @@ -9,6 +9,7 @@ pub struct NoGeneric { } unsafe impl Send for NoGeneric {} +//~^ non_send_fields_in_send_ty pub struct MultiField { field1: T, @@ -17,6 +18,7 @@ pub struct MultiField { } unsafe impl Send for MultiField {} +//~^ non_send_fields_in_send_ty pub enum MyOption { MySome(T), @@ -24,6 +26,7 @@ pub enum MyOption { } unsafe impl Send for MyOption {} +//~^ non_send_fields_in_send_ty // All fields are disallowed when raw pointer heuristic is off extern "C" { @@ -39,5 +42,6 @@ pub struct HeuristicTest { } unsafe impl Send for HeuristicTest {} +//~^ non_send_fields_in_send_ty fn main() {} diff --git a/tests/ui-toml/strict_non_send_fields_in_send_ty/test.stderr b/tests/ui-toml/strict_non_send_fields_in_send_ty/test.stderr index bd1b75458fd1..cdb4a2f44513 100644 --- a/tests/ui-toml/strict_non_send_fields_in_send_ty/test.stderr +++ b/tests/ui-toml/strict_non_send_fields_in_send_ty/test.stderr @@ -14,75 +14,75 @@ LL | rc_is_not_send: Rc, = help: to override `-D warnings` add `#[allow(clippy::non_send_fields_in_send_ty)]` error: some fields in `MultiField` are not safe to be sent to another thread - --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:19:1 + --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:20:1 | LL | unsafe impl Send for MultiField {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: it is not safe to send field `field1` to another thread - --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:14:5 + --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:15:5 | LL | field1: T, | ^^^^^^^^^ = help: add `T: Send` bound in `Send` impl note: it is not safe to send field `field2` to another thread - --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:15:5 + --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:16:5 | LL | field2: T, | ^^^^^^^^^ = help: add `T: Send` bound in `Send` impl note: it is not safe to send field `field3` to another thread - --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:16:5 + --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:17:5 | LL | field3: T, | ^^^^^^^^^ = help: add `T: Send` bound in `Send` impl error: some fields in `MyOption` are not safe to be sent to another thread - --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:26:1 + --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:28:1 | LL | unsafe impl Send for MyOption {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: it is not safe to send field `0` to another thread - --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:22:12 + --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:24:12 | LL | MySome(T), | ^ = help: add `T: Send` bound in `Send` impl error: some fields in `HeuristicTest` are not safe to be sent to another thread - --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:41:1 + --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:44:1 | LL | unsafe impl Send for HeuristicTest {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: it is not safe to send field `field1` to another thread - --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:34:5 + --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:37:5 | LL | field1: Vec<*const NonSend>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: use a thread-safe type that implements `Send` note: it is not safe to send field `field2` to another thread - --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:35:5 + --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:38:5 | LL | field2: [*const NonSend; 3], | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: use a thread-safe type that implements `Send` note: it is not safe to send field `field3` to another thread - --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:36:5 + --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:39:5 | LL | field3: (*const NonSend, *const NonSend, *const NonSend), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: use a thread-safe type that implements `Send` note: it is not safe to send field `field4` to another thread - --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:37:5 + --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:40:5 | LL | field4: (*const NonSend, Rc), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: use a thread-safe type that implements `Send` note: it is not safe to send field `field5` to another thread - --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:38:5 + --> tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs:41:5 | LL | field5: Vec>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/struct_excessive_bools/test.rs b/tests/ui-toml/struct_excessive_bools/test.rs index 32dd80246fab..590cd6eeaa47 100644 --- a/tests/ui-toml/struct_excessive_bools/test.rs +++ b/tests/ui-toml/struct_excessive_bools/test.rs @@ -1,6 +1,7 @@ #![warn(clippy::struct_excessive_bools)] struct S { + //~^ struct_excessive_bools a: bool, } diff --git a/tests/ui-toml/struct_excessive_bools/test.stderr b/tests/ui-toml/struct_excessive_bools/test.stderr index ddf8ec0e5217..d70c76055df8 100644 --- a/tests/ui-toml/struct_excessive_bools/test.stderr +++ b/tests/ui-toml/struct_excessive_bools/test.stderr @@ -2,6 +2,7 @@ error: more than 0 bools in a struct --> tests/ui-toml/struct_excessive_bools/test.rs:3:1 | LL | / struct S { +LL | | LL | | a: bool, LL | | } | |_^ diff --git a/tests/ui-toml/suppress_lint_in_const/test.rs b/tests/ui-toml/suppress_lint_in_const/test.rs index 4613a74b85d8..b077b848837a 100644 --- a/tests/ui-toml/suppress_lint_in_const/test.rs +++ b/tests/ui-toml/suppress_lint_in_const/test.rs @@ -25,6 +25,7 @@ fn main() { let x = [1, 2, 3, 4]; let index: usize = 1; x[index]; + //~^ indexing_slicing x[4]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays. x[1 << 3]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays. @@ -40,15 +41,20 @@ fn main() { let v = vec![0; 5]; v[0]; + //~^ indexing_slicing v[10]; + //~^ indexing_slicing v[1 << 3]; + //~^ indexing_slicing const N: usize = 15; // Out of bounds const M: usize = 3; // In bounds x[N]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays. x[M]; // Ok, should not produce stderr. v[N]; + //~^ indexing_slicing v[M]; + //~^ indexing_slicing } /// An opaque integer representation diff --git a/tests/ui-toml/suppress_lint_in_const/test.stderr b/tests/ui-toml/suppress_lint_in_const/test.stderr index 120f5c35cb03..4c78a6b924cf 100644 --- a/tests/ui-toml/suppress_lint_in_const/test.stderr +++ b/tests/ui-toml/suppress_lint_in_const/test.stderr @@ -9,7 +9,7 @@ LL | x[index]; = help: to override `-D warnings` add `#[allow(clippy::indexing_slicing)]` error: indexing may panic - --> tests/ui-toml/suppress_lint_in_const/test.rs:42:5 + --> tests/ui-toml/suppress_lint_in_const/test.rs:43:5 | LL | v[0]; | ^^^^ @@ -17,7 +17,7 @@ LL | v[0]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> tests/ui-toml/suppress_lint_in_const/test.rs:43:5 + --> tests/ui-toml/suppress_lint_in_const/test.rs:45:5 | LL | v[10]; | ^^^^^ @@ -25,7 +25,7 @@ LL | v[10]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> tests/ui-toml/suppress_lint_in_const/test.rs:44:5 + --> tests/ui-toml/suppress_lint_in_const/test.rs:47:5 | LL | v[1 << 3]; | ^^^^^^^^^ @@ -33,7 +33,7 @@ LL | v[1 << 3]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> tests/ui-toml/suppress_lint_in_const/test.rs:50:5 + --> tests/ui-toml/suppress_lint_in_const/test.rs:54:5 | LL | v[N]; | ^^^^ @@ -41,7 +41,7 @@ LL | v[N]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> tests/ui-toml/suppress_lint_in_const/test.rs:51:5 + --> tests/ui-toml/suppress_lint_in_const/test.rs:56:5 | LL | v[M]; | ^^^^ diff --git a/tests/ui-toml/toml_disallow/conf_french_disallowed_name.rs b/tests/ui-toml/toml_disallow/conf_french_disallowed_name.rs index 2f86b3eda4c5..6555e4291959 100644 --- a/tests/ui-toml/toml_disallow/conf_french_disallowed_name.rs +++ b/tests/ui-toml/toml_disallow/conf_french_disallowed_name.rs @@ -4,17 +4,24 @@ #![warn(clippy::disallowed_names)] fn test(toto: ()) {} +//~^ disallowed_names fn main() { let toto = 42; + //~^ disallowed_names let tata = 42; + //~^ disallowed_names let titi = 42; + //~^ disallowed_names let tatab = 42; let tatatataic = 42; match (42, Some(1337), Some(0)) { (toto, Some(tata), titi @ Some(_)) => (), + //~^ disallowed_names + //~| disallowed_names + //~| disallowed_names _ => (), } } diff --git a/tests/ui-toml/toml_disallow/conf_french_disallowed_name.stderr b/tests/ui-toml/toml_disallow/conf_french_disallowed_name.stderr index 6cd0f9b0d7cb..9096ffca2796 100644 --- a/tests/ui-toml/toml_disallow/conf_french_disallowed_name.stderr +++ b/tests/ui-toml/toml_disallow/conf_french_disallowed_name.stderr @@ -8,37 +8,37 @@ LL | fn test(toto: ()) {} = help: to override `-D warnings` add `#[allow(clippy::disallowed_names)]` error: use of a disallowed/placeholder name `toto` - --> tests/ui-toml/toml_disallow/conf_french_disallowed_name.rs:9:9 + --> tests/ui-toml/toml_disallow/conf_french_disallowed_name.rs:10:9 | LL | let toto = 42; | ^^^^ error: use of a disallowed/placeholder name `tata` - --> tests/ui-toml/toml_disallow/conf_french_disallowed_name.rs:10:9 + --> tests/ui-toml/toml_disallow/conf_french_disallowed_name.rs:12:9 | LL | let tata = 42; | ^^^^ error: use of a disallowed/placeholder name `titi` - --> tests/ui-toml/toml_disallow/conf_french_disallowed_name.rs:11:9 + --> tests/ui-toml/toml_disallow/conf_french_disallowed_name.rs:14:9 | LL | let titi = 42; | ^^^^ error: use of a disallowed/placeholder name `toto` - --> tests/ui-toml/toml_disallow/conf_french_disallowed_name.rs:17:10 + --> tests/ui-toml/toml_disallow/conf_french_disallowed_name.rs:21:10 | LL | (toto, Some(tata), titi @ Some(_)) => (), | ^^^^ error: use of a disallowed/placeholder name `tata` - --> tests/ui-toml/toml_disallow/conf_french_disallowed_name.rs:17:21 + --> tests/ui-toml/toml_disallow/conf_french_disallowed_name.rs:21:21 | LL | (toto, Some(tata), titi @ Some(_)) => (), | ^^^^ error: use of a disallowed/placeholder name `titi` - --> tests/ui-toml/toml_disallow/conf_french_disallowed_name.rs:17:28 + --> tests/ui-toml/toml_disallow/conf_french_disallowed_name.rs:21:28 | LL | (toto, Some(tata), titi @ Some(_)) => (), | ^^^^ diff --git a/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs b/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs index 17fceae01780..dd170d6baf85 100644 --- a/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs +++ b/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs @@ -1,5 +1,3 @@ -//@compile-flags: --crate-name conf_disallowed_methods - #![allow(clippy::needless_raw_strings)] #![warn(clippy::disallowed_methods)] #![allow(clippy::useless_vec)] @@ -33,30 +31,44 @@ mod local_mod { fn main() { let re = Regex::new(r"ab.*c").unwrap(); + //~^ disallowed_methods re.is_match("abc"); + //~^ disallowed_methods let mut a = vec![1, 2, 3, 4]; a.iter().sum::(); + //~^ disallowed_methods a.sort_unstable(); + //~^ disallowed_methods // FIXME(f16_f128): add a clamp test once the function is available let _ = 2.0f32.clamp(3.0f32, 4.0f32); + //~^ disallowed_methods let _ = 2.0f64.clamp(3.0f64, 4.0f64); let indirect: fn(&str) -> Result = Regex::new; + //~^ disallowed_methods let re = indirect(".").unwrap(); let in_call = Box::new(f32::clamp); + //~^ disallowed_methods let in_method_call = ["^", "$"].into_iter().map(Regex::new); + //~^ disallowed_methods // resolve ambiguity between `futures::stream::select_all` the module and the function let same_name_as_module = select_all(vec![empty::<()>()]); + //~^ disallowed_methods local_fn(); + //~^ disallowed_methods local_mod::f(); + //~^ disallowed_methods let s = Struct; s.method(); + //~^ disallowed_methods s.provided_method(); + //~^ disallowed_methods s.implemented_method(); + //~^ disallowed_methods } diff --git a/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr b/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr index e77b2b959497..f7dda81eb936 100644 --- a/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr +++ b/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr @@ -1,5 +1,5 @@ error: use of a disallowed method `regex::Regex::new` - --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:35:14 + --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:33:14 | LL | let re = Regex::new(r"ab.*c").unwrap(); | ^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let re = Regex::new(r"ab.*c").unwrap(); = help: to override `-D warnings` add `#[allow(clippy::disallowed_methods)]` error: use of a disallowed method `regex::Regex::is_match` - --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:36:8 + --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:35:8 | LL | re.is_match("abc"); | ^^^^^^^^ @@ -22,67 +22,67 @@ LL | a.iter().sum::(); | ^^^ error: use of a disallowed method `slice::sort_unstable` - --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:41:7 + --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:42:7 | LL | a.sort_unstable(); | ^^^^^^^^^^^^^ error: use of a disallowed method `f32::clamp` - --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:44:20 + --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:46:20 | LL | let _ = 2.0f32.clamp(3.0f32, 4.0f32); | ^^^^^ error: use of a disallowed method `regex::Regex::new` - --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:47:61 + --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:50:61 | LL | let indirect: fn(&str) -> Result = Regex::new; | ^^^^^^^^^^ error: use of a disallowed method `f32::clamp` - --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:50:28 + --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:54:28 | LL | let in_call = Box::new(f32::clamp); | ^^^^^^^^^^ error: use of a disallowed method `regex::Regex::new` - --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:51:53 + --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:56:53 | LL | let in_method_call = ["^", "$"].into_iter().map(Regex::new); | ^^^^^^^^^^ error: use of a disallowed method `futures::stream::select_all` - --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:54:31 + --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:60:31 | LL | let same_name_as_module = select_all(vec![empty::<()>()]); | ^^^^^^^^^^ error: use of a disallowed method `conf_disallowed_methods::local_fn` - --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:56:5 + --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:63:5 | LL | local_fn(); | ^^^^^^^^ error: use of a disallowed method `conf_disallowed_methods::local_mod::f` - --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:57:5 + --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:65:5 | LL | local_mod::f(); | ^^^^^^^^^^^^ error: use of a disallowed method `conf_disallowed_methods::Struct::method` - --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:59:7 + --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:68:7 | LL | s.method(); | ^^^^^^ error: use of a disallowed method `conf_disallowed_methods::Trait::provided_method` - --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:60:7 + --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:70:7 | LL | s.provided_method(); | ^^^^^^^^^^^^^^^ error: use of a disallowed method `conf_disallowed_methods::Trait::implemented_method` - --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:61:7 + --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:72:7 | LL | s.implemented_method(); | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs b/tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs index f02bd07cfe7b..82c9abe8beb4 100644 --- a/tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs +++ b/tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs @@ -5,40 +5,61 @@ extern crate syn; use std::sync as foo; use std::sync::atomic::AtomicU32; +//~^ disallowed_types use std::time::Instant as Sneaky; +//~^ disallowed_types struct HashMap; fn bad_return_type() -> fn() -> Sneaky { + //~^ disallowed_types todo!() } fn bad_arg_type(_: impl Fn(Sneaky) -> foo::atomic::AtomicU32) {} +//~^ disallowed_types +//~| disallowed_types fn trait_obj(_: &dyn std::io::Read) {} +//~^ disallowed_types fn full_and_single_path_prim(_: usize, _: bool) {} +//~^ disallowed_types +//~| disallowed_types fn const_generics() {} +//~^ disallowed_types struct GenArg([u8; U]); +//~^ disallowed_types static BAD: foo::atomic::AtomicPtr<()> = foo::atomic::AtomicPtr::new(std::ptr::null_mut()); fn ip(_: std::net::Ipv4Addr) {} +//~^ disallowed_types fn listener(_: std::net::TcpListener) {} +//~^ disallowed_types #[allow(clippy::diverging_sub_expression)] fn main() { let _: std::collections::HashMap<(), ()> = std::collections::HashMap::new(); + //~^ disallowed_types + //~| disallowed_types let _ = Sneaky::now(); + //~^ disallowed_types let _ = foo::atomic::AtomicU32::new(0); + //~^ disallowed_types static FOO: std::sync::atomic::AtomicU32 = foo::atomic::AtomicU32::new(1); + //~^ disallowed_types + //~| disallowed_types let _: std::collections::BTreeMap<(), syn::TypePath> = Default::default(); + //~^ disallowed_types let _ = syn::Ident::new("", todo!()); + //~^ disallowed_types let _ = HashMap; let _: usize = 64_usize; + //~^ disallowed_types } mod useless_attribute { diff --git a/tests/ui-toml/toml_disallowed_types/conf_disallowed_types.stderr b/tests/ui-toml/toml_disallowed_types/conf_disallowed_types.stderr index 322cde15526a..18bc36ca1e33 100644 --- a/tests/ui-toml/toml_disallowed_types/conf_disallowed_types.stderr +++ b/tests/ui-toml/toml_disallowed_types/conf_disallowed_types.stderr @@ -8,61 +8,61 @@ LL | use std::sync::atomic::AtomicU32; = help: to override `-D warnings` add `#[allow(clippy::disallowed_types)]` error: use of a disallowed type `std::time::Instant` - --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:8:1 + --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:9:1 | LL | use std::time::Instant as Sneaky; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of a disallowed type `std::time::Instant` - --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:12:33 + --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:14:33 | LL | fn bad_return_type() -> fn() -> Sneaky { | ^^^^^^ error: use of a disallowed type `std::time::Instant` - --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:16:28 + --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:19:28 | LL | fn bad_arg_type(_: impl Fn(Sneaky) -> foo::atomic::AtomicU32) {} | ^^^^^^ error: use of a disallowed type `std::sync::atomic::AtomicU32` - --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:16:39 + --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:19:39 | LL | fn bad_arg_type(_: impl Fn(Sneaky) -> foo::atomic::AtomicU32) {} | ^^^^^^^^^^^^^^^^^^^^^^ error: use of a disallowed type `std::io::Read` - --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:18:22 + --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:23:22 | LL | fn trait_obj(_: &dyn std::io::Read) {} | ^^^^^^^^^^^^^ error: use of a disallowed type `std::primitive::usize` - --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:20:33 + --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:26:33 | LL | fn full_and_single_path_prim(_: usize, _: bool) {} | ^^^^^ error: use of a disallowed type `bool` - --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:20:43 + --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:26:43 | LL | fn full_and_single_path_prim(_: usize, _: bool) {} | ^^^^ error: use of a disallowed type `std::primitive::usize` - --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:22:28 + --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:30:28 | LL | fn const_generics() {} | ^^^^^ error: use of a disallowed type `std::primitive::usize` - --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:24:24 + --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:33:24 | LL | struct GenArg([u8; U]); | ^^^^^ error: use of a disallowed type `std::net::Ipv4Addr` - --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:28:10 + --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:38:10 | LL | fn ip(_: std::net::Ipv4Addr) {} | ^^^^^^^^^^^^^^^^^^ @@ -70,61 +70,61 @@ LL | fn ip(_: std::net::Ipv4Addr) {} = note: no IPv4 allowed error: use of a disallowed type `std::net::TcpListener` - --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:30:16 + --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:41:16 | LL | fn listener(_: std::net::TcpListener) {} | ^^^^^^^^^^^^^^^^^^^^^ error: use of a disallowed type `std::collections::HashMap` - --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:34:48 + --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:46:48 | LL | let _: std::collections::HashMap<(), ()> = std::collections::HashMap::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of a disallowed type `std::collections::HashMap` - --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:34:12 + --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:46:12 | LL | let _: std::collections::HashMap<(), ()> = std::collections::HashMap::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of a disallowed type `std::time::Instant` - --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:35:13 + --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:49:13 | LL | let _ = Sneaky::now(); | ^^^^^^ error: use of a disallowed type `std::sync::atomic::AtomicU32` - --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:36:13 + --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:51:13 | LL | let _ = foo::atomic::AtomicU32::new(0); | ^^^^^^^^^^^^^^^^^^^^^^ error: use of a disallowed type `std::sync::atomic::AtomicU32` - --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:37:17 + --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:53:17 | LL | static FOO: std::sync::atomic::AtomicU32 = foo::atomic::AtomicU32::new(1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of a disallowed type `std::sync::atomic::AtomicU32` - --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:37:48 + --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:53:48 | LL | static FOO: std::sync::atomic::AtomicU32 = foo::atomic::AtomicU32::new(1); | ^^^^^^^^^^^^^^^^^^^^^^ error: use of a disallowed type `syn::TypePath` - --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:38:43 + --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:56:43 | LL | let _: std::collections::BTreeMap<(), syn::TypePath> = Default::default(); | ^^^^^^^^^^^^^ error: use of a disallowed type `proc_macro2::Ident` - --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:39:13 + --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:58:13 | LL | let _ = syn::Ident::new("", todo!()); | ^^^^^^^^^^ error: use of a disallowed type `std::primitive::usize` - --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:41:12 + --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:61:12 | LL | let _: usize = 64_usize; | ^^^^^ diff --git a/tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.fixed b/tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.fixed index 8092e40ff9f1..d44f5fb84bd5 100644 --- a/tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.fixed +++ b/tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.fixed @@ -16,9 +16,11 @@ fn main() { let z = 1; Foo { x, y, z: z }; + //~^ inconsistent_struct_constructor Foo { x, + //~^ inconsistent_struct_constructor z: z, ..Default::default() }; @@ -35,6 +37,7 @@ mod field_attributes { BodyVisitor { macro_unsafe_blocks: Vec::new(), #[expect(clippy::bool_to_int_with_if)] // obfuscates the meaning + //~^ inconsistent_struct_constructor expn_depth: if condition { 1 } else { 0 }, }; } @@ -53,6 +56,7 @@ mod cfgs_between_fields { } let s = S { a: 3, + //~^ inconsistent_struct_constructor b: 2, #[cfg(all())] c: 1, @@ -70,6 +74,7 @@ mod cfgs_between_fields { } let s = S { a: 3, + //~^ inconsistent_struct_constructor #[cfg(any())] c: 1, b: 2, diff --git a/tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.rs b/tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.rs index cd1aff966528..77ac2b4e7c11 100644 --- a/tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.rs +++ b/tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.rs @@ -16,9 +16,11 @@ fn main() { let z = 1; Foo { y, x, z: z }; + //~^ inconsistent_struct_constructor Foo { z: z, + //~^ inconsistent_struct_constructor x, ..Default::default() }; @@ -34,6 +36,7 @@ mod field_attributes { fn check_body(condition: bool) { BodyVisitor { #[expect(clippy::bool_to_int_with_if)] // obfuscates the meaning + //~^ inconsistent_struct_constructor expn_depth: if condition { 1 } else { 0 }, macro_unsafe_blocks: Vec::new(), }; @@ -53,6 +56,7 @@ mod cfgs_between_fields { } let s = S { d: 0, + //~^ inconsistent_struct_constructor #[cfg(all())] c: 1, b: 2, @@ -70,6 +74,7 @@ mod cfgs_between_fields { } let s = S { d: 0, + //~^ inconsistent_struct_constructor #[cfg(any())] c: 1, b: 2, diff --git a/tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.stderr b/tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.stderr index d2533960b84c..be85fa574480 100644 --- a/tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.stderr +++ b/tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.stderr @@ -8,22 +8,25 @@ LL | Foo { y, x, z: z }; = help: to override `-D warnings` add `#[allow(clippy::inconsistent_struct_constructor)]` error: struct constructor field order is inconsistent with struct definition field order - --> tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.rs:21:9 + --> tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.rs:22:9 | LL | / z: z, +LL | | LL | | x, | |_________^ | help: if the field evaluation order doesn't matter, try | LL ~ x, +LL + LL ~ z: z, | error: struct constructor field order is inconsistent with struct definition field order - --> tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.rs:36:13 + --> tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.rs:38:13 | LL | / #[expect(clippy::bool_to_int_with_if)] // obfuscates the meaning +LL | | LL | | expn_depth: if condition { 1 } else { 0 }, LL | | macro_unsafe_blocks: Vec::new(), | |___________________________________________^ @@ -32,13 +35,15 @@ help: if the field evaluation order doesn't matter, try | LL ~ macro_unsafe_blocks: Vec::new(), LL + #[expect(clippy::bool_to_int_with_if)] // obfuscates the meaning +LL + LL ~ expn_depth: if condition { 1 } else { 0 }, | error: struct constructor field order is inconsistent with struct definition field order - --> tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.rs:55:13 + --> tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.rs:58:13 | LL | / d: 0, +LL | | LL | | #[cfg(all())] LL | | c: 1, LL | | b: 2, @@ -48,6 +53,7 @@ LL | | a: 3, help: if the field evaluation order doesn't matter, try | LL ~ a: 3, +LL + LL + b: 2, LL + #[cfg(all())] LL + c: 1, @@ -55,9 +61,10 @@ LL ~ d: 0, | error: struct constructor field order is inconsistent with struct definition field order - --> tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.rs:72:13 + --> tests/ui-toml/toml_inconsistent_struct_constructor/conf_inconsistent_struct_constructor.rs:76:13 | LL | / d: 0, +LL | | LL | | #[cfg(any())] LL | | c: 1, LL | | b: 2, @@ -67,6 +74,7 @@ LL | | a: 3, help: if the field evaluation order doesn't matter, try | LL ~ a: 3, +LL + LL + #[cfg(any())] LL + c: 1, LL + b: 2, diff --git a/tests/ui-toml/toml_replaceable_disallowed_methods/clippy.toml b/tests/ui-toml/toml_replaceable_disallowed_methods/clippy.toml new file mode 100644 index 000000000000..dc393f1355b5 --- /dev/null +++ b/tests/ui-toml/toml_replaceable_disallowed_methods/clippy.toml @@ -0,0 +1,4 @@ +disallowed-methods = [ + { path = "replaceable_disallowed_methods::bad", replacement = "good" }, + { path = "replaceable_disallowed_methods::questionable", replacement = "good", reason = "a better function exists" }, +] diff --git a/tests/ui-toml/toml_replaceable_disallowed_methods/replaceable_disallowed_methods.fixed b/tests/ui-toml/toml_replaceable_disallowed_methods/replaceable_disallowed_methods.fixed new file mode 100644 index 000000000000..df28e0bc94be --- /dev/null +++ b/tests/ui-toml/toml_replaceable_disallowed_methods/replaceable_disallowed_methods.fixed @@ -0,0 +1,10 @@ +fn bad() {} +fn questionable() {} +fn good() {} + +fn main() { + good(); + //~^ disallowed_methods + good(); + //~^ disallowed_methods +} diff --git a/tests/ui-toml/toml_replaceable_disallowed_methods/replaceable_disallowed_methods.rs b/tests/ui-toml/toml_replaceable_disallowed_methods/replaceable_disallowed_methods.rs new file mode 100644 index 000000000000..9257f0e3e1a7 --- /dev/null +++ b/tests/ui-toml/toml_replaceable_disallowed_methods/replaceable_disallowed_methods.rs @@ -0,0 +1,10 @@ +fn bad() {} +fn questionable() {} +fn good() {} + +fn main() { + bad(); + //~^ disallowed_methods + questionable(); + //~^ disallowed_methods +} diff --git a/tests/ui-toml/toml_replaceable_disallowed_methods/replaceable_disallowed_methods.stderr b/tests/ui-toml/toml_replaceable_disallowed_methods/replaceable_disallowed_methods.stderr new file mode 100644 index 000000000000..6f70b4ae6a9e --- /dev/null +++ b/tests/ui-toml/toml_replaceable_disallowed_methods/replaceable_disallowed_methods.stderr @@ -0,0 +1,17 @@ +error: use of a disallowed method `replaceable_disallowed_methods::bad` + --> tests/ui-toml/toml_replaceable_disallowed_methods/replaceable_disallowed_methods.rs:6:5 + | +LL | bad(); + | ^^^ help: use: `good` + | + = note: `-D clippy::disallowed-methods` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::disallowed_methods)]` + +error: use of a disallowed method `replaceable_disallowed_methods::questionable` + --> tests/ui-toml/toml_replaceable_disallowed_methods/replaceable_disallowed_methods.rs:8:5 + | +LL | questionable(); + | ^^^^^^^^^^^^ help: a better function exists: `good` + +error: aborting due to 2 previous errors + diff --git a/tests/ui-toml/toml_trivially_copy/test.rs b/tests/ui-toml/toml_trivially_copy/test.rs index 145a2ce441d3..46f21eef9740 100644 --- a/tests/ui-toml/toml_trivially_copy/test.rs +++ b/tests/ui-toml/toml_trivially_copy/test.rs @@ -13,6 +13,8 @@ struct Bar(u32); fn good(a: &mut u32, b: u32, c: &Bar, d: &u32) {} fn bad(x: &u16, y: &Foo) {} +//~^ trivially_copy_pass_by_ref +//~| trivially_copy_pass_by_ref fn main() { let (mut a, b, c, d, x, y) = (0, 0, Bar(0), 0, 0, Foo(0)); diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs b/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs index 49139b60a9f4..8d02924c9d93 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs @@ -1,4 +1,6 @@ //@no-rustfix -//@error-in-other-file: unknown field `foobar`, expected one of +//@error-in-other-file: unknown field +//@error-in-other-file: error reading Clippy +//@error-in-other-file: error reading Clippy fn main() {} diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index 01e9f5c26a37..acfe739277cc 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -5,6 +5,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect accept-comment-above-statement allow-comparison-to-zero allow-dbg-in-tests + allow-expect-in-consts allow-expect-in-tests allow-indexing-slicing-in-tests allow-mixed-uninlined-format-args @@ -13,6 +14,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect allow-print-in-tests allow-private-module-inception allow-renamed-params-for + allow-unwrap-in-consts allow-unwrap-in-tests allow-useless-vec-in-tests allowed-dotfiles @@ -29,6 +31,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect await-holding-invalid-types blacklisted-names cargo-ignore-publish + check-incompatible-msrv-in-tests check-private-items cognitive-complexity-threshold cyclomatic-complexity-threshold @@ -94,6 +97,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect accept-comment-above-statement allow-comparison-to-zero allow-dbg-in-tests + allow-expect-in-consts allow-expect-in-tests allow-indexing-slicing-in-tests allow-mixed-uninlined-format-args @@ -102,6 +106,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect allow-print-in-tests allow-private-module-inception allow-renamed-params-for + allow-unwrap-in-consts allow-unwrap-in-tests allow-useless-vec-in-tests allowed-dotfiles @@ -118,6 +123,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect await-holding-invalid-types blacklisted-names cargo-ignore-publish + check-incompatible-msrv-in-tests check-private-items cognitive-complexity-threshold cyclomatic-complexity-threshold @@ -183,6 +189,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni accept-comment-above-statement allow-comparison-to-zero allow-dbg-in-tests + allow-expect-in-consts allow-expect-in-tests allow-indexing-slicing-in-tests allow-mixed-uninlined-format-args @@ -191,6 +198,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni allow-print-in-tests allow-private-module-inception allow-renamed-params-for + allow-unwrap-in-consts allow-unwrap-in-tests allow-useless-vec-in-tests allowed-dotfiles @@ -207,6 +215,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni await-holding-invalid-types blacklisted-names cargo-ignore-publish + check-incompatible-msrv-in-tests check-private-items cognitive-complexity-threshold cyclomatic-complexity-threshold diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr index 9677beeb2c24..32ed78151d23 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr @@ -9,7 +9,7 @@ LL | /* Safety: */ unsafe {} = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:274:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:275:5 | LL | unsafe {} | ^^^^^^^^^ @@ -17,7 +17,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:278:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:14 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:278:29 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:29 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:278:48 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:48 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:282:18 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:18 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -49,7 +49,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:282:37 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:37 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -57,7 +57,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:286:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:293:14 | LL | let _ = *unsafe { &42 }; | ^^^^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | let _ = *unsafe { &42 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:291:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:299:19 | LL | let _ = match unsafe {} { | ^^^^^^^^^ @@ -73,7 +73,7 @@ LL | let _ = match unsafe {} { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:297:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:306:14 | LL | let _ = &unsafe {}; | ^^^^^^^^^ @@ -81,7 +81,7 @@ LL | let _ = &unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:301:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:311:14 | LL | let _ = [unsafe {}; 5]; | ^^^^^^^^^ @@ -89,7 +89,7 @@ LL | let _ = [unsafe {}; 5]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:305:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:316:13 | LL | let _ = unsafe {}; | ^^^^^^^^^ @@ -97,7 +97,7 @@ LL | let _ = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:315:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:327:8 | LL | t!(unsafe {}); | ^^^^^^^^^ @@ -105,7 +105,7 @@ LL | t!(unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:321:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:334:13 | LL | unsafe {} | ^^^^^^^^^ @@ -117,7 +117,7 @@ LL | t!(); = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:329:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:343:5 | LL | unsafe {} // SAFETY: | ^^^^^^^^^ @@ -125,7 +125,7 @@ LL | unsafe {} // SAFETY: = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:333:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:349:5 | LL | unsafe { | ^^^^^^^^ @@ -133,7 +133,7 @@ LL | unsafe { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:343:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:360:5 | LL | unsafe {}; | ^^^^^^^^^ @@ -141,7 +141,7 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:347:20 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:365:20 | LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -149,7 +149,7 @@ LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:354:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:373:5 | LL | unsafe impl A for () {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL | unsafe impl A for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:361:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:381:9 | LL | unsafe impl B for (u32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,7 +165,7 @@ LL | unsafe impl B for (u32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:382:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:403:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -177,7 +177,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:407:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:429:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -189,7 +189,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:415:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:439:5 | LL | unsafe impl T for (i32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -197,7 +197,7 @@ LL | unsafe impl T for (i32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:407:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:429:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +209,7 @@ LL | no_safety_comment!(u32); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:421:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:446:5 | LL | unsafe impl T for (bool) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +217,7 @@ LL | unsafe impl T for (bool) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:467:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:493:5 | LL | unsafe impl NoComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -225,7 +225,7 @@ LL | unsafe impl NoComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:471:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:498:19 | LL | /* SAFETY: */ unsafe impl InlineComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -233,7 +233,7 @@ LL | /* SAFETY: */ unsafe impl InlineComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:475:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:503:5 | LL | unsafe impl TrailingComment for () {} // SAFETY: | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,13 +241,13 @@ LL | unsafe impl TrailingComment for () {} // SAFETY: = help: consider adding a safety comment on the preceding line error: constant item has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:479:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:508:5 | LL | const BIG_NUMBER: i32 = 1000000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:478:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:507:5 | LL | // SAFETY: | ^^^^^^^^^^ @@ -255,7 +255,7 @@ LL | // SAFETY: = help: to override `-D warnings` add `#[allow(clippy::unnecessary_safety_comment)]` error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:480:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:510:5 | LL | unsafe impl Interference for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -263,7 +263,7 @@ LL | unsafe impl Interference for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:487:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:518:5 | LL | unsafe impl ImplInFn for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -271,7 +271,7 @@ LL | unsafe impl ImplInFn for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:1 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:528:1 | LL | unsafe impl CrateRoot for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -279,24 +279,23 @@ LL | unsafe impl CrateRoot for () {} = help: consider adding a safety comment on the preceding line error: statement has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:509:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:543:5 | LL | / let _ = { +LL | | LL | | if unsafe { true } { -LL | | todo!(); -LL | | } else { ... | LL | | }; | |______^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:508:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:542:5 | LL | // SAFETY: this is more than one level away, so it should warn | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:510:12 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:545:12 | LL | if unsafe { true } { | ^^^^^^^^^^^^^^^ @@ -304,7 +303,7 @@ LL | if unsafe { true } { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:513:23 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:549:23 | LL | let bar = unsafe {}; | ^^^^^^^^^ diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr index 0eccdd428008..83a6986addf2 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr @@ -9,7 +9,7 @@ LL | /* Safety: */ unsafe {} = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:274:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:275:5 | LL | unsafe {} | ^^^^^^^^^ @@ -17,7 +17,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:278:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:14 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:278:29 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:29 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:278:48 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:48 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:282:18 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:18 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -49,7 +49,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:282:37 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:37 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -57,7 +57,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:286:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:293:14 | LL | let _ = *unsafe { &42 }; | ^^^^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | let _ = *unsafe { &42 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:291:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:299:19 | LL | let _ = match unsafe {} { | ^^^^^^^^^ @@ -73,7 +73,7 @@ LL | let _ = match unsafe {} { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:297:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:306:14 | LL | let _ = &unsafe {}; | ^^^^^^^^^ @@ -81,7 +81,7 @@ LL | let _ = &unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:301:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:311:14 | LL | let _ = [unsafe {}; 5]; | ^^^^^^^^^ @@ -89,7 +89,7 @@ LL | let _ = [unsafe {}; 5]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:305:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:316:13 | LL | let _ = unsafe {}; | ^^^^^^^^^ @@ -97,7 +97,7 @@ LL | let _ = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:315:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:327:8 | LL | t!(unsafe {}); | ^^^^^^^^^ @@ -105,7 +105,7 @@ LL | t!(unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:321:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:334:13 | LL | unsafe {} | ^^^^^^^^^ @@ -117,7 +117,7 @@ LL | t!(); = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:329:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:343:5 | LL | unsafe {} // SAFETY: | ^^^^^^^^^ @@ -125,7 +125,7 @@ LL | unsafe {} // SAFETY: = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:333:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:349:5 | LL | unsafe { | ^^^^^^^^ @@ -133,7 +133,7 @@ LL | unsafe { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:343:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:360:5 | LL | unsafe {}; | ^^^^^^^^^ @@ -141,7 +141,7 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:347:20 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:365:20 | LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -149,7 +149,7 @@ LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:354:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:373:5 | LL | unsafe impl A for () {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL | unsafe impl A for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:361:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:381:9 | LL | unsafe impl B for (u32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,7 +165,7 @@ LL | unsafe impl B for (u32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:382:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:403:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -177,7 +177,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:407:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:429:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -189,7 +189,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:415:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:439:5 | LL | unsafe impl T for (i32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -197,7 +197,7 @@ LL | unsafe impl T for (i32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:407:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:429:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +209,7 @@ LL | no_safety_comment!(u32); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:421:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:446:5 | LL | unsafe impl T for (bool) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +217,7 @@ LL | unsafe impl T for (bool) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:467:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:493:5 | LL | unsafe impl NoComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -225,7 +225,7 @@ LL | unsafe impl NoComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:471:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:498:19 | LL | /* SAFETY: */ unsafe impl InlineComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -233,7 +233,7 @@ LL | /* SAFETY: */ unsafe impl InlineComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:475:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:503:5 | LL | unsafe impl TrailingComment for () {} // SAFETY: | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,13 +241,13 @@ LL | unsafe impl TrailingComment for () {} // SAFETY: = help: consider adding a safety comment on the preceding line error: constant item has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:479:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:508:5 | LL | const BIG_NUMBER: i32 = 1000000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:478:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:507:5 | LL | // SAFETY: | ^^^^^^^^^^ @@ -255,7 +255,7 @@ LL | // SAFETY: = help: to override `-D warnings` add `#[allow(clippy::unnecessary_safety_comment)]` error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:480:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:510:5 | LL | unsafe impl Interference for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -263,7 +263,7 @@ LL | unsafe impl Interference for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:487:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:518:5 | LL | unsafe impl ImplInFn for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -271,7 +271,7 @@ LL | unsafe impl ImplInFn for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:1 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:528:1 | LL | unsafe impl CrateRoot for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -279,7 +279,7 @@ LL | unsafe impl CrateRoot for () {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:506:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:539:9 | LL | unsafe {}; | ^^^^^^^^^ @@ -287,24 +287,23 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: statement has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:509:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:543:5 | LL | / let _ = { +LL | | LL | | if unsafe { true } { -LL | | todo!(); -LL | | } else { ... | LL | | }; | |______^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:508:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:542:5 | LL | // SAFETY: this is more than one level away, so it should warn | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:510:12 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:545:12 | LL | if unsafe { true } { | ^^^^^^^^^^^^^^^ @@ -312,7 +311,7 @@ LL | if unsafe { true } { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:513:23 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:549:23 | LL | let bar = unsafe {}; | ^^^^^^^^^ @@ -320,7 +319,7 @@ LL | let bar = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:531:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:568:9 | LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -328,7 +327,7 @@ LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:535:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:573:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -336,7 +335,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:539:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:578:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -344,7 +343,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:545:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:585:5 | LL | unsafe {} | ^^^^^^^^^ @@ -352,7 +351,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:549:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:590:5 | LL | unsafe { | ^^^^^^^^ @@ -360,7 +359,7 @@ LL | unsafe { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:556:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:598:9 | LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -368,7 +367,7 @@ LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:561:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:604:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -376,7 +375,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:567:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:611:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -384,7 +383,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:572:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:617:5 | LL | unsafe {} | ^^^^^^^^^ diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs index 02170e1f7402..6a3fda3df5c3 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs @@ -268,41 +268,53 @@ fn in_closure(x: *const u32) { #[rustfmt::skip] fn inline_block_comment() { /* Safety: */ unsafe {} + //~^ undocumented_unsafe_blocks } fn no_comment() { unsafe {} + //~^ undocumented_unsafe_blocks } fn no_comment_array() { let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; + //~^ undocumented_unsafe_blocks + //~| undocumented_unsafe_blocks + //~| undocumented_unsafe_blocks } fn no_comment_tuple() { let _ = (42, unsafe {}, "test", unsafe {}); + //~^ undocumented_unsafe_blocks + //~| undocumented_unsafe_blocks } fn no_comment_unary() { let _ = *unsafe { &42 }; + //~^ undocumented_unsafe_blocks } #[allow(clippy::match_single_binding)] fn no_comment_match() { let _ = match unsafe {} { + //~^ undocumented_unsafe_blocks _ => {}, }; } fn no_comment_addr_of() { let _ = &unsafe {}; + //~^ undocumented_unsafe_blocks } fn no_comment_repeat() { let _ = [unsafe {}; 5]; + //~^ undocumented_unsafe_blocks } fn local_no_comment() { let _ = unsafe {}; + //~^ undocumented_unsafe_blocks } fn no_comment_macro_call() { @@ -313,12 +325,14 @@ fn no_comment_macro_call() { } t!(unsafe {}); + //~^ undocumented_unsafe_blocks } fn no_comment_macro_def() { macro_rules! t { () => { unsafe {} + //~^ undocumented_unsafe_blocks }; } @@ -327,10 +341,13 @@ fn no_comment_macro_def() { fn trailing_comment() { unsafe {} // SAFETY: + // + //~^^ undocumented_unsafe_blocks } fn internal_comment() { unsafe { + //~^ undocumented_unsafe_blocks // SAFETY: } } @@ -341,10 +358,12 @@ fn interference() { let _ = 42; unsafe {}; + //~^ undocumented_unsafe_blocks } pub fn print_binary_tree() { println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); + //~^ undocumented_unsafe_blocks } mod unsafe_impl_smoke_test { @@ -352,6 +371,7 @@ mod unsafe_impl_smoke_test { // error: no safety comment unsafe impl A for () {} + //~^ undocumented_unsafe_blocks // Safety: ok unsafe impl A for (i32) {} @@ -359,6 +379,7 @@ mod unsafe_impl_smoke_test { mod sub_mod { // error: unsafe impl B for (u32) {} + //~^ undocumented_unsafe_blocks unsafe trait B {} } @@ -380,6 +401,7 @@ mod unsafe_impl_from_macro { macro_rules! no_safety_comment { ($t:ty) => { unsafe impl T for $t {} + //~^ undocumented_unsafe_blocks }; } @@ -405,6 +427,8 @@ mod unsafe_impl_macro_and_not_macro { macro_rules! no_safety_comment { ($t:ty) => { unsafe impl T for $t {} + //~^ undocumented_unsafe_blocks + //~| undocumented_unsafe_blocks }; } @@ -413,12 +437,14 @@ mod unsafe_impl_macro_and_not_macro { // error unsafe impl T for (i32) {} + //~^ undocumented_unsafe_blocks // ok no_safety_comment!(u32); // error unsafe impl T for (bool) {} + //~^ undocumented_unsafe_blocks } #[rustfmt::skip] @@ -465,19 +491,24 @@ mod unsafe_impl_invalid_comment { unsafe trait NoComment {} unsafe impl NoComment for () {} + //~^ undocumented_unsafe_blocks unsafe trait InlineComment {} /* SAFETY: */ unsafe impl InlineComment for () {} + //~^ undocumented_unsafe_blocks unsafe trait TrailingComment {} unsafe impl TrailingComment for () {} // SAFETY: + //~^ undocumented_unsafe_blocks unsafe trait Interference {} // SAFETY: const BIG_NUMBER: i32 = 1000000; + //~^ unnecessary_safety_comment unsafe impl Interference for () {} + //~^ undocumented_unsafe_blocks } unsafe trait ImplInFn {} @@ -485,6 +516,7 @@ unsafe trait ImplInFn {} fn impl_in_fn() { // error unsafe impl ImplInFn for () {} + //~^ undocumented_unsafe_blocks // SAFETY: ok unsafe impl ImplInFn for (i32) {} @@ -494,6 +526,7 @@ unsafe trait CrateRoot {} // error unsafe impl CrateRoot for () {} +//~^ undocumented_unsafe_blocks // SAFETY: ok unsafe impl CrateRoot for (i32) {} @@ -504,13 +537,17 @@ fn nested_block_separation_issue_9142() { // we need this comment to avoid rustfmt putting // it all on one line unsafe {}; + //~[disabled]^ undocumented_unsafe_blocks // SAFETY: this is more than one level away, so it should warn let _ = { + //~^ unnecessary_safety_comment if unsafe { true } { + //~^ undocumented_unsafe_blocks todo!(); } else { let bar = unsafe {}; + //~^ undocumented_unsafe_blocks todo!(); bar } @@ -529,24 +566,29 @@ fn separate_line_from_let_issue_10832() { // SAFETY: fail ONLY if `accept-comment-above-statement = false` let _some_variable_with_a_very_long_name_to_break_the_line = unsafe { a_function_with_a_very_long_name_to_break_the_line() }; + //~[disabled]^ undocumented_unsafe_blocks // SAFETY: fail ONLY if `accept-comment-above-statement = false` const _SOME_CONST_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 = unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; + //~[disabled]^ undocumented_unsafe_blocks // SAFETY: fail ONLY if `accept-comment-above-statement = false` static _SOME_STATIC_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 = unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; + //~[disabled]^ undocumented_unsafe_blocks } fn above_expr_attribute_issue_8679() { // SAFETY: fail ONLY if `accept-comment-above-attribute = false` #[allow(unsafe_code)] unsafe {} + //~[disabled]^ undocumented_unsafe_blocks // SAFETY: fail ONLY if `accept-comment-above-attribute = false` #[expect(unsafe_code, reason = "totally safe")] unsafe { + //~[disabled]^ undocumented_unsafe_blocks *std::ptr::null::() }; @@ -554,22 +596,26 @@ fn above_expr_attribute_issue_8679() { #[allow(unsafe_code)] let _some_variable_with_a_very_long_name_to_break_the_line = unsafe { a_function_with_a_very_long_name_to_break_the_line() }; + //~[disabled]^ undocumented_unsafe_blocks // SAFETY: fail ONLY if `accept-comment-above-attribute = false` #[allow(unsafe_code)] const _SOME_CONST_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 = unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; + //~[disabled]^ undocumented_unsafe_blocks // SAFETY: fail ONLY if `accept-comment-above-attribute = false` #[allow(unsafe_code)] #[allow(non_upper_case_globals)] static _some_static_with_a_very_long_name_to_break_the_line: u32 = unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; + //~[disabled]^ undocumented_unsafe_blocks // SAFETY: #[allow(unsafe_code)] // This shouldn't work either unsafe {} + //~[disabled]^ undocumented_unsafe_blocks } mod issue_11246 { diff --git a/tests/ui-toml/unwrap_used/clippy.toml b/tests/ui-toml/unwrap_used/clippy.toml index 154626ef4e81..6fd1eb6f8d0d 100644 --- a/tests/ui-toml/unwrap_used/clippy.toml +++ b/tests/ui-toml/unwrap_used/clippy.toml @@ -1 +1,2 @@ +allow-unwrap-in-consts = false allow-unwrap-in-tests = true diff --git a/tests/ui-toml/unwrap_used/unwrap_used.fixed b/tests/ui-toml/unwrap_used/unwrap_used.fixed index cdb8fa0454cd..9b4eaa208eb2 100644 --- a/tests/ui-toml/unwrap_used/unwrap_used.fixed +++ b/tests/ui-toml/unwrap_used/unwrap_used.fixed @@ -36,23 +36,45 @@ fn main() { { // Test `get().unwrap()` let _ = &boxed_slice[1]; + //~^ get_unwrap + //~| unwrap_used let _ = &some_slice[0]; + //~^ get_unwrap + //~| unwrap_used let _ = &some_vec[0]; + //~^ get_unwrap + //~| unwrap_used let _ = &some_vecdeque[0]; + //~^ get_unwrap + //~| unwrap_used let _ = &some_hashmap[&1]; + //~^ get_unwrap + //~| unwrap_used let _ = &some_btreemap[&1]; + //~^ get_unwrap + //~| unwrap_used #[allow(clippy::unwrap_used)] let _ = false_positive.get(0).unwrap(); // Test with deref let _: u8 = boxed_slice[1]; + //~^ get_unwrap + //~| unwrap_used } { // Test `get_mut().unwrap()` boxed_slice[0] = 1; + //~^ get_unwrap + //~| unwrap_used some_slice[0] = 1; + //~^ get_unwrap + //~| unwrap_used some_vec[0] = 1; + //~^ get_unwrap + //~| unwrap_used some_vecdeque[0] = 1; + //~^ get_unwrap + //~| unwrap_used // Check false positives #[allow(clippy::unwrap_used)] { @@ -65,7 +87,11 @@ fn main() { { // Test `get().unwrap().foo()` and `get_mut().unwrap().bar()` let _ = some_vec[0..1].to_vec(); + //~^ get_unwrap + //~| unwrap_used let _ = some_vec[0..1].to_vec(); + //~^ get_unwrap + //~| unwrap_used } } @@ -73,6 +99,7 @@ fn main() { fn test() { let boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]); let _ = &boxed_slice[1]; + //~^ get_unwrap } #[cfg(test)] @@ -92,5 +119,6 @@ mod issue9612 { let _a: u8 = 5.try_into().expect(""); // should still warn let _ = &Box::new([0])[1]; + //~^ get_unwrap } } diff --git a/tests/ui-toml/unwrap_used/unwrap_used.rs b/tests/ui-toml/unwrap_used/unwrap_used.rs index e53d53db5f7a..4845efa68733 100644 --- a/tests/ui-toml/unwrap_used/unwrap_used.rs +++ b/tests/ui-toml/unwrap_used/unwrap_used.rs @@ -36,23 +36,45 @@ fn main() { { // Test `get().unwrap()` let _ = boxed_slice.get(1).unwrap(); + //~^ get_unwrap + //~| unwrap_used let _ = some_slice.get(0).unwrap(); + //~^ get_unwrap + //~| unwrap_used let _ = some_vec.get(0).unwrap(); + //~^ get_unwrap + //~| unwrap_used let _ = some_vecdeque.get(0).unwrap(); + //~^ get_unwrap + //~| unwrap_used let _ = some_hashmap.get(&1).unwrap(); + //~^ get_unwrap + //~| unwrap_used let _ = some_btreemap.get(&1).unwrap(); + //~^ get_unwrap + //~| unwrap_used #[allow(clippy::unwrap_used)] let _ = false_positive.get(0).unwrap(); // Test with deref let _: u8 = *boxed_slice.get(1).unwrap(); + //~^ get_unwrap + //~| unwrap_used } { // Test `get_mut().unwrap()` *boxed_slice.get_mut(0).unwrap() = 1; + //~^ get_unwrap + //~| unwrap_used *some_slice.get_mut(0).unwrap() = 1; + //~^ get_unwrap + //~| unwrap_used *some_vec.get_mut(0).unwrap() = 1; + //~^ get_unwrap + //~| unwrap_used *some_vecdeque.get_mut(0).unwrap() = 1; + //~^ get_unwrap + //~| unwrap_used // Check false positives #[allow(clippy::unwrap_used)] { @@ -65,7 +87,11 @@ fn main() { { // Test `get().unwrap().foo()` and `get_mut().unwrap().bar()` let _ = some_vec.get(0..1).unwrap().to_vec(); + //~^ get_unwrap + //~| unwrap_used let _ = some_vec.get_mut(0..1).unwrap().to_vec(); + //~^ get_unwrap + //~| unwrap_used } } @@ -73,6 +99,7 @@ fn main() { fn test() { let boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]); let _ = boxed_slice.get(1).unwrap(); + //~^ get_unwrap } #[cfg(test)] @@ -92,5 +119,6 @@ mod issue9612 { let _a: u8 = 5.try_into().expect(""); // should still warn let _ = Box::new([0]).get(1).unwrap(); + //~^ get_unwrap } } diff --git a/tests/ui-toml/unwrap_used/unwrap_used.stderr b/tests/ui-toml/unwrap_used/unwrap_used.stderr index 2aff276a4a12..135e35323fdb 100644 --- a/tests/ui-toml/unwrap_used/unwrap_used.stderr +++ b/tests/ui-toml/unwrap_used/unwrap_used.stderr @@ -24,7 +24,7 @@ LL | let _ = boxed_slice.get(1).unwrap(); = help: to override `-D warnings` add `#[allow(clippy::unwrap_used)]` error: called `.get().unwrap()` on a slice - --> tests/ui-toml/unwrap_used/unwrap_used.rs:39:17 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:41:17 | LL | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +36,7 @@ LL + let _ = &some_slice[0]; | error: used `unwrap()` on an `Option` value - --> tests/ui-toml/unwrap_used/unwrap_used.rs:39:17 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:41:17 | LL | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -45,7 +45,7 @@ LL | let _ = some_slice.get(0).unwrap(); = help: consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a Vec - --> tests/ui-toml/unwrap_used/unwrap_used.rs:40:17 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:44:17 | LL | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -57,7 +57,7 @@ LL + let _ = &some_vec[0]; | error: used `unwrap()` on an `Option` value - --> tests/ui-toml/unwrap_used/unwrap_used.rs:40:17 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:44:17 | LL | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | let _ = some_vec.get(0).unwrap(); = help: consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a VecDeque - --> tests/ui-toml/unwrap_used/unwrap_used.rs:41:17 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:47:17 | LL | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -78,7 +78,7 @@ LL + let _ = &some_vecdeque[0]; | error: used `unwrap()` on an `Option` value - --> tests/ui-toml/unwrap_used/unwrap_used.rs:41:17 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:47:17 | LL | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -87,7 +87,7 @@ LL | let _ = some_vecdeque.get(0).unwrap(); = help: consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a HashMap - --> tests/ui-toml/unwrap_used/unwrap_used.rs:42:17 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:50:17 | LL | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -99,7 +99,7 @@ LL + let _ = &some_hashmap[&1]; | error: used `unwrap()` on an `Option` value - --> tests/ui-toml/unwrap_used/unwrap_used.rs:42:17 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:50:17 | LL | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -108,7 +108,7 @@ LL | let _ = some_hashmap.get(&1).unwrap(); = help: consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a BTreeMap - --> tests/ui-toml/unwrap_used/unwrap_used.rs:43:17 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:53:17 | LL | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -120,7 +120,7 @@ LL + let _ = &some_btreemap[&1]; | error: used `unwrap()` on an `Option` value - --> tests/ui-toml/unwrap_used/unwrap_used.rs:43:17 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:53:17 | LL | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -129,7 +129,7 @@ LL | let _ = some_btreemap.get(&1).unwrap(); = help: consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a slice - --> tests/ui-toml/unwrap_used/unwrap_used.rs:47:21 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:59:21 | LL | let _: u8 = *boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -141,7 +141,7 @@ LL + let _: u8 = boxed_slice[1]; | error: used `unwrap()` on an `Option` value - --> tests/ui-toml/unwrap_used/unwrap_used.rs:47:22 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:59:22 | LL | let _: u8 = *boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -150,7 +150,7 @@ LL | let _: u8 = *boxed_slice.get(1).unwrap(); = help: consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a slice - --> tests/ui-toml/unwrap_used/unwrap_used.rs:52:9 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:66:9 | LL | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -162,7 +162,7 @@ LL + boxed_slice[0] = 1; | error: used `unwrap()` on an `Option` value - --> tests/ui-toml/unwrap_used/unwrap_used.rs:52:10 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:66:10 | LL | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -171,7 +171,7 @@ LL | *boxed_slice.get_mut(0).unwrap() = 1; = help: consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a slice - --> tests/ui-toml/unwrap_used/unwrap_used.rs:53:9 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:69:9 | LL | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -183,7 +183,7 @@ LL + some_slice[0] = 1; | error: used `unwrap()` on an `Option` value - --> tests/ui-toml/unwrap_used/unwrap_used.rs:53:10 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:69:10 | LL | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -192,7 +192,7 @@ LL | *some_slice.get_mut(0).unwrap() = 1; = help: consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a Vec - --> tests/ui-toml/unwrap_used/unwrap_used.rs:54:9 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:72:9 | LL | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -204,7 +204,7 @@ LL + some_vec[0] = 1; | error: used `unwrap()` on an `Option` value - --> tests/ui-toml/unwrap_used/unwrap_used.rs:54:10 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:72:10 | LL | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -213,7 +213,7 @@ LL | *some_vec.get_mut(0).unwrap() = 1; = help: consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a VecDeque - --> tests/ui-toml/unwrap_used/unwrap_used.rs:55:9 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:75:9 | LL | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -225,7 +225,7 @@ LL + some_vecdeque[0] = 1; | error: used `unwrap()` on an `Option` value - --> tests/ui-toml/unwrap_used/unwrap_used.rs:55:10 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:75:10 | LL | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -234,7 +234,7 @@ LL | *some_vecdeque.get_mut(0).unwrap() = 1; = help: consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a Vec - --> tests/ui-toml/unwrap_used/unwrap_used.rs:67:17 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:89:17 | LL | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -246,7 +246,7 @@ LL + let _ = some_vec[0..1].to_vec(); | error: used `unwrap()` on an `Option` value - --> tests/ui-toml/unwrap_used/unwrap_used.rs:67:17 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:89:17 | LL | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -255,7 +255,7 @@ LL | let _ = some_vec.get(0..1).unwrap().to_vec(); = help: consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a Vec - --> tests/ui-toml/unwrap_used/unwrap_used.rs:68:17 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:92:17 | LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -267,7 +267,7 @@ LL + let _ = some_vec[0..1].to_vec(); | error: used `unwrap()` on an `Option` value - --> tests/ui-toml/unwrap_used/unwrap_used.rs:68:17 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:92:17 | LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -276,7 +276,7 @@ LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); = help: consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a slice - --> tests/ui-toml/unwrap_used/unwrap_used.rs:75:13 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:101:13 | LL | let _ = boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -288,7 +288,7 @@ LL + let _ = &boxed_slice[1]; | error: called `.get().unwrap()` on a slice - --> tests/ui-toml/unwrap_used/unwrap_used.rs:94:17 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:121:17 | LL | let _ = Box::new([0]).get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/unwrap_used/unwrap_used_const.rs b/tests/ui-toml/unwrap_used/unwrap_used_const.rs new file mode 100644 index 000000000000..c7d8e8c1ffb5 --- /dev/null +++ b/tests/ui-toml/unwrap_used/unwrap_used_const.rs @@ -0,0 +1,11 @@ +#![warn(clippy::unwrap_used)] + +fn main() { + const SOME: Option = Some(3); + const UNWRAPPED: i32 = SOME.unwrap(); + //~^ ERROR: used `unwrap()` on an `Option` value + const { + SOME.unwrap(); + //~^ ERROR: used `unwrap()` on an `Option` value + } +} diff --git a/tests/ui-toml/unwrap_used/unwrap_used_const.stderr b/tests/ui-toml/unwrap_used/unwrap_used_const.stderr new file mode 100644 index 000000000000..362b41bc1bff --- /dev/null +++ b/tests/ui-toml/unwrap_used/unwrap_used_const.stderr @@ -0,0 +1,22 @@ +error: used `unwrap()` on an `Option` value + --> tests/ui-toml/unwrap_used/unwrap_used_const.rs:5:28 + | +LL | const UNWRAPPED: i32 = SOME.unwrap(); + | ^^^^^^^^^^^^^ + | + = note: if this value is `None`, it will panic + = help: consider using `expect()` to provide a better panic message + = note: `-D clippy::unwrap-used` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::unwrap_used)]` + +error: used `unwrap()` on an `Option` value + --> tests/ui-toml/unwrap_used/unwrap_used_const.rs:8:9 + | +LL | SOME.unwrap(); + | ^^^^^^^^^^^^^ + | + = note: if this value is `None`, it will panic + = help: consider using `expect()` to provide a better panic message + +error: aborting due to 2 previous errors + diff --git a/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.fixed b/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.fixed index afb889f157f0..4f1f9ca07273 100644 --- a/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.fixed +++ b/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.fixed @@ -1,24 +1,35 @@ #![warn(clippy::upper_case_acronyms)] struct HttpResponse; // not linted by default, but with cfg option +//~^ upper_case_acronyms struct CString; // not linted enum Flags { Ns, // not linted + //~^ upper_case_acronyms Cwr, + //~^ upper_case_acronyms Ece, + //~^ upper_case_acronyms Urg, + //~^ upper_case_acronyms Ack, + //~^ upper_case_acronyms Psh, + //~^ upper_case_acronyms Rst, + //~^ upper_case_acronyms Syn, + //~^ upper_case_acronyms Fin, + //~^ upper_case_acronyms } // linted with cfg option, beware that lint suggests `GccllvmSomething` instead of // `GccLlvmSomething` struct GccllvmSomething; +//~^ upper_case_acronyms // don't warn on public items pub struct MIXEDCapital; @@ -36,7 +47,9 @@ pub enum ParseError { // private, do lint here enum ParseErrorPrivate { Wasd(u8), + //~^ upper_case_acronyms WasdMixed(String), + //~^ upper_case_acronyms Utf8(std::string::FromUtf8Error), Parse(T, String), } diff --git a/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs b/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs index 1a5cf1b1947c..da522aadfdd7 100644 --- a/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs +++ b/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs @@ -1,24 +1,35 @@ #![warn(clippy::upper_case_acronyms)] struct HTTPResponse; // not linted by default, but with cfg option +//~^ upper_case_acronyms struct CString; // not linted enum Flags { NS, // not linted + //~^ upper_case_acronyms CWR, + //~^ upper_case_acronyms ECE, + //~^ upper_case_acronyms URG, + //~^ upper_case_acronyms ACK, + //~^ upper_case_acronyms PSH, + //~^ upper_case_acronyms RST, + //~^ upper_case_acronyms SYN, + //~^ upper_case_acronyms FIN, + //~^ upper_case_acronyms } // linted with cfg option, beware that lint suggests `GccllvmSomething` instead of // `GccLlvmSomething` struct GCCLLVMSomething; +//~^ upper_case_acronyms // don't warn on public items pub struct MIXEDCapital; @@ -36,7 +47,9 @@ pub enum ParseError { // private, do lint here enum ParseErrorPrivate { WASD(u8), + //~^ upper_case_acronyms WASDMixed(String), + //~^ upper_case_acronyms Utf8(std::string::FromUtf8Error), Parse(T, String), } diff --git a/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.stderr b/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.stderr index 88917603ff8c..e1706b7472c0 100644 --- a/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.stderr +++ b/tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.stderr @@ -8,73 +8,73 @@ LL | struct HTTPResponse; // not linted by default, but with cfg option = help: to override `-D warnings` add `#[allow(clippy::upper_case_acronyms)]` error: name `NS` contains a capitalized acronym - --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:8:5 + --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:9:5 | LL | NS, // not linted | ^^ help: consider making the acronym lowercase, except the initial letter (notice the capitalization): `Ns` error: name `CWR` contains a capitalized acronym - --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:9:5 + --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:11:5 | LL | CWR, | ^^^ help: consider making the acronym lowercase, except the initial letter: `Cwr` error: name `ECE` contains a capitalized acronym - --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:10:5 + --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:13:5 | LL | ECE, | ^^^ help: consider making the acronym lowercase, except the initial letter: `Ece` error: name `URG` contains a capitalized acronym - --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:11:5 + --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:15:5 | LL | URG, | ^^^ help: consider making the acronym lowercase, except the initial letter: `Urg` error: name `ACK` contains a capitalized acronym - --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:12:5 + --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:17:5 | LL | ACK, | ^^^ help: consider making the acronym lowercase, except the initial letter (notice the capitalization): `Ack` error: name `PSH` contains a capitalized acronym - --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:13:5 + --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:19:5 | LL | PSH, | ^^^ help: consider making the acronym lowercase, except the initial letter: `Psh` error: name `RST` contains a capitalized acronym - --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:14:5 + --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:21:5 | LL | RST, | ^^^ help: consider making the acronym lowercase, except the initial letter: `Rst` error: name `SYN` contains a capitalized acronym - --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:15:5 + --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:23:5 | LL | SYN, | ^^^ help: consider making the acronym lowercase, except the initial letter: `Syn` error: name `FIN` contains a capitalized acronym - --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:16:5 + --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:25:5 | LL | FIN, | ^^^ help: consider making the acronym lowercase, except the initial letter: `Fin` error: name `GCCLLVMSomething` contains a capitalized acronym - --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:21:8 + --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:31:8 | LL | struct GCCLLVMSomething; | ^^^^^^^^^^^^^^^^ help: consider making the acronym lowercase, except the initial letter: `GccllvmSomething` error: name `WASD` contains a capitalized acronym - --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:38:5 + --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:49:5 | LL | WASD(u8), | ^^^^ help: consider making the acronym lowercase, except the initial letter: `Wasd` error: name `WASDMixed` contains a capitalized acronym - --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:39:5 + --> tests/ui-toml/upper_case_acronyms_aggressive/upper_case_acronyms.rs:51:5 | LL | WASDMixed(String), | ^^^^^^^^^ help: consider making the acronym lowercase, except the initial letter: `WasdMixed` diff --git a/tests/ui-toml/useless_vec/useless_vec.fixed b/tests/ui-toml/useless_vec/useless_vec.fixed index 08323a0dcc90..6181abc6ea57 100644 --- a/tests/ui-toml/useless_vec/useless_vec.fixed +++ b/tests/ui-toml/useless_vec/useless_vec.fixed @@ -6,6 +6,7 @@ fn foo(_: &[u32]) {} fn main() { foo(&[1_u32]); + //~^ useless_vec } #[test] diff --git a/tests/ui-toml/useless_vec/useless_vec.rs b/tests/ui-toml/useless_vec/useless_vec.rs index 1f4b27c53429..bffdcc59752b 100644 --- a/tests/ui-toml/useless_vec/useless_vec.rs +++ b/tests/ui-toml/useless_vec/useless_vec.rs @@ -6,6 +6,7 @@ fn foo(_: &[u32]) {} fn main() { foo(&vec![1_u32]); + //~^ useless_vec } #[test] diff --git a/tests/ui-toml/vec_box_sized/test.fixed b/tests/ui-toml/vec_box_sized/test.fixed index bb4936401ceb..423c761f1b17 100644 --- a/tests/ui-toml/vec_box_sized/test.fixed +++ b/tests/ui-toml/vec_box_sized/test.fixed @@ -7,10 +7,13 @@ struct C { } struct Foo(Vec); +//~^ vec_box struct Bar(Vec); +//~^ vec_box struct Quux(Vec>); struct Baz(Vec>); struct BarBaz(Vec>); struct FooBarBaz(Vec); +//~^ vec_box fn main() {} diff --git a/tests/ui-toml/vec_box_sized/test.rs b/tests/ui-toml/vec_box_sized/test.rs index 4c46deb585b6..fd9a13430021 100644 --- a/tests/ui-toml/vec_box_sized/test.rs +++ b/tests/ui-toml/vec_box_sized/test.rs @@ -7,10 +7,13 @@ struct C { } struct Foo(Vec>); +//~^ vec_box struct Bar(Vec>); +//~^ vec_box struct Quux(Vec>); struct Baz(Vec>); struct BarBaz(Vec>); struct FooBarBaz(Vec>); +//~^ vec_box fn main() {} diff --git a/tests/ui-toml/vec_box_sized/test.stderr b/tests/ui-toml/vec_box_sized/test.stderr index 8c0750d86663..b80b9492c3ca 100644 --- a/tests/ui-toml/vec_box_sized/test.stderr +++ b/tests/ui-toml/vec_box_sized/test.stderr @@ -8,13 +8,13 @@ LL | struct Foo(Vec>); = help: to override `-D warnings` add `#[allow(clippy::vec_box)]` error: `Vec` is already on the heap, the boxing is unnecessary - --> tests/ui-toml/vec_box_sized/test.rs:10:12 + --> tests/ui-toml/vec_box_sized/test.rs:11:12 | LL | struct Bar(Vec>); | ^^^^^^^^^^^^^ help: try: `Vec` error: `Vec` is already on the heap, the boxing is unnecessary - --> tests/ui-toml/vec_box_sized/test.rs:14:18 + --> tests/ui-toml/vec_box_sized/test.rs:16:18 | LL | struct FooBarBaz(Vec>); | ^^^^^^^^^^^ help: try: `Vec` diff --git a/tests/ui-toml/zero_single_char_names/zero_single_char_names.rs b/tests/ui-toml/zero_single_char_names/zero_single_char_names.rs index 22aaa242b9b9..d335b12d41ec 100644 --- a/tests/ui-toml/zero_single_char_names/zero_single_char_names.rs +++ b/tests/ui-toml/zero_single_char_names/zero_single_char_names.rs @@ -1,3 +1,4 @@ +//@check-pass #![warn(clippy::many_single_char_names)] fn main() {} diff --git a/tests/ui/absurd-extreme-comparisons.rs b/tests/ui/absurd-extreme-comparisons.rs index 60f2ba4abcff..793961d30f0d 100644 --- a/tests/ui/absurd-extreme-comparisons.rs +++ b/tests/ui/absurd-extreme-comparisons.rs @@ -12,46 +12,64 @@ fn main() { const Z: u32 = 0; let u: u32 = 42; u <= 0; - //~^ ERROR: this comparison involving the minimum or maximum element for this type con + //~^ absurd_extreme_comparisons + u <= Z; - //~^ ERROR: this comparison involving the minimum or maximum element for this type con + //~^ absurd_extreme_comparisons + u < Z; - //~^ ERROR: this comparison involving the minimum or maximum element for this type con + //~^ absurd_extreme_comparisons + Z >= u; - //~^ ERROR: this comparison involving the minimum or maximum element for this type con + //~^ absurd_extreme_comparisons + Z > u; - //~^ ERROR: this comparison involving the minimum or maximum element for this type con + //~^ absurd_extreme_comparisons + u > u32::MAX; - //~^ ERROR: this comparison involving the minimum or maximum element for this type con + //~^ absurd_extreme_comparisons + u >= u32::MAX; - //~^ ERROR: this comparison involving the minimum or maximum element for this type con + //~^ absurd_extreme_comparisons + u32::MAX < u; - //~^ ERROR: this comparison involving the minimum or maximum element for this type con + //~^ absurd_extreme_comparisons + u32::MAX <= u; - //~^ ERROR: this comparison involving the minimum or maximum element for this type con + //~^ absurd_extreme_comparisons + 1-1 > u; - //~^ ERROR: this comparison involving the minimum or maximum element for this type con + //~^ absurd_extreme_comparisons + u >= !0; - //~^ ERROR: this comparison involving the minimum or maximum element for this type con + //~^ absurd_extreme_comparisons + u <= 12 - 2*6; - //~^ ERROR: this comparison involving the minimum or maximum element for this type con + //~^ absurd_extreme_comparisons + let i: i8 = 0; i < -127 - 1; - //~^ ERROR: this comparison involving the minimum or maximum element for this type con + //~^ absurd_extreme_comparisons + i8::MAX >= i; - //~^ ERROR: this comparison involving the minimum or maximum element for this type con + //~^ absurd_extreme_comparisons + 3-7 < i32::MIN; - //~^ ERROR: this comparison involving the minimum or maximum element for this type con + //~^ absurd_extreme_comparisons + let b = false; b >= true; - //~^ ERROR: this comparison involving the minimum or maximum element for this type con + //~^ absurd_extreme_comparisons + false > b; - //~^ ERROR: this comparison involving the minimum or maximum element for this type con + //~^ absurd_extreme_comparisons + u > 0; // ok // this is handled by clippy::unit_cmp () < {}; - //~^ ERROR: <-comparison of unit values detected. This will always be false - //~| NOTE: `#[deny(clippy::unit_cmp)]` on by default + //~^ unit_cmp + + } use std::cmp::{Ordering, PartialEq, PartialOrd}; diff --git a/tests/ui/absurd-extreme-comparisons.stderr b/tests/ui/absurd-extreme-comparisons.stderr index f98114c0000a..6df50c15e8cd 100644 --- a/tests/ui/absurd-extreme-comparisons.stderr +++ b/tests/ui/absurd-extreme-comparisons.stderr @@ -9,7 +9,7 @@ LL | u <= 0; = help: to override `-D warnings` add `#[allow(clippy::absurd_extreme_comparisons)]` error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> tests/ui/absurd-extreme-comparisons.rs:16:5 + --> tests/ui/absurd-extreme-comparisons.rs:17:5 | LL | u <= Z; | ^^^^^^ @@ -17,7 +17,7 @@ LL | u <= Z; = help: because `Z` is the minimum value for this type, the case where the two sides are not equal never occurs, consider using `u == Z` instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> tests/ui/absurd-extreme-comparisons.rs:18:5 + --> tests/ui/absurd-extreme-comparisons.rs:20:5 | LL | u < Z; | ^^^^^ @@ -25,7 +25,7 @@ LL | u < Z; = help: because `Z` is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> tests/ui/absurd-extreme-comparisons.rs:20:5 + --> tests/ui/absurd-extreme-comparisons.rs:23:5 | LL | Z >= u; | ^^^^^^ @@ -33,7 +33,7 @@ LL | Z >= u; = help: because `Z` is the minimum value for this type, the case where the two sides are not equal never occurs, consider using `Z == u` instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> tests/ui/absurd-extreme-comparisons.rs:22:5 + --> tests/ui/absurd-extreme-comparisons.rs:26:5 | LL | Z > u; | ^^^^^ @@ -41,7 +41,7 @@ LL | Z > u; = help: because `Z` is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> tests/ui/absurd-extreme-comparisons.rs:24:5 + --> tests/ui/absurd-extreme-comparisons.rs:29:5 | LL | u > u32::MAX; | ^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | u > u32::MAX; = help: because `u32::MAX` is the maximum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> tests/ui/absurd-extreme-comparisons.rs:26:5 + --> tests/ui/absurd-extreme-comparisons.rs:32:5 | LL | u >= u32::MAX; | ^^^^^^^^^^^^^ @@ -57,7 +57,7 @@ LL | u >= u32::MAX; = help: because `u32::MAX` is the maximum value for this type, the case where the two sides are not equal never occurs, consider using `u == u32::MAX` instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> tests/ui/absurd-extreme-comparisons.rs:28:5 + --> tests/ui/absurd-extreme-comparisons.rs:35:5 | LL | u32::MAX < u; | ^^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | u32::MAX < u; = help: because `u32::MAX` is the maximum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> tests/ui/absurd-extreme-comparisons.rs:30:5 + --> tests/ui/absurd-extreme-comparisons.rs:38:5 | LL | u32::MAX <= u; | ^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | u32::MAX <= u; = help: because `u32::MAX` is the maximum value for this type, the case where the two sides are not equal never occurs, consider using `u32::MAX == u` instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> tests/ui/absurd-extreme-comparisons.rs:32:5 + --> tests/ui/absurd-extreme-comparisons.rs:41:5 | LL | 1-1 > u; | ^^^^^^^ @@ -81,7 +81,7 @@ LL | 1-1 > u; = help: because `1-1` is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> tests/ui/absurd-extreme-comparisons.rs:34:5 + --> tests/ui/absurd-extreme-comparisons.rs:44:5 | LL | u >= !0; | ^^^^^^^ @@ -89,7 +89,7 @@ LL | u >= !0; = help: because `!0` is the maximum value for this type, the case where the two sides are not equal never occurs, consider using `u == !0` instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> tests/ui/absurd-extreme-comparisons.rs:36:5 + --> tests/ui/absurd-extreme-comparisons.rs:47:5 | LL | u <= 12 - 2*6; | ^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL | u <= 12 - 2*6; = help: because `12 - 2*6` is the minimum value for this type, the case where the two sides are not equal never occurs, consider using `u == 12 - 2*6` instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> tests/ui/absurd-extreme-comparisons.rs:39:5 + --> tests/ui/absurd-extreme-comparisons.rs:51:5 | LL | i < -127 - 1; | ^^^^^^^^^^^^ @@ -105,7 +105,7 @@ LL | i < -127 - 1; = help: because `-127 - 1` is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> tests/ui/absurd-extreme-comparisons.rs:41:5 + --> tests/ui/absurd-extreme-comparisons.rs:54:5 | LL | i8::MAX >= i; | ^^^^^^^^^^^^ @@ -113,7 +113,7 @@ LL | i8::MAX >= i; = help: because `i8::MAX` is the maximum value for this type, this comparison is always true error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> tests/ui/absurd-extreme-comparisons.rs:43:5 + --> tests/ui/absurd-extreme-comparisons.rs:57:5 | LL | 3-7 < i32::MIN; | ^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL | 3-7 < i32::MIN; = help: because `i32::MIN` is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> tests/ui/absurd-extreme-comparisons.rs:46:5 + --> tests/ui/absurd-extreme-comparisons.rs:61:5 | LL | b >= true; | ^^^^^^^^^ @@ -129,7 +129,7 @@ LL | b >= true; = help: because `true` is the maximum value for this type, the case where the two sides are not equal never occurs, consider using `b == true` instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false - --> tests/ui/absurd-extreme-comparisons.rs:48:5 + --> tests/ui/absurd-extreme-comparisons.rs:64:5 | LL | false > b; | ^^^^^^^^^ @@ -137,7 +137,7 @@ LL | false > b; = help: because `false` is the minimum value for this type, this comparison is always false error: <-comparison of unit values detected. This will always be false - --> tests/ui/absurd-extreme-comparisons.rs:52:5 + --> tests/ui/absurd-extreme-comparisons.rs:69:5 | LL | () < {}; | ^^^^^^^ diff --git a/tests/ui/allow_attributes.fixed b/tests/ui/allow_attributes.fixed index 8f6c962e2f5b..56a98cca3404 100644 --- a/tests/ui/allow_attributes.fixed +++ b/tests/ui/allow_attributes.fixed @@ -11,6 +11,7 @@ use proc_macros::{external, with_span}; // Should lint #[expect(dead_code)] +//~^ allow_attributes struct T1; struct T2; // Should not lint @@ -20,6 +21,7 @@ struct T3; struct T4; // `panic = "unwind"` should always be true #[cfg_attr(panic = "unwind", expect(dead_code))] +//~^ allow_attributes struct CfgT; #[allow(clippy::allow_attributes, unused)] @@ -51,6 +53,7 @@ fn ignore_inner_attr() { #[clippy::msrv = "1.81"] fn msrv_1_81() { #[expect(unused)] + //~^ allow_attributes let x = 1; } diff --git a/tests/ui/allow_attributes.rs b/tests/ui/allow_attributes.rs index cb6c4dcf7158..65a0a6b5a108 100644 --- a/tests/ui/allow_attributes.rs +++ b/tests/ui/allow_attributes.rs @@ -11,6 +11,7 @@ use proc_macros::{external, with_span}; // Should lint #[allow(dead_code)] +//~^ allow_attributes struct T1; struct T2; // Should not lint @@ -20,6 +21,7 @@ struct T3; struct T4; // `panic = "unwind"` should always be true #[cfg_attr(panic = "unwind", allow(dead_code))] +//~^ allow_attributes struct CfgT; #[allow(clippy::allow_attributes, unused)] @@ -51,6 +53,7 @@ fn ignore_inner_attr() { #[clippy::msrv = "1.81"] fn msrv_1_81() { #[allow(unused)] + //~^ allow_attributes let x = 1; } diff --git a/tests/ui/allow_attributes.stderr b/tests/ui/allow_attributes.stderr index 5a4ff287acd2..dd5fb21ffeaf 100644 --- a/tests/ui/allow_attributes.stderr +++ b/tests/ui/allow_attributes.stderr @@ -8,13 +8,13 @@ LL | #[allow(dead_code)] = help: to override `-D warnings` add `#[allow(clippy::allow_attributes)]` error: #[allow] attribute found - --> tests/ui/allow_attributes.rs:22:30 + --> tests/ui/allow_attributes.rs:23:30 | LL | #[cfg_attr(panic = "unwind", allow(dead_code))] | ^^^^^ help: replace it with: `expect` error: #[allow] attribute found - --> tests/ui/allow_attributes.rs:53:7 + --> tests/ui/allow_attributes.rs:55:7 | LL | #[allow(unused)] | ^^^^^ help: replace it with: `expect` diff --git a/tests/ui/allow_attributes_without_reason.rs b/tests/ui/allow_attributes_without_reason.rs index 334e7ddd9d23..ea89511ebb46 100644 --- a/tests/ui/allow_attributes_without_reason.rs +++ b/tests/ui/allow_attributes_without_reason.rs @@ -1,14 +1,18 @@ //@aux-build:proc_macros.rs #![deny(clippy::allow_attributes_without_reason)] #![allow(unfulfilled_lint_expectations, clippy::duplicated_attributes)] +//~^ allow_attributes_without_reason extern crate proc_macros; use proc_macros::{external, with_span}; // These should trigger the lint #[allow(dead_code)] +//~^ allow_attributes_without_reason #[allow(dead_code, deprecated)] +//~^ allow_attributes_without_reason #[expect(dead_code)] +//~^ allow_attributes_without_reason // These should be fine #[allow(dead_code, reason = "This should be allowed")] #[warn(dyn_drop, reason = "Warnings can also have reasons")] @@ -44,6 +48,7 @@ pub fn trigger_fp_result() -> Result<(), &'static str> { #[clippy::msrv = "1.81"] fn msrv_1_81() { #[allow(unused)] + //~^ allow_attributes_without_reason let _ = 1; } diff --git a/tests/ui/allow_attributes_without_reason.stderr b/tests/ui/allow_attributes_without_reason.stderr index 9c1ac5af91b0..07e74839b769 100644 --- a/tests/ui/allow_attributes_without_reason.stderr +++ b/tests/ui/allow_attributes_without_reason.stderr @@ -12,7 +12,7 @@ LL | #![deny(clippy::allow_attributes_without_reason)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `allow` attribute without specifying a reason - --> tests/ui/allow_attributes_without_reason.rs:9:1 + --> tests/ui/allow_attributes_without_reason.rs:10:1 | LL | #[allow(dead_code)] | ^^^^^^^^^^^^^^^^^^^ @@ -20,7 +20,7 @@ LL | #[allow(dead_code)] = help: try adding a reason at the end with `, reason = ".."` error: `allow` attribute without specifying a reason - --> tests/ui/allow_attributes_without_reason.rs:10:1 + --> tests/ui/allow_attributes_without_reason.rs:12:1 | LL | #[allow(dead_code, deprecated)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | #[allow(dead_code, deprecated)] = help: try adding a reason at the end with `, reason = ".."` error: `expect` attribute without specifying a reason - --> tests/ui/allow_attributes_without_reason.rs:11:1 + --> tests/ui/allow_attributes_without_reason.rs:14:1 | LL | #[expect(dead_code)] | ^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +36,7 @@ LL | #[expect(dead_code)] = help: try adding a reason at the end with `, reason = ".."` error: `allow` attribute without specifying a reason - --> tests/ui/allow_attributes_without_reason.rs:46:5 + --> tests/ui/allow_attributes_without_reason.rs:50:5 | LL | #[allow(unused)] | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/almost_complete_range.fixed b/tests/ui/almost_complete_range.fixed index 6c2b2f117437..7591508b8350 100644 --- a/tests/ui/almost_complete_range.fixed +++ b/tests/ui/almost_complete_range.fixed @@ -15,8 +15,11 @@ fn main() { #[rustfmt::skip] { let _ = ('a') ..='z'; + //~^ almost_complete_range let _ = 'A' ..= ('Z'); + //~^ almost_complete_range let _ = ((('0'))) ..= ('9'); + //~^ almost_complete_range } let _ = 'b'..'z'; @@ -24,21 +27,30 @@ fn main() { let _ = '1'..'9'; let _ = (b'a')..=(b'z'); + //~^ almost_complete_range let _ = b'A'..=b'Z'; + //~^ almost_complete_range let _ = b'0'..=b'9'; + //~^ almost_complete_range let _ = b'b'..b'z'; let _ = b'B'..b'Z'; let _ = b'1'..b'9'; let _ = inline!('a')..='z'; + //~^ almost_complete_range let _ = inline!('A')..='Z'; + //~^ almost_complete_range let _ = inline!('0')..='9'; + //~^ almost_complete_range let _ = match 0u8 { b'a'..=b'z' if true => 1, + //~^ almost_complete_range b'A'..=b'Z' if true => 2, + //~^ almost_complete_range b'0'..=b'9' if true => 3, + //~^ almost_complete_range b'b'..b'z' => 4, b'B'..b'Z' => 5, b'1'..b'9' => 6, @@ -47,8 +59,11 @@ fn main() { let _ = match 'x' { 'a'..='z' if true => 1, + //~^ almost_complete_range 'A'..='Z' if true => 2, + //~^ almost_complete_range '0'..='9' if true => 3, + //~^ almost_complete_range 'b'..'z' => 4, 'B'..'Z' => 5, '1'..'9' => 6, @@ -62,8 +77,11 @@ fn main() { ); inline!( let _ = 'a'..='z'; + //~^ almost_complete_range let _ = 'A'..='Z'; + //~^ almost_complete_range let _ = '0'..='9'; + //~^ almost_complete_range ); } @@ -71,8 +89,11 @@ fn main() { fn _under_msrv() { let _ = match 'a' { 'a'...'z' => 1, + //~^ almost_complete_range 'A'...'Z' => 2, + //~^ almost_complete_range '0'...'9' => 3, + //~^ almost_complete_range _ => 4, }; } @@ -80,12 +101,18 @@ fn _under_msrv() { #[clippy::msrv = "1.26"] fn _meets_msrv() { let _ = 'a'..='z'; + //~^ almost_complete_range let _ = 'A'..='Z'; + //~^ almost_complete_range let _ = '0'..='9'; + //~^ almost_complete_range let _ = match 'a' { 'a'..='z' => 1, + //~^ almost_complete_range 'A'..='Z' => 1, + //~^ almost_complete_range '0'..='9' => 3, + //~^ almost_complete_range _ => 4, }; } diff --git a/tests/ui/almost_complete_range.rs b/tests/ui/almost_complete_range.rs index 813668a53096..907f70bd8156 100644 --- a/tests/ui/almost_complete_range.rs +++ b/tests/ui/almost_complete_range.rs @@ -15,8 +15,11 @@ fn main() { #[rustfmt::skip] { let _ = ('a') ..'z'; + //~^ almost_complete_range let _ = 'A' .. ('Z'); + //~^ almost_complete_range let _ = ((('0'))) .. ('9'); + //~^ almost_complete_range } let _ = 'b'..'z'; @@ -24,21 +27,30 @@ fn main() { let _ = '1'..'9'; let _ = (b'a')..(b'z'); + //~^ almost_complete_range let _ = b'A'..b'Z'; + //~^ almost_complete_range let _ = b'0'..b'9'; + //~^ almost_complete_range let _ = b'b'..b'z'; let _ = b'B'..b'Z'; let _ = b'1'..b'9'; let _ = inline!('a')..'z'; + //~^ almost_complete_range let _ = inline!('A')..'Z'; + //~^ almost_complete_range let _ = inline!('0')..'9'; + //~^ almost_complete_range let _ = match 0u8 { b'a'..b'z' if true => 1, + //~^ almost_complete_range b'A'..b'Z' if true => 2, + //~^ almost_complete_range b'0'..b'9' if true => 3, + //~^ almost_complete_range b'b'..b'z' => 4, b'B'..b'Z' => 5, b'1'..b'9' => 6, @@ -47,8 +59,11 @@ fn main() { let _ = match 'x' { 'a'..'z' if true => 1, + //~^ almost_complete_range 'A'..'Z' if true => 2, + //~^ almost_complete_range '0'..'9' if true => 3, + //~^ almost_complete_range 'b'..'z' => 4, 'B'..'Z' => 5, '1'..'9' => 6, @@ -62,8 +77,11 @@ fn main() { ); inline!( let _ = 'a'..'z'; + //~^ almost_complete_range let _ = 'A'..'Z'; + //~^ almost_complete_range let _ = '0'..'9'; + //~^ almost_complete_range ); } @@ -71,8 +89,11 @@ fn main() { fn _under_msrv() { let _ = match 'a' { 'a'..'z' => 1, + //~^ almost_complete_range 'A'..'Z' => 2, + //~^ almost_complete_range '0'..'9' => 3, + //~^ almost_complete_range _ => 4, }; } @@ -80,12 +101,18 @@ fn _under_msrv() { #[clippy::msrv = "1.26"] fn _meets_msrv() { let _ = 'a'..'z'; + //~^ almost_complete_range let _ = 'A'..'Z'; + //~^ almost_complete_range let _ = '0'..'9'; + //~^ almost_complete_range let _ = match 'a' { 'a'..'z' => 1, + //~^ almost_complete_range 'A'..'Z' => 1, + //~^ almost_complete_range '0'..'9' => 3, + //~^ almost_complete_range _ => 4, }; } diff --git a/tests/ui/almost_complete_range.stderr b/tests/ui/almost_complete_range.stderr index bfc2beb07d85..217df7f4883f 100644 --- a/tests/ui/almost_complete_range.stderr +++ b/tests/ui/almost_complete_range.stderr @@ -10,7 +10,7 @@ LL | let _ = ('a') ..'z'; = help: to override `-D warnings` add `#[allow(clippy::almost_complete_range)]` error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:18:17 + --> tests/ui/almost_complete_range.rs:19:17 | LL | let _ = 'A' .. ('Z'); | ^^^^--^^^^^^ @@ -18,7 +18,7 @@ LL | let _ = 'A' .. ('Z'); | help: use an inclusive range: `..=` error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:19:17 + --> tests/ui/almost_complete_range.rs:21:17 | LL | let _ = ((('0'))) .. ('9'); | ^^^^^^^^^^--^^^^^^ @@ -26,7 +26,7 @@ LL | let _ = ((('0'))) .. ('9'); | help: use an inclusive range: `..=` error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:26:13 + --> tests/ui/almost_complete_range.rs:29:13 | LL | let _ = (b'a')..(b'z'); | ^^^^^^--^^^^^^ @@ -34,7 +34,7 @@ LL | let _ = (b'a')..(b'z'); | help: use an inclusive range: `..=` error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:27:13 + --> tests/ui/almost_complete_range.rs:31:13 | LL | let _ = b'A'..b'Z'; | ^^^^--^^^^ @@ -42,7 +42,7 @@ LL | let _ = b'A'..b'Z'; | help: use an inclusive range: `..=` error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:28:13 + --> tests/ui/almost_complete_range.rs:33:13 | LL | let _ = b'0'..b'9'; | ^^^^--^^^^ @@ -50,7 +50,7 @@ LL | let _ = b'0'..b'9'; | help: use an inclusive range: `..=` error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:34:13 + --> tests/ui/almost_complete_range.rs:40:13 | LL | let _ = inline!('a')..'z'; | ^^^^^^^^^^^^--^^^ @@ -58,7 +58,7 @@ LL | let _ = inline!('a')..'z'; | help: use an inclusive range: `..=` error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:35:13 + --> tests/ui/almost_complete_range.rs:42:13 | LL | let _ = inline!('A')..'Z'; | ^^^^^^^^^^^^--^^^ @@ -66,7 +66,7 @@ LL | let _ = inline!('A')..'Z'; | help: use an inclusive range: `..=` error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:36:13 + --> tests/ui/almost_complete_range.rs:44:13 | LL | let _ = inline!('0')..'9'; | ^^^^^^^^^^^^--^^^ @@ -74,7 +74,7 @@ LL | let _ = inline!('0')..'9'; | help: use an inclusive range: `..=` error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:39:9 + --> tests/ui/almost_complete_range.rs:48:9 | LL | b'a'..b'z' if true => 1, | ^^^^--^^^^ @@ -82,7 +82,7 @@ LL | b'a'..b'z' if true => 1, | help: use an inclusive range: `..=` error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:40:9 + --> tests/ui/almost_complete_range.rs:50:9 | LL | b'A'..b'Z' if true => 2, | ^^^^--^^^^ @@ -90,7 +90,7 @@ LL | b'A'..b'Z' if true => 2, | help: use an inclusive range: `..=` error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:41:9 + --> tests/ui/almost_complete_range.rs:52:9 | LL | b'0'..b'9' if true => 3, | ^^^^--^^^^ @@ -98,7 +98,7 @@ LL | b'0'..b'9' if true => 3, | help: use an inclusive range: `..=` error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:49:9 + --> tests/ui/almost_complete_range.rs:61:9 | LL | 'a'..'z' if true => 1, | ^^^--^^^ @@ -106,7 +106,7 @@ LL | 'a'..'z' if true => 1, | help: use an inclusive range: `..=` error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:50:9 + --> tests/ui/almost_complete_range.rs:63:9 | LL | 'A'..'Z' if true => 2, | ^^^--^^^ @@ -114,7 +114,7 @@ LL | 'A'..'Z' if true => 2, | help: use an inclusive range: `..=` error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:51:9 + --> tests/ui/almost_complete_range.rs:65:9 | LL | '0'..'9' if true => 3, | ^^^--^^^ @@ -122,7 +122,7 @@ LL | '0'..'9' if true => 3, | help: use an inclusive range: `..=` error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:64:17 + --> tests/ui/almost_complete_range.rs:79:17 | LL | let _ = 'a'..'z'; | ^^^--^^^ @@ -132,7 +132,7 @@ LL | let _ = 'a'..'z'; = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info) error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:65:17 + --> tests/ui/almost_complete_range.rs:81:17 | LL | let _ = 'A'..'Z'; | ^^^--^^^ @@ -142,7 +142,7 @@ LL | let _ = 'A'..'Z'; = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info) error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:66:17 + --> tests/ui/almost_complete_range.rs:83:17 | LL | let _ = '0'..'9'; | ^^^--^^^ @@ -152,7 +152,7 @@ LL | let _ = '0'..'9'; = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info) error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:73:9 + --> tests/ui/almost_complete_range.rs:91:9 | LL | 'a'..'z' => 1, | ^^^--^^^ @@ -160,7 +160,7 @@ LL | 'a'..'z' => 1, | help: use an inclusive range: `...` error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:74:9 + --> tests/ui/almost_complete_range.rs:93:9 | LL | 'A'..'Z' => 2, | ^^^--^^^ @@ -168,7 +168,7 @@ LL | 'A'..'Z' => 2, | help: use an inclusive range: `...` error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:75:9 + --> tests/ui/almost_complete_range.rs:95:9 | LL | '0'..'9' => 3, | ^^^--^^^ @@ -176,7 +176,7 @@ LL | '0'..'9' => 3, | help: use an inclusive range: `...` error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:82:13 + --> tests/ui/almost_complete_range.rs:103:13 | LL | let _ = 'a'..'z'; | ^^^--^^^ @@ -184,7 +184,7 @@ LL | let _ = 'a'..'z'; | help: use an inclusive range: `..=` error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:83:13 + --> tests/ui/almost_complete_range.rs:105:13 | LL | let _ = 'A'..'Z'; | ^^^--^^^ @@ -192,7 +192,7 @@ LL | let _ = 'A'..'Z'; | help: use an inclusive range: `..=` error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:84:13 + --> tests/ui/almost_complete_range.rs:107:13 | LL | let _ = '0'..'9'; | ^^^--^^^ @@ -200,7 +200,7 @@ LL | let _ = '0'..'9'; | help: use an inclusive range: `..=` error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:86:9 + --> tests/ui/almost_complete_range.rs:110:9 | LL | 'a'..'z' => 1, | ^^^--^^^ @@ -208,7 +208,7 @@ LL | 'a'..'z' => 1, | help: use an inclusive range: `..=` error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:87:9 + --> tests/ui/almost_complete_range.rs:112:9 | LL | 'A'..'Z' => 1, | ^^^--^^^ @@ -216,7 +216,7 @@ LL | 'A'..'Z' => 1, | help: use an inclusive range: `..=` error: almost complete ascii range - --> tests/ui/almost_complete_range.rs:88:9 + --> tests/ui/almost_complete_range.rs:114:9 | LL | '0'..'9' => 3, | ^^^--^^^ diff --git a/tests/ui/approx_const.rs b/tests/ui/approx_const.rs index 3c4ed0367894..6461666be8f5 100644 --- a/tests/ui/approx_const.rs +++ b/tests/ui/approx_const.rs @@ -1,86 +1,109 @@ #[warn(clippy::approx_constant)] fn main() { let my_e = 2.7182; - //~^ ERROR: approximate value of `f{32, 64}::consts::E` found + //~^ approx_constant + let almost_e = 2.718; - //~^ ERROR: approximate value of `f{32, 64}::consts::E` found + //~^ approx_constant + let no_e = 2.71; let my_1_frac_pi = 0.3183; - //~^ ERROR: approximate value of `f{32, 64}::consts::FRAC_1_PI` found + //~^ approx_constant + let no_1_frac_pi = 0.31; let my_frac_1_sqrt_2 = 0.70710678; - //~^ ERROR: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found + //~^ approx_constant + let almost_frac_1_sqrt_2 = 0.70711; - //~^ ERROR: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found + //~^ approx_constant + let my_frac_1_sqrt_2 = 0.707; let my_frac_2_pi = 0.63661977; - //~^ ERROR: approximate value of `f{32, 64}::consts::FRAC_2_PI` found + //~^ approx_constant + let no_frac_2_pi = 0.636; let my_frac_2_sq_pi = 1.128379; - //~^ ERROR: approximate value of `f{32, 64}::consts::FRAC_2_SQRT_PI` found + //~^ approx_constant + let no_frac_2_sq_pi = 1.128; let my_frac_pi_2 = 1.57079632679; - //~^ ERROR: approximate value of `f{32, 64}::consts::FRAC_PI_2` found + //~^ approx_constant + let no_frac_pi_2 = 1.5705; let my_frac_pi_3 = 1.04719755119; - //~^ ERROR: approximate value of `f{32, 64}::consts::FRAC_PI_3` found + //~^ approx_constant + let no_frac_pi_3 = 1.047; let my_frac_pi_4 = 0.785398163397; - //~^ ERROR: approximate value of `f{32, 64}::consts::FRAC_PI_4` found + //~^ approx_constant + let no_frac_pi_4 = 0.785; let my_frac_pi_6 = 0.523598775598; - //~^ ERROR: approximate value of `f{32, 64}::consts::FRAC_PI_6` found + //~^ approx_constant + let no_frac_pi_6 = 0.523; let my_frac_pi_8 = 0.3926990816987; - //~^ ERROR: approximate value of `f{32, 64}::consts::FRAC_PI_8` found + //~^ approx_constant + let no_frac_pi_8 = 0.392; let my_ln_10 = 2.302585092994046; - //~^ ERROR: approximate value of `f{32, 64}::consts::LN_10` found + //~^ approx_constant + let no_ln_10 = 2.303; let my_ln_2 = 0.6931471805599453; - //~^ ERROR: approximate value of `f{32, 64}::consts::LN_2` found + //~^ approx_constant + let no_ln_2 = 0.693; let my_log10_e = 0.4342944819032518; - //~^ ERROR: approximate value of `f{32, 64}::consts::LOG10_E` found + //~^ approx_constant + let no_log10_e = 0.434; let my_log2_e = 1.4426950408889634; - //~^ ERROR: approximate value of `f{32, 64}::consts::LOG2_E` found + //~^ approx_constant + let no_log2_e = 1.442; let log2_10 = 3.321928094887362; - //~^ ERROR: approximate value of `f{32, 64}::consts::LOG2_10` found + //~^ approx_constant + let no_log2_10 = 3.321; let log10_2 = 0.301029995663981; - //~^ ERROR: approximate value of `f{32, 64}::consts::LOG10_2` found + //~^ approx_constant + let no_log10_2 = 0.301; let my_pi = 3.1415; - //~^ ERROR: approximate value of `f{32, 64}::consts::PI` found + //~^ approx_constant + let almost_pi = 3.14; - //~^ ERROR: approximate value of `f{32, 64}::consts::PI` found + //~^ approx_constant + let no_pi = 3.15; let my_sq2 = 1.4142; - //~^ ERROR: approximate value of `f{32, 64}::consts::SQRT_2` found + //~^ approx_constant + let no_sq2 = 1.414; let my_tau = 6.2832; - //~^ ERROR: approximate value of `f{32, 64}::consts::TAU` found + //~^ approx_constant + let almost_tau = 6.28; - //~^ ERROR: approximate value of `f{32, 64}::consts::TAU` found + //~^ approx_constant + let no_tau = 6.3; } diff --git a/tests/ui/approx_const.stderr b/tests/ui/approx_const.stderr index 5e82d51edf20..f7bda0468cbd 100644 --- a/tests/ui/approx_const.stderr +++ b/tests/ui/approx_const.stderr @@ -9,7 +9,7 @@ LL | let my_e = 2.7182; = help: to override `-D warnings` add `#[allow(clippy::approx_constant)]` error: approximate value of `f{32, 64}::consts::E` found - --> tests/ui/approx_const.rs:5:20 + --> tests/ui/approx_const.rs:6:20 | LL | let almost_e = 2.718; | ^^^^^ @@ -17,7 +17,7 @@ LL | let almost_e = 2.718; = help: consider using the constant directly error: approximate value of `f{32, 64}::consts::FRAC_1_PI` found - --> tests/ui/approx_const.rs:9:24 + --> tests/ui/approx_const.rs:11:24 | LL | let my_1_frac_pi = 0.3183; | ^^^^^^ @@ -25,7 +25,7 @@ LL | let my_1_frac_pi = 0.3183; = help: consider using the constant directly error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found - --> tests/ui/approx_const.rs:13:28 + --> tests/ui/approx_const.rs:16:28 | LL | let my_frac_1_sqrt_2 = 0.70710678; | ^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | let my_frac_1_sqrt_2 = 0.70710678; = help: consider using the constant directly error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found - --> tests/ui/approx_const.rs:15:32 + --> tests/ui/approx_const.rs:19:32 | LL | let almost_frac_1_sqrt_2 = 0.70711; | ^^^^^^^ @@ -41,7 +41,7 @@ LL | let almost_frac_1_sqrt_2 = 0.70711; = help: consider using the constant directly error: approximate value of `f{32, 64}::consts::FRAC_2_PI` found - --> tests/ui/approx_const.rs:19:24 + --> tests/ui/approx_const.rs:24:24 | LL | let my_frac_2_pi = 0.63661977; | ^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | let my_frac_2_pi = 0.63661977; = help: consider using the constant directly error: approximate value of `f{32, 64}::consts::FRAC_2_SQRT_PI` found - --> tests/ui/approx_const.rs:23:27 + --> tests/ui/approx_const.rs:29:27 | LL | let my_frac_2_sq_pi = 1.128379; | ^^^^^^^^ @@ -57,7 +57,7 @@ LL | let my_frac_2_sq_pi = 1.128379; = help: consider using the constant directly error: approximate value of `f{32, 64}::consts::FRAC_PI_2` found - --> tests/ui/approx_const.rs:27:24 + --> tests/ui/approx_const.rs:34:24 | LL | let my_frac_pi_2 = 1.57079632679; | ^^^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | let my_frac_pi_2 = 1.57079632679; = help: consider using the constant directly error: approximate value of `f{32, 64}::consts::FRAC_PI_3` found - --> tests/ui/approx_const.rs:31:24 + --> tests/ui/approx_const.rs:39:24 | LL | let my_frac_pi_3 = 1.04719755119; | ^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | let my_frac_pi_3 = 1.04719755119; = help: consider using the constant directly error: approximate value of `f{32, 64}::consts::FRAC_PI_4` found - --> tests/ui/approx_const.rs:35:24 + --> tests/ui/approx_const.rs:44:24 | LL | let my_frac_pi_4 = 0.785398163397; | ^^^^^^^^^^^^^^ @@ -81,7 +81,7 @@ LL | let my_frac_pi_4 = 0.785398163397; = help: consider using the constant directly error: approximate value of `f{32, 64}::consts::FRAC_PI_6` found - --> tests/ui/approx_const.rs:39:24 + --> tests/ui/approx_const.rs:49:24 | LL | let my_frac_pi_6 = 0.523598775598; | ^^^^^^^^^^^^^^ @@ -89,7 +89,7 @@ LL | let my_frac_pi_6 = 0.523598775598; = help: consider using the constant directly error: approximate value of `f{32, 64}::consts::FRAC_PI_8` found - --> tests/ui/approx_const.rs:43:24 + --> tests/ui/approx_const.rs:54:24 | LL | let my_frac_pi_8 = 0.3926990816987; | ^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL | let my_frac_pi_8 = 0.3926990816987; = help: consider using the constant directly error: approximate value of `f{32, 64}::consts::LN_10` found - --> tests/ui/approx_const.rs:47:20 + --> tests/ui/approx_const.rs:59:20 | LL | let my_ln_10 = 2.302585092994046; | ^^^^^^^^^^^^^^^^^ @@ -105,7 +105,7 @@ LL | let my_ln_10 = 2.302585092994046; = help: consider using the constant directly error: approximate value of `f{32, 64}::consts::LN_2` found - --> tests/ui/approx_const.rs:51:19 + --> tests/ui/approx_const.rs:64:19 | LL | let my_ln_2 = 0.6931471805599453; | ^^^^^^^^^^^^^^^^^^ @@ -113,7 +113,7 @@ LL | let my_ln_2 = 0.6931471805599453; = help: consider using the constant directly error: approximate value of `f{32, 64}::consts::LOG10_E` found - --> tests/ui/approx_const.rs:55:22 + --> tests/ui/approx_const.rs:69:22 | LL | let my_log10_e = 0.4342944819032518; | ^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL | let my_log10_e = 0.4342944819032518; = help: consider using the constant directly error: approximate value of `f{32, 64}::consts::LOG2_E` found - --> tests/ui/approx_const.rs:59:21 + --> tests/ui/approx_const.rs:74:21 | LL | let my_log2_e = 1.4426950408889634; | ^^^^^^^^^^^^^^^^^^ @@ -129,7 +129,7 @@ LL | let my_log2_e = 1.4426950408889634; = help: consider using the constant directly error: approximate value of `f{32, 64}::consts::LOG2_10` found - --> tests/ui/approx_const.rs:63:19 + --> tests/ui/approx_const.rs:79:19 | LL | let log2_10 = 3.321928094887362; | ^^^^^^^^^^^^^^^^^ @@ -137,7 +137,7 @@ LL | let log2_10 = 3.321928094887362; = help: consider using the constant directly error: approximate value of `f{32, 64}::consts::LOG10_2` found - --> tests/ui/approx_const.rs:67:19 + --> tests/ui/approx_const.rs:84:19 | LL | let log10_2 = 0.301029995663981; | ^^^^^^^^^^^^^^^^^ @@ -145,7 +145,7 @@ LL | let log10_2 = 0.301029995663981; = help: consider using the constant directly error: approximate value of `f{32, 64}::consts::PI` found - --> tests/ui/approx_const.rs:71:17 + --> tests/ui/approx_const.rs:89:17 | LL | let my_pi = 3.1415; | ^^^^^^ @@ -153,7 +153,7 @@ LL | let my_pi = 3.1415; = help: consider using the constant directly error: approximate value of `f{32, 64}::consts::PI` found - --> tests/ui/approx_const.rs:73:21 + --> tests/ui/approx_const.rs:92:21 | LL | let almost_pi = 3.14; | ^^^^ @@ -161,7 +161,7 @@ LL | let almost_pi = 3.14; = help: consider using the constant directly error: approximate value of `f{32, 64}::consts::SQRT_2` found - --> tests/ui/approx_const.rs:77:18 + --> tests/ui/approx_const.rs:97:18 | LL | let my_sq2 = 1.4142; | ^^^^^^ @@ -169,7 +169,7 @@ LL | let my_sq2 = 1.4142; = help: consider using the constant directly error: approximate value of `f{32, 64}::consts::TAU` found - --> tests/ui/approx_const.rs:81:18 + --> tests/ui/approx_const.rs:102:18 | LL | let my_tau = 6.2832; | ^^^^^^ @@ -177,7 +177,7 @@ LL | let my_tau = 6.2832; = help: consider using the constant directly error: approximate value of `f{32, 64}::consts::TAU` found - --> tests/ui/approx_const.rs:83:22 + --> tests/ui/approx_const.rs:105:22 | LL | let almost_tau = 6.28; | ^^^^ diff --git a/tests/ui/arc_with_non_send_sync.rs b/tests/ui/arc_with_non_send_sync.rs index c287480bb1fd..07025ccc42fd 100644 --- a/tests/ui/arc_with_non_send_sync.rs +++ b/tests/ui/arc_with_non_send_sync.rs @@ -33,9 +33,12 @@ fn main() { let _ = Arc::new(42); let _ = Arc::new(RefCell::new(42)); + //~^ arc_with_non_send_sync let mutex = Mutex::new(1); let _ = Arc::new(mutex.lock().unwrap()); + //~^ arc_with_non_send_sync let _ = Arc::new(&42 as *const i32); + //~^ arc_with_non_send_sync } diff --git a/tests/ui/arc_with_non_send_sync.stderr b/tests/ui/arc_with_non_send_sync.stderr index da363a3ebdd9..5556b0df88c9 100644 --- a/tests/ui/arc_with_non_send_sync.stderr +++ b/tests/ui/arc_with_non_send_sync.stderr @@ -11,7 +11,7 @@ LL | let _ = Arc::new(RefCell::new(42)); = help: to override `-D warnings` add `#[allow(clippy::arc_with_non_send_sync)]` error: usage of an `Arc` that is not `Send` and `Sync` - --> tests/ui/arc_with_non_send_sync.rs:38:13 + --> tests/ui/arc_with_non_send_sync.rs:39:13 | LL | let _ = Arc::new(mutex.lock().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -21,7 +21,7 @@ LL | let _ = Arc::new(mutex.lock().unwrap()); = help: otherwise make `MutexGuard<'_, i32>` `Send` and `Sync` or consider a wrapper type such as `Mutex` error: usage of an `Arc` that is not `Send` and `Sync` - --> tests/ui/arc_with_non_send_sync.rs:40:13 + --> tests/ui/arc_with_non_send_sync.rs:42:13 | LL | let _ = Arc::new(&42 as *const i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/arithmetic_side_effects.rs b/tests/ui/arithmetic_side_effects.rs index f09106773c7e..21be2af201f0 100644 --- a/tests/ui/arithmetic_side_effects.rs +++ b/tests/ui/arithmetic_side_effects.rs @@ -164,13 +164,16 @@ pub fn association_with_structures_should_not_trigger_the_lint() { pub fn hard_coded_allowed() { let _ = 1f16 + 1f16; + //~^ arithmetic_side_effects let _ = 1f32 + 1f32; let _ = 1f64 + 1f64; let _ = 1f128 + 1f128; + //~^ arithmetic_side_effects let _ = Saturating(0u32) + Saturating(0u32); let _ = String::new() + ""; let _ = String::new() + &String::new(); + //~^ arithmetic_side_effects let _ = Wrapping(0u32) + Wrapping(0u32); let saturating: Saturating = Saturating(0u32); @@ -306,117 +309,221 @@ pub fn unknown_ops_or_runtime_ops_that_can_overflow() { // Assign _n += 1; + //~^ arithmetic_side_effects _n += &1; + //~^ arithmetic_side_effects _n -= 1; + //~^ arithmetic_side_effects _n -= &1; + //~^ arithmetic_side_effects _n /= 0; + //~^ arithmetic_side_effects _n /= &0; + //~^ arithmetic_side_effects _n %= 0; + //~^ arithmetic_side_effects _n %= &0; + //~^ arithmetic_side_effects _n *= 2; + //~^ arithmetic_side_effects _n *= &2; + //~^ arithmetic_side_effects _n += -1; + //~^ arithmetic_side_effects _n += &-1; + //~^ arithmetic_side_effects _n -= -1; + //~^ arithmetic_side_effects _n -= &-1; + //~^ arithmetic_side_effects _n /= -0; + //~^ arithmetic_side_effects _n /= &-0; + //~^ arithmetic_side_effects _n %= -0; + //~^ arithmetic_side_effects _n %= &-0; + //~^ arithmetic_side_effects _n *= -2; + //~^ arithmetic_side_effects _n *= &-2; + //~^ arithmetic_side_effects _custom += Custom; + //~^ arithmetic_side_effects _custom += &Custom; + //~^ arithmetic_side_effects _custom -= Custom; + //~^ arithmetic_side_effects _custom -= &Custom; + //~^ arithmetic_side_effects _custom /= Custom; + //~^ arithmetic_side_effects _custom /= &Custom; + //~^ arithmetic_side_effects _custom %= Custom; + //~^ arithmetic_side_effects _custom %= &Custom; + //~^ arithmetic_side_effects _custom *= Custom; + //~^ arithmetic_side_effects _custom *= &Custom; + //~^ arithmetic_side_effects _custom >>= Custom; + //~^ arithmetic_side_effects _custom >>= &Custom; + //~^ arithmetic_side_effects _custom <<= Custom; + //~^ arithmetic_side_effects _custom <<= &Custom; + //~^ arithmetic_side_effects _custom += -Custom; + //~^ arithmetic_side_effects _custom += &-Custom; + //~^ arithmetic_side_effects _custom -= -Custom; + //~^ arithmetic_side_effects _custom -= &-Custom; + //~^ arithmetic_side_effects _custom /= -Custom; + //~^ arithmetic_side_effects _custom /= &-Custom; + //~^ arithmetic_side_effects _custom %= -Custom; + //~^ arithmetic_side_effects _custom %= &-Custom; + //~^ arithmetic_side_effects _custom *= -Custom; + //~^ arithmetic_side_effects _custom *= &-Custom; + //~^ arithmetic_side_effects _custom >>= -Custom; + //~^ arithmetic_side_effects _custom >>= &-Custom; + //~^ arithmetic_side_effects _custom <<= -Custom; + //~^ arithmetic_side_effects _custom <<= &-Custom; + //~^ arithmetic_side_effects // Binary _n = _n + 1; + //~^ arithmetic_side_effects _n = _n + &1; + //~^ arithmetic_side_effects _n = 1 + _n; + //~^ arithmetic_side_effects _n = &1 + _n; + //~^ arithmetic_side_effects _n = _n - 1; + //~^ arithmetic_side_effects _n = _n - &1; + //~^ arithmetic_side_effects _n = 1 - _n; + //~^ arithmetic_side_effects _n = &1 - _n; + //~^ arithmetic_side_effects _n = _n / 0; + //~^ arithmetic_side_effects _n = _n / &0; + //~^ arithmetic_side_effects _n = _n % 0; + //~^ arithmetic_side_effects _n = _n % &0; + //~^ arithmetic_side_effects _n = _n * 2; + //~^ arithmetic_side_effects _n = _n * &2; + //~^ arithmetic_side_effects _n = 2 * _n; + //~^ arithmetic_side_effects _n = &2 * _n; + //~^ arithmetic_side_effects _n = 23 + &85; + //~^ arithmetic_side_effects _n = &23 + 85; + //~^ arithmetic_side_effects _n = &23 + &85; + //~^ arithmetic_side_effects _custom = _custom + _custom; + //~^ arithmetic_side_effects _custom = _custom + &_custom; + //~^ arithmetic_side_effects _custom = Custom + _custom; + //~^ arithmetic_side_effects _custom = &Custom + _custom; + //~^ arithmetic_side_effects _custom = _custom - Custom; + //~^ arithmetic_side_effects _custom = _custom - &Custom; + //~^ arithmetic_side_effects _custom = Custom - _custom; + //~^ arithmetic_side_effects _custom = &Custom - _custom; + //~^ arithmetic_side_effects _custom = _custom / Custom; + //~^ arithmetic_side_effects _custom = _custom / &Custom; + //~^ arithmetic_side_effects _custom = _custom % Custom; + //~^ arithmetic_side_effects _custom = _custom % &Custom; + //~^ arithmetic_side_effects _custom = _custom * Custom; + //~^ arithmetic_side_effects _custom = _custom * &Custom; + //~^ arithmetic_side_effects _custom = Custom * _custom; + //~^ arithmetic_side_effects _custom = &Custom * _custom; + //~^ arithmetic_side_effects _custom = Custom + &Custom; + //~^ arithmetic_side_effects _custom = &Custom + Custom; + //~^ arithmetic_side_effects _custom = &Custom + &Custom; + //~^ arithmetic_side_effects _custom = _custom >> _custom; + //~^ arithmetic_side_effects _custom = _custom >> &_custom; + //~^ arithmetic_side_effects _custom = Custom << _custom; + //~^ arithmetic_side_effects _custom = &Custom << _custom; + //~^ arithmetic_side_effects // Method _n.saturating_div(0); + //~^ arithmetic_side_effects _n.wrapping_div(0); + //~^ arithmetic_side_effects _n.wrapping_rem(0); + //~^ arithmetic_side_effects _n.wrapping_rem_euclid(0); + //~^ arithmetic_side_effects _n.saturating_div(_n); + //~^ arithmetic_side_effects _n.wrapping_div(_n); + //~^ arithmetic_side_effects _n.wrapping_rem(_n); + //~^ arithmetic_side_effects _n.wrapping_rem_euclid(_n); + //~^ arithmetic_side_effects _n.saturating_div(*Box::new(_n)); + //~^ arithmetic_side_effects // Unary _n = -_n; + //~^ arithmetic_side_effects _n = -&_n; + //~^ arithmetic_side_effects _custom = -_custom; + //~^ arithmetic_side_effects _custom = -&_custom; + //~^ arithmetic_side_effects _ = -*Box::new(_n); + //~^ arithmetic_side_effects } // Copied and pasted from the `integer_arithmetic` lint for comparison. @@ -426,10 +533,15 @@ pub fn integer_arithmetic() { let mut var2 = -1i32; 1 + i; + //~^ arithmetic_side_effects i * 2; + //~^ arithmetic_side_effects 1 % i / 2; + //~^ arithmetic_side_effects i - 2 + 2 - i; + //~^ arithmetic_side_effects -i; + //~^ arithmetic_side_effects i >> 1; i << 1; @@ -441,18 +553,27 @@ pub fn integer_arithmetic() { i ^ 1; i += 1; + //~^ arithmetic_side_effects i -= 1; + //~^ arithmetic_side_effects i *= 2; + //~^ arithmetic_side_effects i /= 2; i /= 0; + //~^ arithmetic_side_effects i /= -1; i /= var1; + //~^ arithmetic_side_effects i /= var2; + //~^ arithmetic_side_effects i %= 2; i %= 0; + //~^ arithmetic_side_effects i %= -1; i %= var1; + //~^ arithmetic_side_effects i %= var2; + //~^ arithmetic_side_effects i <<= 3; i >>= 2; @@ -463,6 +584,7 @@ pub fn integer_arithmetic() { pub fn issue_10583(a: u16) -> u16 { 10 / a + //~^ arithmetic_side_effects } pub fn issue_10767() { @@ -517,10 +639,12 @@ pub fn issue_11392() { pub fn issue_11393() { fn example_div(x: Wrapping, maybe_zero: Wrapping) -> Wrapping { x / maybe_zero + //~^ arithmetic_side_effects } fn example_rem(x: Wrapping, maybe_zero: Wrapping) -> Wrapping { x % maybe_zero + //~^ arithmetic_side_effects } let [x, maybe_zero] = [1, 0].map(Wrapping); @@ -532,17 +656,21 @@ pub fn issue_12318() { use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign}; let mut one: i32 = 1; one.add_assign(1); + //~^ arithmetic_side_effects one.div_assign(1); one.mul_assign(1); one.rem_assign(1); one.sub_assign(1); + //~^ arithmetic_side_effects } pub fn explicit_methods() { use core::ops::Add; let one: i32 = 1; one.add(&one); + //~^ arithmetic_side_effects Box::new(one).add(one); + //~^ arithmetic_side_effects } fn main() {} diff --git a/tests/ui/arithmetic_side_effects.stderr b/tests/ui/arithmetic_side_effects.stderr index 9b4cfb83fbb2..e15fb612be5e 100644 --- a/tests/ui/arithmetic_side_effects.stderr +++ b/tests/ui/arithmetic_side_effects.stderr @@ -8,763 +8,763 @@ LL | let _ = 1f16 + 1f16; = help: to override `-D warnings` add `#[allow(clippy::arithmetic_side_effects)]` error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:169:13 + --> tests/ui/arithmetic_side_effects.rs:170:13 | LL | let _ = 1f128 + 1f128; | ^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:173:13 + --> tests/ui/arithmetic_side_effects.rs:175:13 | LL | let _ = String::new() + &String::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:308:5 + --> tests/ui/arithmetic_side_effects.rs:311:5 | LL | _n += 1; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:309:5 + --> tests/ui/arithmetic_side_effects.rs:313:5 | LL | _n += &1; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:310:5 + --> tests/ui/arithmetic_side_effects.rs:315:5 | LL | _n -= 1; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:311:5 + --> tests/ui/arithmetic_side_effects.rs:317:5 | LL | _n -= &1; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:312:5 + --> tests/ui/arithmetic_side_effects.rs:319:5 | LL | _n /= 0; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:313:5 + --> tests/ui/arithmetic_side_effects.rs:321:5 | LL | _n /= &0; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:314:5 + --> tests/ui/arithmetic_side_effects.rs:323:5 | LL | _n %= 0; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:315:5 + --> tests/ui/arithmetic_side_effects.rs:325:5 | LL | _n %= &0; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:316:5 + --> tests/ui/arithmetic_side_effects.rs:327:5 | LL | _n *= 2; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:317:5 + --> tests/ui/arithmetic_side_effects.rs:329:5 | LL | _n *= &2; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:318:5 + --> tests/ui/arithmetic_side_effects.rs:331:5 | LL | _n += -1; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:319:5 + --> tests/ui/arithmetic_side_effects.rs:333:5 | LL | _n += &-1; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:320:5 + --> tests/ui/arithmetic_side_effects.rs:335:5 | LL | _n -= -1; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:321:5 + --> tests/ui/arithmetic_side_effects.rs:337:5 | LL | _n -= &-1; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:322:5 + --> tests/ui/arithmetic_side_effects.rs:339:5 | LL | _n /= -0; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:323:5 + --> tests/ui/arithmetic_side_effects.rs:341:5 | LL | _n /= &-0; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:324:5 + --> tests/ui/arithmetic_side_effects.rs:343:5 | LL | _n %= -0; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:325:5 + --> tests/ui/arithmetic_side_effects.rs:345:5 | LL | _n %= &-0; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:326:5 + --> tests/ui/arithmetic_side_effects.rs:347:5 | LL | _n *= -2; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:327:5 + --> tests/ui/arithmetic_side_effects.rs:349:5 | LL | _n *= &-2; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:328:5 + --> tests/ui/arithmetic_side_effects.rs:351:5 | LL | _custom += Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:329:5 + --> tests/ui/arithmetic_side_effects.rs:353:5 | LL | _custom += &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:330:5 + --> tests/ui/arithmetic_side_effects.rs:355:5 | LL | _custom -= Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:331:5 + --> tests/ui/arithmetic_side_effects.rs:357:5 | LL | _custom -= &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:332:5 + --> tests/ui/arithmetic_side_effects.rs:359:5 | LL | _custom /= Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:333:5 + --> tests/ui/arithmetic_side_effects.rs:361:5 | LL | _custom /= &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:334:5 + --> tests/ui/arithmetic_side_effects.rs:363:5 | LL | _custom %= Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:335:5 + --> tests/ui/arithmetic_side_effects.rs:365:5 | LL | _custom %= &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:336:5 + --> tests/ui/arithmetic_side_effects.rs:367:5 | LL | _custom *= Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:337:5 + --> tests/ui/arithmetic_side_effects.rs:369:5 | LL | _custom *= &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:338:5 + --> tests/ui/arithmetic_side_effects.rs:371:5 | LL | _custom >>= Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:339:5 + --> tests/ui/arithmetic_side_effects.rs:373:5 | LL | _custom >>= &Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:340:5 + --> tests/ui/arithmetic_side_effects.rs:375:5 | LL | _custom <<= Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:341:5 + --> tests/ui/arithmetic_side_effects.rs:377:5 | LL | _custom <<= &Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:342:5 + --> tests/ui/arithmetic_side_effects.rs:379:5 | LL | _custom += -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:343:5 + --> tests/ui/arithmetic_side_effects.rs:381:5 | LL | _custom += &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:344:5 + --> tests/ui/arithmetic_side_effects.rs:383:5 | LL | _custom -= -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:345:5 + --> tests/ui/arithmetic_side_effects.rs:385:5 | LL | _custom -= &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:346:5 + --> tests/ui/arithmetic_side_effects.rs:387:5 | LL | _custom /= -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:347:5 + --> tests/ui/arithmetic_side_effects.rs:389:5 | LL | _custom /= &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:348:5 + --> tests/ui/arithmetic_side_effects.rs:391:5 | LL | _custom %= -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:349:5 + --> tests/ui/arithmetic_side_effects.rs:393:5 | LL | _custom %= &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:350:5 + --> tests/ui/arithmetic_side_effects.rs:395:5 | LL | _custom *= -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:351:5 + --> tests/ui/arithmetic_side_effects.rs:397:5 | LL | _custom *= &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:352:5 + --> tests/ui/arithmetic_side_effects.rs:399:5 | LL | _custom >>= -Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:353:5 + --> tests/ui/arithmetic_side_effects.rs:401:5 | LL | _custom >>= &-Custom; | ^^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:354:5 + --> tests/ui/arithmetic_side_effects.rs:403:5 | LL | _custom <<= -Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:355:5 + --> tests/ui/arithmetic_side_effects.rs:405:5 | LL | _custom <<= &-Custom; | ^^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:358:10 + --> tests/ui/arithmetic_side_effects.rs:409:10 | LL | _n = _n + 1; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:359:10 + --> tests/ui/arithmetic_side_effects.rs:411:10 | LL | _n = _n + &1; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:360:10 + --> tests/ui/arithmetic_side_effects.rs:413:10 | LL | _n = 1 + _n; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:361:10 + --> tests/ui/arithmetic_side_effects.rs:415:10 | LL | _n = &1 + _n; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:362:10 + --> tests/ui/arithmetic_side_effects.rs:417:10 | LL | _n = _n - 1; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:363:10 + --> tests/ui/arithmetic_side_effects.rs:419:10 | LL | _n = _n - &1; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:364:10 + --> tests/ui/arithmetic_side_effects.rs:421:10 | LL | _n = 1 - _n; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:365:10 + --> tests/ui/arithmetic_side_effects.rs:423:10 | LL | _n = &1 - _n; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:366:10 + --> tests/ui/arithmetic_side_effects.rs:425:10 | LL | _n = _n / 0; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:367:10 + --> tests/ui/arithmetic_side_effects.rs:427:10 | LL | _n = _n / &0; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:368:10 + --> tests/ui/arithmetic_side_effects.rs:429:10 | LL | _n = _n % 0; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:369:10 + --> tests/ui/arithmetic_side_effects.rs:431:10 | LL | _n = _n % &0; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:370:10 + --> tests/ui/arithmetic_side_effects.rs:433:10 | LL | _n = _n * 2; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:371:10 + --> tests/ui/arithmetic_side_effects.rs:435:10 | LL | _n = _n * &2; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:372:10 + --> tests/ui/arithmetic_side_effects.rs:437:10 | LL | _n = 2 * _n; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:373:10 + --> tests/ui/arithmetic_side_effects.rs:439:10 | LL | _n = &2 * _n; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:374:10 + --> tests/ui/arithmetic_side_effects.rs:441:10 | LL | _n = 23 + &85; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:375:10 + --> tests/ui/arithmetic_side_effects.rs:443:10 | LL | _n = &23 + 85; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:376:10 + --> tests/ui/arithmetic_side_effects.rs:445:10 | LL | _n = &23 + &85; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:377:15 + --> tests/ui/arithmetic_side_effects.rs:447:15 | LL | _custom = _custom + _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:378:15 + --> tests/ui/arithmetic_side_effects.rs:449:15 | LL | _custom = _custom + &_custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:379:15 + --> tests/ui/arithmetic_side_effects.rs:451:15 | LL | _custom = Custom + _custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:380:15 + --> tests/ui/arithmetic_side_effects.rs:453:15 | LL | _custom = &Custom + _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:381:15 + --> tests/ui/arithmetic_side_effects.rs:455:15 | LL | _custom = _custom - Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:382:15 + --> tests/ui/arithmetic_side_effects.rs:457:15 | LL | _custom = _custom - &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:383:15 + --> tests/ui/arithmetic_side_effects.rs:459:15 | LL | _custom = Custom - _custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:384:15 + --> tests/ui/arithmetic_side_effects.rs:461:15 | LL | _custom = &Custom - _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:385:15 + --> tests/ui/arithmetic_side_effects.rs:463:15 | LL | _custom = _custom / Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:386:15 + --> tests/ui/arithmetic_side_effects.rs:465:15 | LL | _custom = _custom / &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:387:15 + --> tests/ui/arithmetic_side_effects.rs:467:15 | LL | _custom = _custom % Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:388:15 + --> tests/ui/arithmetic_side_effects.rs:469:15 | LL | _custom = _custom % &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:389:15 + --> tests/ui/arithmetic_side_effects.rs:471:15 | LL | _custom = _custom * Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:390:15 + --> tests/ui/arithmetic_side_effects.rs:473:15 | LL | _custom = _custom * &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:391:15 + --> tests/ui/arithmetic_side_effects.rs:475:15 | LL | _custom = Custom * _custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:392:15 + --> tests/ui/arithmetic_side_effects.rs:477:15 | LL | _custom = &Custom * _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:393:15 + --> tests/ui/arithmetic_side_effects.rs:479:15 | LL | _custom = Custom + &Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:394:15 + --> tests/ui/arithmetic_side_effects.rs:481:15 | LL | _custom = &Custom + Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:395:15 + --> tests/ui/arithmetic_side_effects.rs:483:15 | LL | _custom = &Custom + &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:396:15 + --> tests/ui/arithmetic_side_effects.rs:485:15 | LL | _custom = _custom >> _custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:397:15 + --> tests/ui/arithmetic_side_effects.rs:487:15 | LL | _custom = _custom >> &_custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:398:15 + --> tests/ui/arithmetic_side_effects.rs:489:15 | LL | _custom = Custom << _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:399:15 + --> tests/ui/arithmetic_side_effects.rs:491:15 | LL | _custom = &Custom << _custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:402:23 + --> tests/ui/arithmetic_side_effects.rs:495:23 | LL | _n.saturating_div(0); | ^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:403:21 + --> tests/ui/arithmetic_side_effects.rs:497:21 | LL | _n.wrapping_div(0); | ^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:404:21 + --> tests/ui/arithmetic_side_effects.rs:499:21 | LL | _n.wrapping_rem(0); | ^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:405:28 + --> tests/ui/arithmetic_side_effects.rs:501:28 | LL | _n.wrapping_rem_euclid(0); | ^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:407:23 + --> tests/ui/arithmetic_side_effects.rs:504:23 | LL | _n.saturating_div(_n); | ^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:408:21 + --> tests/ui/arithmetic_side_effects.rs:506:21 | LL | _n.wrapping_div(_n); | ^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:409:21 + --> tests/ui/arithmetic_side_effects.rs:508:21 | LL | _n.wrapping_rem(_n); | ^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:410:28 + --> tests/ui/arithmetic_side_effects.rs:510:28 | LL | _n.wrapping_rem_euclid(_n); | ^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:412:23 + --> tests/ui/arithmetic_side_effects.rs:513:23 | LL | _n.saturating_div(*Box::new(_n)); | ^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:415:10 + --> tests/ui/arithmetic_side_effects.rs:517:10 | LL | _n = -_n; | ^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:416:10 + --> tests/ui/arithmetic_side_effects.rs:519:10 | LL | _n = -&_n; | ^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:417:15 + --> tests/ui/arithmetic_side_effects.rs:521:15 | LL | _custom = -_custom; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:418:15 + --> tests/ui/arithmetic_side_effects.rs:523:15 | LL | _custom = -&_custom; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:419:9 + --> tests/ui/arithmetic_side_effects.rs:525:9 | LL | _ = -*Box::new(_n); | ^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:428:5 + --> tests/ui/arithmetic_side_effects.rs:535:5 | LL | 1 + i; | ^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:429:5 + --> tests/ui/arithmetic_side_effects.rs:537:5 | LL | i * 2; | ^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:430:5 + --> tests/ui/arithmetic_side_effects.rs:539:5 | LL | 1 % i / 2; | ^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:431:5 + --> tests/ui/arithmetic_side_effects.rs:541:5 | LL | i - 2 + 2 - i; | ^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:432:5 + --> tests/ui/arithmetic_side_effects.rs:543:5 | LL | -i; | ^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:443:5 + --> tests/ui/arithmetic_side_effects.rs:555:5 | LL | i += 1; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:444:5 + --> tests/ui/arithmetic_side_effects.rs:557:5 | LL | i -= 1; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:445:5 + --> tests/ui/arithmetic_side_effects.rs:559:5 | LL | i *= 2; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:447:5 + --> tests/ui/arithmetic_side_effects.rs:562:5 | LL | i /= 0; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:449:5 + --> tests/ui/arithmetic_side_effects.rs:565:5 | LL | i /= var1; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:450:5 + --> tests/ui/arithmetic_side_effects.rs:567:5 | LL | i /= var2; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:452:5 + --> tests/ui/arithmetic_side_effects.rs:570:5 | LL | i %= 0; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:454:5 + --> tests/ui/arithmetic_side_effects.rs:573:5 | LL | i %= var1; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:455:5 + --> tests/ui/arithmetic_side_effects.rs:575:5 | LL | i %= var2; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:465:5 + --> tests/ui/arithmetic_side_effects.rs:586:5 | LL | 10 / a | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:519:9 + --> tests/ui/arithmetic_side_effects.rs:641:9 | LL | x / maybe_zero | ^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:523:9 + --> tests/ui/arithmetic_side_effects.rs:646:9 | LL | x % maybe_zero | ^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:534:5 + --> tests/ui/arithmetic_side_effects.rs:658:5 | LL | one.add_assign(1); | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:538:5 + --> tests/ui/arithmetic_side_effects.rs:663:5 | LL | one.sub_assign(1); | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:544:5 + --> tests/ui/arithmetic_side_effects.rs:670:5 | LL | one.add(&one); | ^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:545:5 + --> tests/ui/arithmetic_side_effects.rs:672:5 | LL | Box::new(one).add(one); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/as_conversions.rs b/tests/ui/as_conversions.rs index 8499c0ac5a0f..fba8913a2097 100644 --- a/tests/ui/as_conversions.rs +++ b/tests/ui/as_conversions.rs @@ -7,9 +7,11 @@ extern crate proc_macros; use proc_macros::{external, with_span}; fn main() { - let i = 0u32 as u64; + let i = 0u32 as u64; //~ as_conversions let j = &i as *const u64 as *mut u64; + //~^ as_conversions + //~| as_conversions external!(0u32 as u64); } diff --git a/tests/ui/as_pointer_underscore.fixed b/tests/ui/as_pointer_underscore.fixed index db06486ecb04..93daae6bc668 100644 --- a/tests/ui/as_pointer_underscore.fixed +++ b/tests/ui/as_pointer_underscore.fixed @@ -6,10 +6,10 @@ struct S; fn f(s: &S) -> usize { &s as *const &S as usize - //~^ ERROR: using inferred pointer cast + //~^ as_pointer_underscore } fn g(s: &mut S) -> usize { s as *mut S as usize - //~^ ERROR: using inferred pointer cast + //~^ as_pointer_underscore } diff --git a/tests/ui/as_pointer_underscore.rs b/tests/ui/as_pointer_underscore.rs index 955c702ccc99..56f1a8935255 100644 --- a/tests/ui/as_pointer_underscore.rs +++ b/tests/ui/as_pointer_underscore.rs @@ -6,10 +6,10 @@ struct S; fn f(s: &S) -> usize { &s as *const _ as usize - //~^ ERROR: using inferred pointer cast + //~^ as_pointer_underscore } fn g(s: &mut S) -> usize { s as *mut _ as usize - //~^ ERROR: using inferred pointer cast + //~^ as_pointer_underscore } diff --git a/tests/ui/as_ptr_cast_mut.rs b/tests/ui/as_ptr_cast_mut.rs index 9e862320f4ef..baf7279adc4a 100644 --- a/tests/ui/as_ptr_cast_mut.rs +++ b/tests/ui/as_ptr_cast_mut.rs @@ -20,10 +20,11 @@ impl Covariant { fn main() { let mut string = String::new(); let _ = string.as_ptr() as *mut u8; - //~^ ERROR: casting the result of `as_ptr` to *mut u8 - //~| NOTE: `-D clippy::as-ptr-cast-mut` implied by `-D warnings` + //~^ as_ptr_cast_mut + let _: *mut i8 = string.as_ptr() as *mut _; - //~^ ERROR: casting the result of `as_ptr` to *mut i8 + //~^ as_ptr_cast_mut + let _ = string.as_ptr() as *const i8; let _ = string.as_mut_ptr(); let _ = string.as_mut_ptr() as *mut u8; diff --git a/tests/ui/as_underscore.fixed b/tests/ui/as_underscore.fixed index c7f26e64cce7..ca2a7f043286 100644 --- a/tests/ui/as_underscore.fixed +++ b/tests/ui/as_underscore.fixed @@ -5,7 +5,9 @@ fn foo(_n: usize) {} fn main() { let n: u16 = 256; foo(n as usize); + //~^ as_underscore let n = 0_u128; let _n: u8 = n as u8; + //~^ as_underscore } diff --git a/tests/ui/as_underscore.rs b/tests/ui/as_underscore.rs index 70f3b386631c..df500c4c4df1 100644 --- a/tests/ui/as_underscore.rs +++ b/tests/ui/as_underscore.rs @@ -5,7 +5,9 @@ fn foo(_n: usize) {} fn main() { let n: u16 = 256; foo(n as _); + //~^ as_underscore let n = 0_u128; let _n: u8 = n as _; + //~^ as_underscore } diff --git a/tests/ui/as_underscore.stderr b/tests/ui/as_underscore.stderr index dba56a2a8af3..02c10feb78eb 100644 --- a/tests/ui/as_underscore.stderr +++ b/tests/ui/as_underscore.stderr @@ -10,7 +10,7 @@ LL | foo(n as _); = help: to override `-D warnings` add `#[allow(clippy::as_underscore)]` error: using `as _` conversion - --> tests/ui/as_underscore.rs:10:18 + --> tests/ui/as_underscore.rs:11:18 | LL | let _n: u8 = n as _; | ^^^^^- diff --git a/tests/ui/asm_syntax_not_x86.rs b/tests/ui/asm_syntax_not_x86.rs index a7d29cc239e5..edcd5247f18c 100644 --- a/tests/ui/asm_syntax_not_x86.rs +++ b/tests/ui/asm_syntax_not_x86.rs @@ -1,5 +1,6 @@ //@ignore-target: i686 x86 //@needs-asm-support +//@check-pass #[warn(clippy::inline_asm_x86_intel_syntax)] #[warn(clippy::inline_asm_x86_att_syntax)] diff --git a/tests/ui/asm_syntax_x86.rs b/tests/ui/asm_syntax_x86.rs index 5ceaceb7527b..4e91f27cd318 100644 --- a/tests/ui/asm_syntax_x86.rs +++ b/tests/ui/asm_syntax_x86.rs @@ -6,19 +6,24 @@ mod warn_intel { pub(super) unsafe fn use_asm() { asm!(""); - //~^ ERROR: Intel x86 assembly syntax used + //~^ inline_asm_x86_intel_syntax + asm!("", options()); - //~^ ERROR: Intel x86 assembly syntax used + //~^ inline_asm_x86_intel_syntax + asm!("", options(nostack)); - //~^ ERROR: Intel x86 assembly syntax used + //~^ inline_asm_x86_intel_syntax + asm!("", options(att_syntax)); asm!("", options(nostack, att_syntax)); } global_asm!(""); - //~^ ERROR: Intel x86 assembly syntax used + //~^ inline_asm_x86_intel_syntax + global_asm!("", options()); - //~^ ERROR: Intel x86 assembly syntax used + //~^ inline_asm_x86_intel_syntax + global_asm!("", options(att_syntax)); } @@ -31,15 +36,16 @@ mod warn_att { asm!("", options()); asm!("", options(nostack)); asm!("", options(att_syntax)); - //~^ ERROR: AT&T x86 assembly syntax used + //~^ inline_asm_x86_att_syntax + asm!("", options(nostack, att_syntax)); - //~^ ERROR: AT&T x86 assembly syntax used + //~^ inline_asm_x86_att_syntax } global_asm!(""); global_asm!("", options()); global_asm!("", options(att_syntax)); - //~^ ERROR: AT&T x86 assembly syntax used + //~^ inline_asm_x86_att_syntax } fn main() { diff --git a/tests/ui/asm_syntax_x86.stderr b/tests/ui/asm_syntax_x86.stderr index 1911ef66e239..2dcd955f0347 100644 --- a/tests/ui/asm_syntax_x86.stderr +++ b/tests/ui/asm_syntax_x86.stderr @@ -9,7 +9,7 @@ LL | asm!(""); = help: to override `-D warnings` add `#[allow(clippy::inline_asm_x86_intel_syntax)]` error: Intel x86 assembly syntax used - --> tests/ui/asm_syntax_x86.rs:10:9 + --> tests/ui/asm_syntax_x86.rs:11:9 | LL | asm!("", options()); | ^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | asm!("", options()); = help: use AT&T x86 assembly syntax error: Intel x86 assembly syntax used - --> tests/ui/asm_syntax_x86.rs:12:9 + --> tests/ui/asm_syntax_x86.rs:14:9 | LL | asm!("", options(nostack)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | asm!("", options(nostack)); = help: use AT&T x86 assembly syntax error: Intel x86 assembly syntax used - --> tests/ui/asm_syntax_x86.rs:18:5 + --> tests/ui/asm_syntax_x86.rs:21:5 | LL | global_asm!(""); | ^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | global_asm!(""); = help: use AT&T x86 assembly syntax error: Intel x86 assembly syntax used - --> tests/ui/asm_syntax_x86.rs:20:5 + --> tests/ui/asm_syntax_x86.rs:24:5 | LL | global_asm!("", options()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | global_asm!("", options()); = help: use AT&T x86 assembly syntax error: AT&T x86 assembly syntax used - --> tests/ui/asm_syntax_x86.rs:33:9 + --> tests/ui/asm_syntax_x86.rs:38:9 | LL | asm!("", options(att_syntax)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -51,7 +51,7 @@ LL | asm!("", options(att_syntax)); = help: to override `-D warnings` add `#[allow(clippy::inline_asm_x86_att_syntax)]` error: AT&T x86 assembly syntax used - --> tests/ui/asm_syntax_x86.rs:35:9 + --> tests/ui/asm_syntax_x86.rs:41:9 | LL | asm!("", options(nostack, att_syntax)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -59,7 +59,7 @@ LL | asm!("", options(nostack, att_syntax)); = help: use Intel x86 assembly syntax error: AT&T x86 assembly syntax used - --> tests/ui/asm_syntax_x86.rs:41:5 + --> tests/ui/asm_syntax_x86.rs:47:5 | LL | global_asm!("", options(att_syntax)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/assertions_on_constants.rs b/tests/ui/assertions_on_constants.rs index 957154e60dec..c2516c541475 100644 --- a/tests/ui/assertions_on_constants.rs +++ b/tests/ui/assertions_on_constants.rs @@ -8,30 +8,35 @@ macro_rules! assert_const { } fn main() { assert!(true); - //~^ ERROR: `assert!(true)` will be optimized out by the compiler + //~^ assertions_on_constants + assert!(false); - //~^ ERROR: `assert!(false)` should probably be replaced + //~^ assertions_on_constants + assert!(true, "true message"); - //~^ ERROR: `assert!(true)` will be optimized out by the compiler + //~^ assertions_on_constants + assert!(false, "false message"); - //~^ ERROR: `assert!(false, ..)` should probably be replaced + //~^ assertions_on_constants let msg = "panic message"; assert!(false, "{}", msg.to_uppercase()); - //~^ ERROR: `assert!(false, ..)` should probably be replaced + //~^ assertions_on_constants const B: bool = true; assert!(B); - //~^ ERROR: `assert!(true)` will be optimized out by the compiler + //~^ assertions_on_constants const C: bool = false; assert!(C); - //~^ ERROR: `assert!(false)` should probably be replaced + //~^ assertions_on_constants + assert!(C, "C message"); - //~^ ERROR: `assert!(false, ..)` should probably be replaced + //~^ assertions_on_constants debug_assert!(true); - //~^ ERROR: `debug_assert!(true)` will be optimized out by the compiler + //~^ assertions_on_constants + // Don't lint this, since there is no better way for expressing "Only panic in debug mode". debug_assert!(false); // #3948 assert_const!(3); @@ -47,10 +52,10 @@ fn main() { assert!(!CFG_FLAG); const _: () = assert!(true); - //~^ ERROR: `assert!(true)` will be optimized out by the compiler + //~^ assertions_on_constants assert!(8 == (7 + 1)); - //~^ ERROR: `assert!(true)` will be optimized out by the compiler + //~^ assertions_on_constants // Don't lint if the value is dependent on a defined constant: const N: usize = 1024; @@ -59,6 +64,7 @@ fn main() { const _: () = { assert!(true); - //~^ ERROR: `assert!(true)` will be optimized out by the compiler + //~^ assertions_on_constants + assert!(8 == (7 + 1)); }; diff --git a/tests/ui/assertions_on_constants.stderr b/tests/ui/assertions_on_constants.stderr index e164a999c43e..8b7440ec4832 100644 --- a/tests/ui/assertions_on_constants.stderr +++ b/tests/ui/assertions_on_constants.stderr @@ -9,7 +9,7 @@ LL | assert!(true); = help: to override `-D warnings` add `#[allow(clippy::assertions_on_constants)]` error: `assert!(false)` should probably be replaced - --> tests/ui/assertions_on_constants.rs:12:5 + --> tests/ui/assertions_on_constants.rs:13:5 | LL | assert!(false); | ^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | assert!(false); = help: use `panic!()` or `unreachable!()` error: `assert!(true)` will be optimized out by the compiler - --> tests/ui/assertions_on_constants.rs:14:5 + --> tests/ui/assertions_on_constants.rs:16:5 | LL | assert!(true, "true message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | assert!(true, "true message"); = help: remove it error: `assert!(false, ..)` should probably be replaced - --> tests/ui/assertions_on_constants.rs:16:5 + --> tests/ui/assertions_on_constants.rs:19:5 | LL | assert!(false, "false message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | assert!(false, "false message"); = help: use `panic!(..)` or `unreachable!(..)` error: `assert!(false, ..)` should probably be replaced - --> tests/ui/assertions_on_constants.rs:20:5 + --> tests/ui/assertions_on_constants.rs:23:5 | LL | assert!(false, "{}", msg.to_uppercase()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | assert!(false, "{}", msg.to_uppercase()); = help: use `panic!(..)` or `unreachable!(..)` error: `assert!(true)` will be optimized out by the compiler - --> tests/ui/assertions_on_constants.rs:24:5 + --> tests/ui/assertions_on_constants.rs:27:5 | LL | assert!(B); | ^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | assert!(B); = help: remove it error: `assert!(false)` should probably be replaced - --> tests/ui/assertions_on_constants.rs:28:5 + --> tests/ui/assertions_on_constants.rs:31:5 | LL | assert!(C); | ^^^^^^^^^^ @@ -57,7 +57,7 @@ LL | assert!(C); = help: use `panic!()` or `unreachable!()` error: `assert!(false, ..)` should probably be replaced - --> tests/ui/assertions_on_constants.rs:30:5 + --> tests/ui/assertions_on_constants.rs:34:5 | LL | assert!(C, "C message"); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | assert!(C, "C message"); = help: use `panic!(..)` or `unreachable!(..)` error: `debug_assert!(true)` will be optimized out by the compiler - --> tests/ui/assertions_on_constants.rs:33:5 + --> tests/ui/assertions_on_constants.rs:37:5 | LL | debug_assert!(true); | ^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | debug_assert!(true); = help: remove it error: `assert!(true)` will be optimized out by the compiler - --> tests/ui/assertions_on_constants.rs:49:19 + --> tests/ui/assertions_on_constants.rs:54:19 | LL | const _: () = assert!(true); | ^^^^^^^^^^^^^ @@ -81,7 +81,7 @@ LL | const _: () = assert!(true); = help: remove it error: `assert!(true)` will be optimized out by the compiler - --> tests/ui/assertions_on_constants.rs:52:5 + --> tests/ui/assertions_on_constants.rs:57:5 | LL | assert!(8 == (7 + 1)); | ^^^^^^^^^^^^^^^^^^^^^ @@ -89,7 +89,7 @@ LL | assert!(8 == (7 + 1)); = help: remove it error: `assert!(true)` will be optimized out by the compiler - --> tests/ui/assertions_on_constants.rs:61:5 + --> tests/ui/assertions_on_constants.rs:66:5 | LL | assert!(true); | ^^^^^^^^^^^^^ diff --git a/tests/ui/assertions_on_result_states.fixed b/tests/ui/assertions_on_result_states.fixed index 14d9b8b99d5e..09c1a8d0ed1d 100644 --- a/tests/ui/assertions_on_result_states.fixed +++ b/tests/ui/assertions_on_result_states.fixed @@ -22,6 +22,7 @@ fn main() { let r: Result = Ok(Foo); debug_assert!(r.is_ok()); r.unwrap(); + //~^ assertions_on_result_states // test ok with non-debug error type let r: Result = Ok(Foo); @@ -40,9 +41,11 @@ fn main() { Ok(Foo) } get_ok().unwrap(); + //~^ assertions_on_result_states // test macro ok get_ok_macro!().unwrap(); + //~^ assertions_on_result_states // test ok that shouldn't be moved let r: Result = Ok(CopyFoo); @@ -56,12 +59,14 @@ fn main() { // test ok that is copied let r: Result = Ok(CopyFoo); r.unwrap(); + //~^ assertions_on_result_states r.unwrap(); // test reference to ok let r: Result = Ok(CopyFoo); fn test_ref_copy_ok(r: &Result) { r.unwrap(); + //~^ assertions_on_result_states } test_ref_copy_ok(&r); r.unwrap(); @@ -70,6 +75,7 @@ fn main() { let r: Result = Err(Foo); debug_assert!(r.is_err()); r.unwrap_err(); + //~^ assertions_on_result_states // test err with non-debug value type let r: Result = Err(Foo); @@ -80,4 +86,5 @@ fn main() { fn issue9450() { let res: Result = Ok(1); res.unwrap_err(); + //~^ assertions_on_result_states } diff --git a/tests/ui/assertions_on_result_states.rs b/tests/ui/assertions_on_result_states.rs index ac1911d87c93..c63c2502b537 100644 --- a/tests/ui/assertions_on_result_states.rs +++ b/tests/ui/assertions_on_result_states.rs @@ -22,6 +22,7 @@ fn main() { let r: Result = Ok(Foo); debug_assert!(r.is_ok()); assert!(r.is_ok()); + //~^ assertions_on_result_states // test ok with non-debug error type let r: Result = Ok(Foo); @@ -40,9 +41,11 @@ fn main() { Ok(Foo) } assert!(get_ok().is_ok()); + //~^ assertions_on_result_states // test macro ok assert!(get_ok_macro!().is_ok()); + //~^ assertions_on_result_states // test ok that shouldn't be moved let r: Result = Ok(CopyFoo); @@ -56,12 +59,14 @@ fn main() { // test ok that is copied let r: Result = Ok(CopyFoo); assert!(r.is_ok()); + //~^ assertions_on_result_states r.unwrap(); // test reference to ok let r: Result = Ok(CopyFoo); fn test_ref_copy_ok(r: &Result) { assert!(r.is_ok()); + //~^ assertions_on_result_states } test_ref_copy_ok(&r); r.unwrap(); @@ -70,6 +75,7 @@ fn main() { let r: Result = Err(Foo); debug_assert!(r.is_err()); assert!(r.is_err()); + //~^ assertions_on_result_states // test err with non-debug value type let r: Result = Err(Foo); @@ -80,4 +86,5 @@ fn main() { fn issue9450() { let res: Result = Ok(1); assert!(res.is_err()) + //~^ assertions_on_result_states } diff --git a/tests/ui/assertions_on_result_states.stderr b/tests/ui/assertions_on_result_states.stderr index a2bddc7025a9..3bf811588c69 100644 --- a/tests/ui/assertions_on_result_states.stderr +++ b/tests/ui/assertions_on_result_states.stderr @@ -8,37 +8,37 @@ LL | assert!(r.is_ok()); = help: to override `-D warnings` add `#[allow(clippy::assertions_on_result_states)]` error: called `assert!` with `Result::is_ok` - --> tests/ui/assertions_on_result_states.rs:42:5 + --> tests/ui/assertions_on_result_states.rs:43:5 | LL | assert!(get_ok().is_ok()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `get_ok().unwrap()` error: called `assert!` with `Result::is_ok` - --> tests/ui/assertions_on_result_states.rs:45:5 + --> tests/ui/assertions_on_result_states.rs:47:5 | LL | assert!(get_ok_macro!().is_ok()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `get_ok_macro!().unwrap()` error: called `assert!` with `Result::is_ok` - --> tests/ui/assertions_on_result_states.rs:58:5 + --> tests/ui/assertions_on_result_states.rs:61:5 | LL | assert!(r.is_ok()); | ^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap()` error: called `assert!` with `Result::is_ok` - --> tests/ui/assertions_on_result_states.rs:64:9 + --> tests/ui/assertions_on_result_states.rs:68:9 | LL | assert!(r.is_ok()); | ^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap()` error: called `assert!` with `Result::is_err` - --> tests/ui/assertions_on_result_states.rs:72:5 + --> tests/ui/assertions_on_result_states.rs:77:5 | LL | assert!(r.is_err()); | ^^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap_err()` error: called `assert!` with `Result::is_err` - --> tests/ui/assertions_on_result_states.rs:82:5 + --> tests/ui/assertions_on_result_states.rs:88:5 | LL | assert!(res.is_err()) | ^^^^^^^^^^^^^^^^^^^^^ help: replace with: `res.unwrap_err();` diff --git a/tests/ui/assign_ops.fixed b/tests/ui/assign_ops.fixed index 2bd0807f4262..18f0e04a8807 100644 --- a/tests/ui/assign_ops.fixed +++ b/tests/ui/assign_ops.fixed @@ -5,25 +5,36 @@ use core::num::Wrapping; fn main() { let mut a = 5; a += 1; + //~^ assign_op_pattern a += 1; + //~^ assign_op_pattern a -= 1; + //~^ assign_op_pattern a *= 99; + //~^ assign_op_pattern a *= 42; + //~^ assign_op_pattern a /= 2; + //~^ assign_op_pattern a %= 5; + //~^ assign_op_pattern a &= 1; + //~^ assign_op_pattern a = 1 - a; a = 5 / a; a = 42 % a; a = 6 << a; let mut s = String::new(); s += "bla"; + //~^ assign_op_pattern // Issue #9180 let mut a = Wrapping(0u32); a += Wrapping(1u32); + //~^ assign_op_pattern let mut v = vec![0u32, 1u32]; v[0] += v[1]; + //~^ assign_op_pattern let mut v = vec![Wrapping(0u32), Wrapping(1u32)]; v[0] = v[0] + v[1]; let _ = || v[0] = v[0] + v[1]; diff --git a/tests/ui/assign_ops.rs b/tests/ui/assign_ops.rs index be3491a44c7e..8b05c74d8604 100644 --- a/tests/ui/assign_ops.rs +++ b/tests/ui/assign_ops.rs @@ -5,25 +5,36 @@ use core::num::Wrapping; fn main() { let mut a = 5; a = a + 1; + //~^ assign_op_pattern a = 1 + a; + //~^ assign_op_pattern a = a - 1; + //~^ assign_op_pattern a = a * 99; + //~^ assign_op_pattern a = 42 * a; + //~^ assign_op_pattern a = a / 2; + //~^ assign_op_pattern a = a % 5; + //~^ assign_op_pattern a = a & 1; + //~^ assign_op_pattern a = 1 - a; a = 5 / a; a = 42 % a; a = 6 << a; let mut s = String::new(); s = s + "bla"; + //~^ assign_op_pattern // Issue #9180 let mut a = Wrapping(0u32); a = a + Wrapping(1u32); + //~^ assign_op_pattern let mut v = vec![0u32, 1u32]; v[0] = v[0] + v[1]; + //~^ assign_op_pattern let mut v = vec![Wrapping(0u32), Wrapping(1u32)]; v[0] = v[0] + v[1]; let _ = || v[0] = v[0] + v[1]; diff --git a/tests/ui/assign_ops.stderr b/tests/ui/assign_ops.stderr index 4975ac5911fd..17f216ee4a07 100644 --- a/tests/ui/assign_ops.stderr +++ b/tests/ui/assign_ops.stderr @@ -8,61 +8,61 @@ LL | a = a + 1; = help: to override `-D warnings` add `#[allow(clippy::assign_op_pattern)]` error: manual implementation of an assign operation - --> tests/ui/assign_ops.rs:8:5 + --> tests/ui/assign_ops.rs:9:5 | LL | a = 1 + a; | ^^^^^^^^^ help: replace it with: `a += 1` error: manual implementation of an assign operation - --> tests/ui/assign_ops.rs:9:5 + --> tests/ui/assign_ops.rs:11:5 | LL | a = a - 1; | ^^^^^^^^^ help: replace it with: `a -= 1` error: manual implementation of an assign operation - --> tests/ui/assign_ops.rs:10:5 + --> tests/ui/assign_ops.rs:13:5 | LL | a = a * 99; | ^^^^^^^^^^ help: replace it with: `a *= 99` error: manual implementation of an assign operation - --> tests/ui/assign_ops.rs:11:5 + --> tests/ui/assign_ops.rs:15:5 | LL | a = 42 * a; | ^^^^^^^^^^ help: replace it with: `a *= 42` error: manual implementation of an assign operation - --> tests/ui/assign_ops.rs:12:5 + --> tests/ui/assign_ops.rs:17:5 | LL | a = a / 2; | ^^^^^^^^^ help: replace it with: `a /= 2` error: manual implementation of an assign operation - --> tests/ui/assign_ops.rs:13:5 + --> tests/ui/assign_ops.rs:19:5 | LL | a = a % 5; | ^^^^^^^^^ help: replace it with: `a %= 5` error: manual implementation of an assign operation - --> tests/ui/assign_ops.rs:14:5 + --> tests/ui/assign_ops.rs:21:5 | LL | a = a & 1; | ^^^^^^^^^ help: replace it with: `a &= 1` error: manual implementation of an assign operation - --> tests/ui/assign_ops.rs:20:5 + --> tests/ui/assign_ops.rs:28:5 | LL | s = s + "bla"; | ^^^^^^^^^^^^^ help: replace it with: `s += "bla"` error: manual implementation of an assign operation - --> tests/ui/assign_ops.rs:24:5 + --> tests/ui/assign_ops.rs:33:5 | LL | a = a + Wrapping(1u32); | ^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a += Wrapping(1u32)` error: manual implementation of an assign operation - --> tests/ui/assign_ops.rs:26:5 + --> tests/ui/assign_ops.rs:36:5 | LL | v[0] = v[0] + v[1]; | ^^^^^^^^^^^^^^^^^^ help: replace it with: `v[0] += v[1]` diff --git a/tests/ui/assign_ops2.rs b/tests/ui/assign_ops2.rs index a53556425849..51867fa6962c 100644 --- a/tests/ui/assign_ops2.rs +++ b/tests/ui/assign_ops2.rs @@ -6,24 +6,32 @@ fn main() { let mut a = 5; a += a + 1; - //~^ ERROR: variable appears on both sides of an assignment operation - //~| NOTE: `-D clippy::misrefactored-assign-op` implied by `-D warnings` + //~^ misrefactored_assign_op + a += 1 + a; - //~^ ERROR: variable appears on both sides of an assignment operation + //~^ misrefactored_assign_op + a -= a - 1; - //~^ ERROR: variable appears on both sides of an assignment operation + //~^ misrefactored_assign_op + a *= a * 99; - //~^ ERROR: variable appears on both sides of an assignment operation + //~^ misrefactored_assign_op + a *= 42 * a; - //~^ ERROR: variable appears on both sides of an assignment operation + //~^ misrefactored_assign_op + a /= a / 2; - //~^ ERROR: variable appears on both sides of an assignment operation + //~^ misrefactored_assign_op + a %= a % 5; - //~^ ERROR: variable appears on both sides of an assignment operation + //~^ misrefactored_assign_op + a &= a & 1; - //~^ ERROR: variable appears on both sides of an assignment operation + //~^ misrefactored_assign_op + a *= a * a; - //~^ ERROR: variable appears on both sides of an assignment operation + //~^ misrefactored_assign_op + a = a * a * a; a = a * 42 * a; a = a * 2 + a; @@ -61,8 +69,7 @@ fn cow_add_assign() { // this can be linted buf = buf + cows.clone(); - //~^ ERROR: manual implementation of an assign operation - //~| NOTE: `-D clippy::assign-op-pattern` implied by `-D warnings` + //~^ assign_op_pattern // this should not as cow Add is not commutative buf = cows + buf; diff --git a/tests/ui/assign_ops2.stderr b/tests/ui/assign_ops2.stderr index 09b101b216a5..d9ecd3f8b230 100644 --- a/tests/ui/assign_ops2.stderr +++ b/tests/ui/assign_ops2.stderr @@ -35,7 +35,7 @@ LL + a = a + 1 + a; | error: variable appears on both sides of an assignment operation - --> tests/ui/assign_ops2.rs:13:5 + --> tests/ui/assign_ops2.rs:14:5 | LL | a -= a - 1; | ^^^^^^^^^^ @@ -52,7 +52,7 @@ LL + a = a - (a - 1); | error: variable appears on both sides of an assignment operation - --> tests/ui/assign_ops2.rs:15:5 + --> tests/ui/assign_ops2.rs:17:5 | LL | a *= a * 99; | ^^^^^^^^^^^ @@ -69,7 +69,7 @@ LL + a = a * a * 99; | error: variable appears on both sides of an assignment operation - --> tests/ui/assign_ops2.rs:17:5 + --> tests/ui/assign_ops2.rs:20:5 | LL | a *= 42 * a; | ^^^^^^^^^^^ @@ -86,7 +86,7 @@ LL + a = a * 42 * a; | error: variable appears on both sides of an assignment operation - --> tests/ui/assign_ops2.rs:19:5 + --> tests/ui/assign_ops2.rs:23:5 | LL | a /= a / 2; | ^^^^^^^^^^ @@ -103,7 +103,7 @@ LL + a = a / (a / 2); | error: variable appears on both sides of an assignment operation - --> tests/ui/assign_ops2.rs:21:5 + --> tests/ui/assign_ops2.rs:26:5 | LL | a %= a % 5; | ^^^^^^^^^^ @@ -120,7 +120,7 @@ LL + a = a % (a % 5); | error: variable appears on both sides of an assignment operation - --> tests/ui/assign_ops2.rs:23:5 + --> tests/ui/assign_ops2.rs:29:5 | LL | a &= a & 1; | ^^^^^^^^^^ @@ -137,7 +137,7 @@ LL + a = a & a & 1; | error: variable appears on both sides of an assignment operation - --> tests/ui/assign_ops2.rs:25:5 + --> tests/ui/assign_ops2.rs:32:5 | LL | a *= a * a; | ^^^^^^^^^^ @@ -154,7 +154,7 @@ LL + a = a * a * a; | error: manual implementation of an assign operation - --> tests/ui/assign_ops2.rs:63:5 + --> tests/ui/assign_ops2.rs:71:5 | LL | buf = buf + cows.clone(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `buf += cows.clone()` diff --git a/tests/ui/assigning_clones.fixed b/tests/ui/assigning_clones.fixed index 09732d1a50ce..9e44008e6fab 100644 --- a/tests/ui/assigning_clones.fixed +++ b/tests/ui/assigning_clones.fixed @@ -23,60 +23,73 @@ impl Clone for HasCloneFrom { fn clone_method_rhs_val(mut_thing: &mut HasCloneFrom, value_thing: HasCloneFrom) { mut_thing.clone_from(&value_thing); + //~^ assigning_clones } fn clone_method_rhs_ref(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { mut_thing.clone_from(ref_thing); + //~^ assigning_clones } fn clone_method_lhs_val(mut mut_thing: HasCloneFrom, ref_thing: &HasCloneFrom) { mut_thing.clone_from(ref_thing); + //~^ assigning_clones } fn clone_function_lhs_mut_ref(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { Clone::clone_from(mut_thing, ref_thing); + //~^ assigning_clones } fn clone_function_lhs_val(mut mut_thing: HasCloneFrom, ref_thing: &HasCloneFrom) { Clone::clone_from(&mut mut_thing, ref_thing); + //~^ assigning_clones } fn clone_function_through_trait(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { Clone::clone_from(mut_thing, ref_thing); + //~^ assigning_clones } fn clone_function_through_type(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { Clone::clone_from(mut_thing, ref_thing); + //~^ assigning_clones } fn clone_function_fully_qualified(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { Clone::clone_from(mut_thing, ref_thing); + //~^ assigning_clones } fn clone_method_lhs_complex(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { // These parens should be kept as necessary for a receiver (mut_thing + &mut HasCloneFrom).clone_from(ref_thing); + //~^ assigning_clones } fn clone_method_rhs_complex(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { // These parens should be removed since they are not needed in a function argument mut_thing.clone_from(ref_thing + ref_thing); + //~^ assigning_clones } fn clone_method_macro() { let mut s = String::from(""); s.clone_from(&format!("{} {}", "hello", "world")); + //~^ assigning_clones } fn clone_function_macro() { let mut s = String::from(""); Clone::clone_from(&mut s, &format!("{} {}", "hello", "world")); + //~^ assigning_clones } fn assign_to_init_mut_var(b: HasCloneFrom) -> HasCloneFrom { let mut a = HasCloneFrom; for _ in 1..10 { a.clone_from(&b); + //~^ assigning_clones } a } @@ -148,6 +161,7 @@ fn ignore_generic_clone(a: &mut T, b: &T) { #[clippy::msrv = "1.62"] fn msrv_1_62(mut a: String, b: String, c: &str) { a.clone_from(&b); + //~^ assigning_clones // Should not be linted, as clone_into wasn't stabilized until 1.63 a = c.to_owned(); } @@ -155,7 +169,9 @@ fn msrv_1_62(mut a: String, b: String, c: &str) { #[clippy::msrv = "1.63"] fn msrv_1_63(mut a: String, b: String, c: &str) { a.clone_from(&b); + //~^ assigning_clones c.clone_into(&mut a); + //~^ assigning_clones } macro_rules! clone_inside { @@ -186,35 +202,43 @@ impl Clone for AvoidRecursiveCloneFrom { // Deref handling fn clone_into_deref_method(mut a: DerefWrapper, b: HasCloneFrom) { (*a).clone_from(&b); + //~^ assigning_clones } fn clone_into_deref_with_clone_method(mut a: DerefWrapperWithClone, b: HasCloneFrom) { (*a).clone_from(&b); + //~^ assigning_clones } fn clone_into_box_method(mut a: Box, b: HasCloneFrom) { (*a).clone_from(&b); + //~^ assigning_clones } fn clone_into_self_deref_method(a: &mut DerefWrapperWithClone, b: DerefWrapperWithClone) { a.clone_from(&b); + //~^ assigning_clones } fn clone_into_deref_function(mut a: DerefWrapper, b: HasCloneFrom) { Clone::clone_from(&mut *a, &b); + //~^ assigning_clones } fn clone_into_box_function(mut a: Box, b: HasCloneFrom) { Clone::clone_from(&mut *a, &b); + //~^ assigning_clones } // ToOwned fn owned_method_mut_ref(mut_string: &mut String, ref_str: &str) { ref_str.clone_into(mut_string); + //~^ assigning_clones } fn owned_method_val(mut mut_string: String, ref_str: &str) { ref_str.clone_into(&mut mut_string); + //~^ assigning_clones } struct HasDeref { @@ -236,28 +260,34 @@ impl DerefMut for HasDeref { fn owned_method_box(mut_box_string: &mut Box, ref_str: &str) { ref_str.clone_into(&mut (*mut_box_string)); + //~^ assigning_clones } fn owned_method_deref(mut_box_string: &mut HasDeref, ref_str: &str) { ref_str.clone_into(&mut (*mut_box_string)); + //~^ assigning_clones } fn owned_function_mut_ref(mut_thing: &mut String, ref_str: &str) { ToOwned::clone_into(ref_str, mut_thing); + //~^ assigning_clones } fn owned_function_val(mut mut_thing: String, ref_str: &str) { ToOwned::clone_into(ref_str, &mut mut_thing); + //~^ assigning_clones } fn owned_method_macro() { let mut s = String::from(""); format!("{} {}", "hello", "world").clone_into(&mut s); + //~^ assigning_clones } fn owned_function_macro() { let mut s = String::from(""); ToOwned::clone_into(&format!("{} {}", "hello", "world"), &mut s); + //~^ assigning_clones } struct FakeToOwned; diff --git a/tests/ui/assigning_clones.rs b/tests/ui/assigning_clones.rs index 6be25ae17a55..8ae8abfed367 100644 --- a/tests/ui/assigning_clones.rs +++ b/tests/ui/assigning_clones.rs @@ -23,60 +23,73 @@ impl Clone for HasCloneFrom { fn clone_method_rhs_val(mut_thing: &mut HasCloneFrom, value_thing: HasCloneFrom) { *mut_thing = value_thing.clone(); + //~^ assigning_clones } fn clone_method_rhs_ref(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { *mut_thing = ref_thing.clone(); + //~^ assigning_clones } fn clone_method_lhs_val(mut mut_thing: HasCloneFrom, ref_thing: &HasCloneFrom) { mut_thing = ref_thing.clone(); + //~^ assigning_clones } fn clone_function_lhs_mut_ref(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { *mut_thing = Clone::clone(ref_thing); + //~^ assigning_clones } fn clone_function_lhs_val(mut mut_thing: HasCloneFrom, ref_thing: &HasCloneFrom) { mut_thing = Clone::clone(ref_thing); + //~^ assigning_clones } fn clone_function_through_trait(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { *mut_thing = Clone::clone(ref_thing); + //~^ assigning_clones } fn clone_function_through_type(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { *mut_thing = HasCloneFrom::clone(ref_thing); + //~^ assigning_clones } fn clone_function_fully_qualified(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { *mut_thing = ::clone(ref_thing); + //~^ assigning_clones } fn clone_method_lhs_complex(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { // These parens should be kept as necessary for a receiver *(mut_thing + &mut HasCloneFrom) = ref_thing.clone(); + //~^ assigning_clones } fn clone_method_rhs_complex(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { // These parens should be removed since they are not needed in a function argument *mut_thing = (ref_thing + ref_thing).clone(); + //~^ assigning_clones } fn clone_method_macro() { let mut s = String::from(""); s = format!("{} {}", "hello", "world").clone(); + //~^ assigning_clones } fn clone_function_macro() { let mut s = String::from(""); s = Clone::clone(&format!("{} {}", "hello", "world")); + //~^ assigning_clones } fn assign_to_init_mut_var(b: HasCloneFrom) -> HasCloneFrom { let mut a = HasCloneFrom; for _ in 1..10 { a = b.clone(); + //~^ assigning_clones } a } @@ -148,6 +161,7 @@ fn ignore_generic_clone(a: &mut T, b: &T) { #[clippy::msrv = "1.62"] fn msrv_1_62(mut a: String, b: String, c: &str) { a = b.clone(); + //~^ assigning_clones // Should not be linted, as clone_into wasn't stabilized until 1.63 a = c.to_owned(); } @@ -155,7 +169,9 @@ fn msrv_1_62(mut a: String, b: String, c: &str) { #[clippy::msrv = "1.63"] fn msrv_1_63(mut a: String, b: String, c: &str) { a = b.clone(); + //~^ assigning_clones a = c.to_owned(); + //~^ assigning_clones } macro_rules! clone_inside { @@ -186,35 +202,43 @@ impl Clone for AvoidRecursiveCloneFrom { // Deref handling fn clone_into_deref_method(mut a: DerefWrapper, b: HasCloneFrom) { *a = b.clone(); + //~^ assigning_clones } fn clone_into_deref_with_clone_method(mut a: DerefWrapperWithClone, b: HasCloneFrom) { *a = b.clone(); + //~^ assigning_clones } fn clone_into_box_method(mut a: Box, b: HasCloneFrom) { *a = b.clone(); + //~^ assigning_clones } fn clone_into_self_deref_method(a: &mut DerefWrapperWithClone, b: DerefWrapperWithClone) { *a = b.clone(); + //~^ assigning_clones } fn clone_into_deref_function(mut a: DerefWrapper, b: HasCloneFrom) { *a = Clone::clone(&b); + //~^ assigning_clones } fn clone_into_box_function(mut a: Box, b: HasCloneFrom) { *a = Clone::clone(&b); + //~^ assigning_clones } // ToOwned fn owned_method_mut_ref(mut_string: &mut String, ref_str: &str) { *mut_string = ref_str.to_owned(); + //~^ assigning_clones } fn owned_method_val(mut mut_string: String, ref_str: &str) { mut_string = ref_str.to_owned(); + //~^ assigning_clones } struct HasDeref { @@ -236,28 +260,34 @@ impl DerefMut for HasDeref { fn owned_method_box(mut_box_string: &mut Box, ref_str: &str) { **mut_box_string = ref_str.to_owned(); + //~^ assigning_clones } fn owned_method_deref(mut_box_string: &mut HasDeref, ref_str: &str) { **mut_box_string = ref_str.to_owned(); + //~^ assigning_clones } fn owned_function_mut_ref(mut_thing: &mut String, ref_str: &str) { *mut_thing = ToOwned::to_owned(ref_str); + //~^ assigning_clones } fn owned_function_val(mut mut_thing: String, ref_str: &str) { mut_thing = ToOwned::to_owned(ref_str); + //~^ assigning_clones } fn owned_method_macro() { let mut s = String::from(""); s = format!("{} {}", "hello", "world").to_owned(); + //~^ assigning_clones } fn owned_function_macro() { let mut s = String::from(""); s = ToOwned::to_owned(&format!("{} {}", "hello", "world")); + //~^ assigning_clones } struct FakeToOwned; diff --git a/tests/ui/assigning_clones.stderr b/tests/ui/assigning_clones.stderr index 19724a6d4ec2..2714d599b28a 100644 --- a/tests/ui/assigning_clones.stderr +++ b/tests/ui/assigning_clones.stderr @@ -8,175 +8,175 @@ LL | *mut_thing = value_thing.clone(); = help: to override `-D warnings` add `#[allow(clippy::assigning_clones)]` error: assigning the result of `Clone::clone()` may be inefficient - --> tests/ui/assigning_clones.rs:29:5 + --> tests/ui/assigning_clones.rs:30:5 | LL | *mut_thing = ref_thing.clone(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `mut_thing.clone_from(ref_thing)` error: assigning the result of `Clone::clone()` may be inefficient - --> tests/ui/assigning_clones.rs:33:5 + --> tests/ui/assigning_clones.rs:35:5 | LL | mut_thing = ref_thing.clone(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `mut_thing.clone_from(ref_thing)` error: assigning the result of `Clone::clone()` may be inefficient - --> tests/ui/assigning_clones.rs:37:5 + --> tests/ui/assigning_clones.rs:40:5 | LL | *mut_thing = Clone::clone(ref_thing); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(mut_thing, ref_thing)` error: assigning the result of `Clone::clone()` may be inefficient - --> tests/ui/assigning_clones.rs:41:5 + --> tests/ui/assigning_clones.rs:45:5 | LL | mut_thing = Clone::clone(ref_thing); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(&mut mut_thing, ref_thing)` error: assigning the result of `Clone::clone()` may be inefficient - --> tests/ui/assigning_clones.rs:45:5 + --> tests/ui/assigning_clones.rs:50:5 | LL | *mut_thing = Clone::clone(ref_thing); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(mut_thing, ref_thing)` error: assigning the result of `Clone::clone()` may be inefficient - --> tests/ui/assigning_clones.rs:49:5 + --> tests/ui/assigning_clones.rs:55:5 | LL | *mut_thing = HasCloneFrom::clone(ref_thing); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(mut_thing, ref_thing)` error: assigning the result of `Clone::clone()` may be inefficient - --> tests/ui/assigning_clones.rs:53:5 + --> tests/ui/assigning_clones.rs:60:5 | LL | *mut_thing = ::clone(ref_thing); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(mut_thing, ref_thing)` error: assigning the result of `Clone::clone()` may be inefficient - --> tests/ui/assigning_clones.rs:58:5 + --> tests/ui/assigning_clones.rs:66:5 | LL | *(mut_thing + &mut HasCloneFrom) = ref_thing.clone(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `(mut_thing + &mut HasCloneFrom).clone_from(ref_thing)` error: assigning the result of `Clone::clone()` may be inefficient - --> tests/ui/assigning_clones.rs:63:5 + --> tests/ui/assigning_clones.rs:72:5 | LL | *mut_thing = (ref_thing + ref_thing).clone(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `mut_thing.clone_from(ref_thing + ref_thing)` error: assigning the result of `Clone::clone()` may be inefficient - --> tests/ui/assigning_clones.rs:68:5 + --> tests/ui/assigning_clones.rs:78:5 | LL | s = format!("{} {}", "hello", "world").clone(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `s.clone_from(&format!("{} {}", "hello", "world"))` error: assigning the result of `Clone::clone()` may be inefficient - --> tests/ui/assigning_clones.rs:73:5 + --> tests/ui/assigning_clones.rs:84:5 | LL | s = Clone::clone(&format!("{} {}", "hello", "world")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(&mut s, &format!("{} {}", "hello", "world"))` error: assigning the result of `Clone::clone()` may be inefficient - --> tests/ui/assigning_clones.rs:79:9 + --> tests/ui/assigning_clones.rs:91:9 | LL | a = b.clone(); | ^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)` error: assigning the result of `Clone::clone()` may be inefficient - --> tests/ui/assigning_clones.rs:150:5 + --> tests/ui/assigning_clones.rs:163:5 | LL | a = b.clone(); | ^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)` error: assigning the result of `Clone::clone()` may be inefficient - --> tests/ui/assigning_clones.rs:157:5 + --> tests/ui/assigning_clones.rs:171:5 | LL | a = b.clone(); | ^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:158:5 + --> tests/ui/assigning_clones.rs:173:5 | LL | a = c.to_owned(); | ^^^^^^^^^^^^^^^^ help: use `clone_into()`: `c.clone_into(&mut a)` error: assigning the result of `Clone::clone()` may be inefficient - --> tests/ui/assigning_clones.rs:188:5 + --> tests/ui/assigning_clones.rs:204:5 | LL | *a = b.clone(); | ^^^^^^^^^^^^^^ help: use `clone_from()`: `(*a).clone_from(&b)` error: assigning the result of `Clone::clone()` may be inefficient - --> tests/ui/assigning_clones.rs:192:5 + --> tests/ui/assigning_clones.rs:209:5 | LL | *a = b.clone(); | ^^^^^^^^^^^^^^ help: use `clone_from()`: `(*a).clone_from(&b)` error: assigning the result of `Clone::clone()` may be inefficient - --> tests/ui/assigning_clones.rs:196:5 + --> tests/ui/assigning_clones.rs:214:5 | LL | *a = b.clone(); | ^^^^^^^^^^^^^^ help: use `clone_from()`: `(*a).clone_from(&b)` error: assigning the result of `Clone::clone()` may be inefficient - --> tests/ui/assigning_clones.rs:200:5 + --> tests/ui/assigning_clones.rs:219:5 | LL | *a = b.clone(); | ^^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)` error: assigning the result of `Clone::clone()` may be inefficient - --> tests/ui/assigning_clones.rs:204:5 + --> tests/ui/assigning_clones.rs:224:5 | LL | *a = Clone::clone(&b); | ^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(&mut *a, &b)` error: assigning the result of `Clone::clone()` may be inefficient - --> tests/ui/assigning_clones.rs:208:5 + --> tests/ui/assigning_clones.rs:229:5 | LL | *a = Clone::clone(&b); | ^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(&mut *a, &b)` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:213:5 + --> tests/ui/assigning_clones.rs:235:5 | LL | *mut_string = ref_str.to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(mut_string)` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:217:5 + --> tests/ui/assigning_clones.rs:240:5 | LL | mut_string = ref_str.to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut mut_string)` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:238:5 + --> tests/ui/assigning_clones.rs:262:5 | LL | **mut_box_string = ref_str.to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut (*mut_box_string))` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:242:5 + --> tests/ui/assigning_clones.rs:267:5 | LL | **mut_box_string = ref_str.to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut (*mut_box_string))` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:246:5 + --> tests/ui/assigning_clones.rs:272:5 | LL | *mut_thing = ToOwned::to_owned(ref_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, mut_thing)` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:250:5 + --> tests/ui/assigning_clones.rs:277:5 | LL | mut_thing = ToOwned::to_owned(ref_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, &mut mut_thing)` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:255:5 + --> tests/ui/assigning_clones.rs:283:5 | LL | s = format!("{} {}", "hello", "world").to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `format!("{} {}", "hello", "world").clone_into(&mut s)` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:260:5 + --> tests/ui/assigning_clones.rs:289:5 | LL | s = ToOwned::to_owned(&format!("{} {}", "hello", "world")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(&format!("{} {}", "hello", "world"), &mut s)` diff --git a/tests/ui/async_yields_async.fixed b/tests/ui/async_yields_async.fixed index 48402164a827..93c573d30863 100644 --- a/tests/ui/async_yields_async.fixed +++ b/tests/ui/async_yields_async.fixed @@ -38,9 +38,11 @@ fn main() { 3 }.await }; + //~^^^^ async_yields_async let _i = async { CustomFutureType.await }; + //~^^ async_yields_async let _i = async || { 3 }; @@ -49,10 +51,13 @@ fn main() { 3 }.await }; + //~^^^^ async_yields_async let _k = async || { CustomFutureType.await }; + //~^^ async_yields_async let _l = async || CustomFutureType.await; + //~^ async_yields_async let _m = async || { println!("I'm bored"); // Some more stuff @@ -60,6 +65,7 @@ fn main() { // Finally something to await CustomFutureType.await }; + //~^^ async_yields_async let _n = async || custom_future_type_ctor(); let _o = async || f(); } diff --git a/tests/ui/async_yields_async.rs b/tests/ui/async_yields_async.rs index 8ad016b6bb4e..166d522e1c04 100644 --- a/tests/ui/async_yields_async.rs +++ b/tests/ui/async_yields_async.rs @@ -38,9 +38,11 @@ fn main() { 3 } }; + //~^^^^ async_yields_async let _i = async { CustomFutureType }; + //~^^ async_yields_async let _i = async || { 3 }; @@ -49,10 +51,13 @@ fn main() { 3 } }; + //~^^^^ async_yields_async let _k = async || { CustomFutureType }; + //~^^ async_yields_async let _l = async || CustomFutureType; + //~^ async_yields_async let _m = async || { println!("I'm bored"); // Some more stuff @@ -60,6 +65,7 @@ fn main() { // Finally something to await CustomFutureType }; + //~^^ async_yields_async let _n = async || custom_future_type_ctor(); let _o = async || f(); } diff --git a/tests/ui/async_yields_async.stderr b/tests/ui/async_yields_async.stderr index 8c023d0d61f4..17a35076fa3f 100644 --- a/tests/ui/async_yields_async.stderr +++ b/tests/ui/async_yields_async.stderr @@ -20,7 +20,7 @@ LL ~ }.await | error: an async construct yields a type which is itself awaitable - --> tests/ui/async_yields_async.rs:42:9 + --> tests/ui/async_yields_async.rs:43:9 | LL | let _i = async { | ____________________- @@ -33,7 +33,7 @@ LL | | }; | |_____- outer async construct error: an async construct yields a type which is itself awaitable - --> tests/ui/async_yields_async.rs:48:9 + --> tests/ui/async_yields_async.rs:50:9 | LL | let _j = async || { | ________________________- @@ -52,7 +52,7 @@ LL ~ }.await | error: an async construct yields a type which is itself awaitable - --> tests/ui/async_yields_async.rs:53:9 + --> tests/ui/async_yields_async.rs:56:9 | LL | let _k = async || { | _______________________- @@ -65,7 +65,7 @@ LL | | }; | |_____- outer async construct error: an async construct yields a type which is itself awaitable - --> tests/ui/async_yields_async.rs:55:23 + --> tests/ui/async_yields_async.rs:59:23 | LL | let _l = async || CustomFutureType; | ^^^^^^^^^^^^^^^^ @@ -75,7 +75,7 @@ LL | let _l = async || CustomFutureType; | help: consider awaiting this value: `CustomFutureType.await` error: an async construct yields a type which is itself awaitable - --> tests/ui/async_yields_async.rs:61:9 + --> tests/ui/async_yields_async.rs:66:9 | LL | let _m = async || { | _______________________- diff --git a/tests/ui/attrs.rs b/tests/ui/attrs.rs index da96eabede17..f60c71837d5e 100644 --- a/tests/ui/attrs.rs +++ b/tests/ui/attrs.rs @@ -3,8 +3,7 @@ #![allow(clippy::missing_docs_in_private_items, clippy::panic, clippy::unreachable)] #[inline(always)] -//~^ ERROR: you have declared `#[inline(always)]` on `test_attr_lint`. This is usually a b -//~| NOTE: `-D clippy::inline-always` implied by `-D warnings` +//~^ inline_always fn test_attr_lint() { assert!(true) } @@ -25,12 +24,11 @@ fn empty_and_false_positive_stmt() { } #[deprecated(since = "forever")] -//~^ ERROR: the since field must contain a semver-compliant version -//~| NOTE: `-D clippy::deprecated-semver` implied by `-D warnings` +//~^ deprecated_semver pub const SOME_CONST: u8 = 42; #[deprecated(since = "1")] -//~^ ERROR: the since field must contain a semver-compliant version +//~^ deprecated_semver pub const ANOTHER_CONST: u8 = 23; #[deprecated(since = "0.1.1")] diff --git a/tests/ui/attrs.stderr b/tests/ui/attrs.stderr index a7fdceaba6f3..85b318cc0fdb 100644 --- a/tests/ui/attrs.stderr +++ b/tests/ui/attrs.stderr @@ -1,5 +1,5 @@ error: the since field must contain a semver-compliant version - --> tests/ui/attrs.rs:27:14 + --> tests/ui/attrs.rs:26:14 | LL | #[deprecated(since = "forever")] | ^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | #[deprecated(since = "forever")] = help: to override `-D warnings` add `#[allow(clippy::deprecated_semver)]` error: the since field must contain a semver-compliant version - --> tests/ui/attrs.rs:32:14 + --> tests/ui/attrs.rs:30:14 | LL | #[deprecated(since = "1")] | ^^^^^^^^^^^ diff --git a/tests/ui/author.rs b/tests/ui/author.rs index 0a1be3568967..faab114852fb 100644 --- a/tests/ui/author.rs +++ b/tests/ui/author.rs @@ -1,3 +1,5 @@ +//@ check-pass + fn main() { #[clippy::author] let x: char = 0x45 as char; diff --git a/tests/ui/author/blocks.rs b/tests/ui/author/blocks.rs index e9db611a2aa9..73e921e4c75d 100644 --- a/tests/ui/author/blocks.rs +++ b/tests/ui/author/blocks.rs @@ -1,3 +1,4 @@ +//@ check-pass //@edition:2018 #![allow(redundant_semicolons, clippy::no_effect)] diff --git a/tests/ui/author/call.rs b/tests/ui/author/call.rs index e99c3c41dc4e..8d48eb7bd3e3 100644 --- a/tests/ui/author/call.rs +++ b/tests/ui/author/call.rs @@ -1,3 +1,5 @@ +//@ check-pass + fn main() { #[clippy::author] let _ = ::std::cmp::min(3, 4); diff --git a/tests/ui/author/if.rs b/tests/ui/author/if.rs index 946088ab3461..59bc9f5bfa5c 100644 --- a/tests/ui/author/if.rs +++ b/tests/ui/author/if.rs @@ -1,3 +1,5 @@ +//@ check-pass + #[allow(clippy::all)] fn main() { diff --git a/tests/ui/author/issue_3849.rs b/tests/ui/author/issue_3849.rs index 5f65746d71f2..dbd63b21af29 100644 --- a/tests/ui/author/issue_3849.rs +++ b/tests/ui/author/issue_3849.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(dead_code)] #![allow(clippy::zero_ptr)] #![allow(clippy::transmute_ptr_to_ref)] diff --git a/tests/ui/author/loop.rs b/tests/ui/author/loop.rs index ff5b61001179..dcf6fbd72027 100644 --- a/tests/ui/author/loop.rs +++ b/tests/ui/author/loop.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![feature(stmt_expr_attributes)] #![allow( clippy::never_loop, diff --git a/tests/ui/author/macro_in_closure.rs b/tests/ui/author/macro_in_closure.rs index 444e6a12165d..8a02f38fad87 100644 --- a/tests/ui/author/macro_in_closure.rs +++ b/tests/ui/author/macro_in_closure.rs @@ -1,3 +1,5 @@ +//@ check-pass + fn main() { #[clippy::author] let print_text = |x| println!("{}", x); diff --git a/tests/ui/author/macro_in_loop.rs b/tests/ui/author/macro_in_loop.rs index 8a520501f8dd..84ffe416e839 100644 --- a/tests/ui/author/macro_in_loop.rs +++ b/tests/ui/author/macro_in_loop.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![feature(stmt_expr_attributes)] fn main() { diff --git a/tests/ui/author/matches.rs b/tests/ui/author/matches.rs index 674e07ec2d3d..e80d9c51023a 100644 --- a/tests/ui/author/matches.rs +++ b/tests/ui/author/matches.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(clippy::let_and_return)] fn main() { diff --git a/tests/ui/author/repeat.rs b/tests/ui/author/repeat.rs index d8e9d589e689..872f99844a01 100644 --- a/tests/ui/author/repeat.rs +++ b/tests/ui/author/repeat.rs @@ -1,3 +1,5 @@ +//@ check-pass + #[allow(clippy::no_effect)] fn main() { #[clippy::author] diff --git a/tests/ui/author/struct.rs b/tests/ui/author/struct.rs index a99bdfc13137..73db44b73319 100644 --- a/tests/ui/author/struct.rs +++ b/tests/ui/author/struct.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow( clippy::unnecessary_operation, clippy::single_match, diff --git a/tests/ui/await_holding_refcell_ref.rs b/tests/ui/await_holding_refcell_ref.rs index b0c92d8c1f6e..e1db2e387497 100644 --- a/tests/ui/await_holding_refcell_ref.rs +++ b/tests/ui/await_holding_refcell_ref.rs @@ -4,13 +4,15 @@ use std::cell::RefCell; async fn bad(x: &RefCell) -> u32 { let b = x.borrow(); - //~^ ERROR: this `RefCell` reference is held across an await point + //~^ await_holding_refcell_ref + baz().await } async fn bad_mut(x: &RefCell) -> u32 { let b = x.borrow_mut(); - //~^ ERROR: this `RefCell` reference is held across an await point + //~^ await_holding_refcell_ref + baz().await } @@ -32,7 +34,7 @@ async fn also_bad(x: &RefCell) -> u32 { let first = baz().await; let b = x.borrow_mut(); - //~^ ERROR: this `RefCell` reference is held across an await point + //~^ await_holding_refcell_ref let second = baz().await; @@ -45,7 +47,7 @@ async fn less_bad(x: &RefCell) -> u32 { let first = baz().await; let b = x.borrow_mut(); - //~^ ERROR: this `RefCell` reference is held across an await point + //~^ await_holding_refcell_ref let second = baz().await; @@ -61,7 +63,8 @@ async fn not_good(x: &RefCell) -> u32 { let second = { let b = x.borrow_mut(); - //~^ ERROR: this `RefCell` reference is held across an await point + //~^ await_holding_refcell_ref + baz().await }; @@ -74,7 +77,8 @@ async fn not_good(x: &RefCell) -> u32 { fn block_bad(x: &RefCell) -> impl std::future::Future + '_ { async move { let b = x.borrow_mut(); - //~^ ERROR: this `RefCell` reference is held across an await point + //~^ await_holding_refcell_ref + baz().await } } diff --git a/tests/ui/await_holding_refcell_ref.stderr b/tests/ui/await_holding_refcell_ref.stderr index 6c7209c9ff9e..ed8aa747bd07 100644 --- a/tests/ui/await_holding_refcell_ref.stderr +++ b/tests/ui/await_holding_refcell_ref.stderr @@ -6,7 +6,7 @@ LL | let b = x.borrow(); | = help: ensure the reference is dropped before calling `await` note: these are all the await points this reference is held through - --> tests/ui/await_holding_refcell_ref.rs:8:11 + --> tests/ui/await_holding_refcell_ref.rs:9:11 | LL | baz().await | ^^^^^ @@ -14,27 +14,27 @@ LL | baz().await = help: to override `-D warnings` add `#[allow(clippy::await_holding_refcell_ref)]` error: this `RefCell` reference is held across an await point - --> tests/ui/await_holding_refcell_ref.rs:12:9 + --> tests/ui/await_holding_refcell_ref.rs:13:9 | LL | let b = x.borrow_mut(); | ^ | = help: ensure the reference is dropped before calling `await` note: these are all the await points this reference is held through - --> tests/ui/await_holding_refcell_ref.rs:14:11 + --> tests/ui/await_holding_refcell_ref.rs:16:11 | LL | baz().await | ^^^^^ error: this `RefCell` reference is held across an await point - --> tests/ui/await_holding_refcell_ref.rs:34:9 + --> tests/ui/await_holding_refcell_ref.rs:36:9 | LL | let b = x.borrow_mut(); | ^ | = help: ensure the reference is dropped before calling `await` note: these are all the await points this reference is held through - --> tests/ui/await_holding_refcell_ref.rs:37:24 + --> tests/ui/await_holding_refcell_ref.rs:39:24 | LL | let second = baz().await; | ^^^^^ @@ -43,40 +43,40 @@ LL | let third = baz().await; | ^^^^^ error: this `RefCell` reference is held across an await point - --> tests/ui/await_holding_refcell_ref.rs:47:9 + --> tests/ui/await_holding_refcell_ref.rs:49:9 | LL | let b = x.borrow_mut(); | ^ | = help: ensure the reference is dropped before calling `await` note: these are all the await points this reference is held through - --> tests/ui/await_holding_refcell_ref.rs:50:24 + --> tests/ui/await_holding_refcell_ref.rs:52:24 | LL | let second = baz().await; | ^^^^^ error: this `RefCell` reference is held across an await point - --> tests/ui/await_holding_refcell_ref.rs:63:13 + --> tests/ui/await_holding_refcell_ref.rs:65:13 | LL | let b = x.borrow_mut(); | ^ | = help: ensure the reference is dropped before calling `await` note: these are all the await points this reference is held through - --> tests/ui/await_holding_refcell_ref.rs:65:15 + --> tests/ui/await_holding_refcell_ref.rs:68:15 | LL | baz().await | ^^^^^ error: this `RefCell` reference is held across an await point - --> tests/ui/await_holding_refcell_ref.rs:76:13 + --> tests/ui/await_holding_refcell_ref.rs:79:13 | LL | let b = x.borrow_mut(); | ^ | = help: ensure the reference is dropped before calling `await` note: these are all the await points this reference is held through - --> tests/ui/await_holding_refcell_ref.rs:78:15 + --> tests/ui/await_holding_refcell_ref.rs:82:15 | LL | baz().await | ^^^^^ diff --git a/tests/ui/bind_instead_of_map.fixed b/tests/ui/bind_instead_of_map.fixed index 910cec2f203d..80e010e2dfd7 100644 --- a/tests/ui/bind_instead_of_map.fixed +++ b/tests/ui/bind_instead_of_map.fixed @@ -6,13 +6,16 @@ pub fn main() { let x = Some(5); // the easiest cases let _ = x; + //~^ bind_instead_of_map let _ = x.map(|o| o + 1); + //~^ bind_instead_of_map // and an easy counter-example let _ = x.and_then(|o| if o < 32 { Some(o) } else { None }); // Different type let x: Result = Ok(1); let _ = x; + //~^ bind_instead_of_map } pub fn foo() -> Option { diff --git a/tests/ui/bind_instead_of_map.rs b/tests/ui/bind_instead_of_map.rs index 6d66f659ba78..09aa8480cbd9 100644 --- a/tests/ui/bind_instead_of_map.rs +++ b/tests/ui/bind_instead_of_map.rs @@ -6,13 +6,16 @@ pub fn main() { let x = Some(5); // the easiest cases let _ = x.and_then(Some); + //~^ bind_instead_of_map let _ = x.and_then(|o| Some(o + 1)); + //~^ bind_instead_of_map // and an easy counter-example let _ = x.and_then(|o| if o < 32 { Some(o) } else { None }); // Different type let x: Result = Ok(1); let _ = x.and_then(Ok); + //~^ bind_instead_of_map } pub fn foo() -> Option { diff --git a/tests/ui/bind_instead_of_map.stderr b/tests/ui/bind_instead_of_map.stderr index 57e0e4fb8475..08f85fb58549 100644 --- a/tests/ui/bind_instead_of_map.stderr +++ b/tests/ui/bind_instead_of_map.stderr @@ -11,13 +11,13 @@ LL | #![deny(clippy::bind_instead_of_map)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)` - --> tests/ui/bind_instead_of_map.rs:9:13 + --> tests/ui/bind_instead_of_map.rs:10:13 | LL | let _ = x.and_then(|o| Some(o + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.map(|o| o + 1)` error: using `Result.and_then(Ok)`, which is a no-op - --> tests/ui/bind_instead_of_map.rs:15:13 + --> tests/ui/bind_instead_of_map.rs:17:13 | LL | let _ = x.and_then(Ok); | ^^^^^^^^^^^^^^ help: use the expression directly: `x` diff --git a/tests/ui/bind_instead_of_map_multipart.fixed b/tests/ui/bind_instead_of_map_multipart.fixed index 8c77039b3c01..b61ce97fe8e6 100644 --- a/tests/ui/bind_instead_of_map_multipart.fixed +++ b/tests/ui/bind_instead_of_map_multipart.fixed @@ -3,12 +3,15 @@ pub fn main() { let _ = Some("42").map(|s| if s.len() < 42 { 0 } else { s.len() }); + //~^ bind_instead_of_map let _ = Some("42").and_then(|s| if s.len() < 42 { None } else { Some(s.len()) }); let _ = Ok::<_, ()>("42").map(|s| if s.len() < 42 { 0 } else { s.len() }); + //~^ bind_instead_of_map let _ = Ok::<_, ()>("42").and_then(|s| if s.len() < 42 { Err(()) } else { Ok(s.len()) }); let _ = Err::<(), _>("42").map_err(|s| if s.len() < 42 { s.len() + 20 } else { s.len() }); + //~^ bind_instead_of_map let _ = Err::<(), _>("42").or_else(|s| if s.len() < 42 { Ok(()) } else { Err(s.len()) }); hard_example(); @@ -17,6 +20,7 @@ pub fn main() { fn hard_example() { Some("42").map(|s| { + //~^ bind_instead_of_map if { if s == "43" { return 43; @@ -58,4 +62,5 @@ macro_rules! m { fn macro_example() { let _ = Some("").and_then(|s| if s.len() == 20 { m!() } else { Some(20) }); let _ = Some("").map(|s| if s.len() == 20 { m!() } else { Some(20) }); + //~^ bind_instead_of_map } diff --git a/tests/ui/bind_instead_of_map_multipart.rs b/tests/ui/bind_instead_of_map_multipart.rs index 44257f3a4698..37f406def197 100644 --- a/tests/ui/bind_instead_of_map_multipart.rs +++ b/tests/ui/bind_instead_of_map_multipart.rs @@ -3,12 +3,15 @@ pub fn main() { let _ = Some("42").and_then(|s| if s.len() < 42 { Some(0) } else { Some(s.len()) }); + //~^ bind_instead_of_map let _ = Some("42").and_then(|s| if s.len() < 42 { None } else { Some(s.len()) }); let _ = Ok::<_, ()>("42").and_then(|s| if s.len() < 42 { Ok(0) } else { Ok(s.len()) }); + //~^ bind_instead_of_map let _ = Ok::<_, ()>("42").and_then(|s| if s.len() < 42 { Err(()) } else { Ok(s.len()) }); let _ = Err::<(), _>("42").or_else(|s| if s.len() < 42 { Err(s.len() + 20) } else { Err(s.len()) }); + //~^ bind_instead_of_map let _ = Err::<(), _>("42").or_else(|s| if s.len() < 42 { Ok(()) } else { Err(s.len()) }); hard_example(); @@ -17,6 +20,7 @@ pub fn main() { fn hard_example() { Some("42").and_then(|s| { + //~^ bind_instead_of_map if { if s == "43" { return Some(43); @@ -58,4 +62,5 @@ macro_rules! m { fn macro_example() { let _ = Some("").and_then(|s| if s.len() == 20 { m!() } else { Some(20) }); let _ = Some("").and_then(|s| if s.len() == 20 { Some(m!()) } else { Some(Some(20)) }); + //~^ bind_instead_of_map } diff --git a/tests/ui/bind_instead_of_map_multipart.stderr b/tests/ui/bind_instead_of_map_multipart.stderr index 7c5882d4296e..3ae11422357c 100644 --- a/tests/ui/bind_instead_of_map_multipart.stderr +++ b/tests/ui/bind_instead_of_map_multipart.stderr @@ -16,7 +16,7 @@ LL + let _ = Some("42").map(|s| if s.len() < 42 { 0 } else { s.len() }); | error: using `Result.and_then(|x| Ok(y))`, which is more succinctly expressed as `map(|x| y)` - --> tests/ui/bind_instead_of_map_multipart.rs:8:13 + --> tests/ui/bind_instead_of_map_multipart.rs:9:13 | LL | let _ = Ok::<_, ()>("42").and_then(|s| if s.len() < 42 { Ok(0) } else { Ok(s.len()) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL + let _ = Ok::<_, ()>("42").map(|s| if s.len() < 42 { 0 } else { s.len() | error: using `Result.or_else(|x| Err(y))`, which is more succinctly expressed as `map_err(|x| y)` - --> tests/ui/bind_instead_of_map_multipart.rs:11:13 + --> tests/ui/bind_instead_of_map_multipart.rs:13:13 | LL | let _ = Err::<(), _>("42").or_else(|s| if s.len() < 42 { Err(s.len() + 20) } else { Err(s.len()) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -40,12 +40,12 @@ LL + let _ = Err::<(), _>("42").map_err(|s| if s.len() < 42 { s.len() + 20 } | error: using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)` - --> tests/ui/bind_instead_of_map_multipart.rs:19:5 + --> tests/ui/bind_instead_of_map_multipart.rs:22:5 | LL | / Some("42").and_then(|s| { +LL | | LL | | if { LL | | if s == "43" { -LL | | return Some(43); ... | LL | | }); | |______^ @@ -53,6 +53,7 @@ LL | | }); help: use `map` instead | LL ~ Some("42").map(|s| { +LL | LL | if { LL | if s == "43" { LL ~ return 43; @@ -79,7 +80,7 @@ LL ~ _ => 1, | error: using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)` - --> tests/ui/bind_instead_of_map_multipart.rs:60:13 + --> tests/ui/bind_instead_of_map_multipart.rs:64:13 | LL | let _ = Some("").and_then(|s| if s.len() == 20 { Some(m!()) } else { Some(Some(20)) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/bit_masks.rs b/tests/ui/bit_masks.rs index 8e1d066c25e4..87dcdb3084d0 100644 --- a/tests/ui/bit_masks.rs +++ b/tests/ui/bit_masks.rs @@ -12,27 +12,29 @@ fn main() { let x = 5; x & 0 == 0; - //~^ ERROR: &-masking with zero - //~| NOTE: `-D clippy::bad-bit-mask` implied by `-D warnings` - //~| ERROR: this operation will always return zero. This is likely not the intended ou - //~| NOTE: `#[deny(clippy::erasing_op)]` on by default + //~^ bad_bit_mask + //~| erasing_op + x & 1 == 1; //ok, distinguishes bit 0 x & 1 == 0; //ok, compared with zero x & 2 == 1; - //~^ ERROR: incompatible bit mask: `_ & 2` can never be equal to `1` + //~^ bad_bit_mask + x | 0 == 0; //ok, equals x == 0 (maybe warn?) x | 1 == 3; //ok, equals x == 2 || x == 3 x | 3 == 3; //ok, equals x <= 3 x | 3 == 2; - //~^ ERROR: incompatible bit mask: `_ | 3` can never be equal to `2` + //~^ bad_bit_mask x & 1 > 1; - //~^ ERROR: incompatible bit mask: `_ & 1` will never be higher than `1` + //~^ bad_bit_mask + x & 2 > 1; // ok, distinguishes x & 2 == 2 from x & 2 == 0 x & 2 < 1; // ok, distinguishes x & 2 == 2 from x & 2 == 0 x | 1 > 1; // ok (if a bit silly), equals x > 1 x | 2 > 1; - //~^ ERROR: incompatible bit mask: `_ | 2` will always be higher than `1` + //~^ bad_bit_mask + x | 2 <= 2; // ok (if a bit silly), equals x <= 2 x & 192 == 128; // ok, tests for bit 7 and not bit 6 @@ -40,22 +42,26 @@ fn main() { // this also now works with constants x & THREE_BITS == 8; - //~^ ERROR: incompatible bit mask: `_ & 7` can never be equal to `8` + //~^ bad_bit_mask + x | EVEN_MORE_REDIRECTION < 7; - //~^ ERROR: incompatible bit mask: `_ | 7` will never be lower than `7` + //~^ bad_bit_mask 0 & x == 0; - //~^ ERROR: &-masking with zero - //~| ERROR: this operation will always return zero. This is likely not the intended ou + //~^ bad_bit_mask + //~| erasing_op + 1 | x > 1; // and should now also match uncommon usage 1 < 2 | x; - //~^ ERROR: incompatible bit mask: `_ | 2` will always be higher than `1` + //~^ bad_bit_mask + 2 == 3 | x; - //~^ ERROR: incompatible bit mask: `_ | 3` can never be equal to `2` + //~^ bad_bit_mask + 1 == x & 2; - //~^ ERROR: incompatible bit mask: `_ & 2` can never be equal to `1` + //~^ bad_bit_mask x | 1 > 2; // no error, because we allowed ineffective bit masks ineffective(); @@ -67,14 +73,16 @@ fn ineffective() { let x = 5; x | 1 > 3; - //~^ ERROR: ineffective bit mask: `x | 1` compared to `3`, is the same as x compared d - //~| NOTE: `-D clippy::ineffective-bit-mask` implied by `-D warnings` + //~^ ineffective_bit_mask + x | 1 < 4; - //~^ ERROR: ineffective bit mask: `x | 1` compared to `4`, is the same as x compared d + //~^ ineffective_bit_mask + x | 1 <= 3; - //~^ ERROR: ineffective bit mask: `x | 1` compared to `3`, is the same as x compared d + //~^ ineffective_bit_mask + x | 1 >= 8; - //~^ ERROR: ineffective bit mask: `x | 1` compared to `8`, is the same as x compared d + //~^ ineffective_bit_mask x | 1 > 2; // not an error (yet), better written as x >= 2 x | 1 >= 7; // not an error (yet), better written as x >= 6 diff --git a/tests/ui/bit_masks.stderr b/tests/ui/bit_masks.stderr index 004f6ad94841..666ad671edee 100644 --- a/tests/ui/bit_masks.stderr +++ b/tests/ui/bit_masks.stderr @@ -16,7 +16,7 @@ LL | x & 0 == 0; = note: `#[deny(clippy::erasing_op)]` on by default error: incompatible bit mask: `_ & 2` can never be equal to `1` - --> tests/ui/bit_masks.rs:21:5 + --> tests/ui/bit_masks.rs:20:5 | LL | x & 2 == 1; | ^^^^^^^^^^ @@ -34,55 +34,55 @@ LL | x & 1 > 1; | ^^^^^^^^^ error: incompatible bit mask: `_ | 2` will always be higher than `1` - --> tests/ui/bit_masks.rs:34:5 + --> tests/ui/bit_masks.rs:35:5 | LL | x | 2 > 1; | ^^^^^^^^^ error: incompatible bit mask: `_ & 7` can never be equal to `8` - --> tests/ui/bit_masks.rs:42:5 + --> tests/ui/bit_masks.rs:44:5 | LL | x & THREE_BITS == 8; | ^^^^^^^^^^^^^^^^^^^ error: incompatible bit mask: `_ | 7` will never be lower than `7` - --> tests/ui/bit_masks.rs:44:5 + --> tests/ui/bit_masks.rs:47:5 | LL | x | EVEN_MORE_REDIRECTION < 7; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: &-masking with zero - --> tests/ui/bit_masks.rs:47:5 + --> tests/ui/bit_masks.rs:50:5 | LL | 0 & x == 0; | ^^^^^^^^^^ error: this operation will always return zero. This is likely not the intended outcome - --> tests/ui/bit_masks.rs:47:5 + --> tests/ui/bit_masks.rs:50:5 | LL | 0 & x == 0; | ^^^^^ error: incompatible bit mask: `_ | 2` will always be higher than `1` - --> tests/ui/bit_masks.rs:53:5 + --> tests/ui/bit_masks.rs:57:5 | LL | 1 < 2 | x; | ^^^^^^^^^ error: incompatible bit mask: `_ | 3` can never be equal to `2` - --> tests/ui/bit_masks.rs:55:5 + --> tests/ui/bit_masks.rs:60:5 | LL | 2 == 3 | x; | ^^^^^^^^^^ error: incompatible bit mask: `_ & 2` can never be equal to `1` - --> tests/ui/bit_masks.rs:57:5 + --> tests/ui/bit_masks.rs:63:5 | LL | 1 == x & 2; | ^^^^^^^^^^ error: ineffective bit mask: `x | 1` compared to `3`, is the same as x compared directly - --> tests/ui/bit_masks.rs:69:5 + --> tests/ui/bit_masks.rs:75:5 | LL | x | 1 > 3; | ^^^^^^^^^ @@ -91,19 +91,19 @@ LL | x | 1 > 3; = help: to override `-D warnings` add `#[allow(clippy::ineffective_bit_mask)]` error: ineffective bit mask: `x | 1` compared to `4`, is the same as x compared directly - --> tests/ui/bit_masks.rs:72:5 + --> tests/ui/bit_masks.rs:78:5 | LL | x | 1 < 4; | ^^^^^^^^^ error: ineffective bit mask: `x | 1` compared to `3`, is the same as x compared directly - --> tests/ui/bit_masks.rs:74:5 + --> tests/ui/bit_masks.rs:81:5 | LL | x | 1 <= 3; | ^^^^^^^^^^ error: ineffective bit mask: `x | 1` compared to `8`, is the same as x compared directly - --> tests/ui/bit_masks.rs:76:5 + --> tests/ui/bit_masks.rs:84:5 | LL | x | 1 >= 8; | ^^^^^^^^^^ diff --git a/tests/ui/blanket_clippy_restriction_lints.rs b/tests/ui/blanket_clippy_restriction_lints.rs index 2bfaadf8df94..de699309b16d 100644 --- a/tests/ui/blanket_clippy_restriction_lints.rs +++ b/tests/ui/blanket_clippy_restriction_lints.rs @@ -1,13 +1,14 @@ //@compile-flags: -W clippy::restriction +//@error-in-other-file: restriction #![warn(clippy::blanket_clippy_restriction_lints)] //! Test that the whole restriction group is not enabled #![warn(clippy::restriction)] -//~^ ERROR: `clippy::restriction` is not meant to be enabled as a group +//~^ blanket_clippy_restriction_lints #![deny(clippy::restriction)] -//~^ ERROR: `clippy::restriction` is not meant to be enabled as a group +//~^ blanket_clippy_restriction_lints #![forbid(clippy::restriction)] -//~^ ERROR: `clippy::restriction` is not meant to be enabled as a group +//~^ blanket_clippy_restriction_lints fn main() {} diff --git a/tests/ui/blanket_clippy_restriction_lints.stderr b/tests/ui/blanket_clippy_restriction_lints.stderr index 1bad259b09a3..ff3a7cfc3931 100644 --- a/tests/ui/blanket_clippy_restriction_lints.stderr +++ b/tests/ui/blanket_clippy_restriction_lints.stderr @@ -6,7 +6,7 @@ error: `clippy::restriction` is not meant to be enabled as a group = help: to override `-D warnings` add `#[allow(clippy::blanket_clippy_restriction_lints)]` error: `clippy::restriction` is not meant to be enabled as a group - --> tests/ui/blanket_clippy_restriction_lints.rs:6:9 + --> tests/ui/blanket_clippy_restriction_lints.rs:7:9 | LL | #![warn(clippy::restriction)] | ^^^^^^^^^^^^^^^^^^^ @@ -14,7 +14,7 @@ LL | #![warn(clippy::restriction)] = help: enable the restriction lints you need individually error: `clippy::restriction` is not meant to be enabled as a group - --> tests/ui/blanket_clippy_restriction_lints.rs:8:9 + --> tests/ui/blanket_clippy_restriction_lints.rs:9:9 | LL | #![deny(clippy::restriction)] | ^^^^^^^^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | #![deny(clippy::restriction)] = help: enable the restriction lints you need individually error: `clippy::restriction` is not meant to be enabled as a group - --> tests/ui/blanket_clippy_restriction_lints.rs:10:11 + --> tests/ui/blanket_clippy_restriction_lints.rs:11:11 | LL | #![forbid(clippy::restriction)] | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/blocks_in_conditions.fixed b/tests/ui/blocks_in_conditions.fixed index af8e65270d09..df375e370573 100644 --- a/tests/ui/blocks_in_conditions.fixed +++ b/tests/ui/blocks_in_conditions.fixed @@ -46,6 +46,7 @@ fn condition_has_block_with_single_expression() -> i32 { fn condition_is_normal() -> i32 { let x = 3; if x == 3 { 6 } else { 10 } + //~^ nonminimal_bool } fn condition_is_unsafe_block() { diff --git a/tests/ui/blocks_in_conditions.rs b/tests/ui/blocks_in_conditions.rs index 6adae951a290..1d9c9dd42460 100644 --- a/tests/ui/blocks_in_conditions.rs +++ b/tests/ui/blocks_in_conditions.rs @@ -46,6 +46,7 @@ fn condition_has_block_with_single_expression() -> i32 { fn condition_is_normal() -> i32 { let x = 3; if true && x == 3 { 6 } else { 10 } + //~^ nonminimal_bool } fn condition_is_unsafe_block() { diff --git a/tests/ui/blocks_in_conditions.stderr b/tests/ui/blocks_in_conditions.stderr index a55e1efb575e..da21344a8428 100644 --- a/tests/ui/blocks_in_conditions.stderr +++ b/tests/ui/blocks_in_conditions.stderr @@ -35,7 +35,7 @@ LL | if true && x == 3 { 6 } else { 10 } = help: to override `-D warnings` add `#[allow(clippy::nonminimal_bool)]` error: in a `match` scrutinee, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` - --> tests/ui/blocks_in_conditions.rs:75:5 + --> tests/ui/blocks_in_conditions.rs:76:5 | LL | / match { LL | | diff --git a/tests/ui/bool_assert_comparison.fixed b/tests/ui/bool_assert_comparison.fixed index b05166a055ee..721d8b2c2dcd 100644 --- a/tests/ui/bool_assert_comparison.fixed +++ b/tests/ui/bool_assert_comparison.fixed @@ -85,65 +85,90 @@ fn main() { assert_eq!("a".len(), 1); assert!(!"a".is_empty()); + //~^ bool_assert_comparison assert!("".is_empty()); + //~^ bool_assert_comparison assert!("".is_empty()); + //~^ bool_assert_comparison assert_eq!(a!(), b!()); assert_eq!(a!(), "".is_empty()); assert_eq!("".is_empty(), b!()); assert_eq!(a, true); assert!(b); + //~^ bool_assert_comparison assert_ne!("a".len(), 1); assert!("a".is_empty()); + //~^ bool_assert_comparison assert!(!"".is_empty()); + //~^ bool_assert_comparison assert!(!"".is_empty()); + //~^ bool_assert_comparison assert_ne!(a!(), b!()); assert_ne!(a!(), "".is_empty()); assert_ne!("".is_empty(), b!()); assert_ne!(a, true); assert!(!b); + //~^ bool_assert_comparison debug_assert_eq!("a".len(), 1); debug_assert!(!"a".is_empty()); + //~^ bool_assert_comparison debug_assert!("".is_empty()); + //~^ bool_assert_comparison debug_assert!("".is_empty()); + //~^ bool_assert_comparison debug_assert_eq!(a!(), b!()); debug_assert_eq!(a!(), "".is_empty()); debug_assert_eq!("".is_empty(), b!()); debug_assert_eq!(a, true); debug_assert!(b); + //~^ bool_assert_comparison debug_assert_ne!("a".len(), 1); debug_assert!("a".is_empty()); + //~^ bool_assert_comparison debug_assert!(!"".is_empty()); + //~^ bool_assert_comparison debug_assert!(!"".is_empty()); + //~^ bool_assert_comparison debug_assert_ne!(a!(), b!()); debug_assert_ne!(a!(), "".is_empty()); debug_assert_ne!("".is_empty(), b!()); debug_assert_ne!(a, true); debug_assert!(!b); + //~^ bool_assert_comparison // assert with error messages assert_eq!("a".len(), 1, "tadam {}", 1); assert_eq!("a".len(), 1, "tadam {}", true); assert!(!"a".is_empty(), "tadam {}", 1); + //~^ bool_assert_comparison assert!(!"a".is_empty(), "tadam {}", true); + //~^ bool_assert_comparison assert!(!"a".is_empty(), "tadam {}", true); + //~^ bool_assert_comparison assert_eq!(a, true, "tadam {}", false); debug_assert_eq!("a".len(), 1, "tadam {}", 1); debug_assert_eq!("a".len(), 1, "tadam {}", true); debug_assert!(!"a".is_empty(), "tadam {}", 1); + //~^ bool_assert_comparison debug_assert!(!"a".is_empty(), "tadam {}", true); + //~^ bool_assert_comparison debug_assert!(!"a".is_empty(), "tadam {}", true); + //~^ bool_assert_comparison debug_assert_eq!(a, true, "tadam {}", false); assert!(a!()); + //~^ bool_assert_comparison assert!(b!()); + //~^ bool_assert_comparison use debug_assert_eq as renamed; renamed!(a, true); debug_assert!(b); + //~^ bool_assert_comparison let non_copy = NonCopy; assert_eq!(non_copy, true); @@ -158,12 +183,20 @@ fn main() { in_macro!(a); assert!("".is_empty()); + //~^ bool_assert_comparison assert!("".is_empty()); + //~^ bool_assert_comparison assert!(!"requires negation".is_empty()); + //~^ bool_assert_comparison assert!(!"requires negation".is_empty()); + //~^ bool_assert_comparison debug_assert!("".is_empty()); + //~^ bool_assert_comparison debug_assert!("".is_empty()); + //~^ bool_assert_comparison debug_assert!(!"requires negation".is_empty()); + //~^ bool_assert_comparison debug_assert!(!"requires negation".is_empty()); + //~^ bool_assert_comparison } diff --git a/tests/ui/bool_assert_comparison.rs b/tests/ui/bool_assert_comparison.rs index dc51fcf1d36b..5ab4f475b063 100644 --- a/tests/ui/bool_assert_comparison.rs +++ b/tests/ui/bool_assert_comparison.rs @@ -85,65 +85,90 @@ fn main() { assert_eq!("a".len(), 1); assert_eq!("a".is_empty(), false); + //~^ bool_assert_comparison assert_eq!("".is_empty(), true); + //~^ bool_assert_comparison assert_eq!(true, "".is_empty()); + //~^ bool_assert_comparison assert_eq!(a!(), b!()); assert_eq!(a!(), "".is_empty()); assert_eq!("".is_empty(), b!()); assert_eq!(a, true); assert_eq!(b, true); + //~^ bool_assert_comparison assert_ne!("a".len(), 1); assert_ne!("a".is_empty(), false); + //~^ bool_assert_comparison assert_ne!("".is_empty(), true); + //~^ bool_assert_comparison assert_ne!(true, "".is_empty()); + //~^ bool_assert_comparison assert_ne!(a!(), b!()); assert_ne!(a!(), "".is_empty()); assert_ne!("".is_empty(), b!()); assert_ne!(a, true); assert_ne!(b, true); + //~^ bool_assert_comparison debug_assert_eq!("a".len(), 1); debug_assert_eq!("a".is_empty(), false); + //~^ bool_assert_comparison debug_assert_eq!("".is_empty(), true); + //~^ bool_assert_comparison debug_assert_eq!(true, "".is_empty()); + //~^ bool_assert_comparison debug_assert_eq!(a!(), b!()); debug_assert_eq!(a!(), "".is_empty()); debug_assert_eq!("".is_empty(), b!()); debug_assert_eq!(a, true); debug_assert_eq!(b, true); + //~^ bool_assert_comparison debug_assert_ne!("a".len(), 1); debug_assert_ne!("a".is_empty(), false); + //~^ bool_assert_comparison debug_assert_ne!("".is_empty(), true); + //~^ bool_assert_comparison debug_assert_ne!(true, "".is_empty()); + //~^ bool_assert_comparison debug_assert_ne!(a!(), b!()); debug_assert_ne!(a!(), "".is_empty()); debug_assert_ne!("".is_empty(), b!()); debug_assert_ne!(a, true); debug_assert_ne!(b, true); + //~^ bool_assert_comparison // assert with error messages assert_eq!("a".len(), 1, "tadam {}", 1); assert_eq!("a".len(), 1, "tadam {}", true); assert_eq!("a".is_empty(), false, "tadam {}", 1); + //~^ bool_assert_comparison assert_eq!("a".is_empty(), false, "tadam {}", true); + //~^ bool_assert_comparison assert_eq!(false, "a".is_empty(), "tadam {}", true); + //~^ bool_assert_comparison assert_eq!(a, true, "tadam {}", false); debug_assert_eq!("a".len(), 1, "tadam {}", 1); debug_assert_eq!("a".len(), 1, "tadam {}", true); debug_assert_eq!("a".is_empty(), false, "tadam {}", 1); + //~^ bool_assert_comparison debug_assert_eq!("a".is_empty(), false, "tadam {}", true); + //~^ bool_assert_comparison debug_assert_eq!(false, "a".is_empty(), "tadam {}", true); + //~^ bool_assert_comparison debug_assert_eq!(a, true, "tadam {}", false); assert_eq!(a!(), true); + //~^ bool_assert_comparison assert_eq!(true, b!()); + //~^ bool_assert_comparison use debug_assert_eq as renamed; renamed!(a, true); renamed!(b, true); + //~^ bool_assert_comparison let non_copy = NonCopy; assert_eq!(non_copy, true); @@ -158,12 +183,20 @@ fn main() { in_macro!(a); assert_eq!("".is_empty(), true); + //~^ bool_assert_comparison assert_ne!("".is_empty(), false); + //~^ bool_assert_comparison assert_ne!("requires negation".is_empty(), true); + //~^ bool_assert_comparison assert_eq!("requires negation".is_empty(), false); + //~^ bool_assert_comparison debug_assert_eq!("".is_empty(), true); + //~^ bool_assert_comparison debug_assert_ne!("".is_empty(), false); + //~^ bool_assert_comparison debug_assert_ne!("requires negation".is_empty(), true); + //~^ bool_assert_comparison debug_assert_eq!("requires negation".is_empty(), false); + //~^ bool_assert_comparison } diff --git a/tests/ui/bool_assert_comparison.stderr b/tests/ui/bool_assert_comparison.stderr index 41183c61ee01..a1d0af543617 100644 --- a/tests/ui/bool_assert_comparison.stderr +++ b/tests/ui/bool_assert_comparison.stderr @@ -13,7 +13,7 @@ LL + assert!(!"a".is_empty()); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:88:5 + --> tests/ui/bool_assert_comparison.rs:89:5 | LL | assert_eq!("".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + assert!("".is_empty()); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:89:5 + --> tests/ui/bool_assert_comparison.rs:91:5 | LL | assert_eq!(true, "".is_empty()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + assert!("".is_empty()); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:94:5 + --> tests/ui/bool_assert_comparison.rs:97:5 | LL | assert_eq!(b, true); | ^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + assert!(b); | error: used `assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:97:5 + --> tests/ui/bool_assert_comparison.rs:101:5 | LL | assert_ne!("a".is_empty(), false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + assert!("a".is_empty()); | error: used `assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:98:5 + --> tests/ui/bool_assert_comparison.rs:103:5 | LL | assert_ne!("".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + assert!(!"".is_empty()); | error: used `assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:99:5 + --> tests/ui/bool_assert_comparison.rs:105:5 | LL | assert_ne!(true, "".is_empty()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + assert!(!"".is_empty()); | error: used `assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:104:5 + --> tests/ui/bool_assert_comparison.rs:111:5 | LL | assert_ne!(b, true); | ^^^^^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL + assert!(!b); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:107:5 + --> tests/ui/bool_assert_comparison.rs:115:5 | LL | debug_assert_eq!("a".is_empty(), false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL + debug_assert!(!"a".is_empty()); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:108:5 + --> tests/ui/bool_assert_comparison.rs:117:5 | LL | debug_assert_eq!("".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL + debug_assert!("".is_empty()); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:109:5 + --> tests/ui/bool_assert_comparison.rs:119:5 | LL | debug_assert_eq!(true, "".is_empty()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL + debug_assert!("".is_empty()); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:114:5 + --> tests/ui/bool_assert_comparison.rs:125:5 | LL | debug_assert_eq!(b, true); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -145,7 +145,7 @@ LL + debug_assert!(b); | error: used `debug_assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:117:5 + --> tests/ui/bool_assert_comparison.rs:129:5 | LL | debug_assert_ne!("a".is_empty(), false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL + debug_assert!("a".is_empty()); | error: used `debug_assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:118:5 + --> tests/ui/bool_assert_comparison.rs:131:5 | LL | debug_assert_ne!("".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -169,7 +169,7 @@ LL + debug_assert!(!"".is_empty()); | error: used `debug_assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:119:5 + --> tests/ui/bool_assert_comparison.rs:133:5 | LL | debug_assert_ne!(true, "".is_empty()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -181,7 +181,7 @@ LL + debug_assert!(!"".is_empty()); | error: used `debug_assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:124:5 + --> tests/ui/bool_assert_comparison.rs:139:5 | LL | debug_assert_ne!(b, true); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -193,7 +193,7 @@ LL + debug_assert!(!b); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:129:5 + --> tests/ui/bool_assert_comparison.rs:145:5 | LL | assert_eq!("a".is_empty(), false, "tadam {}", 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -205,7 +205,7 @@ LL + assert!(!"a".is_empty(), "tadam {}", 1); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:130:5 + --> tests/ui/bool_assert_comparison.rs:147:5 | LL | assert_eq!("a".is_empty(), false, "tadam {}", true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +217,7 @@ LL + assert!(!"a".is_empty(), "tadam {}", true); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:131:5 + --> tests/ui/bool_assert_comparison.rs:149:5 | LL | assert_eq!(false, "a".is_empty(), "tadam {}", true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -229,7 +229,7 @@ LL + assert!(!"a".is_empty(), "tadam {}", true); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:136:5 + --> tests/ui/bool_assert_comparison.rs:155:5 | LL | debug_assert_eq!("a".is_empty(), false, "tadam {}", 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,7 +241,7 @@ LL + debug_assert!(!"a".is_empty(), "tadam {}", 1); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:137:5 + --> tests/ui/bool_assert_comparison.rs:157:5 | LL | debug_assert_eq!("a".is_empty(), false, "tadam {}", true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -253,7 +253,7 @@ LL + debug_assert!(!"a".is_empty(), "tadam {}", true); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:138:5 + --> tests/ui/bool_assert_comparison.rs:159:5 | LL | debug_assert_eq!(false, "a".is_empty(), "tadam {}", true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -265,7 +265,7 @@ LL + debug_assert!(!"a".is_empty(), "tadam {}", true); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:141:5 + --> tests/ui/bool_assert_comparison.rs:163:5 | LL | assert_eq!(a!(), true); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -277,7 +277,7 @@ LL + assert!(a!()); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:142:5 + --> tests/ui/bool_assert_comparison.rs:165:5 | LL | assert_eq!(true, b!()); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -289,7 +289,7 @@ LL + assert!(b!()); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:146:5 + --> tests/ui/bool_assert_comparison.rs:170:5 | LL | renamed!(b, true); | ^^^^^^^^^^^^^^^^^ @@ -301,7 +301,7 @@ LL + debug_assert!(b); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:160:5 + --> tests/ui/bool_assert_comparison.rs:185:5 | LL | assert_eq!("".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -313,7 +313,7 @@ LL + assert!("".is_empty()); | error: used `assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:161:5 + --> tests/ui/bool_assert_comparison.rs:187:5 | LL | assert_ne!("".is_empty(), false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -325,7 +325,7 @@ LL + assert!("".is_empty()); | error: used `assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:162:5 + --> tests/ui/bool_assert_comparison.rs:189:5 | LL | assert_ne!("requires negation".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -337,7 +337,7 @@ LL + assert!(!"requires negation".is_empty()); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:163:5 + --> tests/ui/bool_assert_comparison.rs:191:5 | LL | assert_eq!("requires negation".is_empty(), false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -349,7 +349,7 @@ LL + assert!(!"requires negation".is_empty()); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:165:5 + --> tests/ui/bool_assert_comparison.rs:194:5 | LL | debug_assert_eq!("".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -361,7 +361,7 @@ LL + debug_assert!("".is_empty()); | error: used `debug_assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:166:5 + --> tests/ui/bool_assert_comparison.rs:196:5 | LL | debug_assert_ne!("".is_empty(), false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -373,7 +373,7 @@ LL + debug_assert!("".is_empty()); | error: used `debug_assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:167:5 + --> tests/ui/bool_assert_comparison.rs:198:5 | LL | debug_assert_ne!("requires negation".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -385,7 +385,7 @@ LL + debug_assert!(!"requires negation".is_empty()); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:168:5 + --> tests/ui/bool_assert_comparison.rs:200:5 | LL | debug_assert_eq!("requires negation".is_empty(), false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/bool_comparison.fixed b/tests/ui/bool_comparison.fixed index 3db91eec8fa7..166abbe549c3 100644 --- a/tests/ui/bool_comparison.fixed +++ b/tests/ui/bool_comparison.fixed @@ -5,72 +5,86 @@ fn main() { let x = true; if x { + //~^ bool_comparison "yes" } else { "no" }; if !x { + //~^ bool_comparison "yes" } else { "no" }; if x { + //~^ bool_comparison "yes" } else { "no" }; if !x { + //~^ bool_comparison "yes" } else { "no" }; if !x { + //~^ bool_comparison "yes" } else { "no" }; if x { + //~^ bool_comparison "yes" } else { "no" }; if !x { + //~^ bool_comparison "yes" } else { "no" }; if x { + //~^ bool_comparison "yes" } else { "no" }; if !x { + //~^ bool_comparison "yes" } else { "no" }; if x { + //~^ bool_comparison "yes" } else { "no" }; if x { + //~^ bool_comparison "yes" } else { "no" }; if !x { + //~^ bool_comparison "yes" } else { "no" }; let y = true; if !x & y { + //~^ bool_comparison "yes" } else { "no" }; if x & !y { + //~^ bool_comparison "yes" } else { "no" @@ -119,12 +133,16 @@ fn issue4983() { let b = false; if a != b {}; + //~^ bool_comparison if a != b {}; + //~^ bool_comparison if a == b {}; if !a == !b {}; if b != a {}; + //~^ bool_comparison if b != a {}; + //~^ bool_comparison if b == a {}; if !b == !a {}; } @@ -149,9 +167,13 @@ fn issue3973() { // lint, could be simplified if !m!(func) {} + //~^ bool_comparison if !m!(func) {} + //~^ bool_comparison if m!(func) {} + //~^ bool_comparison if m!(func) {} + //~^ bool_comparison // no lint with a variable let is_debug = false; @@ -169,8 +191,11 @@ fn issue3973() { #[allow(clippy::unnecessary_cast)] fn issue9907() { let _ = (1 >= 2) as usize; + //~^ bool_comparison let _ = (!m!(func)) as usize; + //~^ bool_comparison // This is not part of the issue, but an unexpected found when fixing the issue, // the provided span was inside of macro rather than the macro callsite. let _ = ((1 < 2) != m!(func)) as usize; + //~^ bool_comparison } diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs index fbcfb1cee7bf..7265c2b4c5a6 100644 --- a/tests/ui/bool_comparison.rs +++ b/tests/ui/bool_comparison.rs @@ -5,72 +5,86 @@ fn main() { let x = true; if x == true { + //~^ bool_comparison "yes" } else { "no" }; if x == false { + //~^ bool_comparison "yes" } else { "no" }; if true == x { + //~^ bool_comparison "yes" } else { "no" }; if false == x { + //~^ bool_comparison "yes" } else { "no" }; if x != true { + //~^ bool_comparison "yes" } else { "no" }; if x != false { + //~^ bool_comparison "yes" } else { "no" }; if true != x { + //~^ bool_comparison "yes" } else { "no" }; if false != x { + //~^ bool_comparison "yes" } else { "no" }; if x < true { + //~^ bool_comparison "yes" } else { "no" }; if false < x { + //~^ bool_comparison "yes" } else { "no" }; if x > false { + //~^ bool_comparison "yes" } else { "no" }; if true > x { + //~^ bool_comparison "yes" } else { "no" }; let y = true; if x < y { + //~^ bool_comparison "yes" } else { "no" }; if x > y { + //~^ bool_comparison "yes" } else { "no" @@ -119,12 +133,16 @@ fn issue4983() { let b = false; if a == !b {}; + //~^ bool_comparison if !a == b {}; + //~^ bool_comparison if a == b {}; if !a == !b {}; if b == !a {}; + //~^ bool_comparison if !b == a {}; + //~^ bool_comparison if b == a {}; if !b == !a {}; } @@ -149,9 +167,13 @@ fn issue3973() { // lint, could be simplified if false == m!(func) {} + //~^ bool_comparison if m!(func) == false {} + //~^ bool_comparison if true == m!(func) {} + //~^ bool_comparison if m!(func) == true {} + //~^ bool_comparison // no lint with a variable let is_debug = false; @@ -169,8 +191,11 @@ fn issue3973() { #[allow(clippy::unnecessary_cast)] fn issue9907() { let _ = ((1 < 2) == false) as usize; + //~^ bool_comparison let _ = (false == m!(func)) as usize; + //~^ bool_comparison // This is not part of the issue, but an unexpected found when fixing the issue, // the provided span was inside of macro rather than the macro callsite. let _ = ((1 < 2) == !m!(func)) as usize; + //~^ bool_comparison } diff --git a/tests/ui/bool_comparison.stderr b/tests/ui/bool_comparison.stderr index 7c8b906221fa..ddbb9ff78edb 100644 --- a/tests/ui/bool_comparison.stderr +++ b/tests/ui/bool_comparison.stderr @@ -8,145 +8,145 @@ LL | if x == true { = help: to override `-D warnings` add `#[allow(clippy::bool_comparison)]` error: equality checks against false can be replaced by a negation - --> tests/ui/bool_comparison.rs:12:8 + --> tests/ui/bool_comparison.rs:13:8 | LL | if x == false { | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: equality checks against true are unnecessary - --> tests/ui/bool_comparison.rs:17:8 + --> tests/ui/bool_comparison.rs:19:8 | LL | if true == x { | ^^^^^^^^^ help: try simplifying it as shown: `x` error: equality checks against false can be replaced by a negation - --> tests/ui/bool_comparison.rs:22:8 + --> tests/ui/bool_comparison.rs:25:8 | LL | if false == x { | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against true can be replaced by a negation - --> tests/ui/bool_comparison.rs:27:8 + --> tests/ui/bool_comparison.rs:31:8 | LL | if x != true { | ^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against false are unnecessary - --> tests/ui/bool_comparison.rs:32:8 + --> tests/ui/bool_comparison.rs:37:8 | LL | if x != false { | ^^^^^^^^^^ help: try simplifying it as shown: `x` error: inequality checks against true can be replaced by a negation - --> tests/ui/bool_comparison.rs:37:8 + --> tests/ui/bool_comparison.rs:43:8 | LL | if true != x { | ^^^^^^^^^ help: try simplifying it as shown: `!x` error: inequality checks against false are unnecessary - --> tests/ui/bool_comparison.rs:42:8 + --> tests/ui/bool_comparison.rs:49:8 | LL | if false != x { | ^^^^^^^^^^ help: try simplifying it as shown: `x` error: less than comparison against true can be replaced by a negation - --> tests/ui/bool_comparison.rs:47:8 + --> tests/ui/bool_comparison.rs:55:8 | LL | if x < true { | ^^^^^^^^ help: try simplifying it as shown: `!x` error: greater than checks against false are unnecessary - --> tests/ui/bool_comparison.rs:52:8 + --> tests/ui/bool_comparison.rs:61:8 | LL | if false < x { | ^^^^^^^^^ help: try simplifying it as shown: `x` error: greater than checks against false are unnecessary - --> tests/ui/bool_comparison.rs:57:8 + --> tests/ui/bool_comparison.rs:67:8 | LL | if x > false { | ^^^^^^^^^ help: try simplifying it as shown: `x` error: less than comparison against true can be replaced by a negation - --> tests/ui/bool_comparison.rs:62:8 + --> tests/ui/bool_comparison.rs:73:8 | LL | if true > x { | ^^^^^^^^ help: try simplifying it as shown: `!x` error: order comparisons between booleans can be simplified - --> tests/ui/bool_comparison.rs:68:8 + --> tests/ui/bool_comparison.rs:80:8 | LL | if x < y { | ^^^^^ help: try simplifying it as shown: `!x & y` error: order comparisons between booleans can be simplified - --> tests/ui/bool_comparison.rs:73:8 + --> tests/ui/bool_comparison.rs:86:8 | LL | if x > y { | ^^^^^ help: try simplifying it as shown: `x & !y` error: this comparison might be written more concisely - --> tests/ui/bool_comparison.rs:121:8 + --> tests/ui/bool_comparison.rs:135:8 | LL | if a == !b {}; | ^^^^^^^ help: try simplifying it as shown: `a != b` error: this comparison might be written more concisely - --> tests/ui/bool_comparison.rs:122:8 + --> tests/ui/bool_comparison.rs:137:8 | LL | if !a == b {}; | ^^^^^^^ help: try simplifying it as shown: `a != b` error: this comparison might be written more concisely - --> tests/ui/bool_comparison.rs:126:8 + --> tests/ui/bool_comparison.rs:142:8 | LL | if b == !a {}; | ^^^^^^^ help: try simplifying it as shown: `b != a` error: this comparison might be written more concisely - --> tests/ui/bool_comparison.rs:127:8 + --> tests/ui/bool_comparison.rs:144:8 | LL | if !b == a {}; | ^^^^^^^ help: try simplifying it as shown: `b != a` error: equality checks against false can be replaced by a negation - --> tests/ui/bool_comparison.rs:151:8 + --> tests/ui/bool_comparison.rs:169:8 | LL | if false == m!(func) {} | ^^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `!m!(func)` error: equality checks against false can be replaced by a negation - --> tests/ui/bool_comparison.rs:152:8 + --> tests/ui/bool_comparison.rs:171:8 | LL | if m!(func) == false {} | ^^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `!m!(func)` error: equality checks against true are unnecessary - --> tests/ui/bool_comparison.rs:153:8 + --> tests/ui/bool_comparison.rs:173:8 | LL | if true == m!(func) {} | ^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `m!(func)` error: equality checks against true are unnecessary - --> tests/ui/bool_comparison.rs:154:8 + --> tests/ui/bool_comparison.rs:175:8 | LL | if m!(func) == true {} | ^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `m!(func)` error: equality checks against false can be replaced by a negation - --> tests/ui/bool_comparison.rs:171:14 + --> tests/ui/bool_comparison.rs:193:14 | LL | let _ = ((1 < 2) == false) as usize; | ^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `1 >= 2` error: equality checks against false can be replaced by a negation - --> tests/ui/bool_comparison.rs:172:14 + --> tests/ui/bool_comparison.rs:195:14 | LL | let _ = (false == m!(func)) as usize; | ^^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `!m!(func)` error: this comparison might be written more concisely - --> tests/ui/bool_comparison.rs:175:14 + --> tests/ui/bool_comparison.rs:199:14 | LL | let _ = ((1 < 2) == !m!(func)) as usize; | ^^^^^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `(1 < 2) != m!(func)` diff --git a/tests/ui/bool_to_int_with_if.fixed b/tests/ui/bool_to_int_with_if.fixed index f7dad28b0369..0080801d46b7 100644 --- a/tests/ui/bool_to_int_with_if.fixed +++ b/tests/ui/bool_to_int_with_if.fixed @@ -88,6 +88,7 @@ fn main() { // Lint returns and type inference fn some_fn(a: bool) -> u8 { u8::from(a) + //~^ bool_to_int_with_if } fn side_effect() {} diff --git a/tests/ui/bool_to_int_with_if.rs b/tests/ui/bool_to_int_with_if.rs index d22871d2c8f2..72c7e2c71c56 100644 --- a/tests/ui/bool_to_int_with_if.rs +++ b/tests/ui/bool_to_int_with_if.rs @@ -12,31 +12,37 @@ fn main() { // Should lint // precedence if a { + //~^ bool_to_int_with_if 1 } else { 0 }; if a { + //~^ bool_to_int_with_if 0 } else { 1 }; if !a { + //~^ bool_to_int_with_if 1 } else { 0 }; if a || b { + //~^ bool_to_int_with_if 1 } else { 0 }; if cond(a, b) { + //~^ bool_to_int_with_if 1 } else { 0 }; if x + y < 4 { + //~^ bool_to_int_with_if 1 } else { 0 @@ -46,6 +52,7 @@ fn main() { if a { 123 } else if b { + //~^ bool_to_int_with_if 1 } else { 0 @@ -55,6 +62,7 @@ fn main() { if a { 123 } else if b { + //~^ bool_to_int_with_if 0 } else { 1 @@ -120,6 +128,7 @@ fn main() { // Lint returns and type inference fn some_fn(a: bool) -> u8 { if a { 1 } else { 0 } + //~^ bool_to_int_with_if } fn side_effect() {} diff --git a/tests/ui/bool_to_int_with_if.stderr b/tests/ui/bool_to_int_with_if.stderr index 1e4a843071a1..415e80f8d73d 100644 --- a/tests/ui/bool_to_int_with_if.stderr +++ b/tests/ui/bool_to_int_with_if.stderr @@ -2,6 +2,7 @@ error: boolean to int conversion using if --> tests/ui/bool_to_int_with_if.rs:14:5 | LL | / if a { +LL | | LL | | 1 LL | | } else { LL | | 0 @@ -13,9 +14,10 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::bool_to_int_with_if)]` error: boolean to int conversion using if - --> tests/ui/bool_to_int_with_if.rs:19:5 + --> tests/ui/bool_to_int_with_if.rs:20:5 | LL | / if a { +LL | | LL | | 0 LL | | } else { LL | | 1 @@ -25,9 +27,10 @@ LL | | }; = note: `!a as i32` or `(!a).into()` can also be valid options error: boolean to int conversion using if - --> tests/ui/bool_to_int_with_if.rs:24:5 + --> tests/ui/bool_to_int_with_if.rs:26:5 | LL | / if !a { +LL | | LL | | 1 LL | | } else { LL | | 0 @@ -37,9 +40,10 @@ LL | | }; = note: `!a as i32` or `(!a).into()` can also be valid options error: boolean to int conversion using if - --> tests/ui/bool_to_int_with_if.rs:29:5 + --> tests/ui/bool_to_int_with_if.rs:32:5 | LL | / if a || b { +LL | | LL | | 1 LL | | } else { LL | | 0 @@ -49,9 +53,10 @@ LL | | }; = note: `(a || b) as i32` or `(a || b).into()` can also be valid options error: boolean to int conversion using if - --> tests/ui/bool_to_int_with_if.rs:34:5 + --> tests/ui/bool_to_int_with_if.rs:38:5 | LL | / if cond(a, b) { +LL | | LL | | 1 LL | | } else { LL | | 0 @@ -61,9 +66,10 @@ LL | | }; = note: `cond(a, b) as i32` or `cond(a, b).into()` can also be valid options error: boolean to int conversion using if - --> tests/ui/bool_to_int_with_if.rs:39:5 + --> tests/ui/bool_to_int_with_if.rs:44:5 | LL | / if x + y < 4 { +LL | | LL | | 1 LL | | } else { LL | | 0 @@ -73,10 +79,11 @@ LL | | }; = note: `(x + y < 4) as i32` or `(x + y < 4).into()` can also be valid options error: boolean to int conversion using if - --> tests/ui/bool_to_int_with_if.rs:48:12 + --> tests/ui/bool_to_int_with_if.rs:54:12 | LL | } else if b { | ____________^ +LL | | LL | | 1 LL | | } else { LL | | 0 @@ -86,10 +93,11 @@ LL | | }; = note: `b as i32` or `b.into()` can also be valid options error: boolean to int conversion using if - --> tests/ui/bool_to_int_with_if.rs:57:12 + --> tests/ui/bool_to_int_with_if.rs:64:12 | LL | } else if b { | ____________^ +LL | | LL | | 0 LL | | } else { LL | | 1 @@ -99,7 +107,7 @@ LL | | }; = note: `!b as i32` or `(!b).into()` can also be valid options error: boolean to int conversion using if - --> tests/ui/bool_to_int_with_if.rs:122:5 + --> tests/ui/bool_to_int_with_if.rs:130:5 | LL | if a { 1 } else { 0 } | ^^^^^^^^^^^^^^^^^^^^^ help: replace with from: `u8::from(a)` diff --git a/tests/ui/borrow_and_ref_as_ptr.fixed b/tests/ui/borrow_and_ref_as_ptr.fixed index 2950b158deb6..b7ee4c6165a7 100644 --- a/tests/ui/borrow_and_ref_as_ptr.fixed +++ b/tests/ui/borrow_and_ref_as_ptr.fixed @@ -7,5 +7,7 @@ fn f(_: T) {} fn main() { let mut val = 0; f(&raw const val); + //~^ borrow_as_ptr f(&raw mut val); + //~^ borrow_as_ptr } diff --git a/tests/ui/borrow_and_ref_as_ptr.rs b/tests/ui/borrow_and_ref_as_ptr.rs index 19eb8f292337..d16ed5aa7b29 100644 --- a/tests/ui/borrow_and_ref_as_ptr.rs +++ b/tests/ui/borrow_and_ref_as_ptr.rs @@ -7,5 +7,7 @@ fn f(_: T) {} fn main() { let mut val = 0; f(&val as *const _); + //~^ borrow_as_ptr f(&mut val as *mut i32); + //~^ borrow_as_ptr } diff --git a/tests/ui/borrow_and_ref_as_ptr.stderr b/tests/ui/borrow_and_ref_as_ptr.stderr index 82a27af303c2..e02f3d8bed97 100644 --- a/tests/ui/borrow_and_ref_as_ptr.stderr +++ b/tests/ui/borrow_and_ref_as_ptr.stderr @@ -8,7 +8,7 @@ LL | f(&val as *const _); = help: to override `-D warnings` add `#[allow(clippy::borrow_as_ptr)]` error: borrow as raw pointer - --> tests/ui/borrow_and_ref_as_ptr.rs:10:7 + --> tests/ui/borrow_and_ref_as_ptr.rs:11:7 | LL | f(&mut val as *mut i32); | ^^^^^^^^^^^^^^^^^^^^ help: try: `&raw mut val` diff --git a/tests/ui/borrow_as_ptr.fixed b/tests/ui/borrow_as_ptr.fixed index 5365f3dd443c..3dca06fce4b8 100644 --- a/tests/ui/borrow_as_ptr.fixed +++ b/tests/ui/borrow_as_ptr.fixed @@ -9,6 +9,7 @@ fn a() -> i32 { fn main() { let val = 1; let _p = std::ptr::addr_of!(val); + //~^ borrow_as_ptr let _p = &0 as *const i32; let _p = &a() as *const i32; let vec = vec![1]; @@ -16,12 +17,15 @@ fn main() { let mut val_mut = 1; let _p_mut = std::ptr::addr_of_mut!(val_mut); + //~^ borrow_as_ptr let mut x: [i32; 2] = [42, 43]; let _raw = std::ptr::addr_of_mut!(x[1]).wrapping_offset(-1); + //~^ borrow_as_ptr } fn issue_13882() { let mut x: [i32; 2] = [42, 43]; let _raw = (&raw mut x[1]).wrapping_offset(-1); + //~^ borrow_as_ptr } diff --git a/tests/ui/borrow_as_ptr.rs b/tests/ui/borrow_as_ptr.rs index 261894f1341c..3559dc23d018 100644 --- a/tests/ui/borrow_as_ptr.rs +++ b/tests/ui/borrow_as_ptr.rs @@ -9,6 +9,7 @@ fn a() -> i32 { fn main() { let val = 1; let _p = &val as *const i32; + //~^ borrow_as_ptr let _p = &0 as *const i32; let _p = &a() as *const i32; let vec = vec![1]; @@ -16,12 +17,15 @@ fn main() { let mut val_mut = 1; let _p_mut = &mut val_mut as *mut i32; + //~^ borrow_as_ptr let mut x: [i32; 2] = [42, 43]; let _raw = (&mut x[1] as *mut i32).wrapping_offset(-1); + //~^ borrow_as_ptr } fn issue_13882() { let mut x: [i32; 2] = [42, 43]; let _raw = (&mut x[1] as *mut i32).wrapping_offset(-1); + //~^ borrow_as_ptr } diff --git a/tests/ui/borrow_as_ptr.stderr b/tests/ui/borrow_as_ptr.stderr index 4595fa4f2487..4a9f2ed4aa00 100644 --- a/tests/ui/borrow_as_ptr.stderr +++ b/tests/ui/borrow_as_ptr.stderr @@ -8,19 +8,19 @@ LL | let _p = &val as *const i32; = help: to override `-D warnings` add `#[allow(clippy::borrow_as_ptr)]` error: borrow as raw pointer - --> tests/ui/borrow_as_ptr.rs:18:18 + --> tests/ui/borrow_as_ptr.rs:19:18 | LL | let _p_mut = &mut val_mut as *mut i32; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::addr_of_mut!(val_mut)` error: borrow as raw pointer - --> tests/ui/borrow_as_ptr.rs:21:16 + --> tests/ui/borrow_as_ptr.rs:23:16 | LL | let _raw = (&mut x[1] as *mut i32).wrapping_offset(-1); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::addr_of_mut!(x[1])` error: borrow as raw pointer - --> tests/ui/borrow_as_ptr.rs:26:17 + --> tests/ui/borrow_as_ptr.rs:29:17 | LL | let _raw = (&mut x[1] as *mut i32).wrapping_offset(-1); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `&raw mut x[1]` diff --git a/tests/ui/borrow_as_ptr_no_std.fixed b/tests/ui/borrow_as_ptr_no_std.fixed index 26c6a5033d16..8972fc0a5e0d 100644 --- a/tests/ui/borrow_as_ptr_no_std.fixed +++ b/tests/ui/borrow_as_ptr_no_std.fixed @@ -6,8 +6,10 @@ pub fn main(_argc: isize, _argv: *const *const u8) -> isize { let val = 1; let _p = core::ptr::addr_of!(val); + //~^ borrow_as_ptr let mut val_mut = 1; let _p_mut = core::ptr::addr_of_mut!(val_mut); + //~^ borrow_as_ptr 0 } diff --git a/tests/ui/borrow_as_ptr_no_std.rs b/tests/ui/borrow_as_ptr_no_std.rs index d8d8b4c380ce..6b4c732dc56e 100644 --- a/tests/ui/borrow_as_ptr_no_std.rs +++ b/tests/ui/borrow_as_ptr_no_std.rs @@ -6,8 +6,10 @@ pub fn main(_argc: isize, _argv: *const *const u8) -> isize { let val = 1; let _p = &val as *const i32; + //~^ borrow_as_ptr let mut val_mut = 1; let _p_mut = &mut val_mut as *mut i32; + //~^ borrow_as_ptr 0 } diff --git a/tests/ui/borrow_as_ptr_no_std.stderr b/tests/ui/borrow_as_ptr_no_std.stderr index 488e0bd96776..6012577559d0 100644 --- a/tests/ui/borrow_as_ptr_no_std.stderr +++ b/tests/ui/borrow_as_ptr_no_std.stderr @@ -8,7 +8,7 @@ LL | let _p = &val as *const i32; = help: to override `-D warnings` add `#[allow(clippy::borrow_as_ptr)]` error: borrow as raw pointer - --> tests/ui/borrow_as_ptr_no_std.rs:11:18 + --> tests/ui/borrow_as_ptr_no_std.rs:12:18 | LL | let _p_mut = &mut val_mut as *mut i32; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::addr_of_mut!(val_mut)` diff --git a/tests/ui/borrow_as_ptr_raw_ref.fixed b/tests/ui/borrow_as_ptr_raw_ref.fixed index d6842e60a3e9..7fbb942b5bc7 100644 --- a/tests/ui/borrow_as_ptr_raw_ref.fixed +++ b/tests/ui/borrow_as_ptr_raw_ref.fixed @@ -9,6 +9,7 @@ fn a() -> i32 { fn main() { let val = 1; let _p = &raw const val; + //~^ borrow_as_ptr let _p = &0 as *const i32; let _p = &a() as *const i32; let vec = vec![1]; @@ -16,4 +17,5 @@ fn main() { let mut val_mut = 1; let _p_mut = &raw mut val_mut; + //~^ borrow_as_ptr } diff --git a/tests/ui/borrow_as_ptr_raw_ref.rs b/tests/ui/borrow_as_ptr_raw_ref.rs index 3c9daed18f15..9cbf2e5c266d 100644 --- a/tests/ui/borrow_as_ptr_raw_ref.rs +++ b/tests/ui/borrow_as_ptr_raw_ref.rs @@ -9,6 +9,7 @@ fn a() -> i32 { fn main() { let val = 1; let _p = &val as *const i32; + //~^ borrow_as_ptr let _p = &0 as *const i32; let _p = &a() as *const i32; let vec = vec![1]; @@ -16,4 +17,5 @@ fn main() { let mut val_mut = 1; let _p_mut = &mut val_mut as *mut i32; + //~^ borrow_as_ptr } diff --git a/tests/ui/borrow_as_ptr_raw_ref.stderr b/tests/ui/borrow_as_ptr_raw_ref.stderr index 5611fcae8d4b..e5c8aec77986 100644 --- a/tests/ui/borrow_as_ptr_raw_ref.stderr +++ b/tests/ui/borrow_as_ptr_raw_ref.stderr @@ -8,7 +8,7 @@ LL | let _p = &val as *const i32; = help: to override `-D warnings` add `#[allow(clippy::borrow_as_ptr)]` error: borrow as raw pointer - --> tests/ui/borrow_as_ptr_raw_ref.rs:18:18 + --> tests/ui/borrow_as_ptr_raw_ref.rs:19:18 | LL | let _p_mut = &mut val_mut as *mut i32; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&raw mut val_mut` diff --git a/tests/ui/borrow_box.fixed b/tests/ui/borrow_box.fixed index 08ea60583ea4..e6e7f74af7cf 100644 --- a/tests/ui/borrow_box.fixed +++ b/tests/ui/borrow_box.fixed @@ -23,17 +23,17 @@ pub fn test1(foo: &mut Box) { pub fn test2() { let foo: &bool; - //~^ ERROR: you seem to be trying to use `&Box`. Consider using just `&T` + //~^ borrowed_box } struct Test3<'a> { foo: &'a bool, - //~^ ERROR: you seem to be trying to use `&Box`. Consider using just `&T` + //~^ borrowed_box } trait Test4 { fn test4(a: &bool); - //~^ ERROR: you seem to be trying to use `&Box`. Consider using just `&T` + //~^ borrowed_box } use std::any::Any; @@ -94,24 +94,28 @@ pub fn test13(boxed_slice: &mut Box<[i32]>) { // The suggestion should include proper parentheses to avoid a syntax error. pub fn test14(_display: &dyn Display) {} -//~^ ERROR: you seem to be trying to use `&Box`. Consider using just `&T` +//~^ borrowed_box + pub fn test15(_display: &(dyn Display + Send)) {} -//~^ ERROR: you seem to be trying to use `&Box`. Consider using just `&T` +//~^ borrowed_box + pub fn test16<'a>(_display: &'a (dyn Display + 'a)) {} -//~^ ERROR: you seem to be trying to use `&Box`. Consider using just `&T` +//~^ borrowed_box pub fn test17(_display: &impl Display) {} -//~^ ERROR: you seem to be trying to use `&Box`. Consider using just `&T` +//~^ borrowed_box + pub fn test18(_display: &(impl Display + Send)) {} -//~^ ERROR: you seem to be trying to use `&Box`. Consider using just `&T` +//~^ borrowed_box + pub fn test19<'a>(_display: &'a (impl Display + 'a)) {} -//~^ ERROR: you seem to be trying to use `&Box`. Consider using just `&T` +//~^ borrowed_box // This exists only to check what happens when parentheses are already present. // Even though the current implementation doesn't put extra parentheses, // it's fine that unnecessary parentheses appear in the future for some reason. pub fn test20(_display: &(dyn Display + Send)) {} -//~^ ERROR: you seem to be trying to use `&Box`. Consider using just `&T` +//~^ borrowed_box #[allow(clippy::borrowed_box)] trait Trait { diff --git a/tests/ui/borrow_box.rs b/tests/ui/borrow_box.rs index b55de1701daa..43cf809306b3 100644 --- a/tests/ui/borrow_box.rs +++ b/tests/ui/borrow_box.rs @@ -23,17 +23,17 @@ pub fn test1(foo: &mut Box) { pub fn test2() { let foo: &Box; - //~^ ERROR: you seem to be trying to use `&Box`. Consider using just `&T` + //~^ borrowed_box } struct Test3<'a> { foo: &'a Box, - //~^ ERROR: you seem to be trying to use `&Box`. Consider using just `&T` + //~^ borrowed_box } trait Test4 { fn test4(a: &Box); - //~^ ERROR: you seem to be trying to use `&Box`. Consider using just `&T` + //~^ borrowed_box } use std::any::Any; @@ -94,24 +94,28 @@ pub fn test13(boxed_slice: &mut Box<[i32]>) { // The suggestion should include proper parentheses to avoid a syntax error. pub fn test14(_display: &Box) {} -//~^ ERROR: you seem to be trying to use `&Box`. Consider using just `&T` +//~^ borrowed_box + pub fn test15(_display: &Box) {} -//~^ ERROR: you seem to be trying to use `&Box`. Consider using just `&T` +//~^ borrowed_box + pub fn test16<'a>(_display: &'a Box) {} -//~^ ERROR: you seem to be trying to use `&Box`. Consider using just `&T` +//~^ borrowed_box pub fn test17(_display: &Box) {} -//~^ ERROR: you seem to be trying to use `&Box`. Consider using just `&T` +//~^ borrowed_box + pub fn test18(_display: &Box) {} -//~^ ERROR: you seem to be trying to use `&Box`. Consider using just `&T` +//~^ borrowed_box + pub fn test19<'a>(_display: &'a Box) {} -//~^ ERROR: you seem to be trying to use `&Box`. Consider using just `&T` +//~^ borrowed_box // This exists only to check what happens when parentheses are already present. // Even though the current implementation doesn't put extra parentheses, // it's fine that unnecessary parentheses appear in the future for some reason. pub fn test20(_display: &Box<(dyn Display + Send)>) {} -//~^ ERROR: you seem to be trying to use `&Box`. Consider using just `&T` +//~^ borrowed_box #[allow(clippy::borrowed_box)] trait Trait { diff --git a/tests/ui/borrow_box.stderr b/tests/ui/borrow_box.stderr index 6f80f86c3b3d..dbe3757dd435 100644 --- a/tests/ui/borrow_box.stderr +++ b/tests/ui/borrow_box.stderr @@ -29,37 +29,37 @@ LL | pub fn test14(_display: &Box) {} | ^^^^^^^^^^^^^^^^^ help: try: `&dyn Display` error: you seem to be trying to use `&Box`. Consider using just `&T` - --> tests/ui/borrow_box.rs:98:25 + --> tests/ui/borrow_box.rs:99:25 | LL | pub fn test15(_display: &Box) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&(dyn Display + Send)` error: you seem to be trying to use `&Box`. Consider using just `&T` - --> tests/ui/borrow_box.rs:100:29 + --> tests/ui/borrow_box.rs:102:29 | LL | pub fn test16<'a>(_display: &'a Box) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&'a (dyn Display + 'a)` error: you seem to be trying to use `&Box`. Consider using just `&T` - --> tests/ui/borrow_box.rs:103:25 + --> tests/ui/borrow_box.rs:105:25 | LL | pub fn test17(_display: &Box) {} | ^^^^^^^^^^^^^^^^^^ help: try: `&impl Display` error: you seem to be trying to use `&Box`. Consider using just `&T` - --> tests/ui/borrow_box.rs:105:25 + --> tests/ui/borrow_box.rs:108:25 | LL | pub fn test18(_display: &Box) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&(impl Display + Send)` error: you seem to be trying to use `&Box`. Consider using just `&T` - --> tests/ui/borrow_box.rs:107:29 + --> tests/ui/borrow_box.rs:111:29 | LL | pub fn test19<'a>(_display: &'a Box) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&'a (impl Display + 'a)` error: you seem to be trying to use `&Box`. Consider using just `&T` - --> tests/ui/borrow_box.rs:113:25 + --> tests/ui/borrow_box.rs:117:25 | LL | pub fn test20(_display: &Box<(dyn Display + Send)>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&(dyn Display + Send)` diff --git a/tests/ui/borrow_deref_ref.fixed b/tests/ui/borrow_deref_ref.fixed index 22e984c46d24..17c224f10bfe 100644 --- a/tests/ui/borrow_deref_ref.fixed +++ b/tests/ui/borrow_deref_ref.fixed @@ -11,8 +11,10 @@ mod should_lint { fn one_help() { let a = &12; let b = a; + //~^ borrow_deref_ref let b = &mut bar(&12); + //~^ borrow_deref_ref } fn bar(x: &u32) -> &u32 { @@ -67,6 +69,8 @@ mod false_negative { let x = &12; let addr_x = &x as *const _ as usize; let addr_y = &x as *const _ as usize; // assert ok + // + //~^^ borrow_deref_ref // let addr_y = &x as *const _ as usize; // assert fail assert_ne!(addr_x, addr_y); } diff --git a/tests/ui/borrow_deref_ref.rs b/tests/ui/borrow_deref_ref.rs index 61d89193f42f..130ed2903dc6 100644 --- a/tests/ui/borrow_deref_ref.rs +++ b/tests/ui/borrow_deref_ref.rs @@ -11,8 +11,10 @@ mod should_lint { fn one_help() { let a = &12; let b = &*a; + //~^ borrow_deref_ref let b = &mut &*bar(&12); + //~^ borrow_deref_ref } fn bar(x: &u32) -> &u32 { @@ -67,6 +69,8 @@ mod false_negative { let x = &12; let addr_x = &x as *const _ as usize; let addr_y = &&*x as *const _ as usize; // assert ok + // + //~^^ borrow_deref_ref // let addr_y = &x as *const _ as usize; // assert fail assert_ne!(addr_x, addr_y); } diff --git a/tests/ui/borrow_deref_ref.stderr b/tests/ui/borrow_deref_ref.stderr index 7fa43ef49cf7..f5868aa87490 100644 --- a/tests/ui/borrow_deref_ref.stderr +++ b/tests/ui/borrow_deref_ref.stderr @@ -8,13 +8,13 @@ LL | let b = &*a; = help: to override `-D warnings` add `#[allow(clippy::borrow_deref_ref)]` error: deref on an immutable reference - --> tests/ui/borrow_deref_ref.rs:15:22 + --> tests/ui/borrow_deref_ref.rs:16:22 | LL | let b = &mut &*bar(&12); | ^^^^^^^^^^ help: if you would like to reborrow, try removing `&*`: `bar(&12)` error: deref on an immutable reference - --> tests/ui/borrow_deref_ref.rs:69:23 + --> tests/ui/borrow_deref_ref.rs:71:23 | LL | let addr_y = &&*x as *const _ as usize; // assert ok | ^^^ help: if you would like to reborrow, try removing `&*`: `x` diff --git a/tests/ui/borrow_deref_ref_unfixable.rs b/tests/ui/borrow_deref_ref_unfixable.rs index be9887339597..f05a90d2c1fa 100644 --- a/tests/ui/borrow_deref_ref_unfixable.rs +++ b/tests/ui/borrow_deref_ref_unfixable.rs @@ -7,7 +7,6 @@ mod should_lint { fn two_helps() { let s = &String::new(); let x: &str = &*s; - //~^ ERROR: deref on an immutable reference - //~| NOTE: `-D clippy::borrow-deref-ref` implied by `-D warnings` + //~^ borrow_deref_ref } } diff --git a/tests/ui/borrow_interior_mutable_const/others.rs b/tests/ui/borrow_interior_mutable_const/others.rs index a49d53fbbd38..fa729b62d7f5 100644 --- a/tests/ui/borrow_interior_mutable_const/others.rs +++ b/tests/ui/borrow_interior_mutable_const/others.rs @@ -62,14 +62,20 @@ mod issue12979 { const CELL_REF: StaticRef<(UnsafeCell,)> = unsafe { StaticRef::new(std::ptr::null()) }; fn main() { - ATOMIC.store(1, Ordering::SeqCst); //~ ERROR: interior mutability - assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR: interior mutability + ATOMIC.store(1, Ordering::SeqCst); + //~^ borrow_interior_mutable_const + assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); + //~^ borrow_interior_mutable_const let _once = ONCE_INIT; - let _once_ref = &ONCE_INIT; //~ ERROR: interior mutability - let _once_ref_2 = &&ONCE_INIT; //~ ERROR: interior mutability - let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR: interior mutability - let _once_mut = &mut ONCE_INIT; //~ ERROR: interior mutability + let _once_ref = &ONCE_INIT; + //~^ borrow_interior_mutable_const + let _once_ref_2 = &&ONCE_INIT; + //~^ borrow_interior_mutable_const + let _once_ref_4 = &&&&ONCE_INIT; + //~^ borrow_interior_mutable_const + let _once_mut = &mut ONCE_INIT; + //~^ borrow_interior_mutable_const let _atomic_into_inner = ATOMIC.into_inner(); // these should be all fine. let _twice = (ONCE_INIT, ONCE_INIT); @@ -80,22 +86,30 @@ fn main() { let _ref_array_once = &[ONCE_INIT, ONCE_INIT][0]; // referencing projection is still bad. - let _ = &ATOMIC_TUPLE; //~ ERROR: interior mutability - let _ = &ATOMIC_TUPLE.0; //~ ERROR: interior mutability - let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR: interior mutability - let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR: interior mutability - let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR: interior mutability + let _ = &ATOMIC_TUPLE; + //~^ borrow_interior_mutable_const + let _ = &ATOMIC_TUPLE.0; + //~^ borrow_interior_mutable_const + let _ = &(&&&&ATOMIC_TUPLE).0; + //~^ borrow_interior_mutable_const + let _ = &ATOMIC_TUPLE.0[0]; + //~^ borrow_interior_mutable_const + let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); + //~^ borrow_interior_mutable_const let _ = &ATOMIC_TUPLE.2; let _ = (&&&&ATOMIC_TUPLE).0; let _ = (&&&&ATOMIC_TUPLE).2; let _ = ATOMIC_TUPLE.0; - let _ = ATOMIC_TUPLE.0[0]; //~ ERROR: interior mutability + let _ = ATOMIC_TUPLE.0[0]; + //~^ borrow_interior_mutable_const let _ = ATOMIC_TUPLE.1.into_iter(); let _ = ATOMIC_TUPLE.2; let _ = &{ ATOMIC_TUPLE }; - CELL.set(2); //~ ERROR: interior mutability - assert_eq!(CELL.get(), 6); //~ ERROR: interior mutability + CELL.set(2); + //~^ borrow_interior_mutable_const + assert_eq!(CELL.get(), 6); + //~^ borrow_interior_mutable_const assert_eq!(INTEGER, 8); assert!(STRING.is_empty()); diff --git a/tests/ui/borrow_interior_mutable_const/others.stderr b/tests/ui/borrow_interior_mutable_const/others.stderr index 4cefcc28008d..decea153f717 100644 --- a/tests/ui/borrow_interior_mutable_const/others.stderr +++ b/tests/ui/borrow_interior_mutable_const/others.stderr @@ -12,7 +12,7 @@ LL | #![deny(clippy::borrow_interior_mutable_const)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/others.rs:66:16 + --> tests/ui/borrow_interior_mutable_const/others.rs:67:16 | LL | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); | ^^^^^^ @@ -20,7 +20,7 @@ LL | assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/others.rs:69:22 + --> tests/ui/borrow_interior_mutable_const/others.rs:71:22 | LL | let _once_ref = &ONCE_INIT; | ^^^^^^^^^ @@ -28,7 +28,7 @@ LL | let _once_ref = &ONCE_INIT; = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/others.rs:70:25 + --> tests/ui/borrow_interior_mutable_const/others.rs:73:25 | LL | let _once_ref_2 = &&ONCE_INIT; | ^^^^^^^^^ @@ -36,7 +36,7 @@ LL | let _once_ref_2 = &&ONCE_INIT; = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/others.rs:71:27 + --> tests/ui/borrow_interior_mutable_const/others.rs:75:27 | LL | let _once_ref_4 = &&&&ONCE_INIT; | ^^^^^^^^^ @@ -44,7 +44,7 @@ LL | let _once_ref_4 = &&&&ONCE_INIT; = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/others.rs:72:26 + --> tests/ui/borrow_interior_mutable_const/others.rs:77:26 | LL | let _once_mut = &mut ONCE_INIT; | ^^^^^^^^^ @@ -52,7 +52,7 @@ LL | let _once_mut = &mut ONCE_INIT; = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/others.rs:83:14 + --> tests/ui/borrow_interior_mutable_const/others.rs:89:14 | LL | let _ = &ATOMIC_TUPLE; | ^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL | let _ = &ATOMIC_TUPLE; = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/others.rs:84:14 + --> tests/ui/borrow_interior_mutable_const/others.rs:91:14 | LL | let _ = &ATOMIC_TUPLE.0; | ^^^^^^^^^^^^ @@ -68,7 +68,7 @@ LL | let _ = &ATOMIC_TUPLE.0; = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/others.rs:85:19 + --> tests/ui/borrow_interior_mutable_const/others.rs:93:19 | LL | let _ = &(&&&&ATOMIC_TUPLE).0; | ^^^^^^^^^^^^ @@ -76,7 +76,7 @@ LL | let _ = &(&&&&ATOMIC_TUPLE).0; = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/others.rs:86:14 + --> tests/ui/borrow_interior_mutable_const/others.rs:95:14 | LL | let _ = &ATOMIC_TUPLE.0[0]; | ^^^^^^^^^^^^ @@ -84,7 +84,7 @@ LL | let _ = &ATOMIC_TUPLE.0[0]; = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/others.rs:87:13 + --> tests/ui/borrow_interior_mutable_const/others.rs:97:13 | LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); | ^^^^^^^^^^^^ @@ -92,7 +92,7 @@ LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/others.rs:92:13 + --> tests/ui/borrow_interior_mutable_const/others.rs:103:13 | LL | let _ = ATOMIC_TUPLE.0[0]; | ^^^^^^^^^^^^ @@ -100,7 +100,7 @@ LL | let _ = ATOMIC_TUPLE.0[0]; = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/others.rs:97:5 + --> tests/ui/borrow_interior_mutable_const/others.rs:109:5 | LL | CELL.set(2); | ^^^^ @@ -108,7 +108,7 @@ LL | CELL.set(2); = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/others.rs:98:16 + --> tests/ui/borrow_interior_mutable_const/others.rs:111:16 | LL | assert_eq!(CELL.get(), 6); | ^^^^ diff --git a/tests/ui/borrow_interior_mutable_const/projections.rs b/tests/ui/borrow_interior_mutable_const/projections.rs new file mode 100644 index 000000000000..bbe5538fbe12 --- /dev/null +++ b/tests/ui/borrow_interior_mutable_const/projections.rs @@ -0,0 +1,42 @@ +#![deny(clippy::borrow_interior_mutable_const)] +#![deny(clippy::declare_interior_mutable_const)] + +// Inspired by https://github.com/rust-lang/rust/pull/130543#issuecomment-2364828139 + +use std::cell::UnsafeCell; + +trait Trait { + type Assoc; +} + +type Assoc = ::Assoc; + +impl Trait for u8 { + type Assoc = UnsafeCell; +} + +impl Trait for () { + type Assoc = (); +} + +enum MaybeMutable { + Mutable(Assoc), + Immutable(Assoc<()>), +} + +const CELL: Assoc = UnsafeCell::new(0); //~ ERROR: interior mutable +const UNIT: Assoc<()> = (); +const MUTABLE: MaybeMutable = MaybeMutable::Mutable(CELL); //~ ERROR: interior mutable +const IMMUTABLE: MaybeMutable = MaybeMutable::Immutable(UNIT); + +fn print_ref(t: &T) { + let p: *const T = t; + println!("{p:p}") +} + +fn main() { + print_ref(&CELL); //~ ERROR: interior mutability + print_ref(&UNIT); + print_ref(&MUTABLE); //~ ERROR: interior mutability + print_ref(&IMMUTABLE); +} diff --git a/tests/ui/borrow_interior_mutable_const/projections.stderr b/tests/ui/borrow_interior_mutable_const/projections.stderr new file mode 100644 index 000000000000..eabaf66560ad --- /dev/null +++ b/tests/ui/borrow_interior_mutable_const/projections.stderr @@ -0,0 +1,44 @@ +error: a `const` item should not be interior mutable + --> tests/ui/borrow_interior_mutable_const/projections.rs:27:1 + | +LL | const CELL: Assoc = UnsafeCell::new(0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider making this `Sync` so that it can go in a static item or using a `thread_local` +note: the lint level is defined here + --> tests/ui/borrow_interior_mutable_const/projections.rs:2:9 + | +LL | #![deny(clippy::declare_interior_mutable_const)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: a `const` item should not be interior mutable + --> tests/ui/borrow_interior_mutable_const/projections.rs:29:1 + | +LL | const MUTABLE: MaybeMutable = MaybeMutable::Mutable(CELL); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider making this `Sync` so that it can go in a static item or using a `thread_local` + +error: a `const` item with interior mutability should not be borrowed + --> tests/ui/borrow_interior_mutable_const/projections.rs:38:16 + | +LL | print_ref(&CELL); + | ^^^^ + | + = help: assign this const to a local or static variable, and use the variable here +note: the lint level is defined here + --> tests/ui/borrow_interior_mutable_const/projections.rs:1:9 + | +LL | #![deny(clippy::borrow_interior_mutable_const)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: a `const` item with interior mutability should not be borrowed + --> tests/ui/borrow_interior_mutable_const/projections.rs:40:16 + | +LL | print_ref(&MUTABLE); + | ^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here + +error: aborting due to 4 previous errors + diff --git a/tests/ui/borrow_interior_mutable_const/traits.rs b/tests/ui/borrow_interior_mutable_const/traits.rs index 5570e7cd6d2e..c4878dbe57b2 100644 --- a/tests/ui/borrow_interior_mutable_const/traits.rs +++ b/tests/ui/borrow_interior_mutable_const/traits.rs @@ -12,7 +12,8 @@ trait ConcreteTypes { const STRING: String; fn function() { - let _ = &Self::ATOMIC; //~ ERROR: interior mutability + let _ = &Self::ATOMIC; + //~^ borrow_interior_mutable_const let _ = &Self::STRING; } } @@ -23,7 +24,8 @@ impl ConcreteTypes for u64 { fn function() { // Lint this again since implementers can choose not to borrow it. - let _ = &Self::ATOMIC; //~ ERROR: interior mutability + let _ = &Self::ATOMIC; + //~^ borrow_interior_mutable_const let _ = &Self::STRING; } } @@ -48,7 +50,8 @@ impl GenericTypes for Vec { fn function() { let _ = &Self::TO_REMAIN_GENERIC; - let _ = &Self::TO_BE_CONCRETE; //~ ERROR: interior mutability + let _ = &Self::TO_BE_CONCRETE; + //~^ borrow_interior_mutable_const } } @@ -83,8 +86,10 @@ impl AssocTypes for Vec { fn function() { let _ = &Self::TO_BE_FROZEN; - let _ = &Self::TO_BE_UNFROZEN; //~ ERROR: interior mutability - let _ = &Self::WRAPPED_TO_BE_UNFROZEN; //~ ERROR: interior mutability + let _ = &Self::TO_BE_UNFROZEN; + //~^ borrow_interior_mutable_const + let _ = &Self::WRAPPED_TO_BE_UNFROZEN; + //~^ borrow_interior_mutable_const let _ = &Self::WRAPPED_TO_BE_GENERIC_PARAM; } } @@ -106,7 +111,8 @@ where fn function() { let _ = &Self::NOT_BOUNDED; - let _ = &Self::BOUNDED; //~ ERROR: interior mutability + let _ = &Self::BOUNDED; + //~^ borrow_interior_mutable_const } } @@ -119,7 +125,8 @@ where fn function() { let _ = &Self::NOT_BOUNDED; - let _ = &Self::BOUNDED; //~ ERROR: interior mutability + let _ = &Self::BOUNDED; + //~^ borrow_interior_mutable_const } } @@ -148,8 +155,10 @@ impl SelfType for AtomicUsize { const WRAPPED_SELF: Option = Some(AtomicUsize::new(21)); fn function() { - let _ = &Self::SELF; //~ ERROR: interior mutability - let _ = &Self::WRAPPED_SELF; //~ ERROR: interior mutability + let _ = &Self::SELF; + //~^ borrow_interior_mutable_const + let _ = &Self::WRAPPED_SELF; + //~^ borrow_interior_mutable_const } } @@ -158,8 +167,10 @@ trait BothOfCellAndGeneric { const INDIRECT: Cell<*const T>; fn function() { - let _ = &Self::DIRECT; //~ ERROR: interior mutability - let _ = &Self::INDIRECT; //~ ERROR: interior mutability + let _ = &Self::DIRECT; + //~^ borrow_interior_mutable_const + let _ = &Self::INDIRECT; + //~^ borrow_interior_mutable_const } } @@ -168,8 +179,10 @@ impl BothOfCellAndGeneric for Vec { const INDIRECT: Cell<*const T> = Cell::new(std::ptr::null()); fn function() { - let _ = &Self::DIRECT; //~ ERROR: interior mutability - let _ = &Self::INDIRECT; //~ ERROR: interior mutability + let _ = &Self::DIRECT; + //~^ borrow_interior_mutable_const + let _ = &Self::INDIRECT; + //~^ borrow_interior_mutable_const } } @@ -188,15 +201,19 @@ where const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); fn function() { - let _ = &Self::ATOMIC; //~ ERROR: interior mutability + let _ = &Self::ATOMIC; + //~^ borrow_interior_mutable_const let _ = &Self::COW; let _ = &Self::GENERIC_TYPE; let _ = &Self::ASSOC_TYPE; - let _ = &Self::BOUNDED_ASSOC_TYPE; //~ ERROR: interior mutability + let _ = &Self::BOUNDED_ASSOC_TYPE; + //~^ borrow_interior_mutable_const } } fn main() { - u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR: interior mutability - assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR: interior mutability + u64::ATOMIC.store(5, Ordering::SeqCst); + //~^ borrow_interior_mutable_const + assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); + //~^ borrow_interior_mutable_const } diff --git a/tests/ui/borrow_interior_mutable_const/traits.stderr b/tests/ui/borrow_interior_mutable_const/traits.stderr index 8602b46b0dcf..cad68ca9260c 100644 --- a/tests/ui/borrow_interior_mutable_const/traits.stderr +++ b/tests/ui/borrow_interior_mutable_const/traits.stderr @@ -12,7 +12,7 @@ LL | #![deny(clippy::borrow_interior_mutable_const)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/traits.rs:26:18 + --> tests/ui/borrow_interior_mutable_const/traits.rs:27:18 | LL | let _ = &Self::ATOMIC; | ^^^^^^^^^^^^ @@ -20,7 +20,7 @@ LL | let _ = &Self::ATOMIC; = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/traits.rs:51:18 + --> tests/ui/borrow_interior_mutable_const/traits.rs:53:18 | LL | let _ = &Self::TO_BE_CONCRETE; | ^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | let _ = &Self::TO_BE_CONCRETE; = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/traits.rs:86:18 + --> tests/ui/borrow_interior_mutable_const/traits.rs:89:18 | LL | let _ = &Self::TO_BE_UNFROZEN; | ^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +36,7 @@ LL | let _ = &Self::TO_BE_UNFROZEN; = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/traits.rs:87:18 + --> tests/ui/borrow_interior_mutable_const/traits.rs:91:18 | LL | let _ = &Self::WRAPPED_TO_BE_UNFROZEN; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | let _ = &Self::WRAPPED_TO_BE_UNFROZEN; = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/traits.rs:109:18 + --> tests/ui/borrow_interior_mutable_const/traits.rs:114:18 | LL | let _ = &Self::BOUNDED; | ^^^^^^^^^^^^^ @@ -52,7 +52,7 @@ LL | let _ = &Self::BOUNDED; = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/traits.rs:122:18 + --> tests/ui/borrow_interior_mutable_const/traits.rs:128:18 | LL | let _ = &Self::BOUNDED; | ^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL | let _ = &Self::BOUNDED; = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/traits.rs:151:18 + --> tests/ui/borrow_interior_mutable_const/traits.rs:158:18 | LL | let _ = &Self::SELF; | ^^^^^^^^^^ @@ -68,7 +68,7 @@ LL | let _ = &Self::SELF; = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/traits.rs:152:18 + --> tests/ui/borrow_interior_mutable_const/traits.rs:160:18 | LL | let _ = &Self::WRAPPED_SELF; | ^^^^^^^^^^^^^^^^^^ @@ -76,23 +76,7 @@ LL | let _ = &Self::WRAPPED_SELF; = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/traits.rs:161:18 - | -LL | let _ = &Self::DIRECT; - | ^^^^^^^^^^^^ - | - = help: assign this const to a local or static variable, and use the variable here - -error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/traits.rs:162:18 - | -LL | let _ = &Self::INDIRECT; - | ^^^^^^^^^^^^^^ - | - = help: assign this const to a local or static variable, and use the variable here - -error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/traits.rs:171:18 + --> tests/ui/borrow_interior_mutable_const/traits.rs:170:18 | LL | let _ = &Self::DIRECT; | ^^^^^^^^^^^^ @@ -108,7 +92,23 @@ LL | let _ = &Self::INDIRECT; = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/traits.rs:191:18 + --> tests/ui/borrow_interior_mutable_const/traits.rs:182:18 + | +LL | let _ = &Self::DIRECT; + | ^^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here + +error: a `const` item with interior mutability should not be borrowed + --> tests/ui/borrow_interior_mutable_const/traits.rs:184:18 + | +LL | let _ = &Self::INDIRECT; + | ^^^^^^^^^^^^^^ + | + = help: assign this const to a local or static variable, and use the variable here + +error: a `const` item with interior mutability should not be borrowed + --> tests/ui/borrow_interior_mutable_const/traits.rs:204:18 | LL | let _ = &Self::ATOMIC; | ^^^^^^^^^^^^ @@ -116,7 +116,7 @@ LL | let _ = &Self::ATOMIC; = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/traits.rs:195:18 + --> tests/ui/borrow_interior_mutable_const/traits.rs:209:18 | LL | let _ = &Self::BOUNDED_ASSOC_TYPE; | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -124,7 +124,7 @@ LL | let _ = &Self::BOUNDED_ASSOC_TYPE; = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/traits.rs:200:5 + --> tests/ui/borrow_interior_mutable_const/traits.rs:215:5 | LL | u64::ATOMIC.store(5, Ordering::SeqCst); | ^^^^^^^^^^^ @@ -132,7 +132,7 @@ LL | u64::ATOMIC.store(5, Ordering::SeqCst); = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/traits.rs:201:16 + --> tests/ui/borrow_interior_mutable_const/traits.rs:217:16 | LL | assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); | ^^^^^^^^^^^ diff --git a/tests/ui/box_collection.rs b/tests/ui/box_collection.rs index 499625ea9c31..0f7d3c74ddd0 100644 --- a/tests/ui/box_collection.rs +++ b/tests/ui/box_collection.rs @@ -19,7 +19,7 @@ fn test_macro() { } fn test1(foo: Box>) {} -//~^ ERROR: you seem to be trying to use `Box>`. Consider using just `Vec<..>` +//~^ box_collection fn test2(foo: Box)>) { // pass if #31 is fixed @@ -27,28 +27,28 @@ fn test2(foo: Box)>) { } fn test3(foo: Box) {} -//~^ ERROR: you seem to be trying to use `Box`. Consider using just `String` +//~^ box_collection fn test4(foo: Box>) {} -//~^ ERROR: you seem to be trying to use `Box>`. Consider using just `HashMap< +//~^ box_collection fn test5(foo: Box>) {} -//~^ ERROR: you seem to be trying to use `Box>`. Consider using just `HashSet< +//~^ box_collection fn test6(foo: Box>) {} -//~^ ERROR: you seem to be trying to use `Box>`. Consider using just `VecDequ +//~^ box_collection fn test7(foo: Box>) {} -//~^ ERROR: you seem to be trying to use `Box>`. Consider using just `Linke +//~^ box_collection fn test8(foo: Box>) {} -//~^ ERROR: you seem to be trying to use `Box>`. Consider using just `BTreeMa +//~^ box_collection fn test9(foo: Box>) {} -//~^ ERROR: you seem to be trying to use `Box>`. Consider using just `BTreeSe +//~^ box_collection fn test10(foo: Box>) {} -//~^ ERROR: you seem to be trying to use `Box>`. Consider using just `Binar +//~^ box_collection fn test_local_not_linted() { let _: Box>; diff --git a/tests/ui/box_default.fixed b/tests/ui/box_default.fixed index 1f2f57c2507d..80000f5de4fd 100644 --- a/tests/ui/box_default.fixed +++ b/tests/ui/box_default.fixed @@ -32,14 +32,22 @@ macro_rules! box_new { fn main() { let string1: Box = Box::default(); + //~^ box_default let string2: Box = Box::default(); + //~^ box_default let impl1: Box = Box::default(); + //~^ box_default let vec: Box> = Box::default(); + //~^ box_default let byte: Box = Box::default(); + //~^ box_default let vec2: Box> = Box::default(); + //~^ box_default let vec3: Box> = Box::default(); + //~^ box_default let plain_default = Box::default(); + //~^ box_default let _: Box = plain_default; let _: Box = Box::new(default!()); @@ -57,6 +65,7 @@ fn main() { let vec4: Box<_> = Box::new(Vec::from([false; 0])); let more = ret_ty_fn(); call_ty_fn(Box::default()); + //~^ box_default issue_10381(); // `Box::>::default()` would be valid here, but not `Box::default()` or @@ -84,6 +93,7 @@ impl X { fn same_generic_param() { Self::x(Box::default()); + //~^ box_default } } diff --git a/tests/ui/box_default.rs b/tests/ui/box_default.rs index addfebc24f58..4681016d7cd3 100644 --- a/tests/ui/box_default.rs +++ b/tests/ui/box_default.rs @@ -32,14 +32,22 @@ macro_rules! box_new { fn main() { let string1: Box = Box::new(Default::default()); + //~^ box_default let string2: Box = Box::new(String::new()); + //~^ box_default let impl1: Box = Box::new(Default::default()); + //~^ box_default let vec: Box> = Box::new(Vec::new()); + //~^ box_default let byte: Box = Box::new(u8::default()); + //~^ box_default let vec2: Box> = Box::new(vec![]); + //~^ box_default let vec3: Box> = Box::new(Vec::from([])); + //~^ box_default let plain_default = Box::new(Default::default()); + //~^ box_default let _: Box = plain_default; let _: Box = Box::new(default!()); @@ -57,6 +65,7 @@ fn main() { let vec4: Box<_> = Box::new(Vec::from([false; 0])); let more = ret_ty_fn(); call_ty_fn(Box::new(u8::default())); + //~^ box_default issue_10381(); // `Box::>::default()` would be valid here, but not `Box::default()` or @@ -84,6 +93,7 @@ impl X { fn same_generic_param() { Self::x(Box::new(T::default())); + //~^ box_default } } diff --git a/tests/ui/box_default.stderr b/tests/ui/box_default.stderr index 39fd0d29bbf9..f63d97665b34 100644 --- a/tests/ui/box_default.stderr +++ b/tests/ui/box_default.stderr @@ -8,55 +8,55 @@ LL | let string1: Box = Box::new(Default::default()); = help: to override `-D warnings` add `#[allow(clippy::box_default)]` error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:35:32 + --> tests/ui/box_default.rs:36:32 | LL | let string2: Box = Box::new(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:36:41 + --> tests/ui/box_default.rs:38:41 | LL | let impl1: Box = Box::new(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:37:29 + --> tests/ui/box_default.rs:40:29 | LL | let vec: Box> = Box::new(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:38:25 + --> tests/ui/box_default.rs:42:25 | LL | let byte: Box = Box::new(u8::default()); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:39:45 + --> tests/ui/box_default.rs:44:45 | LL | let vec2: Box> = Box::new(vec![]); | ^^^^^^^^^^^^^^^^ help: try: `Box::default()` error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:40:32 + --> tests/ui/box_default.rs:46:32 | LL | let vec3: Box> = Box::new(Vec::from([])); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:42:25 + --> tests/ui/box_default.rs:49:25 | LL | let plain_default = Box::new(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:59:16 + --> tests/ui/box_default.rs:67:16 | LL | call_ty_fn(Box::new(u8::default())); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` error: `Box::new(_)` of default value - --> tests/ui/box_default.rs:86:17 + --> tests/ui/box_default.rs:95:17 | LL | Self::x(Box::new(T::default())); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` diff --git a/tests/ui/box_default_no_std.rs b/tests/ui/box_default_no_std.rs index edb701fcd084..2881caf0c185 100644 --- a/tests/ui/box_default_no_std.rs +++ b/tests/ui/box_default_no_std.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::box_default)] #![no_std] #![crate_type = "lib"] diff --git a/tests/ui/boxed_local.rs b/tests/ui/boxed_local.rs index 4f361f5162be..3fb685aa36c1 100644 --- a/tests/ui/boxed_local.rs +++ b/tests/ui/boxed_local.rs @@ -38,8 +38,8 @@ fn warn_call() { } fn warn_arg(x: Box) { - //~^ ERROR: local variable doesn't need to be boxed here - //~| NOTE: `-D clippy::boxed-local` implied by `-D warnings` + //~^ boxed_local + x.foo(); } @@ -121,7 +121,7 @@ pub struct PeekableSeekable { } pub fn new(_needs_name: Box>) -> () {} -//~^ ERROR: local variable doesn't need to be boxed here +//~^ boxed_local /// Regression for #916, #1123 /// @@ -187,7 +187,8 @@ mod issue4804 { // warn on `x: Box` fn default_impl_x(self: Box, x: Box) -> u32 { - //~^ ERROR: local variable doesn't need to be boxed here + //~^ boxed_local + 4 } } @@ -195,7 +196,7 @@ mod issue4804 { trait WarnTrait { // warn on `x: Box` fn foo(x: Box) {} - //~^ ERROR: local variable doesn't need to be boxed here + //~^ boxed_local } } diff --git a/tests/ui/boxed_local.stderr b/tests/ui/boxed_local.stderr index 08fe375afb23..81ebc4fde498 100644 --- a/tests/ui/boxed_local.stderr +++ b/tests/ui/boxed_local.stderr @@ -20,7 +20,7 @@ LL | fn default_impl_x(self: Box, x: Box) -> u32 { | ^ error: local variable doesn't need to be boxed here - --> tests/ui/boxed_local.rs:197:16 + --> tests/ui/boxed_local.rs:198:16 | LL | fn foo(x: Box) {} | ^ diff --git a/tests/ui/branches_sharing_code/false_positives.rs b/tests/ui/branches_sharing_code/false_positives.rs index 5e3a1a29693f..49496e631fb1 100644 --- a/tests/ui/branches_sharing_code/false_positives.rs +++ b/tests/ui/branches_sharing_code/false_positives.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(dead_code)] #![deny(clippy::if_same_then_else, clippy::branches_sharing_code)] diff --git a/tests/ui/branches_sharing_code/shared_at_bottom.rs b/tests/ui/branches_sharing_code/shared_at_bottom.rs index 549908b8770e..06472a4f5d57 100644 --- a/tests/ui/branches_sharing_code/shared_at_bottom.rs +++ b/tests/ui/branches_sharing_code/shared_at_bottom.rs @@ -33,8 +33,8 @@ fn simple_examples() { // The rest is self contained and moveable => Only lint the rest let result = false; - //~^ ERROR: all if blocks contain the same code at the end - //~| NOTE: the end suggestion probably needs some adjustments to use the expressio + //~^ branches_sharing_code + println!("Block end!"); result }; @@ -53,7 +53,7 @@ fn simple_examples() { } else { println!("This is also eq with the else block"); println!("Same end of block"); - //~^ ERROR: all if blocks contain the same code at the end + //~^ branches_sharing_code } // Use of outer scope value @@ -71,7 +71,7 @@ fn simple_examples() { println!("I'm a local because I use the value `z`: `{}`", z); println!( - //~^ ERROR: all if blocks contain the same code at the end + //~^ branches_sharing_code "I'm moveable because I know: `outer_scope_value`: '{}'", outer_scope_value ); @@ -84,7 +84,7 @@ fn simple_examples() { println!("Hello World"); } else { println!("Hello World"); - //~^ ERROR: all if blocks contain the same code at the end + //~^ branches_sharing_code } } } @@ -101,7 +101,8 @@ fn simple_but_suggestion_is_invalid() { println!("{}", later_used_value); } else { let later_used_value = "A string value"; - //~^ ERROR: all if blocks contain the same code at the end + //~^ branches_sharing_code + println!("{}", later_used_value); // I'm expecting a note about this } @@ -115,7 +116,8 @@ fn simple_but_suggestion_is_invalid() { println!("Separator print statement"); let simple_examples = "I now identify as a &str :)"; - //~^ ERROR: all if blocks contain the same code at the end + //~^ branches_sharing_code + println!("This is the new simple_example: {}", simple_examples); } simple_examples(); @@ -181,8 +183,7 @@ fn added_note_for_expression_use() -> u32 { } else { let _ = 6; x << 2 - //~^ ERROR: all if blocks contain the same code at the end - //~| NOTE: the end suggestion probably needs some adjustments to use the expressio + //~^ branches_sharing_code }; if x == 9 { @@ -190,8 +191,7 @@ fn added_note_for_expression_use() -> u32 { } else { let _ = 17; x * 4 - //~^ ERROR: all if blocks contain the same code at the end - //~| NOTE: the end suggestion probably needs some adjustments to use the expressio + //~^ branches_sharing_code } } @@ -204,7 +204,8 @@ fn test_suggestion_with_weird_formatting() { // The error message still looks weird tbh but this is the best I can do // for weird formatting if x == 17 { b = 1; a = 0x99; } else { a = 0x99; } - //~^ ERROR: all if blocks contain the same code at the end + //~^ branches_sharing_code + } fn fp_test() { diff --git a/tests/ui/branches_sharing_code/shared_at_bottom.stderr b/tests/ui/branches_sharing_code/shared_at_bottom.stderr index 36b177739732..648a99c65ed2 100644 --- a/tests/ui/branches_sharing_code/shared_at_bottom.stderr +++ b/tests/ui/branches_sharing_code/shared_at_bottom.stderr @@ -20,7 +20,7 @@ help: consider moving these statements after the if LL ~ } LL + let result = false; LL + -LL + +LL + LL + println!("Block end!"); LL ~ result; | @@ -79,6 +79,7 @@ error: all if blocks contain the same code at the end | LL | / let later_used_value = "A string value"; LL | | +LL | | LL | | println!("{}", later_used_value); LL | | // I'm expecting a note about this LL | | } @@ -90,14 +91,16 @@ help: consider moving these statements after the if LL ~ } LL + let later_used_value = "A string value"; LL + +LL + LL + println!("{}", later_used_value); | error: all if blocks contain the same code at the end - --> tests/ui/branches_sharing_code/shared_at_bottom.rs:117:5 + --> tests/ui/branches_sharing_code/shared_at_bottom.rs:118:5 | LL | / let simple_examples = "I now identify as a &str :)"; LL | | +LL | | LL | | println!("This is the new simple_example: {}", simple_examples); LL | | } | |_____^ @@ -108,14 +111,15 @@ help: consider moving these statements after the if LL ~ } LL + let simple_examples = "I now identify as a &str :)"; LL + +LL + LL + println!("This is the new simple_example: {}", simple_examples); | error: all if blocks contain the same code at the end - --> tests/ui/branches_sharing_code/shared_at_bottom.rs:183:5 + --> tests/ui/branches_sharing_code/shared_at_bottom.rs:185:5 | LL | / x << 2 -... | +LL | | LL | | }; | |_____^ | @@ -127,10 +131,10 @@ LL ~ x << 2; | error: all if blocks contain the same code at the end - --> tests/ui/branches_sharing_code/shared_at_bottom.rs:192:5 + --> tests/ui/branches_sharing_code/shared_at_bottom.rs:193:5 | LL | / x * 4 -... | +LL | | LL | | } | |_____^ | diff --git a/tests/ui/branches_sharing_code/shared_at_top.rs b/tests/ui/branches_sharing_code/shared_at_top.rs index 9af81f6f7cdd..694c67d4c85b 100644 --- a/tests/ui/branches_sharing_code/shared_at_top.rs +++ b/tests/ui/branches_sharing_code/shared_at_top.rs @@ -9,16 +9,17 @@ fn simple_examples() { // Simple if true { + //~^ branches_sharing_code println!("Hello World!"); println!("I'm branch nr: 1"); } else { println!("Hello World!"); println!("I'm branch nr: 2"); } - //~^^^^^^^ ERROR: all if blocks contain the same code at the start // Else if if x == 0 { + //~^ branches_sharing_code let y = 9; println!("The value y was set to: `{}`", y); let _z = y; @@ -37,11 +38,11 @@ fn simple_examples() { println!("Ha, Pascal allows you to start the array where you want") } - //~^^^^^^^^^^^^^^^^^^^ ERROR: all if blocks contain the same code at the start // Return a value let _ = if x == 7 { - //~^ ERROR: all if blocks contain the same code at the start + //~^ branches_sharing_code + let y = 16; println!("What can I say except: \"you're welcome?\""); let _ = y; @@ -60,6 +61,7 @@ fn simple_but_suggestion_is_invalid() { // Can't be automatically moved because used_value_name is getting used again let used_value_name = 19; if x == 10 { + //~^ branches_sharing_code let used_value_name = "Different type"; println!("Str: {}", used_value_name); let _ = 1; @@ -68,14 +70,15 @@ fn simple_but_suggestion_is_invalid() { println!("Str: {}", used_value_name); let _ = 2; } - //~^^^^^^^^^ ERROR: all if blocks contain the same code at the start + let _ = used_value_name; // This can be automatically moved as `can_be_overridden` is not used again let can_be_overridden = 8; let _ = can_be_overridden; if x == 11 { - //~^ ERROR: all if blocks contain the same code at the start + //~^ branches_sharing_code + let can_be_overridden = "Move me"; println!("I'm also moveable"); let _ = 111; @@ -92,7 +95,8 @@ fn check_if_same_than_else_mask() { #[allow(clippy::if_same_then_else)] if x == 2020 { - //~^ ERROR: all if blocks contain the same code at the start + //~^ branches_sharing_code + println!("This should trigger the `SHARED_CODE_IN_IF_BLOCKS` lint."); println!("Because `IF_SAME_THEN_ELSE` is allowed here"); } else { @@ -105,7 +109,7 @@ fn check_if_same_than_else_mask() { } else { println!("This should trigger `IS_SAME_THAN_ELSE` as usual"); } - //~^^^^^ ERROR: this `if` has identical blocks + //~^^^^^ if_same_then_else } #[allow(clippy::vec_init_then_push)] diff --git a/tests/ui/branches_sharing_code/shared_at_top.stderr b/tests/ui/branches_sharing_code/shared_at_top.stderr index 0d4e19be1f52..d28e9c7af296 100644 --- a/tests/ui/branches_sharing_code/shared_at_top.stderr +++ b/tests/ui/branches_sharing_code/shared_at_top.stderr @@ -2,6 +2,7 @@ error: all if blocks contain the same code at the start --> tests/ui/branches_sharing_code/shared_at_top.rs:11:5 | LL | / if true { +LL | | LL | | println!("Hello World!"); | |_________________________________^ | @@ -20,6 +21,7 @@ error: all if blocks contain the same code at the start --> tests/ui/branches_sharing_code/shared_at_top.rs:21:5 | LL | / if x == 0 { +LL | | LL | | let y = 9; LL | | println!("The value y was set to: `{}`", y); LL | | let _z = y; @@ -38,7 +40,7 @@ error: all if blocks contain the same code at the start --> tests/ui/branches_sharing_code/shared_at_top.rs:43:5 | LL | / let _ = if x == 7 { -LL | | +... | LL | | let y = 16; | |___________________^ | @@ -49,9 +51,10 @@ LL + let _ = if x == 7 { | error: all if blocks contain the same code at the start - --> tests/ui/branches_sharing_code/shared_at_top.rs:62:5 + --> tests/ui/branches_sharing_code/shared_at_top.rs:63:5 | LL | / if x == 10 { +LL | | LL | | let used_value_name = "Different type"; LL | | println!("Str: {}", used_value_name); | |_____________________________________________^ @@ -65,10 +68,11 @@ LL + if x == 10 { | error: all if blocks contain the same code at the start - --> tests/ui/branches_sharing_code/shared_at_top.rs:77:5 + --> tests/ui/branches_sharing_code/shared_at_top.rs:79:5 | LL | / if x == 11 { LL | | +LL | | LL | | let can_be_overridden = "Move me"; LL | | println!("I'm also moveable"); | |______________________________________^ @@ -82,10 +86,11 @@ LL + if x == 11 { | error: all if blocks contain the same code at the start - --> tests/ui/branches_sharing_code/shared_at_top.rs:94:5 + --> tests/ui/branches_sharing_code/shared_at_top.rs:97:5 | LL | / if x == 2020 { LL | | +LL | | LL | | println!("This should trigger the `SHARED_CODE_IN_IF_BLOCKS` lint."); LL | | println!("Because `IF_SAME_THEN_ELSE` is allowed here"); | |________________________________________________________________^ @@ -98,7 +103,7 @@ LL + if x == 2020 { | error: this `if` has identical blocks - --> tests/ui/branches_sharing_code/shared_at_top.rs:103:18 + --> tests/ui/branches_sharing_code/shared_at_top.rs:107:18 | LL | if x == 2019 { | __________________^ @@ -107,7 +112,7 @@ LL | | } else { | |_____^ | note: same as this - --> tests/ui/branches_sharing_code/shared_at_top.rs:105:12 + --> tests/ui/branches_sharing_code/shared_at_top.rs:109:12 | LL | } else { | ____________^ diff --git a/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs b/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs index 36620ee1a9bf..75334f70f1f6 100644 --- a/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs +++ b/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs @@ -15,7 +15,8 @@ fn overlapping_eq_regions() { // Overlap with separator if x == 7 { - //~^ ERROR: all if blocks contain the same code at both the start and the end + //~^ branches_sharing_code + let t = 7; let _overlap_start = t * 2; let _overlap_end = 2 * t; @@ -32,7 +33,8 @@ fn overlapping_eq_regions() { // Overlap with separator if x == 99 { - //~^ ERROR: all if blocks contain the same code at both the start and the end + //~^ branches_sharing_code + let r = 7; let _overlap_start = r; let _overlap_middle = r * r; @@ -62,7 +64,8 @@ fn complexer_example() { let x = 8; let y = 9; if (x > 7 && y < 13) || (x + y) % 2 == 1 { - //~^ ERROR: all if blocks contain the same code at both the start and the end + //~^ branches_sharing_code + let a = 0xcafe; let b = 0xffff00ff; let e_id = gen_id(a, b); @@ -96,7 +99,8 @@ fn added_note_for_expression_use() -> u32 { let x = 9; let _ = if x == 7 { - //~^ ERROR: all if blocks contain the same code at both the start and the end + //~^ branches_sharing_code + let _ = 19; let _splitter = 6; @@ -109,7 +113,8 @@ fn added_note_for_expression_use() -> u32 { }; if x == 9 { - //~^ ERROR: all if blocks contain the same code at both the start and the end + //~^ branches_sharing_code + let _ = 17; let _splitter = 6; diff --git a/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr b/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr index b79307f96778..2200ab450890 100644 --- a/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr +++ b/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr @@ -3,13 +3,14 @@ error: all if blocks contain the same code at both the start and the end | LL | / if x == 7 { LL | | +LL | | LL | | let t = 7; LL | | let _overlap_start = t * 2; LL | | let _overlap_end = 2 * t; | |_________________________________^ | note: this code is shared at the end - --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:30:5 + --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:31:5 | LL | / let _u = 9; LL | | } @@ -33,17 +34,18 @@ LL + let _u = 9; | error: all if blocks contain the same code at both the start and the end - --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:34:5 + --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:35:5 | LL | / if x == 99 { LL | | +LL | | LL | | let r = 7; LL | | let _overlap_start = r; LL | | let _overlap_middle = r * r; | |____________________________________^ | note: this code is shared at the end - --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:46:5 + --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:48:5 | LL | / let _overlap_end = r * r * r; LL | | let z = "end"; @@ -65,17 +67,18 @@ LL + let z = "end"; | error: all if blocks contain the same code at both the start and the end - --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:64:5 + --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:66:5 | LL | / if (x > 7 && y < 13) || (x + y) % 2 == 1 { LL | | +LL | | LL | | let a = 0xcafe; LL | | let b = 0xffff00ff; LL | | let e_id = gen_id(a, b); | |________________________________^ | note: this code is shared at the end - --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:85:5 + --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:88:5 | LL | / let pack = DataPack { LL | | id: e_id, @@ -105,15 +108,15 @@ LL + process_data(pack); | error: all if blocks contain the same code at both the start and the end - --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:98:5 + --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:101:5 | LL | / let _ = if x == 7 { -LL | | +... | LL | | let _ = 19; | |___________________^ | note: this code is shared at the end - --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:108:5 + --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:112:5 | LL | / x << 2 LL | | }; @@ -131,15 +134,15 @@ LL ~ x << 2; | error: all if blocks contain the same code at both the start and the end - --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:111:5 + --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:115:5 | LL | / if x == 9 { -LL | | +... | LL | | let _ = 17; | |___________________^ | note: this code is shared at the end - --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:121:5 + --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:126:5 | LL | / x * 4 LL | | } diff --git a/tests/ui/branches_sharing_code/valid_if_blocks.rs b/tests/ui/branches_sharing_code/valid_if_blocks.rs index b63819d7c393..d72c5eef87ad 100644 --- a/tests/ui/branches_sharing_code/valid_if_blocks.rs +++ b/tests/ui/branches_sharing_code/valid_if_blocks.rs @@ -109,7 +109,7 @@ fn valid_examples() { if false { } else { } - //~^^^ ERROR: this `if` has identical blocks + //~^^^ if_same_then_else } /// This makes sure that the `if_same_then_else` masks the `shared_code_in_if_blocks` lint @@ -127,11 +127,11 @@ fn trigger_other_lint() { println!("How are u today?"); let _ = "This is a string"; } - //~^^^^^^^^^ ERROR: this `if` has identical blocks + //~^^^^^^^^^ if_same_then_else // Only same expression let _ = if x == 6 { 7 } else { 7 }; - //~^ ERROR: this `if` has identical blocks + //~^ if_same_then_else // Same in else if block let _ = if x == 67 { @@ -146,7 +146,7 @@ fn trigger_other_lint() { if y == 90 { "=^.^=" } else { ":D" } }; - //~^^^^^^^^^ ERROR: this `if` has identical blocks + //~^^^^^^^^^ if_same_then_else if x == 0 { println!("I'm single"); @@ -155,7 +155,7 @@ fn trigger_other_lint() { } else { println!("I'm a doppelgänger"); } - //~^^^^^ ERROR: this `if` has identical blocks + //~^^^^^ if_same_then_else } fn main() {} diff --git a/tests/ui/builtin_type_shadow.rs b/tests/ui/builtin_type_shadow.rs index c5addd53434c..eda22b7c38ef 100644 --- a/tests/ui/builtin_type_shadow.rs +++ b/tests/ui/builtin_type_shadow.rs @@ -2,8 +2,8 @@ #![allow(non_camel_case_types)] fn foo(a: u32) -> u32 { - 42 - //~^ ERROR: mismatched types + //~^ builtin_type_shadow + 42 //~ ERROR: mismatched type } fn main() {} diff --git a/tests/ui/builtin_type_shadow.stderr b/tests/ui/builtin_type_shadow.stderr index 033204af9255..a62b41d5c271 100644 --- a/tests/ui/builtin_type_shadow.stderr +++ b/tests/ui/builtin_type_shadow.stderr @@ -8,12 +8,13 @@ LL | fn foo(a: u32) -> u32 { = help: to override `-D warnings` add `#[allow(clippy::builtin_type_shadow)]` error[E0308]: mismatched types - --> tests/ui/builtin_type_shadow.rs:5:5 + --> tests/ui/builtin_type_shadow.rs:6:5 | LL | fn foo(a: u32) -> u32 { | --- --- expected `u32` because of return type | | | expected this type parameter +LL | LL | 42 | ^^ expected type parameter `u32`, found integer | diff --git a/tests/ui/byte_char_slices.fixed b/tests/ui/byte_char_slices.fixed index d1db58f9363e..b0c1b1f034b4 100644 --- a/tests/ui/byte_char_slices.fixed +++ b/tests/ui/byte_char_slices.fixed @@ -3,11 +3,16 @@ fn main() { let bad = b"abc"; + //~^ byte_char_slices let quotes = b"\"Hi"; + //~^ byte_char_slices let quotes = b"'Sup"; + //~^ byte_char_slices let escapes = b"\x42Esc"; + //~^ byte_char_slices let good = &[b'a', 0x42]; let good = [b'a', b'a']; + //~^ useless_vec let good: u8 = [b'a', b'c'].into_iter().sum(); } diff --git a/tests/ui/byte_char_slices.rs b/tests/ui/byte_char_slices.rs index 18648fffceb4..0d6953dda97e 100644 --- a/tests/ui/byte_char_slices.rs +++ b/tests/ui/byte_char_slices.rs @@ -3,11 +3,16 @@ fn main() { let bad = &[b'a', b'b', b'c']; + //~^ byte_char_slices let quotes = &[b'"', b'H', b'i']; + //~^ byte_char_slices let quotes = &[b'\'', b'S', b'u', b'p']; + //~^ byte_char_slices let escapes = &[b'\x42', b'E', b's', b'c']; + //~^ byte_char_slices let good = &[b'a', 0x42]; let good = vec![b'a', b'a']; + //~^ useless_vec let good: u8 = [b'a', b'c'].into_iter().sum(); } diff --git a/tests/ui/byte_char_slices.stderr b/tests/ui/byte_char_slices.stderr index 4e2b5d8a7329..2556aa9c0f76 100644 --- a/tests/ui/byte_char_slices.stderr +++ b/tests/ui/byte_char_slices.stderr @@ -8,25 +8,25 @@ LL | let bad = &[b'a', b'b', b'c']; = help: to override `-D warnings` add `#[allow(clippy::byte_char_slices)]` error: can be more succinctly written as a byte str - --> tests/ui/byte_char_slices.rs:6:18 + --> tests/ui/byte_char_slices.rs:7:18 | LL | let quotes = &[b'"', b'H', b'i']; | ^^^^^^^^^^^^^^^^^^^ help: try: `b"\"Hi"` error: can be more succinctly written as a byte str - --> tests/ui/byte_char_slices.rs:7:18 + --> tests/ui/byte_char_slices.rs:9:18 | LL | let quotes = &[b'\'', b'S', b'u', b'p']; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b"'Sup"` error: can be more succinctly written as a byte str - --> tests/ui/byte_char_slices.rs:8:19 + --> tests/ui/byte_char_slices.rs:11:19 | LL | let escapes = &[b'\x42', b'E', b's', b'c']; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b"\x42Esc"` error: useless use of `vec!` - --> tests/ui/byte_char_slices.rs:11:16 + --> tests/ui/byte_char_slices.rs:15:16 | LL | let good = vec![b'a', b'a']; | ^^^^^^^^^^^^^^^^ help: you can use an array directly: `[b'a', b'a']` diff --git a/tests/ui/bytecount.rs b/tests/ui/bytecount.rs index f3b02fda8a81..f03f99177d54 100644 --- a/tests/ui/bytecount.rs +++ b/tests/ui/bytecount.rs @@ -8,11 +8,11 @@ fn main() { // naive byte count let _ = x.iter().filter(|&&a| a == 0).count(); - //~^ ERROR: you appear to be counting bytes the naive way + //~^ naive_bytecount // naive byte count let _ = (&x[..]).iter().filter(|&a| *a == 0).count(); - //~^ ERROR: you appear to be counting bytes the naive way + //~^ naive_bytecount // not an equality count, OK. let _ = x.iter().filter(|a| **a > 0).count(); @@ -30,7 +30,7 @@ fn main() { // naive byte count let _ = x.iter().filter(|a| b + 1 == **a).count(); - //~^ ERROR: you appear to be counting bytes the naive way + //~^ naive_bytecount let y = vec![0_u16; 3]; diff --git a/tests/ui/bytes_count_to_len.fixed b/tests/ui/bytes_count_to_len.fixed index d20af22535a0..aa0484a83110 100644 --- a/tests/ui/bytes_count_to_len.fixed +++ b/tests/ui/bytes_count_to_len.fixed @@ -1,19 +1,23 @@ #![warn(clippy::bytes_count_to_len)] use std::fs::File; -use std::io::Read; +use std::io::{BufReader, Read}; fn main() { // should fix, because type is String let _ = String::from("foo").len(); + //~^ bytes_count_to_len let s1 = String::from("foo"); let _ = s1.len(); + //~^ bytes_count_to_len // should fix, because type is &str let _ = "foo".len(); + //~^ bytes_count_to_len let s2 = "foo"; let _ = s2.len(); + //~^ bytes_count_to_len // make sure using count() normally doesn't trigger warning let vector = [0, 1, 2]; @@ -26,8 +30,8 @@ fn main() { bytes.bytes().count(); // The type is File, so should not fix - let _ = File::open("foobar").unwrap().bytes().count(); + let _ = BufReader::new(File::open("foobar").unwrap()).bytes().count(); - let f = File::open("foobar").unwrap(); + let f = BufReader::new(File::open("foobar").unwrap()); let _ = f.bytes().count(); } diff --git a/tests/ui/bytes_count_to_len.rs b/tests/ui/bytes_count_to_len.rs index 340e6b412556..7e38858bf783 100644 --- a/tests/ui/bytes_count_to_len.rs +++ b/tests/ui/bytes_count_to_len.rs @@ -1,19 +1,23 @@ #![warn(clippy::bytes_count_to_len)] use std::fs::File; -use std::io::Read; +use std::io::{BufReader, Read}; fn main() { // should fix, because type is String let _ = String::from("foo").bytes().count(); + //~^ bytes_count_to_len let s1 = String::from("foo"); let _ = s1.bytes().count(); + //~^ bytes_count_to_len // should fix, because type is &str let _ = "foo".bytes().count(); + //~^ bytes_count_to_len let s2 = "foo"; let _ = s2.bytes().count(); + //~^ bytes_count_to_len // make sure using count() normally doesn't trigger warning let vector = [0, 1, 2]; @@ -26,8 +30,8 @@ fn main() { bytes.bytes().count(); // The type is File, so should not fix - let _ = File::open("foobar").unwrap().bytes().count(); + let _ = BufReader::new(File::open("foobar").unwrap()).bytes().count(); - let f = File::open("foobar").unwrap(); + let f = BufReader::new(File::open("foobar").unwrap()); let _ = f.bytes().count(); } diff --git a/tests/ui/bytes_count_to_len.stderr b/tests/ui/bytes_count_to_len.stderr index b80f3af18f78..999da9ca1365 100644 --- a/tests/ui/bytes_count_to_len.stderr +++ b/tests/ui/bytes_count_to_len.stderr @@ -8,19 +8,19 @@ LL | let _ = String::from("foo").bytes().count(); = help: to override `-D warnings` add `#[allow(clippy::bytes_count_to_len)]` error: using long and hard to read `.bytes().count()` - --> tests/ui/bytes_count_to_len.rs:10:13 + --> tests/ui/bytes_count_to_len.rs:11:13 | LL | let _ = s1.bytes().count(); | ^^^^^^^^^^^^^^^^^^ help: consider calling `.len()` instead: `s1.len()` error: using long and hard to read `.bytes().count()` - --> tests/ui/bytes_count_to_len.rs:13:13 + --> tests/ui/bytes_count_to_len.rs:15:13 | LL | let _ = "foo".bytes().count(); | ^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.len()` instead: `"foo".len()` error: using long and hard to read `.bytes().count()` - --> tests/ui/bytes_count_to_len.rs:16:13 + --> tests/ui/bytes_count_to_len.rs:19:13 | LL | let _ = s2.bytes().count(); | ^^^^^^^^^^^^^^^^^^ help: consider calling `.len()` instead: `s2.len()` diff --git a/tests/ui/bytes_nth.fixed b/tests/ui/bytes_nth.fixed index da35fcb55e5a..6f4c2e7116e9 100644 --- a/tests/ui/bytes_nth.fixed +++ b/tests/ui/bytes_nth.fixed @@ -5,6 +5,9 @@ fn main() { let s = String::from("String"); let _ = s.as_bytes().get(3).copied(); + //~^ bytes_nth let _ = &s.as_bytes()[3]; + //~^ bytes_nth let _ = s[..].as_bytes().get(3).copied(); + //~^ bytes_nth } diff --git a/tests/ui/bytes_nth.rs b/tests/ui/bytes_nth.rs index 5dbe84ecec8b..27655bebb264 100644 --- a/tests/ui/bytes_nth.rs +++ b/tests/ui/bytes_nth.rs @@ -5,6 +5,9 @@ fn main() { let s = String::from("String"); let _ = s.bytes().nth(3); + //~^ bytes_nth let _ = &s.bytes().nth(3).unwrap(); + //~^ bytes_nth let _ = s[..].bytes().nth(3); + //~^ bytes_nth } diff --git a/tests/ui/bytes_nth.stderr b/tests/ui/bytes_nth.stderr index c5f341cb37f6..c421839ff3f5 100644 --- a/tests/ui/bytes_nth.stderr +++ b/tests/ui/bytes_nth.stderr @@ -8,13 +8,13 @@ LL | let _ = s.bytes().nth(3); = help: to override `-D warnings` add `#[allow(clippy::bytes_nth)]` error: called `.bytes().nth().unwrap()` on a `String` - --> tests/ui/bytes_nth.rs:8:14 + --> tests/ui/bytes_nth.rs:9:14 | LL | let _ = &s.bytes().nth(3).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.as_bytes()[3]` error: called `.bytes().nth()` on a `str` - --> tests/ui/bytes_nth.rs:9:13 + --> tests/ui/bytes_nth.rs:11:13 | LL | let _ = s[..].bytes().nth(3); | ^^^^^^^^^^^^^^^^^^^^ help: try: `s[..].as_bytes().get(3).copied()` diff --git a/tests/ui/case_sensitive_file_extension_comparisons.fixed b/tests/ui/case_sensitive_file_extension_comparisons.fixed index c4d77f24f126..bf7635fdf09b 100644 --- a/tests/ui/case_sensitive_file_extension_comparisons.fixed +++ b/tests/ui/case_sensitive_file_extension_comparisons.fixed @@ -14,6 +14,7 @@ fn is_rust_file(filename: &str) -> bool { std::path::Path::new(filename) .extension() .map_or(false, |ext| ext.eq_ignore_ascii_case("rs")) + //~^ case_sensitive_file_extension_comparisons } fn main() { @@ -21,15 +22,18 @@ fn main() { let _ = std::path::Path::new(&String::new()) .extension() .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); + //~^ case_sensitive_file_extension_comparisons let _ = std::path::Path::new("str") .extension() .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); + //~^ case_sensitive_file_extension_comparisons // The fixup should preserve the indentation level { let _ = std::path::Path::new("str") .extension() .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); + //~^ case_sensitive_file_extension_comparisons } // The test struct should not trigger the lint failure with .ext12 @@ -39,9 +43,11 @@ fn main() { let _ = std::path::Path::new(&String::new()) .extension() .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); + //~^ case_sensitive_file_extension_comparisons let _ = std::path::Path::new("str") .extension() .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); + //~^ case_sensitive_file_extension_comparisons // Should not trigger the lint failure because of the calls to to_lowercase and to_uppercase let _ = String::new().to_lowercase().ends_with(".EXT12"); diff --git a/tests/ui/case_sensitive_file_extension_comparisons.rs b/tests/ui/case_sensitive_file_extension_comparisons.rs index 690e93c2639a..0c4070a42d4b 100644 --- a/tests/ui/case_sensitive_file_extension_comparisons.rs +++ b/tests/ui/case_sensitive_file_extension_comparisons.rs @@ -12,16 +12,20 @@ impl TestStruct { #[allow(dead_code)] fn is_rust_file(filename: &str) -> bool { filename.ends_with(".rs") + //~^ case_sensitive_file_extension_comparisons } fn main() { // std::string::String and &str should trigger the lint failure with .ext12 let _ = String::new().ends_with(".ext12"); + //~^ case_sensitive_file_extension_comparisons let _ = "str".ends_with(".ext12"); + //~^ case_sensitive_file_extension_comparisons // The fixup should preserve the indentation level { let _ = "str".ends_with(".ext12"); + //~^ case_sensitive_file_extension_comparisons } // The test struct should not trigger the lint failure with .ext12 @@ -29,7 +33,9 @@ fn main() { // std::string::String and &str should trigger the lint failure with .EXT12 let _ = String::new().ends_with(".EXT12"); + //~^ case_sensitive_file_extension_comparisons let _ = "str".ends_with(".EXT12"); + //~^ case_sensitive_file_extension_comparisons // Should not trigger the lint failure because of the calls to to_lowercase and to_uppercase let _ = String::new().to_lowercase().ends_with(".EXT12"); diff --git a/tests/ui/case_sensitive_file_extension_comparisons.stderr b/tests/ui/case_sensitive_file_extension_comparisons.stderr index e21815f251b7..e035534d2699 100644 --- a/tests/ui/case_sensitive_file_extension_comparisons.stderr +++ b/tests/ui/case_sensitive_file_extension_comparisons.stderr @@ -15,7 +15,7 @@ LL + .map_or(false, |ext| ext.eq_ignore_ascii_case("rs")) | error: case-sensitive file extension comparison - --> tests/ui/case_sensitive_file_extension_comparisons.rs:19:13 + --> tests/ui/case_sensitive_file_extension_comparisons.rs:20:13 | LL | let _ = String::new().ends_with(".ext12"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -29,7 +29,7 @@ LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); | error: case-sensitive file extension comparison - --> tests/ui/case_sensitive_file_extension_comparisons.rs:20:13 + --> tests/ui/case_sensitive_file_extension_comparisons.rs:22:13 | LL | let _ = "str".ends_with(".ext12"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -43,7 +43,7 @@ LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); | error: case-sensitive file extension comparison - --> tests/ui/case_sensitive_file_extension_comparisons.rs:24:17 + --> tests/ui/case_sensitive_file_extension_comparisons.rs:27:17 | LL | let _ = "str".ends_with(".ext12"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -57,7 +57,7 @@ LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); | error: case-sensitive file extension comparison - --> tests/ui/case_sensitive_file_extension_comparisons.rs:31:13 + --> tests/ui/case_sensitive_file_extension_comparisons.rs:35:13 | LL | let _ = String::new().ends_with(".EXT12"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -71,7 +71,7 @@ LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); | error: case-sensitive file extension comparison - --> tests/ui/case_sensitive_file_extension_comparisons.rs:32:13 + --> tests/ui/case_sensitive_file_extension_comparisons.rs:37:13 | LL | let _ = "str".ends_with(".EXT12"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs index 0de53a75c623..88c2549f4dc5 100644 --- a/tests/ui/cast.rs +++ b/tests/ui/cast.rs @@ -23,101 +23,127 @@ fn main() { // Test clippy::cast_precision_loss let x0 = 1i32; x0 as f32; - //~^ ERROR: casting `i32` to `f32` causes a loss of precision (`i32` is 32 bits wide, - //~| NOTE: `-D clippy::cast-precision-loss` implied by `-D warnings` + //~^ cast_precision_loss + let x1 = 1i64; x1 as f32; - //~^ ERROR: casting `i64` to `f32` causes a loss of precision (`i64` is 64 bits wide, + //~^ cast_precision_loss + x1 as f64; - //~^ ERROR: casting `i64` to `f64` causes a loss of precision (`i64` is 64 bits wide, + //~^ cast_precision_loss + let x2 = 1u32; x2 as f32; - //~^ ERROR: casting `u32` to `f32` causes a loss of precision (`u32` is 32 bits wide, + //~^ cast_precision_loss + let x3 = 1u64; x3 as f32; - //~^ ERROR: casting `u64` to `f32` causes a loss of precision (`u64` is 64 bits wide, + //~^ cast_precision_loss + x3 as f64; - //~^ ERROR: casting `u64` to `f64` causes a loss of precision (`u64` is 64 bits wide, + //~^ cast_precision_loss + // Test clippy::cast_possible_truncation 1f32 as i32; - //~^ ERROR: casting `f32` to `i32` may truncate the value + //~^ cast_possible_truncation + 1f32 as u32; - //~^ ERROR: casting `f32` to `u32` may truncate the value - //~| ERROR: casting `f32` to `u32` may lose the sign of the value - //~| NOTE: `-D clippy::cast-sign-loss` implied by `-D warnings` + //~^ cast_possible_truncation + //~| cast_sign_loss + 1f64 as f32; - //~^ ERROR: casting `f64` to `f32` may truncate the value + //~^ cast_possible_truncation + 1i32 as i8; - //~^ ERROR: casting `i32` to `i8` may truncate the value + //~^ cast_possible_truncation + 1i32 as u8; - //~^ ERROR: casting `i32` to `u8` may truncate the value + //~^ cast_possible_truncation + 1f64 as isize; - //~^ ERROR: casting `f64` to `isize` may truncate the value + //~^ cast_possible_truncation + 1f64 as usize; - //~^ ERROR: casting `f64` to `usize` may truncate the value - //~| ERROR: casting `f64` to `usize` may lose the sign of the value + //~^ cast_possible_truncation + //~| cast_sign_loss + 1f32 as u32 as u16; - //~^ ERROR: casting `u32` to `u16` may truncate the value - //~| ERROR: casting `f32` to `u32` may truncate the value - //~| ERROR: casting `f32` to `u32` may lose the sign of the value + //~^ cast_possible_truncation + //~| cast_possible_truncation + //~| cast_sign_loss + { let _x: i8 = 1i32 as _; - //~^ ERROR: casting `i32` to `i8` may truncate the value + //~^ cast_possible_truncation + 1f32 as i32; - //~^ ERROR: casting `f32` to `i32` may truncate the value + //~^ cast_possible_truncation + 1f64 as i32; - //~^ ERROR: casting `f64` to `i32` may truncate the value + //~^ cast_possible_truncation + 1f32 as u8; - //~^ ERROR: casting `f32` to `u8` may truncate the value - //~| ERROR: casting `f32` to `u8` may lose the sign of the value + //~^ cast_possible_truncation + //~| cast_sign_loss } // Test clippy::cast_possible_wrap 1u8 as i8; - //~^ ERROR: casting `u8` to `i8` may wrap around the value - //~| NOTE: `-D clippy::cast-possible-wrap` implied by `-D warnings` + //~^ cast_possible_wrap + 1u16 as i16; - //~^ ERROR: casting `u16` to `i16` may wrap around the value + //~^ cast_possible_wrap + 1u32 as i32; - //~^ ERROR: casting `u32` to `i32` may wrap around the value + //~^ cast_possible_wrap + 1u64 as i64; - //~^ ERROR: casting `u64` to `i64` may wrap around the value + //~^ cast_possible_wrap + 1usize as isize; - //~^ ERROR: casting `usize` to `isize` may wrap around the value + //~^ cast_possible_wrap + // should not wrap, usize is never 8 bits 1usize as i8; - //~^ ERROR: casting `usize` to `i8` may truncate the value + //~^ cast_possible_truncation + // wraps on 16 bit ptr size 1usize as i16; - //~^ ERROR: casting `usize` to `i16` may truncate the value - //~| ERROR: casting `usize` to `i16` may wrap around the value on targets with 16-bit - //~| NOTE: `usize` and `isize` may be as small as 16 bits on some platforms + //~^ cast_possible_truncation + //~| cast_possible_wrap + // wraps on 32 bit ptr size 1usize as i32; - //~^ ERROR: casting `usize` to `i32` may truncate the value on targets with 64-bit wid - //~| ERROR: casting `usize` to `i32` may wrap around the value on targets with 32-bit + //~^ cast_possible_truncation + //~| cast_possible_wrap + // wraps on 64 bit ptr size 1usize as i64; - //~^ ERROR: casting `usize` to `i64` may wrap around the value on targets with 64-bit + //~^ cast_possible_wrap + // should not wrap, isize is never 8 bits 1u8 as isize; // wraps on 16 bit ptr size 1u16 as isize; - //~^ ERROR: casting `u16` to `isize` may wrap around the value on targets with 16-bit - //~| NOTE: `usize` and `isize` may be as small as 16 bits on some platforms + //~^ cast_possible_wrap + // wraps on 32 bit ptr size 1u32 as isize; - //~^ ERROR: casting `u32` to `isize` may wrap around the value on targets with 32-bit + //~^ cast_possible_wrap + // wraps on 64 bit ptr size 1u64 as isize; - //~^ ERROR: casting `u64` to `isize` may truncate the value on targets with 32-bit wid - //~| ERROR: casting `u64` to `isize` may wrap around the value on targets with 64-bit + //~^ cast_possible_truncation + //~| cast_possible_wrap + // Test clippy::cast_sign_loss 1i32 as u32; -1i32 as u32; - //~^ ERROR: casting `i32` to `u32` may lose the sign of the value + //~^ cast_sign_loss + 1isize as usize; -1isize as usize; - //~^ ERROR: casting `isize` to `usize` may lose the sign of the value + //~^ cast_sign_loss + 0i8 as u8; i8::MAX as u8; i16::MAX as u16; @@ -128,11 +154,14 @@ fn main() { (-1i8).saturating_abs() as u8; // abs() can return a negative value in release builds (i8::MIN).abs() as u8; - //~^ ERROR: casting `i8` to `u8` may lose the sign of the value + //~^ cast_sign_loss + (-1i16).saturating_abs() as u16; (-1i32).saturating_abs() as u32; (-1i64).abs() as u64; + //~^ cast_sign_loss (-1isize).abs() as usize; + //~^ cast_sign_loss (-1i8).checked_abs().unwrap() as u8; (i8::MIN).checked_abs().unwrap() as u8; @@ -140,6 +169,7 @@ fn main() { (-1i32).checked_abs().unwrap() as u32; // SAFETY: -1 is a small number which will always return Some (unsafe { (-1i64).checked_abs().unwrap_unchecked() }) as u64; + //~^ cast_sign_loss (-1isize).checked_abs().expect("-1 is a small number") as usize; (-1i8).isqrt() as u8; @@ -155,6 +185,7 @@ fn main() { (-1i32).checked_isqrt().unwrap() as u32; // SAFETY: -1 is a small number which will always return Some (unsafe { (-1i64).checked_isqrt().unwrap_unchecked() }) as u64; + //~^ cast_sign_loss (-1isize).checked_isqrt().expect("-1 is a small number") as usize; (-1i8).rem_euclid(1i8) as u8; @@ -206,7 +237,7 @@ fn main() { // Test for signed min // should be linted because signed (-99999999999i64).min(1) as i8; - //~^ ERROR: casting `i64` to `i8` may truncate the value + //~^ cast_possible_truncation // Test for various operations that remove enough bits for the result to fit (999999u64 & 1) as u8; @@ -220,7 +251,7 @@ fn main() { 999999u64.clamp(0, 255) as u8; // should still be linted 999999u64.clamp(0, 256) as u8; - //~^ ERROR: casting `u64` to `u8` may truncate the value + //~^ cast_possible_truncation #[derive(Clone, Copy)] enum E1 { @@ -243,10 +274,11 @@ fn main() { impl E2 { fn test(self) { let _ = self as u8; - //~^ ERROR: casting `main::E2` to `u8` may truncate the value + //~^ cast_possible_truncation + let _ = Self::B as u8; - //~^ ERROR: casting `main::E2::B` to `u8` will truncate the value - //~| NOTE: `-D clippy::cast-enum-truncation` implied by `-D warnings` + //~^ cast_enum_truncation + // Don't lint. `255..=256` fits in i16 let _ = self as i16; // Don't lint. @@ -287,9 +319,11 @@ fn main() { impl E5 { fn test(self) { let _ = self as i8; - //~^ ERROR: casting `main::E5` to `i8` may truncate the value + //~^ cast_possible_truncation + let _ = Self::A as i8; - //~^ ERROR: casting `main::E5::A` to `i8` will truncate the value + //~^ cast_enum_truncation + // Don't lint. `-129..=127` fits in i16 let _ = self as i16; // Don't lint. @@ -306,7 +340,8 @@ fn main() { impl E6 { fn test(self) { let _ = self as i16; - //~^ ERROR: casting `main::E6` to `i16` may truncate the value + //~^ cast_possible_truncation + // Don't lint. `2^16-1` fits in u16 let _ = Self::A as u16; // Don't lint. `2^16-1..=2^16` fits in u32 @@ -325,7 +360,8 @@ fn main() { impl E7 { fn test(self) { let _ = self as usize; - //~^ ERROR: casting `main::E7` to `usize` may truncate the value on targets wi + //~^ cast_possible_truncation + // Don't lint. let _ = Self::A as usize; // Don't lint. `2^32-1..=2^32` fits in u64 @@ -372,7 +408,8 @@ fn main() { impl E10 { fn test(self) { let _ = self as u16; - //~^ ERROR: casting `main::E10` to `u16` may truncate the value + //~^ cast_possible_truncation + // Don't lint. let _ = Self::B as u32; // Don't lint. @@ -383,11 +420,13 @@ fn main() { fn avoid_subtract_overflow(q: u32) { let c = (q >> 16) as u8; - //~^ ERROR: casting `u32` to `u8` may truncate the value + //~^ cast_possible_truncation + c as usize; let c = (q / 1000) as u8; - //~^ ERROR: casting `u32` to `u8` may truncate the value + //~^ cast_possible_truncation + c as usize; } @@ -399,70 +438,93 @@ fn issue11642() { fn square(x: i16) -> u32 { let x = x as i32; (x * x) as u32; + //~^ cast_sign_loss x.pow(2) as u32; (-2_i32).saturating_pow(2) as u32 } let _a = |x: i32| -> u32 { (x * x * x * x) as u32 }; + //~^ cast_sign_loss (2_i32).checked_pow(3).unwrap() as u32; + //~^ cast_sign_loss (-2_i32).pow(3) as u32; - //~^ ERROR: casting `i32` to `u32` may lose the sign of the value + //~^ cast_sign_loss (3_i32 % 2) as u32; (3_i32 % -2) as u32; (-5_i32 % 2) as u32; - //~^ ERROR: casting `i32` to `u32` may lose the sign of the value + //~^ cast_sign_loss + (-5_i32 % -2) as u32; - //~^ ERROR: casting `i32` to `u32` may lose the sign of the value + //~^ cast_sign_loss + (2_i32 >> 1) as u32; (-2_i32 >> 1) as u32; - //~^ ERROR: casting `i32` to `u32` may lose the sign of the value + //~^ cast_sign_loss let x: i32 = 10; (x * x) as u32; + //~^ cast_sign_loss (x * x * x) as u32; - //~^ ERROR: casting `i32` to `u32` may lose the sign of the value + //~^ cast_sign_loss let y: i16 = -2; (y * y * y * y * -2) as u16; - //~^ ERROR: casting `i16` to `u16` may lose the sign of the value + //~^ cast_sign_loss + (y * y * y / y * 2) as u16; + //~^ cast_sign_loss (y * y / y * 2) as u16; - //~^ ERROR: casting `i16` to `u16` may lose the sign of the value + //~^ cast_sign_loss + (y / y * y * -2) as u16; - //~^ ERROR: casting `i16` to `u16` may lose the sign of the value + //~^ cast_sign_loss + //~| eq_op (y + y + y + -2) as u16; - //~^ ERROR: casting `i16` to `u16` may lose the sign of the value + //~^ cast_sign_loss + (y + y + y + 2) as u16; - //~^ ERROR: casting `i16` to `u16` may lose the sign of the value + //~^ cast_sign_loss let z: i16 = 2; (z + -2) as u16; - //~^ ERROR: casting `i16` to `u16` may lose the sign of the value + //~^ cast_sign_loss + (z + z + 2) as u16; + //~^ cast_sign_loss fn foo(a: i32, b: i32, c: i32) -> u32 { (a * a * b * b * c * c) as u32; + //~^ cast_sign_loss (a * b * c) as u32; - //~^ ERROR: casting `i32` to `u32` may lose the sign of the value + //~^ cast_sign_loss + (a * -b * c) as u32; - //~^ ERROR: casting `i32` to `u32` may lose the sign of the value + //~^ cast_sign_loss + (a * b * c * c) as u32; + //~^ cast_sign_loss (a * -2) as u32; - //~^ ERROR: casting `i32` to `u32` may lose the sign of the value + //~^ cast_sign_loss + (a * b * c * -2) as u32; - //~^ ERROR: casting `i32` to `u32` may lose the sign of the value + //~^ cast_sign_loss + (a / b) as u32; + //~^ cast_sign_loss (a / b * c) as u32; - //~^ ERROR: casting `i32` to `u32` may lose the sign of the value + //~^ cast_sign_loss + (a / b + b * c) as u32; - //~^ ERROR: casting `i32` to `u32` may lose the sign of the value + //~^ cast_sign_loss + a.saturating_pow(3) as u32; - //~^ ERROR: casting `i32` to `u32` may lose the sign of the value + //~^ cast_sign_loss + (a.abs() * b.pow(2) / c.abs()) as u32 - //~^ ERROR: casting `i32` to `u32` may lose the sign of the value + //~^ cast_sign_loss } } @@ -470,8 +532,14 @@ fn issue11738() { macro_rules! m { () => { let _ = i32::MIN as u32; // cast_sign_loss + // + //~^^ cast_sign_loss let _ = u32::MAX as u8; // cast_possible_truncation + // + //~^^ cast_possible_truncation let _ = std::f64::consts::PI as f32; // cast_possible_truncation + // + //~^^ cast_possible_truncation let _ = 0i8 as i32; // cast_lossless }; } @@ -481,6 +549,8 @@ fn issue11738() { fn issue12506() -> usize { let bar: Result, u32> = Ok(Some(10)); bar.unwrap().unwrap() as usize + //~^ cast_possible_truncation + //~| cast_sign_loss } fn issue12721() { @@ -496,7 +566,8 @@ fn issue12721() { let _ = (999999 & (x() & 255)) as u8; (256 & 999999u64) as u8; - //~^ ERROR: casting `u64` to `u8` may truncate the value + //~^ cast_possible_truncation + (255 % 999999u64) as u8; - //~^ ERROR: casting `u64` to `u8` may truncate the value + //~^ cast_possible_truncation } diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index 901447c738ed..4d03282f6676 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -14,31 +14,31 @@ LL | x1 as f32; | ^^^^^^^^^ error: casting `i64` to `f64` causes a loss of precision (`i64` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide) - --> tests/ui/cast.rs:31:5 + --> tests/ui/cast.rs:32:5 | LL | x1 as f64; | ^^^^^^^^^ error: casting `u32` to `f32` causes a loss of precision (`u32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide) - --> tests/ui/cast.rs:34:5 + --> tests/ui/cast.rs:36:5 | LL | x2 as f32; | ^^^^^^^^^ error: casting `u64` to `f32` causes a loss of precision (`u64` is 64 bits wide, but `f32`'s mantissa is only 23 bits wide) - --> tests/ui/cast.rs:37:5 + --> tests/ui/cast.rs:40:5 | LL | x3 as f32; | ^^^^^^^^^ error: casting `u64` to `f64` causes a loss of precision (`u64` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide) - --> tests/ui/cast.rs:39:5 + --> tests/ui/cast.rs:43:5 | LL | x3 as f64; | ^^^^^^^^^ error: casting `f32` to `i32` may truncate the value - --> tests/ui/cast.rs:42:5 + --> tests/ui/cast.rs:47:5 | LL | 1f32 as i32; | ^^^^^^^^^^^ @@ -48,7 +48,7 @@ LL | 1f32 as i32; = help: to override `-D warnings` add `#[allow(clippy::cast_possible_truncation)]` error: casting `f32` to `u32` may truncate the value - --> tests/ui/cast.rs:44:5 + --> tests/ui/cast.rs:50:5 | LL | 1f32 as u32; | ^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | 1f32 as u32; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:44:5 + --> tests/ui/cast.rs:50:5 | LL | 1f32 as u32; | ^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | 1f32 as u32; = help: to override `-D warnings` add `#[allow(clippy::cast_sign_loss)]` error: casting `f64` to `f32` may truncate the value - --> tests/ui/cast.rs:48:5 + --> tests/ui/cast.rs:54:5 | LL | 1f64 as f32; | ^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | 1f64 as f32; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `i32` to `i8` may truncate the value - --> tests/ui/cast.rs:50:5 + --> tests/ui/cast.rs:57:5 | LL | 1i32 as i8; | ^^^^^^^^^^ @@ -86,7 +86,7 @@ LL + i8::try_from(1i32); | error: casting `i32` to `u8` may truncate the value - --> tests/ui/cast.rs:52:5 + --> tests/ui/cast.rs:60:5 | LL | 1i32 as u8; | ^^^^^^^^^^ @@ -99,7 +99,7 @@ LL + u8::try_from(1i32); | error: casting `f64` to `isize` may truncate the value - --> tests/ui/cast.rs:54:5 + --> tests/ui/cast.rs:63:5 | LL | 1f64 as isize; | ^^^^^^^^^^^^^ @@ -107,7 +107,7 @@ LL | 1f64 as isize; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f64` to `usize` may truncate the value - --> tests/ui/cast.rs:56:5 + --> tests/ui/cast.rs:66:5 | LL | 1f64 as usize; | ^^^^^^^^^^^^^ @@ -115,13 +115,13 @@ LL | 1f64 as usize; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f64` to `usize` may lose the sign of the value - --> tests/ui/cast.rs:56:5 + --> tests/ui/cast.rs:66:5 | LL | 1f64 as usize; | ^^^^^^^^^^^^^ error: casting `u32` to `u16` may truncate the value - --> tests/ui/cast.rs:59:5 + --> tests/ui/cast.rs:70:5 | LL | 1f32 as u32 as u16; | ^^^^^^^^^^^^^^^^^^ @@ -134,7 +134,7 @@ LL + u16::try_from(1f32 as u32); | error: casting `f32` to `u32` may truncate the value - --> tests/ui/cast.rs:59:5 + --> tests/ui/cast.rs:70:5 | LL | 1f32 as u32 as u16; | ^^^^^^^^^^^ @@ -142,13 +142,13 @@ LL | 1f32 as u32 as u16; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:59:5 + --> tests/ui/cast.rs:70:5 | LL | 1f32 as u32 as u16; | ^^^^^^^^^^^ error: casting `i32` to `i8` may truncate the value - --> tests/ui/cast.rs:64:22 + --> tests/ui/cast.rs:76:22 | LL | let _x: i8 = 1i32 as _; | ^^^^^^^^^ @@ -161,7 +161,7 @@ LL + let _x: i8 = 1i32.try_into(); | error: casting `f32` to `i32` may truncate the value - --> tests/ui/cast.rs:66:9 + --> tests/ui/cast.rs:79:9 | LL | 1f32 as i32; | ^^^^^^^^^^^ @@ -169,7 +169,7 @@ LL | 1f32 as i32; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f64` to `i32` may truncate the value - --> tests/ui/cast.rs:68:9 + --> tests/ui/cast.rs:82:9 | LL | 1f64 as i32; | ^^^^^^^^^^^ @@ -177,7 +177,7 @@ LL | 1f64 as i32; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f32` to `u8` may truncate the value - --> tests/ui/cast.rs:70:9 + --> tests/ui/cast.rs:85:9 | LL | 1f32 as u8; | ^^^^^^^^^^ @@ -185,13 +185,13 @@ LL | 1f32 as u8; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... error: casting `f32` to `u8` may lose the sign of the value - --> tests/ui/cast.rs:70:9 + --> tests/ui/cast.rs:85:9 | LL | 1f32 as u8; | ^^^^^^^^^^ error: casting `u8` to `i8` may wrap around the value - --> tests/ui/cast.rs:75:5 + --> tests/ui/cast.rs:90:5 | LL | 1u8 as i8; | ^^^^^^^^^ @@ -200,31 +200,31 @@ LL | 1u8 as i8; = help: to override `-D warnings` add `#[allow(clippy::cast_possible_wrap)]` error: casting `u16` to `i16` may wrap around the value - --> tests/ui/cast.rs:78:5 + --> tests/ui/cast.rs:93:5 | LL | 1u16 as i16; | ^^^^^^^^^^^ error: casting `u32` to `i32` may wrap around the value - --> tests/ui/cast.rs:80:5 + --> tests/ui/cast.rs:96:5 | LL | 1u32 as i32; | ^^^^^^^^^^^ error: casting `u64` to `i64` may wrap around the value - --> tests/ui/cast.rs:82:5 + --> tests/ui/cast.rs:99:5 | LL | 1u64 as i64; | ^^^^^^^^^^^ error: casting `usize` to `isize` may wrap around the value - --> tests/ui/cast.rs:84:5 + --> tests/ui/cast.rs:102:5 | LL | 1usize as isize; | ^^^^^^^^^^^^^^^ error: casting `usize` to `i8` may truncate the value - --> tests/ui/cast.rs:87:5 + --> tests/ui/cast.rs:106:5 | LL | 1usize as i8; | ^^^^^^^^^^^^ @@ -237,7 +237,7 @@ LL + i8::try_from(1usize); | error: casting `usize` to `i16` may truncate the value - --> tests/ui/cast.rs:90:5 + --> tests/ui/cast.rs:110:5 | LL | 1usize as i16; | ^^^^^^^^^^^^^ @@ -250,7 +250,7 @@ LL + i16::try_from(1usize); | error: casting `usize` to `i16` may wrap around the value on targets with 16-bit wide pointers - --> tests/ui/cast.rs:90:5 + --> tests/ui/cast.rs:110:5 | LL | 1usize as i16; | ^^^^^^^^^^^^^ @@ -259,7 +259,7 @@ LL | 1usize as i16; = note: for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types error: casting `usize` to `i32` may truncate the value on targets with 64-bit wide pointers - --> tests/ui/cast.rs:95:5 + --> tests/ui/cast.rs:115:5 | LL | 1usize as i32; | ^^^^^^^^^^^^^ @@ -272,19 +272,19 @@ LL + i32::try_from(1usize); | error: casting `usize` to `i32` may wrap around the value on targets with 32-bit wide pointers - --> tests/ui/cast.rs:95:5 + --> tests/ui/cast.rs:115:5 | LL | 1usize as i32; | ^^^^^^^^^^^^^ error: casting `usize` to `i64` may wrap around the value on targets with 64-bit wide pointers - --> tests/ui/cast.rs:99:5 + --> tests/ui/cast.rs:120:5 | LL | 1usize as i64; | ^^^^^^^^^^^^^ error: casting `u16` to `isize` may wrap around the value on targets with 16-bit wide pointers - --> tests/ui/cast.rs:104:5 + --> tests/ui/cast.rs:126:5 | LL | 1u16 as isize; | ^^^^^^^^^^^^^ @@ -293,13 +293,13 @@ LL | 1u16 as isize; = note: for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types error: casting `u32` to `isize` may wrap around the value on targets with 32-bit wide pointers - --> tests/ui/cast.rs:108:5 + --> tests/ui/cast.rs:130:5 | LL | 1u32 as isize; | ^^^^^^^^^^^^^ error: casting `u64` to `isize` may truncate the value on targets with 32-bit wide pointers - --> tests/ui/cast.rs:111:5 + --> tests/ui/cast.rs:134:5 | LL | 1u64 as isize; | ^^^^^^^^^^^^^ @@ -312,55 +312,55 @@ LL + isize::try_from(1u64); | error: casting `u64` to `isize` may wrap around the value on targets with 64-bit wide pointers - --> tests/ui/cast.rs:111:5 + --> tests/ui/cast.rs:134:5 | LL | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:116:5 + --> tests/ui/cast.rs:140:5 | LL | -1i32 as u32; | ^^^^^^^^^^^^ error: casting `isize` to `usize` may lose the sign of the value - --> tests/ui/cast.rs:119:5 + --> tests/ui/cast.rs:144:5 | LL | -1isize as usize; | ^^^^^^^^^^^^^^^^ error: casting `i8` to `u8` may lose the sign of the value - --> tests/ui/cast.rs:130:5 + --> tests/ui/cast.rs:156:5 | LL | (i8::MIN).abs() as u8; | ^^^^^^^^^^^^^^^^^^^^^ error: casting `i64` to `u64` may lose the sign of the value - --> tests/ui/cast.rs:134:5 + --> tests/ui/cast.rs:161:5 | LL | (-1i64).abs() as u64; | ^^^^^^^^^^^^^^^^^^^^ error: casting `isize` to `usize` may lose the sign of the value - --> tests/ui/cast.rs:135:5 + --> tests/ui/cast.rs:163:5 | LL | (-1isize).abs() as usize; | ^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i64` to `u64` may lose the sign of the value - --> tests/ui/cast.rs:142:5 + --> tests/ui/cast.rs:171:5 | LL | (unsafe { (-1i64).checked_abs().unwrap_unchecked() }) as u64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i64` to `u64` may lose the sign of the value - --> tests/ui/cast.rs:157:5 + --> tests/ui/cast.rs:187:5 | LL | (unsafe { (-1i64).checked_isqrt().unwrap_unchecked() }) as u64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i64` to `i8` may truncate the value - --> tests/ui/cast.rs:208:5 + --> tests/ui/cast.rs:239:5 | LL | (-99999999999i64).min(1) as i8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -373,7 +373,7 @@ LL + i8::try_from((-99999999999i64).min(1)); | error: casting `u64` to `u8` may truncate the value - --> tests/ui/cast.rs:222:5 + --> tests/ui/cast.rs:253:5 | LL | 999999u64.clamp(0, 256) as u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -386,7 +386,7 @@ LL + u8::try_from(999999u64.clamp(0, 256)); | error: casting `main::E2` to `u8` may truncate the value - --> tests/ui/cast.rs:245:21 + --> tests/ui/cast.rs:276:21 | LL | let _ = self as u8; | ^^^^^^^^^^ @@ -399,7 +399,7 @@ LL + let _ = u8::try_from(self); | error: casting `main::E2::B` to `u8` will truncate the value - --> tests/ui/cast.rs:247:21 + --> tests/ui/cast.rs:279:21 | LL | let _ = Self::B as u8; | ^^^^^^^^^^^^^ @@ -408,7 +408,7 @@ LL | let _ = Self::B as u8; = help: to override `-D warnings` add `#[allow(clippy::cast_enum_truncation)]` error: casting `main::E5` to `i8` may truncate the value - --> tests/ui/cast.rs:289:21 + --> tests/ui/cast.rs:321:21 | LL | let _ = self as i8; | ^^^^^^^^^^ @@ -421,13 +421,13 @@ LL + let _ = i8::try_from(self); | error: casting `main::E5::A` to `i8` will truncate the value - --> tests/ui/cast.rs:291:21 + --> tests/ui/cast.rs:324:21 | LL | let _ = Self::A as i8; | ^^^^^^^^^^^^^ error: casting `main::E6` to `i16` may truncate the value - --> tests/ui/cast.rs:308:21 + --> tests/ui/cast.rs:342:21 | LL | let _ = self as i16; | ^^^^^^^^^^^ @@ -440,7 +440,7 @@ LL + let _ = i16::try_from(self); | error: casting `main::E7` to `usize` may truncate the value on targets with 32-bit wide pointers - --> tests/ui/cast.rs:327:21 + --> tests/ui/cast.rs:362:21 | LL | let _ = self as usize; | ^^^^^^^^^^^^^ @@ -453,7 +453,7 @@ LL + let _ = usize::try_from(self); | error: casting `main::E10` to `u16` may truncate the value - --> tests/ui/cast.rs:374:21 + --> tests/ui/cast.rs:410:21 | LL | let _ = self as u16; | ^^^^^^^^^^^ @@ -466,7 +466,7 @@ LL + let _ = u16::try_from(self); | error: casting `u32` to `u8` may truncate the value - --> tests/ui/cast.rs:385:13 + --> tests/ui/cast.rs:422:13 | LL | let c = (q >> 16) as u8; | ^^^^^^^^^^^^^^^ @@ -479,7 +479,7 @@ LL + let c = u8::try_from(q >> 16); | error: casting `u32` to `u8` may truncate the value - --> tests/ui/cast.rs:389:13 + --> tests/ui/cast.rs:427:13 | LL | let c = (q / 1000) as u8; | ^^^^^^^^^^^^^^^^ @@ -492,85 +492,85 @@ LL + let c = u8::try_from(q / 1000); | error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:401:9 + --> tests/ui/cast.rs:440:9 | LL | (x * x) as u32; | ^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:406:32 + --> tests/ui/cast.rs:446:32 | LL | let _a = |x: i32| -> u32 { (x * x * x * x) as u32 }; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:408:5 + --> tests/ui/cast.rs:449:5 | LL | (2_i32).checked_pow(3).unwrap() as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:409:5 + --> tests/ui/cast.rs:451:5 | LL | (-2_i32).pow(3) as u32; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:414:5 + --> tests/ui/cast.rs:456:5 | LL | (-5_i32 % 2) as u32; | ^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:416:5 + --> tests/ui/cast.rs:459:5 | LL | (-5_i32 % -2) as u32; | ^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:419:5 + --> tests/ui/cast.rs:463:5 | LL | (-2_i32 >> 1) as u32; | ^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:423:5 + --> tests/ui/cast.rs:467:5 | LL | (x * x) as u32; | ^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:424:5 + --> tests/ui/cast.rs:469:5 | LL | (x * x * x) as u32; | ^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:428:5 + --> tests/ui/cast.rs:473:5 | LL | (y * y * y * y * -2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:430:5 + --> tests/ui/cast.rs:476:5 | LL | (y * y * y / y * 2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:431:5 + --> tests/ui/cast.rs:478:5 | LL | (y * y / y * 2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:433:5 + --> tests/ui/cast.rs:481:5 | LL | (y / y * y * -2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `/` - --> tests/ui/cast.rs:433:6 + --> tests/ui/cast.rs:481:6 | LL | (y / y * y * -2) as u16; | ^^^^^ @@ -578,97 +578,97 @@ LL | (y / y * y * -2) as u16; = note: `#[deny(clippy::eq_op)]` on by default error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:436:5 + --> tests/ui/cast.rs:485:5 | LL | (y + y + y + -2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:438:5 + --> tests/ui/cast.rs:488:5 | LL | (y + y + y + 2) as u16; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:442:5 + --> tests/ui/cast.rs:492:5 | LL | (z + -2) as u16; | ^^^^^^^^^^^^^^^ error: casting `i16` to `u16` may lose the sign of the value - --> tests/ui/cast.rs:444:5 + --> tests/ui/cast.rs:495:5 | LL | (z + z + 2) as u16; | ^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:447:9 + --> tests/ui/cast.rs:499:9 | LL | (a * a * b * b * c * c) as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:448:9 + --> tests/ui/cast.rs:501:9 | LL | (a * b * c) as u32; | ^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:450:9 + --> tests/ui/cast.rs:504:9 | LL | (a * -b * c) as u32; | ^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:452:9 + --> tests/ui/cast.rs:507:9 | LL | (a * b * c * c) as u32; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:453:9 + --> tests/ui/cast.rs:509:9 | LL | (a * -2) as u32; | ^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:455:9 + --> tests/ui/cast.rs:512:9 | LL | (a * b * c * -2) as u32; | ^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:457:9 + --> tests/ui/cast.rs:515:9 | LL | (a / b) as u32; | ^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:458:9 + --> tests/ui/cast.rs:517:9 | LL | (a / b * c) as u32; | ^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:460:9 + --> tests/ui/cast.rs:520:9 | LL | (a / b + b * c) as u32; | ^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:462:9 + --> tests/ui/cast.rs:523:9 | LL | a.saturating_pow(3) as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:464:9 + --> tests/ui/cast.rs:526:9 | LL | (a.abs() * b.pow(2) / c.abs()) as u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> tests/ui/cast.rs:472:21 + --> tests/ui/cast.rs:534:21 | LL | let _ = i32::MIN as u32; // cast_sign_loss | ^^^^^^^^^^^^^^^ @@ -679,7 +679,7 @@ LL | m!(); = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: casting `u32` to `u8` may truncate the value - --> tests/ui/cast.rs:473:21 + --> tests/ui/cast.rs:537:21 | LL | let _ = u32::MAX as u8; // cast_possible_truncation | ^^^^^^^^^^^^^^ @@ -696,7 +696,7 @@ LL + let _ = u8::try_from(u32::MAX); // cast_possible_truncation | error: casting `f64` to `f32` may truncate the value - --> tests/ui/cast.rs:474:21 + --> tests/ui/cast.rs:540:21 | LL | let _ = std::f64::consts::PI as f32; // cast_possible_truncation | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -708,7 +708,7 @@ LL | m!(); = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: casting `i64` to `usize` may truncate the value on targets with 32-bit wide pointers - --> tests/ui/cast.rs:483:5 + --> tests/ui/cast.rs:551:5 | LL | bar.unwrap().unwrap() as usize | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -721,13 +721,13 @@ LL + usize::try_from(bar.unwrap().unwrap()) | error: casting `i64` to `usize` may lose the sign of the value - --> tests/ui/cast.rs:483:5 + --> tests/ui/cast.rs:551:5 | LL | bar.unwrap().unwrap() as usize | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `u64` to `u8` may truncate the value - --> tests/ui/cast.rs:498:5 + --> tests/ui/cast.rs:568:5 | LL | (256 & 999999u64) as u8; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -740,7 +740,7 @@ LL + u8::try_from(256 & 999999u64); | error: casting `u64` to `u8` may truncate the value - --> tests/ui/cast.rs:500:5 + --> tests/ui/cast.rs:571:5 | LL | (255 % 999999u64) as u8; | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/cast_abs_to_unsigned.fixed b/tests/ui/cast_abs_to_unsigned.fixed index 6ca01b7cc367..b55c22f5ca83 100644 --- a/tests/ui/cast_abs_to_unsigned.fixed +++ b/tests/ui/cast_abs_to_unsigned.fixed @@ -4,30 +4,47 @@ fn main() { let x: i32 = -42; let y: u32 = x.unsigned_abs(); + //~^ cast_abs_to_unsigned println!("The absolute value of {} is {}", x, y); let a: i32 = -3; let _: usize = a.unsigned_abs() as usize; + //~^ cast_abs_to_unsigned let _: usize = a.unsigned_abs() as _; + //~^ cast_abs_to_unsigned let _ = a.unsigned_abs() as usize; + //~^ cast_abs_to_unsigned let a: i64 = -3; let _ = a.unsigned_abs() as usize; + //~^ cast_abs_to_unsigned let _ = a.unsigned_abs() as u8; + //~^ cast_abs_to_unsigned let _ = a.unsigned_abs() as u16; + //~^ cast_abs_to_unsigned let _ = a.unsigned_abs() as u32; + //~^ cast_abs_to_unsigned let _ = a.unsigned_abs(); + //~^ cast_abs_to_unsigned let _ = a.unsigned_abs() as u128; + //~^ cast_abs_to_unsigned let a: isize = -3; let _ = a.unsigned_abs(); + //~^ cast_abs_to_unsigned let _ = a.unsigned_abs() as u8; + //~^ cast_abs_to_unsigned let _ = a.unsigned_abs() as u16; + //~^ cast_abs_to_unsigned let _ = a.unsigned_abs() as u32; + //~^ cast_abs_to_unsigned let _ = a.unsigned_abs() as u64; + //~^ cast_abs_to_unsigned let _ = a.unsigned_abs() as u128; + //~^ cast_abs_to_unsigned let _ = (x as i64 - y as i64).unsigned_abs() as u32; + //~^ cast_abs_to_unsigned } #[clippy::msrv = "1.50"] @@ -40,4 +57,5 @@ fn msrv_1_50() { fn msrv_1_51() { let x: i32 = 10; assert_eq!(10u32, x.unsigned_abs()); + //~^ cast_abs_to_unsigned } diff --git a/tests/ui/cast_abs_to_unsigned.rs b/tests/ui/cast_abs_to_unsigned.rs index 190a77c10232..466aa6aeb1fb 100644 --- a/tests/ui/cast_abs_to_unsigned.rs +++ b/tests/ui/cast_abs_to_unsigned.rs @@ -4,30 +4,47 @@ fn main() { let x: i32 = -42; let y: u32 = x.abs() as u32; + //~^ cast_abs_to_unsigned println!("The absolute value of {} is {}", x, y); let a: i32 = -3; let _: usize = a.abs() as usize; + //~^ cast_abs_to_unsigned let _: usize = a.abs() as _; + //~^ cast_abs_to_unsigned let _ = a.abs() as usize; + //~^ cast_abs_to_unsigned let a: i64 = -3; let _ = a.abs() as usize; + //~^ cast_abs_to_unsigned let _ = a.abs() as u8; + //~^ cast_abs_to_unsigned let _ = a.abs() as u16; + //~^ cast_abs_to_unsigned let _ = a.abs() as u32; + //~^ cast_abs_to_unsigned let _ = a.abs() as u64; + //~^ cast_abs_to_unsigned let _ = a.abs() as u128; + //~^ cast_abs_to_unsigned let a: isize = -3; let _ = a.abs() as usize; + //~^ cast_abs_to_unsigned let _ = a.abs() as u8; + //~^ cast_abs_to_unsigned let _ = a.abs() as u16; + //~^ cast_abs_to_unsigned let _ = a.abs() as u32; + //~^ cast_abs_to_unsigned let _ = a.abs() as u64; + //~^ cast_abs_to_unsigned let _ = a.abs() as u128; + //~^ cast_abs_to_unsigned let _ = (x as i64 - y as i64).abs() as u32; + //~^ cast_abs_to_unsigned } #[clippy::msrv = "1.50"] @@ -40,4 +57,5 @@ fn msrv_1_50() { fn msrv_1_51() { let x: i32 = 10; assert_eq!(10u32, x.abs() as u32); + //~^ cast_abs_to_unsigned } diff --git a/tests/ui/cast_abs_to_unsigned.stderr b/tests/ui/cast_abs_to_unsigned.stderr index 96e5c1724a51..26220693969c 100644 --- a/tests/ui/cast_abs_to_unsigned.stderr +++ b/tests/ui/cast_abs_to_unsigned.stderr @@ -8,103 +8,103 @@ LL | let y: u32 = x.abs() as u32; = help: to override `-D warnings` add `#[allow(clippy::cast_abs_to_unsigned)]` error: casting the result of `i32::abs()` to usize - --> tests/ui/cast_abs_to_unsigned.rs:10:20 + --> tests/ui/cast_abs_to_unsigned.rs:11:20 | LL | let _: usize = a.abs() as usize; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i32::abs()` to usize - --> tests/ui/cast_abs_to_unsigned.rs:11:20 + --> tests/ui/cast_abs_to_unsigned.rs:13:20 | LL | let _: usize = a.abs() as _; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i32::abs()` to usize - --> tests/ui/cast_abs_to_unsigned.rs:12:13 - | -LL | let _ = a.abs() as usize; - | ^^^^^^^ help: replace with: `a.unsigned_abs()` - -error: casting the result of `i64::abs()` to usize --> tests/ui/cast_abs_to_unsigned.rs:15:13 | LL | let _ = a.abs() as usize; | ^^^^^^^ help: replace with: `a.unsigned_abs()` +error: casting the result of `i64::abs()` to usize + --> tests/ui/cast_abs_to_unsigned.rs:19:13 + | +LL | let _ = a.abs() as usize; + | ^^^^^^^ help: replace with: `a.unsigned_abs()` + error: casting the result of `i64::abs()` to u8 - --> tests/ui/cast_abs_to_unsigned.rs:16:13 + --> tests/ui/cast_abs_to_unsigned.rs:21:13 | LL | let _ = a.abs() as u8; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i64::abs()` to u16 - --> tests/ui/cast_abs_to_unsigned.rs:17:13 + --> tests/ui/cast_abs_to_unsigned.rs:23:13 | LL | let _ = a.abs() as u16; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i64::abs()` to u32 - --> tests/ui/cast_abs_to_unsigned.rs:18:13 + --> tests/ui/cast_abs_to_unsigned.rs:25:13 | LL | let _ = a.abs() as u32; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i64::abs()` to u64 - --> tests/ui/cast_abs_to_unsigned.rs:19:13 + --> tests/ui/cast_abs_to_unsigned.rs:27:13 | LL | let _ = a.abs() as u64; | ^^^^^^^^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i64::abs()` to u128 - --> tests/ui/cast_abs_to_unsigned.rs:20:13 + --> tests/ui/cast_abs_to_unsigned.rs:29:13 | LL | let _ = a.abs() as u128; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `isize::abs()` to usize - --> tests/ui/cast_abs_to_unsigned.rs:23:13 + --> tests/ui/cast_abs_to_unsigned.rs:33:13 | LL | let _ = a.abs() as usize; | ^^^^^^^^^^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `isize::abs()` to u8 - --> tests/ui/cast_abs_to_unsigned.rs:24:13 + --> tests/ui/cast_abs_to_unsigned.rs:35:13 | LL | let _ = a.abs() as u8; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `isize::abs()` to u16 - --> tests/ui/cast_abs_to_unsigned.rs:25:13 + --> tests/ui/cast_abs_to_unsigned.rs:37:13 | LL | let _ = a.abs() as u16; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `isize::abs()` to u32 - --> tests/ui/cast_abs_to_unsigned.rs:26:13 + --> tests/ui/cast_abs_to_unsigned.rs:39:13 | LL | let _ = a.abs() as u32; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `isize::abs()` to u64 - --> tests/ui/cast_abs_to_unsigned.rs:27:13 + --> tests/ui/cast_abs_to_unsigned.rs:41:13 | LL | let _ = a.abs() as u64; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `isize::abs()` to u128 - --> tests/ui/cast_abs_to_unsigned.rs:28:13 + --> tests/ui/cast_abs_to_unsigned.rs:43:13 | LL | let _ = a.abs() as u128; | ^^^^^^^ help: replace with: `a.unsigned_abs()` error: casting the result of `i64::abs()` to u32 - --> tests/ui/cast_abs_to_unsigned.rs:30:13 + --> tests/ui/cast_abs_to_unsigned.rs:46:13 | LL | let _ = (x as i64 - y as i64).abs() as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `(x as i64 - y as i64).unsigned_abs()` error: casting the result of `i32::abs()` to u32 - --> tests/ui/cast_abs_to_unsigned.rs:42:23 + --> tests/ui/cast_abs_to_unsigned.rs:59:23 | LL | assert_eq!(10u32, x.abs() as u32); | ^^^^^^^^^^^^^^ help: replace with: `x.unsigned_abs()` diff --git a/tests/ui/cast_alignment.rs b/tests/ui/cast_alignment.rs index 72f5d4268cc1..5773ffddb917 100644 --- a/tests/ui/cast_alignment.rs +++ b/tests/ui/cast_alignment.rs @@ -17,16 +17,17 @@ fn main() { // cast to more-strictly-aligned type (&1u8 as *const u8) as *const u16; - //~^ ERROR: casting from `*const u8` to a more-strictly-aligned pointer (`*const u16`) - //~| NOTE: `-D clippy::cast-ptr-alignment` implied by `-D warnings` + //~^ cast_ptr_alignment + (&mut 1u8 as *mut u8) as *mut u16; - //~^ ERROR: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) (1 + //~^ cast_ptr_alignment // cast to more-strictly-aligned type, but with the `pointer::cast` function. (&1u8 as *const u8).cast::(); - //~^ ERROR: casting from `*const u8` to a more-strictly-aligned pointer (`*const u16`) + //~^ cast_ptr_alignment + (&mut 1u8 as *mut u8).cast::(); - //~^ ERROR: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) (1 + //~^ cast_ptr_alignment /* These should be ok */ diff --git a/tests/ui/cast_alignment.stderr b/tests/ui/cast_alignment.stderr index b32624f958fc..6d9a81f0ecfd 100644 --- a/tests/ui/cast_alignment.stderr +++ b/tests/ui/cast_alignment.stderr @@ -20,7 +20,7 @@ LL | (&1u8 as *const u8).cast::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) (1 < 2 bytes) - --> tests/ui/cast_alignment.rs:28:5 + --> tests/ui/cast_alignment.rs:29:5 | LL | (&mut 1u8 as *mut u8).cast::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/cast_enum_constructor.rs b/tests/ui/cast_enum_constructor.rs index 3226f487b3af..eecf56f71a33 100644 --- a/tests/ui/cast_enum_constructor.rs +++ b/tests/ui/cast_enum_constructor.rs @@ -11,10 +11,11 @@ fn main() { } let _ = Foo::Y as usize; - //~^ ERROR: cast of an enum tuple constructor to an integer - //~| NOTE: `-D clippy::cast-enum-constructor` implied by `-D warnings` + //~^ cast_enum_constructor + let _ = Foo::Y as isize; - //~^ ERROR: cast of an enum tuple constructor to an integer + //~^ cast_enum_constructor + let _ = Foo::Y as fn(u32) -> Foo; let _ = Bar::X as usize; } diff --git a/tests/ui/cast_lossless_bool.fixed b/tests/ui/cast_lossless_bool.fixed index 51a38a60cf6b..21dc280a5864 100644 --- a/tests/ui/cast_lossless_bool.fixed +++ b/tests/ui/cast_lossless_bool.fixed @@ -6,23 +6,37 @@ type U8 = u8; fn main() { // Test clippy::cast_lossless with casts to integer types let _ = u8::from(true); + //~^ cast_lossless let _ = u16::from(true); + //~^ cast_lossless let _ = u32::from(true); + //~^ cast_lossless let _ = u64::from(true); + //~^ cast_lossless let _ = u128::from(true); + //~^ cast_lossless let _ = usize::from(true); + //~^ cast_lossless let _ = i8::from(true); + //~^ cast_lossless let _ = i16::from(true); + //~^ cast_lossless let _ = i32::from(true); + //~^ cast_lossless let _ = i64::from(true); + //~^ cast_lossless let _ = i128::from(true); + //~^ cast_lossless let _ = isize::from(true); + //~^ cast_lossless // Test with an expression wrapped in parens let _ = u16::from(true | false); + //~^ cast_lossless let _ = U8::from(true); + //~^ cast_lossless } // The lint would suggest using `u32::from(input)` here but the `XX::from` function is not const, @@ -51,4 +65,5 @@ fn msrv_1_27() { #[clippy::msrv = "1.28"] fn msrv_1_28() { let _ = u8::from(true); + //~^ cast_lossless } diff --git a/tests/ui/cast_lossless_bool.rs b/tests/ui/cast_lossless_bool.rs index cb307bd68e43..d03badd9a7bc 100644 --- a/tests/ui/cast_lossless_bool.rs +++ b/tests/ui/cast_lossless_bool.rs @@ -6,23 +6,37 @@ type U8 = u8; fn main() { // Test clippy::cast_lossless with casts to integer types let _ = true as u8; + //~^ cast_lossless let _ = true as u16; + //~^ cast_lossless let _ = true as u32; + //~^ cast_lossless let _ = true as u64; + //~^ cast_lossless let _ = true as u128; + //~^ cast_lossless let _ = true as usize; + //~^ cast_lossless let _ = true as i8; + //~^ cast_lossless let _ = true as i16; + //~^ cast_lossless let _ = true as i32; + //~^ cast_lossless let _ = true as i64; + //~^ cast_lossless let _ = true as i128; + //~^ cast_lossless let _ = true as isize; + //~^ cast_lossless // Test with an expression wrapped in parens let _ = (true | false) as u16; + //~^ cast_lossless let _ = true as U8; + //~^ cast_lossless } // The lint would suggest using `u32::from(input)` here but the `XX::from` function is not const, @@ -51,4 +65,5 @@ fn msrv_1_27() { #[clippy::msrv = "1.28"] fn msrv_1_28() { let _ = true as u8; + //~^ cast_lossless } diff --git a/tests/ui/cast_lossless_bool.stderr b/tests/ui/cast_lossless_bool.stderr index 689922717623..802eeaebbbdd 100644 --- a/tests/ui/cast_lossless_bool.stderr +++ b/tests/ui/cast_lossless_bool.stderr @@ -14,7 +14,7 @@ LL + let _ = u8::from(true); | error: casts from `bool` to `u16` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_bool.rs:9:13 + --> tests/ui/cast_lossless_bool.rs:10:13 | LL | let _ = true as u16; | ^^^^^^^^^^^ @@ -27,7 +27,7 @@ LL + let _ = u16::from(true); | error: casts from `bool` to `u32` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_bool.rs:10:13 + --> tests/ui/cast_lossless_bool.rs:12:13 | LL | let _ = true as u32; | ^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL + let _ = u32::from(true); | error: casts from `bool` to `u64` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_bool.rs:11:13 + --> tests/ui/cast_lossless_bool.rs:14:13 | LL | let _ = true as u64; | ^^^^^^^^^^^ @@ -53,7 +53,7 @@ LL + let _ = u64::from(true); | error: casts from `bool` to `u128` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_bool.rs:12:13 + --> tests/ui/cast_lossless_bool.rs:16:13 | LL | let _ = true as u128; | ^^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL + let _ = u128::from(true); | error: casts from `bool` to `usize` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_bool.rs:13:13 + --> tests/ui/cast_lossless_bool.rs:18:13 | LL | let _ = true as usize; | ^^^^^^^^^^^^^ @@ -79,7 +79,7 @@ LL + let _ = usize::from(true); | error: casts from `bool` to `i8` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_bool.rs:15:13 + --> tests/ui/cast_lossless_bool.rs:21:13 | LL | let _ = true as i8; | ^^^^^^^^^^ @@ -92,7 +92,7 @@ LL + let _ = i8::from(true); | error: casts from `bool` to `i16` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_bool.rs:16:13 + --> tests/ui/cast_lossless_bool.rs:23:13 | LL | let _ = true as i16; | ^^^^^^^^^^^ @@ -105,7 +105,7 @@ LL + let _ = i16::from(true); | error: casts from `bool` to `i32` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_bool.rs:17:13 + --> tests/ui/cast_lossless_bool.rs:25:13 | LL | let _ = true as i32; | ^^^^^^^^^^^ @@ -118,7 +118,7 @@ LL + let _ = i32::from(true); | error: casts from `bool` to `i64` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_bool.rs:18:13 + --> tests/ui/cast_lossless_bool.rs:27:13 | LL | let _ = true as i64; | ^^^^^^^^^^^ @@ -131,7 +131,7 @@ LL + let _ = i64::from(true); | error: casts from `bool` to `i128` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_bool.rs:19:13 + --> tests/ui/cast_lossless_bool.rs:29:13 | LL | let _ = true as i128; | ^^^^^^^^^^^^ @@ -144,7 +144,7 @@ LL + let _ = i128::from(true); | error: casts from `bool` to `isize` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_bool.rs:20:13 + --> tests/ui/cast_lossless_bool.rs:31:13 | LL | let _ = true as isize; | ^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL + let _ = isize::from(true); | error: casts from `bool` to `u16` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_bool.rs:23:13 + --> tests/ui/cast_lossless_bool.rs:35:13 | LL | let _ = (true | false) as u16; | ^^^^^^^^^^^^^^^^^^^^^ @@ -170,7 +170,7 @@ LL + let _ = u16::from(true | false); | error: casts from `bool` to `u8` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_bool.rs:25:13 + --> tests/ui/cast_lossless_bool.rs:38:13 | LL | let _ = true as U8; | ^^^^^^^^^^ @@ -183,7 +183,7 @@ LL + let _ = U8::from(true); | error: casts from `bool` to `u8` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_bool.rs:53:13 + --> tests/ui/cast_lossless_bool.rs:67:13 | LL | let _ = true as u8; | ^^^^^^^^^^ diff --git a/tests/ui/cast_lossless_float.fixed b/tests/ui/cast_lossless_float.fixed index 163432631e13..6ddd5f10a2ca 100644 --- a/tests/ui/cast_lossless_float.fixed +++ b/tests/ui/cast_lossless_float.fixed @@ -10,25 +10,38 @@ fn main() { // Test clippy::cast_lossless with casts to floating-point types let x0 = 1i8; let _ = f32::from(x0); + //~^ cast_lossless let _ = f64::from(x0); + //~^ cast_lossless let _ = F32::from(x0); + //~^ cast_lossless let _ = F64::from(x0); + //~^ cast_lossless let x1 = 1u8; let _ = f32::from(x1); + //~^ cast_lossless let _ = f64::from(x1); + //~^ cast_lossless let x2 = 1i16; let _ = f32::from(x2); + //~^ cast_lossless let _ = f64::from(x2); + //~^ cast_lossless let x3 = 1u16; let _ = f32::from(x3); + //~^ cast_lossless let _ = f64::from(x3); + //~^ cast_lossless let x4 = 1i32; let _ = f64::from(x4); + //~^ cast_lossless let x5 = 1u32; let _ = f64::from(x5); + //~^ cast_lossless // Test with casts from floating-point types let _ = f64::from(1.0f32); + //~^ cast_lossless } // The lint would suggest using `f64::from(input)` here but the `XX::from` function is not const, diff --git a/tests/ui/cast_lossless_float.rs b/tests/ui/cast_lossless_float.rs index afb2a3d890ee..fe5a90544538 100644 --- a/tests/ui/cast_lossless_float.rs +++ b/tests/ui/cast_lossless_float.rs @@ -10,25 +10,38 @@ fn main() { // Test clippy::cast_lossless with casts to floating-point types let x0 = 1i8; let _ = x0 as f32; + //~^ cast_lossless let _ = x0 as f64; + //~^ cast_lossless let _ = x0 as F32; + //~^ cast_lossless let _ = x0 as F64; + //~^ cast_lossless let x1 = 1u8; let _ = x1 as f32; + //~^ cast_lossless let _ = x1 as f64; + //~^ cast_lossless let x2 = 1i16; let _ = x2 as f32; + //~^ cast_lossless let _ = x2 as f64; + //~^ cast_lossless let x3 = 1u16; let _ = x3 as f32; + //~^ cast_lossless let _ = x3 as f64; + //~^ cast_lossless let x4 = 1i32; let _ = x4 as f64; + //~^ cast_lossless let x5 = 1u32; let _ = x5 as f64; + //~^ cast_lossless // Test with casts from floating-point types let _ = 1.0f32 as f64; + //~^ cast_lossless } // The lint would suggest using `f64::from(input)` here but the `XX::from` function is not const, diff --git a/tests/ui/cast_lossless_float.stderr b/tests/ui/cast_lossless_float.stderr index 3f405e3f402f..35ae38b1d36a 100644 --- a/tests/ui/cast_lossless_float.stderr +++ b/tests/ui/cast_lossless_float.stderr @@ -14,7 +14,7 @@ LL + let _ = f32::from(x0); | error: casts from `i8` to `f64` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_float.rs:13:13 + --> tests/ui/cast_lossless_float.rs:14:13 | LL | let _ = x0 as f64; | ^^^^^^^^^ @@ -27,7 +27,7 @@ LL + let _ = f64::from(x0); | error: casts from `i8` to `f32` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_float.rs:14:13 + --> tests/ui/cast_lossless_float.rs:16:13 | LL | let _ = x0 as F32; | ^^^^^^^^^ @@ -40,7 +40,7 @@ LL + let _ = F32::from(x0); | error: casts from `i8` to `f64` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_float.rs:15:13 + --> tests/ui/cast_lossless_float.rs:18:13 | LL | let _ = x0 as F64; | ^^^^^^^^^ @@ -53,7 +53,7 @@ LL + let _ = F64::from(x0); | error: casts from `u8` to `f32` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_float.rs:17:13 + --> tests/ui/cast_lossless_float.rs:21:13 | LL | let _ = x1 as f32; | ^^^^^^^^^ @@ -66,7 +66,7 @@ LL + let _ = f32::from(x1); | error: casts from `u8` to `f64` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_float.rs:18:13 + --> tests/ui/cast_lossless_float.rs:23:13 | LL | let _ = x1 as f64; | ^^^^^^^^^ @@ -79,7 +79,7 @@ LL + let _ = f64::from(x1); | error: casts from `i16` to `f32` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_float.rs:20:13 + --> tests/ui/cast_lossless_float.rs:26:13 | LL | let _ = x2 as f32; | ^^^^^^^^^ @@ -92,7 +92,7 @@ LL + let _ = f32::from(x2); | error: casts from `i16` to `f64` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_float.rs:21:13 + --> tests/ui/cast_lossless_float.rs:28:13 | LL | let _ = x2 as f64; | ^^^^^^^^^ @@ -105,7 +105,7 @@ LL + let _ = f64::from(x2); | error: casts from `u16` to `f32` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_float.rs:23:13 + --> tests/ui/cast_lossless_float.rs:31:13 | LL | let _ = x3 as f32; | ^^^^^^^^^ @@ -118,7 +118,7 @@ LL + let _ = f32::from(x3); | error: casts from `u16` to `f64` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_float.rs:24:13 + --> tests/ui/cast_lossless_float.rs:33:13 | LL | let _ = x3 as f64; | ^^^^^^^^^ @@ -131,7 +131,7 @@ LL + let _ = f64::from(x3); | error: casts from `i32` to `f64` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_float.rs:26:13 + --> tests/ui/cast_lossless_float.rs:36:13 | LL | let _ = x4 as f64; | ^^^^^^^^^ @@ -144,7 +144,7 @@ LL + let _ = f64::from(x4); | error: casts from `u32` to `f64` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_float.rs:28:13 + --> tests/ui/cast_lossless_float.rs:39:13 | LL | let _ = x5 as f64; | ^^^^^^^^^ @@ -157,7 +157,7 @@ LL + let _ = f64::from(x5); | error: casts from `f32` to `f64` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_float.rs:31:13 + --> tests/ui/cast_lossless_float.rs:43:13 | LL | let _ = 1.0f32 as f64; | ^^^^^^^^^^^^^ diff --git a/tests/ui/cast_lossless_integer.fixed b/tests/ui/cast_lossless_integer.fixed index cdb065678368..2af2dbd1282d 100644 --- a/tests/ui/cast_lossless_integer.fixed +++ b/tests/ui/cast_lossless_integer.fixed @@ -7,66 +7,88 @@ fn main() { // Test clippy::cast_lossless with casts to integer types u16::from(0u8); //~^ cast_lossless + i16::from(0u8); //~^ cast_lossless + u32::from(0u8); //~^ cast_lossless + i32::from(0u8); //~^ cast_lossless + u64::from(0u8); //~^ cast_lossless + i64::from(0u8); //~^ cast_lossless + u128::from(0u8); //~^ cast_lossless + i128::from(0u8); //~^ cast_lossless u32::from(0u16); //~^ cast_lossless + i32::from(0u16); //~^ cast_lossless + u64::from(0u16); //~^ cast_lossless + i64::from(0u16); //~^ cast_lossless + u128::from(0u16); //~^ cast_lossless + i128::from(0u16); //~^ cast_lossless u64::from(0u32); //~^ cast_lossless + i64::from(0u32); //~^ cast_lossless + u128::from(0u32); //~^ cast_lossless + i128::from(0u32); //~^ cast_lossless u128::from(0u64); //~^ cast_lossless + i128::from(0u64); //~^ cast_lossless i16::from(0i8); //~^ cast_lossless + i32::from(0i8); //~^ cast_lossless + i64::from(0i8); //~^ cast_lossless + i128::from(0i8); //~^ cast_lossless i32::from(0i16); //~^ cast_lossless + i64::from(0i16); //~^ cast_lossless + i128::from(0i16); //~^ cast_lossless i64::from(0i32); //~^ cast_lossless + i128::from(0i32); //~^ cast_lossless @@ -82,10 +104,13 @@ fn main() { let _: u16 = 0u8.into(); //~^ cast_lossless + let _: i16 = (-1i8).into(); //~^ cast_lossless + let _: u16 = (1u8 + 2).into(); //~^ cast_lossless + let _: u32 = (1i8 as u16).into(); //~^ cast_lossless } @@ -123,6 +148,7 @@ fn issue11458() { let x = 10_u128; let _ = i32::from(sign_cast!(x, u8, i8)); //~^ cast_lossless + let _ = i32::from(sign_cast!(x, u8, i8) + 1); //~^ cast_lossless } @@ -146,6 +172,7 @@ fn ty_from_macro() { } let _ = ::from(0u8); + //~^ cast_lossless } const IN_CONST: u64 = 0u8 as u64; diff --git a/tests/ui/cast_lossless_integer.rs b/tests/ui/cast_lossless_integer.rs index 1f510b1a3036..c65b725bb729 100644 --- a/tests/ui/cast_lossless_integer.rs +++ b/tests/ui/cast_lossless_integer.rs @@ -7,66 +7,88 @@ fn main() { // Test clippy::cast_lossless with casts to integer types 0u8 as u16; //~^ cast_lossless + 0u8 as i16; //~^ cast_lossless + 0u8 as u32; //~^ cast_lossless + 0u8 as i32; //~^ cast_lossless + 0u8 as u64; //~^ cast_lossless + 0u8 as i64; //~^ cast_lossless + 0u8 as u128; //~^ cast_lossless + 0u8 as i128; //~^ cast_lossless 0u16 as u32; //~^ cast_lossless + 0u16 as i32; //~^ cast_lossless + 0u16 as u64; //~^ cast_lossless + 0u16 as i64; //~^ cast_lossless + 0u16 as u128; //~^ cast_lossless + 0u16 as i128; //~^ cast_lossless 0u32 as u64; //~^ cast_lossless + 0u32 as i64; //~^ cast_lossless + 0u32 as u128; //~^ cast_lossless + 0u32 as i128; //~^ cast_lossless 0u64 as u128; //~^ cast_lossless + 0u64 as i128; //~^ cast_lossless 0i8 as i16; //~^ cast_lossless + 0i8 as i32; //~^ cast_lossless + 0i8 as i64; //~^ cast_lossless + 0i8 as i128; //~^ cast_lossless 0i16 as i32; //~^ cast_lossless + 0i16 as i64; //~^ cast_lossless + 0i16 as i128; //~^ cast_lossless 0i32 as i64; //~^ cast_lossless + 0i32 as i128; //~^ cast_lossless @@ -82,10 +104,13 @@ fn main() { let _: u16 = 0u8 as _; //~^ cast_lossless + let _: i16 = -1i8 as _; //~^ cast_lossless + let _: u16 = (1u8 + 2) as _; //~^ cast_lossless + let _: u32 = 1i8 as u16 as _; //~^ cast_lossless } @@ -123,6 +148,7 @@ fn issue11458() { let x = 10_u128; let _ = sign_cast!(x, u8, i8) as i32; //~^ cast_lossless + let _ = (sign_cast!(x, u8, i8) + 1) as i32; //~^ cast_lossless } @@ -146,6 +172,7 @@ fn ty_from_macro() { } let _ = 0u8 as ty!(); + //~^ cast_lossless } const IN_CONST: u64 = 0u8 as u64; diff --git a/tests/ui/cast_lossless_integer.stderr b/tests/ui/cast_lossless_integer.stderr index d2580913bb54..9852eca71279 100644 --- a/tests/ui/cast_lossless_integer.stderr +++ b/tests/ui/cast_lossless_integer.stderr @@ -14,7 +14,7 @@ LL + u16::from(0u8); | error: casts from `u8` to `i16` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:10:5 + --> tests/ui/cast_lossless_integer.rs:11:5 | LL | 0u8 as i16; | ^^^^^^^^^^ @@ -27,7 +27,7 @@ LL + i16::from(0u8); | error: casts from `u8` to `u32` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:12:5 + --> tests/ui/cast_lossless_integer.rs:14:5 | LL | 0u8 as u32; | ^^^^^^^^^^ @@ -40,7 +40,7 @@ LL + u32::from(0u8); | error: casts from `u8` to `i32` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:14:5 + --> tests/ui/cast_lossless_integer.rs:17:5 | LL | 0u8 as i32; | ^^^^^^^^^^ @@ -53,7 +53,7 @@ LL + i32::from(0u8); | error: casts from `u8` to `u64` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:16:5 + --> tests/ui/cast_lossless_integer.rs:20:5 | LL | 0u8 as u64; | ^^^^^^^^^^ @@ -66,7 +66,7 @@ LL + u64::from(0u8); | error: casts from `u8` to `i64` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:18:5 + --> tests/ui/cast_lossless_integer.rs:23:5 | LL | 0u8 as i64; | ^^^^^^^^^^ @@ -79,7 +79,7 @@ LL + i64::from(0u8); | error: casts from `u8` to `u128` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:20:5 + --> tests/ui/cast_lossless_integer.rs:26:5 | LL | 0u8 as u128; | ^^^^^^^^^^^ @@ -92,7 +92,7 @@ LL + u128::from(0u8); | error: casts from `u8` to `i128` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:22:5 + --> tests/ui/cast_lossless_integer.rs:29:5 | LL | 0u8 as i128; | ^^^^^^^^^^^ @@ -105,7 +105,7 @@ LL + i128::from(0u8); | error: casts from `u16` to `u32` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:25:5 + --> tests/ui/cast_lossless_integer.rs:32:5 | LL | 0u16 as u32; | ^^^^^^^^^^^ @@ -118,7 +118,7 @@ LL + u32::from(0u16); | error: casts from `u16` to `i32` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:27:5 + --> tests/ui/cast_lossless_integer.rs:35:5 | LL | 0u16 as i32; | ^^^^^^^^^^^ @@ -131,7 +131,7 @@ LL + i32::from(0u16); | error: casts from `u16` to `u64` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:29:5 + --> tests/ui/cast_lossless_integer.rs:38:5 | LL | 0u16 as u64; | ^^^^^^^^^^^ @@ -144,7 +144,7 @@ LL + u64::from(0u16); | error: casts from `u16` to `i64` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:31:5 + --> tests/ui/cast_lossless_integer.rs:41:5 | LL | 0u16 as i64; | ^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL + i64::from(0u16); | error: casts from `u16` to `u128` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:33:5 + --> tests/ui/cast_lossless_integer.rs:44:5 | LL | 0u16 as u128; | ^^^^^^^^^^^^ @@ -170,7 +170,7 @@ LL + u128::from(0u16); | error: casts from `u16` to `i128` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:35:5 + --> tests/ui/cast_lossless_integer.rs:47:5 | LL | 0u16 as i128; | ^^^^^^^^^^^^ @@ -183,7 +183,7 @@ LL + i128::from(0u16); | error: casts from `u32` to `u64` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:38:5 + --> tests/ui/cast_lossless_integer.rs:50:5 | LL | 0u32 as u64; | ^^^^^^^^^^^ @@ -196,7 +196,7 @@ LL + u64::from(0u32); | error: casts from `u32` to `i64` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:40:5 + --> tests/ui/cast_lossless_integer.rs:53:5 | LL | 0u32 as i64; | ^^^^^^^^^^^ @@ -209,7 +209,7 @@ LL + i64::from(0u32); | error: casts from `u32` to `u128` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:42:5 + --> tests/ui/cast_lossless_integer.rs:56:5 | LL | 0u32 as u128; | ^^^^^^^^^^^^ @@ -222,7 +222,7 @@ LL + u128::from(0u32); | error: casts from `u32` to `i128` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:44:5 + --> tests/ui/cast_lossless_integer.rs:59:5 | LL | 0u32 as i128; | ^^^^^^^^^^^^ @@ -235,7 +235,7 @@ LL + i128::from(0u32); | error: casts from `u64` to `u128` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:47:5 + --> tests/ui/cast_lossless_integer.rs:62:5 | LL | 0u64 as u128; | ^^^^^^^^^^^^ @@ -248,7 +248,7 @@ LL + u128::from(0u64); | error: casts from `u64` to `i128` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:49:5 + --> tests/ui/cast_lossless_integer.rs:65:5 | LL | 0u64 as i128; | ^^^^^^^^^^^^ @@ -261,7 +261,7 @@ LL + i128::from(0u64); | error: casts from `i8` to `i16` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:52:5 + --> tests/ui/cast_lossless_integer.rs:68:5 | LL | 0i8 as i16; | ^^^^^^^^^^ @@ -274,7 +274,7 @@ LL + i16::from(0i8); | error: casts from `i8` to `i32` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:54:5 + --> tests/ui/cast_lossless_integer.rs:71:5 | LL | 0i8 as i32; | ^^^^^^^^^^ @@ -287,7 +287,7 @@ LL + i32::from(0i8); | error: casts from `i8` to `i64` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:56:5 + --> tests/ui/cast_lossless_integer.rs:74:5 | LL | 0i8 as i64; | ^^^^^^^^^^ @@ -300,7 +300,7 @@ LL + i64::from(0i8); | error: casts from `i8` to `i128` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:58:5 + --> tests/ui/cast_lossless_integer.rs:77:5 | LL | 0i8 as i128; | ^^^^^^^^^^^ @@ -313,7 +313,7 @@ LL + i128::from(0i8); | error: casts from `i16` to `i32` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:61:5 + --> tests/ui/cast_lossless_integer.rs:80:5 | LL | 0i16 as i32; | ^^^^^^^^^^^ @@ -326,7 +326,7 @@ LL + i32::from(0i16); | error: casts from `i16` to `i64` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:63:5 + --> tests/ui/cast_lossless_integer.rs:83:5 | LL | 0i16 as i64; | ^^^^^^^^^^^ @@ -339,7 +339,7 @@ LL + i64::from(0i16); | error: casts from `i16` to `i128` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:65:5 + --> tests/ui/cast_lossless_integer.rs:86:5 | LL | 0i16 as i128; | ^^^^^^^^^^^^ @@ -352,7 +352,7 @@ LL + i128::from(0i16); | error: casts from `i32` to `i64` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:68:5 + --> tests/ui/cast_lossless_integer.rs:89:5 | LL | 0i32 as i64; | ^^^^^^^^^^^ @@ -365,7 +365,7 @@ LL + i64::from(0i32); | error: casts from `i32` to `i128` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:70:5 + --> tests/ui/cast_lossless_integer.rs:92:5 | LL | 0i32 as i128; | ^^^^^^^^^^^^ @@ -378,7 +378,7 @@ LL + i128::from(0i32); | error: casts from `i64` to `i128` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:73:5 + --> tests/ui/cast_lossless_integer.rs:95:5 | LL | 0i64 as i128; | ^^^^^^^^^^^^ @@ -391,7 +391,7 @@ LL + i128::from(0i64); | error: casts from `u8` to `u16` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:77:13 + --> tests/ui/cast_lossless_integer.rs:99:13 | LL | let _ = (1u8 + 1u8) as u16; | ^^^^^^^^^^^^^^^^^^ @@ -404,7 +404,7 @@ LL + let _ = u16::from(1u8 + 1u8); | error: casts from `i8` to `i64` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:80:13 + --> tests/ui/cast_lossless_integer.rs:102:13 | LL | let _ = 1i8 as I64Alias; | ^^^^^^^^^^^^^^^ @@ -417,7 +417,7 @@ LL + let _ = I64Alias::from(1i8); | error: casts from `u8` to `u16` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:83:18 + --> tests/ui/cast_lossless_integer.rs:105:18 | LL | let _: u16 = 0u8 as _; | ^^^^^^^^ @@ -430,7 +430,7 @@ LL + let _: u16 = 0u8.into(); | error: casts from `i8` to `i16` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:85:18 + --> tests/ui/cast_lossless_integer.rs:108:18 | LL | let _: i16 = -1i8 as _; | ^^^^^^^^^ @@ -443,7 +443,7 @@ LL + let _: i16 = (-1i8).into(); | error: casts from `u8` to `u16` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:87:18 + --> tests/ui/cast_lossless_integer.rs:111:18 | LL | let _: u16 = (1u8 + 2) as _; | ^^^^^^^^^^^^^^ @@ -456,7 +456,7 @@ LL + let _: u16 = (1u8 + 2).into(); | error: casts from `u16` to `u32` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:89:18 + --> tests/ui/cast_lossless_integer.rs:114:18 | LL | let _: u32 = 1i8 as u16 as _; | ^^^^^^^^^^^^^^^ @@ -469,7 +469,7 @@ LL + let _: u32 = (1i8 as u16).into(); | error: casts from `i8` to `i32` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:124:13 + --> tests/ui/cast_lossless_integer.rs:149:13 | LL | let _ = sign_cast!(x, u8, i8) as i32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -482,7 +482,7 @@ LL + let _ = i32::from(sign_cast!(x, u8, i8)); | error: casts from `i8` to `i32` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:126:13 + --> tests/ui/cast_lossless_integer.rs:152:13 | LL | let _ = (sign_cast!(x, u8, i8) + 1) as i32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -495,7 +495,7 @@ LL + let _ = i32::from(sign_cast!(x, u8, i8) + 1); | error: casts from `u8` to `u32` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:133:13 + --> tests/ui/cast_lossless_integer.rs:159:13 | LL | 1u8 as u32 | ^^^^^^^^^^ @@ -512,7 +512,7 @@ LL + u32::from(1u8) | error: casts from `u8` to `u32` can be expressed infallibly using `From` - --> tests/ui/cast_lossless_integer.rs:148:13 + --> tests/ui/cast_lossless_integer.rs:174:13 | LL | let _ = 0u8 as ty!(); | ^^^^^^^^^^^^ diff --git a/tests/ui/cast_nan_to_int.rs b/tests/ui/cast_nan_to_int.rs index aee38da9a159..72e61b3542e2 100644 --- a/tests/ui/cast_nan_to_int.rs +++ b/tests/ui/cast_nan_to_int.rs @@ -5,24 +5,22 @@ fn main() { let _ = (0.0_f32 / -0.0) as usize; - //~^ ERROR: casting a known NaN to usize - //~| NOTE: this always evaluates to 0 + //~^ cast_nan_to_int + let _ = (f64::INFINITY * -0.0) as usize; - //~^ ERROR: casting a known NaN to usize - //~| NOTE: this always evaluates to 0 + //~^ cast_nan_to_int + let _ = (0.0 * f32::INFINITY) as usize; - //~^ ERROR: casting a known NaN to usize - //~| NOTE: this always evaluates to 0 + //~^ cast_nan_to_int let _ = (f64::INFINITY + f64::NEG_INFINITY) as usize; - //~^ ERROR: casting a known NaN to usize - //~| NOTE: this always evaluates to 0 + //~^ cast_nan_to_int + let _ = (f32::INFINITY - f32::INFINITY) as usize; - //~^ ERROR: casting a known NaN to usize - //~| NOTE: this always evaluates to 0 + //~^ cast_nan_to_int + let _ = (f32::INFINITY / f32::NEG_INFINITY) as usize; - //~^ ERROR: casting a known NaN to usize - //~| NOTE: this always evaluates to 0 + //~^ cast_nan_to_int // those won't be linted: let _ = (1.0_f32 / 0.0) as usize; diff --git a/tests/ui/cast_nan_to_int.stderr b/tests/ui/cast_nan_to_int.stderr index 3aeb2d545251..15ca3876ea18 100644 --- a/tests/ui/cast_nan_to_int.stderr +++ b/tests/ui/cast_nan_to_int.stderr @@ -25,7 +25,7 @@ LL | let _ = (0.0 * f32::INFINITY) as usize; = note: this always evaluates to 0 error: casting a known NaN to usize - --> tests/ui/cast_nan_to_int.rs:17:13 + --> tests/ui/cast_nan_to_int.rs:16:13 | LL | let _ = (f64::INFINITY + f64::NEG_INFINITY) as usize; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | let _ = (f64::INFINITY + f64::NEG_INFINITY) as usize; = note: this always evaluates to 0 error: casting a known NaN to usize - --> tests/ui/cast_nan_to_int.rs:20:13 + --> tests/ui/cast_nan_to_int.rs:19:13 | LL | let _ = (f32::INFINITY - f32::INFINITY) as usize; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | let _ = (f32::INFINITY - f32::INFINITY) as usize; = note: this always evaluates to 0 error: casting a known NaN to usize - --> tests/ui/cast_nan_to_int.rs:23:13 + --> tests/ui/cast_nan_to_int.rs:22:13 | LL | let _ = (f32::INFINITY / f32::NEG_INFINITY) as usize; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/cast_raw_slice_pointer_cast.fixed b/tests/ui/cast_raw_slice_pointer_cast.fixed index e78bd66c3cb5..bddcb0ebf64e 100644 --- a/tests/ui/cast_raw_slice_pointer_cast.fixed +++ b/tests/ui/cast_raw_slice_pointer_cast.fixed @@ -6,18 +6,25 @@ fn main() { let ptr: *const u8 = vec.as_ptr(); let mptr = vec.as_mut_ptr(); let _: *const [u8] = unsafe { core::ptr::slice_from_raw_parts(ptr, 1) }; + //~^ cast_slice_from_raw_parts let _: *const [u8] = unsafe { core::ptr::slice_from_raw_parts_mut(mptr, 1) }; + //~^ cast_slice_from_raw_parts let _: *const [u8] = core::ptr::slice_from_raw_parts(ptr, 1); + //~^ cast_slice_from_raw_parts { use core::slice; let _: *const [u8] = core::ptr::slice_from_raw_parts(ptr, 1); + //~^ cast_slice_from_raw_parts use slice as one; let _: *const [u8] = core::ptr::slice_from_raw_parts(ptr, 1); + //~^ cast_slice_from_raw_parts } { use std::slice; let _: *const [u8] = core::ptr::slice_from_raw_parts(ptr, 1); + //~^ cast_slice_from_raw_parts use slice as one; let _: *const [u8] = core::ptr::slice_from_raw_parts(ptr, 1); + //~^ cast_slice_from_raw_parts } } diff --git a/tests/ui/cast_raw_slice_pointer_cast.rs b/tests/ui/cast_raw_slice_pointer_cast.rs index c3d8c7bee989..0a1eb276d5e9 100644 --- a/tests/ui/cast_raw_slice_pointer_cast.rs +++ b/tests/ui/cast_raw_slice_pointer_cast.rs @@ -6,18 +6,25 @@ fn main() { let ptr: *const u8 = vec.as_ptr(); let mptr = vec.as_mut_ptr(); let _: *const [u8] = unsafe { std::slice::from_raw_parts(ptr, 1) as *const [u8] }; + //~^ cast_slice_from_raw_parts let _: *const [u8] = unsafe { std::slice::from_raw_parts_mut(mptr, 1) as *mut [u8] }; + //~^ cast_slice_from_raw_parts let _: *const [u8] = unsafe { std::slice::from_raw_parts(ptr, 1) } as *const [u8]; + //~^ cast_slice_from_raw_parts { use core::slice; let _: *const [u8] = unsafe { slice::from_raw_parts(ptr, 1) } as *const [u8]; + //~^ cast_slice_from_raw_parts use slice as one; let _: *const [u8] = unsafe { one::from_raw_parts(ptr, 1) } as *const [u8]; + //~^ cast_slice_from_raw_parts } { use std::slice; let _: *const [u8] = unsafe { slice::from_raw_parts(ptr, 1) } as *const [u8]; + //~^ cast_slice_from_raw_parts use slice as one; let _: *const [u8] = unsafe { one::from_raw_parts(ptr, 1) } as *const [u8]; + //~^ cast_slice_from_raw_parts } } diff --git a/tests/ui/cast_raw_slice_pointer_cast.stderr b/tests/ui/cast_raw_slice_pointer_cast.stderr index 2aedd320a428..60794a988db7 100644 --- a/tests/ui/cast_raw_slice_pointer_cast.stderr +++ b/tests/ui/cast_raw_slice_pointer_cast.stderr @@ -8,37 +8,37 @@ LL | let _: *const [u8] = unsafe { std::slice::from_raw_parts(ptr, 1) as *co = help: to override `-D warnings` add `#[allow(clippy::cast_slice_from_raw_parts)]` error: casting the result of `from_raw_parts_mut` to *mut [u8] - --> tests/ui/cast_raw_slice_pointer_cast.rs:9:35 + --> tests/ui/cast_raw_slice_pointer_cast.rs:10:35 | LL | let _: *const [u8] = unsafe { std::slice::from_raw_parts_mut(mptr, 1) as *mut [u8] }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts_mut(mptr, 1)` error: casting the result of `from_raw_parts` to *const [u8] - --> tests/ui/cast_raw_slice_pointer_cast.rs:10:26 + --> tests/ui/cast_raw_slice_pointer_cast.rs:12:26 | LL | let _: *const [u8] = unsafe { std::slice::from_raw_parts(ptr, 1) } as *const [u8]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts(ptr, 1)` error: casting the result of `from_raw_parts` to *const [u8] - --> tests/ui/cast_raw_slice_pointer_cast.rs:13:30 + --> tests/ui/cast_raw_slice_pointer_cast.rs:16:30 | LL | let _: *const [u8] = unsafe { slice::from_raw_parts(ptr, 1) } as *const [u8]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts(ptr, 1)` error: casting the result of `from_raw_parts` to *const [u8] - --> tests/ui/cast_raw_slice_pointer_cast.rs:15:30 + --> tests/ui/cast_raw_slice_pointer_cast.rs:19:30 | LL | let _: *const [u8] = unsafe { one::from_raw_parts(ptr, 1) } as *const [u8]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts(ptr, 1)` error: casting the result of `from_raw_parts` to *const [u8] - --> tests/ui/cast_raw_slice_pointer_cast.rs:19:30 + --> tests/ui/cast_raw_slice_pointer_cast.rs:24:30 | LL | let _: *const [u8] = unsafe { slice::from_raw_parts(ptr, 1) } as *const [u8]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts(ptr, 1)` error: casting the result of `from_raw_parts` to *const [u8] - --> tests/ui/cast_raw_slice_pointer_cast.rs:21:30 + --> tests/ui/cast_raw_slice_pointer_cast.rs:27:30 | LL | let _: *const [u8] = unsafe { one::from_raw_parts(ptr, 1) } as *const [u8]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts(ptr, 1)` diff --git a/tests/ui/cast_size.32bit.stderr b/tests/ui/cast_size.32bit.stderr index 8ff3464676c3..cb1620e36a26 100644 --- a/tests/ui/cast_size.32bit.stderr +++ b/tests/ui/cast_size.32bit.stderr @@ -1,5 +1,5 @@ error: casting `isize` to `i8` may truncate the value - --> tests/ui/cast_size.rs:15:5 + --> tests/ui/cast_size.rs:17:5 | LL | 1isize as i8; | ^^^^^^^^^^^^ @@ -9,11 +9,12 @@ LL | 1isize as i8; = help: to override `-D warnings` add `#[allow(clippy::cast_possible_truncation)]` help: ... or use `try_from` and handle the error accordingly | -LL | i8::try_from(1isize); - | ~~~~~~~~~~~~~~~~~~~~ +LL - 1isize as i8; +LL + i8::try_from(1isize); + | error: casting `isize` to `f32` causes a loss of precision (`isize` is 32 or 64 bits wide, but `f32`'s mantissa is only 23 bits wide) - --> tests/ui/cast_size.rs:21:5 + --> tests/ui/cast_size.rs:24:5 | LL | x0 as f32; | ^^^^^^^^^ @@ -22,25 +23,25 @@ LL | x0 as f32; = help: to override `-D warnings` add `#[allow(clippy::cast_precision_loss)]` error: casting `usize` to `f32` causes a loss of precision (`usize` is 32 or 64 bits wide, but `f32`'s mantissa is only 23 bits wide) - --> tests/ui/cast_size.rs:22:5 + --> tests/ui/cast_size.rs:26:5 | LL | x1 as f32; | ^^^^^^^^^ error: casting `isize` to `f64` causes a loss of precision on targets with 64-bit wide pointers (`isize` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide) - --> tests/ui/cast_size.rs:23:5 + --> tests/ui/cast_size.rs:28:5 | LL | x0 as f64; | ^^^^^^^^^ error: casting `usize` to `f64` causes a loss of precision on targets with 64-bit wide pointers (`usize` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide) - --> tests/ui/cast_size.rs:24:5 + --> tests/ui/cast_size.rs:30:5 | LL | x1 as f64; | ^^^^^^^^^ error: casting `isize` to `i32` may truncate the value on targets with 64-bit wide pointers - --> tests/ui/cast_size.rs:28:5 + --> tests/ui/cast_size.rs:35:5 | LL | 1isize as i32; | ^^^^^^^^^^^^^ @@ -48,11 +49,12 @@ LL | 1isize as i32; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... help: ... or use `try_from` and handle the error accordingly | -LL | i32::try_from(1isize); - | ~~~~~~~~~~~~~~~~~~~~~ +LL - 1isize as i32; +LL + i32::try_from(1isize); + | error: casting `isize` to `u32` may truncate the value on targets with 64-bit wide pointers - --> tests/ui/cast_size.rs:29:5 + --> tests/ui/cast_size.rs:37:5 | LL | 1isize as u32; | ^^^^^^^^^^^^^ @@ -60,11 +62,12 @@ LL | 1isize as u32; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... help: ... or use `try_from` and handle the error accordingly | -LL | u32::try_from(1isize); - | ~~~~~~~~~~~~~~~~~~~~~ +LL - 1isize as u32; +LL + u32::try_from(1isize); + | error: casting `usize` to `u32` may truncate the value on targets with 64-bit wide pointers - --> tests/ui/cast_size.rs:30:5 + --> tests/ui/cast_size.rs:39:5 | LL | 1usize as u32; | ^^^^^^^^^^^^^ @@ -72,11 +75,12 @@ LL | 1usize as u32; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... help: ... or use `try_from` and handle the error accordingly | -LL | u32::try_from(1usize); - | ~~~~~~~~~~~~~~~~~~~~~ +LL - 1usize as u32; +LL + u32::try_from(1usize); + | error: casting `usize` to `i32` may truncate the value on targets with 64-bit wide pointers - --> tests/ui/cast_size.rs:31:5 + --> tests/ui/cast_size.rs:41:5 | LL | 1usize as i32; | ^^^^^^^^^^^^^ @@ -84,11 +88,12 @@ LL | 1usize as i32; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... help: ... or use `try_from` and handle the error accordingly | -LL | i32::try_from(1usize); - | ~~~~~~~~~~~~~~~~~~~~~ +LL - 1usize as i32; +LL + i32::try_from(1usize); + | error: casting `usize` to `i32` may wrap around the value on targets with 32-bit wide pointers - --> tests/ui/cast_size.rs:31:5 + --> tests/ui/cast_size.rs:41:5 | LL | 1usize as i32; | ^^^^^^^^^^^^^ @@ -97,7 +102,7 @@ LL | 1usize as i32; = help: to override `-D warnings` add `#[allow(clippy::cast_possible_wrap)]` error: casting `i64` to `isize` may truncate the value on targets with 32-bit wide pointers - --> tests/ui/cast_size.rs:32:5 + --> tests/ui/cast_size.rs:44:5 | LL | 1i64 as isize; | ^^^^^^^^^^^^^ @@ -105,11 +110,12 @@ LL | 1i64 as isize; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... help: ... or use `try_from` and handle the error accordingly | -LL | isize::try_from(1i64); - | ~~~~~~~~~~~~~~~~~~~~~ +LL - 1i64 as isize; +LL + isize::try_from(1i64); + | error: casting `i64` to `usize` may truncate the value on targets with 32-bit wide pointers - --> tests/ui/cast_size.rs:33:5 + --> tests/ui/cast_size.rs:46:5 | LL | 1i64 as usize; | ^^^^^^^^^^^^^ @@ -117,11 +123,12 @@ LL | 1i64 as usize; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... help: ... or use `try_from` and handle the error accordingly | -LL | usize::try_from(1i64); - | ~~~~~~~~~~~~~~~~~~~~~ +LL - 1i64 as usize; +LL + usize::try_from(1i64); + | error: casting `u64` to `isize` may truncate the value on targets with 32-bit wide pointers - --> tests/ui/cast_size.rs:34:5 + --> tests/ui/cast_size.rs:48:5 | LL | 1u64 as isize; | ^^^^^^^^^^^^^ @@ -129,17 +136,18 @@ LL | 1u64 as isize; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... help: ... or use `try_from` and handle the error accordingly | -LL | isize::try_from(1u64); - | ~~~~~~~~~~~~~~~~~~~~~ +LL - 1u64 as isize; +LL + isize::try_from(1u64); + | error: casting `u64` to `isize` may wrap around the value on targets with 64-bit wide pointers - --> tests/ui/cast_size.rs:34:5 + --> tests/ui/cast_size.rs:48:5 | LL | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting `u64` to `usize` may truncate the value on targets with 32-bit wide pointers - --> tests/ui/cast_size.rs:35:5 + --> tests/ui/cast_size.rs:51:5 | LL | 1u64 as usize; | ^^^^^^^^^^^^^ @@ -147,29 +155,30 @@ LL | 1u64 as usize; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... help: ... or use `try_from` and handle the error accordingly | -LL | usize::try_from(1u64); - | ~~~~~~~~~~~~~~~~~~~~~ +LL - 1u64 as usize; +LL + usize::try_from(1u64); + | error: casting `u32` to `isize` may wrap around the value on targets with 32-bit wide pointers - --> tests/ui/cast_size.rs:36:5 + --> tests/ui/cast_size.rs:53:5 | LL | 1u32 as isize; | ^^^^^^^^^^^^^ error: casting `i32` to `f32` causes a loss of precision (`i32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide) - --> tests/ui/cast_size.rs:43:5 + --> tests/ui/cast_size.rs:61:5 | LL | 999_999_999 as f32; | ^^^^^^^^^^^^^^^^^^ error: casting `usize` to `f64` causes a loss of precision on targets with 64-bit wide pointers (`usize` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide) - --> tests/ui/cast_size.rs:44:5 + --> tests/ui/cast_size.rs:63:5 | LL | 9_999_999_999_999_999usize as f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: literal out of range for `usize` - --> tests/ui/cast_size.rs:44:5 + --> tests/ui/cast_size.rs:63:5 | LL | 9_999_999_999_999_999usize as f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/cast_size.64bit.stderr b/tests/ui/cast_size.64bit.stderr index 6b9919f8a105..b6000a52abb3 100644 --- a/tests/ui/cast_size.64bit.stderr +++ b/tests/ui/cast_size.64bit.stderr @@ -1,5 +1,5 @@ error: casting `isize` to `i8` may truncate the value - --> tests/ui/cast_size.rs:15:5 + --> tests/ui/cast_size.rs:17:5 | LL | 1isize as i8; | ^^^^^^^^^^^^ @@ -14,7 +14,7 @@ LL + i8::try_from(1isize); | error: casting `isize` to `f32` causes a loss of precision (`isize` is 32 or 64 bits wide, but `f32`'s mantissa is only 23 bits wide) - --> tests/ui/cast_size.rs:21:5 + --> tests/ui/cast_size.rs:24:5 | LL | x0 as f32; | ^^^^^^^^^ @@ -23,25 +23,25 @@ LL | x0 as f32; = help: to override `-D warnings` add `#[allow(clippy::cast_precision_loss)]` error: casting `usize` to `f32` causes a loss of precision (`usize` is 32 or 64 bits wide, but `f32`'s mantissa is only 23 bits wide) - --> tests/ui/cast_size.rs:22:5 + --> tests/ui/cast_size.rs:26:5 | LL | x1 as f32; | ^^^^^^^^^ error: casting `isize` to `f64` causes a loss of precision on targets with 64-bit wide pointers (`isize` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide) - --> tests/ui/cast_size.rs:23:5 + --> tests/ui/cast_size.rs:28:5 | LL | x0 as f64; | ^^^^^^^^^ error: casting `usize` to `f64` causes a loss of precision on targets with 64-bit wide pointers (`usize` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide) - --> tests/ui/cast_size.rs:24:5 + --> tests/ui/cast_size.rs:30:5 | LL | x1 as f64; | ^^^^^^^^^ error: casting `isize` to `i32` may truncate the value on targets with 64-bit wide pointers - --> tests/ui/cast_size.rs:28:5 + --> tests/ui/cast_size.rs:35:5 | LL | 1isize as i32; | ^^^^^^^^^^^^^ @@ -54,7 +54,7 @@ LL + i32::try_from(1isize); | error: casting `isize` to `u32` may truncate the value on targets with 64-bit wide pointers - --> tests/ui/cast_size.rs:29:5 + --> tests/ui/cast_size.rs:37:5 | LL | 1isize as u32; | ^^^^^^^^^^^^^ @@ -67,7 +67,7 @@ LL + u32::try_from(1isize); | error: casting `usize` to `u32` may truncate the value on targets with 64-bit wide pointers - --> tests/ui/cast_size.rs:30:5 + --> tests/ui/cast_size.rs:39:5 | LL | 1usize as u32; | ^^^^^^^^^^^^^ @@ -80,7 +80,7 @@ LL + u32::try_from(1usize); | error: casting `usize` to `i32` may truncate the value on targets with 64-bit wide pointers - --> tests/ui/cast_size.rs:31:5 + --> tests/ui/cast_size.rs:41:5 | LL | 1usize as i32; | ^^^^^^^^^^^^^ @@ -93,7 +93,7 @@ LL + i32::try_from(1usize); | error: casting `usize` to `i32` may wrap around the value on targets with 32-bit wide pointers - --> tests/ui/cast_size.rs:31:5 + --> tests/ui/cast_size.rs:41:5 | LL | 1usize as i32; | ^^^^^^^^^^^^^ @@ -102,7 +102,7 @@ LL | 1usize as i32; = help: to override `-D warnings` add `#[allow(clippy::cast_possible_wrap)]` error: casting `i64` to `isize` may truncate the value on targets with 32-bit wide pointers - --> tests/ui/cast_size.rs:32:5 + --> tests/ui/cast_size.rs:44:5 | LL | 1i64 as isize; | ^^^^^^^^^^^^^ @@ -115,7 +115,7 @@ LL + isize::try_from(1i64); | error: casting `i64` to `usize` may truncate the value on targets with 32-bit wide pointers - --> tests/ui/cast_size.rs:33:5 + --> tests/ui/cast_size.rs:46:5 | LL | 1i64 as usize; | ^^^^^^^^^^^^^ @@ -128,7 +128,7 @@ LL + usize::try_from(1i64); | error: casting `u64` to `isize` may truncate the value on targets with 32-bit wide pointers - --> tests/ui/cast_size.rs:34:5 + --> tests/ui/cast_size.rs:48:5 | LL | 1u64 as isize; | ^^^^^^^^^^^^^ @@ -141,13 +141,13 @@ LL + isize::try_from(1u64); | error: casting `u64` to `isize` may wrap around the value on targets with 64-bit wide pointers - --> tests/ui/cast_size.rs:34:5 + --> tests/ui/cast_size.rs:48:5 | LL | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting `u64` to `usize` may truncate the value on targets with 32-bit wide pointers - --> tests/ui/cast_size.rs:35:5 + --> tests/ui/cast_size.rs:51:5 | LL | 1u64 as usize; | ^^^^^^^^^^^^^ @@ -160,19 +160,19 @@ LL + usize::try_from(1u64); | error: casting `u32` to `isize` may wrap around the value on targets with 32-bit wide pointers - --> tests/ui/cast_size.rs:36:5 + --> tests/ui/cast_size.rs:53:5 | LL | 1u32 as isize; | ^^^^^^^^^^^^^ error: casting `i32` to `f32` causes a loss of precision (`i32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide) - --> tests/ui/cast_size.rs:43:5 + --> tests/ui/cast_size.rs:61:5 | LL | 999_999_999 as f32; | ^^^^^^^^^^^^^^^^^^ error: casting `usize` to `f64` causes a loss of precision on targets with 64-bit wide pointers (`usize` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide) - --> tests/ui/cast_size.rs:44:5 + --> tests/ui/cast_size.rs:63:5 | LL | 9_999_999_999_999_999usize as f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/cast_size.rs b/tests/ui/cast_size.rs index d0ed8e57d7ae..e92401808867 100644 --- a/tests/ui/cast_size.rs +++ b/tests/ui/cast_size.rs @@ -1,4 +1,6 @@ -//@stderr-per-bitwidth +//@revisions: 32bit 64bit +//@[32bit]ignore-bitwidth: 64 +//@[64bit]ignore-bitwidth: 32 //@no-rustfix #![warn( @@ -13,27 +15,43 @@ fn main() { // Casting from *size 1isize as i8; + //~^ cast_possible_truncation let x0 = 1isize; let x1 = 1usize; // FIXME(f16_f128): enable f16 and f128 conversions once const eval supports them // x0 as f16; // x1 as f16; x0 as f32; + //~^ cast_precision_loss x1 as f32; + //~^ cast_precision_loss x0 as f64; + //~^ cast_precision_loss x1 as f64; + //~^ cast_precision_loss // x0 as f128; // x1 as f128; 1isize as i32; + //~^ cast_possible_truncation 1isize as u32; + //~^ cast_possible_truncation 1usize as u32; + //~^ cast_possible_truncation 1usize as i32; + //~^ cast_possible_truncation + //~| cast_possible_wrap 1i64 as isize; + //~^ cast_possible_truncation 1i64 as usize; + //~^ cast_possible_truncation 1u64 as isize; + //~^ cast_possible_truncation + //~| cast_possible_wrap 1u64 as usize; + //~^ cast_possible_truncation 1u32 as isize; + //~^ cast_possible_wrap 1u32 as usize; // Should not trigger any lint 1i32 as isize; // Neither should this 1i32 as usize; @@ -41,6 +59,9 @@ fn main() { // Big integer literal to float // 999_999 as f16; 999_999_999 as f32; + //~^ cast_precision_loss 9_999_999_999_999_999usize as f64; + //~^ cast_precision_loss + //~[32bit]^^ ERROR: literal out of range for `usize` // 999_999_999_999_999_999_999_999_999_999u128 as f128; } diff --git a/tests/ui/cast_slice_different_sizes.rs b/tests/ui/cast_slice_different_sizes.rs index d8101030a8a2..518ed77ab220 100644 --- a/tests/ui/cast_slice_different_sizes.rs +++ b/tests/ui/cast_slice_different_sizes.rs @@ -8,14 +8,14 @@ fn main() { // Because it's separate, it does not check the cast back to something of the same size let a = r_x as *const [i32]; let b = a as *const [u8]; - //~^ ERROR: casting between raw pointers to `[i32]` (element size 4) and `[u8]` (eleme - //~| NOTE: `#[deny(clippy::cast_slice_different_sizes)]` on by default + //~^ cast_slice_different_sizes + let c = b as *const [u32]; - //~^ ERROR: casting between raw pointers to `[u8]` (element size 1) and `[u32]` (eleme + //~^ cast_slice_different_sizes // loses data let loss = r_x as *const [i32] as *const [u8]; - //~^ ERROR: casting between raw pointers to `[i32]` (element size 4) and `[u8]` (eleme + //~^ cast_slice_different_sizes // Cast back to same size but different type loses no data, just type conversion // This is weird code but there's no reason for this lint specifically to fire *twice* on it @@ -23,9 +23,11 @@ fn main() { // Check casting through blocks is detected let loss_block_1 = { r_x as *const [i32] } as *const [u8]; - //~^ ERROR: casting between raw pointers to `[i32]` (element size 4) and `[u8]` (eleme + //~^ cast_slice_different_sizes + let loss_block_2 = { - //~^ ERROR: casting between raw pointers to `[i32]` (element size 4) and `[u8]` (eleme + //~^ cast_slice_different_sizes + let _ = (); r_x as *const [i32] } as *const [u8]; @@ -43,7 +45,8 @@ fn main() { // Check that the result of a long chain of casts is detected let long_chain_loss = r_x as *const [i32] as *const [u32] as *const [u16] as *const [i8] as *const [u8]; - //~^ ERROR: casting between raw pointers to `[i32]` (element size 4) and `[u8]` (eleme + //~^ cast_slice_different_sizes + let long_chain_restore = r_x as *const [i32] as *const [u32] as *const [u16] as *const [i8] as *const [u8] as *const [u32]; } @@ -59,40 +62,47 @@ fn foo2(x: *mut [u8]) -> *mut [u8] { // Test that casts as part of function returns work fn bar(x: *mut [u16]) -> *mut [u8] { - //~^ ERROR: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (element s + //~^ cast_slice_different_sizes + x as *mut [u8] } fn uwu(x: *mut [u16]) -> *mut [u8] { - //~^ ERROR: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (element s + //~^ cast_slice_different_sizes + x as *mut _ } fn bar2(x: *mut [u16]) -> *mut [u8] { - //~^ ERROR: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (element s + //~^ cast_slice_different_sizes + x as _ } // constify fn bar3(x: *mut [u16]) -> *const [u8] { - //~^ ERROR: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (element s + //~^ cast_slice_different_sizes + x as _ } // unconstify fn bar4(x: *const [u16]) -> *mut [u8] { - //~^ ERROR: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (element s + //~^ cast_slice_different_sizes + x as _ } // function returns plus blocks fn blocks(x: *mut [u16]) -> *mut [u8] { - //~^ ERROR: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (element s + //~^ cast_slice_different_sizes + ({ x }) as _ } fn more_blocks(x: *mut [u16]) -> *mut [u8] { - //~^ ERROR: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (element s + //~^ cast_slice_different_sizes + { ({ x }) as _ } - //~^ ERROR: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (eleme + //~^ cast_slice_different_sizes } diff --git a/tests/ui/cast_slice_different_sizes.stderr b/tests/ui/cast_slice_different_sizes.stderr index 625de4a8359b..307d37ac2ea8 100644 --- a/tests/ui/cast_slice_different_sizes.stderr +++ b/tests/ui/cast_slice_different_sizes.stderr @@ -25,11 +25,12 @@ LL | let loss_block_1 = { r_x as *const [i32] } as *const [u8]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with `ptr::slice_from_raw_parts`: `core::ptr::slice_from_raw_parts({ r_x as *const [i32] } as *const u8, ..)` error: casting between raw pointers to `[i32]` (element size 4) and `[u8]` (element size 1) does not adjust the count - --> tests/ui/cast_slice_different_sizes.rs:27:24 + --> tests/ui/cast_slice_different_sizes.rs:28:24 | LL | let loss_block_2 = { | ________________________^ LL | | +LL | | LL | | let _ = (); LL | | r_x as *const [i32] LL | | } as *const [u8]; @@ -39,90 +40,98 @@ help: replace with `ptr::slice_from_raw_parts` | LL ~ let loss_block_2 = core::ptr::slice_from_raw_parts({ LL + +LL + LL + let _ = (); LL + r_x as *const [i32] LL ~ } as *const u8, ..); | error: casting between raw pointers to `[i32]` (element size 4) and `[u8]` (element size 1) does not adjust the count - --> tests/ui/cast_slice_different_sizes.rs:45:27 + --> tests/ui/cast_slice_different_sizes.rs:47:27 | LL | let long_chain_loss = r_x as *const [i32] as *const [u32] as *const [u16] as *const [i8] as *const [u8]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with `ptr::slice_from_raw_parts`: `core::ptr::slice_from_raw_parts(r_x as *const [i32] as *const u8, ..)` error: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (element size 1) does not adjust the count - --> tests/ui/cast_slice_different_sizes.rs:61:36 + --> tests/ui/cast_slice_different_sizes.rs:64:36 | LL | fn bar(x: *mut [u16]) -> *mut [u8] { | ____________________________________^ LL | | +LL | | LL | | x as *mut [u8] LL | | } | |_^ help: replace with `ptr::slice_from_raw_parts_mut`: `core::ptr::slice_from_raw_parts_mut(x as *mut u8, ..)` error: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (element size 1) does not adjust the count - --> tests/ui/cast_slice_different_sizes.rs:66:36 + --> tests/ui/cast_slice_different_sizes.rs:70:36 | LL | fn uwu(x: *mut [u16]) -> *mut [u8] { | ____________________________________^ LL | | +LL | | LL | | x as *mut _ LL | | } | |_^ help: replace with `ptr::slice_from_raw_parts_mut`: `core::ptr::slice_from_raw_parts_mut(x as *mut u8, ..)` error: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (element size 1) does not adjust the count - --> tests/ui/cast_slice_different_sizes.rs:71:37 + --> tests/ui/cast_slice_different_sizes.rs:76:37 | LL | fn bar2(x: *mut [u16]) -> *mut [u8] { | _____________________________________^ LL | | +LL | | LL | | x as _ LL | | } | |_^ help: replace with `ptr::slice_from_raw_parts_mut`: `core::ptr::slice_from_raw_parts_mut(x as *mut u8, ..)` error: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (element size 1) does not adjust the count - --> tests/ui/cast_slice_different_sizes.rs:77:39 + --> tests/ui/cast_slice_different_sizes.rs:83:39 | LL | fn bar3(x: *mut [u16]) -> *const [u8] { | _______________________________________^ LL | | +LL | | LL | | x as _ LL | | } | |_^ help: replace with `ptr::slice_from_raw_parts`: `core::ptr::slice_from_raw_parts(x as *const u8, ..)` error: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (element size 1) does not adjust the count - --> tests/ui/cast_slice_different_sizes.rs:83:39 + --> tests/ui/cast_slice_different_sizes.rs:90:39 | LL | fn bar4(x: *const [u16]) -> *mut [u8] { | _______________________________________^ LL | | +LL | | LL | | x as _ LL | | } | |_^ help: replace with `ptr::slice_from_raw_parts_mut`: `core::ptr::slice_from_raw_parts_mut(x as *mut u8, ..)` error: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (element size 1) does not adjust the count - --> tests/ui/cast_slice_different_sizes.rs:89:39 + --> tests/ui/cast_slice_different_sizes.rs:97:39 | LL | fn blocks(x: *mut [u16]) -> *mut [u8] { | _______________________________________^ LL | | +LL | | LL | | ({ x }) as _ LL | | } | |_^ help: replace with `ptr::slice_from_raw_parts_mut`: `core::ptr::slice_from_raw_parts_mut(({ x }) as *mut u8, ..)` error: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (element size 1) does not adjust the count - --> tests/ui/cast_slice_different_sizes.rs:94:44 + --> tests/ui/cast_slice_different_sizes.rs:103:44 | LL | fn more_blocks(x: *mut [u16]) -> *mut [u8] { | ____________________________________________^ LL | | +LL | | LL | | { ({ x }) as _ } LL | | LL | | } | |_^ help: replace with `ptr::slice_from_raw_parts_mut`: `core::ptr::slice_from_raw_parts_mut(({ x }) as *mut u8, ..)` error: casting between raw pointers to `[u16]` (element size 2) and `[u8]` (element size 1) does not adjust the count - --> tests/ui/cast_slice_different_sizes.rs:96:5 + --> tests/ui/cast_slice_different_sizes.rs:106:5 | LL | { ({ x }) as _ } | ^^^^^^^^^^^^^^^^ help: replace with `ptr::slice_from_raw_parts_mut`: `core::ptr::slice_from_raw_parts_mut(({ x }) as *mut u8, ..)` diff --git a/tests/ui/cfg_attr_cargo_clippy.fixed b/tests/ui/cfg_attr_cargo_clippy.fixed index 89815ffe9cbc..f55920db5503 100644 --- a/tests/ui/cfg_attr_cargo_clippy.fixed +++ b/tests/ui/cfg_attr_cargo_clippy.fixed @@ -1,13 +1,20 @@ #![warn(clippy::deprecated_clippy_cfg_attr)] #![allow(clippy::non_minimal_cfg)] -#![cfg_attr(clippy, doc = "a")] //~ ERROR: `feature = "cargo-clippy"` was +#![cfg_attr(clippy, doc = "a")] +//~^ deprecated_clippy_cfg_attr -#[cfg_attr(clippy, derive(Debug))] //~ ERROR: `feature = "cargo-clippy"` was -#[cfg_attr(not(clippy), derive(Debug))] //~ ERROR: `feature = "cargo-clippy"` was -#[cfg(clippy)] //~ ERROR: `feature = "cargo-clippy"` was -#[cfg(not(clippy))] //~ ERROR: `feature = "cargo-clippy"` was -#[cfg(any(clippy))] //~ ERROR: `feature = "cargo-clippy"` was -#[cfg(all(clippy))] //~ ERROR: `feature = "cargo-clippy"` was +#[cfg_attr(clippy, derive(Debug))] +//~^ deprecated_clippy_cfg_attr +#[cfg_attr(not(clippy), derive(Debug))] +//~^ deprecated_clippy_cfg_attr +#[cfg(clippy)] +//~^ deprecated_clippy_cfg_attr +#[cfg(not(clippy))] +//~^ deprecated_clippy_cfg_attr +#[cfg(any(clippy))] +//~^ deprecated_clippy_cfg_attr +#[cfg(all(clippy))] +//~^ deprecated_clippy_cfg_attr pub struct Bar; fn main() {} diff --git a/tests/ui/cfg_attr_cargo_clippy.rs b/tests/ui/cfg_attr_cargo_clippy.rs index 745f8957641e..faf36d98f2b3 100644 --- a/tests/ui/cfg_attr_cargo_clippy.rs +++ b/tests/ui/cfg_attr_cargo_clippy.rs @@ -1,13 +1,20 @@ #![warn(clippy::deprecated_clippy_cfg_attr)] #![allow(clippy::non_minimal_cfg)] -#![cfg_attr(feature = "cargo-clippy", doc = "a")] //~ ERROR: `feature = "cargo-clippy"` was +#![cfg_attr(feature = "cargo-clippy", doc = "a")] +//~^ deprecated_clippy_cfg_attr -#[cfg_attr(feature = "cargo-clippy", derive(Debug))] //~ ERROR: `feature = "cargo-clippy"` was -#[cfg_attr(not(feature = "cargo-clippy"), derive(Debug))] //~ ERROR: `feature = "cargo-clippy"` was -#[cfg(feature = "cargo-clippy")] //~ ERROR: `feature = "cargo-clippy"` was -#[cfg(not(feature = "cargo-clippy"))] //~ ERROR: `feature = "cargo-clippy"` was -#[cfg(any(feature = "cargo-clippy"))] //~ ERROR: `feature = "cargo-clippy"` was -#[cfg(all(feature = "cargo-clippy"))] //~ ERROR: `feature = "cargo-clippy"` was +#[cfg_attr(feature = "cargo-clippy", derive(Debug))] +//~^ deprecated_clippy_cfg_attr +#[cfg_attr(not(feature = "cargo-clippy"), derive(Debug))] +//~^ deprecated_clippy_cfg_attr +#[cfg(feature = "cargo-clippy")] +//~^ deprecated_clippy_cfg_attr +#[cfg(not(feature = "cargo-clippy"))] +//~^ deprecated_clippy_cfg_attr +#[cfg(any(feature = "cargo-clippy"))] +//~^ deprecated_clippy_cfg_attr +#[cfg(all(feature = "cargo-clippy"))] +//~^ deprecated_clippy_cfg_attr pub struct Bar; fn main() {} diff --git a/tests/ui/cfg_attr_cargo_clippy.stderr b/tests/ui/cfg_attr_cargo_clippy.stderr index 0a358f1a6847..4f5c39b78415 100644 --- a/tests/ui/cfg_attr_cargo_clippy.stderr +++ b/tests/ui/cfg_attr_cargo_clippy.stderr @@ -8,37 +8,37 @@ LL | #![cfg_attr(feature = "cargo-clippy", doc = "a")] = help: to override `-D warnings` add `#[allow(clippy::deprecated_clippy_cfg_attr)]` error: `feature = "cargo-clippy"` was replaced by `clippy` - --> tests/ui/cfg_attr_cargo_clippy.rs:5:12 + --> tests/ui/cfg_attr_cargo_clippy.rs:6:12 | LL | #[cfg_attr(feature = "cargo-clippy", derive(Debug))] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `clippy` error: `feature = "cargo-clippy"` was replaced by `clippy` - --> tests/ui/cfg_attr_cargo_clippy.rs:6:16 + --> tests/ui/cfg_attr_cargo_clippy.rs:8:16 | LL | #[cfg_attr(not(feature = "cargo-clippy"), derive(Debug))] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `clippy` error: `feature = "cargo-clippy"` was replaced by `clippy` - --> tests/ui/cfg_attr_cargo_clippy.rs:7:7 + --> tests/ui/cfg_attr_cargo_clippy.rs:10:7 | LL | #[cfg(feature = "cargo-clippy")] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `clippy` error: `feature = "cargo-clippy"` was replaced by `clippy` - --> tests/ui/cfg_attr_cargo_clippy.rs:8:11 + --> tests/ui/cfg_attr_cargo_clippy.rs:12:11 | LL | #[cfg(not(feature = "cargo-clippy"))] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `clippy` error: `feature = "cargo-clippy"` was replaced by `clippy` - --> tests/ui/cfg_attr_cargo_clippy.rs:9:11 + --> tests/ui/cfg_attr_cargo_clippy.rs:14:11 | LL | #[cfg(any(feature = "cargo-clippy"))] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `clippy` error: `feature = "cargo-clippy"` was replaced by `clippy` - --> tests/ui/cfg_attr_cargo_clippy.rs:10:11 + --> tests/ui/cfg_attr_cargo_clippy.rs:16:11 | LL | #[cfg(all(feature = "cargo-clippy"))] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `clippy` diff --git a/tests/ui/cfg_attr_rustfmt.fixed b/tests/ui/cfg_attr_rustfmt.fixed index 05d5b3d10eaf..401476a9c1fe 100644 --- a/tests/ui/cfg_attr_rustfmt.fixed +++ b/tests/ui/cfg_attr_rustfmt.fixed @@ -16,10 +16,12 @@ fn foo( fn skip_on_statements() { #[rustfmt::skip] + //~^ deprecated_cfg_attr 5+3; } #[rustfmt::skip] +//~^ deprecated_cfg_attr fn main() { foo::f(); } @@ -39,5 +41,6 @@ fn msrv_1_29() { #[clippy::msrv = "1.30"] fn msrv_1_30() { #[rustfmt::skip] + //~^ deprecated_cfg_attr 1+30; } diff --git a/tests/ui/cfg_attr_rustfmt.rs b/tests/ui/cfg_attr_rustfmt.rs index bc29e20210e8..3cf368129fd8 100644 --- a/tests/ui/cfg_attr_rustfmt.rs +++ b/tests/ui/cfg_attr_rustfmt.rs @@ -16,10 +16,12 @@ fn foo( fn skip_on_statements() { #[cfg_attr(rustfmt, rustfmt::skip)] + //~^ deprecated_cfg_attr 5+3; } #[cfg_attr(rustfmt, rustfmt_skip)] +//~^ deprecated_cfg_attr fn main() { foo::f(); } @@ -39,5 +41,6 @@ fn msrv_1_29() { #[clippy::msrv = "1.30"] fn msrv_1_30() { #[cfg_attr(rustfmt, rustfmt::skip)] + //~^ deprecated_cfg_attr 1+30; } diff --git a/tests/ui/cfg_attr_rustfmt.stderr b/tests/ui/cfg_attr_rustfmt.stderr index 24b6ed1b0458..d7825f854be5 100644 --- a/tests/ui/cfg_attr_rustfmt.stderr +++ b/tests/ui/cfg_attr_rustfmt.stderr @@ -8,13 +8,13 @@ LL | #[cfg_attr(rustfmt, rustfmt::skip)] = help: to override `-D warnings` add `#[allow(clippy::deprecated_cfg_attr)]` error: `cfg_attr` is deprecated for rustfmt and got replaced by tool attributes - --> tests/ui/cfg_attr_rustfmt.rs:22:1 + --> tests/ui/cfg_attr_rustfmt.rs:23:1 | LL | #[cfg_attr(rustfmt, rustfmt_skip)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#[rustfmt::skip]` error: `cfg_attr` is deprecated for rustfmt and got replaced by tool attributes - --> tests/ui/cfg_attr_rustfmt.rs:41:5 + --> tests/ui/cfg_attr_rustfmt.rs:43:5 | LL | #[cfg_attr(rustfmt, rustfmt::skip)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#[rustfmt::skip]` diff --git a/tests/ui/cfg_not_test.rs b/tests/ui/cfg_not_test.rs index da3e29d28966..d93e16f3b185 100644 --- a/tests/ui/cfg_not_test.rs +++ b/tests/ui/cfg_not_test.rs @@ -6,10 +6,12 @@ fn important_check() {} fn main() { // Statement #[cfg(not(test))] + //~^ cfg_not_test let answer = 42; // Expression #[cfg(not(test))] + //~^ cfg_not_test important_check(); // Make sure only not(test) are checked, not other attributes @@ -22,10 +24,13 @@ struct CfgNotTest; // Deeply nested `not(test)` #[cfg(not(test))] +//~^ cfg_not_test fn foo() {} #[cfg(all(debug_assertions, not(test)))] +//~^ cfg_not_test fn bar() {} #[cfg(not(any(not(debug_assertions), test)))] +//~^ cfg_not_test fn baz() {} #[cfg(test)] diff --git a/tests/ui/cfg_not_test.stderr b/tests/ui/cfg_not_test.stderr index c1bf626887af..e452ef2b5ab6 100644 --- a/tests/ui/cfg_not_test.stderr +++ b/tests/ui/cfg_not_test.stderr @@ -10,7 +10,7 @@ LL | #[cfg(not(test))] = help: to override `-D warnings` add `#[allow(clippy::cfg_not_test)]` error: code is excluded from test builds - --> tests/ui/cfg_not_test.rs:12:5 + --> tests/ui/cfg_not_test.rs:13:5 | LL | #[cfg(not(test))] | ^^^^^^^^^^^^^^^^^ @@ -18,7 +18,7 @@ LL | #[cfg(not(test))] = help: consider not excluding any code from test builds error: code is excluded from test builds - --> tests/ui/cfg_not_test.rs:24:1 + --> tests/ui/cfg_not_test.rs:26:1 | LL | #[cfg(not(test))] | ^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | #[cfg(not(test))] = help: consider not excluding any code from test builds error: code is excluded from test builds - --> tests/ui/cfg_not_test.rs:26:1 + --> tests/ui/cfg_not_test.rs:29:1 | LL | #[cfg(all(debug_assertions, not(test)))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,7 +34,7 @@ LL | #[cfg(all(debug_assertions, not(test)))] = help: consider not excluding any code from test builds error: code is excluded from test builds - --> tests/ui/cfg_not_test.rs:28:1 + --> tests/ui/cfg_not_test.rs:32:1 | LL | #[cfg(not(any(not(debug_assertions), test)))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/char_lit_as_u8.rs b/tests/ui/char_lit_as_u8.rs index 7bb3daf0f1e7..c8774c7f3091 100644 --- a/tests/ui/char_lit_as_u8.rs +++ b/tests/ui/char_lit_as_u8.rs @@ -3,6 +3,5 @@ fn main() { // no suggestion, since a byte literal won't work. let _ = '❤' as u8; - //~^ ERROR: casting a character literal to `u8` truncates - //~| NOTE: `char` is four bytes wide, but `u8` is a single byte + //~^ char_lit_as_u8 } diff --git a/tests/ui/char_lit_as_u8_suggestions.fixed b/tests/ui/char_lit_as_u8_suggestions.fixed index 6f13078a3ae9..64aacedfd36a 100644 --- a/tests/ui/char_lit_as_u8_suggestions.fixed +++ b/tests/ui/char_lit_as_u8_suggestions.fixed @@ -2,7 +2,11 @@ fn main() { let _ = b'a'; + //~^ char_lit_as_u8 let _ = b'\n'; + //~^ char_lit_as_u8 let _ = b'\0'; + //~^ char_lit_as_u8 let _ = b'\x01'; + //~^ char_lit_as_u8 } diff --git a/tests/ui/char_lit_as_u8_suggestions.rs b/tests/ui/char_lit_as_u8_suggestions.rs index 7737eb5135fb..a8f39e27605e 100644 --- a/tests/ui/char_lit_as_u8_suggestions.rs +++ b/tests/ui/char_lit_as_u8_suggestions.rs @@ -2,7 +2,11 @@ fn main() { let _ = 'a' as u8; + //~^ char_lit_as_u8 let _ = '\n' as u8; + //~^ char_lit_as_u8 let _ = '\0' as u8; + //~^ char_lit_as_u8 let _ = '\x01' as u8; + //~^ char_lit_as_u8 } diff --git a/tests/ui/char_lit_as_u8_suggestions.stderr b/tests/ui/char_lit_as_u8_suggestions.stderr index 4826aca42e1c..158dfd6bed26 100644 --- a/tests/ui/char_lit_as_u8_suggestions.stderr +++ b/tests/ui/char_lit_as_u8_suggestions.stderr @@ -9,7 +9,7 @@ LL | let _ = 'a' as u8; = help: to override `-D warnings` add `#[allow(clippy::char_lit_as_u8)]` error: casting a character literal to `u8` truncates - --> tests/ui/char_lit_as_u8_suggestions.rs:5:13 + --> tests/ui/char_lit_as_u8_suggestions.rs:6:13 | LL | let _ = '\n' as u8; | ^^^^^^^^^^ help: use a byte literal instead: `b'\n'` @@ -17,7 +17,7 @@ LL | let _ = '\n' as u8; = note: `char` is four bytes wide, but `u8` is a single byte error: casting a character literal to `u8` truncates - --> tests/ui/char_lit_as_u8_suggestions.rs:6:13 + --> tests/ui/char_lit_as_u8_suggestions.rs:8:13 | LL | let _ = '\0' as u8; | ^^^^^^^^^^ help: use a byte literal instead: `b'\0'` @@ -25,7 +25,7 @@ LL | let _ = '\0' as u8; = note: `char` is four bytes wide, but `u8` is a single byte error: casting a character literal to `u8` truncates - --> tests/ui/char_lit_as_u8_suggestions.rs:7:13 + --> tests/ui/char_lit_as_u8_suggestions.rs:10:13 | LL | let _ = '\x01' as u8; | ^^^^^^^^^^^^ help: use a byte literal instead: `b'\x01'` diff --git a/tests/ui/checked_conversions.fixed b/tests/ui/checked_conversions.fixed index 1e8da3316141..279a5b6e1ff8 100644 --- a/tests/ui/checked_conversions.fixed +++ b/tests/ui/checked_conversions.fixed @@ -13,46 +13,62 @@ pub fn i64_to_u32(value: i64) { let _ = u32::try_from(value).is_ok(); + //~^ checked_conversions let _ = u32::try_from(value).is_ok(); + //~^ checked_conversions } pub fn i64_to_u16(value: i64) { let _ = u16::try_from(value).is_ok(); + //~^ checked_conversions let _ = u16::try_from(value).is_ok(); + //~^ checked_conversions } pub fn isize_to_u8(value: isize) { let _ = u8::try_from(value).is_ok(); + //~^ checked_conversions let _ = u8::try_from(value).is_ok(); + //~^ checked_conversions } // Signed to signed pub fn i64_to_i32(value: i64) { let _ = i32::try_from(value).is_ok(); + //~^ checked_conversions let _ = i32::try_from(value).is_ok(); + //~^ checked_conversions } pub fn i64_to_i16(value: i64) { let _ = i16::try_from(value).is_ok(); + //~^ checked_conversions let _ = i16::try_from(value).is_ok(); + //~^ checked_conversions } // Unsigned to X pub fn u32_to_i32(value: u32) { let _ = i32::try_from(value).is_ok(); + //~^ checked_conversions let _ = i32::try_from(value).is_ok(); + //~^ checked_conversions } pub fn usize_to_isize(value: usize) { let _ = isize::try_from(value).is_ok() && value as i32 == 5; + //~^ checked_conversions let _ = isize::try_from(value).is_ok() && value as i32 == 5; + //~^ checked_conversions } pub fn u32_to_u16(value: u32) { let _ = u16::try_from(value).is_ok() && value as i32 == 5; + //~^ checked_conversions let _ = u16::try_from(value).is_ok() && value as i32 == 5; + //~^ checked_conversions } // Negative tests @@ -86,6 +102,7 @@ fn msrv_1_33() { fn msrv_1_34() { let value: i64 = 34; let _ = u32::try_from(value).is_ok(); + //~^ checked_conversions } fn main() {} diff --git a/tests/ui/checked_conversions.rs b/tests/ui/checked_conversions.rs index 67a9adc049ea..c339bc674bbb 100644 --- a/tests/ui/checked_conversions.rs +++ b/tests/ui/checked_conversions.rs @@ -13,46 +13,62 @@ pub fn i64_to_u32(value: i64) { let _ = value <= (u32::max_value() as i64) && value >= 0; + //~^ checked_conversions let _ = value <= (u32::MAX as i64) && value >= 0; + //~^ checked_conversions } pub fn i64_to_u16(value: i64) { let _ = value <= i64::from(u16::max_value()) && value >= 0; + //~^ checked_conversions let _ = value <= i64::from(u16::MAX) && value >= 0; + //~^ checked_conversions } pub fn isize_to_u8(value: isize) { let _ = value <= (u8::max_value() as isize) && value >= 0; + //~^ checked_conversions let _ = value <= (u8::MAX as isize) && value >= 0; + //~^ checked_conversions } // Signed to signed pub fn i64_to_i32(value: i64) { let _ = value <= (i32::max_value() as i64) && value >= (i32::min_value() as i64); + //~^ checked_conversions let _ = value <= (i32::MAX as i64) && value >= (i32::MIN as i64); + //~^ checked_conversions } pub fn i64_to_i16(value: i64) { let _ = value <= i64::from(i16::max_value()) && value >= i64::from(i16::min_value()); + //~^ checked_conversions let _ = value <= i64::from(i16::MAX) && value >= i64::from(i16::MIN); + //~^ checked_conversions } // Unsigned to X pub fn u32_to_i32(value: u32) { let _ = value <= i32::max_value() as u32; + //~^ checked_conversions let _ = value <= i32::MAX as u32; + //~^ checked_conversions } pub fn usize_to_isize(value: usize) { let _ = value <= isize::max_value() as usize && value as i32 == 5; + //~^ checked_conversions let _ = value <= isize::MAX as usize && value as i32 == 5; + //~^ checked_conversions } pub fn u32_to_u16(value: u32) { let _ = value <= u16::max_value() as u32 && value as i32 == 5; + //~^ checked_conversions let _ = value <= u16::MAX as u32 && value as i32 == 5; + //~^ checked_conversions } // Negative tests @@ -86,6 +102,7 @@ fn msrv_1_33() { fn msrv_1_34() { let value: i64 = 34; let _ = value <= (u32::MAX as i64) && value >= 0; + //~^ checked_conversions } fn main() {} diff --git a/tests/ui/checked_conversions.stderr b/tests/ui/checked_conversions.stderr index 453cd7fcf016..3841b9d5a4dd 100644 --- a/tests/ui/checked_conversions.stderr +++ b/tests/ui/checked_conversions.stderr @@ -8,97 +8,97 @@ LL | let _ = value <= (u32::max_value() as i64) && value >= 0; = help: to override `-D warnings` add `#[allow(clippy::checked_conversions)]` error: checked cast can be simplified - --> tests/ui/checked_conversions.rs:16:13 + --> tests/ui/checked_conversions.rs:17:13 | LL | let _ = value <= (u32::MAX as i64) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()` error: checked cast can be simplified - --> tests/ui/checked_conversions.rs:20:13 + --> tests/ui/checked_conversions.rs:22:13 | LL | let _ = value <= i64::from(u16::max_value()) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()` error: checked cast can be simplified - --> tests/ui/checked_conversions.rs:21:13 + --> tests/ui/checked_conversions.rs:24:13 | LL | let _ = value <= i64::from(u16::MAX) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()` error: checked cast can be simplified - --> tests/ui/checked_conversions.rs:25:13 + --> tests/ui/checked_conversions.rs:29:13 | LL | let _ = value <= (u8::max_value() as isize) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u8::try_from(value).is_ok()` error: checked cast can be simplified - --> tests/ui/checked_conversions.rs:26:13 + --> tests/ui/checked_conversions.rs:31:13 | LL | let _ = value <= (u8::MAX as isize) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u8::try_from(value).is_ok()` error: checked cast can be simplified - --> tests/ui/checked_conversions.rs:32:13 + --> tests/ui/checked_conversions.rs:38:13 | LL | let _ = value <= (i32::max_value() as i64) && value >= (i32::min_value() as i64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` error: checked cast can be simplified - --> tests/ui/checked_conversions.rs:33:13 + --> tests/ui/checked_conversions.rs:40:13 | LL | let _ = value <= (i32::MAX as i64) && value >= (i32::MIN as i64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` error: checked cast can be simplified - --> tests/ui/checked_conversions.rs:37:13 + --> tests/ui/checked_conversions.rs:45:13 | LL | let _ = value <= i64::from(i16::max_value()) && value >= i64::from(i16::min_value()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i16::try_from(value).is_ok()` error: checked cast can be simplified - --> tests/ui/checked_conversions.rs:38:13 + --> tests/ui/checked_conversions.rs:47:13 | LL | let _ = value <= i64::from(i16::MAX) && value >= i64::from(i16::MIN); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i16::try_from(value).is_ok()` error: checked cast can be simplified - --> tests/ui/checked_conversions.rs:44:13 + --> tests/ui/checked_conversions.rs:54:13 | LL | let _ = value <= i32::max_value() as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` error: checked cast can be simplified - --> tests/ui/checked_conversions.rs:45:13 + --> tests/ui/checked_conversions.rs:56:13 | LL | let _ = value <= i32::MAX as u32; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()` error: checked cast can be simplified - --> tests/ui/checked_conversions.rs:49:13 + --> tests/ui/checked_conversions.rs:61:13 | LL | let _ = value <= isize::max_value() as usize && value as i32 == 5; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `isize::try_from(value).is_ok()` error: checked cast can be simplified - --> tests/ui/checked_conversions.rs:50:13 + --> tests/ui/checked_conversions.rs:63:13 | LL | let _ = value <= isize::MAX as usize && value as i32 == 5; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `isize::try_from(value).is_ok()` error: checked cast can be simplified - --> tests/ui/checked_conversions.rs:54:13 + --> tests/ui/checked_conversions.rs:68:13 | LL | let _ = value <= u16::max_value() as u32 && value as i32 == 5; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()` error: checked cast can be simplified - --> tests/ui/checked_conversions.rs:55:13 + --> tests/ui/checked_conversions.rs:70:13 | LL | let _ = value <= u16::MAX as u32 && value as i32 == 5; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()` error: checked cast can be simplified - --> tests/ui/checked_conversions.rs:88:13 + --> tests/ui/checked_conversions.rs:104:13 | LL | let _ = value <= (u32::MAX as i64) && value >= 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()` diff --git a/tests/ui/checked_unwrap/complex_conditionals.rs b/tests/ui/checked_unwrap/complex_conditionals.rs index 323dae380633..7d0bcc547a42 100644 --- a/tests/ui/checked_unwrap/complex_conditionals.rs +++ b/tests/ui/checked_unwrap/complex_conditionals.rs @@ -11,16 +11,19 @@ fn test_complex_conditions() { if x.is_ok() && y.is_err() { // unnecessary x.unwrap(); - //~^ ERROR: called `unwrap` on `x` after checking its variant with `is_ok` + //~^ unnecessary_unwrap + // will panic x.unwrap_err(); - //~^ ERROR: this call to `unwrap_err()` will always panic + //~^ panicking_unwrap + // will panic y.unwrap(); - //~^ ERROR: this call to `unwrap()` will always panic + //~^ panicking_unwrap + // unnecessary y.unwrap_err(); - //~^ ERROR: called `unwrap_err` on `y` after checking its variant with `is_err` + //~^ unnecessary_unwrap } else { // not statically determinable whether any of the following will always succeed or always fail: x.unwrap(); @@ -36,37 +39,45 @@ fn test_complex_conditions() { } else { // will panic x.unwrap(); - //~^ ERROR: this call to `unwrap()` will always panic + //~^ panicking_unwrap + // unnecessary x.unwrap_err(); - //~^ ERROR: called `unwrap_err` on `x` after checking its variant with `is_ok` + //~^ unnecessary_unwrap + // will panic y.unwrap(); - //~^ ERROR: this call to `unwrap()` will always panic + //~^ panicking_unwrap + // unnecessary y.unwrap_err(); - //~^ ERROR: called `unwrap_err` on `y` after checking its variant with `is_ok` + //~^ unnecessary_unwrap } let z: Result<(), ()> = Ok(()); if x.is_ok() && !(y.is_ok() || z.is_err()) { // unnecessary x.unwrap(); - //~^ ERROR: called `unwrap` on `x` after checking its variant with `is_ok` + //~^ unnecessary_unwrap + // will panic x.unwrap_err(); - //~^ ERROR: this call to `unwrap_err()` will always panic + //~^ panicking_unwrap + // will panic y.unwrap(); - //~^ ERROR: this call to `unwrap()` will always panic + //~^ panicking_unwrap + // unnecessary y.unwrap_err(); - //~^ ERROR: called `unwrap_err` on `y` after checking its variant with `is_ok` + //~^ unnecessary_unwrap + // unnecessary z.unwrap(); - //~^ ERROR: called `unwrap` on `z` after checking its variant with `is_err` + //~^ unnecessary_unwrap + // will panic z.unwrap_err(); - //~^ ERROR: this call to `unwrap_err()` will always panic + //~^ panicking_unwrap } if x.is_ok() || !(y.is_ok() && z.is_err()) { // not statically determinable whether any of the following will always succeed or always fail: @@ -76,22 +87,27 @@ fn test_complex_conditions() { } else { // will panic x.unwrap(); - //~^ ERROR: this call to `unwrap()` will always panic + //~^ panicking_unwrap + // unnecessary x.unwrap_err(); - //~^ ERROR: called `unwrap_err` on `x` after checking its variant with `is_ok` + //~^ unnecessary_unwrap + // unnecessary y.unwrap(); - //~^ ERROR: called `unwrap` on `y` after checking its variant with `is_ok` + //~^ unnecessary_unwrap + // will panic y.unwrap_err(); - //~^ ERROR: this call to `unwrap_err()` will always panic + //~^ panicking_unwrap + // will panic z.unwrap(); - //~^ ERROR: this call to `unwrap()` will always panic + //~^ panicking_unwrap + // unnecessary z.unwrap_err(); - //~^ ERROR: called `unwrap_err` on `z` after checking its variant with `is_err` + //~^ unnecessary_unwrap } } diff --git a/tests/ui/checked_unwrap/complex_conditionals.stderr b/tests/ui/checked_unwrap/complex_conditionals.stderr index aa72e8cce590..d3905850c970 100644 --- a/tests/ui/checked_unwrap/complex_conditionals.stderr +++ b/tests/ui/checked_unwrap/complex_conditionals.stderr @@ -15,7 +15,7 @@ LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap_err()` will always panic - --> tests/ui/checked_unwrap/complex_conditionals.rs:16:9 + --> tests/ui/checked_unwrap/complex_conditionals.rs:17:9 | LL | if x.is_ok() && y.is_err() { | --------- because of this check @@ -30,7 +30,7 @@ LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> tests/ui/checked_unwrap/complex_conditionals.rs:19:9 + --> tests/ui/checked_unwrap/complex_conditionals.rs:21:9 | LL | if x.is_ok() && y.is_err() { | ---------- because of this check @@ -39,7 +39,7 @@ LL | y.unwrap(); | ^^^^^^^^^^ error: called `unwrap_err` on `y` after checking its variant with `is_err` - --> tests/ui/checked_unwrap/complex_conditionals.rs:22:9 + --> tests/ui/checked_unwrap/complex_conditionals.rs:25:9 | LL | if x.is_ok() && y.is_err() { | ---------- the check is happening here @@ -50,7 +50,7 @@ LL | y.unwrap_err(); = help: try using `if let` or `match` error: this call to `unwrap()` will always panic - --> tests/ui/checked_unwrap/complex_conditionals.rs:38:9 + --> tests/ui/checked_unwrap/complex_conditionals.rs:41:9 | LL | if x.is_ok() || y.is_ok() { | --------- because of this check @@ -59,7 +59,7 @@ LL | x.unwrap(); | ^^^^^^^^^^ error: called `unwrap_err` on `x` after checking its variant with `is_ok` - --> tests/ui/checked_unwrap/complex_conditionals.rs:41:9 + --> tests/ui/checked_unwrap/complex_conditionals.rs:45:9 | LL | if x.is_ok() || y.is_ok() { | --------- the check is happening here @@ -70,7 +70,7 @@ LL | x.unwrap_err(); = help: try using `if let` or `match` error: this call to `unwrap()` will always panic - --> tests/ui/checked_unwrap/complex_conditionals.rs:44:9 + --> tests/ui/checked_unwrap/complex_conditionals.rs:49:9 | LL | if x.is_ok() || y.is_ok() { | --------- because of this check @@ -79,7 +79,7 @@ LL | y.unwrap(); | ^^^^^^^^^^ error: called `unwrap_err` on `y` after checking its variant with `is_ok` - --> tests/ui/checked_unwrap/complex_conditionals.rs:47:9 + --> tests/ui/checked_unwrap/complex_conditionals.rs:53:9 | LL | if x.is_ok() || y.is_ok() { | --------- the check is happening here @@ -90,7 +90,7 @@ LL | y.unwrap_err(); = help: try using `if let` or `match` error: called `unwrap` on `x` after checking its variant with `is_ok` - --> tests/ui/checked_unwrap/complex_conditionals.rs:53:9 + --> tests/ui/checked_unwrap/complex_conditionals.rs:59:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- the check is happening here @@ -101,7 +101,7 @@ LL | x.unwrap(); = help: try using `if let` or `match` error: this call to `unwrap_err()` will always panic - --> tests/ui/checked_unwrap/complex_conditionals.rs:56:9 + --> tests/ui/checked_unwrap/complex_conditionals.rs:63:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- because of this check @@ -110,7 +110,7 @@ LL | x.unwrap_err(); | ^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> tests/ui/checked_unwrap/complex_conditionals.rs:59:9 + --> tests/ui/checked_unwrap/complex_conditionals.rs:67:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- because of this check @@ -119,7 +119,7 @@ LL | y.unwrap(); | ^^^^^^^^^^ error: called `unwrap_err` on `y` after checking its variant with `is_ok` - --> tests/ui/checked_unwrap/complex_conditionals.rs:62:9 + --> tests/ui/checked_unwrap/complex_conditionals.rs:71:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- the check is happening here @@ -130,7 +130,7 @@ LL | y.unwrap_err(); = help: try using `if let` or `match` error: called `unwrap` on `z` after checking its variant with `is_err` - --> tests/ui/checked_unwrap/complex_conditionals.rs:65:9 + --> tests/ui/checked_unwrap/complex_conditionals.rs:75:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | ---------- the check is happening here @@ -141,7 +141,7 @@ LL | z.unwrap(); = help: try using `if let` or `match` error: this call to `unwrap_err()` will always panic - --> tests/ui/checked_unwrap/complex_conditionals.rs:68:9 + --> tests/ui/checked_unwrap/complex_conditionals.rs:79:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | ---------- because of this check @@ -150,7 +150,7 @@ LL | z.unwrap_err(); | ^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> tests/ui/checked_unwrap/complex_conditionals.rs:78:9 + --> tests/ui/checked_unwrap/complex_conditionals.rs:89:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- because of this check @@ -159,7 +159,7 @@ LL | x.unwrap(); | ^^^^^^^^^^ error: called `unwrap_err` on `x` after checking its variant with `is_ok` - --> tests/ui/checked_unwrap/complex_conditionals.rs:81:9 + --> tests/ui/checked_unwrap/complex_conditionals.rs:93:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- the check is happening here @@ -170,7 +170,7 @@ LL | x.unwrap_err(); = help: try using `if let` or `match` error: called `unwrap` on `y` after checking its variant with `is_ok` - --> tests/ui/checked_unwrap/complex_conditionals.rs:84:9 + --> tests/ui/checked_unwrap/complex_conditionals.rs:97:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- the check is happening here @@ -181,7 +181,7 @@ LL | y.unwrap(); = help: try using `if let` or `match` error: this call to `unwrap_err()` will always panic - --> tests/ui/checked_unwrap/complex_conditionals.rs:87:9 + --> tests/ui/checked_unwrap/complex_conditionals.rs:101:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- because of this check @@ -190,7 +190,7 @@ LL | y.unwrap_err(); | ^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> tests/ui/checked_unwrap/complex_conditionals.rs:90:9 + --> tests/ui/checked_unwrap/complex_conditionals.rs:105:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | ---------- because of this check @@ -199,7 +199,7 @@ LL | z.unwrap(); | ^^^^^^^^^^ error: called `unwrap_err` on `z` after checking its variant with `is_err` - --> tests/ui/checked_unwrap/complex_conditionals.rs:93:9 + --> tests/ui/checked_unwrap/complex_conditionals.rs:109:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | ---------- the check is happening here diff --git a/tests/ui/checked_unwrap/complex_conditionals_nested.rs b/tests/ui/checked_unwrap/complex_conditionals_nested.rs index 68923793dcdf..145885702a9b 100644 --- a/tests/ui/checked_unwrap/complex_conditionals_nested.rs +++ b/tests/ui/checked_unwrap/complex_conditionals_nested.rs @@ -11,11 +11,11 @@ fn test_nested() { if x.is_some() { // unnecessary x.unwrap(); - //~^ ERROR: called `unwrap` on `x` after checking its variant with `is_some` + //~^ unnecessary_unwrap } else { // will panic x.unwrap(); - //~^ ERROR: this call to `unwrap()` will always panic + //~^ panicking_unwrap } } } diff --git a/tests/ui/checked_unwrap/simple_conditionals.rs b/tests/ui/checked_unwrap/simple_conditionals.rs index c3c8562edffb..4101897d3800 100644 --- a/tests/ui/checked_unwrap/simple_conditionals.rs +++ b/tests/ui/checked_unwrap/simple_conditionals.rs @@ -11,6 +11,7 @@ macro_rules! m { if $a.is_some() { // unnecessary $a.unwrap(); + //~^ unnecessary_unwrap } }; } @@ -44,26 +45,28 @@ fn main() { if x.is_some() { // unnecessary x.unwrap(); - //~^ ERROR: called `unwrap` on `x` after checking its variant with `is_some` + //~^ unnecessary_unwrap + // unnecessary x.expect("an error message"); - //~^ ERROR: called `expect` on `x` after checking its variant with `is_some` + //~^ unnecessary_unwrap } else { // will panic x.unwrap(); - //~^ ERROR: this call to `unwrap()` will always panic + //~^ panicking_unwrap + // will panic x.expect("an error message"); - //~^ ERROR: this call to `expect()` will always panic + //~^ panicking_unwrap } if x.is_none() { // will panic x.unwrap(); - //~^ ERROR: this call to `unwrap()` will always panic + //~^ panicking_unwrap } else { // unnecessary x.unwrap(); - //~^ ERROR: called `unwrap` on `x` after checking its variant with `is_none` + //~^ unnecessary_unwrap } m!(x); // ok @@ -76,38 +79,44 @@ fn main() { if x.is_ok() { // unnecessary x.unwrap(); - //~^ ERROR: called `unwrap` on `x` after checking its variant with `is_ok` + //~^ unnecessary_unwrap + // unnecessary x.expect("an error message"); - //~^ ERROR: called `expect` on `x` after checking its variant with `is_ok` + //~^ unnecessary_unwrap + // will panic x.unwrap_err(); - //~^ ERROR: this call to `unwrap_err()` will always panic + //~^ panicking_unwrap } else { // will panic x.unwrap(); - //~^ ERROR: this call to `unwrap()` will always panic + //~^ panicking_unwrap + // will panic x.expect("an error message"); - //~^ ERROR: this call to `expect()` will always panic + //~^ panicking_unwrap + // unnecessary x.unwrap_err(); - //~^ ERROR: called `unwrap_err` on `x` after checking its variant with `is_ok` + //~^ unnecessary_unwrap } if x.is_err() { // will panic x.unwrap(); - //~^ ERROR: this call to `unwrap()` will always panic + //~^ panicking_unwrap + // unnecessary x.unwrap_err(); - //~^ ERROR: called `unwrap_err` on `x` after checking its variant with `is_err` + //~^ unnecessary_unwrap } else { // unnecessary x.unwrap(); - //~^ ERROR: called `unwrap` on `x` after checking its variant with `is_err` + //~^ unnecessary_unwrap + // will panic x.unwrap_err(); - //~^ ERROR: this call to `unwrap_err()` will always panic + //~^ panicking_unwrap } if x.is_ok() { x = Err(()); @@ -132,38 +141,38 @@ fn issue11371() { if option.is_some() { option.as_ref().unwrap(); - //~^ ERROR: called `unwrap` on `option` after checking its variant with `is_some` + //~^ unnecessary_unwrap } else { option.as_ref().unwrap(); - //~^ ERROR: this call to `unwrap()` will always panic + //~^ panicking_unwrap } let result = Ok::<(), ()>(()); if result.is_ok() { result.as_ref().unwrap(); - //~^ ERROR: called `unwrap` on `result` after checking its variant with `is_ok` + //~^ unnecessary_unwrap } else { result.as_ref().unwrap(); - //~^ ERROR: this call to `unwrap()` will always panic + //~^ panicking_unwrap } let mut option = Some(()); if option.is_some() { option.as_mut().unwrap(); - //~^ ERROR: called `unwrap` on `option` after checking its variant with `is_some` + //~^ unnecessary_unwrap } else { option.as_mut().unwrap(); - //~^ ERROR: this call to `unwrap()` will always panic + //~^ panicking_unwrap } let mut result = Ok::<(), ()>(()); if result.is_ok() { result.as_mut().unwrap(); - //~^ ERROR: called `unwrap` on `result` after checking its variant with `is_ok` + //~^ unnecessary_unwrap } else { result.as_mut().unwrap(); - //~^ ERROR: this call to `unwrap()` will always panic + //~^ panicking_unwrap } // This should not lint. Statics are, at the time of writing, not linted on anyway, @@ -172,6 +181,7 @@ fn issue11371() { static mut X: Option = Some(123); unsafe { if X.is_some() { + //~^ ERROR: creating a shared reference X = None; X.unwrap(); } diff --git a/tests/ui/checked_unwrap/simple_conditionals.stderr b/tests/ui/checked_unwrap/simple_conditionals.stderr index d92c03f48881..c17eaef2326b 100644 --- a/tests/ui/checked_unwrap/simple_conditionals.stderr +++ b/tests/ui/checked_unwrap/simple_conditionals.stderr @@ -1,5 +1,5 @@ error: called `unwrap` on `x` after checking its variant with `is_some` - --> tests/ui/checked_unwrap/simple_conditionals.rs:46:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:47:9 | LL | if x.is_some() { | -------------- help: try: `if let Some() = x` @@ -14,7 +14,7 @@ LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `expect` on `x` after checking its variant with `is_some` - --> tests/ui/checked_unwrap/simple_conditionals.rs:49:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:51:9 | LL | if x.is_some() { | -------------- help: try: `if let Some() = x` @@ -23,7 +23,7 @@ LL | x.expect("an error message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:53:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:55:9 | LL | if x.is_some() { | ----------- because of this check @@ -38,7 +38,7 @@ LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `expect()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:56:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:59:9 | LL | if x.is_some() { | ----------- because of this check @@ -47,7 +47,7 @@ LL | x.expect("an error message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:61:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:64:9 | LL | if x.is_none() { | ----------- because of this check @@ -56,7 +56,7 @@ LL | x.unwrap(); | ^^^^^^^^^^ error: called `unwrap` on `x` after checking its variant with `is_none` - --> tests/ui/checked_unwrap/simple_conditionals.rs:65:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:68:9 | LL | if x.is_none() { | -------------- help: try: `if let Some() = x` @@ -79,7 +79,7 @@ LL | m!(x); = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: called `unwrap` on `x` after checking its variant with `is_ok` - --> tests/ui/checked_unwrap/simple_conditionals.rs:78:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:81:9 | LL | if x.is_ok() { | ------------ help: try: `if let Ok() = x` @@ -88,7 +88,7 @@ LL | x.unwrap(); | ^^^^^^^^^^ error: called `expect` on `x` after checking its variant with `is_ok` - --> tests/ui/checked_unwrap/simple_conditionals.rs:81:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:85:9 | LL | if x.is_ok() { | ------------ help: try: `if let Ok() = x` @@ -97,7 +97,7 @@ LL | x.expect("an error message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap_err()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:84:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:89:9 | LL | if x.is_ok() { | --------- because of this check @@ -106,7 +106,7 @@ LL | x.unwrap_err(); | ^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:88:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:93:9 | LL | if x.is_ok() { | --------- because of this check @@ -115,7 +115,7 @@ LL | x.unwrap(); | ^^^^^^^^^^ error: this call to `expect()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:91:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:97:9 | LL | if x.is_ok() { | --------- because of this check @@ -124,7 +124,7 @@ LL | x.expect("an error message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `unwrap_err` on `x` after checking its variant with `is_ok` - --> tests/ui/checked_unwrap/simple_conditionals.rs:94:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:101:9 | LL | if x.is_ok() { | ------------ help: try: `if let Err() = x` @@ -133,7 +133,7 @@ LL | x.unwrap_err(); | ^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:99:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:106:9 | LL | if x.is_err() { | ---------- because of this check @@ -142,7 +142,7 @@ LL | x.unwrap(); | ^^^^^^^^^^ error: called `unwrap_err` on `x` after checking its variant with `is_err` - --> tests/ui/checked_unwrap/simple_conditionals.rs:102:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:110:9 | LL | if x.is_err() { | ------------- help: try: `if let Err() = x` @@ -151,7 +151,7 @@ LL | x.unwrap_err(); | ^^^^^^^^^^^^^^ error: called `unwrap` on `x` after checking its variant with `is_err` - --> tests/ui/checked_unwrap/simple_conditionals.rs:106:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:114:9 | LL | if x.is_err() { | ------------- help: try: `if let Ok() = x` @@ -160,7 +160,7 @@ LL | x.unwrap(); | ^^^^^^^^^^ error: this call to `unwrap_err()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:109:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:118:9 | LL | if x.is_err() { | ---------- because of this check @@ -169,7 +169,7 @@ LL | x.unwrap_err(); | ^^^^^^^^^^^^^^ error: called `unwrap` on `option` after checking its variant with `is_some` - --> tests/ui/checked_unwrap/simple_conditionals.rs:134:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:143:9 | LL | if option.is_some() { | ------------------- help: try: `if let Some() = &option` @@ -177,7 +177,7 @@ LL | option.as_ref().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:137:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:146:9 | LL | if option.is_some() { | ---------------- because of this check @@ -186,7 +186,7 @@ LL | option.as_ref().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: called `unwrap` on `result` after checking its variant with `is_ok` - --> tests/ui/checked_unwrap/simple_conditionals.rs:144:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:153:9 | LL | if result.is_ok() { | ----------------- help: try: `if let Ok() = &result` @@ -194,7 +194,7 @@ LL | result.as_ref().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:147:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:156:9 | LL | if result.is_ok() { | -------------- because of this check @@ -203,7 +203,7 @@ LL | result.as_ref().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: called `unwrap` on `option` after checking its variant with `is_some` - --> tests/ui/checked_unwrap/simple_conditionals.rs:153:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:162:9 | LL | if option.is_some() { | ------------------- help: try: `if let Some() = &mut option` @@ -211,7 +211,7 @@ LL | option.as_mut().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:156:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:165:9 | LL | if option.is_some() { | ---------------- because of this check @@ -220,7 +220,7 @@ LL | option.as_mut().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: called `unwrap` on `result` after checking its variant with `is_ok` - --> tests/ui/checked_unwrap/simple_conditionals.rs:162:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:171:9 | LL | if result.is_ok() { | ----------------- help: try: `if let Ok() = &mut result` @@ -228,7 +228,7 @@ LL | result.as_mut().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:165:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:174:9 | LL | if result.is_ok() { | -------------- because of this check @@ -237,7 +237,7 @@ LL | result.as_mut().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: creating a shared reference to mutable static is discouraged - --> tests/ui/checked_unwrap/simple_conditionals.rs:174:12 + --> tests/ui/checked_unwrap/simple_conditionals.rs:183:12 | LL | if X.is_some() { | ^^^^^^^^^^^ shared reference to mutable static diff --git a/tests/ui/clear_with_drain.fixed b/tests/ui/clear_with_drain.fixed index 15777a4ea5b3..92fd86668b76 100644 --- a/tests/ui/clear_with_drain.fixed +++ b/tests/ui/clear_with_drain.fixed @@ -20,10 +20,12 @@ fn vec_range() { // Do lint let mut v = vec![1, 2, 3]; v.clear(); + //~^ clear_with_drain // Do lint let mut v = vec![1, 2, 3]; v.clear(); + //~^ clear_with_drain } fn vec_range_from() { @@ -43,10 +45,12 @@ fn vec_range_from() { // Do lint let mut v = vec![1, 2, 3]; v.clear(); + //~^ clear_with_drain // Do lint let mut v = vec![1, 2, 3]; v.clear(); + //~^ clear_with_drain } fn vec_range_full() { @@ -63,6 +67,7 @@ fn vec_range_full() { // Do lint let mut v = vec![1, 2, 3]; v.clear(); + //~^ clear_with_drain } fn vec_range_to() { @@ -80,6 +85,7 @@ fn vec_range_to() { // Do lint let mut v = vec![1, 2, 3]; v.clear(); + //~^ clear_with_drain } fn vec_partial_drains() { @@ -118,10 +124,12 @@ fn vec_deque_range() { // Do lint let mut deque = VecDeque::from([1, 2, 3]); deque.clear(); + //~^ clear_with_drain // Do lint let mut deque = VecDeque::from([1, 2, 3]); deque.clear(); + //~^ clear_with_drain } fn vec_deque_range_from() { @@ -141,10 +149,12 @@ fn vec_deque_range_from() { // Do lint let mut deque = VecDeque::from([1, 2, 3]); deque.clear(); + //~^ clear_with_drain // Do lint let mut deque = VecDeque::from([1, 2, 3]); deque.clear(); + //~^ clear_with_drain } fn vec_deque_range_full() { @@ -161,6 +171,7 @@ fn vec_deque_range_full() { // Do lint let mut deque = VecDeque::from([1, 2, 3]); deque.clear(); + //~^ clear_with_drain } fn vec_deque_range_to() { @@ -178,6 +189,7 @@ fn vec_deque_range_to() { // Do lint let mut deque = VecDeque::from([1, 2, 3]); deque.clear(); + //~^ clear_with_drain } fn vec_deque_partial_drains() { @@ -216,10 +228,12 @@ fn string_range() { // Do lint let mut s = String::from("Hello, world!"); s.clear(); + //~^ clear_with_drain // Do lint let mut s = String::from("Hello, world!"); s.clear(); + //~^ clear_with_drain } fn string_range_from() { @@ -239,10 +253,12 @@ fn string_range_from() { // Do lint let mut s = String::from("Hello, world!"); s.clear(); + //~^ clear_with_drain // Do lint let mut s = String::from("Hello, world!"); s.clear(); + //~^ clear_with_drain } fn string_range_full() { @@ -259,6 +275,7 @@ fn string_range_full() { // Do lint let mut s = String::from("Hello, world!"); s.clear(); + //~^ clear_with_drain } fn string_range_to() { @@ -276,6 +293,7 @@ fn string_range_to() { // Do lint let mut s = String::from("Hello, world!"); s.clear(); + //~^ clear_with_drain } fn string_partial_drains() { @@ -314,6 +332,7 @@ fn hash_set() { // Do lint let mut set = HashSet::from([1, 2, 3]); set.clear(); + //~^ clear_with_drain } fn hash_map() { @@ -333,6 +352,7 @@ fn hash_map() { // Do lint let mut map = HashMap::from([(1, "a"), (2, "b")]); map.clear(); + //~^ clear_with_drain } fn binary_heap() { @@ -352,6 +372,7 @@ fn binary_heap() { // Do lint let mut heap = BinaryHeap::from([1, 2]); heap.clear(); + //~^ clear_with_drain } fn main() {} diff --git a/tests/ui/clear_with_drain.rs b/tests/ui/clear_with_drain.rs index 1dea7235ef66..28122fcaeded 100644 --- a/tests/ui/clear_with_drain.rs +++ b/tests/ui/clear_with_drain.rs @@ -20,10 +20,12 @@ fn vec_range() { // Do lint let mut v = vec![1, 2, 3]; v.drain(0..v.len()); + //~^ clear_with_drain // Do lint let mut v = vec![1, 2, 3]; v.drain(usize::MIN..v.len()); + //~^ clear_with_drain } fn vec_range_from() { @@ -43,10 +45,12 @@ fn vec_range_from() { // Do lint let mut v = vec![1, 2, 3]; v.drain(0..); + //~^ clear_with_drain // Do lint let mut v = vec![1, 2, 3]; v.drain(usize::MIN..); + //~^ clear_with_drain } fn vec_range_full() { @@ -63,6 +67,7 @@ fn vec_range_full() { // Do lint let mut v = vec![1, 2, 3]; v.drain(..); + //~^ clear_with_drain } fn vec_range_to() { @@ -80,6 +85,7 @@ fn vec_range_to() { // Do lint let mut v = vec![1, 2, 3]; v.drain(..v.len()); + //~^ clear_with_drain } fn vec_partial_drains() { @@ -118,10 +124,12 @@ fn vec_deque_range() { // Do lint let mut deque = VecDeque::from([1, 2, 3]); deque.drain(0..deque.len()); + //~^ clear_with_drain // Do lint let mut deque = VecDeque::from([1, 2, 3]); deque.drain(usize::MIN..deque.len()); + //~^ clear_with_drain } fn vec_deque_range_from() { @@ -141,10 +149,12 @@ fn vec_deque_range_from() { // Do lint let mut deque = VecDeque::from([1, 2, 3]); deque.drain(0..); + //~^ clear_with_drain // Do lint let mut deque = VecDeque::from([1, 2, 3]); deque.drain(usize::MIN..); + //~^ clear_with_drain } fn vec_deque_range_full() { @@ -161,6 +171,7 @@ fn vec_deque_range_full() { // Do lint let mut deque = VecDeque::from([1, 2, 3]); deque.drain(..); + //~^ clear_with_drain } fn vec_deque_range_to() { @@ -178,6 +189,7 @@ fn vec_deque_range_to() { // Do lint let mut deque = VecDeque::from([1, 2, 3]); deque.drain(..deque.len()); + //~^ clear_with_drain } fn vec_deque_partial_drains() { @@ -216,10 +228,12 @@ fn string_range() { // Do lint let mut s = String::from("Hello, world!"); s.drain(0..s.len()); + //~^ clear_with_drain // Do lint let mut s = String::from("Hello, world!"); s.drain(usize::MIN..s.len()); + //~^ clear_with_drain } fn string_range_from() { @@ -239,10 +253,12 @@ fn string_range_from() { // Do lint let mut s = String::from("Hello, world!"); s.drain(0..); + //~^ clear_with_drain // Do lint let mut s = String::from("Hello, world!"); s.drain(usize::MIN..); + //~^ clear_with_drain } fn string_range_full() { @@ -259,6 +275,7 @@ fn string_range_full() { // Do lint let mut s = String::from("Hello, world!"); s.drain(..); + //~^ clear_with_drain } fn string_range_to() { @@ -276,6 +293,7 @@ fn string_range_to() { // Do lint let mut s = String::from("Hello, world!"); s.drain(..s.len()); + //~^ clear_with_drain } fn string_partial_drains() { @@ -314,6 +332,7 @@ fn hash_set() { // Do lint let mut set = HashSet::from([1, 2, 3]); set.drain(); + //~^ clear_with_drain } fn hash_map() { @@ -333,6 +352,7 @@ fn hash_map() { // Do lint let mut map = HashMap::from([(1, "a"), (2, "b")]); map.drain(); + //~^ clear_with_drain } fn binary_heap() { @@ -352,6 +372,7 @@ fn binary_heap() { // Do lint let mut heap = BinaryHeap::from([1, 2]); heap.drain(); + //~^ clear_with_drain } fn main() {} diff --git a/tests/ui/clear_with_drain.stderr b/tests/ui/clear_with_drain.stderr index 3c7d22192dc7..0f060fa9dade 100644 --- a/tests/ui/clear_with_drain.stderr +++ b/tests/ui/clear_with_drain.stderr @@ -8,121 +8,121 @@ LL | v.drain(0..v.len()); = help: to override `-D warnings` add `#[allow(clippy::clear_with_drain)]` error: `drain` used to clear a `Vec` - --> tests/ui/clear_with_drain.rs:26:7 + --> tests/ui/clear_with_drain.rs:27:7 | LL | v.drain(usize::MIN..v.len()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `clear()` error: `drain` used to clear a `Vec` - --> tests/ui/clear_with_drain.rs:45:7 + --> tests/ui/clear_with_drain.rs:47:7 | LL | v.drain(0..); | ^^^^^^^^^^ help: try: `clear()` error: `drain` used to clear a `Vec` - --> tests/ui/clear_with_drain.rs:49:7 + --> tests/ui/clear_with_drain.rs:52:7 | LL | v.drain(usize::MIN..); | ^^^^^^^^^^^^^^^^^^^ help: try: `clear()` error: `drain` used to clear a `Vec` - --> tests/ui/clear_with_drain.rs:65:7 + --> tests/ui/clear_with_drain.rs:69:7 | LL | v.drain(..); | ^^^^^^^^^ help: try: `clear()` error: `drain` used to clear a `Vec` - --> tests/ui/clear_with_drain.rs:82:7 + --> tests/ui/clear_with_drain.rs:87:7 | LL | v.drain(..v.len()); | ^^^^^^^^^^^^^^^^ help: try: `clear()` error: `drain` used to clear a `VecDeque` - --> tests/ui/clear_with_drain.rs:120:11 + --> tests/ui/clear_with_drain.rs:126:11 | LL | deque.drain(0..deque.len()); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `clear()` error: `drain` used to clear a `VecDeque` - --> tests/ui/clear_with_drain.rs:124:11 + --> tests/ui/clear_with_drain.rs:131:11 | LL | deque.drain(usize::MIN..deque.len()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `clear()` error: `drain` used to clear a `VecDeque` - --> tests/ui/clear_with_drain.rs:143:11 + --> tests/ui/clear_with_drain.rs:151:11 | LL | deque.drain(0..); | ^^^^^^^^^^ help: try: `clear()` error: `drain` used to clear a `VecDeque` - --> tests/ui/clear_with_drain.rs:147:11 + --> tests/ui/clear_with_drain.rs:156:11 | LL | deque.drain(usize::MIN..); | ^^^^^^^^^^^^^^^^^^^ help: try: `clear()` error: `drain` used to clear a `VecDeque` - --> tests/ui/clear_with_drain.rs:163:11 + --> tests/ui/clear_with_drain.rs:173:11 | LL | deque.drain(..); | ^^^^^^^^^ help: try: `clear()` error: `drain` used to clear a `VecDeque` - --> tests/ui/clear_with_drain.rs:180:11 + --> tests/ui/clear_with_drain.rs:191:11 | LL | deque.drain(..deque.len()); | ^^^^^^^^^^^^^^^^^^^^ help: try: `clear()` error: `drain` used to clear a `String` - --> tests/ui/clear_with_drain.rs:218:7 + --> tests/ui/clear_with_drain.rs:230:7 | LL | s.drain(0..s.len()); | ^^^^^^^^^^^^^^^^^ help: try: `clear()` error: `drain` used to clear a `String` - --> tests/ui/clear_with_drain.rs:222:7 + --> tests/ui/clear_with_drain.rs:235:7 | LL | s.drain(usize::MIN..s.len()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `clear()` error: `drain` used to clear a `String` - --> tests/ui/clear_with_drain.rs:241:7 + --> tests/ui/clear_with_drain.rs:255:7 | LL | s.drain(0..); | ^^^^^^^^^^ help: try: `clear()` error: `drain` used to clear a `String` - --> tests/ui/clear_with_drain.rs:245:7 + --> tests/ui/clear_with_drain.rs:260:7 | LL | s.drain(usize::MIN..); | ^^^^^^^^^^^^^^^^^^^ help: try: `clear()` error: `drain` used to clear a `String` - --> tests/ui/clear_with_drain.rs:261:7 + --> tests/ui/clear_with_drain.rs:277:7 | LL | s.drain(..); | ^^^^^^^^^ help: try: `clear()` error: `drain` used to clear a `String` - --> tests/ui/clear_with_drain.rs:278:7 + --> tests/ui/clear_with_drain.rs:295:7 | LL | s.drain(..s.len()); | ^^^^^^^^^^^^^^^^ help: try: `clear()` error: `drain` used to clear a `HashSet` - --> tests/ui/clear_with_drain.rs:316:9 + --> tests/ui/clear_with_drain.rs:334:9 | LL | set.drain(); | ^^^^^^^ help: try: `clear()` error: `drain` used to clear a `HashMap` - --> tests/ui/clear_with_drain.rs:335:9 + --> tests/ui/clear_with_drain.rs:354:9 | LL | map.drain(); | ^^^^^^^ help: try: `clear()` error: `drain` used to clear a `BinaryHeap` - --> tests/ui/clear_with_drain.rs:354:10 + --> tests/ui/clear_with_drain.rs:374:10 | LL | heap.drain(); | ^^^^^^^ help: try: `clear()` diff --git a/tests/ui/clone_on_copy.fixed b/tests/ui/clone_on_copy.fixed index 9d9a5bf20f43..2dd8af152515 100644 --- a/tests/ui/clone_on_copy.fixed +++ b/tests/ui/clone_on_copy.fixed @@ -21,16 +21,20 @@ fn is_ascii(ch: char) -> bool { fn clone_on_copy() -> Option<(i32)> { 42; + //~^ clone_on_copy vec![1].clone(); // ok, not a Copy type Some(vec![1]).clone(); // ok, not a Copy type *(&42); + //~^ clone_on_copy let rc = RefCell::new(0); *rc.borrow(); + //~^ clone_on_copy let x = 0u32; x.rotate_left(1); + //~^ clone_on_copy #[derive(Clone, Copy)] struct Foo; @@ -45,6 +49,7 @@ fn clone_on_copy() -> Option<(i32)> { ($e:expr) => {{ $e }}; } m!(42); + //~^ clone_on_copy struct Wrap([u32; 2]); impl core::ops::Deref for Wrap { @@ -55,6 +60,7 @@ fn clone_on_copy() -> Option<(i32)> { } let x = Wrap([0, 0]); (*x)[0]; + //~^ clone_on_copy let x = 42; let ref y = x.clone(); // ok, binds by reference @@ -65,13 +71,17 @@ fn clone_on_copy() -> Option<(i32)> { let _ = &x.clone(); // ok, getting a ref 'a'.clone().make_ascii_uppercase(); // ok, clone and then mutate is_ascii('z'); + //~^ clone_on_copy // Issue #5436 let mut vec = Vec::new(); vec.push(42); + //~^ clone_on_copy // Issue #9277 let opt: &Option = &None; let value = (*opt)?; // operator precedence needed (*opt)? + // + //~^^ clone_on_copy None } diff --git a/tests/ui/clone_on_copy.rs b/tests/ui/clone_on_copy.rs index 305bc6816e1b..a371afb04a78 100644 --- a/tests/ui/clone_on_copy.rs +++ b/tests/ui/clone_on_copy.rs @@ -21,16 +21,20 @@ fn is_ascii(ch: char) -> bool { fn clone_on_copy() -> Option<(i32)> { 42.clone(); + //~^ clone_on_copy vec![1].clone(); // ok, not a Copy type Some(vec![1]).clone(); // ok, not a Copy type (&42).clone(); + //~^ clone_on_copy let rc = RefCell::new(0); rc.borrow().clone(); + //~^ clone_on_copy let x = 0u32; x.clone().rotate_left(1); + //~^ clone_on_copy #[derive(Clone, Copy)] struct Foo; @@ -45,6 +49,7 @@ fn clone_on_copy() -> Option<(i32)> { ($e:expr) => {{ $e }}; } m!(42).clone(); + //~^ clone_on_copy struct Wrap([u32; 2]); impl core::ops::Deref for Wrap { @@ -55,6 +60,7 @@ fn clone_on_copy() -> Option<(i32)> { } let x = Wrap([0, 0]); x.clone()[0]; + //~^ clone_on_copy let x = 42; let ref y = x.clone(); // ok, binds by reference @@ -65,13 +71,17 @@ fn clone_on_copy() -> Option<(i32)> { let _ = &x.clone(); // ok, getting a ref 'a'.clone().make_ascii_uppercase(); // ok, clone and then mutate is_ascii('z'.clone()); + //~^ clone_on_copy // Issue #5436 let mut vec = Vec::new(); vec.push(42.clone()); + //~^ clone_on_copy // Issue #9277 let opt: &Option = &None; let value = opt.clone()?; // operator precedence needed (*opt)? + // + //~^^ clone_on_copy None } diff --git a/tests/ui/clone_on_copy.stderr b/tests/ui/clone_on_copy.stderr index 314fd13afca4..92cdd635d20a 100644 --- a/tests/ui/clone_on_copy.stderr +++ b/tests/ui/clone_on_copy.stderr @@ -8,49 +8,49 @@ LL | 42.clone(); = help: to override `-D warnings` add `#[allow(clippy::clone_on_copy)]` error: using `clone` on type `i32` which implements the `Copy` trait - --> tests/ui/clone_on_copy.rs:27:5 + --> tests/ui/clone_on_copy.rs:28:5 | LL | (&42).clone(); | ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)` error: using `clone` on type `i32` which implements the `Copy` trait - --> tests/ui/clone_on_copy.rs:30:5 + --> tests/ui/clone_on_copy.rs:32:5 | LL | rc.borrow().clone(); | ^^^^^^^^^^^^^^^^^^^ help: try dereferencing it: `*rc.borrow()` error: using `clone` on type `u32` which implements the `Copy` trait - --> tests/ui/clone_on_copy.rs:33:5 + --> tests/ui/clone_on_copy.rs:36:5 | LL | x.clone().rotate_left(1); | ^^^^^^^^^ help: try removing the `clone` call: `x` error: using `clone` on type `i32` which implements the `Copy` trait - --> tests/ui/clone_on_copy.rs:47:5 + --> tests/ui/clone_on_copy.rs:51:5 | LL | m!(42).clone(); | ^^^^^^^^^^^^^^ help: try removing the `clone` call: `m!(42)` error: using `clone` on type `[u32; 2]` which implements the `Copy` trait - --> tests/ui/clone_on_copy.rs:57:5 + --> tests/ui/clone_on_copy.rs:62:5 | LL | x.clone()[0]; | ^^^^^^^^^ help: try dereferencing it: `(*x)` error: using `clone` on type `char` which implements the `Copy` trait - --> tests/ui/clone_on_copy.rs:67:14 + --> tests/ui/clone_on_copy.rs:73:14 | LL | is_ascii('z'.clone()); | ^^^^^^^^^^^ help: try removing the `clone` call: `'z'` error: using `clone` on type `i32` which implements the `Copy` trait - --> tests/ui/clone_on_copy.rs:71:14 + --> tests/ui/clone_on_copy.rs:78:14 | LL | vec.push(42.clone()); | ^^^^^^^^^^ help: try removing the `clone` call: `42` error: using `clone` on type `Option` which implements the `Copy` trait - --> tests/ui/clone_on_copy.rs:75:17 + --> tests/ui/clone_on_copy.rs:83:17 | LL | let value = opt.clone()?; // operator precedence needed (*opt)? | ^^^^^^^^^^^ help: try dereferencing it: `(*opt)` diff --git a/tests/ui/clone_on_copy_impl.rs b/tests/ui/clone_on_copy_impl.rs index 2d03544ad8b6..33375aead4d5 100644 --- a/tests/ui/clone_on_copy_impl.rs +++ b/tests/ui/clone_on_copy_impl.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(clippy::non_canonical_clone_impl)] use std::fmt; diff --git a/tests/ui/cloned_instead_of_copied.fixed b/tests/ui/cloned_instead_of_copied.fixed index bc939bb3dbb9..0a1a59ddf9b8 100644 --- a/tests/ui/cloned_instead_of_copied.fixed +++ b/tests/ui/cloned_instead_of_copied.fixed @@ -5,10 +5,15 @@ fn main() { // yay let _ = [1].iter().copied(); + //~^ cloned_instead_of_copied let _ = vec!["hi"].iter().copied(); + //~^ cloned_instead_of_copied let _ = Some(&1).copied(); + //~^ cloned_instead_of_copied let _ = Box::new([1].iter()).copied(); + //~^ cloned_instead_of_copied let _ = Box::new(Some(&1)).copied(); + //~^ cloned_instead_of_copied // nay let _ = [String::new()].iter().cloned(); @@ -25,10 +30,15 @@ fn msrv_1_34() { fn msrv_1_35() { let _ = [1].iter().cloned(); let _ = Some(&1).copied(); // Option::copied needs 1.35 + // + //~^^ cloned_instead_of_copied } #[clippy::msrv = "1.36"] fn msrv_1_36() { let _ = [1].iter().copied(); // Iterator::copied needs 1.36 + // + //~^^ cloned_instead_of_copied let _ = Some(&1).copied(); + //~^ cloned_instead_of_copied } diff --git a/tests/ui/cloned_instead_of_copied.rs b/tests/ui/cloned_instead_of_copied.rs index 27346adbfbf1..c452dd007a1e 100644 --- a/tests/ui/cloned_instead_of_copied.rs +++ b/tests/ui/cloned_instead_of_copied.rs @@ -5,10 +5,15 @@ fn main() { // yay let _ = [1].iter().cloned(); + //~^ cloned_instead_of_copied let _ = vec!["hi"].iter().cloned(); + //~^ cloned_instead_of_copied let _ = Some(&1).cloned(); + //~^ cloned_instead_of_copied let _ = Box::new([1].iter()).cloned(); + //~^ cloned_instead_of_copied let _ = Box::new(Some(&1)).cloned(); + //~^ cloned_instead_of_copied // nay let _ = [String::new()].iter().cloned(); @@ -25,10 +30,15 @@ fn msrv_1_34() { fn msrv_1_35() { let _ = [1].iter().cloned(); let _ = Some(&1).cloned(); // Option::copied needs 1.35 + // + //~^^ cloned_instead_of_copied } #[clippy::msrv = "1.36"] fn msrv_1_36() { let _ = [1].iter().cloned(); // Iterator::copied needs 1.36 + // + //~^^ cloned_instead_of_copied let _ = Some(&1).cloned(); + //~^ cloned_instead_of_copied } diff --git a/tests/ui/cloned_instead_of_copied.stderr b/tests/ui/cloned_instead_of_copied.stderr index ad857c4ef7d0..bd741e41321b 100644 --- a/tests/ui/cloned_instead_of_copied.stderr +++ b/tests/ui/cloned_instead_of_copied.stderr @@ -8,43 +8,43 @@ LL | let _ = [1].iter().cloned(); = help: to override `-D warnings` add `#[allow(clippy::cloned_instead_of_copied)]` error: used `cloned` where `copied` could be used instead - --> tests/ui/cloned_instead_of_copied.rs:8:31 + --> tests/ui/cloned_instead_of_copied.rs:9:31 | LL | let _ = vec!["hi"].iter().cloned(); | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> tests/ui/cloned_instead_of_copied.rs:9:22 + --> tests/ui/cloned_instead_of_copied.rs:11:22 | LL | let _ = Some(&1).cloned(); | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> tests/ui/cloned_instead_of_copied.rs:10:34 + --> tests/ui/cloned_instead_of_copied.rs:13:34 | LL | let _ = Box::new([1].iter()).cloned(); | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> tests/ui/cloned_instead_of_copied.rs:11:32 + --> tests/ui/cloned_instead_of_copied.rs:15:32 | LL | let _ = Box::new(Some(&1)).cloned(); | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> tests/ui/cloned_instead_of_copied.rs:27:22 + --> tests/ui/cloned_instead_of_copied.rs:32:22 | LL | let _ = Some(&1).cloned(); // Option::copied needs 1.35 | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> tests/ui/cloned_instead_of_copied.rs:32:24 + --> tests/ui/cloned_instead_of_copied.rs:39:24 | LL | let _ = [1].iter().cloned(); // Iterator::copied needs 1.36 | ^^^^^^ help: try: `copied` error: used `cloned` where `copied` could be used instead - --> tests/ui/cloned_instead_of_copied.rs:33:22 + --> tests/ui/cloned_instead_of_copied.rs:42:22 | LL | let _ = Some(&1).cloned(); | ^^^^^^ help: try: `copied` diff --git a/tests/ui/cmp_null.fixed b/tests/ui/cmp_null.fixed index e5ab765bc861..140ddb10aeb8 100644 --- a/tests/ui/cmp_null.fixed +++ b/tests/ui/cmp_null.fixed @@ -7,26 +7,29 @@ fn main() { let x = 0; let p: *const usize = &x; if p.is_null() { - //~^ ERROR: comparing with null is better expressed by the `.is_null()` method - //~| NOTE: `-D clippy::cmp-null` implied by `-D warnings` + //~^ cmp_null + println!("This is surprising!"); } if p.is_null() { - //~^ ERROR: comparing with null is better expressed by the `.is_null()` method + //~^ cmp_null + println!("This is surprising!"); } let mut y = 0; let mut m: *mut usize = &mut y; if m.is_null() { - //~^ ERROR: comparing with null is better expressed by the `.is_null()` method + //~^ cmp_null + println!("This is surprising, too!"); } if m.is_null() { - //~^ ERROR: comparing with null is better expressed by the `.is_null()` method + //~^ cmp_null + println!("This is surprising, too!"); } let _ = (x as *const ()).is_null(); - //~^ ERROR: comparing with null is better expressed by the `.is_null()` method + //~^ cmp_null } diff --git a/tests/ui/cmp_null.rs b/tests/ui/cmp_null.rs index 257f7ba26627..16ed17765dac 100644 --- a/tests/ui/cmp_null.rs +++ b/tests/ui/cmp_null.rs @@ -7,26 +7,29 @@ fn main() { let x = 0; let p: *const usize = &x; if p == ptr::null() { - //~^ ERROR: comparing with null is better expressed by the `.is_null()` method - //~| NOTE: `-D clippy::cmp-null` implied by `-D warnings` + //~^ cmp_null + println!("This is surprising!"); } if ptr::null() == p { - //~^ ERROR: comparing with null is better expressed by the `.is_null()` method + //~^ cmp_null + println!("This is surprising!"); } let mut y = 0; let mut m: *mut usize = &mut y; if m == ptr::null_mut() { - //~^ ERROR: comparing with null is better expressed by the `.is_null()` method + //~^ cmp_null + println!("This is surprising, too!"); } if ptr::null_mut() == m { - //~^ ERROR: comparing with null is better expressed by the `.is_null()` method + //~^ cmp_null + println!("This is surprising, too!"); } let _ = x as *const () == ptr::null(); - //~^ ERROR: comparing with null is better expressed by the `.is_null()` method + //~^ cmp_null } diff --git a/tests/ui/cmp_null.stderr b/tests/ui/cmp_null.stderr index f3b35f3afba8..6821846d0466 100644 --- a/tests/ui/cmp_null.stderr +++ b/tests/ui/cmp_null.stderr @@ -14,19 +14,19 @@ LL | if ptr::null() == p { | ^^^^^^^^^^^^^^^^ help: try: `p.is_null()` error: comparing with null is better expressed by the `.is_null()` method - --> tests/ui/cmp_null.rs:21:8 + --> tests/ui/cmp_null.rs:22:8 | LL | if m == ptr::null_mut() { | ^^^^^^^^^^^^^^^^^^^^ help: try: `m.is_null()` error: comparing with null is better expressed by the `.is_null()` method - --> tests/ui/cmp_null.rs:25:8 + --> tests/ui/cmp_null.rs:27:8 | LL | if ptr::null_mut() == m { | ^^^^^^^^^^^^^^^^^^^^ help: try: `m.is_null()` error: comparing with null is better expressed by the `.is_null()` method - --> tests/ui/cmp_null.rs:30:13 + --> tests/ui/cmp_null.rs:33:13 | LL | let _ = x as *const () == ptr::null(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(x as *const ()).is_null()` diff --git a/tests/ui/cmp_owned/asymmetric_partial_eq.fixed b/tests/ui/cmp_owned/asymmetric_partial_eq.fixed index 9fc70ab6f4a0..8d543b042200 100644 --- a/tests/ui/cmp_owned/asymmetric_partial_eq.fixed +++ b/tests/ui/cmp_owned/asymmetric_partial_eq.fixed @@ -44,7 +44,9 @@ mod borrowed_eq_owned { let borrowed = Borrowed {}; if borrowed == owned {} + //~^ cmp_owned if borrowed == owned {} + //~^ cmp_owned } } @@ -63,7 +65,9 @@ mod owned_eq_borrowed { let borrowed = Borrowed {}; if owned == borrowed {} + //~^ cmp_owned if owned == borrowed {} + //~^ cmp_owned } } @@ -90,7 +94,9 @@ mod issue_4874 { let borrowed = Borrowed {}; if borrowed == "Hi" {} + //~^ cmp_owned if borrowed == "Hi" {} + //~^ cmp_owned } } diff --git a/tests/ui/cmp_owned/asymmetric_partial_eq.rs b/tests/ui/cmp_owned/asymmetric_partial_eq.rs index 5cd43ea1d411..6da311c50ee7 100644 --- a/tests/ui/cmp_owned/asymmetric_partial_eq.rs +++ b/tests/ui/cmp_owned/asymmetric_partial_eq.rs @@ -44,7 +44,9 @@ mod borrowed_eq_owned { let borrowed = Borrowed {}; if borrowed.to_owned() == owned {} + //~^ cmp_owned if owned == borrowed.to_owned() {} + //~^ cmp_owned } } @@ -63,7 +65,9 @@ mod owned_eq_borrowed { let borrowed = Borrowed {}; if owned == borrowed.to_owned() {} + //~^ cmp_owned if borrowed.to_owned() == owned {} + //~^ cmp_owned } } @@ -90,7 +94,9 @@ mod issue_4874 { let borrowed = Borrowed {}; if "Hi" == borrowed.to_string() {} + //~^ cmp_owned if borrowed.to_string() == "Hi" {} + //~^ cmp_owned } } diff --git a/tests/ui/cmp_owned/asymmetric_partial_eq.stderr b/tests/ui/cmp_owned/asymmetric_partial_eq.stderr index e230d5f06bb0..1d2645d358f3 100644 --- a/tests/ui/cmp_owned/asymmetric_partial_eq.stderr +++ b/tests/ui/cmp_owned/asymmetric_partial_eq.stderr @@ -8,7 +8,7 @@ LL | if borrowed.to_owned() == owned {} = help: to override `-D warnings` add `#[allow(clippy::cmp_owned)]` error: this creates an owned instance just for comparison - --> tests/ui/cmp_owned/asymmetric_partial_eq.rs:47:21 + --> tests/ui/cmp_owned/asymmetric_partial_eq.rs:48:21 | LL | if owned == borrowed.to_owned() {} | ---------^^^^^^^^^^^^^^^^^^^ @@ -16,13 +16,13 @@ LL | if owned == borrowed.to_owned() {} | help: try: `borrowed == owned` error: this creates an owned instance just for comparison - --> tests/ui/cmp_owned/asymmetric_partial_eq.rs:65:21 + --> tests/ui/cmp_owned/asymmetric_partial_eq.rs:67:21 | LL | if owned == borrowed.to_owned() {} | ^^^^^^^^^^^^^^^^^^^ help: try: `borrowed` error: this creates an owned instance just for comparison - --> tests/ui/cmp_owned/asymmetric_partial_eq.rs:66:12 + --> tests/ui/cmp_owned/asymmetric_partial_eq.rs:69:12 | LL | if borrowed.to_owned() == owned {} | ^^^^^^^^^^^^^^^^^^^--------- @@ -30,7 +30,7 @@ LL | if borrowed.to_owned() == owned {} | help: try: `owned == borrowed` error: this creates an owned instance just for comparison - --> tests/ui/cmp_owned/asymmetric_partial_eq.rs:92:20 + --> tests/ui/cmp_owned/asymmetric_partial_eq.rs:96:20 | LL | if "Hi" == borrowed.to_string() {} | --------^^^^^^^^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ LL | if "Hi" == borrowed.to_string() {} | help: try: `borrowed == "Hi"` error: this creates an owned instance just for comparison - --> tests/ui/cmp_owned/asymmetric_partial_eq.rs:93:12 + --> tests/ui/cmp_owned/asymmetric_partial_eq.rs:98:12 | LL | if borrowed.to_string() == "Hi" {} | ^^^^^^^^^^^^^^^^^^^^ help: try: `borrowed` diff --git a/tests/ui/cmp_owned/comparison_flip.fixed b/tests/ui/cmp_owned/comparison_flip.fixed index 40d7b5e49fcd..711fbca1c8d2 100644 --- a/tests/ui/cmp_owned/comparison_flip.fixed +++ b/tests/ui/cmp_owned/comparison_flip.fixed @@ -4,10 +4,12 @@ fn main() { let a = Foo; if a != "bar" { + //~^ cmp_owned println!("foo"); } if a != "bar" { + //~^ cmp_owned println!("foo"); } } diff --git a/tests/ui/cmp_owned/comparison_flip.rs b/tests/ui/cmp_owned/comparison_flip.rs index 59a945668b2e..ce86bb3f7b5c 100644 --- a/tests/ui/cmp_owned/comparison_flip.rs +++ b/tests/ui/cmp_owned/comparison_flip.rs @@ -4,10 +4,12 @@ fn main() { let a = Foo; if a.to_string() != "bar" { + //~^ cmp_owned println!("foo"); } if "bar" != a.to_string() { + //~^ cmp_owned println!("foo"); } } diff --git a/tests/ui/cmp_owned/comparison_flip.stderr b/tests/ui/cmp_owned/comparison_flip.stderr index cfb6978158b3..ca571837039d 100644 --- a/tests/ui/cmp_owned/comparison_flip.stderr +++ b/tests/ui/cmp_owned/comparison_flip.stderr @@ -8,7 +8,7 @@ LL | if a.to_string() != "bar" { = help: to override `-D warnings` add `#[allow(clippy::cmp_owned)]` error: this creates an owned instance just for comparison - --> tests/ui/cmp_owned/comparison_flip.rs:10:17 + --> tests/ui/cmp_owned/comparison_flip.rs:11:17 | LL | if "bar" != a.to_string() { | ---------^^^^^^^^^^^^^ diff --git a/tests/ui/cmp_owned/with_suggestion.fixed b/tests/ui/cmp_owned/with_suggestion.fixed index ab72e096cc7c..eb01633a25fd 100644 --- a/tests/ui/cmp_owned/with_suggestion.fixed +++ b/tests/ui/cmp_owned/with_suggestion.fixed @@ -3,8 +3,10 @@ fn main() { fn with_to_string(x: &str) { x != "foo"; + //~^ cmp_owned "foo" != x; + //~^ cmp_owned } let x = "oh"; @@ -12,14 +14,18 @@ fn main() { with_to_string(x); x != "foo"; + //~^ cmp_owned x != "foo"; + //~^ cmp_owned 42.to_string() == "42"; Foo == Foo; + //~^ cmp_owned "abc".chars().filter(|c| *c != 'X'); + //~^ cmp_owned "abc".chars().filter(|c| *c != 'X'); } diff --git a/tests/ui/cmp_owned/with_suggestion.rs b/tests/ui/cmp_owned/with_suggestion.rs index cb5268734d32..82409f27b129 100644 --- a/tests/ui/cmp_owned/with_suggestion.rs +++ b/tests/ui/cmp_owned/with_suggestion.rs @@ -3,8 +3,10 @@ fn main() { fn with_to_string(x: &str) { x != "foo".to_string(); + //~^ cmp_owned "foo".to_string() != x; + //~^ cmp_owned } let x = "oh"; @@ -12,14 +14,18 @@ fn main() { with_to_string(x); x != "foo".to_owned(); + //~^ cmp_owned x != String::from("foo"); + //~^ cmp_owned 42.to_string() == "42"; Foo.to_owned() == Foo; + //~^ cmp_owned "abc".chars().filter(|c| c.to_owned() != 'X'); + //~^ cmp_owned "abc".chars().filter(|c| *c != 'X'); } diff --git a/tests/ui/cmp_owned/with_suggestion.stderr b/tests/ui/cmp_owned/with_suggestion.stderr index 41448e012003..ca2ab4484727 100644 --- a/tests/ui/cmp_owned/with_suggestion.stderr +++ b/tests/ui/cmp_owned/with_suggestion.stderr @@ -8,31 +8,31 @@ LL | x != "foo".to_string(); = help: to override `-D warnings` add `#[allow(clippy::cmp_owned)]` error: this creates an owned instance just for comparison - --> tests/ui/cmp_owned/with_suggestion.rs:7:9 + --> tests/ui/cmp_owned/with_suggestion.rs:8:9 | LL | "foo".to_string() != x; | ^^^^^^^^^^^^^^^^^ help: try: `"foo"` error: this creates an owned instance just for comparison - --> tests/ui/cmp_owned/with_suggestion.rs:14:10 + --> tests/ui/cmp_owned/with_suggestion.rs:16:10 | LL | x != "foo".to_owned(); | ^^^^^^^^^^^^^^^^ help: try: `"foo"` error: this creates an owned instance just for comparison - --> tests/ui/cmp_owned/with_suggestion.rs:16:10 + --> tests/ui/cmp_owned/with_suggestion.rs:19:10 | LL | x != String::from("foo"); | ^^^^^^^^^^^^^^^^^^^ help: try: `"foo"` error: this creates an owned instance just for comparison - --> tests/ui/cmp_owned/with_suggestion.rs:20:5 + --> tests/ui/cmp_owned/with_suggestion.rs:24:5 | LL | Foo.to_owned() == Foo; | ^^^^^^^^^^^^^^ help: try: `Foo` error: this creates an owned instance just for comparison - --> tests/ui/cmp_owned/with_suggestion.rs:22:30 + --> tests/ui/cmp_owned/with_suggestion.rs:27:30 | LL | "abc".chars().filter(|c| c.to_owned() != 'X'); | ^^^^^^^^^^^^ help: try: `*c` diff --git a/tests/ui/cmp_owned/without_suggestion.rs b/tests/ui/cmp_owned/without_suggestion.rs index 913aab727471..4e14c3054d9f 100644 --- a/tests/ui/cmp_owned/without_suggestion.rs +++ b/tests/ui/cmp_owned/without_suggestion.rs @@ -5,13 +5,12 @@ fn main() { let x = &Baz; let y = &Baz; y.to_owned() == *x; - //~^ ERROR: this creates an owned instance just for comparison - //~| NOTE: `-D clippy::cmp-owned` implied by `-D warnings` + //~^ cmp_owned let x = &&Baz; let y = &Baz; y.to_owned() == **x; - //~^ ERROR: this creates an owned instance just for comparison + //~^ cmp_owned let x = 0u32; let y = U32Wrapper(x); @@ -23,7 +22,7 @@ struct Foo; impl PartialEq for Foo { fn eq(&self, other: &Self) -> bool { self.to_owned() == *other - //~^ ERROR: this creates an owned instance just for comparison + //~^ cmp_owned } } diff --git a/tests/ui/cmp_owned/without_suggestion.stderr b/tests/ui/cmp_owned/without_suggestion.stderr index 13ca699b9fd3..c8e2efab4915 100644 --- a/tests/ui/cmp_owned/without_suggestion.stderr +++ b/tests/ui/cmp_owned/without_suggestion.stderr @@ -8,13 +8,13 @@ LL | y.to_owned() == *x; = help: to override `-D warnings` add `#[allow(clippy::cmp_owned)]` error: this creates an owned instance just for comparison - --> tests/ui/cmp_owned/without_suggestion.rs:13:5 + --> tests/ui/cmp_owned/without_suggestion.rs:12:5 | LL | y.to_owned() == **x; | ^^^^^^^^^^^^^^^^^^^ try implementing the comparison without allocating error: this creates an owned instance just for comparison - --> tests/ui/cmp_owned/without_suggestion.rs:25:9 + --> tests/ui/cmp_owned/without_suggestion.rs:24:9 | LL | self.to_owned() == *other | ^^^^^^^^^^^^^^^^^^^^^^^^^ try implementing the comparison without allocating diff --git a/tests/ui/cognitive_complexity.rs b/tests/ui/cognitive_complexity.rs index e8fd063a98f2..2dbec955f63f 100644 --- a/tests/ui/cognitive_complexity.rs +++ b/tests/ui/cognitive_complexity.rs @@ -4,7 +4,8 @@ #[rustfmt::skip] fn main() { -//~^ ERROR: the function has a cognitive complexity of (28/25) +//~^ cognitive_complexity + if true { println!("a"); } @@ -90,7 +91,8 @@ fn main() { #[clippy::cognitive_complexity = "1"] fn kaboom() { - //~^ ERROR: the function has a cognitive complexity of (7/1) + //~^ cognitive_complexity + let n = 0; 'a: for i in 0..20 { 'b: for j in i..20 { @@ -149,9 +151,10 @@ fn lots_of_short_circuits2() -> bool { #[clippy::cognitive_complexity = "1"] fn baa() { - //~^ ERROR: the function has a cognitive complexity of (2/1) + //~^ cognitive_complexity + let x = || match 99 { - //~^ ERROR: the function has a cognitive complexity of (2/1) + //~^ cognitive_complexity 0 => 0, 1 => 1, 2 => 2, @@ -169,7 +172,8 @@ fn baa() { #[clippy::cognitive_complexity = "1"] fn bar() { - //~^ ERROR: the function has a cognitive complexity of (2/1) + //~^ cognitive_complexity + match 99 { 0 => println!("hi"), _ => println!("bye"), @@ -181,7 +185,8 @@ fn bar() { /// Tests are usually complex but simple at the same time. `clippy::cognitive_complexity` used to /// give lots of false-positives in tests. fn dont_warn_on_tests() { - //~^ ERROR: the function has a cognitive complexity of (2/1) + //~^ cognitive_complexity + match 99 { 0 => println!("hi"), _ => println!("bye"), @@ -190,7 +195,8 @@ fn dont_warn_on_tests() { #[clippy::cognitive_complexity = "1"] fn barr() { - //~^ ERROR: the function has a cognitive complexity of (2/1) + //~^ cognitive_complexity + match 99 { 0 => println!("hi"), 1 => println!("bla"), @@ -201,7 +207,8 @@ fn barr() { #[clippy::cognitive_complexity = "1"] fn barr2() { - //~^ ERROR: the function has a cognitive complexity of (3/1) + //~^ cognitive_complexity + match 99 { 0 => println!("hi"), 1 => println!("bla"), @@ -218,7 +225,8 @@ fn barr2() { #[clippy::cognitive_complexity = "1"] fn barrr() { - //~^ ERROR: the function has a cognitive complexity of (2/1) + //~^ cognitive_complexity + match 99 { 0 => println!("hi"), 1 => panic!("bla"), @@ -229,7 +237,8 @@ fn barrr() { #[clippy::cognitive_complexity = "1"] fn barrr2() { - //~^ ERROR: the function has a cognitive complexity of (3/1) + //~^ cognitive_complexity + match 99 { 0 => println!("hi"), 1 => panic!("bla"), @@ -246,7 +255,8 @@ fn barrr2() { #[clippy::cognitive_complexity = "1"] fn barrrr() { - //~^ ERROR: the function has a cognitive complexity of (2/1) + //~^ cognitive_complexity + match 99 { 0 => println!("hi"), 1 => println!("bla"), @@ -257,7 +267,8 @@ fn barrrr() { #[clippy::cognitive_complexity = "1"] fn barrrr2() { - //~^ ERROR: the function has a cognitive complexity of (3/1) + //~^ cognitive_complexity + match 99 { 0 => println!("hi"), 1 => println!("bla"), @@ -274,7 +285,8 @@ fn barrrr2() { #[clippy::cognitive_complexity = "1"] fn cake() { - //~^ ERROR: the function has a cognitive complexity of (2/1) + //~^ cognitive_complexity + if 4 == 5 { println!("yea"); } else { @@ -285,7 +297,8 @@ fn cake() { #[clippy::cognitive_complexity = "1"] pub fn read_file(input_path: &str) -> String { - //~^ ERROR: the function has a cognitive complexity of (4/1) + //~^ cognitive_complexity + use std::fs::File; use std::io::{Read, Write}; use std::path::Path; @@ -317,7 +330,8 @@ enum Void {} #[clippy::cognitive_complexity = "1"] fn void(void: Void) { - //~^ ERROR: the function has a cognitive complexity of (2/1) + //~^ cognitive_complexity + if true { match void {} } @@ -369,7 +383,8 @@ fn early() -> Result { #[rustfmt::skip] #[clippy::cognitive_complexity = "1"] fn early_ret() -> i32 { -//~^ ERROR: the function has a cognitive complexity of (8/1) +//~^ cognitive_complexity + let a = if true { 42 } else { return 0; }; let a = if a < 99 { 42 } else { return 0; }; let a = if a < 99 { 42 } else { return 0; }; @@ -391,7 +406,8 @@ fn early_ret() -> i32 { #[clippy::cognitive_complexity = "1"] fn closures() { let x = |a: i32, b: i32| -> i32 { - //~^ ERROR: the function has a cognitive complexity of (2/1) + //~^ cognitive_complexity + if true { println!("moo"); } @@ -405,7 +421,8 @@ struct Moo; #[clippy::cognitive_complexity = "1"] impl Moo { fn moo(&self) { - //~^ ERROR: the function has a cognitive complexity of (2/1) + //~^ cognitive_complexity + if true { println!("moo"); } @@ -415,7 +432,8 @@ impl Moo { #[clippy::cognitive_complexity = "1"] mod issue9300 { async fn a() { - //~^ ERROR: the function has a cognitive complexity of (2/1) + //~^ cognitive_complexity + let a = 0; if a == 0 {} } @@ -423,7 +441,8 @@ mod issue9300 { pub struct S; impl S { pub async fn async_method() { - //~^ ERROR: the function has a cognitive complexity of (2/1) + //~^ cognitive_complexity + let a = 0; if a == 0 {} } diff --git a/tests/ui/cognitive_complexity.stderr b/tests/ui/cognitive_complexity.stderr index 1e60247e5f58..52607b87c60e 100644 --- a/tests/ui/cognitive_complexity.stderr +++ b/tests/ui/cognitive_complexity.stderr @@ -9,7 +9,7 @@ LL | fn main() { = help: to override `-D warnings` add `#[allow(clippy::cognitive_complexity)]` error: the function has a cognitive complexity of (7/1) - --> tests/ui/cognitive_complexity.rs:92:4 + --> tests/ui/cognitive_complexity.rs:93:4 | LL | fn kaboom() { | ^^^^^^ @@ -17,7 +17,7 @@ LL | fn kaboom() { = help: you could split it up into multiple smaller functions error: the function has a cognitive complexity of (2/1) - --> tests/ui/cognitive_complexity.rs:151:4 + --> tests/ui/cognitive_complexity.rs:153:4 | LL | fn baa() { | ^^^ @@ -25,7 +25,7 @@ LL | fn baa() { = help: you could split it up into multiple smaller functions error: the function has a cognitive complexity of (2/1) - --> tests/ui/cognitive_complexity.rs:153:13 + --> tests/ui/cognitive_complexity.rs:156:13 | LL | let x = || match 99 { | ^^ @@ -33,7 +33,7 @@ LL | let x = || match 99 { = help: you could split it up into multiple smaller functions error: the function has a cognitive complexity of (2/1) - --> tests/ui/cognitive_complexity.rs:171:4 + --> tests/ui/cognitive_complexity.rs:174:4 | LL | fn bar() { | ^^^ @@ -41,7 +41,7 @@ LL | fn bar() { = help: you could split it up into multiple smaller functions error: the function has a cognitive complexity of (2/1) - --> tests/ui/cognitive_complexity.rs:183:4 + --> tests/ui/cognitive_complexity.rs:187:4 | LL | fn dont_warn_on_tests() { | ^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | fn dont_warn_on_tests() { = help: you could split it up into multiple smaller functions error: the function has a cognitive complexity of (2/1) - --> tests/ui/cognitive_complexity.rs:192:4 + --> tests/ui/cognitive_complexity.rs:197:4 | LL | fn barr() { | ^^^^ @@ -57,7 +57,7 @@ LL | fn barr() { = help: you could split it up into multiple smaller functions error: the function has a cognitive complexity of (3/1) - --> tests/ui/cognitive_complexity.rs:203:4 + --> tests/ui/cognitive_complexity.rs:209:4 | LL | fn barr2() { | ^^^^^ @@ -65,7 +65,7 @@ LL | fn barr2() { = help: you could split it up into multiple smaller functions error: the function has a cognitive complexity of (2/1) - --> tests/ui/cognitive_complexity.rs:220:4 + --> tests/ui/cognitive_complexity.rs:227:4 | LL | fn barrr() { | ^^^^^ @@ -73,7 +73,7 @@ LL | fn barrr() { = help: you could split it up into multiple smaller functions error: the function has a cognitive complexity of (3/1) - --> tests/ui/cognitive_complexity.rs:231:4 + --> tests/ui/cognitive_complexity.rs:239:4 | LL | fn barrr2() { | ^^^^^^ @@ -81,7 +81,7 @@ LL | fn barrr2() { = help: you could split it up into multiple smaller functions error: the function has a cognitive complexity of (2/1) - --> tests/ui/cognitive_complexity.rs:248:4 + --> tests/ui/cognitive_complexity.rs:257:4 | LL | fn barrrr() { | ^^^^^^ @@ -89,7 +89,7 @@ LL | fn barrrr() { = help: you could split it up into multiple smaller functions error: the function has a cognitive complexity of (3/1) - --> tests/ui/cognitive_complexity.rs:259:4 + --> tests/ui/cognitive_complexity.rs:269:4 | LL | fn barrrr2() { | ^^^^^^^ @@ -97,7 +97,7 @@ LL | fn barrrr2() { = help: you could split it up into multiple smaller functions error: the function has a cognitive complexity of (2/1) - --> tests/ui/cognitive_complexity.rs:276:4 + --> tests/ui/cognitive_complexity.rs:287:4 | LL | fn cake() { | ^^^^ @@ -105,7 +105,7 @@ LL | fn cake() { = help: you could split it up into multiple smaller functions error: the function has a cognitive complexity of (4/1) - --> tests/ui/cognitive_complexity.rs:287:8 + --> tests/ui/cognitive_complexity.rs:299:8 | LL | pub fn read_file(input_path: &str) -> String { | ^^^^^^^^^ @@ -113,7 +113,7 @@ LL | pub fn read_file(input_path: &str) -> String { = help: you could split it up into multiple smaller functions error: the function has a cognitive complexity of (2/1) - --> tests/ui/cognitive_complexity.rs:319:4 + --> tests/ui/cognitive_complexity.rs:332:4 | LL | fn void(void: Void) { | ^^^^ @@ -121,7 +121,7 @@ LL | fn void(void: Void) { = help: you could split it up into multiple smaller functions error: the function has a cognitive complexity of (8/1) - --> tests/ui/cognitive_complexity.rs:371:4 + --> tests/ui/cognitive_complexity.rs:385:4 | LL | fn early_ret() -> i32 { | ^^^^^^^^^ @@ -129,7 +129,7 @@ LL | fn early_ret() -> i32 { = help: you could split it up into multiple smaller functions error: the function has a cognitive complexity of (2/1) - --> tests/ui/cognitive_complexity.rs:393:13 + --> tests/ui/cognitive_complexity.rs:408:13 | LL | let x = |a: i32, b: i32| -> i32 { | ^^^^^^^^^^^^^^^^ @@ -137,7 +137,7 @@ LL | let x = |a: i32, b: i32| -> i32 { = help: you could split it up into multiple smaller functions error: the function has a cognitive complexity of (2/1) - --> tests/ui/cognitive_complexity.rs:407:8 + --> tests/ui/cognitive_complexity.rs:423:8 | LL | fn moo(&self) { | ^^^ @@ -145,7 +145,7 @@ LL | fn moo(&self) { = help: you could split it up into multiple smaller functions error: the function has a cognitive complexity of (2/1) - --> tests/ui/cognitive_complexity.rs:417:14 + --> tests/ui/cognitive_complexity.rs:434:14 | LL | async fn a() { | ^ @@ -153,7 +153,7 @@ LL | async fn a() { = help: you could split it up into multiple smaller functions error: the function has a cognitive complexity of (2/1) - --> tests/ui/cognitive_complexity.rs:425:22 + --> tests/ui/cognitive_complexity.rs:443:22 | LL | pub async fn async_method() { | ^^^^^^^^^^^^ diff --git a/tests/ui/cognitive_complexity_attr_used.rs b/tests/ui/cognitive_complexity_attr_used.rs index 6f6e89983d2b..a260fdee3cfd 100644 --- a/tests/ui/cognitive_complexity_attr_used.rs +++ b/tests/ui/cognitive_complexity_attr_used.rs @@ -7,7 +7,8 @@ fn main() { #[clippy::cognitive_complexity = "0"] fn kaboom() { - //~^ ERROR: the function has a cognitive complexity of (3/0) + //~^ cognitive_complexity + if 42 == 43 { panic!(); } else if "cake" == "lie" { diff --git a/tests/ui/collapsible_else_if.fixed b/tests/ui/collapsible_else_if.fixed index c2d76146c641..9f530ad670a0 100644 --- a/tests/ui/collapsible_else_if.fixed +++ b/tests/ui/collapsible_else_if.fixed @@ -11,12 +11,14 @@ fn main() { } else if y == "world" { println!("world!") } + //~^^^^^ collapsible_else_if if x == "hello" { print!("Hello "); } else if let Some(42) = Some(42) { println!("world!") } + //~^^^^^ collapsible_else_if if x == "hello" { print!("Hello "); @@ -26,6 +28,7 @@ fn main() { else { println!("!") } + //~^^^^^^^^ collapsible_else_if if x == "hello" { print!("Hello "); @@ -35,6 +38,7 @@ fn main() { else { println!("!") } + //~^^^^^^^^ collapsible_else_if if let Some(42) = Some(42) { print!("Hello "); @@ -44,6 +48,7 @@ fn main() { else { println!("!") } + //~^^^^^^^^ collapsible_else_if if let Some(42) = Some(42) { print!("Hello "); @@ -53,6 +58,7 @@ fn main() { else { println!("!") } + //~^^^^^^^^ collapsible_else_if if let Some(42) = Some(42) { print!("Hello "); @@ -62,6 +68,7 @@ fn main() { else { println!("!") } + //~^^^^^^^^ collapsible_else_if if x == "hello" { print!("Hello "); @@ -77,4 +84,5 @@ fn main() { fn issue_7318() { if true { println!("I've been resolved!") }else if false {} + //~^^^ collapsible_else_if } diff --git a/tests/ui/collapsible_else_if.rs b/tests/ui/collapsible_else_if.rs index 3579e46cd447..2c646cd1d4da 100644 --- a/tests/ui/collapsible_else_if.rs +++ b/tests/ui/collapsible_else_if.rs @@ -13,6 +13,7 @@ fn main() { println!("world!") } } + //~^^^^^ collapsible_else_if if x == "hello" { print!("Hello "); @@ -21,6 +22,7 @@ fn main() { println!("world!") } } + //~^^^^^ collapsible_else_if if x == "hello" { print!("Hello "); @@ -32,6 +34,7 @@ fn main() { println!("!") } } + //~^^^^^^^^ collapsible_else_if if x == "hello" { print!("Hello "); @@ -43,6 +46,7 @@ fn main() { println!("!") } } + //~^^^^^^^^ collapsible_else_if if let Some(42) = Some(42) { print!("Hello "); @@ -54,6 +58,7 @@ fn main() { println!("!") } } + //~^^^^^^^^ collapsible_else_if if let Some(42) = Some(42) { print!("Hello "); @@ -65,6 +70,7 @@ fn main() { println!("!") } } + //~^^^^^^^^ collapsible_else_if if let Some(42) = Some(42) { print!("Hello "); @@ -76,6 +82,7 @@ fn main() { println!("!") } } + //~^^^^^^^^ collapsible_else_if if x == "hello" { print!("Hello "); @@ -93,4 +100,5 @@ fn issue_7318() { }else{ if false {} } + //~^^^ collapsible_else_if } diff --git a/tests/ui/collapsible_else_if.stderr b/tests/ui/collapsible_else_if.stderr index 45566a78bd81..7d80894cadbb 100644 --- a/tests/ui/collapsible_else_if.stderr +++ b/tests/ui/collapsible_else_if.stderr @@ -19,7 +19,7 @@ LL + } | error: this `else { if .. }` block can be collapsed - --> tests/ui/collapsible_else_if.rs:19:12 + --> tests/ui/collapsible_else_if.rs:20:12 | LL | } else { | ____________^ @@ -37,7 +37,7 @@ LL + } | error: this `else { if .. }` block can be collapsed - --> tests/ui/collapsible_else_if.rs:27:12 + --> tests/ui/collapsible_else_if.rs:29:12 | LL | } else { | ____________^ @@ -58,7 +58,7 @@ LL + } | error: this `else { if .. }` block can be collapsed - --> tests/ui/collapsible_else_if.rs:38:12 + --> tests/ui/collapsible_else_if.rs:41:12 | LL | } else { | ____________^ @@ -79,7 +79,7 @@ LL + } | error: this `else { if .. }` block can be collapsed - --> tests/ui/collapsible_else_if.rs:49:12 + --> tests/ui/collapsible_else_if.rs:53:12 | LL | } else { | ____________^ @@ -100,7 +100,7 @@ LL + } | error: this `else { if .. }` block can be collapsed - --> tests/ui/collapsible_else_if.rs:60:12 + --> tests/ui/collapsible_else_if.rs:65:12 | LL | } else { | ____________^ @@ -121,7 +121,7 @@ LL + } | error: this `else { if .. }` block can be collapsed - --> tests/ui/collapsible_else_if.rs:71:12 + --> tests/ui/collapsible_else_if.rs:77:12 | LL | } else { | ____________^ @@ -142,7 +142,7 @@ LL + } | error: this `else { if .. }` block can be collapsed - --> tests/ui/collapsible_else_if.rs:93:10 + --> tests/ui/collapsible_else_if.rs:100:10 | LL | }else{ | __________^ diff --git a/tests/ui/collapsible_if.fixed b/tests/ui/collapsible_if.fixed index 44b0b6e73915..6e994018aef0 100644 --- a/tests/ui/collapsible_if.fixed +++ b/tests/ui/collapsible_if.fixed @@ -15,26 +15,32 @@ fn main() { if x == "hello" && y == "world" { println!("Hello world!"); } + //~^^^^^ collapsible_if if (x == "hello" || x == "world") && (y == "world" || y == "hello") { println!("Hello world!"); } + //~^^^^^ collapsible_if if x == "hello" && x == "world" && (y == "world" || y == "hello") { println!("Hello world!"); } + //~^^^^^ collapsible_if if (x == "hello" || x == "world") && y == "world" && y == "hello" { println!("Hello world!"); } + //~^^^^^ collapsible_if if x == "hello" && x == "world" && y == "world" && y == "hello" { println!("Hello world!"); } + //~^^^^^ collapsible_if if 42 == 1337 && 'a' != 'A' { println!("world!") } + //~^^^^^ collapsible_if // Works because any if with an else statement cannot be collapsed. if x == "hello" { @@ -89,6 +95,7 @@ fn main() { if x == "hello" && y == "world" { // Collapsible println!("Hello world!"); } + //~^^^^^ collapsible_if if x == "hello" { print!("Hello "); @@ -144,9 +151,11 @@ fn main() { // Fix #5962 if matches!(true, true) && matches!(true, true) {} + //~^^^ collapsible_if // Issue #9375 if matches!(true, true) && truth() && matches!(true, true) {} + //~^^^ collapsible_if if true { #[cfg(not(teehee))] diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs index 563a273dcddd..5cf591a658c7 100644 --- a/tests/ui/collapsible_if.rs +++ b/tests/ui/collapsible_if.rs @@ -17,36 +17,42 @@ fn main() { println!("Hello world!"); } } + //~^^^^^ collapsible_if if x == "hello" || x == "world" { if y == "world" || y == "hello" { println!("Hello world!"); } } + //~^^^^^ collapsible_if if x == "hello" && x == "world" { if y == "world" || y == "hello" { println!("Hello world!"); } } + //~^^^^^ collapsible_if if x == "hello" || x == "world" { if y == "world" && y == "hello" { println!("Hello world!"); } } + //~^^^^^ collapsible_if if x == "hello" && x == "world" { if y == "world" && y == "hello" { println!("Hello world!"); } } + //~^^^^^ collapsible_if if 42 == 1337 { if 'a' != 'A' { println!("world!") } } + //~^^^^^ collapsible_if // Works because any if with an else statement cannot be collapsed. if x == "hello" { @@ -103,6 +109,7 @@ fn main() { println!("Hello world!"); } } + //~^^^^^ collapsible_if if x == "hello" { print!("Hello "); @@ -160,11 +167,13 @@ fn main() { if matches!(true, true) { if matches!(true, true) {} } + //~^^^ collapsible_if // Issue #9375 if matches!(true, true) && truth() { if matches!(true, true) {} } + //~^^^ collapsible_if if true { #[cfg(not(teehee))] diff --git a/tests/ui/collapsible_if.stderr b/tests/ui/collapsible_if.stderr index 5bcbdf2fd08d..3cc3fe5534f2 100644 --- a/tests/ui/collapsible_if.stderr +++ b/tests/ui/collapsible_if.stderr @@ -18,7 +18,7 @@ LL + } | error: this `if` statement can be collapsed - --> tests/ui/collapsible_if.rs:21:5 + --> tests/ui/collapsible_if.rs:22:5 | LL | / if x == "hello" || x == "world" { LL | | if y == "world" || y == "hello" { @@ -35,7 +35,7 @@ LL + } | error: this `if` statement can be collapsed - --> tests/ui/collapsible_if.rs:27:5 + --> tests/ui/collapsible_if.rs:29:5 | LL | / if x == "hello" && x == "world" { LL | | if y == "world" || y == "hello" { @@ -52,7 +52,7 @@ LL + } | error: this `if` statement can be collapsed - --> tests/ui/collapsible_if.rs:33:5 + --> tests/ui/collapsible_if.rs:36:5 | LL | / if x == "hello" || x == "world" { LL | | if y == "world" && y == "hello" { @@ -69,7 +69,7 @@ LL + } | error: this `if` statement can be collapsed - --> tests/ui/collapsible_if.rs:39:5 + --> tests/ui/collapsible_if.rs:43:5 | LL | / if x == "hello" && x == "world" { LL | | if y == "world" && y == "hello" { @@ -86,7 +86,7 @@ LL + } | error: this `if` statement can be collapsed - --> tests/ui/collapsible_if.rs:45:5 + --> tests/ui/collapsible_if.rs:50:5 | LL | / if 42 == 1337 { LL | | if 'a' != 'A' { @@ -103,7 +103,7 @@ LL + } | error: this `if` statement can be collapsed - --> tests/ui/collapsible_if.rs:101:5 + --> tests/ui/collapsible_if.rs:107:5 | LL | / if x == "hello" { LL | | if y == "world" { // Collapsible @@ -120,7 +120,7 @@ LL + } | error: this `if` statement can be collapsed - --> tests/ui/collapsible_if.rs:160:5 + --> tests/ui/collapsible_if.rs:167:5 | LL | / if matches!(true, true) { LL | | if matches!(true, true) {} @@ -128,7 +128,7 @@ LL | | } | |_____^ help: collapse nested if block: `if matches!(true, true) && matches!(true, true) {}` error: this `if` statement can be collapsed - --> tests/ui/collapsible_if.rs:165:5 + --> tests/ui/collapsible_if.rs:173:5 | LL | / if matches!(true, true) && truth() { LL | | if matches!(true, true) {} diff --git a/tests/ui/collapsible_match.rs b/tests/ui/collapsible_match.rs index 2264b560791a..796cabd4b669 100644 --- a/tests/ui/collapsible_match.rs +++ b/tests/ui/collapsible_match.rs @@ -12,7 +12,7 @@ fn lint_cases(opt_opt: Option>, res_opt: Result, String> // match without block match res_opt { Ok(val) => match val { - //~^ ERROR: this `match` can be collapsed into the outer `match` + //~^ collapsible_match Some(n) => foo(n), _ => return, }, @@ -22,7 +22,7 @@ fn lint_cases(opt_opt: Option>, res_opt: Result, String> // match with block match res_opt { Ok(val) => match val { - //~^ ERROR: this `match` can be collapsed into the outer `match` + //~^ collapsible_match Some(n) => foo(n), _ => return, }, @@ -32,7 +32,8 @@ fn lint_cases(opt_opt: Option>, res_opt: Result, String> // if let, if let if let Ok(val) = res_opt { if let Some(n) = val { - //~^ ERROR: this `if let` can be collapsed into the outer `if let` + //~^ collapsible_match + take(n); } } @@ -40,7 +41,8 @@ fn lint_cases(opt_opt: Option>, res_opt: Result, String> // if let else, if let else if let Ok(val) = res_opt { if let Some(n) = val { - //~^ ERROR: this `if let` can be collapsed into the outer `if let` + //~^ collapsible_match + take(n); } else { return; @@ -52,7 +54,7 @@ fn lint_cases(opt_opt: Option>, res_opt: Result, String> // if let, match if let Ok(val) = res_opt { match val { - //~^ ERROR: this `match` can be collapsed into the outer `if let` + //~^ collapsible_match Some(n) => foo(n), _ => (), } @@ -62,7 +64,8 @@ fn lint_cases(opt_opt: Option>, res_opt: Result, String> match res_opt { Ok(val) => { if let Some(n) = val { - //~^ ERROR: this `if let` can be collapsed into the outer `match` + //~^ collapsible_match + take(n); } }, @@ -72,7 +75,7 @@ fn lint_cases(opt_opt: Option>, res_opt: Result, String> // if let else, match if let Ok(val) = res_opt { match val { - //~^ ERROR: this `match` can be collapsed into the outer `if let` + //~^ collapsible_match Some(n) => foo(n), _ => return, } @@ -84,7 +87,8 @@ fn lint_cases(opt_opt: Option>, res_opt: Result, String> match res_opt { Ok(val) => { if let Some(n) = val { - //~^ ERROR: this `if let` can be collapsed into the outer `match` + //~^ collapsible_match + take(n); } else { return; @@ -96,7 +100,7 @@ fn lint_cases(opt_opt: Option>, res_opt: Result, String> // None in inner match same as outer wild branch match res_opt { Ok(val) => match val { - //~^ ERROR: this `match` can be collapsed into the outer `match` + //~^ collapsible_match Some(n) => foo(n), None => return, }, @@ -106,7 +110,7 @@ fn lint_cases(opt_opt: Option>, res_opt: Result, String> // None in outer match same as inner wild branch match opt_opt { Some(val) => match val { - //~^ ERROR: this `match` can be collapsed into the outer `match` + //~^ collapsible_match Some(n) => foo(n), _ => return, }, @@ -250,6 +254,7 @@ fn negative_cases(res_opt: Result, String>, res_res: Result>>() { Some(val) => match val { + //~^ collapsible_match E::A(val) | E::B(val) => foo(val), _ => return, }, @@ -281,7 +286,8 @@ pub enum Issue9647 { pub fn test_1(x: Issue9647) { if let Issue9647::A { a, .. } = x { if let Some(u) = a { - //~^ ERROR: this `if let` can be collapsed into the outer `if let` + //~^ collapsible_match + println!("{u:?}") } } @@ -290,7 +296,8 @@ pub fn test_1(x: Issue9647) { pub fn test_2(x: Issue9647) { if let Issue9647::A { a: Some(a), .. } = x { if let Some(u) = a { - //~^ ERROR: this `if let` can be collapsed into the outer `if let` + //~^ collapsible_match + println!("{u}") } } diff --git a/tests/ui/collapsible_match.stderr b/tests/ui/collapsible_match.stderr index 1da78b56239c..5294a9d6975d 100644 --- a/tests/ui/collapsible_match.stderr +++ b/tests/ui/collapsible_match.stderr @@ -45,6 +45,7 @@ error: this `if let` can be collapsed into the outer `if let` | LL | / if let Some(n) = val { LL | | +LL | | LL | | take(n); LL | | } | |_________^ @@ -58,10 +59,11 @@ LL | if let Some(n) = val { | ^^^^^^^ with this pattern error: this `if let` can be collapsed into the outer `if let` - --> tests/ui/collapsible_match.rs:42:9 + --> tests/ui/collapsible_match.rs:43:9 | LL | / if let Some(n) = val { LL | | +LL | | LL | | take(n); LL | | } else { LL | | return; @@ -69,7 +71,7 @@ LL | | } | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match.rs:41:15 + --> tests/ui/collapsible_match.rs:42:15 | LL | if let Ok(val) = res_opt { | ^^^ replace this binding @@ -77,7 +79,7 @@ LL | if let Some(n) = val { | ^^^^^^^ with this pattern error: this `match` can be collapsed into the outer `if let` - --> tests/ui/collapsible_match.rs:54:9 + --> tests/ui/collapsible_match.rs:56:9 | LL | / match val { LL | | @@ -87,7 +89,7 @@ LL | | } | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match.rs:53:15 + --> tests/ui/collapsible_match.rs:55:15 | LL | if let Ok(val) = res_opt { | ^^^ replace this binding @@ -96,16 +98,17 @@ LL | Some(n) => foo(n), | ^^^^^^^ with this pattern error: this `if let` can be collapsed into the outer `match` - --> tests/ui/collapsible_match.rs:64:13 + --> tests/ui/collapsible_match.rs:66:13 | LL | / if let Some(n) = val { LL | | +LL | | LL | | take(n); LL | | } | |_____________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match.rs:63:12 + --> tests/ui/collapsible_match.rs:65:12 | LL | Ok(val) => { | ^^^ replace this binding @@ -113,7 +116,7 @@ LL | if let Some(n) = val { | ^^^^^^^ with this pattern error: this `match` can be collapsed into the outer `if let` - --> tests/ui/collapsible_match.rs:74:9 + --> tests/ui/collapsible_match.rs:77:9 | LL | / match val { LL | | @@ -123,7 +126,7 @@ LL | | } | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match.rs:73:15 + --> tests/ui/collapsible_match.rs:76:15 | LL | if let Ok(val) = res_opt { | ^^^ replace this binding @@ -132,10 +135,11 @@ LL | Some(n) => foo(n), | ^^^^^^^ with this pattern error: this `if let` can be collapsed into the outer `match` - --> tests/ui/collapsible_match.rs:86:13 + --> tests/ui/collapsible_match.rs:89:13 | LL | / if let Some(n) = val { LL | | +LL | | LL | | take(n); LL | | } else { LL | | return; @@ -143,7 +147,7 @@ LL | | } | |_____________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match.rs:85:12 + --> tests/ui/collapsible_match.rs:88:12 | LL | Ok(val) => { | ^^^ replace this binding @@ -151,7 +155,7 @@ LL | if let Some(n) = val { | ^^^^^^^ with this pattern error: this `match` can be collapsed into the outer `match` - --> tests/ui/collapsible_match.rs:98:20 + --> tests/ui/collapsible_match.rs:102:20 | LL | Ok(val) => match val { | ____________________^ @@ -162,7 +166,7 @@ LL | | }, | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match.rs:98:12 + --> tests/ui/collapsible_match.rs:102:12 | LL | Ok(val) => match val { | ^^^ replace this binding @@ -171,7 +175,7 @@ LL | Some(n) => foo(n), | ^^^^^^^ with this pattern error: this `match` can be collapsed into the outer `match` - --> tests/ui/collapsible_match.rs:108:22 + --> tests/ui/collapsible_match.rs:112:22 | LL | Some(val) => match val { | ______________________^ @@ -182,7 +186,7 @@ LL | | }, | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match.rs:108:14 + --> tests/ui/collapsible_match.rs:112:14 | LL | Some(val) => match val { | ^^^ replace this binding @@ -191,34 +195,37 @@ LL | Some(n) => foo(n), | ^^^^^^^ with this pattern error: this `match` can be collapsed into the outer `match` - --> tests/ui/collapsible_match.rs:252:22 + --> tests/ui/collapsible_match.rs:256:22 | LL | Some(val) => match val { | ______________________^ +LL | | LL | | E::A(val) | E::B(val) => foo(val), LL | | _ => return, LL | | }, | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match.rs:252:14 + --> tests/ui/collapsible_match.rs:256:14 | LL | Some(val) => match val { | ^^^ replace this binding +LL | LL | E::A(val) | E::B(val) => foo(val), | ^^^^^^^^^^^^^^^^^^^^^ with this pattern error: this `if let` can be collapsed into the outer `if let` - --> tests/ui/collapsible_match.rs:283:9 + --> tests/ui/collapsible_match.rs:288:9 | LL | / if let Some(u) = a { LL | | +LL | | LL | | println!("{u:?}") LL | | } | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match.rs:282:27 + --> tests/ui/collapsible_match.rs:287:27 | LL | if let Issue9647::A { a, .. } = x { | ^ replace this binding @@ -226,16 +233,17 @@ LL | if let Some(u) = a { | ^^^^^^^ with this pattern, prefixed by `a`: error: this `if let` can be collapsed into the outer `if let` - --> tests/ui/collapsible_match.rs:292:9 + --> tests/ui/collapsible_match.rs:298:9 | LL | / if let Some(u) = a { LL | | +LL | | LL | | println!("{u}") LL | | } | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match.rs:291:35 + --> tests/ui/collapsible_match.rs:297:35 | LL | if let Issue9647::A { a: Some(a), .. } = x { | ^ replace this binding diff --git a/tests/ui/collapsible_match2.rs b/tests/ui/collapsible_match2.rs index 56801f99e454..ba7f2f2720dc 100644 --- a/tests/ui/collapsible_match2.rs +++ b/tests/ui/collapsible_match2.rs @@ -11,7 +11,7 @@ fn lint_cases(opt_opt: Option>, res_opt: Result, String> { match res_opt { Ok(val) if make() => match val { - //~^ ERROR: this `match` can be collapsed into the outer `match` + //~^ collapsible_match Some(n) => foo(n), _ => return, }, @@ -19,7 +19,7 @@ fn lint_cases(opt_opt: Option>, res_opt: Result, String> } match res_opt { Ok(val) => match val { - //~^ ERROR: this `match` can be collapsed into the outer `match` + //~^ collapsible_match Some(n) => foo(n), _ => return, }, @@ -34,6 +34,7 @@ fn lint_cases(opt_opt: Option>, res_opt: Result, String> ($outer:expr => $pat:pat, $e:expr => $inner_pat:pat, $then:expr) => { match $outer { $pat => match $e { + //~^ collapsible_match $inner_pat => $then, _ => return, }, @@ -51,7 +52,7 @@ fn lint_cases(opt_opt: Option>, res_opt: Result, String> // deref reference value match Some(&[1]) { Some(s) => match *s { - //~^ ERROR: this `match` can be collapsed into the outer `match` + //~^ collapsible_match [n] => foo(n), _ => (), }, @@ -61,7 +62,7 @@ fn lint_cases(opt_opt: Option>, res_opt: Result, String> // ref pattern and deref match Some(&[1]) { Some(ref s) => match s { - //~^ ERROR: this `match` can be collapsed into the outer `match` + //~^ collapsible_match [n] => foo(n), _ => (), }, diff --git a/tests/ui/collapsible_match2.stderr b/tests/ui/collapsible_match2.stderr index 13caa78fbeb5..7b2730637528 100644 --- a/tests/ui/collapsible_match2.stderr +++ b/tests/ui/collapsible_match2.stderr @@ -45,6 +45,7 @@ error: this `match` can be collapsed into the outer `match` | LL | $pat => match $e { | _____________________________^ +LL | | LL | | $inner_pat => $then, LL | | _ => return, LL | | }, @@ -54,7 +55,7 @@ LL | mac!(res_opt => Ok(val), val => Some(n), foo(n)); | ------------------------------------------------ in this macro invocation | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match2.rs:48:28 + --> tests/ui/collapsible_match2.rs:49:28 | LL | mac!(res_opt => Ok(val), val => Some(n), foo(n)); | ^^^ ^^^^^^^ with this pattern @@ -63,7 +64,7 @@ LL | mac!(res_opt => Ok(val), val => Some(n), foo(n)); = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: this `match` can be collapsed into the outer `match` - --> tests/ui/collapsible_match2.rs:53:20 + --> tests/ui/collapsible_match2.rs:54:20 | LL | Some(s) => match *s { | ____________________^ @@ -74,7 +75,7 @@ LL | | }, | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match2.rs:53:14 + --> tests/ui/collapsible_match2.rs:54:14 | LL | Some(s) => match *s { | ^ replace this binding @@ -83,7 +84,7 @@ LL | [n] => foo(n), | ^^^ with this pattern error: this `match` can be collapsed into the outer `match` - --> tests/ui/collapsible_match2.rs:63:24 + --> tests/ui/collapsible_match2.rs:64:24 | LL | Some(ref s) => match s { | ________________________^ @@ -94,7 +95,7 @@ LL | | }, | |_________^ | help: the outer pattern can be modified to include the inner pattern - --> tests/ui/collapsible_match2.rs:63:14 + --> tests/ui/collapsible_match2.rs:64:14 | LL | Some(ref s) => match s { | ^^^^^ replace this binding diff --git a/tests/ui/collapsible_str_replace.fixed b/tests/ui/collapsible_str_replace.fixed index 03b393d5a674..e9a7384b761b 100644 --- a/tests/ui/collapsible_str_replace.fixed +++ b/tests/ui/collapsible_str_replace.fixed @@ -16,32 +16,44 @@ fn main() { // LINT CASES let _ = "hesuo worpd".replace(['s', 'u'], "l"); + //~^ collapsible_str_replace let _ = "hesuo worpd".replace(['s', 'u'], l); + //~^ collapsible_str_replace let _ = "hesuo worpd".replace(['s', 'u', 'p'], "l"); + //~^ collapsible_str_replace let _ = "hesuo worpd" .replace(['s', 'u', 'p', 'd'], "l"); let _ = "hesuo world".replace([s, 'u'], "l"); + //~^ collapsible_str_replace let _ = "hesuo worpd".replace([s, 'u', 'p'], "l"); + //~^ collapsible_str_replace let _ = "hesuo worpd".replace([s, u, 'p'], "l"); + //~^ collapsible_str_replace let _ = "hesuo worpd".replace([s, u, p], "l"); + //~^ collapsible_str_replace let _ = "hesuo worlp".replace(['s', 'u'], "l").replace('p', "d"); + //~^ collapsible_str_replace let _ = "hesuo worpd".replace('s', "x").replace(['u', 'p'], "l"); + //~^ collapsible_str_replace // Note: Future iterations could lint `replace(|c| matches!(c, "su" | 'd' | 'p'), "l")` let _ = "hesudo worpd".replace("su", "l").replace(['d', 'p'], "l"); + //~^ collapsible_str_replace let _ = "hesudo worpd".replace([d, 'p'], "l").replace("su", "l"); + //~^ collapsible_str_replace let _ = "hesuo world".replace([get_filter(), 's'], "l"); + //~^ collapsible_str_replace // NO LINT CASES let _ = "hesuo world".replace('s', "l").replace('u', "p"); @@ -79,4 +91,5 @@ fn msrv_1_57() { #[clippy::msrv = "1.58"] fn msrv_1_58() { let _ = "".replace(['a', 'b'], "1.58"); + //~^ collapsible_str_replace } diff --git a/tests/ui/collapsible_str_replace.rs b/tests/ui/collapsible_str_replace.rs index 364e5493b872..4dc12c1b1c6e 100644 --- a/tests/ui/collapsible_str_replace.rs +++ b/tests/ui/collapsible_str_replace.rs @@ -16,35 +16,48 @@ fn main() { // LINT CASES let _ = "hesuo worpd".replace('s', "l").replace('u', "l"); + //~^ collapsible_str_replace let _ = "hesuo worpd".replace('s', l).replace('u', l); + //~^ collapsible_str_replace let _ = "hesuo worpd".replace('s', "l").replace('u', "l").replace('p', "l"); + //~^ collapsible_str_replace let _ = "hesuo worpd" .replace('s', "l") + //~^ collapsible_str_replace .replace('u', "l") .replace('p', "l") .replace('d', "l"); let _ = "hesuo world".replace(s, "l").replace('u', "l"); + //~^ collapsible_str_replace let _ = "hesuo worpd".replace(s, "l").replace('u', "l").replace('p', "l"); + //~^ collapsible_str_replace let _ = "hesuo worpd".replace(s, "l").replace(u, "l").replace('p', "l"); + //~^ collapsible_str_replace let _ = "hesuo worpd".replace(s, "l").replace(u, "l").replace(p, "l"); + //~^ collapsible_str_replace let _ = "hesuo worlp".replace('s', "l").replace('u', "l").replace('p', "d"); + //~^ collapsible_str_replace let _ = "hesuo worpd".replace('s', "x").replace('u', "l").replace('p', "l"); + //~^ collapsible_str_replace // Note: Future iterations could lint `replace(|c| matches!(c, "su" | 'd' | 'p'), "l")` let _ = "hesudo worpd".replace("su", "l").replace('d', "l").replace('p', "l"); + //~^ collapsible_str_replace let _ = "hesudo worpd".replace(d, "l").replace('p', "l").replace("su", "l"); + //~^ collapsible_str_replace let _ = "hesuo world".replace(get_filter(), "l").replace('s', "l"); + //~^ collapsible_str_replace // NO LINT CASES let _ = "hesuo world".replace('s', "l").replace('u', "p"); @@ -82,4 +95,5 @@ fn msrv_1_57() { #[clippy::msrv = "1.58"] fn msrv_1_58() { let _ = "".replace('a', "1.58").replace('b', "1.58"); + //~^ collapsible_str_replace } diff --git a/tests/ui/collapsible_str_replace.stderr b/tests/ui/collapsible_str_replace.stderr index da681dffd875..a634b857dd46 100644 --- a/tests/ui/collapsible_str_replace.stderr +++ b/tests/ui/collapsible_str_replace.stderr @@ -8,83 +8,84 @@ LL | let _ = "hesuo worpd".replace('s', "l").replace('u', "l"); = help: to override `-D warnings` add `#[allow(clippy::collapsible_str_replace)]` error: used consecutive `str::replace` call - --> tests/ui/collapsible_str_replace.rs:20:27 + --> tests/ui/collapsible_str_replace.rs:21:27 | LL | let _ = "hesuo worpd".replace('s', l).replace('u', l); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['s', 'u'], l)` error: used consecutive `str::replace` call - --> tests/ui/collapsible_str_replace.rs:22:27 + --> tests/ui/collapsible_str_replace.rs:24:27 | LL | let _ = "hesuo worpd".replace('s', "l").replace('u', "l").replace('p', "l"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['s', 'u', 'p'], "l")` error: used consecutive `str::replace` call - --> tests/ui/collapsible_str_replace.rs:25:10 + --> tests/ui/collapsible_str_replace.rs:28:10 | LL | .replace('s', "l") | __________^ +LL | | LL | | .replace('u', "l") LL | | .replace('p', "l") LL | | .replace('d', "l"); | |__________________________^ help: replace with: `replace(['s', 'u', 'p', 'd'], "l")` error: used consecutive `str::replace` call - --> tests/ui/collapsible_str_replace.rs:30:27 + --> tests/ui/collapsible_str_replace.rs:34:27 | LL | let _ = "hesuo world".replace(s, "l").replace('u', "l"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([s, 'u'], "l")` error: used consecutive `str::replace` call - --> tests/ui/collapsible_str_replace.rs:32:27 + --> tests/ui/collapsible_str_replace.rs:37:27 | LL | let _ = "hesuo worpd".replace(s, "l").replace('u', "l").replace('p', "l"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([s, 'u', 'p'], "l")` error: used consecutive `str::replace` call - --> tests/ui/collapsible_str_replace.rs:34:27 + --> tests/ui/collapsible_str_replace.rs:40:27 | LL | let _ = "hesuo worpd".replace(s, "l").replace(u, "l").replace('p', "l"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([s, u, 'p'], "l")` error: used consecutive `str::replace` call - --> tests/ui/collapsible_str_replace.rs:36:27 + --> tests/ui/collapsible_str_replace.rs:43:27 | LL | let _ = "hesuo worpd".replace(s, "l").replace(u, "l").replace(p, "l"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([s, u, p], "l")` error: used consecutive `str::replace` call - --> tests/ui/collapsible_str_replace.rs:38:27 + --> tests/ui/collapsible_str_replace.rs:46:27 | LL | let _ = "hesuo worlp".replace('s', "l").replace('u', "l").replace('p', "d"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['s', 'u'], "l")` error: used consecutive `str::replace` call - --> tests/ui/collapsible_str_replace.rs:40:45 + --> tests/ui/collapsible_str_replace.rs:49:45 | LL | let _ = "hesuo worpd".replace('s', "x").replace('u', "l").replace('p', "l"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['u', 'p'], "l")` error: used consecutive `str::replace` call - --> tests/ui/collapsible_str_replace.rs:43:47 + --> tests/ui/collapsible_str_replace.rs:53:47 | LL | let _ = "hesudo worpd".replace("su", "l").replace('d', "l").replace('p', "l"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['d', 'p'], "l")` error: used consecutive `str::replace` call - --> tests/ui/collapsible_str_replace.rs:45:28 + --> tests/ui/collapsible_str_replace.rs:56:28 | LL | let _ = "hesudo worpd".replace(d, "l").replace('p', "l").replace("su", "l"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([d, 'p'], "l")` error: used consecutive `str::replace` call - --> tests/ui/collapsible_str_replace.rs:47:27 + --> tests/ui/collapsible_str_replace.rs:59:27 | LL | let _ = "hesuo world".replace(get_filter(), "l").replace('s', "l"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([get_filter(), 's'], "l")` error: used consecutive `str::replace` call - --> tests/ui/collapsible_str_replace.rs:84:16 + --> tests/ui/collapsible_str_replace.rs:97:16 | LL | let _ = "".replace('a', "1.58").replace('b', "1.58"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['a', 'b'], "1.58")` diff --git a/tests/ui/collection_is_never_read.rs b/tests/ui/collection_is_never_read.rs index eeb10da3402a..77cc84fef177 100644 --- a/tests/ui/collection_is_never_read.rs +++ b/tests/ui/collection_is_never_read.rs @@ -19,8 +19,8 @@ fn no_access_at_all() { fn write_without_read() { // The main use case for `collection_is_never_read`. let mut x = HashMap::new(); - //~^ ERROR: collection is never read - //~| NOTE: `-D clippy::collection-is-never-read` implied by `-D warnings` + //~^ collection_is_never_read + x.insert(1, 2); } @@ -60,7 +60,8 @@ fn read_in_closure() { fn write_in_closure() { let mut x = vec![1, 2, 3]; - //~^ ERROR: collection is never read + //~^ collection_is_never_read + let _ = || { x.push(4); }; @@ -76,13 +77,15 @@ fn shadowing_1() { let x = HashMap::::new(); // Ok let _ = x.len(); let mut x = HashMap::new(); - //~^ ERROR: collection is never read + //~^ collection_is_never_read + x.insert(1, 2); } fn shadowing_2() { let mut x = HashMap::new(); - //~^ ERROR: collection is never read + //~^ collection_is_never_read + x.insert(1, 2); let x = HashMap::::new(); // Ok let _ = x.len(); @@ -91,21 +94,24 @@ fn shadowing_2() { #[allow(clippy::let_unit_value)] fn fake_read_1() { let mut x = vec![1, 2, 3]; - //~^ ERROR: collection is never read + //~^ collection_is_never_read + x.reverse(); let _: () = x.clear(); } fn fake_read_2() { let mut x = vec![1, 2, 3]; - //~^ ERROR: collection is never read + //~^ collection_is_never_read + x.reverse(); println!("{:?}", x.push(5)); } fn assignment() { let mut x = vec![1, 2, 3]; - //~^ ERROR: collection is never read + //~^ collection_is_never_read + let y = vec![4, 5, 6]; // Ok x = y; } @@ -113,7 +119,8 @@ fn assignment() { #[allow(clippy::self_assignment)] fn self_assignment() { let mut x = vec![1, 2, 3]; - //~^ ERROR: collection is never read + //~^ collection_is_never_read + x = x; } @@ -131,7 +138,8 @@ fn method_argument_but_not_target() { fn insert_is_not_a_read() { let mut x = HashSet::new(); - //~^ ERROR: collection is never read + //~^ collection_is_never_read + x.insert(5); } @@ -146,7 +154,8 @@ fn not_read_if_return_value_not_used() { // `is_empty` does not modify the set, so it's a query. But since the return value is not used, the // lint does not consider it a read here. let x = vec![1, 2, 3]; - //~^ ERROR: collection is never read + //~^ collection_is_never_read + x.is_empty(); } @@ -182,44 +191,54 @@ fn function_argument() { fn supported_types() { let mut x = std::collections::BTreeMap::new(); - //~^ ERROR: collection is never read + //~^ collection_is_never_read + x.insert(true, 1); let mut x = std::collections::BTreeSet::new(); - //~^ ERROR: collection is never read + //~^ collection_is_never_read + x.insert(1); let mut x = std::collections::BinaryHeap::new(); - //~^ ERROR: collection is never read + //~^ collection_is_never_read + x.push(1); let mut x = std::collections::HashMap::new(); - //~^ ERROR: collection is never read + //~^ collection_is_never_read + x.insert(1, 2); let mut x = std::collections::HashSet::new(); - //~^ ERROR: collection is never read + //~^ collection_is_never_read + x.insert(1); let mut x = std::collections::LinkedList::new(); - //~^ ERROR: collection is never read + //~^ collection_is_never_read + x.push_front(1); let mut x = Some(true); - //~^ ERROR: collection is never read + //~^ collection_is_never_read + x.insert(false); let mut x = String::from("hello"); - //~^ ERROR: collection is never read + //~^ collection_is_never_read + x.push('!'); let mut x = Vec::new(); - //~^ ERROR: collection is never read + //~^ collection_is_never_read + x.clear(); x.push(1); let mut x = std::collections::VecDeque::new(); - //~^ ERROR: collection is never read + //~^ collection_is_never_read + x.push_front(1); } diff --git a/tests/ui/collection_is_never_read.stderr b/tests/ui/collection_is_never_read.stderr index f91ce07483c3..d92b84c4a652 100644 --- a/tests/ui/collection_is_never_read.stderr +++ b/tests/ui/collection_is_never_read.stderr @@ -14,109 +14,109 @@ LL | let mut x = vec![1, 2, 3]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> tests/ui/collection_is_never_read.rs:78:5 + --> tests/ui/collection_is_never_read.rs:79:5 | LL | let mut x = HashMap::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> tests/ui/collection_is_never_read.rs:84:5 + --> tests/ui/collection_is_never_read.rs:86:5 | LL | let mut x = HashMap::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> tests/ui/collection_is_never_read.rs:93:5 + --> tests/ui/collection_is_never_read.rs:96:5 | LL | let mut x = vec![1, 2, 3]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> tests/ui/collection_is_never_read.rs:100:5 + --> tests/ui/collection_is_never_read.rs:104:5 | LL | let mut x = vec![1, 2, 3]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> tests/ui/collection_is_never_read.rs:107:5 + --> tests/ui/collection_is_never_read.rs:112:5 | LL | let mut x = vec![1, 2, 3]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> tests/ui/collection_is_never_read.rs:115:5 + --> tests/ui/collection_is_never_read.rs:121:5 | LL | let mut x = vec![1, 2, 3]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> tests/ui/collection_is_never_read.rs:133:5 + --> tests/ui/collection_is_never_read.rs:140:5 | LL | let mut x = HashSet::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> tests/ui/collection_is_never_read.rs:148:5 + --> tests/ui/collection_is_never_read.rs:156:5 | LL | let x = vec![1, 2, 3]; | ^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> tests/ui/collection_is_never_read.rs:184:5 + --> tests/ui/collection_is_never_read.rs:193:5 | LL | let mut x = std::collections::BTreeMap::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> tests/ui/collection_is_never_read.rs:188:5 + --> tests/ui/collection_is_never_read.rs:198:5 | LL | let mut x = std::collections::BTreeSet::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> tests/ui/collection_is_never_read.rs:192:5 + --> tests/ui/collection_is_never_read.rs:203:5 | LL | let mut x = std::collections::BinaryHeap::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> tests/ui/collection_is_never_read.rs:196:5 + --> tests/ui/collection_is_never_read.rs:208:5 | LL | let mut x = std::collections::HashMap::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> tests/ui/collection_is_never_read.rs:200:5 + --> tests/ui/collection_is_never_read.rs:213:5 | LL | let mut x = std::collections::HashSet::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> tests/ui/collection_is_never_read.rs:204:5 + --> tests/ui/collection_is_never_read.rs:218:5 | LL | let mut x = std::collections::LinkedList::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> tests/ui/collection_is_never_read.rs:208:5 + --> tests/ui/collection_is_never_read.rs:223:5 | LL | let mut x = Some(true); | ^^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> tests/ui/collection_is_never_read.rs:212:5 + --> tests/ui/collection_is_never_read.rs:228:5 | LL | let mut x = String::from("hello"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> tests/ui/collection_is_never_read.rs:216:5 + --> tests/ui/collection_is_never_read.rs:233:5 | LL | let mut x = Vec::new(); | ^^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> tests/ui/collection_is_never_read.rs:221:5 + --> tests/ui/collection_is_never_read.rs:239:5 | LL | let mut x = std::collections::VecDeque::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/comparison_chain.rs b/tests/ui/comparison_chain.rs index cab460d100dd..669690a4d42c 100644 --- a/tests/ui/comparison_chain.rs +++ b/tests/ui/comparison_chain.rs @@ -13,7 +13,8 @@ fn f(x: u8, y: u8, z: u8) { } if x > y { - //~^ ERROR: `if` chain can be rewritten with `match` + //~^ comparison_chain + a() } else if x < y { b() @@ -27,7 +28,8 @@ fn f(x: u8, y: u8, z: u8) { } if x > y { - //~^ ERROR: `if` chain can be rewritten with `match` + //~^ comparison_chain + a() } else if x < y { b() @@ -36,7 +38,8 @@ fn f(x: u8, y: u8, z: u8) { } if x > y { - //~^ ERROR: `if` chain can be rewritten with `match` + //~^ comparison_chain + a() } else if y > x { b() @@ -45,7 +48,8 @@ fn f(x: u8, y: u8, z: u8) { } if x > 1 { - //~^ ERROR: `if` chain can be rewritten with `match` + //~^ comparison_chain + a() } else if x < 1 { b() @@ -120,14 +124,16 @@ fn g(x: f64, y: f64, z: f64) { fn h(x: T, y: T, z: T) { if x > y { - //~^ ERROR: `if` chain can be rewritten with `match` + //~^ comparison_chain + a() } else if x < y { b() } if x > y { - //~^ ERROR: `if` chain can be rewritten with `match` + //~^ comparison_chain + a() } else if x < y { b() @@ -136,7 +142,8 @@ fn h(x: T, y: T, z: T) { } if x > y { - //~^ ERROR: `if` chain can be rewritten with `match` + //~^ comparison_chain + a() } else if y > x { b() @@ -242,7 +249,8 @@ const fn sign_i8(n: i8) -> Sign { fn needs_parens() -> &'static str { let (x, y) = (1, 2); if x + 1 > y * 2 { - //~^ ERROR: `if` chain can be rewritten with `match` + //~^ comparison_chain + "aa" } else if x + 1 < y * 2 { "bb" diff --git a/tests/ui/comparison_chain.stderr b/tests/ui/comparison_chain.stderr index 814004e3d4b1..0256573d0d90 100644 --- a/tests/ui/comparison_chain.stderr +++ b/tests/ui/comparison_chain.stderr @@ -3,6 +3,7 @@ error: `if` chain can be rewritten with `match` | LL | / if x > y { LL | | +LL | | LL | | a() LL | | } else if x < y { LL | | b() @@ -13,46 +14,47 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::comparison_chain)]` error: `if` chain can be rewritten with `match` - --> tests/ui/comparison_chain.rs:29:5 + --> tests/ui/comparison_chain.rs:30:5 | LL | / if x > y { LL | | +LL | | LL | | a() -LL | | } else if x < y { ... | LL | | c() LL | | } | |_____^ help: consider rewriting the `if` chain with `match`: `match x.cmp(&y) {...}` error: `if` chain can be rewritten with `match` - --> tests/ui/comparison_chain.rs:38:5 + --> tests/ui/comparison_chain.rs:40:5 | LL | / if x > y { LL | | +LL | | LL | | a() -LL | | } else if y > x { ... | LL | | c() LL | | } | |_____^ help: consider rewriting the `if` chain with `match`: `match x.cmp(&y) {...}` error: `if` chain can be rewritten with `match` - --> tests/ui/comparison_chain.rs:47:5 + --> tests/ui/comparison_chain.rs:50:5 | LL | / if x > 1 { LL | | +LL | | LL | | a() -LL | | } else if x < 1 { ... | LL | | c() LL | | } | |_____^ help: consider rewriting the `if` chain with `match`: `match x.cmp(&1) {...}` error: `if` chain can be rewritten with `match` - --> tests/ui/comparison_chain.rs:122:5 + --> tests/ui/comparison_chain.rs:126:5 | LL | / if x > y { LL | | +LL | | LL | | a() LL | | } else if x < y { LL | | b() @@ -60,36 +62,36 @@ LL | | } | |_____^ help: consider rewriting the `if` chain with `match`: `match x.cmp(&y) {...}` error: `if` chain can be rewritten with `match` - --> tests/ui/comparison_chain.rs:129:5 + --> tests/ui/comparison_chain.rs:134:5 | LL | / if x > y { LL | | +LL | | LL | | a() -LL | | } else if x < y { ... | LL | | c() LL | | } | |_____^ help: consider rewriting the `if` chain with `match`: `match x.cmp(&y) {...}` error: `if` chain can be rewritten with `match` - --> tests/ui/comparison_chain.rs:138:5 + --> tests/ui/comparison_chain.rs:144:5 | LL | / if x > y { LL | | +LL | | LL | | a() -LL | | } else if y > x { ... | LL | | c() LL | | } | |_____^ help: consider rewriting the `if` chain with `match`: `match x.cmp(&y) {...}` error: `if` chain can be rewritten with `match` - --> tests/ui/comparison_chain.rs:244:5 + --> tests/ui/comparison_chain.rs:251:5 | LL | / if x + 1 > y * 2 { LL | | +LL | | LL | | "aa" -LL | | } else if x + 1 < y * 2 { ... | LL | | "cc" LL | | } diff --git a/tests/ui/comparison_to_empty.fixed b/tests/ui/comparison_to_empty.fixed index a2a3dd9086d4..dfbb61683840 100644 --- a/tests/ui/comparison_to_empty.fixed +++ b/tests/ui/comparison_to_empty.fixed @@ -6,17 +6,26 @@ fn main() { // Disallow comparisons to empty let s = String::new(); let _ = s.is_empty(); + //~^ comparison_to_empty let _ = !s.is_empty(); + //~^ comparison_to_empty let v = vec![0]; let _ = v.is_empty(); + //~^ comparison_to_empty let _ = !v.is_empty(); + //~^ comparison_to_empty if (*v).is_empty() {} + //~^ comparison_to_empty let s = [0].as_slice(); if s.is_empty() {} + //~^ comparison_to_empty if s.is_empty() {} + //~^ comparison_to_empty if s.is_empty() + //~^ comparison_to_empty && s.is_empty() + //~^ comparison_to_empty {} // Allow comparisons to non-empty @@ -37,8 +46,12 @@ fn main() { // Also lint the `PartialEq` methods let s = String::new(); let _ = s.is_empty(); + //~^ comparison_to_empty let _ = !s.is_empty(); + //~^ comparison_to_empty let v = vec![0]; let _ = v.is_empty(); + //~^ comparison_to_empty let _ = !v.is_empty(); + //~^ comparison_to_empty } diff --git a/tests/ui/comparison_to_empty.rs b/tests/ui/comparison_to_empty.rs index 7c5689a4bbec..61cdb2bbe9f8 100644 --- a/tests/ui/comparison_to_empty.rs +++ b/tests/ui/comparison_to_empty.rs @@ -6,17 +6,26 @@ fn main() { // Disallow comparisons to empty let s = String::new(); let _ = s == ""; + //~^ comparison_to_empty let _ = s != ""; + //~^ comparison_to_empty let v = vec![0]; let _ = v == []; + //~^ comparison_to_empty let _ = v != []; + //~^ comparison_to_empty if let [] = &*v {} + //~^ comparison_to_empty let s = [0].as_slice(); if let [] = s {} + //~^ comparison_to_empty if let [] = &*s {} + //~^ comparison_to_empty if let [] = &*s + //~^ comparison_to_empty && s == [] + //~^ comparison_to_empty {} // Allow comparisons to non-empty @@ -37,8 +46,12 @@ fn main() { // Also lint the `PartialEq` methods let s = String::new(); let _ = s.eq(""); + //~^ comparison_to_empty let _ = s.ne(""); + //~^ comparison_to_empty let v = vec![0]; let _ = v.eq(&[]); + //~^ comparison_to_empty let _ = v.ne(&[]); + //~^ comparison_to_empty } diff --git a/tests/ui/comparison_to_empty.stderr b/tests/ui/comparison_to_empty.stderr index 2ee0efc7dbb1..00a50430a3ee 100644 --- a/tests/ui/comparison_to_empty.stderr +++ b/tests/ui/comparison_to_empty.stderr @@ -8,73 +8,73 @@ LL | let _ = s == ""; = help: to override `-D warnings` add `#[allow(clippy::comparison_to_empty)]` error: comparison to empty slice - --> tests/ui/comparison_to_empty.rs:9:13 + --> tests/ui/comparison_to_empty.rs:10:13 | LL | let _ = s != ""; | ^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!s.is_empty()` error: comparison to empty slice - --> tests/ui/comparison_to_empty.rs:12:13 + --> tests/ui/comparison_to_empty.rs:14:13 | LL | let _ = v == []; | ^^^^^^^ help: using `is_empty` is clearer and more explicit: `v.is_empty()` error: comparison to empty slice - --> tests/ui/comparison_to_empty.rs:13:13 + --> tests/ui/comparison_to_empty.rs:16:13 | LL | let _ = v != []; | ^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!v.is_empty()` error: comparison to empty slice using `if let` - --> tests/ui/comparison_to_empty.rs:14:8 + --> tests/ui/comparison_to_empty.rs:18:8 | LL | if let [] = &*v {} | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `(*v).is_empty()` error: comparison to empty slice using `if let` - --> tests/ui/comparison_to_empty.rs:16:8 + --> tests/ui/comparison_to_empty.rs:21:8 | LL | if let [] = s {} | ^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s.is_empty()` error: comparison to empty slice using `if let` - --> tests/ui/comparison_to_empty.rs:17:8 + --> tests/ui/comparison_to_empty.rs:23:8 | LL | if let [] = &*s {} | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s.is_empty()` error: comparison to empty slice using `if let` - --> tests/ui/comparison_to_empty.rs:18:8 + --> tests/ui/comparison_to_empty.rs:25:8 | LL | if let [] = &*s | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s.is_empty()` error: comparison to empty slice - --> tests/ui/comparison_to_empty.rs:19:12 + --> tests/ui/comparison_to_empty.rs:27:12 | LL | && s == [] | ^^^^^^^ help: using `is_empty` is clearer and more explicit: `s.is_empty()` error: comparison to empty slice - --> tests/ui/comparison_to_empty.rs:39:13 + --> tests/ui/comparison_to_empty.rs:48:13 | LL | let _ = s.eq(""); | ^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s.is_empty()` error: comparison to empty slice - --> tests/ui/comparison_to_empty.rs:40:13 + --> tests/ui/comparison_to_empty.rs:50:13 | LL | let _ = s.ne(""); | ^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!s.is_empty()` error: comparison to empty slice - --> tests/ui/comparison_to_empty.rs:42:13 + --> tests/ui/comparison_to_empty.rs:53:13 | LL | let _ = v.eq(&[]); | ^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `v.is_empty()` error: comparison to empty slice - --> tests/ui/comparison_to_empty.rs:43:13 + --> tests/ui/comparison_to_empty.rs:55:13 | LL | let _ = v.ne(&[]); | ^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!v.is_empty()` diff --git a/tests/ui/const_comparisons.rs b/tests/ui/const_comparisons.rs index 0898b4ebd465..b732d7d142fc 100644 --- a/tests/ui/const_comparisons.rs +++ b/tests/ui/const_comparisons.rs @@ -43,42 +43,39 @@ fn main() { // Correct status_code >= 400 && status_code < 500; status_code <= 400 && status_code > 500; - //~^ ERROR: boolean expression will never evaluate to 'true' - //~| NOTE: since `400` < `500`, the expression evaluates to false for any value of `st + //~^ impossible_comparisons + status_code > 500 && status_code < 400; - //~^ ERROR: boolean expression will never evaluate to 'true' - //~| NOTE: since `500` > `400`, the expression evaluates to false for any value of `st + //~^ impossible_comparisons + status_code < 500 && status_code > 500; - //~^ ERROR: boolean expression will never evaluate to 'true' - //~| NOTE: `status_code` cannot simultaneously be greater than and less than `500` + //~^ impossible_comparisons // More complex expressions status_code < { 400 } && status_code > { 500 }; - //~^ ERROR: boolean expression will never evaluate to 'true' - //~| NOTE: since `{ 400 }` < `{ 500 }`, the expression evaluates to false for any valu + //~^ impossible_comparisons + status_code < STATUS_BAD_REQUEST && status_code > STATUS_SERVER_ERROR; - //~^ ERROR: boolean expression will never evaluate to 'true' - //~| NOTE: since `STATUS_BAD_REQUEST` < `STATUS_SERVER_ERROR`, the expression evaluate + //~^ impossible_comparisons + status_code <= u16::MIN + 1 && status_code > STATUS_SERVER_ERROR; - //~^ ERROR: boolean expression will never evaluate to 'true' - //~| NOTE: since `u16::MIN + 1` < `STATUS_SERVER_ERROR`, the expression evaluates to f + //~^ impossible_comparisons + status_code < STATUS_SERVER_ERROR && status_code > STATUS_SERVER_ERROR; - //~^ ERROR: boolean expression will never evaluate to 'true' - //~| NOTE: `status_code` cannot simultaneously be greater than and less than `STATUS_S + //~^ impossible_comparisons // Comparing two different types, via the `impl PartialOrd for Status` status < { 400 } && status > { 500 }; - //~^ ERROR: boolean expression will never evaluate to 'true' - //~| NOTE: since `{ 400 }` < `{ 500 }`, the expression evaluates to false for any valu + //~^ impossible_comparisons + status < STATUS_BAD_REQUEST && status > STATUS_SERVER_ERROR; - //~^ ERROR: boolean expression will never evaluate to 'true' - //~| NOTE: since `STATUS_BAD_REQUEST` < `STATUS_SERVER_ERROR`, the expression evaluate + //~^ impossible_comparisons + status <= u16::MIN + 1 && status > STATUS_SERVER_ERROR; - //~^ ERROR: boolean expression will never evaluate to 'true' - //~| NOTE: since `u16::MIN + 1` < `STATUS_SERVER_ERROR`, the expression evaluates to f + //~^ impossible_comparisons + status < STATUS_SERVER_ERROR && status > STATUS_SERVER_ERROR; - //~^ ERROR: boolean expression will never evaluate to 'true' - //~| NOTE: `status` cannot simultaneously be greater than and less than `STATUS_SERVER + //~^ impossible_comparisons // Yoda conditions // Correct @@ -87,12 +84,11 @@ fn main() { 500 <= status_code && status_code <= 600; // Incorrect 500 >= status_code && 600 < status_code; - //~^ ERROR: boolean expression will never evaluate to 'true' - //~| NOTE: since `500` < `600`, the expression evaluates to false for any value of `st + //~^ impossible_comparisons + // Incorrect 500 >= status_code && status_code > 600; - //~^ ERROR: boolean expression will never evaluate to 'true' - //~| NOTE: since `500` < `600`, the expression evaluates to false for any value of `st + //~^ impossible_comparisons // Yoda conditions, comparing two different types // Correct @@ -101,50 +97,49 @@ fn main() { 500 <= status && status <= 600; // Incorrect 500 >= status && 600 < status; - //~^ ERROR: boolean expression will never evaluate to 'true' - //~| NOTE: since `500` < `600`, the expression evaluates to false for any value of `st + //~^ impossible_comparisons + // Incorrect 500 >= status && status > 600; - //~^ ERROR: boolean expression will never evaluate to 'true' - //~| NOTE: since `500` < `600`, the expression evaluates to false for any value of `st + //~^ impossible_comparisons // Expressions where one of the sides has no effect status_code < 200 && status_code <= 299; - //~^ ERROR: right-hand side of `&&` operator has no effect + //~^ redundant_comparisons + status_code > 200 && status_code >= 299; - //~^ ERROR: left-hand side of `&&` operator has no effect + //~^ redundant_comparisons // Useless left status_code >= 500 && status_code > 500; - //~^ ERROR: left-hand side of `&&` operator has no effect + //~^ redundant_comparisons + // Useless right status_code > 500 && status_code >= 500; - //~^ ERROR: right-hand side of `&&` operator has no effect + //~^ redundant_comparisons + // Useless left status_code <= 500 && status_code < 500; - //~^ ERROR: left-hand side of `&&` operator has no effect + //~^ redundant_comparisons + // Useless right status_code < 500 && status_code <= 500; - //~^ ERROR: right-hand side of `&&` operator has no effect + //~^ redundant_comparisons // Other types let name = "Steve"; name < "Jennifer" && name > "Shannon"; - //~^ ERROR: boolean expression will never evaluate to 'true' - //~| NOTE: since `"Jennifer"` < `"Shannon"`, the expression evaluates to false for any + //~^ impossible_comparisons let numbers = [1, 2]; numbers < [3, 4] && numbers > [5, 6]; - //~^ ERROR: boolean expression will never evaluate to 'true' - //~| NOTE: since `[3, 4]` < `[5, 6]`, the expression evaluates to false for any value + //~^ impossible_comparisons let letter = 'a'; letter < 'b' && letter > 'c'; - //~^ ERROR: boolean expression will never evaluate to 'true' - //~| NOTE: since `'b'` < `'c'`, the expression evaluates to false for any value of `le + //~^ impossible_comparisons let area = 42.0; area < std::f32::consts::E && area > std::f32::consts::PI; - //~^ ERROR: boolean expression will never evaluate to 'true' - //~| NOTE: since `std::f32::consts::E` < `std::f32::consts::PI`, the expression evalua + //~^ impossible_comparisons } diff --git a/tests/ui/const_comparisons.stderr b/tests/ui/const_comparisons.stderr index 1b8fd9733fae..48a2c6e8d487 100644 --- a/tests/ui/const_comparisons.stderr +++ b/tests/ui/const_comparisons.stderr @@ -25,7 +25,7 @@ LL | status_code < 500 && status_code > 500; = note: `status_code` cannot simultaneously be greater than and less than `500` error: boolean expression will never evaluate to 'true' - --> tests/ui/const_comparisons.rs:56:5 + --> tests/ui/const_comparisons.rs:55:5 | LL | status_code < { 400 } && status_code > { 500 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | status_code < { 400 } && status_code > { 500 }; = note: since `{ 400 }` < `{ 500 }`, the expression evaluates to false for any value of `status_code` error: boolean expression will never evaluate to 'true' - --> tests/ui/const_comparisons.rs:59:5 + --> tests/ui/const_comparisons.rs:58:5 | LL | status_code < STATUS_BAD_REQUEST && status_code > STATUS_SERVER_ERROR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | status_code < STATUS_BAD_REQUEST && status_code > STATUS_SERVER_ERROR; = note: since `STATUS_BAD_REQUEST` < `STATUS_SERVER_ERROR`, the expression evaluates to false for any value of `status_code` error: boolean expression will never evaluate to 'true' - --> tests/ui/const_comparisons.rs:62:5 + --> tests/ui/const_comparisons.rs:61:5 | LL | status_code <= u16::MIN + 1 && status_code > STATUS_SERVER_ERROR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | status_code <= u16::MIN + 1 && status_code > STATUS_SERVER_ERROR; = note: since `u16::MIN + 1` < `STATUS_SERVER_ERROR`, the expression evaluates to false for any value of `status_code` error: boolean expression will never evaluate to 'true' - --> tests/ui/const_comparisons.rs:65:5 + --> tests/ui/const_comparisons.rs:64:5 | LL | status_code < STATUS_SERVER_ERROR && status_code > STATUS_SERVER_ERROR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -57,7 +57,7 @@ LL | status_code < STATUS_SERVER_ERROR && status_code > STATUS_SERVER_ERROR; = note: `status_code` cannot simultaneously be greater than and less than `STATUS_SERVER_ERROR` error: boolean expression will never evaluate to 'true' - --> tests/ui/const_comparisons.rs:70:5 + --> tests/ui/const_comparisons.rs:68:5 | LL | status < { 400 } && status > { 500 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | status < { 400 } && status > { 500 }; = note: since `{ 400 }` < `{ 500 }`, the expression evaluates to false for any value of `status` error: boolean expression will never evaluate to 'true' - --> tests/ui/const_comparisons.rs:73:5 + --> tests/ui/const_comparisons.rs:71:5 | LL | status < STATUS_BAD_REQUEST && status > STATUS_SERVER_ERROR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | status < STATUS_BAD_REQUEST && status > STATUS_SERVER_ERROR; = note: since `STATUS_BAD_REQUEST` < `STATUS_SERVER_ERROR`, the expression evaluates to false for any value of `status` error: boolean expression will never evaluate to 'true' - --> tests/ui/const_comparisons.rs:76:5 + --> tests/ui/const_comparisons.rs:74:5 | LL | status <= u16::MIN + 1 && status > STATUS_SERVER_ERROR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -81,7 +81,7 @@ LL | status <= u16::MIN + 1 && status > STATUS_SERVER_ERROR; = note: since `u16::MIN + 1` < `STATUS_SERVER_ERROR`, the expression evaluates to false for any value of `status` error: boolean expression will never evaluate to 'true' - --> tests/ui/const_comparisons.rs:79:5 + --> tests/ui/const_comparisons.rs:77:5 | LL | status < STATUS_SERVER_ERROR && status > STATUS_SERVER_ERROR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -89,7 +89,7 @@ LL | status < STATUS_SERVER_ERROR && status > STATUS_SERVER_ERROR; = note: `status` cannot simultaneously be greater than and less than `STATUS_SERVER_ERROR` error: boolean expression will never evaluate to 'true' - --> tests/ui/const_comparisons.rs:89:5 + --> tests/ui/const_comparisons.rs:86:5 | LL | 500 >= status_code && 600 < status_code; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL | 500 >= status_code && 600 < status_code; = note: since `500` < `600`, the expression evaluates to false for any value of `status_code` error: boolean expression will never evaluate to 'true' - --> tests/ui/const_comparisons.rs:93:5 + --> tests/ui/const_comparisons.rs:90:5 | LL | 500 >= status_code && status_code > 600; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -105,7 +105,7 @@ LL | 500 >= status_code && status_code > 600; = note: since `500` < `600`, the expression evaluates to false for any value of `status_code` error: boolean expression will never evaluate to 'true' - --> tests/ui/const_comparisons.rs:103:5 + --> tests/ui/const_comparisons.rs:99:5 | LL | 500 >= status && 600 < status; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -113,7 +113,7 @@ LL | 500 >= status && 600 < status; = note: since `500` < `600`, the expression evaluates to false for any value of `status` error: boolean expression will never evaluate to 'true' - --> tests/ui/const_comparisons.rs:107:5 + --> tests/ui/const_comparisons.rs:103:5 | LL | 500 >= status && status > 600; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,13 +121,13 @@ LL | 500 >= status && status > 600; = note: since `500` < `600`, the expression evaluates to false for any value of `status` error: right-hand side of `&&` operator has no effect - --> tests/ui/const_comparisons.rs:112:5 + --> tests/ui/const_comparisons.rs:107:5 | LL | status_code < 200 && status_code <= 299; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `if `status_code < 200` evaluates to true, status_code <= 299` will always evaluate to true as well - --> tests/ui/const_comparisons.rs:112:23 + --> tests/ui/const_comparisons.rs:107:23 | LL | status_code < 200 && status_code <= 299; | ^^^^^^^^^^^^^^^^^^^^^ @@ -135,67 +135,67 @@ LL | status_code < 200 && status_code <= 299; = help: to override `-D warnings` add `#[allow(clippy::redundant_comparisons)]` error: left-hand side of `&&` operator has no effect - --> tests/ui/const_comparisons.rs:114:5 + --> tests/ui/const_comparisons.rs:110:5 | LL | status_code > 200 && status_code >= 299; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `if `status_code >= 299` evaluates to true, status_code > 200` will always evaluate to true as well - --> tests/ui/const_comparisons.rs:114:5 + --> tests/ui/const_comparisons.rs:110:5 | LL | status_code > 200 && status_code >= 299; | ^^^^^^^^^^^^^^^^^^^^^ error: left-hand side of `&&` operator has no effect - --> tests/ui/const_comparisons.rs:118:5 + --> tests/ui/const_comparisons.rs:114:5 | LL | status_code >= 500 && status_code > 500; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `if `status_code > 500` evaluates to true, status_code >= 500` will always evaluate to true as well - --> tests/ui/const_comparisons.rs:118:5 + --> tests/ui/const_comparisons.rs:114:5 | LL | status_code >= 500 && status_code > 500; | ^^^^^^^^^^^^^^^^^^^^^^ error: right-hand side of `&&` operator has no effect - --> tests/ui/const_comparisons.rs:121:5 + --> tests/ui/const_comparisons.rs:118:5 | LL | status_code > 500 && status_code >= 500; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `if `status_code > 500` evaluates to true, status_code >= 500` will always evaluate to true as well - --> tests/ui/const_comparisons.rs:121:23 + --> tests/ui/const_comparisons.rs:118:23 | LL | status_code > 500 && status_code >= 500; | ^^^^^^^^^^^^^^^^^^^^^ error: left-hand side of `&&` operator has no effect - --> tests/ui/const_comparisons.rs:124:5 + --> tests/ui/const_comparisons.rs:122:5 | LL | status_code <= 500 && status_code < 500; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `if `status_code < 500` evaluates to true, status_code <= 500` will always evaluate to true as well - --> tests/ui/const_comparisons.rs:124:5 + --> tests/ui/const_comparisons.rs:122:5 | LL | status_code <= 500 && status_code < 500; | ^^^^^^^^^^^^^^^^^^^^^^ error: right-hand side of `&&` operator has no effect - --> tests/ui/const_comparisons.rs:127:5 + --> tests/ui/const_comparisons.rs:126:5 | LL | status_code < 500 && status_code <= 500; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `if `status_code < 500` evaluates to true, status_code <= 500` will always evaluate to true as well - --> tests/ui/const_comparisons.rs:127:23 + --> tests/ui/const_comparisons.rs:126:23 | LL | status_code < 500 && status_code <= 500; | ^^^^^^^^^^^^^^^^^^^^^ error: boolean expression will never evaluate to 'true' - --> tests/ui/const_comparisons.rs:132:5 + --> tests/ui/const_comparisons.rs:131:5 | LL | name < "Jennifer" && name > "Shannon"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -203,7 +203,7 @@ LL | name < "Jennifer" && name > "Shannon"; = note: since `"Jennifer"` < `"Shannon"`, the expression evaluates to false for any value of `name` error: boolean expression will never evaluate to 'true' - --> tests/ui/const_comparisons.rs:137:5 + --> tests/ui/const_comparisons.rs:135:5 | LL | numbers < [3, 4] && numbers > [5, 6]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -211,7 +211,7 @@ LL | numbers < [3, 4] && numbers > [5, 6]; = note: since `[3, 4]` < `[5, 6]`, the expression evaluates to false for any value of `numbers` error: boolean expression will never evaluate to 'true' - --> tests/ui/const_comparisons.rs:142:5 + --> tests/ui/const_comparisons.rs:139:5 | LL | letter < 'b' && letter > 'c'; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -219,7 +219,7 @@ LL | letter < 'b' && letter > 'c'; = note: since `'b'` < `'c'`, the expression evaluates to false for any value of `letter` error: boolean expression will never evaluate to 'true' - --> tests/ui/const_comparisons.rs:147:5 + --> tests/ui/const_comparisons.rs:143:5 | LL | area < std::f32::consts::E && area > std::f32::consts::PI; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const_is_empty.rs b/tests/ui/const_is_empty.rs index b5e27b61548a..8bb4f0e5d975 100644 --- a/tests/ui/const_is_empty.rs +++ b/tests/ui/const_is_empty.rs @@ -3,19 +3,19 @@ fn test_literal() { if "".is_empty() { - //~^ERROR: this expression always evaluates to true + //~^ const_is_empty } if "foobar".is_empty() { - //~^ERROR: this expression always evaluates to false + //~^ const_is_empty } } fn test_byte_literal() { if b"".is_empty() { - //~^ERROR: this expression always evaluates to true + //~^ const_is_empty } if b"foobar".is_empty() { - //~^ERROR: this expression always evaluates to false + //~^ const_is_empty } } @@ -32,10 +32,10 @@ fn test_propagated() { let empty2 = empty; let non_empty2 = non_empty; if empty2.is_empty() { - //~^ERROR: this expression always evaluates to true + //~^ const_is_empty } if non_empty2.is_empty() { - //~^ERROR: this expression always evaluates to false + //~^ const_is_empty } } @@ -57,48 +57,65 @@ const NON_EMPTY_REF_ARRAY: &[u32; 3] = &[1, 2, 3]; fn test_from_const() { let _ = EMPTY_STR.is_empty(); - //~^ ERROR: this expression always evaluates to true + //~^ const_is_empty + let _ = NON_EMPTY_STR.is_empty(); - //~^ ERROR: this expression always evaluates to false + //~^ const_is_empty + let _ = EMPTY_BSTR.is_empty(); - //~^ ERROR: this expression always evaluates to true + //~^ const_is_empty + let _ = NON_EMPTY_BSTR.is_empty(); - //~^ ERROR: this expression always evaluates to false + //~^ const_is_empty + let _ = EMPTY_ARRAY.is_empty(); - //~^ ERROR: this expression always evaluates to true + //~^ const_is_empty + let _ = EMPTY_ARRAY_REPEAT.is_empty(); - //~^ ERROR: this expression always evaluates to true + //~^ const_is_empty + let _ = EMPTY_U8_SLICE.is_empty(); - //~^ ERROR: this expression always evaluates to true + //~^ const_is_empty + let _ = NON_EMPTY_U8_SLICE.is_empty(); - //~^ ERROR: this expression always evaluates to false + //~^ const_is_empty + let _ = NON_EMPTY_ARRAY.is_empty(); - //~^ ERROR: this expression always evaluates to false + //~^ const_is_empty + let _ = NON_EMPTY_ARRAY_REPEAT.is_empty(); - //~^ ERROR: this expression always evaluates to false + //~^ const_is_empty + let _ = EMPTY_REF_ARRAY.is_empty(); - //~^ ERROR: this expression always evaluates to true + //~^ const_is_empty + let _ = NON_EMPTY_REF_ARRAY.is_empty(); - //~^ ERROR: this expression always evaluates to false + //~^ const_is_empty + let _ = EMPTY_SLICE.is_empty(); - //~^ ERROR: this expression always evaluates to true + //~^ const_is_empty + let _ = NON_EMPTY_SLICE.is_empty(); - //~^ ERROR: this expression always evaluates to false + //~^ const_is_empty + let _ = NON_EMPTY_SLICE_REPEAT.is_empty(); - //~^ ERROR: this expression always evaluates to false + //~^ const_is_empty } fn main() { let value = "foobar"; let _ = value.is_empty(); - //~^ ERROR: this expression always evaluates to false + //~^ const_is_empty + let x = value; let _ = x.is_empty(); - //~^ ERROR: this expression always evaluates to false + //~^ const_is_empty + let _ = "".is_empty(); - //~^ ERROR: this expression always evaluates to true + //~^ const_is_empty + let _ = b"".is_empty(); - //~^ ERROR: this expression always evaluates to true + //~^ const_is_empty } fn str_from_arg(var: &str) { @@ -152,7 +169,7 @@ fn not_cfg_conditioned() { let val = ""; #[cfg(not(target_os = "inexistent"))] let _ = val.is_empty(); - //~^ ERROR: this expression always evaluates to true + //~^ const_is_empty } const fn const_rand() -> &'static str { @@ -183,5 +200,6 @@ fn issue_13106() { const { EMPTY_STR.is_empty(); + //~^ const_is_empty } } diff --git a/tests/ui/const_is_empty.stderr b/tests/ui/const_is_empty.stderr index 0afba940d8b4..2ba189058e83 100644 --- a/tests/ui/const_is_empty.stderr +++ b/tests/ui/const_is_empty.stderr @@ -44,121 +44,121 @@ LL | let _ = EMPTY_STR.is_empty(); | ^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to false - --> tests/ui/const_is_empty.rs:61:13 + --> tests/ui/const_is_empty.rs:62:13 | LL | let _ = NON_EMPTY_STR.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:63:13 + --> tests/ui/const_is_empty.rs:65:13 | LL | let _ = EMPTY_BSTR.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to false - --> tests/ui/const_is_empty.rs:65:13 + --> tests/ui/const_is_empty.rs:68:13 | LL | let _ = NON_EMPTY_BSTR.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:67:13 + --> tests/ui/const_is_empty.rs:71:13 | LL | let _ = EMPTY_ARRAY.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:69:13 + --> tests/ui/const_is_empty.rs:74:13 | LL | let _ = EMPTY_ARRAY_REPEAT.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:71:13 + --> tests/ui/const_is_empty.rs:77:13 | LL | let _ = EMPTY_U8_SLICE.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to false - --> tests/ui/const_is_empty.rs:73:13 + --> tests/ui/const_is_empty.rs:80:13 | LL | let _ = NON_EMPTY_U8_SLICE.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to false - --> tests/ui/const_is_empty.rs:75:13 + --> tests/ui/const_is_empty.rs:83:13 | LL | let _ = NON_EMPTY_ARRAY.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to false - --> tests/ui/const_is_empty.rs:77:13 + --> tests/ui/const_is_empty.rs:86:13 | LL | let _ = NON_EMPTY_ARRAY_REPEAT.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:79:13 + --> tests/ui/const_is_empty.rs:89:13 | LL | let _ = EMPTY_REF_ARRAY.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to false - --> tests/ui/const_is_empty.rs:81:13 + --> tests/ui/const_is_empty.rs:92:13 | LL | let _ = NON_EMPTY_REF_ARRAY.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:83:13 + --> tests/ui/const_is_empty.rs:95:13 | LL | let _ = EMPTY_SLICE.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to false - --> tests/ui/const_is_empty.rs:85:13 + --> tests/ui/const_is_empty.rs:98:13 | LL | let _ = NON_EMPTY_SLICE.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to false - --> tests/ui/const_is_empty.rs:87:13 + --> tests/ui/const_is_empty.rs:101:13 | LL | let _ = NON_EMPTY_SLICE_REPEAT.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to false - --> tests/ui/const_is_empty.rs:93:13 + --> tests/ui/const_is_empty.rs:107:13 | LL | let _ = value.is_empty(); | ^^^^^^^^^^^^^^^^ error: this expression always evaluates to false - --> tests/ui/const_is_empty.rs:96:13 + --> tests/ui/const_is_empty.rs:111:13 | LL | let _ = x.is_empty(); | ^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:98:13 + --> tests/ui/const_is_empty.rs:114:13 | LL | let _ = "".is_empty(); | ^^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:100:13 + --> tests/ui/const_is_empty.rs:117:13 | LL | let _ = b"".is_empty(); | ^^^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:154:13 + --> tests/ui/const_is_empty.rs:171:13 | LL | let _ = val.is_empty(); | ^^^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:185:9 + --> tests/ui/const_is_empty.rs:202:9 | LL | EMPTY_STR.is_empty(); | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/copy_iterator.rs b/tests/ui/copy_iterator.rs index ea3a4face93f..5639583289d2 100644 --- a/tests/ui/copy_iterator.rs +++ b/tests/ui/copy_iterator.rs @@ -5,8 +5,8 @@ struct Countdown(u8); impl Iterator for Countdown { - //~^ ERROR: you are implementing `Iterator` on a `Copy` type - //~| NOTE: consider implementing `IntoIterator` instead + //~^ copy_iterator + type Item = u8; fn next(&mut self) -> Option { diff --git a/tests/ui/crashes/associated-constant-ice.rs b/tests/ui/crashes/associated-constant-ice.rs index fec16671eeb3..c5767cd656e9 100644 --- a/tests/ui/crashes/associated-constant-ice.rs +++ b/tests/ui/crashes/associated-constant-ice.rs @@ -1,3 +1,4 @@ +//@ check-pass // Test for https://github.com/rust-lang/rust-clippy/issues/1698 pub trait Trait { diff --git a/tests/ui/crashes/cc_seme.rs b/tests/ui/crashes/cc_seme.rs index 98897d6d7aaf..1d8e635ffe44 100644 --- a/tests/ui/crashes/cc_seme.rs +++ b/tests/ui/crashes/cc_seme.rs @@ -1,3 +1,4 @@ +//@ check-pass // Test for https://github.com/rust-lang/rust-clippy/issues/478 enum Baz { diff --git a/tests/ui/crashes/needless_lifetimes_impl_trait.fixed b/tests/ui/crashes/elidable_lifetime_names_impl_trait.fixed similarity index 65% rename from tests/ui/crashes/needless_lifetimes_impl_trait.fixed rename to tests/ui/crashes/elidable_lifetime_names_impl_trait.fixed index 837069cae6d1..681887314ed5 100644 --- a/tests/ui/crashes/needless_lifetimes_impl_trait.fixed +++ b/tests/ui/crashes/elidable_lifetime_names_impl_trait.fixed @@ -1,4 +1,4 @@ -#![deny(clippy::needless_lifetimes)] +#![deny(clippy::elidable_lifetime_names)] #![allow(dead_code)] trait Foo {} @@ -10,10 +10,12 @@ struct Baz<'a> { } impl Foo for Baz<'_> {} +//~^ elidable_lifetime_names impl Bar { fn baz(&self) -> impl Foo + '_ { - //~^ ERROR: the following explicit lifetimes could be elided: 'a + //~^ elidable_lifetime_names + Baz { bar: self } } } diff --git a/tests/ui/crashes/needless_lifetimes_impl_trait.rs b/tests/ui/crashes/elidable_lifetime_names_impl_trait.rs similarity index 66% rename from tests/ui/crashes/needless_lifetimes_impl_trait.rs rename to tests/ui/crashes/elidable_lifetime_names_impl_trait.rs index 06947e3a3513..ed5f95bdca82 100644 --- a/tests/ui/crashes/needless_lifetimes_impl_trait.rs +++ b/tests/ui/crashes/elidable_lifetime_names_impl_trait.rs @@ -1,4 +1,4 @@ -#![deny(clippy::needless_lifetimes)] +#![deny(clippy::elidable_lifetime_names)] #![allow(dead_code)] trait Foo {} @@ -10,10 +10,12 @@ struct Baz<'a> { } impl<'a> Foo for Baz<'a> {} +//~^ elidable_lifetime_names impl Bar { fn baz<'a>(&'a self) -> impl Foo + 'a { - //~^ ERROR: the following explicit lifetimes could be elided: 'a + //~^ elidable_lifetime_names + Baz { bar: self } } } diff --git a/tests/ui/crashes/needless_lifetimes_impl_trait.stderr b/tests/ui/crashes/elidable_lifetime_names_impl_trait.stderr similarity index 67% rename from tests/ui/crashes/needless_lifetimes_impl_trait.stderr rename to tests/ui/crashes/elidable_lifetime_names_impl_trait.stderr index bed6aab25c4d..ef4b7e0a476e 100644 --- a/tests/ui/crashes/needless_lifetimes_impl_trait.stderr +++ b/tests/ui/crashes/elidable_lifetime_names_impl_trait.stderr @@ -1,14 +1,14 @@ error: the following explicit lifetimes could be elided: 'a - --> tests/ui/crashes/needless_lifetimes_impl_trait.rs:12:6 + --> tests/ui/crashes/elidable_lifetime_names_impl_trait.rs:12:6 | LL | impl<'a> Foo for Baz<'a> {} | ^^ ^^ | note: the lint level is defined here - --> tests/ui/crashes/needless_lifetimes_impl_trait.rs:1:9 + --> tests/ui/crashes/elidable_lifetime_names_impl_trait.rs:1:9 | -LL | #![deny(clippy::needless_lifetimes)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![deny(clippy::elidable_lifetime_names)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: elide the lifetimes | LL - impl<'a> Foo for Baz<'a> {} @@ -16,7 +16,7 @@ LL + impl Foo for Baz<'_> {} | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/crashes/needless_lifetimes_impl_trait.rs:15:12 + --> tests/ui/crashes/elidable_lifetime_names_impl_trait.rs:16:12 | LL | fn baz<'a>(&'a self) -> impl Foo + 'a { | ^^ ^^ ^^ diff --git a/tests/ui/crashes/enum-glob-import-crate.rs b/tests/ui/crashes/enum-glob-import-crate.rs index dca32aa3b561..bbcd599f6d0b 100644 --- a/tests/ui/crashes/enum-glob-import-crate.rs +++ b/tests/ui/crashes/enum-glob-import-crate.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![deny(clippy::all)] #![allow(unused_imports)] diff --git a/tests/ui/crashes/ice-10148.rs b/tests/ui/crashes/ice-10148.rs index d89d94edbcdb..8baaccd811d7 100644 --- a/tests/ui/crashes/ice-10148.rs +++ b/tests/ui/crashes/ice-10148.rs @@ -6,4 +6,5 @@ use proc_macros::with_span; fn main() { println!(with_span!(""something "")); + //~^ println_empty_string } diff --git a/tests/ui/crashes/ice-10508a.rs b/tests/ui/crashes/ice-10508a.rs new file mode 100644 index 000000000000..43da01344555 --- /dev/null +++ b/tests/ui/crashes/ice-10508a.rs @@ -0,0 +1,20 @@ +//@ check-pass +// Used to overflow in `is_normalizable` + +use std::marker::PhantomData; + +struct Node { + m: PhantomData<&'static T>, +} + +struct Digit { + elem: T, +} + +enum FingerTree { + Single(T), + + Deep(Digit, Box>>), +} + +fn main() {} diff --git a/tests/ui/crashes/ice-10508b.rs b/tests/ui/crashes/ice-10508b.rs new file mode 100644 index 000000000000..7588419381cf --- /dev/null +++ b/tests/ui/crashes/ice-10508b.rs @@ -0,0 +1,26 @@ +//@ check-pass + +use std::marker::PhantomData; + +struct Digit { + elem: T, +} + +struct Node { + m: PhantomData<&'static T>, +} + +enum FingerTree { + Single(T), + + Deep(Digit, Node>>), +} + +enum Wrapper { + Simple, + Other(FingerTree), +} + +fn main() { + let w = Some(Wrapper::Simple::); +} diff --git a/tests/ui/crashes/ice-10508c.rs b/tests/ui/crashes/ice-10508c.rs new file mode 100644 index 000000000000..d207fdb2c87a --- /dev/null +++ b/tests/ui/crashes/ice-10508c.rs @@ -0,0 +1,9 @@ +//@ check-pass + +#[derive(Debug)] +struct S { + t: T, + s: Box>, +} + +fn main() {} diff --git a/tests/ui/crashes/ice-10972-tait.rs b/tests/ui/crashes/ice-10972-tait.rs index f3ab9cebb7c2..11ddbfc3a04b 100644 --- a/tests/ui/crashes/ice-10972-tait.rs +++ b/tests/ui/crashes/ice-10972-tait.rs @@ -1,3 +1,4 @@ +//@ check-pass // ICE: #10972 // asked to assemble constituent types of unexpected type: Binder(Foo, []) #![feature(type_alias_impl_trait)] diff --git a/tests/ui/crashes/ice-11065.rs b/tests/ui/crashes/ice-11065.rs index a17d7e38e0c3..434f11a2c577 100644 --- a/tests/ui/crashes/ice-11065.rs +++ b/tests/ui/crashes/ice-11065.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::useless_conversion)] use std::option::IntoIter as OptionIter; diff --git a/tests/ui/crashes/ice-11230.fixed b/tests/ui/crashes/ice-11230.fixed index 1d4c3dd9dcc4..181e1ebbe5a3 100644 --- a/tests/ui/crashes/ice-11230.fixed +++ b/tests/ui/crashes/ice-11230.fixed @@ -6,6 +6,7 @@ fn main() { const A: &[for<'a> fn(&'a ())] = &[]; for v in A {} + //~^ explicit_iter_loop } // needless_collect @@ -13,4 +14,5 @@ trait Helper<'a>: Iterator {} fn x(w: &mut dyn for<'a> Helper<'a>) { w.next().is_none(); + //~^ needless_collect } diff --git a/tests/ui/crashes/ice-11230.rs b/tests/ui/crashes/ice-11230.rs index a16fb271497c..fb05dc781bc0 100644 --- a/tests/ui/crashes/ice-11230.rs +++ b/tests/ui/crashes/ice-11230.rs @@ -6,6 +6,7 @@ fn main() { const A: &[for<'a> fn(&'a ())] = &[]; for v in A.iter() {} + //~^ explicit_iter_loop } // needless_collect @@ -13,4 +14,5 @@ trait Helper<'a>: Iterator {} fn x(w: &mut dyn for<'a> Helper<'a>) { w.collect::>().is_empty(); + //~^ needless_collect } diff --git a/tests/ui/crashes/ice-11230.stderr b/tests/ui/crashes/ice-11230.stderr index 7167d90e456e..b4a3f67081ae 100644 --- a/tests/ui/crashes/ice-11230.stderr +++ b/tests/ui/crashes/ice-11230.stderr @@ -8,7 +8,7 @@ LL | for v in A.iter() {} = help: to override `-D warnings` add `#[allow(clippy::explicit_iter_loop)]` error: avoid using `collect()` when not needed - --> tests/ui/crashes/ice-11230.rs:15:7 + --> tests/ui/crashes/ice-11230.rs:16:7 | LL | w.collect::>().is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()` diff --git a/tests/ui/crashes/ice-11337.rs b/tests/ui/crashes/ice-11337.rs index 0bed4035f6bf..317b7a7083a6 100644 --- a/tests/ui/crashes/ice-11337.rs +++ b/tests/ui/crashes/ice-11337.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![feature(trait_alias)] trait Confusing = Fn(i32) where F: Fn(u32); diff --git a/tests/ui/crashes/ice-11422.fixed b/tests/ui/crashes/ice-11422.fixed index d996b1db08a6..be07a9d8c1f9 100644 --- a/tests/ui/crashes/ice-11422.fixed +++ b/tests/ui/crashes/ice-11422.fixed @@ -4,6 +4,7 @@ use std::fmt::Debug; use std::ops::*; fn r#gen() -> impl PartialOrd + Debug {} +//~^ implied_bounds_in_impls struct Bar {} trait Foo {} diff --git a/tests/ui/crashes/ice-11422.rs b/tests/ui/crashes/ice-11422.rs index eb89b7c38f43..43de882caa11 100644 --- a/tests/ui/crashes/ice-11422.rs +++ b/tests/ui/crashes/ice-11422.rs @@ -4,6 +4,7 @@ use std::fmt::Debug; use std::ops::*; fn r#gen() -> impl PartialOrd + PartialEq + Debug {} +//~^ implied_bounds_in_impls struct Bar {} trait Foo {} diff --git a/tests/ui/crashes/ice-11755.rs b/tests/ui/crashes/ice-11755.rs index 367cb6998578..d6aa1e5183d2 100644 --- a/tests/ui/crashes/ice-11755.rs +++ b/tests/ui/crashes/ice-11755.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::unused_enumerate_index)] fn main() { diff --git a/tests/ui/crashes/ice-11803.rs b/tests/ui/crashes/ice-11803.rs index 1bb8bf0c746b..e85f31909388 100644 --- a/tests/ui/crashes/ice-11803.rs +++ b/tests/ui/crashes/ice-11803.rs @@ -3,6 +3,8 @@ #![warn(clippy::impl_trait_in_params)] pub fn g>>() { + //~^ impl_trait_in_params + //~| impl_trait_in_params extern "C" fn implementation_detail() {} } diff --git a/tests/ui/crashes/ice-11939.rs b/tests/ui/crashes/ice-11939.rs index 5e7193b68264..ce7a0de1ac3a 100644 --- a/tests/ui/crashes/ice-11939.rs +++ b/tests/ui/crashes/ice-11939.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(clippy::unit_arg, clippy::no_effect)] const fn v(_: ()) {} diff --git a/tests/ui/crashes/ice-12253.rs b/tests/ui/crashes/ice-12253.rs index 41f50035144a..58ad7c3bfbf5 100644 --- a/tests/ui/crashes/ice-12253.rs +++ b/tests/ui/crashes/ice-12253.rs @@ -1,3 +1,5 @@ +//@ check-pass + #[allow(overflowing_literals, unconditional_panic, clippy::no_effect)] fn main() { let arr: [i32; 5] = [0; 5]; diff --git a/tests/ui/crashes/ice-12491.fixed b/tests/ui/crashes/ice-12491.fixed index 4ea480b0663c..ab9c61463e92 100644 --- a/tests/ui/crashes/ice-12491.fixed +++ b/tests/ui/crashes/ice-12491.fixed @@ -3,5 +3,6 @@ fn main() { if (true) { // anything一些中文 + //~^^ needless_return } } diff --git a/tests/ui/crashes/ice-12491.rs b/tests/ui/crashes/ice-12491.rs index 60add6afa2c4..b774bd3788a7 100644 --- a/tests/ui/crashes/ice-12491.rs +++ b/tests/ui/crashes/ice-12491.rs @@ -4,5 +4,6 @@ fn main() { if (true) { // anything一些中文 return; + //~^^ needless_return } } diff --git a/tests/ui/crashes/ice-12585.rs b/tests/ui/crashes/ice-12585.rs index 7928115c0a94..f35e95c6bc34 100644 --- a/tests/ui/crashes/ice-12585.rs +++ b/tests/ui/crashes/ice-12585.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(clippy::unit_arg)] struct One { diff --git a/tests/ui/crashes/ice-12616.fixed b/tests/ui/crashes/ice-12616.fixed index a5a5b3d1e78e..b7840cabc6b4 100644 --- a/tests/ui/crashes/ice-12616.fixed +++ b/tests/ui/crashes/ice-12616.fixed @@ -4,4 +4,5 @@ fn main() { let s = std::ptr::null::<()>; s().cast::<()>(); + //~^ ptr_as_ptr } diff --git a/tests/ui/crashes/ice-12616.rs b/tests/ui/crashes/ice-12616.rs index 6ee9a5ec08fe..bb37b2e6a679 100644 --- a/tests/ui/crashes/ice-12616.rs +++ b/tests/ui/crashes/ice-12616.rs @@ -4,4 +4,5 @@ fn main() { let s = std::ptr::null::<()>; s() as *const (); + //~^ ptr_as_ptr } diff --git a/tests/ui/crashes/ice-13862.rs b/tests/ui/crashes/ice-13862.rs index a5f010054b2f..774774e6245b 100644 --- a/tests/ui/crashes/ice-13862.rs +++ b/tests/ui/crashes/ice-13862.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![crate_type = "lib"] #![no_std] diff --git a/tests/ui/crashes/ice-14303.rs b/tests/ui/crashes/ice-14303.rs new file mode 100644 index 000000000000..e81f29cd7af9 --- /dev/null +++ b/tests/ui/crashes/ice-14303.rs @@ -0,0 +1,12 @@ +//@check-pass +#![warn(clippy::macro_use_imports)] + +#[repr(transparent)] +pub struct X(()); + +#[repr(u8)] +pub enum Action { + Off = 0, +} + +fn main() {} diff --git a/tests/ui/crashes/ice-14325.rs b/tests/ui/crashes/ice-14325.rs new file mode 100644 index 000000000000..d762bd6c9e00 --- /dev/null +++ b/tests/ui/crashes/ice-14325.rs @@ -0,0 +1,17 @@ +//@check-pass + +#![allow(clippy::redundant_pattern_matching)] + +struct S<'a> { + s: &'a str, +} + +fn foo() -> Option> { + if let Some(_) = Some(0) { + Some(S { s: "xyz" }) + } else { + None + } +} + +fn main() {} diff --git a/tests/ui/crashes/ice-1588.rs b/tests/ui/crashes/ice-1588.rs index 9ec093721c17..3ccd33052cd6 100644 --- a/tests/ui/crashes/ice-1588.rs +++ b/tests/ui/crashes/ice-1588.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(clippy::all)] // Test for https://github.com/rust-lang/rust-clippy/issues/1588 diff --git a/tests/ui/crashes/ice-1782.rs b/tests/ui/crashes/ice-1782.rs index 73de5721cbc1..fefdc405cce2 100644 --- a/tests/ui/crashes/ice-1782.rs +++ b/tests/ui/crashes/ice-1782.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(dead_code, unused_variables)] #![allow(clippy::unnecessary_cast, clippy::missing_transmute_annotations)] diff --git a/tests/ui/crashes/ice-1969.rs b/tests/ui/crashes/ice-1969.rs index eb901c767294..34ff725d7117 100644 --- a/tests/ui/crashes/ice-1969.rs +++ b/tests/ui/crashes/ice-1969.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(clippy::all)] // Test for https://github.com/rust-lang/rust-clippy/issues/1969 diff --git a/tests/ui/crashes/ice-2499.rs b/tests/ui/crashes/ice-2499.rs index 732f331ad145..685c28ff4d6a 100644 --- a/tests/ui/crashes/ice-2499.rs +++ b/tests/ui/crashes/ice-2499.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(dead_code, clippy::char_lit_as_u8, clippy::needless_bool)] // Should not trigger an ICE in `SpanlessHash` / `consts::constant` diff --git a/tests/ui/crashes/ice-2594.rs b/tests/ui/crashes/ice-2594.rs index dddf860bd178..d4d9e74cc193 100644 --- a/tests/ui/crashes/ice-2594.rs +++ b/tests/ui/crashes/ice-2594.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(dead_code, unused_variables)] /// Should not trigger an ICE in `SpanlessHash` / `consts::constant` diff --git a/tests/ui/crashes/ice-2727.rs b/tests/ui/crashes/ice-2727.rs index 59fb9b04b86d..92287459424f 100644 --- a/tests/ui/crashes/ice-2727.rs +++ b/tests/ui/crashes/ice-2727.rs @@ -1,3 +1,4 @@ +//@ check-pass // Test for https://github.com/rust-lang/rust-clippy/issues/2727 pub fn f(new: fn()) { diff --git a/tests/ui/crashes/ice-2760.rs b/tests/ui/crashes/ice-2760.rs index 5f7d91abf995..188d90fcae22 100644 --- a/tests/ui/crashes/ice-2760.rs +++ b/tests/ui/crashes/ice-2760.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow( unused_variables, clippy::disallowed_names, diff --git a/tests/ui/crashes/ice-2774.fixed b/tests/ui/crashes/ice-2774.fixed index 96cf0d8540cd..35d969441763 100644 --- a/tests/ui/crashes/ice-2774.fixed +++ b/tests/ui/crashes/ice-2774.fixed @@ -13,8 +13,8 @@ pub struct Foo; #[allow(clippy::implicit_hasher)] // This should not cause a "cannot relate bound region" ICE. pub fn add_barfoos_to_foos(bars: &HashSet<&Bar>) { - //~^ ERROR: the following explicit lifetimes could be elided: 'a - //~| NOTE: `-D clippy::needless-lifetimes` implied by `-D warnings` + //~^ needless_lifetimes + let mut foos = HashSet::new(); foos.extend(bars.iter().map(|b| &b.foo)); } diff --git a/tests/ui/crashes/ice-2774.rs b/tests/ui/crashes/ice-2774.rs index 464d7891c9f4..1eb6df0095ed 100644 --- a/tests/ui/crashes/ice-2774.rs +++ b/tests/ui/crashes/ice-2774.rs @@ -13,8 +13,8 @@ pub struct Foo; #[allow(clippy::implicit_hasher)] // This should not cause a "cannot relate bound region" ICE. pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) { - //~^ ERROR: the following explicit lifetimes could be elided: 'a - //~| NOTE: `-D clippy::needless-lifetimes` implied by `-D warnings` + //~^ needless_lifetimes + let mut foos = HashSet::new(); foos.extend(bars.iter().map(|b| &b.foo)); } diff --git a/tests/ui/crashes/ice-2862.rs b/tests/ui/crashes/ice-2862.rs index 2573b571f55c..e27bdba04e80 100644 --- a/tests/ui/crashes/ice-2862.rs +++ b/tests/ui/crashes/ice-2862.rs @@ -1,3 +1,4 @@ +//@ check-pass // Test for https://github.com/rust-lang/rust-clippy/issues/2862 pub trait FooMap { diff --git a/tests/ui/crashes/ice-2865.rs b/tests/ui/crashes/ice-2865.rs index 28363707acca..681d10a75014 100644 --- a/tests/ui/crashes/ice-2865.rs +++ b/tests/ui/crashes/ice-2865.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(dead_code, clippy::extra_unused_lifetimes)] // Test for https://github.com/rust-lang/rust-clippy/issues/2865 diff --git a/tests/ui/crashes/ice-3151.rs b/tests/ui/crashes/ice-3151.rs index f88a26cb4859..f0c57d2f19f4 100644 --- a/tests/ui/crashes/ice-3151.rs +++ b/tests/ui/crashes/ice-3151.rs @@ -1,3 +1,4 @@ +//@ check-pass // Test for https://github.com/rust-lang/rust-clippy/issues/3151 #[derive(Clone)] diff --git a/tests/ui/crashes/ice-3462.rs b/tests/ui/crashes/ice-3462.rs index ccd617e305da..4ce484917ae2 100644 --- a/tests/ui/crashes/ice-3462.rs +++ b/tests/ui/crashes/ice-3462.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::all)] #![allow(clippy::disallowed_names, clippy::equatable_if_let, clippy::needless_if)] #![allow(unused)] diff --git a/tests/ui/crashes/ice-360.rs b/tests/ui/crashes/ice-360.rs index 0d10932b0987..cb8176a2973f 100644 --- a/tests/ui/crashes/ice-360.rs +++ b/tests/ui/crashes/ice-360.rs @@ -3,14 +3,14 @@ fn main() {} fn no_panic(slice: &[T]) { let mut iter = slice.iter(); loop { - //~^ ERROR: this loop never actually loops - //~| ERROR: this loop could be written as a `while let` loop - //~| NOTE: `-D clippy::while-let-loop` implied by `-D warnings` + //~^ never_loop + //~| while_let_loop + let _ = match iter.next() { Some(ele) => ele, None => break, }; loop {} - //~^ ERROR: empty `loop {}` wastes CPU cycles + //~^ empty_loop } } diff --git a/tests/ui/crashes/ice-3717.fixed b/tests/ui/crashes/ice-3717.fixed index 3f54b326979c..5581b67fa5c4 100644 --- a/tests/ui/crashes/ice-3717.fixed +++ b/tests/ui/crashes/ice-3717.fixed @@ -5,7 +5,8 @@ use std::collections::HashSet; fn main() {} pub fn ice_3717(_: &HashSet) { - //~^ ERROR: parameter of type `HashSet` should be generalized over different hashers + //~^ implicit_hasher + let _ = [0u8; 0]; let _: HashSet = HashSet::default(); } diff --git a/tests/ui/crashes/ice-3717.rs b/tests/ui/crashes/ice-3717.rs index 2890a9277c71..c612270865c5 100644 --- a/tests/ui/crashes/ice-3717.rs +++ b/tests/ui/crashes/ice-3717.rs @@ -5,7 +5,8 @@ use std::collections::HashSet; fn main() {} pub fn ice_3717(_: &HashSet) { - //~^ ERROR: parameter of type `HashSet` should be generalized over different hashers + //~^ implicit_hasher + let _ = [0u8; 0]; let _: HashSet = HashSet::new(); } diff --git a/tests/ui/crashes/ice-3717.stderr b/tests/ui/crashes/ice-3717.stderr index aac72c669654..2e53b610922e 100644 --- a/tests/ui/crashes/ice-3717.stderr +++ b/tests/ui/crashes/ice-3717.stderr @@ -13,6 +13,7 @@ help: add a type parameter for `BuildHasher` | LL ~ pub fn ice_3717(_: &HashSet) { LL | +LL | LL | let _ = [0u8; 0]; LL ~ let _: HashSet = HashSet::default(); | diff --git a/tests/ui/crashes/ice-3741.rs b/tests/ui/crashes/ice-3741.rs index 3106a2e72169..d8c02b1ba452 100644 --- a/tests/ui/crashes/ice-3741.rs +++ b/tests/ui/crashes/ice-3741.rs @@ -1,3 +1,4 @@ +//@ check-pass //@aux-build:proc_macro_crash.rs #![warn(clippy::suspicious_else_formatting)] diff --git a/tests/ui/crashes/ice-3747.rs b/tests/ui/crashes/ice-3747.rs index 44b1d7ed1b2e..62c7835ac55c 100644 --- a/tests/ui/crashes/ice-3747.rs +++ b/tests/ui/crashes/ice-3747.rs @@ -1,3 +1,4 @@ +//@ check-pass // Test for https://github.com/rust-lang/rust-clippy/issues/3747 macro_rules! a { diff --git a/tests/ui/crashes/ice-3969.rs b/tests/ui/crashes/ice-3969.rs index ac09ce08753a..fa3ca6f1d538 100644 --- a/tests/ui/crashes/ice-3969.rs +++ b/tests/ui/crashes/ice-3969.rs @@ -18,13 +18,12 @@ struct Dst { struct TwoStrs(str, str) where str: Sized; -//~^ ERROR: trait bound str: std::marker::Sized does not depend on any type or lifetime -//~| NOTE: `-D trivial-bounds` implied by `-D warnings` +//~^ ERROR: trait bound fn unsized_local() where for<'a> Dst: Sized, - //~^ ERROR: trait bound for<'a> Dst<(dyn A + 'a)>: std::marker::Sized does not depend + //~^ ERROR: trait bound { let x: Dst = *(Box::new(Dst { x: 1 }) as Box>); } @@ -32,7 +31,7 @@ where fn return_str() -> str where str: Sized, - //~^ ERROR: trait bound str: std::marker::Sized does not depend on any type or lifetim + //~^ ERROR: trait bound { *"Sized".to_string().into_boxed_str() } @@ -40,7 +39,7 @@ where fn use_op(s: String) -> String where String: ::std::ops::Neg, - //~^ ERROR: trait bound std::string::String: std::ops::Neg does not depend on any type + //~^ ERROR: trait bound { -s } @@ -48,7 +47,7 @@ where fn use_for() where i32: Iterator, - //~^ ERROR: trait bound i32: std::iter::Iterator does not depend on any type or lifeti + //~^ ERROR: trait bound { for _ in 2i32 {} } diff --git a/tests/ui/crashes/ice-3969.stderr b/tests/ui/crashes/ice-3969.stderr index 285efee36bd8..b820ecf7e332 100644 --- a/tests/ui/crashes/ice-3969.stderr +++ b/tests/ui/crashes/ice-3969.stderr @@ -8,25 +8,25 @@ LL | str: Sized; = help: to override `-D warnings` add `#[allow(trivial_bounds)]` error: trait bound for<'a> Dst<(dyn A + 'a)>: std::marker::Sized does not depend on any type or lifetime parameters - --> tests/ui/crashes/ice-3969.rs:26:30 + --> tests/ui/crashes/ice-3969.rs:25:30 | LL | for<'a> Dst: Sized, | ^^^^^ error: trait bound str: std::marker::Sized does not depend on any type or lifetime parameters - --> tests/ui/crashes/ice-3969.rs:34:10 + --> tests/ui/crashes/ice-3969.rs:33:10 | LL | str: Sized, | ^^^^^ error: trait bound std::string::String: std::ops::Neg does not depend on any type or lifetime parameters - --> tests/ui/crashes/ice-3969.rs:42:13 + --> tests/ui/crashes/ice-3969.rs:41:13 | LL | String: ::std::ops::Neg, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: trait bound i32: std::iter::Iterator does not depend on any type or lifetime parameters - --> tests/ui/crashes/ice-3969.rs:50:10 + --> tests/ui/crashes/ice-3969.rs:49:10 | LL | i32: Iterator, | ^^^^^^^^ diff --git a/tests/ui/crashes/ice-4121.rs b/tests/ui/crashes/ice-4121.rs index e1a142fdcb67..a1192b229ecd 100644 --- a/tests/ui/crashes/ice-4121.rs +++ b/tests/ui/crashes/ice-4121.rs @@ -1,3 +1,5 @@ +//@ check-pass + use std::mem; pub struct Foo(A, B); diff --git a/tests/ui/crashes/ice-4545.rs b/tests/ui/crashes/ice-4545.rs index d9c9c2096d97..1d7cb53ee7be 100644 --- a/tests/ui/crashes/ice-4545.rs +++ b/tests/ui/crashes/ice-4545.rs @@ -1,3 +1,5 @@ +//@ check-pass + fn repro() { trait Foo { type Bar; diff --git a/tests/ui/crashes/ice-4579.rs b/tests/ui/crashes/ice-4579.rs index 2e7e279f847d..14c8113e315b 100644 --- a/tests/ui/crashes/ice-4579.rs +++ b/tests/ui/crashes/ice-4579.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(clippy::single_match)] use std::ptr; diff --git a/tests/ui/crashes/ice-4671.rs b/tests/ui/crashes/ice-4671.rs index 64e8e7769412..3309d51302e2 100644 --- a/tests/ui/crashes/ice-4671.rs +++ b/tests/ui/crashes/ice-4671.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::use_self)] #[macro_use] diff --git a/tests/ui/crashes/ice-4727.rs b/tests/ui/crashes/ice-4727.rs index 2a4bc83f58a5..f90c6ca9a679 100644 --- a/tests/ui/crashes/ice-4727.rs +++ b/tests/ui/crashes/ice-4727.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::use_self)] #[path = "auxiliary/ice-4727-aux.rs"] diff --git a/tests/ui/crashes/ice-4760.rs b/tests/ui/crashes/ice-4760.rs index e1265169762f..07387db7b294 100644 --- a/tests/ui/crashes/ice-4760.rs +++ b/tests/ui/crashes/ice-4760.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(non_local_definitions)] const COUNT: usize = 2; diff --git a/tests/ui/crashes/ice-4775.rs b/tests/ui/crashes/ice-4775.rs index f693aafd1cbb..dd6c6b8de25a 100644 --- a/tests/ui/crashes/ice-4775.rs +++ b/tests/ui/crashes/ice-4775.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(clippy::uninlined_format_args)] pub struct ArrayWrapper([usize; N]); diff --git a/tests/ui/crashes/ice-4968.rs b/tests/ui/crashes/ice-4968.rs index 50473868005e..542cb63516da 100644 --- a/tests/ui/crashes/ice-4968.rs +++ b/tests/ui/crashes/ice-4968.rs @@ -1,3 +1,4 @@ +//@ check-pass // Test for https://github.com/rust-lang/rust-clippy/issues/4968 #![warn(clippy::unsound_collection_transmute)] diff --git a/tests/ui/crashes/ice-5207.rs b/tests/ui/crashes/ice-5207.rs index 0df8b88fea2f..6e438bcc2843 100644 --- a/tests/ui/crashes/ice-5207.rs +++ b/tests/ui/crashes/ice-5207.rs @@ -1,3 +1,4 @@ +//@ check-pass // Regression test for https://github.com/rust-lang/rust-clippy/issues/5207 pub async fn bar<'a, T: 'a>(_: T) {} diff --git a/tests/ui/crashes/ice-5223.rs b/tests/ui/crashes/ice-5223.rs index e3b3b27a6fc3..c055e551b298 100644 --- a/tests/ui/crashes/ice-5223.rs +++ b/tests/ui/crashes/ice-5223.rs @@ -1,3 +1,4 @@ +//@ check-pass // Regression test for #5233 #![warn(clippy::indexing_slicing, clippy::iter_cloned_collect)] diff --git a/tests/ui/crashes/ice-5238.rs b/tests/ui/crashes/ice-5238.rs index ee2ae4f1a042..1d7dd8c76507 100644 --- a/tests/ui/crashes/ice-5238.rs +++ b/tests/ui/crashes/ice-5238.rs @@ -1,3 +1,4 @@ +//@ check-pass // Regression test for #5238 / https://github.com/rust-lang/rust/pull/69562 #![feature(coroutines, coroutine_trait, stmt_expr_attributes)] diff --git a/tests/ui/crashes/ice-5389.rs b/tests/ui/crashes/ice-5389.rs index de262199004b..b54562095a21 100644 --- a/tests/ui/crashes/ice-5389.rs +++ b/tests/ui/crashes/ice-5389.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(clippy::explicit_counter_loop)] fn main() { diff --git a/tests/ui/crashes/ice-5579.rs b/tests/ui/crashes/ice-5579.rs index 8ab36bbf93cb..e3e408a52539 100644 --- a/tests/ui/crashes/ice-5579.rs +++ b/tests/ui/crashes/ice-5579.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(clippy::unnecessary_literal_unwrap)] trait IsErr { diff --git a/tests/ui/crashes/ice-5835.1.fixed b/tests/ui/crashes/ice-5835.1.fixed new file mode 100644 index 000000000000..acd61a9bd6c3 --- /dev/null +++ b/tests/ui/crashes/ice-5835.1.fixed @@ -0,0 +1,11 @@ +#[rustfmt::skip] +pub struct Foo { + /// 位 + //~^ tabs_in_doc_comments + //~| empty_line_after_doc_comments + /// ^ Do not remove this tab character. + /// It was required to trigger the ICE. + pub bar: u8, +} + +fn main() {} diff --git a/tests/ui/crashes/ice-5835.2.fixed b/tests/ui/crashes/ice-5835.2.fixed new file mode 100644 index 000000000000..71d2ec0c0018 --- /dev/null +++ b/tests/ui/crashes/ice-5835.2.fixed @@ -0,0 +1,13 @@ +#[rustfmt::skip] +pub struct Foo { + // /// 位 + //~^ tabs_in_doc_comments + //~| empty_line_after_doc_comments + + + /// ^ Do not remove this tab character. + /// It was required to trigger the ICE. + pub bar: u8, +} + +fn main() {} diff --git a/tests/ui/crashes/ice-5835.fixed b/tests/ui/crashes/ice-5835.fixed index c0532d685786..e9c24b8e9f09 100644 --- a/tests/ui/crashes/ice-5835.fixed +++ b/tests/ui/crashes/ice-5835.fixed @@ -1,8 +1,7 @@ #[rustfmt::skip] pub struct Foo { + //~v tabs_in_doc_comments /// 位 - //~^ ERROR: using tabs in doc comments is not recommended - //~| NOTE: `-D clippy::tabs-in-doc-comments` implied by `-D warnings` /// ^ Do not remove this tab character. /// It was required to trigger the ICE. pub bar: u8, diff --git a/tests/ui/crashes/ice-5835.rs b/tests/ui/crashes/ice-5835.rs index 122bddd6ae67..99858f45933e 100644 --- a/tests/ui/crashes/ice-5835.rs +++ b/tests/ui/crashes/ice-5835.rs @@ -1,8 +1,7 @@ #[rustfmt::skip] pub struct Foo { + //~v tabs_in_doc_comments /// 位 - //~^ ERROR: using tabs in doc comments is not recommended - //~| NOTE: `-D clippy::tabs-in-doc-comments` implied by `-D warnings` /// ^ Do not remove this tab character. /// It was required to trigger the ICE. pub bar: u8, diff --git a/tests/ui/crashes/ice-5835.stderr b/tests/ui/crashes/ice-5835.stderr index 45e5e9a4b83d..4ef91e4116b2 100644 --- a/tests/ui/crashes/ice-5835.stderr +++ b/tests/ui/crashes/ice-5835.stderr @@ -1,5 +1,5 @@ error: using tabs in doc comments is not recommended - --> tests/ui/crashes/ice-5835.rs:3:10 + --> tests/ui/crashes/ice-5835.rs:4:10 | LL | /// 位 | ^^^^ help: consider using four spaces per tab diff --git a/tests/ui/crashes/ice-5872.fixed b/tests/ui/crashes/ice-5872.fixed index c8e870c62fbf..521fa15e1846 100644 --- a/tests/ui/crashes/ice-5872.fixed +++ b/tests/ui/crashes/ice-5872.fixed @@ -2,6 +2,5 @@ fn main() { let _ = vec![1, 2, 3].into_iter().next().is_none(); - //~^ ERROR: avoid using `collect()` when not needed - //~| NOTE: `-D clippy::needless-collect` implied by `-D warnings` + //~^ needless_collect } diff --git a/tests/ui/crashes/ice-5872.rs b/tests/ui/crashes/ice-5872.rs index c6ed31365892..10235ea8ab7f 100644 --- a/tests/ui/crashes/ice-5872.rs +++ b/tests/ui/crashes/ice-5872.rs @@ -2,6 +2,5 @@ fn main() { let _ = vec![1, 2, 3].into_iter().collect::>().is_empty(); - //~^ ERROR: avoid using `collect()` when not needed - //~| NOTE: `-D clippy::needless-collect` implied by `-D warnings` + //~^ needless_collect } diff --git a/tests/ui/crashes/ice-5944.rs b/tests/ui/crashes/ice-5944.rs index ce46bc1acc1b..2a93c5436511 100644 --- a/tests/ui/crashes/ice-5944.rs +++ b/tests/ui/crashes/ice-5944.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::repeat_once)] #![allow(clippy::let_unit_value)] diff --git a/tests/ui/crashes/ice-6139.rs b/tests/ui/crashes/ice-6139.rs index f3966e47f5e8..866e13a86592 100644 --- a/tests/ui/crashes/ice-6139.rs +++ b/tests/ui/crashes/ice-6139.rs @@ -1,3 +1,5 @@ +//@ check-pass + trait T<'a> {} fn foo(_: Vec>>) {} diff --git a/tests/ui/crashes/ice-6153.rs b/tests/ui/crashes/ice-6153.rs index 9f73f39f10d7..84873c2ecf4c 100644 --- a/tests/ui/crashes/ice-6153.rs +++ b/tests/ui/crashes/ice-6153.rs @@ -1,3 +1,5 @@ +//@ check-pass + pub struct S<'a, 'e>(&'a str, &'e str); pub type T<'a, 'e> = std::collections::HashMap, ()>; diff --git a/tests/ui/crashes/ice-6179.rs b/tests/ui/crashes/ice-6179.rs index 91160eef03df..640b51517f74 100644 --- a/tests/ui/crashes/ice-6179.rs +++ b/tests/ui/crashes/ice-6179.rs @@ -1,3 +1,4 @@ +//@ check-pass //! This is a minimal reproducer for the ICE in https://github.com/rust-lang/rust-clippy/pull/6179. //! The ICE is mainly caused by using `lower_ty`. See the discussion in the PR for details. diff --git a/tests/ui/crashes/ice-6250.rs b/tests/ui/crashes/ice-6250.rs index 32849f2ca6f0..65cdce793142 100644 --- a/tests/ui/crashes/ice-6250.rs +++ b/tests/ui/crashes/ice-6250.rs @@ -10,6 +10,8 @@ pub fn list_data(cache: &Cache, key: usize) { if /* let */ Some(reference) = cache.data.get(key) { + //~^ ERROR: mismatched types + //~| ERROR: mismatched types unimplemented!() } } diff --git a/tests/ui/crashes/ice-6251.rs b/tests/ui/crashes/ice-6251.rs index 73e919b6dd2e..a58265752ec3 100644 --- a/tests/ui/crashes/ice-6251.rs +++ b/tests/ui/crashes/ice-6251.rs @@ -2,5 +2,8 @@ // assertion failed: `(left == right)` ; different DefIds //@no-rustfix fn bug() -> impl Iterator { + //~^ ERROR: the size for values + //~| ERROR: the size for values + //~| ERROR: mismatched types std::iter::empty() } diff --git a/tests/ui/crashes/ice-6252.rs b/tests/ui/crashes/ice-6252.rs index 67fbb0ff699c..829cb447211c 100644 --- a/tests/ui/crashes/ice-6252.rs +++ b/tests/ui/crashes/ice-6252.rs @@ -7,8 +7,11 @@ trait TypeVal { struct Five; struct Multiply { _n: PhantomData, + //~^ ERROR: cannot find type } impl TypeVal for Multiply where N: TypeVal {} +//~^ ERROR: cannot find type +//~| ERROR: not all trait items fn main() { [1; >::VAL]; diff --git a/tests/ui/crashes/ice-6252.stderr b/tests/ui/crashes/ice-6252.stderr index cd2031af1c6d..201a897b2319 100644 --- a/tests/ui/crashes/ice-6252.stderr +++ b/tests/ui/crashes/ice-6252.stderr @@ -10,7 +10,7 @@ LL + use std::marker::PhantomData; | error[E0412]: cannot find type `VAL` in this scope - --> tests/ui/crashes/ice-6252.rs:11:63 + --> tests/ui/crashes/ice-6252.rs:12:63 | LL | impl TypeVal for Multiply where N: TypeVal {} | ^^^ not found in this scope @@ -21,7 +21,7 @@ LL | impl TypeVal for Multiply where N: TypeVal {} | +++++ error[E0046]: not all trait items implemented, missing: `VAL` - --> tests/ui/crashes/ice-6252.rs:11:1 + --> tests/ui/crashes/ice-6252.rs:12:1 | LL | const VAL: T; | ------------ `VAL` from trait diff --git a/tests/ui/crashes/ice-6254.rs b/tests/ui/crashes/ice-6254.rs index aaca32ab2d93..45144fd9e5ec 100644 --- a/tests/ui/crashes/ice-6254.rs +++ b/tests/ui/crashes/ice-6254.rs @@ -1,3 +1,4 @@ +//@ check-pass // originally from ./tests/ui/pattern/usefulness/consts-opaque.rs // panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', // compiler/rustc_mir_build/src/thir/pattern/_match.rs:2030:5 diff --git a/tests/ui/crashes/ice-6332.rs b/tests/ui/crashes/ice-6332.rs index 9dc92aa500b2..25660a3ce853 100644 --- a/tests/ui/crashes/ice-6332.rs +++ b/tests/ui/crashes/ice-6332.rs @@ -1,3 +1,5 @@ +//@ check-pass + fn cmark_check() { let mut link_err = false; macro_rules! cmark_error { diff --git a/tests/ui/crashes/ice-6539.rs b/tests/ui/crashes/ice-6539.rs index ac6c3e4aba04..cff0882cbee3 100644 --- a/tests/ui/crashes/ice-6539.rs +++ b/tests/ui/crashes/ice-6539.rs @@ -1,3 +1,4 @@ +//@ check-pass // The test for the ICE 6539: https://github.com/rust-lang/rust-clippy/issues/6539. // The cause is that `zero_sized_map_values` used `layout_of` with types from type aliases, // which is essentially the same as the ICE 4968. diff --git a/tests/ui/crashes/ice-6792.rs b/tests/ui/crashes/ice-6792.rs index 9cbafc716b50..372ce5ac06f3 100644 --- a/tests/ui/crashes/ice-6792.rs +++ b/tests/ui/crashes/ice-6792.rs @@ -1,3 +1,4 @@ +//@ check-pass //! This is a reproducer for the ICE 6792: https://github.com/rust-lang/rust-clippy/issues/6792. //! The ICE is caused by using `TyCtxt::type_of(assoc_type_id)`. diff --git a/tests/ui/crashes/ice-6793.rs b/tests/ui/crashes/ice-6793.rs index 12a4a0d25ef5..d83a2ee251db 100644 --- a/tests/ui/crashes/ice-6793.rs +++ b/tests/ui/crashes/ice-6793.rs @@ -1,3 +1,4 @@ +//@ check-pass //! This is a reproducer for the ICE 6793: https://github.com/rust-lang/rust-clippy/issues/6793. //! The ICE is caused by using `TyCtxt::type_of(assoc_type_id)`, which is the same as the ICE 6792. diff --git a/tests/ui/crashes/ice-6840.rs b/tests/ui/crashes/ice-6840.rs index d789f60c5d5a..94481f248998 100644 --- a/tests/ui/crashes/ice-6840.rs +++ b/tests/ui/crashes/ice-6840.rs @@ -1,3 +1,4 @@ +//@ check-pass //! This is a reproducer for the ICE 6840: https://github.com/rust-lang/rust-clippy/issues/6840. //! The ICE is caused by `TyCtxt::layout_of` and `is_normalizable` not being strict enough #![allow(dead_code)] diff --git a/tests/ui/crashes/ice-700.rs b/tests/ui/crashes/ice-700.rs index 5e004b94330e..aa3bf493c201 100644 --- a/tests/ui/crashes/ice-700.rs +++ b/tests/ui/crashes/ice-700.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![deny(clippy::all)] // Test for https://github.com/rust-lang/rust-clippy/issues/700 diff --git a/tests/ui/crashes/ice-7012.rs b/tests/ui/crashes/ice-7012.rs index 60bdbc4f124e..d76995adadf1 100644 --- a/tests/ui/crashes/ice-7012.rs +++ b/tests/ui/crashes/ice-7012.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(clippy::all)] enum _MyOption { diff --git a/tests/ui/crashes/ice-7126.rs b/tests/ui/crashes/ice-7126.rs index b2dc2248b556..f0c23c7e852d 100644 --- a/tests/ui/crashes/ice-7126.rs +++ b/tests/ui/crashes/ice-7126.rs @@ -1,3 +1,4 @@ +//@ check-pass // This test requires a feature gated const fn and will stop working in the future. #![feature(const_btree_len)] diff --git a/tests/ui/crashes/ice-7169.fixed b/tests/ui/crashes/ice-7169.fixed index cf4077e4d898..71a40ad7de71 100644 --- a/tests/ui/crashes/ice-7169.fixed +++ b/tests/ui/crashes/ice-7169.fixed @@ -8,6 +8,5 @@ struct A { fn main() { if Ok::<_, ()>(A::::default()).is_ok() {} - //~^ ERROR: redundant pattern matching, consider using `is_ok()` - //~| NOTE: `-D clippy::redundant-pattern-matching` implied by `-D warnings` + //~^ redundant_pattern_matching } diff --git a/tests/ui/crashes/ice-7169.rs b/tests/ui/crashes/ice-7169.rs index b09e6f384632..d43e2cc164d7 100644 --- a/tests/ui/crashes/ice-7169.rs +++ b/tests/ui/crashes/ice-7169.rs @@ -8,6 +8,5 @@ struct A { fn main() { if let Ok(_) = Ok::<_, ()>(A::::default()) {} - //~^ ERROR: redundant pattern matching, consider using `is_ok()` - //~| NOTE: `-D clippy::redundant-pattern-matching` implied by `-D warnings` + //~^ redundant_pattern_matching } diff --git a/tests/ui/crashes/ice-7231.rs b/tests/ui/crashes/ice-7231.rs index 4ad0d351372f..873cdbb0516c 100644 --- a/tests/ui/crashes/ice-7231.rs +++ b/tests/ui/crashes/ice-7231.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(clippy::never_loop)] async fn f() { diff --git a/tests/ui/crashes/ice-7272.rs b/tests/ui/crashes/ice-7272.rs index e949038c8d0b..e1910096418b 100644 --- a/tests/ui/crashes/ice-7272.rs +++ b/tests/ui/crashes/ice-7272.rs @@ -1,3 +1,4 @@ +//@ check-pass //@aux-build:ice-7272-aux.rs #![allow(clippy::no_effect)] diff --git a/tests/ui/crashes/ice-7340.rs b/tests/ui/crashes/ice-7340.rs index 7d2351d606f1..6c71c232fddb 100644 --- a/tests/ui/crashes/ice-7340.rs +++ b/tests/ui/crashes/ice-7340.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(clippy::no_effect)] fn main() { diff --git a/tests/ui/crashes/ice-7410.rs b/tests/ui/crashes/ice-7410.rs index addbca54e80a..71f00fb9aede 100644 --- a/tests/ui/crashes/ice-7410.rs +++ b/tests/ui/crashes/ice-7410.rs @@ -1,3 +1,4 @@ +//@ check-pass //@compile-flags: -Clink-arg=-nostartfiles //@ignore-target: apple windows diff --git a/tests/ui/crashes/ice-7423.rs b/tests/ui/crashes/ice-7423.rs index 31340b012dd0..a03981842fcc 100644 --- a/tests/ui/crashes/ice-7423.rs +++ b/tests/ui/crashes/ice-7423.rs @@ -1,3 +1,5 @@ +//@ check-pass + pub trait Trait { fn f(); } diff --git a/tests/ui/crashes/ice-7868.rs b/tests/ui/crashes/ice-7868.rs index c6932164e3bf..727dd41aa322 100644 --- a/tests/ui/crashes/ice-7868.rs +++ b/tests/ui/crashes/ice-7868.rs @@ -1,3 +1,4 @@ +//@error-in-other-file: #![warn(clippy::undocumented_unsafe_blocks)] #![allow(clippy::no_effect)] diff --git a/tests/ui/crashes/ice-7869.rs b/tests/ui/crashes/ice-7869.rs index 774e22f6b4c5..a5b557849aba 100644 --- a/tests/ui/crashes/ice-7869.rs +++ b/tests/ui/crashes/ice-7869.rs @@ -1,5 +1,5 @@ enum Tila { - //~^ ERROR: all variants have the same prefix: `Työ` + //~^ enum_variant_names TyöAlkoi, TyöKeskeytyi, TyöValmis, diff --git a/tests/ui/crashes/ice-7934.rs b/tests/ui/crashes/ice-7934.rs index a4691c4131b3..c7a8d68d63b6 100644 --- a/tests/ui/crashes/ice-7934.rs +++ b/tests/ui/crashes/ice-7934.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::undocumented_unsafe_blocks)] #![allow(clippy::no_effect)] diff --git a/tests/ui/crashes/ice-8250.fixed b/tests/ui/crashes/ice-8250.fixed index 984b61258c78..b0c2ddb2450d 100644 --- a/tests/ui/crashes/ice-8250.fixed +++ b/tests/ui/crashes/ice-8250.fixed @@ -1,7 +1,7 @@ fn _f(s: &str) -> Option<()> { let _ = s[1..].split('.').next()?; - //~^ ERROR: unnecessary use of `splitn` - //~| NOTE: `-D clippy::needless-splitn` implied by `-D warnings` + //~^ needless_splitn + Some(()) } diff --git a/tests/ui/crashes/ice-8250.rs b/tests/ui/crashes/ice-8250.rs index c1b2e48ba3c0..ee0eb8e1eb1a 100644 --- a/tests/ui/crashes/ice-8250.rs +++ b/tests/ui/crashes/ice-8250.rs @@ -1,7 +1,7 @@ fn _f(s: &str) -> Option<()> { let _ = s[1..].splitn(2, '.').next()?; - //~^ ERROR: unnecessary use of `splitn` - //~| NOTE: `-D clippy::needless-splitn` implied by `-D warnings` + //~^ needless_splitn + Some(()) } diff --git a/tests/ui/crashes/ice-8386.rs b/tests/ui/crashes/ice-8386.rs index 3e38b1408d8c..1c7a809174b6 100644 --- a/tests/ui/crashes/ice-8386.rs +++ b/tests/ui/crashes/ice-8386.rs @@ -1,3 +1,5 @@ +//@ check-pass + fn f(x: u32, mut arg: &String) {} fn main() {} diff --git a/tests/ui/crashes/ice-8681.rs b/tests/ui/crashes/ice-8681.rs index 607b9caa3249..b7d6c4556bbd 100644 --- a/tests/ui/crashes/ice-8681.rs +++ b/tests/ui/crashes/ice-8681.rs @@ -1,3 +1,4 @@ +//@ check-pass //@aux-build: ice-8681-aux.rs #![warn(clippy::undocumented_unsafe_blocks)] diff --git a/tests/ui/crashes/ice-8821.rs b/tests/ui/crashes/ice-8821.rs index fb87b79aeed8..c9fea3d1ccb8 100644 --- a/tests/ui/crashes/ice-8821.rs +++ b/tests/ui/crashes/ice-8821.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::let_unit_value)] fn f() {} diff --git a/tests/ui/crashes/ice-8850.fixed b/tests/ui/crashes/ice-8850.fixed index 4569b9e8793e..0e1d8d5a2aae 100644 --- a/tests/ui/crashes/ice-8850.fixed +++ b/tests/ui/crashes/ice-8850.fixed @@ -2,15 +2,14 @@ fn fn_pointer_static() -> usize { static FN: fn() -> usize = || 1; FN() + 1 - //~^ ERROR: returning the result of a `let` binding from a block - //~| NOTE: `-D clippy::let-and-return` implied by `-D warnings` + //~^ let_and_return } fn fn_pointer_const() -> usize { const FN: fn() -> usize = || 1; FN() + 1 - //~^ ERROR: returning the result of a `let` binding from a block + //~^ let_and_return } fn deref_to_dyn_fn() -> usize { @@ -25,7 +24,7 @@ fn deref_to_dyn_fn() -> usize { static FN: Derefs = Derefs; FN() + 1 - //~^ ERROR: returning the result of a `let` binding from a block + //~^ let_and_return } fn main() {} diff --git a/tests/ui/crashes/ice-8850.rs b/tests/ui/crashes/ice-8850.rs index 499756ecefe9..0109911bca68 100644 --- a/tests/ui/crashes/ice-8850.rs +++ b/tests/ui/crashes/ice-8850.rs @@ -2,15 +2,14 @@ fn fn_pointer_static() -> usize { static FN: fn() -> usize = || 1; let res = FN() + 1; res - //~^ ERROR: returning the result of a `let` binding from a block - //~| NOTE: `-D clippy::let-and-return` implied by `-D warnings` + //~^ let_and_return } fn fn_pointer_const() -> usize { const FN: fn() -> usize = || 1; let res = FN() + 1; res - //~^ ERROR: returning the result of a `let` binding from a block + //~^ let_and_return } fn deref_to_dyn_fn() -> usize { @@ -25,7 +24,7 @@ fn deref_to_dyn_fn() -> usize { static FN: Derefs = Derefs; let res = FN() + 1; res - //~^ ERROR: returning the result of a `let` binding from a block + //~^ let_and_return } fn main() {} diff --git a/tests/ui/crashes/ice-8850.stderr b/tests/ui/crashes/ice-8850.stderr index 5a8f24ee8c0b..1a44f103beb3 100644 --- a/tests/ui/crashes/ice-8850.stderr +++ b/tests/ui/crashes/ice-8850.stderr @@ -15,7 +15,7 @@ LL ~ FN() + 1 | error: returning the result of a `let` binding from a block - --> tests/ui/crashes/ice-8850.rs:12:5 + --> tests/ui/crashes/ice-8850.rs:11:5 | LL | let res = FN() + 1; | ------------------- unnecessary `let` binding @@ -29,7 +29,7 @@ LL ~ FN() + 1 | error: returning the result of a `let` binding from a block - --> tests/ui/crashes/ice-8850.rs:27:5 + --> tests/ui/crashes/ice-8850.rs:26:5 | LL | let res = FN() + 1; | ------------------- unnecessary `let` binding diff --git a/tests/ui/crashes/ice-9041.rs b/tests/ui/crashes/ice-9041.rs index 727d88f7fbd2..4b2a0f953114 100644 --- a/tests/ui/crashes/ice-9041.rs +++ b/tests/ui/crashes/ice-9041.rs @@ -3,8 +3,7 @@ pub struct Thing; pub fn has_thing(things: &[Thing]) -> bool { let is_thing_ready = |_peer: &Thing| -> bool { todo!() }; things.iter().find(|p| is_thing_ready(p)).is_some() - //~^ ERROR: called `is_some()` after searching an `Iterator` with `find` - //~| NOTE: `-D clippy::search-is-some` implied by `-D warnings` + //~^ search_is_some } fn main() {} diff --git a/tests/ui/crashes/ice-9238.rs b/tests/ui/crashes/ice-9238.rs index ee6abd519f16..cbce84305ba8 100644 --- a/tests/ui/crashes/ice-9238.rs +++ b/tests/ui/crashes/ice-9238.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(incomplete_features)] #![feature(generic_const_exprs)] #![warn(clippy::branches_sharing_code)] diff --git a/tests/ui/crashes/ice-9242.rs b/tests/ui/crashes/ice-9242.rs index 0099e6e2f34b..ac5bbad98c14 100644 --- a/tests/ui/crashes/ice-9242.rs +++ b/tests/ui/crashes/ice-9242.rs @@ -1,3 +1,5 @@ +//@ check-pass + enum E { X(), Y, diff --git a/tests/ui/crashes/ice-9405.rs b/tests/ui/crashes/ice-9405.rs index e2d274aeb044..74a56f4d2ef8 100644 --- a/tests/ui/crashes/ice-9405.rs +++ b/tests/ui/crashes/ice-9405.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::useless_format)] #![allow(clippy::print_literal)] diff --git a/tests/ui/crashes/ice-9405.stderr b/tests/ui/crashes/ice-9405.stderr index e8a73b9e782e..96e0f2ea736a 100644 --- a/tests/ui/crashes/ice-9405.stderr +++ b/tests/ui/crashes/ice-9405.stderr @@ -1,5 +1,5 @@ warning: multiple lines skipped by escaped newline - --> tests/ui/crashes/ice-9405.rs:6:10 + --> tests/ui/crashes/ice-9405.rs:8:10 | LL | "\ | __________^ diff --git a/tests/ui/crashes/ice-9414.rs b/tests/ui/crashes/ice-9414.rs index 02cf5d5c240f..2341c99b2390 100644 --- a/tests/ui/crashes/ice-9414.rs +++ b/tests/ui/crashes/ice-9414.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::result_large_err)] trait T {} diff --git a/tests/ui/crashes/ice-9445.rs b/tests/ui/crashes/ice-9445.rs index c67b22f6f8c4..232b8e4a7959 100644 --- a/tests/ui/crashes/ice-9445.rs +++ b/tests/ui/crashes/ice-9445.rs @@ -1,3 +1,4 @@ const UNINIT: core::mem::MaybeUninit> = core::mem::MaybeUninit::uninit(); +//~^ declare_interior_mutable_const fn main() {} diff --git a/tests/ui/crashes/ice-9459.rs b/tests/ui/crashes/ice-9459.rs index 55615124fcf0..43d3264b264d 100644 --- a/tests/ui/crashes/ice-9459.rs +++ b/tests/ui/crashes/ice-9459.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![feature(unsized_fn_params)] pub fn f0(_f: dyn FnOnce()) {} diff --git a/tests/ui/crashes/ice-9463.rs b/tests/ui/crashes/ice-9463.rs index fa83d25b3942..93808e0f8923 100644 --- a/tests/ui/crashes/ice-9463.rs +++ b/tests/ui/crashes/ice-9463.rs @@ -4,6 +4,5 @@ fn main() { //~^ ERROR: this arithmetic operation will overflow let _y = 1u32 >> 10000000000000u32; //~^ ERROR: this arithmetic operation will overflow - //~| ERROR: literal out of range for `u32` - //~| NOTE: the literal `10000000000000u32` does not fit into the type `u32` whose rang + //~| ERROR: literal out of range } diff --git a/tests/ui/crashes/ice-9625.rs b/tests/ui/crashes/ice-9625.rs index a765882b5d81..52117883aa7d 100644 --- a/tests/ui/crashes/ice-9625.rs +++ b/tests/ui/crashes/ice-9625.rs @@ -1,3 +1,5 @@ +//@ check-pass + fn main() { let x = &1; let _ = &1 < x && x < &10; diff --git a/tests/ui/crashes/ice-9746.rs b/tests/ui/crashes/ice-9746.rs index fbd373c70bf2..39fa8ff7a915 100644 --- a/tests/ui/crashes/ice-9746.rs +++ b/tests/ui/crashes/ice-9746.rs @@ -1,3 +1,4 @@ +//@ check-pass //! trait Trait {} diff --git a/tests/ui/crashes/ice-rust-107877.rs b/tests/ui/crashes/ice-rust-107877.rs index 7f5bae60d55d..55fe418bed12 100644 --- a/tests/ui/crashes/ice-rust-107877.rs +++ b/tests/ui/crashes/ice-rust-107877.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(dead_code)] struct Foo; diff --git a/tests/ui/crashes/ice_exact_size.rs b/tests/ui/crashes/ice_exact_size.rs index c0671eaff145..cb4685e78e22 100644 --- a/tests/ui/crashes/ice_exact_size.rs +++ b/tests/ui/crashes/ice_exact_size.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![deny(clippy::all)] // Test for https://github.com/rust-lang/rust-clippy/issues/1336 diff --git a/tests/ui/crashes/if_same_then_else.rs b/tests/ui/crashes/if_same_then_else.rs index a900fe5e6bc6..58ee751948b5 100644 --- a/tests/ui/crashes/if_same_then_else.rs +++ b/tests/ui/crashes/if_same_then_else.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(clippy::comparison_chain)] #![deny(clippy::if_same_then_else)] diff --git a/tests/ui/crashes/implements-trait.rs b/tests/ui/crashes/implements-trait.rs index 4502b0147a83..0e68c40be999 100644 --- a/tests/ui/crashes/implements-trait.rs +++ b/tests/ui/crashes/implements-trait.rs @@ -1,3 +1,5 @@ +//@ check-pass + #[allow(clippy::needless_borrowed_reference)] fn main() { let mut v = Vec::::new(); diff --git a/tests/ui/crashes/inherent_impl.rs b/tests/ui/crashes/inherent_impl.rs index 800a5a383f62..87f1347ecfca 100644 --- a/tests/ui/crashes/inherent_impl.rs +++ b/tests/ui/crashes/inherent_impl.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![deny(clippy::multiple_inherent_impl)] // Test for https://github.com/rust-lang/rust-clippy/issues/4578 diff --git a/tests/ui/crashes/issue-825.rs b/tests/ui/crashes/issue-825.rs index e8b455a0ec67..9bbb86e4c65a 100644 --- a/tests/ui/crashes/issue-825.rs +++ b/tests/ui/crashes/issue-825.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(warnings)] // Test for https://github.com/rust-lang/rust-clippy/issues/825 diff --git a/tests/ui/crashes/issues_loop_mut_cond.rs b/tests/ui/crashes/issues_loop_mut_cond.rs index bb238c81ebc0..635580c6a6e7 100644 --- a/tests/ui/crashes/issues_loop_mut_cond.rs +++ b/tests/ui/crashes/issues_loop_mut_cond.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(dead_code)] /// Issue: https://github.com/rust-lang/rust-clippy/issues/2596 diff --git a/tests/ui/crashes/match_same_arms_const.rs b/tests/ui/crashes/match_same_arms_const.rs index 626179c00155..a70623f0c51f 100644 --- a/tests/ui/crashes/match_same_arms_const.rs +++ b/tests/ui/crashes/match_same_arms_const.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![deny(clippy::match_same_arms)] // Test for https://github.com/rust-lang/rust-clippy/issues/2427 diff --git a/tests/ui/crashes/needless_borrow_fp.rs b/tests/ui/crashes/needless_borrow_fp.rs index 4f61c76828db..68e39531682a 100644 --- a/tests/ui/crashes/needless_borrow_fp.rs +++ b/tests/ui/crashes/needless_borrow_fp.rs @@ -1,3 +1,5 @@ +//@ check-pass + #[deny(clippy::all)] #[derive(Debug)] pub enum Error { diff --git a/tests/ui/crashes/needless_pass_by_value-w-late-bound.fixed b/tests/ui/crashes/needless_pass_by_value-w-late-bound.fixed index 774dea391939..7d7286ceb99a 100644 --- a/tests/ui/crashes/needless_pass_by_value-w-late-bound.fixed +++ b/tests/ui/crashes/needless_pass_by_value-w-late-bound.fixed @@ -5,6 +5,6 @@ struct Foo<'a>(&'a [(); 100]); fn test(x: &Foo<'_>) {} -//~^ ERROR: this argument is passed by value, but not consumed in the function body +//~^ needless_pass_by_value fn main() {} diff --git a/tests/ui/crashes/needless_pass_by_value-w-late-bound.rs b/tests/ui/crashes/needless_pass_by_value-w-late-bound.rs index f3d8871929a2..949cd5de7fb8 100644 --- a/tests/ui/crashes/needless_pass_by_value-w-late-bound.rs +++ b/tests/ui/crashes/needless_pass_by_value-w-late-bound.rs @@ -5,6 +5,6 @@ struct Foo<'a>(&'a [(); 100]); fn test(x: Foo<'_>) {} -//~^ ERROR: this argument is passed by value, but not consumed in the function body +//~^ needless_pass_by_value fn main() {} diff --git a/tests/ui/crashes/regressions.rs b/tests/ui/crashes/regressions.rs index b34997d4ee0b..8fda12fab06a 100644 --- a/tests/ui/crashes/regressions.rs +++ b/tests/ui/crashes/regressions.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(clippy::disallowed_names, clippy::uninlined_format_args)] pub fn foo(bar: *const u8) { diff --git a/tests/ui/crashes/returns.rs b/tests/ui/crashes/returns.rs index 91cdb5306c89..ccab9522753e 100644 --- a/tests/ui/crashes/returns.rs +++ b/tests/ui/crashes/returns.rs @@ -1,3 +1,4 @@ +//@ check-pass // Test for https://github.com/rust-lang/rust-clippy/issues/1346 #[deny(warnings)] diff --git a/tests/ui/crashes/shadow.rs b/tests/ui/crashes/shadow.rs index 843e8ef64dcd..237988a01681 100644 --- a/tests/ui/crashes/shadow.rs +++ b/tests/ui/crashes/shadow.rs @@ -1,3 +1,5 @@ +//@ check-pass + fn main() { let x: [i32; { let u = 2; diff --git a/tests/ui/crashes/single-match-else.rs b/tests/ui/crashes/single-match-else.rs index 1ba7ac082132..2ef5dd891c56 100644 --- a/tests/ui/crashes/single-match-else.rs +++ b/tests/ui/crashes/single-match-else.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::single_match_else)] //! Test for https://github.com/rust-lang/rust-clippy/issues/1588 diff --git a/tests/ui/crashes/third-party/conf_allowlisted.rs b/tests/ui/crashes/third-party/conf_allowlisted.rs index f328e4d9d04c..20c76a4d46d9 100644 --- a/tests/ui/crashes/third-party/conf_allowlisted.rs +++ b/tests/ui/crashes/third-party/conf_allowlisted.rs @@ -1 +1,3 @@ +//@ check-pass + fn main() {} diff --git a/tests/ui/crashes/trivial_bounds.rs b/tests/ui/crashes/trivial_bounds.rs index 60105a8213fe..23982fca7e7c 100644 --- a/tests/ui/crashes/trivial_bounds.rs +++ b/tests/ui/crashes/trivial_bounds.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![feature(trivial_bounds)] #![allow(unused, trivial_bounds)] diff --git a/tests/ui/crashes/unreachable-array-or-slice.rs b/tests/ui/crashes/unreachable-array-or-slice.rs index e920e58d6ec6..bc2e9aa92ce1 100644 --- a/tests/ui/crashes/unreachable-array-or-slice.rs +++ b/tests/ui/crashes/unreachable-array-or-slice.rs @@ -2,6 +2,7 @@ struct Foo(isize, isize, isize, isize); pub fn main() { let Self::anything_here_kills_it(a, b, ..) = Foo(5, 5, 5, 5); + //~^ ERROR: failed to resolve match [5, 5, 5, 5] { [..] => {}, } diff --git a/tests/ui/crashes/used_underscore_binding_macro.rs b/tests/ui/crashes/used_underscore_binding_macro.rs index 901eb4e50398..0fff0afdf1fe 100644 --- a/tests/ui/crashes/used_underscore_binding_macro.rs +++ b/tests/ui/crashes/used_underscore_binding_macro.rs @@ -1,3 +1,5 @@ +//@ check-pass + use serde::Deserialize; /// Tests that we do not lint for unused underscores in a `MacroAttribute` diff --git a/tests/ui/crate_in_macro_def.fixed b/tests/ui/crate_in_macro_def.fixed index bd91389c8219..d7d8e2a64419 100644 --- a/tests/ui/crate_in_macro_def.fixed +++ b/tests/ui/crate_in_macro_def.fixed @@ -16,6 +16,7 @@ mod unhygienic { macro_rules! print_message_unhygienic { () => { println!("{}", $crate::unhygienic::MESSAGE); + //~^ crate_in_macro_def }; } diff --git a/tests/ui/crate_in_macro_def.rs b/tests/ui/crate_in_macro_def.rs index f6fa338eedbf..9ed9dacee48b 100644 --- a/tests/ui/crate_in_macro_def.rs +++ b/tests/ui/crate_in_macro_def.rs @@ -16,6 +16,7 @@ mod unhygienic { macro_rules! print_message_unhygienic { () => { println!("{}", crate::unhygienic::MESSAGE); + //~^ crate_in_macro_def }; } diff --git a/tests/ui/crate_level_checks/entrypoint_recursion.rs b/tests/ui/crate_level_checks/entrypoint_recursion.rs index 5d853d97bc35..3ded902e36b1 100644 --- a/tests/ui/crate_level_checks/entrypoint_recursion.rs +++ b/tests/ui/crate_level_checks/entrypoint_recursion.rs @@ -1,3 +1,4 @@ +//@check-pass //@ignore-target: apple #![feature(rustc_attrs)] diff --git a/tests/ui/crate_level_checks/no_std_swap.rs b/tests/ui/crate_level_checks/no_std_swap.rs index 536e71b4a25a..66ca97690c17 100644 --- a/tests/ui/crate_level_checks/no_std_swap.rs +++ b/tests/ui/crate_level_checks/no_std_swap.rs @@ -9,7 +9,7 @@ pub fn main() { let mut b = 1337; a = b; - //~^ ERROR: this looks like you are trying to swap `a` and `b` - //~| NOTE: or maybe you should use `core::mem::replace`? + //~^ almost_swapped + b = a; } diff --git a/tests/ui/crate_level_checks/std_main_recursion.rs b/tests/ui/crate_level_checks/std_main_recursion.rs index c2c3e0958ec7..50f82b59a96e 100644 --- a/tests/ui/crate_level_checks/std_main_recursion.rs +++ b/tests/ui/crate_level_checks/std_main_recursion.rs @@ -3,5 +3,5 @@ fn main() { println!("Hello, World!"); main(); - //~^ ERROR: recursing into entrypoint `main` + //~^ main_recursion } diff --git a/tests/ui/create_dir.fixed b/tests/ui/create_dir.fixed index 8fbf7dd19b83..4a5b1b77be6b 100644 --- a/tests/ui/create_dir.fixed +++ b/tests/ui/create_dir.fixed @@ -8,7 +8,9 @@ fn create_dir() {} fn main() { // Should be warned create_dir_all("foo"); + //~^ create_dir create_dir_all("bar").unwrap(); + //~^ create_dir // Shouldn't be warned create_dir(); diff --git a/tests/ui/create_dir.rs b/tests/ui/create_dir.rs index af2c326ec436..bf185ba3a7c3 100644 --- a/tests/ui/create_dir.rs +++ b/tests/ui/create_dir.rs @@ -8,7 +8,9 @@ fn create_dir() {} fn main() { // Should be warned std::fs::create_dir("foo"); + //~^ create_dir std::fs::create_dir("bar").unwrap(); + //~^ create_dir // Shouldn't be warned create_dir(); diff --git a/tests/ui/create_dir.stderr b/tests/ui/create_dir.stderr index 9bb98a2606dd..51d6ac686e02 100644 --- a/tests/ui/create_dir.stderr +++ b/tests/ui/create_dir.stderr @@ -13,7 +13,7 @@ LL + create_dir_all("foo"); | error: calling `std::fs::create_dir` where there may be a better way - --> tests/ui/create_dir.rs:11:5 + --> tests/ui/create_dir.rs:12:5 | LL | std::fs::create_dir("bar").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/dbg_macro/dbg_macro.fixed b/tests/ui/dbg_macro/dbg_macro.fixed index bda9221a5e1e..fd1a0d8934b3 100644 --- a/tests/ui/dbg_macro/dbg_macro.fixed +++ b/tests/ui/dbg_macro/dbg_macro.fixed @@ -3,28 +3,31 @@ fn foo(n: u32) -> u32 { if let Some(n) = n.checked_sub(4) { n } else { n } - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro } fn bar(_: ()) {} fn factorial(n: u32) -> u32 { if n <= 1 { - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro + 1 - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro } else { n * factorial(n - 1) - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro } } fn main() { 42; - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro + foo(3) + factorial(4); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro + (1, 2, 3, 4, 5); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro } fn issue9914() { @@ -41,21 +44,26 @@ fn issue9914() { macro_rules! expand_to_dbg { () => { - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro }; } - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro + #[allow(clippy::let_unit_value)] let _ = (); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro + bar(()); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro + foo!(()); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro + foo2!(foo!(())); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro + expand_to_dbg!(); } @@ -77,35 +85,36 @@ mod issue7274 { struct MyThing; define_thing!(MyThing, { 2; - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro }); } #[test] pub fn issue8481() { 1; - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro } #[cfg(test)] fn foo2() { 1; - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro } #[cfg(test)] mod mod1 { fn func() { 1; - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro } } mod issue12131 { fn dbg_in_print(s: &str) { println!("dbg: {:?}", s); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro + print!("{}", s); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro } } diff --git a/tests/ui/dbg_macro/dbg_macro.rs b/tests/ui/dbg_macro/dbg_macro.rs index 8244254026be..c96e2c7251c2 100644 --- a/tests/ui/dbg_macro/dbg_macro.rs +++ b/tests/ui/dbg_macro/dbg_macro.rs @@ -3,28 +3,31 @@ fn foo(n: u32) -> u32 { if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n } - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro } fn bar(_: ()) {} fn factorial(n: u32) -> u32 { if dbg!(n <= 1) { - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro + dbg!(1) - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro } else { dbg!(n * factorial(n - 1)) - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro } } fn main() { dbg!(42); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro + foo(3) + dbg!(factorial(4)); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro + dbg!(1, 2, 3, 4, 5); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro } fn issue9914() { @@ -41,21 +44,26 @@ fn issue9914() { macro_rules! expand_to_dbg { () => { dbg!(); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro }; } dbg!(); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro + #[allow(clippy::let_unit_value)] let _ = dbg!(); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro + bar(dbg!()); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro + foo!(dbg!()); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro + foo2!(foo!(dbg!())); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro + expand_to_dbg!(); } @@ -77,35 +85,36 @@ mod issue7274 { struct MyThing; define_thing!(MyThing, { dbg!(2); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro }); } #[test] pub fn issue8481() { dbg!(1); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro } #[cfg(test)] fn foo2() { dbg!(1); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro } #[cfg(test)] mod mod1 { fn func() { dbg!(1); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro } } mod issue12131 { fn dbg_in_print(s: &str) { println!("dbg: {:?}", dbg!(s)); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro + print!("{}", dbg!(s)); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro } } diff --git a/tests/ui/dbg_macro/dbg_macro.stderr b/tests/ui/dbg_macro/dbg_macro.stderr index f218614fdd62..cd6dce584a2f 100644 --- a/tests/ui/dbg_macro/dbg_macro.stderr +++ b/tests/ui/dbg_macro/dbg_macro.stderr @@ -25,7 +25,7 @@ LL + if n <= 1 { | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:13:9 + --> tests/ui/dbg_macro/dbg_macro.rs:14:9 | LL | dbg!(1) | ^^^^^^^ @@ -37,7 +37,7 @@ LL + 1 | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:16:9 + --> tests/ui/dbg_macro/dbg_macro.rs:17:9 | LL | dbg!(n * factorial(n - 1)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + n * factorial(n - 1) | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:22:5 + --> tests/ui/dbg_macro/dbg_macro.rs:23:5 | LL | dbg!(42); | ^^^^^^^^ @@ -61,7 +61,7 @@ LL + 42; | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:24:14 + --> tests/ui/dbg_macro/dbg_macro.rs:26:14 | LL | foo(3) + dbg!(factorial(4)); | ^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + foo(3) + factorial(4); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:26:5 + --> tests/ui/dbg_macro/dbg_macro.rs:29:5 | LL | dbg!(1, 2, 3, 4, 5); | ^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + (1, 2, 3, 4, 5); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:48:5 + --> tests/ui/dbg_macro/dbg_macro.rs:51:5 | LL | dbg!(); | ^^^^^^ @@ -96,7 +96,7 @@ LL - dbg!(); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:51:13 + --> tests/ui/dbg_macro/dbg_macro.rs:55:13 | LL | let _ = dbg!(); | ^^^^^^ @@ -108,7 +108,7 @@ LL + let _ = (); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:53:9 + --> tests/ui/dbg_macro/dbg_macro.rs:58:9 | LL | bar(dbg!()); | ^^^^^^ @@ -120,7 +120,7 @@ LL + bar(()); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:55:10 + --> tests/ui/dbg_macro/dbg_macro.rs:61:10 | LL | foo!(dbg!()); | ^^^^^^ @@ -132,7 +132,7 @@ LL + foo!(()); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:57:16 + --> tests/ui/dbg_macro/dbg_macro.rs:64:16 | LL | foo2!(foo!(dbg!())); | ^^^^^^ @@ -144,7 +144,7 @@ LL + foo2!(foo!(())); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:43:13 + --> tests/ui/dbg_macro/dbg_macro.rs:46:13 | LL | dbg!(); | ^^^^^^ @@ -159,7 +159,7 @@ LL - dbg!(); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:79:9 + --> tests/ui/dbg_macro/dbg_macro.rs:87:9 | LL | dbg!(2); | ^^^^^^^ @@ -171,7 +171,7 @@ LL + 2; | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:86:5 + --> tests/ui/dbg_macro/dbg_macro.rs:94:5 | LL | dbg!(1); | ^^^^^^^ @@ -183,7 +183,7 @@ LL + 1; | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:92:5 + --> tests/ui/dbg_macro/dbg_macro.rs:100:5 | LL | dbg!(1); | ^^^^^^^ @@ -195,7 +195,7 @@ LL + 1; | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:99:9 + --> tests/ui/dbg_macro/dbg_macro.rs:107:9 | LL | dbg!(1); | ^^^^^^^ @@ -207,7 +207,7 @@ LL + 1; | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:106:31 + --> tests/ui/dbg_macro/dbg_macro.rs:114:31 | LL | println!("dbg: {:?}", dbg!(s)); | ^^^^^^^ @@ -219,7 +219,7 @@ LL + println!("dbg: {:?}", s); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro.rs:108:22 + --> tests/ui/dbg_macro/dbg_macro.rs:117:22 | LL | print!("{}", dbg!(s)); | ^^^^^^^ diff --git a/tests/ui/dbg_macro/dbg_macro_unfixable.rs b/tests/ui/dbg_macro/dbg_macro_unfixable.rs index 0e83766ccaec..1a5119651b53 100644 --- a/tests/ui/dbg_macro/dbg_macro_unfixable.rs +++ b/tests/ui/dbg_macro/dbg_macro_unfixable.rs @@ -1,4 +1,5 @@ //@no-rustfix +//@error-in-other-file: #![warn(clippy::dbg_macro)] #[path = "auxiliary/submodule.rs"] @@ -6,7 +7,11 @@ mod submodule; fn main() { dbg!(dbg!(dbg!(42))); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro + //~| dbg_macro + //~| dbg_macro + dbg!(1, 2, dbg!(3, 4)); - //~^ ERROR: the `dbg!` macro is intended as a debugging tool + //~^ dbg_macro + //~| dbg_macro } diff --git a/tests/ui/dbg_macro/dbg_macro_unfixable.stderr b/tests/ui/dbg_macro/dbg_macro_unfixable.stderr index e8d5f9f2f46f..afade6f08b3c 100644 --- a/tests/ui/dbg_macro/dbg_macro_unfixable.stderr +++ b/tests/ui/dbg_macro/dbg_macro_unfixable.stderr @@ -12,7 +12,7 @@ LL - dbg!(); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro_unfixable.rs:8:5 + --> tests/ui/dbg_macro/dbg_macro_unfixable.rs:9:5 | LL | dbg!(dbg!(dbg!(42))); | ^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL + dbg!(dbg!(42)); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro_unfixable.rs:8:10 + --> tests/ui/dbg_macro/dbg_macro_unfixable.rs:9:10 | LL | dbg!(dbg!(dbg!(42))); | ^^^^^^^^^^^^^^ @@ -36,7 +36,7 @@ LL + dbg!(dbg!(42)); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro_unfixable.rs:8:15 + --> tests/ui/dbg_macro/dbg_macro_unfixable.rs:9:15 | LL | dbg!(dbg!(dbg!(42))); | ^^^^^^^^ @@ -48,7 +48,7 @@ LL + dbg!(dbg!(42)); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro_unfixable.rs:10:5 + --> tests/ui/dbg_macro/dbg_macro_unfixable.rs:14:5 | LL | dbg!(1, 2, dbg!(3, 4)); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL + (1, 2, dbg!(3, 4)); | error: the `dbg!` macro is intended as a debugging tool - --> tests/ui/dbg_macro/dbg_macro_unfixable.rs:10:16 + --> tests/ui/dbg_macro/dbg_macro_unfixable.rs:14:16 | LL | dbg!(1, 2, dbg!(3, 4)); | ^^^^^^^^^^ diff --git a/tests/ui/debug_assert_with_mut_call.rs b/tests/ui/debug_assert_with_mut_call.rs index 8d04be777c7b..74d59b7593fa 100644 --- a/tests/ui/debug_assert_with_mut_call.rs +++ b/tests/ui/debug_assert_with_mut_call.rs @@ -40,20 +40,26 @@ fn func_non_mutable() { fn func_mutable() { debug_assert!(bool_mut(&mut 3)); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert!` - //~| NOTE: `-D clippy::debug-assert-with-mut-call` implied by `-D warnings` + //~^ debug_assert_with_mut_call + + debug_assert!(!bool_mut(&mut 3)); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert!` + //~^ debug_assert_with_mut_call + debug_assert_eq!(0, u32_mut(&mut 3)); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert_eq!` + //~^ debug_assert_with_mut_call + debug_assert_eq!(u32_mut(&mut 3), 0); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert_eq!` + //~^ debug_assert_with_mut_call + debug_assert_ne!(1, u32_mut(&mut 3)); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert_ne!` + //~^ debug_assert_with_mut_call + debug_assert_ne!(u32_mut(&mut 3), 1); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert_ne!` + //~^ debug_assert_with_mut_call + } fn method_non_mutable() { @@ -69,33 +75,46 @@ fn method_non_mutable() { fn method_mutable() { debug_assert!(S.bool_self_mut()); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert!` + //~^ debug_assert_with_mut_call + debug_assert!(!S.bool_self_mut()); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert!` + //~^ debug_assert_with_mut_call + debug_assert!(S.bool_self_ref_arg_mut(&mut 3)); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert!` + //~^ debug_assert_with_mut_call + debug_assert!(S.bool_self_mut_arg_ref(&3)); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert!` + //~^ debug_assert_with_mut_call + debug_assert!(S.bool_self_mut_arg_mut(&mut 3)); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert!` + //~^ debug_assert_with_mut_call + debug_assert_eq!(S.u32_self_mut(), 0); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert_eq!` + //~^ debug_assert_with_mut_call + debug_assert_eq!(S.u32_self_mut_arg_ref(&3), 0); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert_eq!` + //~^ debug_assert_with_mut_call + debug_assert_eq!(S.u32_self_ref_arg_mut(&mut 3), 0); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert_eq!` + //~^ debug_assert_with_mut_call + debug_assert_eq!(S.u32_self_mut_arg_mut(&mut 3), 0); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert_eq!` + //~^ debug_assert_with_mut_call + debug_assert_ne!(S.u32_self_mut(), 1); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert_ne!` + //~^ debug_assert_with_mut_call + debug_assert_ne!(S.u32_self_mut_arg_ref(&3), 1); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert_ne!` + //~^ debug_assert_with_mut_call + debug_assert_ne!(S.u32_self_ref_arg_mut(&mut 3), 1); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert_ne!` + //~^ debug_assert_with_mut_call + debug_assert_ne!(S.u32_self_mut_arg_mut(&mut 3), 1); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert_ne!` + //~^ debug_assert_with_mut_call + } fn misc() { @@ -104,35 +123,43 @@ fn misc() { debug_assert_eq!(v.get(0), Some(&1)); debug_assert_ne!(v[0], 2); debug_assert_eq!(v.pop(), Some(1)); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert_eq!` + //~^ debug_assert_with_mut_call + debug_assert_ne!(Some(3), v.pop()); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert_ne!` + //~^ debug_assert_with_mut_call + let a = &mut 3; debug_assert!(bool_mut(a)); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert!` + //~^ debug_assert_with_mut_call + // nested debug_assert!(!(bool_ref(&u32_mut(&mut 3)))); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert!` + //~^ debug_assert_with_mut_call + // chained debug_assert_eq!(v.pop().unwrap(), 3); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert_eq!` + //~^ debug_assert_with_mut_call + // format args debug_assert!(bool_ref(&3), "w/o format"); debug_assert!(bool_mut(&mut 3), "w/o format"); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert!` + //~^ debug_assert_with_mut_call + debug_assert!(bool_ref(&3), "{} format", "w/"); debug_assert!(bool_mut(&mut 3), "{} format", "w/"); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert!` + //~^ debug_assert_with_mut_call + // sub block let mut x = 42_u32; debug_assert!({ bool_mut(&mut x); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert! + //~^ debug_assert_with_mut_call + x > 10 }); @@ -140,7 +167,8 @@ fn misc() { debug_assert!((|| { let mut x = 42; bool_mut(&mut x); - //~^ ERROR: do not call a function with mutable arguments inside of `debug_assert! + //~^ debug_assert_with_mut_call + x > 10 })()); } diff --git a/tests/ui/debug_assert_with_mut_call.stderr b/tests/ui/debug_assert_with_mut_call.stderr index 83e1105a07df..216ab27264c1 100644 --- a/tests/ui/debug_assert_with_mut_call.stderr +++ b/tests/ui/debug_assert_with_mut_call.stderr @@ -8,163 +8,163 @@ LL | debug_assert!(bool_mut(&mut 3)); = help: to override `-D warnings` add `#[allow(clippy::debug_assert_with_mut_call)]` error: do not call a function with mutable arguments inside of `debug_assert!` - --> tests/ui/debug_assert_with_mut_call.rs:45:20 + --> tests/ui/debug_assert_with_mut_call.rs:46:20 | LL | debug_assert!(!bool_mut(&mut 3)); | ^^^^^^^^^^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert_eq!` - --> tests/ui/debug_assert_with_mut_call.rs:48:25 + --> tests/ui/debug_assert_with_mut_call.rs:50:25 | LL | debug_assert_eq!(0, u32_mut(&mut 3)); | ^^^^^^^^^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert_eq!` - --> tests/ui/debug_assert_with_mut_call.rs:50:22 + --> tests/ui/debug_assert_with_mut_call.rs:53:22 | LL | debug_assert_eq!(u32_mut(&mut 3), 0); | ^^^^^^^^^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert_ne!` - --> tests/ui/debug_assert_with_mut_call.rs:53:25 + --> tests/ui/debug_assert_with_mut_call.rs:57:25 | LL | debug_assert_ne!(1, u32_mut(&mut 3)); | ^^^^^^^^^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert_ne!` - --> tests/ui/debug_assert_with_mut_call.rs:55:22 + --> tests/ui/debug_assert_with_mut_call.rs:60:22 | LL | debug_assert_ne!(u32_mut(&mut 3), 1); | ^^^^^^^^^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert!` - --> tests/ui/debug_assert_with_mut_call.rs:71:19 + --> tests/ui/debug_assert_with_mut_call.rs:77:19 | LL | debug_assert!(S.bool_self_mut()); | ^^^^^^^^^^^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert!` - --> tests/ui/debug_assert_with_mut_call.rs:73:20 + --> tests/ui/debug_assert_with_mut_call.rs:80:20 | LL | debug_assert!(!S.bool_self_mut()); | ^^^^^^^^^^^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert!` - --> tests/ui/debug_assert_with_mut_call.rs:75:19 + --> tests/ui/debug_assert_with_mut_call.rs:83:19 | LL | debug_assert!(S.bool_self_ref_arg_mut(&mut 3)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert!` - --> tests/ui/debug_assert_with_mut_call.rs:77:19 + --> tests/ui/debug_assert_with_mut_call.rs:86:19 | LL | debug_assert!(S.bool_self_mut_arg_ref(&3)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert!` - --> tests/ui/debug_assert_with_mut_call.rs:79:19 + --> tests/ui/debug_assert_with_mut_call.rs:89:19 | LL | debug_assert!(S.bool_self_mut_arg_mut(&mut 3)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert_eq!` - --> tests/ui/debug_assert_with_mut_call.rs:82:22 + --> tests/ui/debug_assert_with_mut_call.rs:93:22 | LL | debug_assert_eq!(S.u32_self_mut(), 0); | ^^^^^^^^^^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert_eq!` - --> tests/ui/debug_assert_with_mut_call.rs:84:22 + --> tests/ui/debug_assert_with_mut_call.rs:96:22 | LL | debug_assert_eq!(S.u32_self_mut_arg_ref(&3), 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert_eq!` - --> tests/ui/debug_assert_with_mut_call.rs:86:22 + --> tests/ui/debug_assert_with_mut_call.rs:99:22 | LL | debug_assert_eq!(S.u32_self_ref_arg_mut(&mut 3), 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert_eq!` - --> tests/ui/debug_assert_with_mut_call.rs:88:22 + --> tests/ui/debug_assert_with_mut_call.rs:102:22 | LL | debug_assert_eq!(S.u32_self_mut_arg_mut(&mut 3), 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert_ne!` - --> tests/ui/debug_assert_with_mut_call.rs:91:22 + --> tests/ui/debug_assert_with_mut_call.rs:106:22 | LL | debug_assert_ne!(S.u32_self_mut(), 1); | ^^^^^^^^^^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert_ne!` - --> tests/ui/debug_assert_with_mut_call.rs:93:22 + --> tests/ui/debug_assert_with_mut_call.rs:109:22 | LL | debug_assert_ne!(S.u32_self_mut_arg_ref(&3), 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert_ne!` - --> tests/ui/debug_assert_with_mut_call.rs:95:22 + --> tests/ui/debug_assert_with_mut_call.rs:112:22 | LL | debug_assert_ne!(S.u32_self_ref_arg_mut(&mut 3), 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert_ne!` - --> tests/ui/debug_assert_with_mut_call.rs:97:22 + --> tests/ui/debug_assert_with_mut_call.rs:115:22 | LL | debug_assert_ne!(S.u32_self_mut_arg_mut(&mut 3), 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert_eq!` - --> tests/ui/debug_assert_with_mut_call.rs:106:22 + --> tests/ui/debug_assert_with_mut_call.rs:125:22 | LL | debug_assert_eq!(v.pop(), Some(1)); | ^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert_ne!` - --> tests/ui/debug_assert_with_mut_call.rs:108:31 + --> tests/ui/debug_assert_with_mut_call.rs:128:31 | LL | debug_assert_ne!(Some(3), v.pop()); | ^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert!` - --> tests/ui/debug_assert_with_mut_call.rs:112:19 + --> tests/ui/debug_assert_with_mut_call.rs:133:19 | LL | debug_assert!(bool_mut(a)); | ^^^^^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert!` - --> tests/ui/debug_assert_with_mut_call.rs:116:31 + --> tests/ui/debug_assert_with_mut_call.rs:138:31 | LL | debug_assert!(!(bool_ref(&u32_mut(&mut 3)))); | ^^^^^^^^^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert_eq!` - --> tests/ui/debug_assert_with_mut_call.rs:120:22 + --> tests/ui/debug_assert_with_mut_call.rs:143:22 | LL | debug_assert_eq!(v.pop().unwrap(), 3); | ^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert!` - --> tests/ui/debug_assert_with_mut_call.rs:125:19 + --> tests/ui/debug_assert_with_mut_call.rs:149:19 | LL | debug_assert!(bool_mut(&mut 3), "w/o format"); | ^^^^^^^^^^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert!` - --> tests/ui/debug_assert_with_mut_call.rs:128:19 + --> tests/ui/debug_assert_with_mut_call.rs:153:19 | LL | debug_assert!(bool_mut(&mut 3), "{} format", "w/"); | ^^^^^^^^^^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert!` - --> tests/ui/debug_assert_with_mut_call.rs:134:9 + --> tests/ui/debug_assert_with_mut_call.rs:160:9 | LL | bool_mut(&mut x); | ^^^^^^^^^^^^^^^^ error: do not call a function with mutable arguments inside of `debug_assert!` - --> tests/ui/debug_assert_with_mut_call.rs:142:9 + --> tests/ui/debug_assert_with_mut_call.rs:169:9 | LL | bool_mut(&mut x); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/decimal_literal_representation.fixed b/tests/ui/decimal_literal_representation.fixed index e34f48b65dd1..e0477578488c 100644 --- a/tests/ui/decimal_literal_representation.fixed +++ b/tests/ui/decimal_literal_representation.fixed @@ -14,12 +14,19 @@ fn main() { ); let bad = ( // Hex: 0x8005, // 0x8005 + //~^ decimal_literal_representation 0xFF00, // 0xFF00 + //~^ decimal_literal_representation 0x7F0F_F00F, // 0x7F0F_F00F + //~^ decimal_literal_representation 0x7FFF_FFFF, // 0x7FFF_FFFF + //~^ decimal_literal_representation #[allow(overflowing_literals)] 0xF0F0_F0F0, // 0xF0F0_F0F0 + //~^ decimal_literal_representation 0x8005_usize, // 0x8005_usize + //~^ decimal_literal_representation 0x7F0F_F00F_isize, // 0x7F0F_F00F_isize + //~^ decimal_literal_representation ); } diff --git a/tests/ui/decimal_literal_representation.rs b/tests/ui/decimal_literal_representation.rs index bcc4d0df9c0e..85dc4fac0928 100644 --- a/tests/ui/decimal_literal_representation.rs +++ b/tests/ui/decimal_literal_representation.rs @@ -14,12 +14,19 @@ fn main() { ); let bad = ( // Hex: 32_773, // 0x8005 + //~^ decimal_literal_representation 65_280, // 0xFF00 + //~^ decimal_literal_representation 2_131_750_927, // 0x7F0F_F00F + //~^ decimal_literal_representation 2_147_483_647, // 0x7FFF_FFFF + //~^ decimal_literal_representation #[allow(overflowing_literals)] 4_042_322_160, // 0xF0F0_F0F0 + //~^ decimal_literal_representation 32_773usize, // 0x8005_usize + //~^ decimal_literal_representation 2_131_750_927isize, // 0x7F0F_F00F_isize + //~^ decimal_literal_representation ); } diff --git a/tests/ui/decimal_literal_representation.stderr b/tests/ui/decimal_literal_representation.stderr index 824e7ec85ee0..0196350ce402 100644 --- a/tests/ui/decimal_literal_representation.stderr +++ b/tests/ui/decimal_literal_representation.stderr @@ -8,37 +8,37 @@ LL | 32_773, // 0x8005 = help: to override `-D warnings` add `#[allow(clippy::decimal_literal_representation)]` error: integer literal has a better hexadecimal representation - --> tests/ui/decimal_literal_representation.rs:17:9 + --> tests/ui/decimal_literal_representation.rs:18:9 | LL | 65_280, // 0xFF00 | ^^^^^^ help: consider: `0xFF00` error: integer literal has a better hexadecimal representation - --> tests/ui/decimal_literal_representation.rs:18:9 + --> tests/ui/decimal_literal_representation.rs:20:9 | LL | 2_131_750_927, // 0x7F0F_F00F | ^^^^^^^^^^^^^ help: consider: `0x7F0F_F00F` error: integer literal has a better hexadecimal representation - --> tests/ui/decimal_literal_representation.rs:19:9 + --> tests/ui/decimal_literal_representation.rs:22:9 | LL | 2_147_483_647, // 0x7FFF_FFFF | ^^^^^^^^^^^^^ help: consider: `0x7FFF_FFFF` error: integer literal has a better hexadecimal representation - --> tests/ui/decimal_literal_representation.rs:21:9 + --> tests/ui/decimal_literal_representation.rs:25:9 | LL | 4_042_322_160, // 0xF0F0_F0F0 | ^^^^^^^^^^^^^ help: consider: `0xF0F0_F0F0` error: integer literal has a better hexadecimal representation - --> tests/ui/decimal_literal_representation.rs:22:9 + --> tests/ui/decimal_literal_representation.rs:27:9 | LL | 32_773usize, // 0x8005_usize | ^^^^^^^^^^^ help: consider: `0x8005_usize` error: integer literal has a better hexadecimal representation - --> tests/ui/decimal_literal_representation.rs:23:9 + --> tests/ui/decimal_literal_representation.rs:29:9 | LL | 2_131_750_927isize, // 0x7F0F_F00F_isize | ^^^^^^^^^^^^^^^^^^ help: consider: `0x7F0F_F00F_isize` diff --git a/tests/ui/declare_interior_mutable_const/enums.rs b/tests/ui/declare_interior_mutable_const/enums.rs index a88bf7b21b8b..c87468277fb3 100644 --- a/tests/ui/declare_interior_mutable_const/enums.rs +++ b/tests/ui/declare_interior_mutable_const/enums.rs @@ -9,7 +9,8 @@ enum OptionalCell { } // a constant with enums should be linted only when the used variant is unfrozen (#3962). -const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true)); //~ ERROR: interior mutable +const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true)); +//~^ declare_interior_mutable_const const FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen; const fn unfrozen_variant() -> OptionalCell { @@ -20,7 +21,8 @@ const fn frozen_variant() -> OptionalCell { OptionalCell::Frozen } -const UNFROZEN_VARIANT_FROM_FN: OptionalCell = unfrozen_variant(); //~ ERROR: interior mutable +const UNFROZEN_VARIANT_FROM_FN: OptionalCell = unfrozen_variant(); +//~^ declare_interior_mutable_const const FROZEN_VARIANT_FROM_FN: OptionalCell = frozen_variant(); enum NestedInnermost { @@ -43,7 +45,7 @@ struct NestedOutermost { // a constant with enums should be linted according to its value, no matter how structs involve. const NESTED_UNFROZEN_VARIANT: NestedOutermost = NestedOutermost { - //~^ ERROR: interior mutable + //~^ declare_interior_mutable_const outer: NestedOuter::NestedInner(NestedInner { inner: NestedInnermost::Unfrozen(AtomicUsize::new(2)), }), @@ -57,11 +59,14 @@ const NESTED_FROZEN_VARIANT: NestedOutermost = NestedOutermost { trait AssocConsts { // When there's no default value, lint it only according to its type. // Further details are on the corresponding code (`NonCopyConst::check_trait_item`). - const TO_BE_UNFROZEN_VARIANT: OptionalCell; //~ ERROR: interior mutable - const TO_BE_FROZEN_VARIANT: OptionalCell; //~ ERROR: interior mutable + const TO_BE_UNFROZEN_VARIANT: OptionalCell; + //~^ declare_interior_mutable_const + const TO_BE_FROZEN_VARIANT: OptionalCell; + //~^ declare_interior_mutable_const // Lint default values accordingly. - const DEFAULTED_ON_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false)); //~ ERROR: interior mutable + const DEFAULTED_ON_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false)); + //~^ declare_interior_mutable_const const DEFAULTED_ON_FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen; } @@ -87,7 +92,8 @@ trait AssocTypes { impl AssocTypes for u64 { type ToBeUnfrozen = AtomicUsize; - const TO_BE_UNFROZEN_VARIANT: Option = Some(Self::ToBeUnfrozen::new(4)); //~ ERROR: interior mutable + const TO_BE_UNFROZEN_VARIANT: Option = Some(Self::ToBeUnfrozen::new(4)); + //~^ declare_interior_mutable_const const TO_BE_FROZEN_VARIANT: Option = None; } @@ -99,25 +105,30 @@ enum BothOfCellAndGeneric { } impl BothOfCellAndGeneric { - const UNFROZEN_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR: interior mutable + const UNFROZEN_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); + //~^ declare_interior_mutable_const // This is a false positive. The argument about this is on `is_value_unfrozen_raw` - const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR: interior mutable + const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); + //~^ declare_interior_mutable_const const FROZEN_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Frozen(5); // This is what is likely to be a false negative when one tries to fix // the `GENERIC_VARIANT` false positive. - const NO_ENUM: Cell<*const T> = Cell::new(std::ptr::null()); //~ ERROR: interior mutable + const NO_ENUM: Cell<*const T> = Cell::new(std::ptr::null()); + //~^ declare_interior_mutable_const } // associated types here is basically the same as the one above. trait BothOfCellAndGenericWithAssocType { type AssocType; - const UNFROZEN_VARIANT: BothOfCellAndGeneric = //~ ERROR: interior mutable + const UNFROZEN_VARIANT: BothOfCellAndGeneric = + //~^ declare_interior_mutable_const BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); - const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR: interior mutable + const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); + //~^ declare_interior_mutable_const const FROZEN_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Frozen(5); } diff --git a/tests/ui/declare_interior_mutable_const/enums.stderr b/tests/ui/declare_interior_mutable_const/enums.stderr index 22329172c3af..32839d14f0ed 100644 --- a/tests/ui/declare_interior_mutable_const/enums.stderr +++ b/tests/ui/declare_interior_mutable_const/enums.stderr @@ -9,7 +9,7 @@ LL | const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(tru = help: to override `-D warnings` add `#[allow(clippy::declare_interior_mutable_const)]` error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/enums.rs:23:1 + --> tests/ui/declare_interior_mutable_const/enums.rs:24:1 | LL | const UNFROZEN_VARIANT_FROM_FN: OptionalCell = unfrozen_variant(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | const UNFROZEN_VARIANT_FROM_FN: OptionalCell = unfrozen_variant(); = help: consider making this `Sync` so that it can go in a static item or using a `thread_local` error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/enums.rs:45:1 + --> tests/ui/declare_interior_mutable_const/enums.rs:47:1 | LL | / const NESTED_UNFROZEN_VARIANT: NestedOutermost = NestedOutermost { LL | | @@ -30,56 +30,57 @@ LL | | }; = help: consider making this a static item error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/enums.rs:60:5 + --> tests/ui/declare_interior_mutable_const/enums.rs:62:5 | LL | const TO_BE_UNFROZEN_VARIANT: OptionalCell; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/enums.rs:61:5 + --> tests/ui/declare_interior_mutable_const/enums.rs:64:5 | LL | const TO_BE_FROZEN_VARIANT: OptionalCell; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/enums.rs:64:5 + --> tests/ui/declare_interior_mutable_const/enums.rs:68:5 | LL | const DEFAULTED_ON_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/enums.rs:90:5 + --> tests/ui/declare_interior_mutable_const/enums.rs:95:5 | LL | const TO_BE_UNFROZEN_VARIANT: Option = Some(Self::ToBeUnfrozen::new(4)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/enums.rs:102:5 + --> tests/ui/declare_interior_mutable_const/enums.rs:108:5 | LL | const UNFROZEN_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/enums.rs:105:5 + --> tests/ui/declare_interior_mutable_const/enums.rs:112:5 | LL | const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/enums.rs:111:5 + --> tests/ui/declare_interior_mutable_const/enums.rs:119:5 | LL | const NO_ENUM: Cell<*const T> = Cell::new(std::ptr::null()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/enums.rs:118:5 + --> tests/ui/declare_interior_mutable_const/enums.rs:127:5 | LL | / const UNFROZEN_VARIANT: BothOfCellAndGeneric = +LL | | LL | | BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); | |____________________________________________________________________^ error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/enums.rs:120:5 + --> tests/ui/declare_interior_mutable_const/enums.rs:130:5 | LL | const GENERIC_VARIANT: BothOfCellAndGeneric = BothOfCellAndGeneric::Generic(std::ptr::null()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/declare_interior_mutable_const/others.rs b/tests/ui/declare_interior_mutable_const/others.rs index 0dccf18c4930..7ce04a3f2c34 100644 --- a/tests/ui/declare_interior_mutable_const/others.rs +++ b/tests/ui/declare_interior_mutable_const/others.rs @@ -7,15 +7,17 @@ use std::ptr; use std::sync::Once; use std::sync::atomic::AtomicUsize; -const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR: interior mutable -const CELL: Cell = Cell::new(6); //~ ERROR: interior mutable +const ATOMIC: AtomicUsize = AtomicUsize::new(5); +//~^ declare_interior_mutable_const +const CELL: Cell = Cell::new(6); +//~^ declare_interior_mutable_const const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec, u8) = ([ATOMIC], Vec::new(), 7); -//~^ ERROR: interior mutable +//~^ declare_interior_mutable_const macro_rules! declare_const { ($name:ident: $ty:ty = $e:expr) => { const $name: $ty = $e; - //~^ ERROR: interior mutable + //~^ declare_interior_mutable_const }; } declare_const!(_ONCE: Once = Once::new()); @@ -43,6 +45,7 @@ mod issue_8493 { macro_rules! issue_8493 { () => { const _BAZ: Cell = Cell::new(0); + //~^ declare_interior_mutable_const static _FOOBAR: () = { thread_local! { static _VAR: Cell = const { Cell::new(0) }; diff --git a/tests/ui/declare_interior_mutable_const/others.stderr b/tests/ui/declare_interior_mutable_const/others.stderr index 4a7251471424..09299b290416 100644 --- a/tests/ui/declare_interior_mutable_const/others.stderr +++ b/tests/ui/declare_interior_mutable_const/others.stderr @@ -9,7 +9,7 @@ LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5); = help: to override `-D warnings` add `#[allow(clippy::declare_interior_mutable_const)]` error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/others.rs:11:1 + --> tests/ui/declare_interior_mutable_const/others.rs:12:1 | LL | const CELL: Cell = Cell::new(6); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | const CELL: Cell = Cell::new(6); = help: consider making this `Sync` so that it can go in a static item or using a `thread_local` error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/others.rs:12:1 + --> tests/ui/declare_interior_mutable_const/others.rs:14:1 | LL | const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec, u8) = ([ATOMIC], Vec::new(), 7); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec, u8) = ([ATOMIC], V = help: consider making this a static item error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/others.rs:17:9 + --> tests/ui/declare_interior_mutable_const/others.rs:19:9 | LL | const $name: $ty = $e; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +36,7 @@ LL | declare_const!(_ONCE: Once = Once::new()); = note: this error originates in the macro `declare_const` (in Nightly builds, run with -Z macro-backtrace for more info) error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/others.rs:45:13 + --> tests/ui/declare_interior_mutable_const/others.rs:47:13 | LL | const _BAZ: Cell = Cell::new(0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/declare_interior_mutable_const/traits.rs b/tests/ui/declare_interior_mutable_const/traits.rs index 490073f97fb1..d3139be6859f 100644 --- a/tests/ui/declare_interior_mutable_const/traits.rs +++ b/tests/ui/declare_interior_mutable_const/traits.rs @@ -7,13 +7,14 @@ use std::sync::atomic::AtomicUsize; macro_rules! declare_const { ($name:ident: $ty:ty = $e:expr) => { const $name: $ty = $e; - //~^ ERROR: interior mutable + //~^ declare_interior_mutable_const }; } // a constant whose type is a concrete type should be linted at the definition site. trait ConcreteTypes { - const ATOMIC: AtomicUsize; //~ ERROR: interior mutable + const ATOMIC: AtomicUsize; + //~^ declare_interior_mutable_const const INTEGER: u64; const STRING: String; declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC); @@ -41,7 +42,8 @@ trait GenericTypes { impl GenericTypes for u64 { const TO_REMAIN_GENERIC: T = T::DEFAULT; - const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11); //~ ERROR: interior mutable + const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11); + //~^ declare_interior_mutable_const } // a helper type used below @@ -66,8 +68,10 @@ impl AssocTypes for Vec { type ToBeGenericParam = T; const TO_BE_FROZEN: Self::ToBeFrozen = 12; - const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13); //~ ERROR: interior mutable - const WRAPPED_TO_BE_UNFROZEN: Wrapper = Wrapper(AtomicUsize::new(14)); //~ ERROR: interior mutable + const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13); + //~^ declare_interior_mutable_const + const WRAPPED_TO_BE_UNFROZEN: Wrapper = Wrapper(AtomicUsize::new(14)); + //~^ declare_interior_mutable_const const WRAPPED_TO_BE_GENERIC_PARAM: Wrapper = Wrapper(T::DEFAULT); } @@ -86,7 +90,8 @@ where T: AssocTypesHelper, { const NOT_BOUNDED: T::NotToBeBounded; - const BOUNDED: T::ToBeBounded; //~ ERROR: interior mutable + const BOUNDED: T::ToBeBounded; + //~^ declare_interior_mutable_const } impl AssocTypesFromGenericParam for u64 @@ -114,19 +119,24 @@ impl SelfType for u64 { impl SelfType for AtomicUsize { // this (interior mutable `Self` const) exists in `parking_lot`. // `const_trait_impl` will replace it in the future, hopefully. - const SELF: Self = AtomicUsize::new(17); //~ ERROR: interior mutable - const WRAPPED_SELF: Option = Some(AtomicUsize::new(21)); //~ ERROR: interior mutable + const SELF: Self = AtomicUsize::new(17); + //~^ declare_interior_mutable_const + const WRAPPED_SELF: Option = Some(AtomicUsize::new(21)); + //~^ declare_interior_mutable_const } // Even though a constant contains a generic type, if it also have an interior mutable type, // it should be linted at the definition site. trait BothOfCellAndGeneric { - const DIRECT: Cell; //~ ERROR: interior mutable - const INDIRECT: Cell<*const T>; //~ ERROR: interior mutable + const DIRECT: Cell; + //~^ declare_interior_mutable_const + const INDIRECT: Cell<*const T>; + //~^ declare_interior_mutable_const } impl BothOfCellAndGeneric for u64 { - const DIRECT: Cell = Cell::new(T::DEFAULT); //~ ERROR: interior mutable + const DIRECT: Cell = Cell::new(T::DEFAULT); + //~^ declare_interior_mutable_const const INDIRECT: Cell<*const T> = Cell::new(std::ptr::null()); } @@ -138,13 +148,15 @@ impl Local where T: ConstDefault + AssocTypesHelper, { - const ATOMIC: AtomicUsize = AtomicUsize::new(18); //~ ERROR: interior mutable + const ATOMIC: AtomicUsize = AtomicUsize::new(18); + //~^ declare_interior_mutable_const const COW: Cow<'static, str> = Cow::Borrowed("tuvwxy"); const GENERIC_TYPE: T = T::DEFAULT; const ASSOC_TYPE: T::NotToBeBounded = T::NOT_TO_BE_BOUNDED; - const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); //~ ERROR: interior mutable + const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); + //~^ declare_interior_mutable_const } fn main() {} diff --git a/tests/ui/declare_interior_mutable_const/traits.stderr b/tests/ui/declare_interior_mutable_const/traits.stderr index 4a793d985e5e..b03dd7a08403 100644 --- a/tests/ui/declare_interior_mutable_const/traits.stderr +++ b/tests/ui/declare_interior_mutable_const/traits.stderr @@ -19,67 +19,67 @@ LL | declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC); = note: this error originates in the macro `declare_const` (in Nightly builds, run with -Z macro-backtrace for more info) error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/traits.rs:44:5 + --> tests/ui/declare_interior_mutable_const/traits.rs:45:5 | LL | const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/traits.rs:69:5 + --> tests/ui/declare_interior_mutable_const/traits.rs:71:5 | LL | const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/traits.rs:70:5 + --> tests/ui/declare_interior_mutable_const/traits.rs:73:5 | LL | const WRAPPED_TO_BE_UNFROZEN: Wrapper = Wrapper(AtomicUsize::new(14)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/traits.rs:89:5 + --> tests/ui/declare_interior_mutable_const/traits.rs:93:5 | LL | const BOUNDED: T::ToBeBounded; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/traits.rs:117:5 + --> tests/ui/declare_interior_mutable_const/traits.rs:122:5 | LL | const SELF: Self = AtomicUsize::new(17); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/traits.rs:118:5 + --> tests/ui/declare_interior_mutable_const/traits.rs:124:5 | LL | const WRAPPED_SELF: Option = Some(AtomicUsize::new(21)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/traits.rs:124:5 + --> tests/ui/declare_interior_mutable_const/traits.rs:131:5 | LL | const DIRECT: Cell; | ^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/traits.rs:125:5 + --> tests/ui/declare_interior_mutable_const/traits.rs:133:5 | LL | const INDIRECT: Cell<*const T>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/traits.rs:129:5 + --> tests/ui/declare_interior_mutable_const/traits.rs:138:5 | LL | const DIRECT: Cell = Cell::new(T::DEFAULT); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/traits.rs:141:5 + --> tests/ui/declare_interior_mutable_const/traits.rs:151:5 | LL | const ATOMIC: AtomicUsize = AtomicUsize::new(18); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/traits.rs:147:5 + --> tests/ui/declare_interior_mutable_const/traits.rs:158:5 | LL | const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/default_constructed_unit_structs.fixed b/tests/ui/default_constructed_unit_structs.fixed index 3047c221d457..fa4d55177823 100644 --- a/tests/ui/default_constructed_unit_structs.fixed +++ b/tests/ui/default_constructed_unit_structs.fixed @@ -9,6 +9,7 @@ impl UnitStruct { fn new() -> Self { //should lint Self + //~^ default_constructed_unit_structs } } @@ -51,6 +52,7 @@ impl NormalStruct { // should lint Self { inner: PhantomData, + //~^ default_constructed_unit_structs } } @@ -124,9 +126,13 @@ mod issue_10755 { fn main() { // should lint let _ = PhantomData::; + //~^ default_constructed_unit_structs let _: PhantomData = PhantomData; + //~^ default_constructed_unit_structs let _: PhantomData = std::marker::PhantomData; + //~^ default_constructed_unit_structs let _ = UnitStruct; + //~^ default_constructed_unit_structs // should not lint let _ = TupleStruct::default(); diff --git a/tests/ui/default_constructed_unit_structs.rs b/tests/ui/default_constructed_unit_structs.rs index 66afedb23801..291cd89da0b7 100644 --- a/tests/ui/default_constructed_unit_structs.rs +++ b/tests/ui/default_constructed_unit_structs.rs @@ -9,6 +9,7 @@ impl UnitStruct { fn new() -> Self { //should lint Self::default() + //~^ default_constructed_unit_structs } } @@ -51,6 +52,7 @@ impl NormalStruct { // should lint Self { inner: PhantomData::default(), + //~^ default_constructed_unit_structs } } @@ -124,9 +126,13 @@ mod issue_10755 { fn main() { // should lint let _ = PhantomData::::default(); + //~^ default_constructed_unit_structs let _: PhantomData = PhantomData::default(); + //~^ default_constructed_unit_structs let _: PhantomData = std::marker::PhantomData::default(); + //~^ default_constructed_unit_structs let _ = UnitStruct::default(); + //~^ default_constructed_unit_structs // should not lint let _ = TupleStruct::default(); diff --git a/tests/ui/default_constructed_unit_structs.stderr b/tests/ui/default_constructed_unit_structs.stderr index c0fa73515c03..6d4e1bdc2cc8 100644 --- a/tests/ui/default_constructed_unit_structs.stderr +++ b/tests/ui/default_constructed_unit_structs.stderr @@ -8,31 +8,31 @@ LL | Self::default() = help: to override `-D warnings` add `#[allow(clippy::default_constructed_unit_structs)]` error: use of `default` to create a unit struct - --> tests/ui/default_constructed_unit_structs.rs:53:31 + --> tests/ui/default_constructed_unit_structs.rs:54:31 | LL | inner: PhantomData::default(), | ^^^^^^^^^^^ help: remove this call to `default` error: use of `default` to create a unit struct - --> tests/ui/default_constructed_unit_structs.rs:126:33 + --> tests/ui/default_constructed_unit_structs.rs:128:33 | LL | let _ = PhantomData::::default(); | ^^^^^^^^^^^ help: remove this call to `default` error: use of `default` to create a unit struct - --> tests/ui/default_constructed_unit_structs.rs:127:42 + --> tests/ui/default_constructed_unit_structs.rs:130:42 | LL | let _: PhantomData = PhantomData::default(); | ^^^^^^^^^^^ help: remove this call to `default` error: use of `default` to create a unit struct - --> tests/ui/default_constructed_unit_structs.rs:128:55 + --> tests/ui/default_constructed_unit_structs.rs:132:55 | LL | let _: PhantomData = std::marker::PhantomData::default(); | ^^^^^^^^^^^ help: remove this call to `default` error: use of `default` to create a unit struct - --> tests/ui/default_constructed_unit_structs.rs:129:23 + --> tests/ui/default_constructed_unit_structs.rs:134:23 | LL | let _ = UnitStruct::default(); | ^^^^^^^^^^^ help: remove this call to `default` diff --git a/tests/ui/default_instead_of_iter_empty.fixed b/tests/ui/default_instead_of_iter_empty.fixed index 3298a222bda6..548de9379927 100644 --- a/tests/ui/default_instead_of_iter_empty.fixed +++ b/tests/ui/default_instead_of_iter_empty.fixed @@ -10,8 +10,11 @@ struct Iter { fn main() { // Do lint. let _ = std::iter::empty::(); + //~^ default_instead_of_iter_empty let _ = std::iter::empty::>(); + //~^ default_instead_of_iter_empty let _foo: std::iter::Empty = std::iter::empty(); + //~^ default_instead_of_iter_empty // Do not lint. let _ = Vec::::default(); diff --git a/tests/ui/default_instead_of_iter_empty.rs b/tests/ui/default_instead_of_iter_empty.rs index 75b088a99590..824cc20566de 100644 --- a/tests/ui/default_instead_of_iter_empty.rs +++ b/tests/ui/default_instead_of_iter_empty.rs @@ -10,8 +10,11 @@ struct Iter { fn main() { // Do lint. let _ = std::iter::Empty::::default(); + //~^ default_instead_of_iter_empty let _ = std::iter::Empty::>::default(); + //~^ default_instead_of_iter_empty let _foo: std::iter::Empty = std::iter::Empty::default(); + //~^ default_instead_of_iter_empty // Do not lint. let _ = Vec::::default(); diff --git a/tests/ui/default_instead_of_iter_empty.stderr b/tests/ui/default_instead_of_iter_empty.stderr index 4bd4d060a3f7..dc0b757adc2e 100644 --- a/tests/ui/default_instead_of_iter_empty.stderr +++ b/tests/ui/default_instead_of_iter_empty.stderr @@ -8,13 +8,13 @@ LL | let _ = std::iter::Empty::::default(); = help: to override `-D warnings` add `#[allow(clippy::default_instead_of_iter_empty)]` error: `std::iter::empty()` is the more idiomatic way - --> tests/ui/default_instead_of_iter_empty.rs:13:13 + --> tests/ui/default_instead_of_iter_empty.rs:14:13 | LL | let _ = std::iter::Empty::>::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::iter::empty::>()` error: `std::iter::empty()` is the more idiomatic way - --> tests/ui/default_instead_of_iter_empty.rs:14:41 + --> tests/ui/default_instead_of_iter_empty.rs:16:41 | LL | let _foo: std::iter::Empty = std::iter::Empty::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::iter::empty()` diff --git a/tests/ui/default_instead_of_iter_empty_no_std.fixed b/tests/ui/default_instead_of_iter_empty_no_std.fixed index 7300bd9bd2ab..76d75ea7e591 100644 --- a/tests/ui/default_instead_of_iter_empty_no_std.fixed +++ b/tests/ui/default_instead_of_iter_empty_no_std.fixed @@ -21,7 +21,9 @@ struct Iter { fn main() { // Do lint. let _ = core::iter::empty::(); + //~^ default_instead_of_iter_empty let _foo: core::iter::Empty = core::iter::empty(); + //~^ default_instead_of_iter_empty // Do not lint. let _ = Iter::default(); diff --git a/tests/ui/default_instead_of_iter_empty_no_std.rs b/tests/ui/default_instead_of_iter_empty_no_std.rs index 0bc5c7169d12..639b73ba38de 100644 --- a/tests/ui/default_instead_of_iter_empty_no_std.rs +++ b/tests/ui/default_instead_of_iter_empty_no_std.rs @@ -21,7 +21,9 @@ struct Iter { fn main() { // Do lint. let _ = core::iter::Empty::::default(); + //~^ default_instead_of_iter_empty let _foo: core::iter::Empty = core::iter::Empty::default(); + //~^ default_instead_of_iter_empty // Do not lint. let _ = Iter::default(); diff --git a/tests/ui/default_instead_of_iter_empty_no_std.stderr b/tests/ui/default_instead_of_iter_empty_no_std.stderr index eb80da13e850..69812eba5423 100644 --- a/tests/ui/default_instead_of_iter_empty_no_std.stderr +++ b/tests/ui/default_instead_of_iter_empty_no_std.stderr @@ -8,7 +8,7 @@ LL | let _ = core::iter::Empty::::default(); = help: to override `-D warnings` add `#[allow(clippy::default_instead_of_iter_empty)]` error: `core::iter::empty()` is the more idiomatic way - --> tests/ui/default_instead_of_iter_empty_no_std.rs:24:42 + --> tests/ui/default_instead_of_iter_empty_no_std.rs:25:42 | LL | let _foo: core::iter::Empty = core::iter::Empty::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::iter::empty()` diff --git a/tests/ui/default_numeric_fallback_f64.fixed b/tests/ui/default_numeric_fallback_f64.fixed index 00f0d7644340..cf1ccab688c5 100644 --- a/tests/ui/default_numeric_fallback_f64.fixed +++ b/tests/ui/default_numeric_fallback_f64.fixed @@ -19,10 +19,20 @@ mod basic_expr { fn test() { // Should lint unsuffixed literals typed `f64`. let x = 0.12_f64; + //~^ default_numeric_fallback let x = [1.0_f64, 2.0_f64, 3.0_f64]; + //~^ default_numeric_fallback + //~| default_numeric_fallback + //~| default_numeric_fallback let x = if true { (1.0_f64, 2.0_f64) } else { (3.0_f64, 4.0_f64) }; + //~^ default_numeric_fallback + //~| default_numeric_fallback + //~| default_numeric_fallback + //~| default_numeric_fallback let x = match 1.0_f64 { + //~^ default_numeric_fallback _ => 1.0_f64, + //~^ default_numeric_fallback }; // Should NOT lint suffixed literals. @@ -42,6 +52,7 @@ mod nested_local { let x: _ = { // Should lint this because this literal is not bound to any types. let y = 1.0_f64; + //~^ default_numeric_fallback // Should NOT lint this because this literal is bound to `_` of outer `Local`. 1. @@ -50,12 +61,14 @@ mod nested_local { let x: _ = if true { // Should lint this because this literal is not bound to any types. let y = 1.0_f64; + //~^ default_numeric_fallback // Should NOT lint this because this literal is bound to `_` of outer `Local`. 1. } else { // Should lint this because this literal is not bound to any types. let y = 1.0_f64; + //~^ default_numeric_fallback // Should NOT lint this because this literal is bound to `_` of outer `Local`. 2. @@ -64,6 +77,7 @@ mod nested_local { const X: f32 = { // Should lint this because this literal is not bound to any types. let y = 1.0_f64; + //~^ default_numeric_fallback // Should NOT lint this because this literal is bound to `_` of outer `Local`. 1. @@ -80,10 +94,12 @@ mod function_def { // Should lint this because return type is inferred to `f64` and NOT bound to a concrete // type. let f = || -> _ { 1.0_f64 }; + //~^ default_numeric_fallback // Even though the output type is specified, // this unsuffixed literal is linted to reduce heuristics and keep codebase simple. let f = || -> f64 { 1.0_f64 }; + //~^ default_numeric_fallback } } @@ -98,9 +114,11 @@ mod function_calls { // Should lint this because the argument type is inferred to `f64` and NOT bound to a concrete type. generic_arg(1.0_f64); + //~^ default_numeric_fallback // Should lint this because the argument type is inferred to `f64` and NOT bound to a concrete type. let x: _ = generic_arg(1.0_f64); + //~^ default_numeric_fallback } } @@ -119,9 +137,11 @@ mod struct_ctor { // Should lint this because the field type is inferred to `f64` and NOT bound to a concrete type. GenericStruct { x: 1.0_f64 }; + //~^ default_numeric_fallback // Should lint this because the field type is inferred to `f64` and NOT bound to a concrete type. let _ = GenericStruct { x: 1.0_f64 }; + //~^ default_numeric_fallback } } @@ -140,6 +160,7 @@ mod enum_ctor { // Should lint this because the field type is inferred to `f64` and NOT bound to a concrete type. GenericEnum::X(1.0_f64); + //~^ default_numeric_fallback } } @@ -160,6 +181,7 @@ mod method_calls { // Should lint this because the argument type is bound to a concrete type. s.generic_arg(1.0_f64); + //~^ default_numeric_fallback } } @@ -170,6 +192,7 @@ mod in_macro { #[inline_macros] fn internal() { inline!(let x = 22.0_f64;); + //~^ default_numeric_fallback } // Should NOT lint in external macro. diff --git a/tests/ui/default_numeric_fallback_f64.rs b/tests/ui/default_numeric_fallback_f64.rs index 942cedac2753..345e65e0b4f9 100644 --- a/tests/ui/default_numeric_fallback_f64.rs +++ b/tests/ui/default_numeric_fallback_f64.rs @@ -19,10 +19,20 @@ mod basic_expr { fn test() { // Should lint unsuffixed literals typed `f64`. let x = 0.12; + //~^ default_numeric_fallback let x = [1., 2., 3.]; + //~^ default_numeric_fallback + //~| default_numeric_fallback + //~| default_numeric_fallback let x = if true { (1., 2.) } else { (3., 4.) }; + //~^ default_numeric_fallback + //~| default_numeric_fallback + //~| default_numeric_fallback + //~| default_numeric_fallback let x = match 1. { + //~^ default_numeric_fallback _ => 1., + //~^ default_numeric_fallback }; // Should NOT lint suffixed literals. @@ -42,6 +52,7 @@ mod nested_local { let x: _ = { // Should lint this because this literal is not bound to any types. let y = 1.; + //~^ default_numeric_fallback // Should NOT lint this because this literal is bound to `_` of outer `Local`. 1. @@ -50,12 +61,14 @@ mod nested_local { let x: _ = if true { // Should lint this because this literal is not bound to any types. let y = 1.; + //~^ default_numeric_fallback // Should NOT lint this because this literal is bound to `_` of outer `Local`. 1. } else { // Should lint this because this literal is not bound to any types. let y = 1.; + //~^ default_numeric_fallback // Should NOT lint this because this literal is bound to `_` of outer `Local`. 2. @@ -64,6 +77,7 @@ mod nested_local { const X: f32 = { // Should lint this because this literal is not bound to any types. let y = 1.; + //~^ default_numeric_fallback // Should NOT lint this because this literal is bound to `_` of outer `Local`. 1. @@ -80,10 +94,12 @@ mod function_def { // Should lint this because return type is inferred to `f64` and NOT bound to a concrete // type. let f = || -> _ { 1. }; + //~^ default_numeric_fallback // Even though the output type is specified, // this unsuffixed literal is linted to reduce heuristics and keep codebase simple. let f = || -> f64 { 1. }; + //~^ default_numeric_fallback } } @@ -98,9 +114,11 @@ mod function_calls { // Should lint this because the argument type is inferred to `f64` and NOT bound to a concrete type. generic_arg(1.); + //~^ default_numeric_fallback // Should lint this because the argument type is inferred to `f64` and NOT bound to a concrete type. let x: _ = generic_arg(1.); + //~^ default_numeric_fallback } } @@ -119,9 +137,11 @@ mod struct_ctor { // Should lint this because the field type is inferred to `f64` and NOT bound to a concrete type. GenericStruct { x: 1. }; + //~^ default_numeric_fallback // Should lint this because the field type is inferred to `f64` and NOT bound to a concrete type. let _ = GenericStruct { x: 1. }; + //~^ default_numeric_fallback } } @@ -140,6 +160,7 @@ mod enum_ctor { // Should lint this because the field type is inferred to `f64` and NOT bound to a concrete type. GenericEnum::X(1.); + //~^ default_numeric_fallback } } @@ -160,6 +181,7 @@ mod method_calls { // Should lint this because the argument type is bound to a concrete type. s.generic_arg(1.); + //~^ default_numeric_fallback } } @@ -170,6 +192,7 @@ mod in_macro { #[inline_macros] fn internal() { inline!(let x = 22.;); + //~^ default_numeric_fallback } // Should NOT lint in external macro. diff --git a/tests/ui/default_numeric_fallback_f64.stderr b/tests/ui/default_numeric_fallback_f64.stderr index d7e4dbd63771..f9451211e1ac 100644 --- a/tests/ui/default_numeric_fallback_f64.stderr +++ b/tests/ui/default_numeric_fallback_f64.stderr @@ -8,133 +8,133 @@ LL | let x = 0.12; = help: to override `-D warnings` add `#[allow(clippy::default_numeric_fallback)]` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_f64.rs:22:18 + --> tests/ui/default_numeric_fallback_f64.rs:23:18 | LL | let x = [1., 2., 3.]; | ^^ help: consider adding suffix: `1.0_f64` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_f64.rs:22:22 + --> tests/ui/default_numeric_fallback_f64.rs:23:22 | LL | let x = [1., 2., 3.]; | ^^ help: consider adding suffix: `2.0_f64` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_f64.rs:22:26 + --> tests/ui/default_numeric_fallback_f64.rs:23:26 | LL | let x = [1., 2., 3.]; | ^^ help: consider adding suffix: `3.0_f64` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_f64.rs:23:28 + --> tests/ui/default_numeric_fallback_f64.rs:27:28 | LL | let x = if true { (1., 2.) } else { (3., 4.) }; | ^^ help: consider adding suffix: `1.0_f64` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_f64.rs:23:32 + --> tests/ui/default_numeric_fallback_f64.rs:27:32 | LL | let x = if true { (1., 2.) } else { (3., 4.) }; | ^^ help: consider adding suffix: `2.0_f64` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_f64.rs:23:46 + --> tests/ui/default_numeric_fallback_f64.rs:27:46 | LL | let x = if true { (1., 2.) } else { (3., 4.) }; | ^^ help: consider adding suffix: `3.0_f64` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_f64.rs:23:50 + --> tests/ui/default_numeric_fallback_f64.rs:27:50 | LL | let x = if true { (1., 2.) } else { (3., 4.) }; | ^^ help: consider adding suffix: `4.0_f64` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_f64.rs:24:23 + --> tests/ui/default_numeric_fallback_f64.rs:32:23 | LL | let x = match 1. { | ^^ help: consider adding suffix: `1.0_f64` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_f64.rs:25:18 + --> tests/ui/default_numeric_fallback_f64.rs:34:18 | LL | _ => 1., | ^^ help: consider adding suffix: `1.0_f64` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_f64.rs:44:21 + --> tests/ui/default_numeric_fallback_f64.rs:54:21 | LL | let y = 1.; | ^^ help: consider adding suffix: `1.0_f64` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_f64.rs:52:21 + --> tests/ui/default_numeric_fallback_f64.rs:63:21 | LL | let y = 1.; | ^^ help: consider adding suffix: `1.0_f64` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_f64.rs:58:21 + --> tests/ui/default_numeric_fallback_f64.rs:70:21 | LL | let y = 1.; | ^^ help: consider adding suffix: `1.0_f64` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_f64.rs:66:21 + --> tests/ui/default_numeric_fallback_f64.rs:79:21 | LL | let y = 1.; | ^^ help: consider adding suffix: `1.0_f64` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_f64.rs:82:27 + --> tests/ui/default_numeric_fallback_f64.rs:96:27 | LL | let f = || -> _ { 1. }; | ^^ help: consider adding suffix: `1.0_f64` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_f64.rs:86:29 + --> tests/ui/default_numeric_fallback_f64.rs:101:29 | LL | let f = || -> f64 { 1. }; | ^^ help: consider adding suffix: `1.0_f64` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_f64.rs:100:21 + --> tests/ui/default_numeric_fallback_f64.rs:116:21 | LL | generic_arg(1.); | ^^ help: consider adding suffix: `1.0_f64` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_f64.rs:103:32 + --> tests/ui/default_numeric_fallback_f64.rs:120:32 | LL | let x: _ = generic_arg(1.); | ^^ help: consider adding suffix: `1.0_f64` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_f64.rs:121:28 + --> tests/ui/default_numeric_fallback_f64.rs:139:28 | LL | GenericStruct { x: 1. }; | ^^ help: consider adding suffix: `1.0_f64` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_f64.rs:124:36 + --> tests/ui/default_numeric_fallback_f64.rs:143:36 | LL | let _ = GenericStruct { x: 1. }; | ^^ help: consider adding suffix: `1.0_f64` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_f64.rs:142:24 + --> tests/ui/default_numeric_fallback_f64.rs:162:24 | LL | GenericEnum::X(1.); | ^^ help: consider adding suffix: `1.0_f64` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_f64.rs:162:23 + --> tests/ui/default_numeric_fallback_f64.rs:183:23 | LL | s.generic_arg(1.); | ^^ help: consider adding suffix: `1.0_f64` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_f64.rs:172:25 + --> tests/ui/default_numeric_fallback_f64.rs:194:25 | LL | inline!(let x = 22.;); | ^^^ help: consider adding suffix: `22.0_f64` diff --git a/tests/ui/default_numeric_fallback_i32.fixed b/tests/ui/default_numeric_fallback_i32.fixed index f28ae04fd0a4..496408aa9e87 100644 --- a/tests/ui/default_numeric_fallback_i32.fixed +++ b/tests/ui/default_numeric_fallback_i32.fixed @@ -18,11 +18,23 @@ mod basic_expr { fn test() { // Should lint unsuffixed literals typed `i32`. let x = 22_i32; + //~^ default_numeric_fallback let x = [1_i32, 2_i32, 3_i32]; + //~^ default_numeric_fallback + //~| default_numeric_fallback + //~| default_numeric_fallback let x = if true { (1_i32, 2_i32) } else { (3_i32, 4_i32) }; + //~^ default_numeric_fallback + //~| default_numeric_fallback + //~| default_numeric_fallback + //~| default_numeric_fallback let x = match 1_i32 { + //~^ default_numeric_fallback 1_i32 => 1_i32, + //~^ default_numeric_fallback + //~| default_numeric_fallback _ => 2_i32, + //~^ default_numeric_fallback }; // Should NOT lint suffixed literals. @@ -42,6 +54,7 @@ mod nested_local { let x: _ = { // Should lint this because this literal is not bound to any types. let y = 1_i32; + //~^ default_numeric_fallback // Should NOT lint this because this literal is bound to `_` of outer `Local`. 1 @@ -50,12 +63,14 @@ mod nested_local { let x: _ = if true { // Should lint this because this literal is not bound to any types. let y = 1_i32; + //~^ default_numeric_fallback // Should NOT lint this because this literal is bound to `_` of outer `Local`. 1 } else { // Should lint this because this literal is not bound to any types. let y = 1_i32; + //~^ default_numeric_fallback // Should NOT lint this because this literal is bound to `_` of outer `Local`. 2 @@ -64,6 +79,7 @@ mod nested_local { const CONST_X: i32 = { // Should lint this because this literal is not bound to any types. let y = 1_i32; + //~^ default_numeric_fallback // Should NOT lint this because this literal is bound to `_` of outer `Local`. 1 @@ -80,10 +96,12 @@ mod function_def { // Should lint this because return type is inferred to `i32` and NOT bound to a concrete // type. let f = || -> _ { 1_i32 }; + //~^ default_numeric_fallback // Even though the output type is specified, // this unsuffixed literal is linted to reduce heuristics and keep codebase simple. let f = || -> i32 { 1_i32 }; + //~^ default_numeric_fallback } } @@ -98,9 +116,11 @@ mod function_calls { // Should lint this because the argument type is inferred to `i32` and NOT bound to a concrete type. generic_arg(1_i32); + //~^ default_numeric_fallback // Should lint this because the argument type is inferred to `i32` and NOT bound to a concrete type. let x: _ = generic_arg(1_i32); + //~^ default_numeric_fallback } } @@ -119,9 +139,11 @@ mod struct_ctor { // Should lint this because the field type is inferred to `i32` and NOT bound to a concrete type. GenericStruct { x: 1_i32 }; + //~^ default_numeric_fallback // Should lint this because the field type is inferred to `i32` and NOT bound to a concrete type. let _ = GenericStruct { x: 1_i32 }; + //~^ default_numeric_fallback } } @@ -140,6 +162,7 @@ mod enum_ctor { // Should lint this because the field type is inferred to `i32` and NOT bound to a concrete type. GenericEnum::X(1_i32); + //~^ default_numeric_fallback } } @@ -160,6 +183,7 @@ mod method_calls { // Should lint this because the argument type is bound to a concrete type. s.generic_arg(1_i32); + //~^ default_numeric_fallback } } @@ -170,6 +194,7 @@ mod in_macro { #[inline_macros] fn internal() { inline!(let x = 22_i32;); + //~^ default_numeric_fallback } // Should NOT lint in external macro. @@ -212,6 +237,9 @@ mod type_already_inferred { // Should NOT lint in `vec!` call if the type was already stated let data_i32: Vec = vec![1, 2, 3]; let data_i32 = vec![1_i32, 2_i32, 3_i32]; + //~^ default_numeric_fallback + //~| default_numeric_fallback + //~| default_numeric_fallback } } diff --git a/tests/ui/default_numeric_fallback_i32.rs b/tests/ui/default_numeric_fallback_i32.rs index 78a5006444ee..90fcf4091ddc 100644 --- a/tests/ui/default_numeric_fallback_i32.rs +++ b/tests/ui/default_numeric_fallback_i32.rs @@ -18,11 +18,23 @@ mod basic_expr { fn test() { // Should lint unsuffixed literals typed `i32`. let x = 22; + //~^ default_numeric_fallback let x = [1, 2, 3]; + //~^ default_numeric_fallback + //~| default_numeric_fallback + //~| default_numeric_fallback let x = if true { (1, 2) } else { (3, 4) }; + //~^ default_numeric_fallback + //~| default_numeric_fallback + //~| default_numeric_fallback + //~| default_numeric_fallback let x = match 1 { + //~^ default_numeric_fallback 1 => 1, + //~^ default_numeric_fallback + //~| default_numeric_fallback _ => 2, + //~^ default_numeric_fallback }; // Should NOT lint suffixed literals. @@ -42,6 +54,7 @@ mod nested_local { let x: _ = { // Should lint this because this literal is not bound to any types. let y = 1; + //~^ default_numeric_fallback // Should NOT lint this because this literal is bound to `_` of outer `Local`. 1 @@ -50,12 +63,14 @@ mod nested_local { let x: _ = if true { // Should lint this because this literal is not bound to any types. let y = 1; + //~^ default_numeric_fallback // Should NOT lint this because this literal is bound to `_` of outer `Local`. 1 } else { // Should lint this because this literal is not bound to any types. let y = 1; + //~^ default_numeric_fallback // Should NOT lint this because this literal is bound to `_` of outer `Local`. 2 @@ -64,6 +79,7 @@ mod nested_local { const CONST_X: i32 = { // Should lint this because this literal is not bound to any types. let y = 1; + //~^ default_numeric_fallback // Should NOT lint this because this literal is bound to `_` of outer `Local`. 1 @@ -80,10 +96,12 @@ mod function_def { // Should lint this because return type is inferred to `i32` and NOT bound to a concrete // type. let f = || -> _ { 1 }; + //~^ default_numeric_fallback // Even though the output type is specified, // this unsuffixed literal is linted to reduce heuristics and keep codebase simple. let f = || -> i32 { 1 }; + //~^ default_numeric_fallback } } @@ -98,9 +116,11 @@ mod function_calls { // Should lint this because the argument type is inferred to `i32` and NOT bound to a concrete type. generic_arg(1); + //~^ default_numeric_fallback // Should lint this because the argument type is inferred to `i32` and NOT bound to a concrete type. let x: _ = generic_arg(1); + //~^ default_numeric_fallback } } @@ -119,9 +139,11 @@ mod struct_ctor { // Should lint this because the field type is inferred to `i32` and NOT bound to a concrete type. GenericStruct { x: 1 }; + //~^ default_numeric_fallback // Should lint this because the field type is inferred to `i32` and NOT bound to a concrete type. let _ = GenericStruct { x: 1 }; + //~^ default_numeric_fallback } } @@ -140,6 +162,7 @@ mod enum_ctor { // Should lint this because the field type is inferred to `i32` and NOT bound to a concrete type. GenericEnum::X(1); + //~^ default_numeric_fallback } } @@ -160,6 +183,7 @@ mod method_calls { // Should lint this because the argument type is bound to a concrete type. s.generic_arg(1); + //~^ default_numeric_fallback } } @@ -170,6 +194,7 @@ mod in_macro { #[inline_macros] fn internal() { inline!(let x = 22;); + //~^ default_numeric_fallback } // Should NOT lint in external macro. @@ -212,6 +237,9 @@ mod type_already_inferred { // Should NOT lint in `vec!` call if the type was already stated let data_i32: Vec = vec![1, 2, 3]; let data_i32 = vec![1, 2, 3]; + //~^ default_numeric_fallback + //~| default_numeric_fallback + //~| default_numeric_fallback } } diff --git a/tests/ui/default_numeric_fallback_i32.stderr b/tests/ui/default_numeric_fallback_i32.stderr index 67ab923ecf5f..02afbddcb3be 100644 --- a/tests/ui/default_numeric_fallback_i32.stderr +++ b/tests/ui/default_numeric_fallback_i32.stderr @@ -8,145 +8,145 @@ LL | let x = 22; = help: to override `-D warnings` add `#[allow(clippy::default_numeric_fallback)]` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:21:18 + --> tests/ui/default_numeric_fallback_i32.rs:22:18 | LL | let x = [1, 2, 3]; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:21:21 + --> tests/ui/default_numeric_fallback_i32.rs:22:21 | LL | let x = [1, 2, 3]; | ^ help: consider adding suffix: `2_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:21:24 + --> tests/ui/default_numeric_fallback_i32.rs:22:24 | LL | let x = [1, 2, 3]; | ^ help: consider adding suffix: `3_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:22:28 + --> tests/ui/default_numeric_fallback_i32.rs:26:28 | LL | let x = if true { (1, 2) } else { (3, 4) }; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:22:31 + --> tests/ui/default_numeric_fallback_i32.rs:26:31 | LL | let x = if true { (1, 2) } else { (3, 4) }; | ^ help: consider adding suffix: `2_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:22:44 + --> tests/ui/default_numeric_fallback_i32.rs:26:44 | LL | let x = if true { (1, 2) } else { (3, 4) }; | ^ help: consider adding suffix: `3_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:22:47 + --> tests/ui/default_numeric_fallback_i32.rs:26:47 | LL | let x = if true { (1, 2) } else { (3, 4) }; | ^ help: consider adding suffix: `4_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:23:23 + --> tests/ui/default_numeric_fallback_i32.rs:31:23 | LL | let x = match 1 { | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:24:13 + --> tests/ui/default_numeric_fallback_i32.rs:33:13 | LL | 1 => 1, | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:24:18 + --> tests/ui/default_numeric_fallback_i32.rs:33:18 | LL | 1 => 1, | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:25:18 + --> tests/ui/default_numeric_fallback_i32.rs:36:18 | LL | _ => 2, | ^ help: consider adding suffix: `2_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:44:21 + --> tests/ui/default_numeric_fallback_i32.rs:56:21 | LL | let y = 1; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:52:21 + --> tests/ui/default_numeric_fallback_i32.rs:65:21 | LL | let y = 1; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:58:21 + --> tests/ui/default_numeric_fallback_i32.rs:72:21 | LL | let y = 1; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:66:21 + --> tests/ui/default_numeric_fallback_i32.rs:81:21 | LL | let y = 1; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:82:27 + --> tests/ui/default_numeric_fallback_i32.rs:98:27 | LL | let f = || -> _ { 1 }; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:86:29 + --> tests/ui/default_numeric_fallback_i32.rs:103:29 | LL | let f = || -> i32 { 1 }; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:100:21 + --> tests/ui/default_numeric_fallback_i32.rs:118:21 | LL | generic_arg(1); | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:103:32 + --> tests/ui/default_numeric_fallback_i32.rs:122:32 | LL | let x: _ = generic_arg(1); | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:121:28 + --> tests/ui/default_numeric_fallback_i32.rs:141:28 | LL | GenericStruct { x: 1 }; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:124:36 + --> tests/ui/default_numeric_fallback_i32.rs:145:36 | LL | let _ = GenericStruct { x: 1 }; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:142:24 + --> tests/ui/default_numeric_fallback_i32.rs:164:24 | LL | GenericEnum::X(1); | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:162:23 + --> tests/ui/default_numeric_fallback_i32.rs:185:23 | LL | s.generic_arg(1); | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:172:25 + --> tests/ui/default_numeric_fallback_i32.rs:196:25 | LL | inline!(let x = 22;); | ^^ help: consider adding suffix: `22_i32` @@ -154,19 +154,19 @@ LL | inline!(let x = 22;); = note: this error originates in the macro `__inline_mac_fn_internal` (in Nightly builds, run with -Z macro-backtrace for more info) error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:214:29 + --> tests/ui/default_numeric_fallback_i32.rs:239:29 | LL | let data_i32 = vec![1, 2, 3]; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:214:32 + --> tests/ui/default_numeric_fallback_i32.rs:239:32 | LL | let data_i32 = vec![1, 2, 3]; | ^ help: consider adding suffix: `2_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:214:35 + --> tests/ui/default_numeric_fallback_i32.rs:239:35 | LL | let data_i32 = vec![1, 2, 3]; | ^ help: consider adding suffix: `3_i32` diff --git a/tests/ui/default_trait_access.fixed b/tests/ui/default_trait_access.fixed index 6f1e72c5a6c0..d3fe09a052ef 100644 --- a/tests/ui/default_trait_access.fixed +++ b/tests/ui/default_trait_access.fixed @@ -11,16 +11,20 @@ use std::{default, string}; fn main() { let s1: String = String::default(); + //~^ default_trait_access let s2 = String::default(); let s3: String = String::default(); + //~^ default_trait_access let s4: String = String::default(); + //~^ default_trait_access let s5 = string::String::default(); let s6: String = String::default(); + //~^ default_trait_access let s7 = std::string::String::default(); @@ -31,18 +35,22 @@ fn main() { let s10 = DerivedDefault::default(); let s11: GenericDerivedDefault = GenericDerivedDefault::default(); + //~^ default_trait_access let s12 = GenericDerivedDefault::::default(); let s13 = TupleDerivedDefault::default(); let s14: TupleDerivedDefault = TupleDerivedDefault::default(); + //~^ default_trait_access let s15: ArrayDerivedDefault = ArrayDerivedDefault::default(); + //~^ default_trait_access let s16 = ArrayDerivedDefault::default(); let s17: TupleStructDerivedDefault = TupleStructDerivedDefault::default(); + //~^ default_trait_access let s18 = TupleStructDerivedDefault::default(); diff --git a/tests/ui/default_trait_access.rs b/tests/ui/default_trait_access.rs index 5528ca8b7936..cdffb2a2ee8c 100644 --- a/tests/ui/default_trait_access.rs +++ b/tests/ui/default_trait_access.rs @@ -11,16 +11,20 @@ use std::{default, string}; fn main() { let s1: String = Default::default(); + //~^ default_trait_access let s2 = String::default(); let s3: String = D2::default(); + //~^ default_trait_access let s4: String = std::default::Default::default(); + //~^ default_trait_access let s5 = string::String::default(); let s6: String = default::Default::default(); + //~^ default_trait_access let s7 = std::string::String::default(); @@ -31,18 +35,22 @@ fn main() { let s10 = DerivedDefault::default(); let s11: GenericDerivedDefault = Default::default(); + //~^ default_trait_access let s12 = GenericDerivedDefault::::default(); let s13 = TupleDerivedDefault::default(); let s14: TupleDerivedDefault = Default::default(); + //~^ default_trait_access let s15: ArrayDerivedDefault = Default::default(); + //~^ default_trait_access let s16 = ArrayDerivedDefault::default(); let s17: TupleStructDerivedDefault = Default::default(); + //~^ default_trait_access let s18 = TupleStructDerivedDefault::default(); diff --git a/tests/ui/default_trait_access.stderr b/tests/ui/default_trait_access.stderr index 276f03d79df1..aa7eb4f89558 100644 --- a/tests/ui/default_trait_access.stderr +++ b/tests/ui/default_trait_access.stderr @@ -11,43 +11,43 @@ LL | #![deny(clippy::default_trait_access)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: calling `String::default()` is more clear than this expression - --> tests/ui/default_trait_access.rs:17:22 + --> tests/ui/default_trait_access.rs:18:22 | LL | let s3: String = D2::default(); | ^^^^^^^^^^^^^ help: try: `String::default()` error: calling `String::default()` is more clear than this expression - --> tests/ui/default_trait_access.rs:19:22 + --> tests/ui/default_trait_access.rs:21:22 | LL | let s4: String = std::default::Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `String::default()` error: calling `String::default()` is more clear than this expression - --> tests/ui/default_trait_access.rs:23:22 + --> tests/ui/default_trait_access.rs:26:22 | LL | let s6: String = default::Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `String::default()` error: calling `GenericDerivedDefault::default()` is more clear than this expression - --> tests/ui/default_trait_access.rs:33:46 + --> tests/ui/default_trait_access.rs:37:46 | LL | let s11: GenericDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `GenericDerivedDefault::default()` error: calling `TupleDerivedDefault::default()` is more clear than this expression - --> tests/ui/default_trait_access.rs:39:36 + --> tests/ui/default_trait_access.rs:44:36 | LL | let s14: TupleDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `TupleDerivedDefault::default()` error: calling `ArrayDerivedDefault::default()` is more clear than this expression - --> tests/ui/default_trait_access.rs:41:36 + --> tests/ui/default_trait_access.rs:47:36 | LL | let s15: ArrayDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `ArrayDerivedDefault::default()` error: calling `TupleStructDerivedDefault::default()` is more clear than this expression - --> tests/ui/default_trait_access.rs:45:42 + --> tests/ui/default_trait_access.rs:52:42 | LL | let s17: TupleStructDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `TupleStructDerivedDefault::default()` diff --git a/tests/ui/default_union_representation.rs b/tests/ui/default_union_representation.rs index ba63cde2fa9d..92c429c79a07 100644 --- a/tests/ui/default_union_representation.rs +++ b/tests/ui/default_union_representation.rs @@ -3,7 +3,7 @@ #![allow(clippy::repr_packed_without_abi)] union NoAttribute { - //~^ ERROR: this union has the default representation + //~^ default_union_representation a: i32, b: u32, } @@ -16,7 +16,7 @@ union ReprC { #[repr(packed)] union ReprPacked { - //~^ ERROR: this union has the default representation + //~^ default_union_representation a: i32, b: u32, } @@ -35,7 +35,7 @@ union ReprCAlign { #[repr(align(32))] union ReprAlign { - //~^ ERROR: this union has the default representation + //~^ default_union_representation a: i32, b: u32, } @@ -56,7 +56,7 @@ union ZSTsAndField2 { f3: (), } union ZSTAndTwoFields { - //~^ ERROR: this union has the default representation + //~^ default_union_representation f0: u32, f1: u64, f2: (), diff --git a/tests/ui/deprecated.rs b/tests/ui/deprecated.rs index 5617db90a470..35646e1c2391 100644 --- a/tests/ui/deprecated.rs +++ b/tests/ui/deprecated.rs @@ -15,5 +15,6 @@ #![warn(clippy::regex_macro)] //~ ERROR: lint `clippy::regex_macro` #![warn(clippy::pub_enum_variant_names)] //~ ERROR: lint `clippy::pub_enum_variant_names` #![warn(clippy::wrong_pub_self_convention)] //~ ERROR: lint `clippy::wrong_pub_self_convention` +#![warn(clippy::option_map_or_err_ok)] //~ ERROR: lint `clippy::option_map_or_err_ok` fn main() {} diff --git a/tests/ui/deprecated.stderr b/tests/ui/deprecated.stderr index b3e1646c8045..d7be1e583b08 100644 --- a/tests/ui/deprecated.stderr +++ b/tests/ui/deprecated.stderr @@ -79,5 +79,11 @@ error: lint `clippy::wrong_pub_self_convention` has been removed: `clippy::wrong LL | #![warn(clippy::wrong_pub_self_convention)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 13 previous errors +error: lint `clippy::option_map_or_err_ok` has been removed: `clippy::manual_ok_or` covers this case + --> tests/ui/deprecated.rs:18:9 + | +LL | #![warn(clippy::option_map_or_err_ok)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 14 previous errors diff --git a/tests/ui/deref_addrof.fixed b/tests/ui/deref_addrof.fixed index f412c57d6505..35dbd790e890 100644 --- a/tests/ui/deref_addrof.fixed +++ b/tests/ui/deref_addrof.fixed @@ -21,30 +21,39 @@ fn main() { let aref = &a; let b = a; + //~^ deref_addrof let b = get_number(); + //~^ deref_addrof let b = *get_reference(&a); let bytes: Vec = vec![1, 2, 3, 4]; let b = bytes[1..2][0]; + //~^ deref_addrof //This produces a suggestion of 'let b = (a);' which //will trigger the 'unused_parens' lint let b = (a); + //~^ deref_addrof let b = a; + //~^ deref_addrof #[rustfmt::skip] let b = a; + //~^ deref_addrof let b = &a; + //~^ deref_addrof let b = *aref; + //~^ deref_addrof let _ = unsafe { *core::ptr::addr_of!(a) }; let _repeat = [0; 64]; + //~^ deref_addrof // do NOT lint for array as semantic differences with/out `*&`. let _arr = *&[0, 1, 2, 3, 4]; } @@ -55,9 +64,11 @@ pub struct S; impl S { pub fn f(&self) -> &Self { inline!($(@expr self)) + //~^ deref_addrof } #[allow(unused_mut)] // mut will be unused, once the macro is fixed pub fn f_mut(mut self) -> Self { inline!($(@expr self)) + //~^ deref_addrof } } diff --git a/tests/ui/deref_addrof.rs b/tests/ui/deref_addrof.rs index 67836b0de52d..96d1b92ef7be 100644 --- a/tests/ui/deref_addrof.rs +++ b/tests/ui/deref_addrof.rs @@ -21,30 +21,39 @@ fn main() { let aref = &a; let b = *&a; + //~^ deref_addrof let b = *&get_number(); + //~^ deref_addrof let b = *get_reference(&a); let bytes: Vec = vec![1, 2, 3, 4]; let b = *&bytes[1..2][0]; + //~^ deref_addrof //This produces a suggestion of 'let b = (a);' which //will trigger the 'unused_parens' lint let b = *&(a); + //~^ deref_addrof let b = *(&a); + //~^ deref_addrof #[rustfmt::skip] let b = *((&a)); + //~^ deref_addrof let b = *&&a; + //~^ deref_addrof let b = **&aref; + //~^ deref_addrof let _ = unsafe { *core::ptr::addr_of!(a) }; let _repeat = *&[0; 64]; + //~^ deref_addrof // do NOT lint for array as semantic differences with/out `*&`. let _arr = *&[0, 1, 2, 3, 4]; } @@ -55,9 +64,11 @@ pub struct S; impl S { pub fn f(&self) -> &Self { inline!(*& $(@expr self)) + //~^ deref_addrof } #[allow(unused_mut)] // mut will be unused, once the macro is fixed pub fn f_mut(mut self) -> Self { inline!(*&mut $(@expr self)) + //~^ deref_addrof } } diff --git a/tests/ui/deref_addrof.stderr b/tests/ui/deref_addrof.stderr index 20069f746c81..81414b625b2f 100644 --- a/tests/ui/deref_addrof.stderr +++ b/tests/ui/deref_addrof.stderr @@ -8,55 +8,55 @@ LL | let b = *&a; = help: to override `-D warnings` add `#[allow(clippy::deref_addrof)]` error: immediately dereferencing a reference - --> tests/ui/deref_addrof.rs:25:13 + --> tests/ui/deref_addrof.rs:26:13 | LL | let b = *&get_number(); | ^^^^^^^^^^^^^^ help: try: `get_number()` error: immediately dereferencing a reference - --> tests/ui/deref_addrof.rs:30:13 + --> tests/ui/deref_addrof.rs:32:13 | LL | let b = *&bytes[1..2][0]; | ^^^^^^^^^^^^^^^^ help: try: `bytes[1..2][0]` error: immediately dereferencing a reference - --> tests/ui/deref_addrof.rs:34:13 + --> tests/ui/deref_addrof.rs:37:13 | LL | let b = *&(a); | ^^^^^ help: try: `(a)` error: immediately dereferencing a reference - --> tests/ui/deref_addrof.rs:36:13 + --> tests/ui/deref_addrof.rs:40:13 | LL | let b = *(&a); | ^^^^^ help: try: `a` error: immediately dereferencing a reference - --> tests/ui/deref_addrof.rs:39:13 + --> tests/ui/deref_addrof.rs:44:13 | LL | let b = *((&a)); | ^^^^^^^ help: try: `a` error: immediately dereferencing a reference - --> tests/ui/deref_addrof.rs:41:13 + --> tests/ui/deref_addrof.rs:47:13 | LL | let b = *&&a; | ^^^^ help: try: `&a` error: immediately dereferencing a reference - --> tests/ui/deref_addrof.rs:43:14 + --> tests/ui/deref_addrof.rs:50:14 | LL | let b = **&aref; | ^^^^^^ help: try: `aref` error: immediately dereferencing a reference - --> tests/ui/deref_addrof.rs:47:19 + --> tests/ui/deref_addrof.rs:55:19 | LL | let _repeat = *&[0; 64]; | ^^^^^^^^^ help: try: `[0; 64]` error: immediately dereferencing a reference - --> tests/ui/deref_addrof.rs:57:17 + --> tests/ui/deref_addrof.rs:66:17 | LL | inline!(*& $(@expr self)) | ^^^^^^^^^^^^^^^^ help: try: `$(@expr self)` @@ -64,7 +64,7 @@ LL | inline!(*& $(@expr self)) = note: this error originates in the macro `__inline_mac_impl` (in Nightly builds, run with -Z macro-backtrace for more info) error: immediately dereferencing a reference - --> tests/ui/deref_addrof.rs:61:17 + --> tests/ui/deref_addrof.rs:71:17 | LL | inline!(*&mut $(@expr self)) | ^^^^^^^^^^^^^^^^^^^ help: try: `$(@expr self)` diff --git a/tests/ui/deref_addrof_double_trigger.rs b/tests/ui/deref_addrof_double_trigger.rs index 6f997875777e..b08b2aba2319 100644 --- a/tests/ui/deref_addrof_double_trigger.rs +++ b/tests/ui/deref_addrof_double_trigger.rs @@ -8,13 +8,12 @@ fn main() { //This produces a suggestion of 'let b = *&a;' which //will trigger the 'clippy::deref_addrof' lint again let b = **&&a; - //~^ ERROR: immediately dereferencing a reference - //~| NOTE: `-D clippy::deref-addrof` implied by `-D warnings` + //~^ deref_addrof { let mut x = 10; let y = *&mut x; - //~^ ERROR: immediately dereferencing a reference + //~^ deref_addrof } { @@ -22,6 +21,6 @@ fn main() { //will trigger the 'clippy::deref_addrof' lint again let mut x = 10; let y = **&mut &mut x; - //~^ ERROR: immediately dereferencing a reference + //~^ deref_addrof } } diff --git a/tests/ui/deref_addrof_double_trigger.stderr b/tests/ui/deref_addrof_double_trigger.stderr index 8905b1424674..9ac60dd6d544 100644 --- a/tests/ui/deref_addrof_double_trigger.stderr +++ b/tests/ui/deref_addrof_double_trigger.stderr @@ -8,13 +8,13 @@ LL | let b = **&&a; = help: to override `-D warnings` add `#[allow(clippy::deref_addrof)]` error: immediately dereferencing a reference - --> tests/ui/deref_addrof_double_trigger.rs:16:17 + --> tests/ui/deref_addrof_double_trigger.rs:15:17 | LL | let y = *&mut x; | ^^^^^^^ help: try: `x` error: immediately dereferencing a reference - --> tests/ui/deref_addrof_double_trigger.rs:24:18 + --> tests/ui/deref_addrof_double_trigger.rs:23:18 | LL | let y = **&mut &mut x; | ^^^^^^^^^^^^ help: try: `&mut x` diff --git a/tests/ui/deref_addrof_macro.rs b/tests/ui/deref_addrof_macro.rs index c7e60f365060..452ccd173a16 100644 --- a/tests/ui/deref_addrof_macro.rs +++ b/tests/ui/deref_addrof_macro.rs @@ -1,3 +1,4 @@ +//@ check-pass //@aux-build:proc_macros.rs #![warn(clippy::deref_addrof)] diff --git a/tests/ui/deref_by_slicing.fixed b/tests/ui/deref_by_slicing.fixed index 87b33b1f881d..ba03904040b4 100644 --- a/tests/ui/deref_by_slicing.fixed +++ b/tests/ui/deref_by_slicing.fixed @@ -6,27 +6,41 @@ use std::io::Read; fn main() { let mut vec = vec![0]; let _ = &*vec; + //~^ deref_by_slicing let _ = &mut *vec; + //~^ deref_by_slicing let ref_vec = &mut vec; let _ = &**ref_vec; + //~^ deref_by_slicing let mut_slice = &mut **ref_vec; + //~^ deref_by_slicing let _ = &mut *mut_slice; // Err, re-borrows slice + // + //~^^ deref_by_slicing let s = String::new(); let _ = &*s; + //~^ deref_by_slicing static S: &[u8] = &[0, 1, 2]; let _ = &mut &*S; // Err, re-borrows slice + // + //~^^ deref_by_slicing let slice: &[u32] = &[0u32, 1u32]; let slice_ref = &slice; let _ = *slice_ref; // Err, derefs slice + // + //~^^ deref_by_slicing let bytes: &[u8] = &[]; let _ = (&*bytes).read_to_end(&mut vec![]).unwrap(); // Err, re-borrows slice + // + //~^^ deref_by_slicing // issue 12751 let a = &mut [1, 2, 3][..]; let _ = &*a; + //~^ deref_by_slicing } diff --git a/tests/ui/deref_by_slicing.rs b/tests/ui/deref_by_slicing.rs index 8d8882a1781e..fdaac9467f86 100644 --- a/tests/ui/deref_by_slicing.rs +++ b/tests/ui/deref_by_slicing.rs @@ -6,27 +6,41 @@ use std::io::Read; fn main() { let mut vec = vec![0]; let _ = &vec[..]; + //~^ deref_by_slicing let _ = &mut vec[..]; + //~^ deref_by_slicing let ref_vec = &mut vec; let _ = &ref_vec[..]; + //~^ deref_by_slicing let mut_slice = &mut ref_vec[..]; + //~^ deref_by_slicing let _ = &mut mut_slice[..]; // Err, re-borrows slice + // + //~^^ deref_by_slicing let s = String::new(); let _ = &s[..]; + //~^ deref_by_slicing static S: &[u8] = &[0, 1, 2]; let _ = &mut &S[..]; // Err, re-borrows slice + // + //~^^ deref_by_slicing let slice: &[u32] = &[0u32, 1u32]; let slice_ref = &slice; let _ = &slice_ref[..]; // Err, derefs slice + // + //~^^ deref_by_slicing let bytes: &[u8] = &[]; let _ = (&bytes[..]).read_to_end(&mut vec![]).unwrap(); // Err, re-borrows slice + // + //~^^ deref_by_slicing // issue 12751 let a = &mut [1, 2, 3][..]; let _ = &a[..]; + //~^ deref_by_slicing } diff --git a/tests/ui/deref_by_slicing.stderr b/tests/ui/deref_by_slicing.stderr index ceb9ab6db73d..4a379a83dfa7 100644 --- a/tests/ui/deref_by_slicing.stderr +++ b/tests/ui/deref_by_slicing.stderr @@ -8,55 +8,55 @@ LL | let _ = &vec[..]; = help: to override `-D warnings` add `#[allow(clippy::deref_by_slicing)]` error: slicing when dereferencing would work - --> tests/ui/deref_by_slicing.rs:9:13 + --> tests/ui/deref_by_slicing.rs:10:13 | LL | let _ = &mut vec[..]; | ^^^^^^^^^^^^ help: dereference the original value instead: `&mut *vec` error: slicing when dereferencing would work - --> tests/ui/deref_by_slicing.rs:12:13 + --> tests/ui/deref_by_slicing.rs:14:13 | LL | let _ = &ref_vec[..]; | ^^^^^^^^^^^^ help: dereference the original value instead: `&**ref_vec` error: slicing when dereferencing would work - --> tests/ui/deref_by_slicing.rs:13:21 + --> tests/ui/deref_by_slicing.rs:16:21 | LL | let mut_slice = &mut ref_vec[..]; | ^^^^^^^^^^^^^^^^ help: dereference the original value instead: `&mut **ref_vec` error: slicing when dereferencing would work - --> tests/ui/deref_by_slicing.rs:14:13 + --> tests/ui/deref_by_slicing.rs:18:13 | LL | let _ = &mut mut_slice[..]; // Err, re-borrows slice | ^^^^^^^^^^^^^^^^^^ help: reborrow the original value instead: `&mut *mut_slice` error: slicing when dereferencing would work - --> tests/ui/deref_by_slicing.rs:17:13 + --> tests/ui/deref_by_slicing.rs:23:13 | LL | let _ = &s[..]; | ^^^^^^ help: dereference the original value instead: `&*s` error: slicing when dereferencing would work - --> tests/ui/deref_by_slicing.rs:20:18 + --> tests/ui/deref_by_slicing.rs:27:18 | LL | let _ = &mut &S[..]; // Err, re-borrows slice | ^^^^^^ help: reborrow the original value instead: `&*S` error: slicing when dereferencing would work - --> tests/ui/deref_by_slicing.rs:24:13 + --> tests/ui/deref_by_slicing.rs:33:13 | LL | let _ = &slice_ref[..]; // Err, derefs slice | ^^^^^^^^^^^^^^ help: dereference the original value instead: `*slice_ref` error: slicing when dereferencing would work - --> tests/ui/deref_by_slicing.rs:27:13 + --> tests/ui/deref_by_slicing.rs:38:13 | LL | let _ = (&bytes[..]).read_to_end(&mut vec![]).unwrap(); // Err, re-borrows slice | ^^^^^^^^^^^^ help: reborrow the original value instead: `(&*bytes)` error: slicing when dereferencing would work - --> tests/ui/deref_by_slicing.rs:31:13 + --> tests/ui/deref_by_slicing.rs:44:13 | LL | let _ = &a[..]; | ^^^^^^ help: reborrow the original value instead: `&*a` diff --git a/tests/ui/derivable_impls.fixed b/tests/ui/derivable_impls.fixed index c85f384fd6eb..65bfded38835 100644 --- a/tests/ui/derivable_impls.fixed +++ b/tests/ui/derivable_impls.fixed @@ -144,6 +144,40 @@ impl Default for SpecializedImpl2 { } } +#[derive(Default)] +pub struct DirectDefaultDefaultCall { + v: Vec, +} + + +#[derive(Default)] +pub struct EquivalentToDefaultDefaultCallVec { + v: Vec, +} + + +pub struct S { + x: i32, +} + +impl S { + fn new() -> S { + S { x: 42 } + } +} + +impl Default for S { + fn default() -> Self { + Self::new() + } +} + +#[derive(Default)] +pub struct EquivalentToDefaultDefaultCallLocal { + v: S, +} + + // https://github.com/rust-lang/rust-clippy/issues/7654 pub struct Color { diff --git a/tests/ui/derivable_impls.rs b/tests/ui/derivable_impls.rs index 21d73ba8b777..4826c5497b4a 100644 --- a/tests/ui/derivable_impls.rs +++ b/tests/ui/derivable_impls.rs @@ -18,6 +18,7 @@ struct FooDefault<'a> { } impl std::default::Default for FooDefault<'_> { + //~^ derivable_impls fn default() -> Self { Self { a: false, @@ -39,6 +40,7 @@ impl std::default::Default for FooDefault<'_> { struct TupleDefault(bool, i32, u64); impl std::default::Default for TupleDefault { + //~^ derivable_impls fn default() -> Self { Self(false, 0, 0u64) } @@ -91,6 +93,7 @@ impl Default for FooNDVec { struct StrDefault<'a>(&'a str); impl Default for StrDefault<'_> { + //~^ derivable_impls fn default() -> Self { Self("") } @@ -117,6 +120,7 @@ mac!(0); struct Y(u32); impl Default for Y { + //~^ derivable_impls fn default() -> Self { Self(mac!()) } @@ -156,6 +160,7 @@ struct WithoutSelfCurly { } impl Default for WithoutSelfCurly { + //~^ derivable_impls fn default() -> Self { WithoutSelfCurly { a: false } } @@ -164,6 +169,7 @@ impl Default for WithoutSelfCurly { struct WithoutSelfParan(bool); impl Default for WithoutSelfParan { + //~^ derivable_impls fn default() -> Self { WithoutSelfParan(false) } @@ -181,6 +187,58 @@ impl Default for SpecializedImpl2 { } } +pub struct DirectDefaultDefaultCall { + v: Vec, +} + +impl Default for DirectDefaultDefaultCall { + //~^ derivable_impls + fn default() -> Self { + // When calling `Default::default()` in all fields, we know it is the same as deriving. + Self { v: Default::default() } + } +} + +pub struct EquivalentToDefaultDefaultCallVec { + v: Vec, +} + +impl Default for EquivalentToDefaultDefaultCallVec { + //~^ derivable_impls + fn default() -> Self { + // The body of `::default()` is `Vec::new()`, so they are equivalent. + Self { v: Vec::new() } + } +} + +pub struct S { + x: i32, +} + +impl S { + fn new() -> S { + S { x: 42 } + } +} + +impl Default for S { + fn default() -> Self { + Self::new() + } +} + +pub struct EquivalentToDefaultDefaultCallLocal { + v: S, +} + +impl Default for EquivalentToDefaultDefaultCallLocal { + //~^ derivable_impls + fn default() -> Self { + // The body of `::default()` is `S::new()`, so they are equivalent. + Self { v: S::new() } + } +} + // https://github.com/rust-lang/rust-clippy/issues/7654 pub struct Color { @@ -214,6 +272,7 @@ pub struct RepeatDefault1 { } impl Default for RepeatDefault1 { + //~^ derivable_impls fn default() -> Self { RepeatDefault1 { a: [0; 32] } } @@ -248,6 +307,7 @@ pub enum SimpleEnum { } impl Default for SimpleEnum { + //~^ derivable_impls fn default() -> Self { SimpleEnum::Bar } diff --git a/tests/ui/derivable_impls.stderr b/tests/ui/derivable_impls.stderr index 0caea892358a..0f73ad55a85e 100644 --- a/tests/ui/derivable_impls.stderr +++ b/tests/ui/derivable_impls.stderr @@ -2,9 +2,9 @@ error: this `impl` can be derived --> tests/ui/derivable_impls.rs:20:1 | LL | / impl std::default::Default for FooDefault<'_> { +LL | | LL | | fn default() -> Self { LL | | Self { -LL | | a: false, ... | LL | | } | |_^ @@ -18,9 +18,10 @@ LL ~ struct FooDefault<'a> { | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:41:1 + --> tests/ui/derivable_impls.rs:42:1 | LL | / impl std::default::Default for TupleDefault { +LL | | LL | | fn default() -> Self { LL | | Self(false, 0, 0u64) LL | | } @@ -34,9 +35,10 @@ LL ~ struct TupleDefault(bool, i32, u64); | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:93:1 + --> tests/ui/derivable_impls.rs:95:1 | LL | / impl Default for StrDefault<'_> { +LL | | LL | | fn default() -> Self { LL | | Self("") LL | | } @@ -50,9 +52,10 @@ LL ~ struct StrDefault<'a>(&'a str); | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:119:1 + --> tests/ui/derivable_impls.rs:122:1 | LL | / impl Default for Y { +LL | | LL | | fn default() -> Self { LL | | Self(mac!()) LL | | } @@ -66,9 +69,10 @@ LL ~ struct Y(u32); | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:158:1 + --> tests/ui/derivable_impls.rs:162:1 | LL | / impl Default for WithoutSelfCurly { +LL | | LL | | fn default() -> Self { LL | | WithoutSelfCurly { a: false } LL | | } @@ -82,9 +86,10 @@ LL ~ struct WithoutSelfCurly { | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:166:1 + --> tests/ui/derivable_impls.rs:171:1 | LL | / impl Default for WithoutSelfParan { +LL | | LL | | fn default() -> Self { LL | | WithoutSelfParan(false) LL | | } @@ -98,9 +103,58 @@ LL ~ struct WithoutSelfParan(bool); | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:216:1 + --> tests/ui/derivable_impls.rs:194:1 + | +LL | / impl Default for DirectDefaultDefaultCall { +LL | | +LL | | fn default() -> Self { +... | +LL | | } + | |_^ + | +help: replace the manual implementation with a derive attribute + | +LL + #[derive(Default)] +LL ~ pub struct DirectDefaultDefaultCall { + | + +error: this `impl` can be derived + --> tests/ui/derivable_impls.rs:206:1 + | +LL | / impl Default for EquivalentToDefaultDefaultCallVec { +LL | | +LL | | fn default() -> Self { +... | +LL | | } + | |_^ + | +help: replace the manual implementation with a derive attribute + | +LL + #[derive(Default)] +LL ~ pub struct EquivalentToDefaultDefaultCallVec { + | + +error: this `impl` can be derived + --> tests/ui/derivable_impls.rs:234:1 + | +LL | / impl Default for EquivalentToDefaultDefaultCallLocal { +LL | | +LL | | fn default() -> Self { +... | +LL | | } + | |_^ + | +help: replace the manual implementation with a derive attribute + | +LL + #[derive(Default)] +LL ~ pub struct EquivalentToDefaultDefaultCallLocal { + | + +error: this `impl` can be derived + --> tests/ui/derivable_impls.rs:274:1 | LL | / impl Default for RepeatDefault1 { +LL | | LL | | fn default() -> Self { LL | | RepeatDefault1 { a: [0; 32] } LL | | } @@ -114,9 +168,10 @@ LL ~ pub struct RepeatDefault1 { | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:250:1 + --> tests/ui/derivable_impls.rs:309:1 | LL | / impl Default for SimpleEnum { +LL | | LL | | fn default() -> Self { LL | | SimpleEnum::Bar LL | | } @@ -132,5 +187,5 @@ LL ~ #[default] LL ~ Bar, | -error: aborting due to 8 previous errors +error: aborting due to 11 previous errors diff --git a/tests/ui/derive.rs b/tests/ui/derive.rs index d03cc01a08b0..707a9ff05857 100644 --- a/tests/ui/derive.rs +++ b/tests/ui/derive.rs @@ -12,7 +12,8 @@ struct Qux; impl Clone for Qux { - //~^ ERROR: you are implementing `Clone` explicitly on a `Copy` type + //~^ expl_impl_clone_on_copy + fn clone(&self) -> Self { Qux } @@ -37,7 +38,8 @@ struct Lt<'a> { } impl<'a> Clone for Lt<'a> { - //~^ ERROR: you are implementing `Clone` explicitly on a `Copy` type + //~^ expl_impl_clone_on_copy + fn clone(&self) -> Self { unimplemented!() } @@ -49,7 +51,8 @@ struct BigArray { } impl Clone for BigArray { - //~^ ERROR: you are implementing `Clone` explicitly on a `Copy` type + //~^ expl_impl_clone_on_copy + fn clone(&self) -> Self { unimplemented!() } @@ -61,7 +64,8 @@ struct FnPtr { } impl Clone for FnPtr { - //~^ ERROR: you are implementing `Clone` explicitly on a `Copy` type + //~^ expl_impl_clone_on_copy + fn clone(&self) -> Self { unimplemented!() } @@ -82,7 +86,8 @@ impl Clone for Generic { #[derive(Copy)] struct Generic2(T); impl Clone for Generic2 { - //~^ ERROR: you are implementing `Clone` explicitly on a `Copy` type + //~^ expl_impl_clone_on_copy + fn clone(&self) -> Self { Self(self.0.clone()) } diff --git a/tests/ui/derive.stderr b/tests/ui/derive.stderr index d70a59855229..20278d4f4e4a 100644 --- a/tests/ui/derive.stderr +++ b/tests/ui/derive.stderr @@ -3,9 +3,9 @@ error: you are implementing `Clone` explicitly on a `Copy` type | LL | / impl Clone for Qux { LL | | +LL | | LL | | fn clone(&self) -> Self { -LL | | Qux -LL | | } +... | LL | | } | |_^ | @@ -14,99 +14,99 @@ note: consider deriving `Clone` or removing `Copy` | LL | / impl Clone for Qux { LL | | +LL | | LL | | fn clone(&self) -> Self { -LL | | Qux -LL | | } +... | LL | | } | |_^ = note: `-D clippy::expl-impl-clone-on-copy` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::expl_impl_clone_on_copy)]` error: you are implementing `Clone` explicitly on a `Copy` type - --> tests/ui/derive.rs:39:1 + --> tests/ui/derive.rs:40:1 | LL | / impl<'a> Clone for Lt<'a> { LL | | +LL | | LL | | fn clone(&self) -> Self { -LL | | unimplemented!() -LL | | } +... | LL | | } | |_^ | note: consider deriving `Clone` or removing `Copy` - --> tests/ui/derive.rs:39:1 + --> tests/ui/derive.rs:40:1 | LL | / impl<'a> Clone for Lt<'a> { LL | | +LL | | LL | | fn clone(&self) -> Self { -LL | | unimplemented!() -LL | | } +... | LL | | } | |_^ error: you are implementing `Clone` explicitly on a `Copy` type - --> tests/ui/derive.rs:51:1 + --> tests/ui/derive.rs:53:1 | LL | / impl Clone for BigArray { LL | | +LL | | LL | | fn clone(&self) -> Self { -LL | | unimplemented!() -LL | | } +... | LL | | } | |_^ | note: consider deriving `Clone` or removing `Copy` - --> tests/ui/derive.rs:51:1 + --> tests/ui/derive.rs:53:1 | LL | / impl Clone for BigArray { LL | | +LL | | LL | | fn clone(&self) -> Self { -LL | | unimplemented!() -LL | | } +... | LL | | } | |_^ error: you are implementing `Clone` explicitly on a `Copy` type - --> tests/ui/derive.rs:63:1 + --> tests/ui/derive.rs:66:1 | LL | / impl Clone for FnPtr { LL | | +LL | | LL | | fn clone(&self) -> Self { -LL | | unimplemented!() -LL | | } +... | LL | | } | |_^ | note: consider deriving `Clone` or removing `Copy` - --> tests/ui/derive.rs:63:1 + --> tests/ui/derive.rs:66:1 | LL | / impl Clone for FnPtr { LL | | +LL | | LL | | fn clone(&self) -> Self { -LL | | unimplemented!() -LL | | } +... | LL | | } | |_^ error: you are implementing `Clone` explicitly on a `Copy` type - --> tests/ui/derive.rs:84:1 + --> tests/ui/derive.rs:88:1 | LL | / impl Clone for Generic2 { LL | | +LL | | LL | | fn clone(&self) -> Self { -LL | | Self(self.0.clone()) -LL | | } +... | LL | | } | |_^ | note: consider deriving `Clone` or removing `Copy` - --> tests/ui/derive.rs:84:1 + --> tests/ui/derive.rs:88:1 | LL | / impl Clone for Generic2 { LL | | +LL | | LL | | fn clone(&self) -> Self { -LL | | Self(self.0.clone()) -LL | | } +... | LL | | } | |_^ diff --git a/tests/ui/derive_ord_xor_partial_ord.rs b/tests/ui/derive_ord_xor_partial_ord.rs index 1c7e6d1c2023..3ef4ee9463dc 100644 --- a/tests/ui/derive_ord_xor_partial_ord.rs +++ b/tests/ui/derive_ord_xor_partial_ord.rs @@ -20,7 +20,8 @@ impl PartialOrd for DeriveBoth { } #[derive(Ord, PartialEq, Eq)] -//~^ ERROR: you are deriving `Ord` but have implemented `PartialOrd` explicitly +//~^ derive_ord_xor_partial_ord + struct DeriveOrd; impl PartialOrd for DeriveOrd { @@ -30,7 +31,8 @@ impl PartialOrd for DeriveOrd { } #[derive(Ord, PartialEq, Eq)] -//~^ ERROR: you are deriving `Ord` but have implemented `PartialOrd` explicitly +//~^ derive_ord_xor_partial_ord + struct DeriveOrdWithExplicitTypeVariable; impl PartialOrd for DeriveOrdWithExplicitTypeVariable { @@ -43,7 +45,8 @@ impl PartialOrd for DeriveOrdWithExplicitType struct DerivePartialOrd; impl std::cmp::Ord for DerivePartialOrd { - //~^ ERROR: you are implementing `Ord` explicitly but have derived `PartialOrd` + //~^ derive_ord_xor_partial_ord + fn cmp(&self, other: &Self) -> Ordering { Ordering::Less } @@ -64,7 +67,8 @@ mod use_ord { struct DerivePartialOrdInUseOrd; impl Ord for DerivePartialOrdInUseOrd { - //~^ ERROR: you are implementing `Ord` explicitly but have derived `PartialOrd` + //~^ derive_ord_xor_partial_ord + fn cmp(&self, other: &Self) -> Ordering { Ordering::Less } diff --git a/tests/ui/derive_ord_xor_partial_ord.stderr b/tests/ui/derive_ord_xor_partial_ord.stderr index dcf32419baa2..6bbe54eeaa6a 100644 --- a/tests/ui/derive_ord_xor_partial_ord.stderr +++ b/tests/ui/derive_ord_xor_partial_ord.stderr @@ -5,7 +5,7 @@ LL | #[derive(Ord, PartialEq, Eq)] | ^^^ | note: `PartialOrd` implemented here - --> tests/ui/derive_ord_xor_partial_ord.rs:26:1 + --> tests/ui/derive_ord_xor_partial_ord.rs:27:1 | LL | impl PartialOrd for DeriveOrd { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,49 +14,49 @@ LL | impl PartialOrd for DeriveOrd { = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are deriving `Ord` but have implemented `PartialOrd` explicitly - --> tests/ui/derive_ord_xor_partial_ord.rs:32:10 + --> tests/ui/derive_ord_xor_partial_ord.rs:33:10 | LL | #[derive(Ord, PartialEq, Eq)] | ^^^ | note: `PartialOrd` implemented here - --> tests/ui/derive_ord_xor_partial_ord.rs:36:1 + --> tests/ui/derive_ord_xor_partial_ord.rs:38:1 | LL | impl PartialOrd for DeriveOrdWithExplicitTypeVariable { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are implementing `Ord` explicitly but have derived `PartialOrd` - --> tests/ui/derive_ord_xor_partial_ord.rs:45:1 + --> tests/ui/derive_ord_xor_partial_ord.rs:47:1 | LL | / impl std::cmp::Ord for DerivePartialOrd { LL | | +LL | | LL | | fn cmp(&self, other: &Self) -> Ordering { -LL | | Ordering::Less -LL | | } +... | LL | | } | |_^ | note: `PartialOrd` implemented here - --> tests/ui/derive_ord_xor_partial_ord.rs:42:10 + --> tests/ui/derive_ord_xor_partial_ord.rs:44:10 | LL | #[derive(PartialOrd, PartialEq, Eq)] | ^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are implementing `Ord` explicitly but have derived `PartialOrd` - --> tests/ui/derive_ord_xor_partial_ord.rs:66:5 + --> tests/ui/derive_ord_xor_partial_ord.rs:69:5 | LL | / impl Ord for DerivePartialOrdInUseOrd { LL | | +LL | | LL | | fn cmp(&self, other: &Self) -> Ordering { -LL | | Ordering::Less -LL | | } +... | LL | | } | |_____^ | note: `PartialOrd` implemented here - --> tests/ui/derive_ord_xor_partial_ord.rs:63:14 + --> tests/ui/derive_ord_xor_partial_ord.rs:66:14 | LL | #[derive(PartialOrd, PartialEq, Eq)] | ^^^^^^^^^^ diff --git a/tests/ui/derive_partial_eq_without_eq.fixed b/tests/ui/derive_partial_eq_without_eq.fixed index e4a33193a1ab..00f51d6acb94 100644 --- a/tests/ui/derive_partial_eq_without_eq.fixed +++ b/tests/ui/derive_partial_eq_without_eq.fixed @@ -9,6 +9,7 @@ pub struct NotPartialEq { // Eq can be derived but is missing #[derive(Debug, PartialEq, Eq)] +//~^ derive_partial_eq_without_eq pub struct MissingEq { foo: u32, bar: String, @@ -67,33 +68,39 @@ impl PartialEq for ManualPartialEqImpl { // Generic fields should be properly checked for Eq-ness #[derive(PartialEq, Eq)] +//~^ derive_partial_eq_without_eq pub struct GenericNotEq { foo: T, bar: U, } #[derive(PartialEq, Eq)] +//~^ derive_partial_eq_without_eq pub struct GenericEq { foo: T, bar: U, } #[derive(PartialEq, Eq)] +//~^ derive_partial_eq_without_eq pub struct TupleStruct(u32); #[derive(PartialEq, Eq)] +//~^ derive_partial_eq_without_eq pub struct GenericTupleStruct(T); #[derive(PartialEq)] pub struct TupleStructNotEq(f32); #[derive(PartialEq, Eq)] +//~^ derive_partial_eq_without_eq pub enum Enum { Foo(u32), Bar { a: String, b: () }, } #[derive(PartialEq, Eq)] +//~^ derive_partial_eq_without_eq pub enum GenericEnum { Foo(T), Bar { a: U, b: V }, @@ -107,9 +114,11 @@ pub enum EnumNotEq { // Ensure that rustfix works properly when `PartialEq` has other derives on either side #[derive(Debug, PartialEq, Eq, Clone)] +//~^ derive_partial_eq_without_eq pub struct RustFixWithOtherDerives; #[derive(PartialEq, Eq)] +//~^ derive_partial_eq_without_eq pub struct Generic(T); #[derive(PartialEq, Eq)] @@ -117,9 +126,11 @@ pub struct GenericPhantom(core::marker::PhantomData); mod _hidden { #[derive(PartialEq, Eq)] + //~^ derive_partial_eq_without_eq pub struct Reexported; #[derive(PartialEq, Eq)] + //~^ derive_partial_eq_without_eq pub struct InPubFn; #[derive(PartialEq)] @@ -180,7 +191,8 @@ mod struct_gen { } #[derive(PartialEq, Eq)] - //~^ ERROR: you are deriving `PartialEq` and can implement `Eq` + //~^ derive_partial_eq_without_eq + pub struct Foo(::Element); #[derive(PartialEq, Eq)] @@ -188,7 +200,8 @@ mod struct_gen { // issue 9319 #[derive(PartialEq, Eq)] - //~^ ERROR: you are deriving `PartialEq` and can implement `Eq` + //~^ derive_partial_eq_without_eq + pub struct Oof(T); #[derive(PartialEq, Eq)] diff --git a/tests/ui/derive_partial_eq_without_eq.rs b/tests/ui/derive_partial_eq_without_eq.rs index a418b38e3499..073330468d31 100644 --- a/tests/ui/derive_partial_eq_without_eq.rs +++ b/tests/ui/derive_partial_eq_without_eq.rs @@ -9,6 +9,7 @@ pub struct NotPartialEq { // Eq can be derived but is missing #[derive(Debug, PartialEq)] +//~^ derive_partial_eq_without_eq pub struct MissingEq { foo: u32, bar: String, @@ -67,33 +68,39 @@ impl PartialEq for ManualPartialEqImpl { // Generic fields should be properly checked for Eq-ness #[derive(PartialEq)] +//~^ derive_partial_eq_without_eq pub struct GenericNotEq { foo: T, bar: U, } #[derive(PartialEq)] +//~^ derive_partial_eq_without_eq pub struct GenericEq { foo: T, bar: U, } #[derive(PartialEq)] +//~^ derive_partial_eq_without_eq pub struct TupleStruct(u32); #[derive(PartialEq)] +//~^ derive_partial_eq_without_eq pub struct GenericTupleStruct(T); #[derive(PartialEq)] pub struct TupleStructNotEq(f32); #[derive(PartialEq)] +//~^ derive_partial_eq_without_eq pub enum Enum { Foo(u32), Bar { a: String, b: () }, } #[derive(PartialEq)] +//~^ derive_partial_eq_without_eq pub enum GenericEnum { Foo(T), Bar { a: U, b: V }, @@ -107,9 +114,11 @@ pub enum EnumNotEq { // Ensure that rustfix works properly when `PartialEq` has other derives on either side #[derive(Debug, PartialEq, Clone)] +//~^ derive_partial_eq_without_eq pub struct RustFixWithOtherDerives; #[derive(PartialEq)] +//~^ derive_partial_eq_without_eq pub struct Generic(T); #[derive(PartialEq, Eq)] @@ -117,9 +126,11 @@ pub struct GenericPhantom(core::marker::PhantomData); mod _hidden { #[derive(PartialEq)] + //~^ derive_partial_eq_without_eq pub struct Reexported; #[derive(PartialEq)] + //~^ derive_partial_eq_without_eq pub struct InPubFn; #[derive(PartialEq)] @@ -180,7 +191,8 @@ mod struct_gen { } #[derive(PartialEq)] - //~^ ERROR: you are deriving `PartialEq` and can implement `Eq` + //~^ derive_partial_eq_without_eq + pub struct Foo(::Element); #[derive(PartialEq, Eq)] @@ -188,7 +200,8 @@ mod struct_gen { // issue 9319 #[derive(PartialEq)] - //~^ ERROR: you are deriving `PartialEq` and can implement `Eq` + //~^ derive_partial_eq_without_eq + pub struct Oof(T); #[derive(PartialEq, Eq)] diff --git a/tests/ui/derive_partial_eq_without_eq.stderr b/tests/ui/derive_partial_eq_without_eq.stderr index 7436114fadb2..fd9bac28a711 100644 --- a/tests/ui/derive_partial_eq_without_eq.stderr +++ b/tests/ui/derive_partial_eq_without_eq.stderr @@ -8,19 +8,13 @@ LL | #[derive(Debug, PartialEq)] = help: to override `-D warnings` add `#[allow(clippy::derive_partial_eq_without_eq)]` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:69:10 + --> tests/ui/derive_partial_eq_without_eq.rs:70:10 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:75:10 - | -LL | #[derive(PartialEq)] - | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` - -error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:81:10 + --> tests/ui/derive_partial_eq_without_eq.rs:77:10 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` @@ -32,49 +26,55 @@ LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:90:10 + --> tests/ui/derive_partial_eq_without_eq.rs:88:10 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:96:10 + --> tests/ui/derive_partial_eq_without_eq.rs:95:10 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:109:17 + --> tests/ui/derive_partial_eq_without_eq.rs:102:10 + | +LL | #[derive(PartialEq)] + | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` + +error: you are deriving `PartialEq` and can implement `Eq` + --> tests/ui/derive_partial_eq_without_eq.rs:116:17 | LL | #[derive(Debug, PartialEq, Clone)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:112:10 + --> tests/ui/derive_partial_eq_without_eq.rs:120:10 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:119:14 + --> tests/ui/derive_partial_eq_without_eq.rs:128:14 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:122:14 + --> tests/ui/derive_partial_eq_without_eq.rs:132:14 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:182:14 + --> tests/ui/derive_partial_eq_without_eq.rs:193:14 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:190:14 + --> tests/ui/derive_partial_eq_without_eq.rs:202:14 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` diff --git a/tests/ui/derived_hash_with_manual_eq.rs b/tests/ui/derived_hash_with_manual_eq.rs index 8423699d99ed..88b574add3f2 100644 --- a/tests/ui/derived_hash_with_manual_eq.rs +++ b/tests/ui/derived_hash_with_manual_eq.rs @@ -10,7 +10,8 @@ impl PartialEq for Foo { } #[derive(Hash)] -//~^ ERROR: you are deriving `Hash` but have implemented `PartialEq` explicitly +//~^ derived_hash_with_manual_eq + struct Bar; impl PartialEq for Bar { @@ -20,7 +21,8 @@ impl PartialEq for Bar { } #[derive(Hash)] -//~^ ERROR: you are deriving `Hash` but have implemented `PartialEq` explicitly +//~^ derived_hash_with_manual_eq + struct Baz; impl PartialEq for Baz { diff --git a/tests/ui/derived_hash_with_manual_eq.stderr b/tests/ui/derived_hash_with_manual_eq.stderr index af4d247f95ba..19a24e752810 100644 --- a/tests/ui/derived_hash_with_manual_eq.stderr +++ b/tests/ui/derived_hash_with_manual_eq.stderr @@ -5,7 +5,7 @@ LL | #[derive(Hash)] | ^^^^ | note: `PartialEq` implemented here - --> tests/ui/derived_hash_with_manual_eq.rs:16:1 + --> tests/ui/derived_hash_with_manual_eq.rs:17:1 | LL | impl PartialEq for Bar { | ^^^^^^^^^^^^^^^^^^^^^^ @@ -13,13 +13,13 @@ LL | impl PartialEq for Bar { = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are deriving `Hash` but have implemented `PartialEq` explicitly - --> tests/ui/derived_hash_with_manual_eq.rs:22:10 + --> tests/ui/derived_hash_with_manual_eq.rs:23:10 | LL | #[derive(Hash)] | ^^^^ | note: `PartialEq` implemented here - --> tests/ui/derived_hash_with_manual_eq.rs:26:1 + --> tests/ui/derived_hash_with_manual_eq.rs:28:1 | LL | impl PartialEq for Baz { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/disallowed_names.rs b/tests/ui/disallowed_names.rs index 96531bf8d88c..30fbdbc1fdc8 100644 --- a/tests/ui/disallowed_names.rs +++ b/tests/ui/disallowed_names.rs @@ -10,16 +10,18 @@ #![warn(clippy::disallowed_names)] fn test(foo: ()) {} -//~^ ERROR: use of a disallowed/placeholder name `foo` -//~| NOTE: `-D clippy::disallowed-names` implied by `-D warnings` +//~^ disallowed_names fn main() { let foo = 42; - //~^ ERROR: use of a disallowed/placeholder name `foo` + //~^ disallowed_names + let baz = 42; - //~^ ERROR: use of a disallowed/placeholder name `baz` + //~^ disallowed_names + let quux = 42; - //~^ ERROR: use of a disallowed/placeholder name `quux` + //~^ disallowed_names + // Unlike these others, `bar` is actually considered an acceptable name. // Among many other legitimate uses, bar commonly refers to a period of time in music. // See https://github.com/rust-lang/rust-clippy/issues/5225. @@ -31,33 +33,37 @@ fn main() { match (42, Some(1337), Some(0)) { (foo, Some(baz), quux @ Some(_)) => (), - //~^ ERROR: use of a disallowed/placeholder name `foo` - //~| ERROR: use of a disallowed/placeholder name `baz` - //~| ERROR: use of a disallowed/placeholder name `quux` + //~^ disallowed_names + //~| disallowed_names + //~| disallowed_names _ => (), } } fn issue_1647(mut foo: u8) { - //~^ ERROR: use of a disallowed/placeholder name `foo` + //~^ disallowed_names + let mut baz = 0; - //~^ ERROR: use of a disallowed/placeholder name `baz` + //~^ disallowed_names + if let Some(mut quux) = Some(42) {} - //~^ ERROR: use of a disallowed/placeholder name `quux` + //~^ disallowed_names } fn issue_1647_ref() { let ref baz = 0; - //~^ ERROR: use of a disallowed/placeholder name `baz` + //~^ disallowed_names + if let Some(ref quux) = Some(42) {} - //~^ ERROR: use of a disallowed/placeholder name `quux` + //~^ disallowed_names } fn issue_1647_ref_mut() { let ref mut baz = 0; - //~^ ERROR: use of a disallowed/placeholder name `baz` + //~^ disallowed_names + if let Some(ref mut quux) = Some(42) {} - //~^ ERROR: use of a disallowed/placeholder name `quux` + //~^ disallowed_names } #[cfg(test)] diff --git a/tests/ui/disallowed_names.stderr b/tests/ui/disallowed_names.stderr index d131cad8e11e..09398ebbab77 100644 --- a/tests/ui/disallowed_names.stderr +++ b/tests/ui/disallowed_names.stderr @@ -8,7 +8,7 @@ LL | fn test(foo: ()) {} = help: to override `-D warnings` add `#[allow(clippy::disallowed_names)]` error: use of a disallowed/placeholder name `foo` - --> tests/ui/disallowed_names.rs:17:9 + --> tests/ui/disallowed_names.rs:16:9 | LL | let foo = 42; | ^^^ @@ -20,67 +20,67 @@ LL | let baz = 42; | ^^^ error: use of a disallowed/placeholder name `quux` - --> tests/ui/disallowed_names.rs:21:9 + --> tests/ui/disallowed_names.rs:22:9 | LL | let quux = 42; | ^^^^ error: use of a disallowed/placeholder name `foo` - --> tests/ui/disallowed_names.rs:33:10 + --> tests/ui/disallowed_names.rs:35:10 | LL | (foo, Some(baz), quux @ Some(_)) => (), | ^^^ error: use of a disallowed/placeholder name `baz` - --> tests/ui/disallowed_names.rs:33:20 + --> tests/ui/disallowed_names.rs:35:20 | LL | (foo, Some(baz), quux @ Some(_)) => (), | ^^^ error: use of a disallowed/placeholder name `quux` - --> tests/ui/disallowed_names.rs:33:26 + --> tests/ui/disallowed_names.rs:35:26 | LL | (foo, Some(baz), quux @ Some(_)) => (), | ^^^^ error: use of a disallowed/placeholder name `foo` - --> tests/ui/disallowed_names.rs:41:19 + --> tests/ui/disallowed_names.rs:43:19 | LL | fn issue_1647(mut foo: u8) { | ^^^ error: use of a disallowed/placeholder name `baz` - --> tests/ui/disallowed_names.rs:43:13 + --> tests/ui/disallowed_names.rs:46:13 | LL | let mut baz = 0; | ^^^ error: use of a disallowed/placeholder name `quux` - --> tests/ui/disallowed_names.rs:45:21 + --> tests/ui/disallowed_names.rs:49:21 | LL | if let Some(mut quux) = Some(42) {} | ^^^^ error: use of a disallowed/placeholder name `baz` - --> tests/ui/disallowed_names.rs:50:13 + --> tests/ui/disallowed_names.rs:54:13 | LL | let ref baz = 0; | ^^^ error: use of a disallowed/placeholder name `quux` - --> tests/ui/disallowed_names.rs:52:21 + --> tests/ui/disallowed_names.rs:57:21 | LL | if let Some(ref quux) = Some(42) {} | ^^^^ error: use of a disallowed/placeholder name `baz` - --> tests/ui/disallowed_names.rs:57:17 + --> tests/ui/disallowed_names.rs:62:17 | LL | let ref mut baz = 0; | ^^^ error: use of a disallowed/placeholder name `quux` - --> tests/ui/disallowed_names.rs:59:25 + --> tests/ui/disallowed_names.rs:65:25 | LL | if let Some(ref mut quux) = Some(42) {} | ^^^^ diff --git a/tests/ui/disallowed_script_idents.rs b/tests/ui/disallowed_script_idents.rs index 6b68fae318c0..08fd1d9669ee 100644 --- a/tests/ui/disallowed_script_idents.rs +++ b/tests/ui/disallowed_script_idents.rs @@ -9,8 +9,9 @@ fn main() { // Cyrillic is not allowed by default. let счётчик = 10; - //~^ ERROR: identifier `счётчик` has a Unicode script that is not allowed by configura + //~^ disallowed_script_idents + // Same for japanese. let カウンタ = 10; - //~^ ERROR: identifier `カウンタ` has a Unicode script that is not allowed by configuratio + //~^ disallowed_script_idents } diff --git a/tests/ui/disallowed_script_idents.stderr b/tests/ui/disallowed_script_idents.stderr index c11655ab6021..edbcea5e5dd6 100644 --- a/tests/ui/disallowed_script_idents.stderr +++ b/tests/ui/disallowed_script_idents.stderr @@ -11,7 +11,7 @@ LL | #![deny(clippy::disallowed_script_idents)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: identifier `カウンタ` has a Unicode script that is not allowed by configuration: Katakana - --> tests/ui/disallowed_script_idents.rs:14:9 + --> tests/ui/disallowed_script_idents.rs:15:9 | LL | let カウンタ = 10; | ^^^^^^^^ diff --git a/tests/ui/diverging_sub_expression.rs b/tests/ui/diverging_sub_expression.rs index 1abba60fd34a..b226ba69799e 100644 --- a/tests/ui/diverging_sub_expression.rs +++ b/tests/ui/diverging_sub_expression.rs @@ -18,10 +18,10 @@ impl A { fn main() { let b = true; b || diverge(); - //~^ ERROR: sub-expression diverges - //~| NOTE: `-D clippy::diverging-sub-expression` implied by `-D warnings` + //~^ diverging_sub_expression + b || A.foo(); - //~^ ERROR: sub-expression diverges + //~^ diverging_sub_expression } #[allow(dead_code, unused_variables)] @@ -32,28 +32,36 @@ fn foobar() { 4 => return, 5 => continue, 6 => true || return, - //~^ ERROR: sub-expression diverges + //~^ diverging_sub_expression + 7 => true || continue, - //~^ ERROR: sub-expression diverges + //~^ diverging_sub_expression + 8 => break, 9 => diverge(), 3 => true || diverge(), - //~^ ERROR: sub-expression diverges + //~^ diverging_sub_expression + 10 => match 42 { 99 => return, _ => true || panic!("boo"), - //~^ ERROR: sub-expression diverges + //~^ diverging_sub_expression + }, // lint blocks as well 15 => true || { return; }, - //~^ ERROR: sub-expression diverges + //~^ diverging_sub_expression + 16 => false || { return; }, - //~^ ERROR: sub-expression diverges + //~^ diverging_sub_expression + // ... and when it's a single expression 17 => true || { return }, - //~^ ERROR: sub-expression diverges + //~^ diverging_sub_expression + 18 => false || { return }, - //~^ ERROR: sub-expression diverges + //~^ diverging_sub_expression + // ... but not when there's both an expression and a statement 19 => true || { _ = 1; return }, 20 => false || { _ = 1; return }, @@ -63,7 +71,8 @@ fn foobar() { 23 => true || { return; true }, 24 => true || { return; true }, _ => true || break, - //~^ ERROR: sub-expression diverges + //~^ diverging_sub_expression + }; } } diff --git a/tests/ui/diverging_sub_expression.stderr b/tests/ui/diverging_sub_expression.stderr index f90c95696a9c..3e417aa39cd8 100644 --- a/tests/ui/diverging_sub_expression.stderr +++ b/tests/ui/diverging_sub_expression.stderr @@ -20,19 +20,19 @@ LL | 6 => true || return, | ^^^^^^ error: sub-expression diverges - --> tests/ui/diverging_sub_expression.rs:36:26 + --> tests/ui/diverging_sub_expression.rs:37:26 | LL | 7 => true || continue, | ^^^^^^^^ error: sub-expression diverges - --> tests/ui/diverging_sub_expression.rs:40:26 + --> tests/ui/diverging_sub_expression.rs:42:26 | LL | 3 => true || diverge(), | ^^^^^^^^^ error: sub-expression diverges - --> tests/ui/diverging_sub_expression.rs:44:30 + --> tests/ui/diverging_sub_expression.rs:47:30 | LL | _ => true || panic!("boo"), | ^^^^^^^^^^^^^ @@ -40,31 +40,31 @@ LL | _ => true || panic!("boo"), = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: sub-expression diverges - --> tests/ui/diverging_sub_expression.rs:48:29 + --> tests/ui/diverging_sub_expression.rs:52:29 | LL | 15 => true || { return; }, | ^^^^^^ error: sub-expression diverges - --> tests/ui/diverging_sub_expression.rs:50:30 + --> tests/ui/diverging_sub_expression.rs:55:30 | LL | 16 => false || { return; }, | ^^^^^^ error: sub-expression diverges - --> tests/ui/diverging_sub_expression.rs:53:29 + --> tests/ui/diverging_sub_expression.rs:59:29 | LL | 17 => true || { return }, | ^^^^^^ error: sub-expression diverges - --> tests/ui/diverging_sub_expression.rs:55:30 + --> tests/ui/diverging_sub_expression.rs:62:30 | LL | 18 => false || { return }, | ^^^^^^ error: sub-expression diverges - --> tests/ui/diverging_sub_expression.rs:65:26 + --> tests/ui/diverging_sub_expression.rs:73:26 | LL | _ => true || break, | ^^^^^ diff --git a/tests/ui/doc/doc-fixable.fixed b/tests/ui/doc/doc-fixable.fixed index 83574a5cd98d..5f2b697f88b0 100644 --- a/tests/ui/doc/doc-fixable.fixed +++ b/tests/ui/doc/doc-fixable.fixed @@ -7,13 +7,22 @@ #![rustfmt::skip] /// The `foo_bar` function does _nothing_. See also `foo::bar`. (note the dot there) +//~^ doc_markdown +//~| doc_markdown /// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. But not `Foo::some_fun` +//~^ doc_markdown /// which should be reported only once despite being __doubly bad__. /// Here be `::a::global:path`, and _`::another::global::path`_. :: is not a path though. +//~^ doc_markdown +//~| doc_markdown /// Import an item from `::awesome::global::blob::` (Intended postfix) +//~^ doc_markdown /// These are the options for `::Cat`: (Intended trailing single colon, shouldn't be linted) +//~^ doc_markdown /// That's not code ~`NotInCodeBlock`~. +//~^ doc_markdown /// `be_sure_we_got_to_the_end_of_it` +//~^ doc_markdown fn foo_bar() { } @@ -28,6 +37,7 @@ fn foo_bar() { /// _foo bar_ /// ~~~ /// `be_sure_we_got_to_the_end_of_it` +//~^ doc_markdown fn multiline_codeblock() { } @@ -35,6 +45,7 @@ fn multiline_codeblock() { /// multiline /// emphasis_. /// `be_sure_we_got_to_the_end_of_it` +//~^ doc_markdown fn test_emphasis() { } @@ -49,6 +60,7 @@ fn test_emphasis() { /// 32kb 32Mb 32Gb 32Tb 32Pb 32Eb /// NaN /// `be_sure_we_got_to_the_end_of_it` +//~^ doc_markdown fn test_units() { } @@ -77,6 +89,7 @@ fn test_units() { /// MinGW /// CamelCase (see also #2395) /// `be_sure_we_got_to_the_end_of_it` +//~^ doc_markdown fn test_allowed() { } @@ -94,6 +107,7 @@ fn test_allowed() { /// expression of the type `_ m c` (where `` /// is one of {`&`, '|'} and `` is one of {`!=`, `>=`, `>` , /// `be_sure_we_got_to_the_end_of_it` +//~^ doc_markdown fn main() { foo_bar(); multiline_codeblock(); @@ -102,12 +116,16 @@ fn main() { } /// ## `CamelCaseThing` +//~^ doc_markdown /// Talks about `CamelCaseThing`. Titles should be ignored; see issue #897. /// /// # `CamelCaseThing` +//~^ doc_markdown /// /// Not a title #897 `CamelCaseThing` +//~^ doc_markdown /// `be_sure_we_got_to_the_end_of_it` +//~^ doc_markdown fn issue897() { } @@ -115,6 +133,7 @@ fn issue897() { /// I am confused by brackets? (foo `x_y`) /// I am confused by brackets? (`x_y` foo) /// `be_sure_we_got_to_the_end_of_it` +//~^ doc_markdown fn issue900() { } @@ -128,6 +147,7 @@ fn issue900() { /// [iterator]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html /// [helper_types]: ../helper_types/index.html /// `be_sure_we_got_to_the_end_of_it` +//~^ doc_markdown fn issue883() { } @@ -146,6 +166,9 @@ That's in a code block: `PackedNode` And `BarQuz` too. `be_sure_we_got_to_the_end_of_it` */ +//~^^^ doc_markdown +//~^^^ doc_markdown +//~^^^^^^^^^^ doc_markdown fn issue1073() { } @@ -157,6 +180,9 @@ That's in a code block: PackedNode And `BarQuz` too. `be_sure_we_got_to_the_end_of_it` */ +//~^^ doc_markdown +//~^^^^ doc_markdown +//~^^^^^^^^^^ doc_markdown fn issue1073_alt() { } @@ -167,6 +193,7 @@ fn issue1073_alt() { /// StillDont /// ```` /// `be_sure_we_got_to_the_end_of_it` +//~^ doc_markdown fn four_quotes() { } @@ -186,6 +213,7 @@ fn issue_1469() {} fn issue_1920() {} /// An iterator over `mycrate::Collection`'s values. +//~^ doc_markdown /// It should not lint a `'static` lifetime in ticks. fn issue_2210() {} @@ -210,6 +238,7 @@ fn intra_doc_link() {} fn issue_2581() {} /// Foo \[bar\] \[baz\] \[qux\]. `DocMarkdownLint` +//~^ doc_markdown fn lint_after_escaped_chars() {} // issue #7033 - generic_const_exprs ICE @@ -233,17 +262,22 @@ where [(); N.checked_next_power_of_two().unwrap()]: { fn issue_11568() {} /// There is no try (`do()` or `do_not()`). +//~^ doc_markdown +//~| doc_markdown fn parenthesized_word() {} /// `ABes` +//~^ doc_markdown /// OSes /// UXes fn plural_acronym_test() {} extern "C" { /// `foo()` + //~^ doc_markdown fn in_extern(); } /// +//~^ doc_markdown fn check_autofix_for_base_urls() {} diff --git a/tests/ui/doc/doc-fixable.rs b/tests/ui/doc/doc-fixable.rs index 20fe89cdc536..ed3925694c67 100644 --- a/tests/ui/doc/doc-fixable.rs +++ b/tests/ui/doc/doc-fixable.rs @@ -7,13 +7,22 @@ #![rustfmt::skip] /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) +//~^ doc_markdown +//~| doc_markdown /// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. But not Foo::some_fun +//~^ doc_markdown /// which should be reported only once despite being __doubly bad__. /// Here be ::a::global:path, and _::another::global::path_. :: is not a path though. +//~^ doc_markdown +//~| doc_markdown /// Import an item from ::awesome::global::blob:: (Intended postfix) +//~^ doc_markdown /// These are the options for ::Cat: (Intended trailing single colon, shouldn't be linted) +//~^ doc_markdown /// That's not code ~NotInCodeBlock~. +//~^ doc_markdown /// be_sure_we_got_to_the_end_of_it +//~^ doc_markdown fn foo_bar() { } @@ -28,6 +37,7 @@ fn foo_bar() { /// _foo bar_ /// ~~~ /// be_sure_we_got_to_the_end_of_it +//~^ doc_markdown fn multiline_codeblock() { } @@ -35,6 +45,7 @@ fn multiline_codeblock() { /// multiline /// emphasis_. /// be_sure_we_got_to_the_end_of_it +//~^ doc_markdown fn test_emphasis() { } @@ -49,6 +60,7 @@ fn test_emphasis() { /// 32kb 32Mb 32Gb 32Tb 32Pb 32Eb /// NaN /// be_sure_we_got_to_the_end_of_it +//~^ doc_markdown fn test_units() { } @@ -77,6 +89,7 @@ fn test_units() { /// MinGW /// CamelCase (see also #2395) /// be_sure_we_got_to_the_end_of_it +//~^ doc_markdown fn test_allowed() { } @@ -94,6 +107,7 @@ fn test_allowed() { /// expression of the type `_ m c` (where `` /// is one of {`&`, '|'} and `` is one of {`!=`, `>=`, `>` , /// be_sure_we_got_to_the_end_of_it +//~^ doc_markdown fn main() { foo_bar(); multiline_codeblock(); @@ -102,12 +116,16 @@ fn main() { } /// ## CamelCaseThing +//~^ doc_markdown /// Talks about `CamelCaseThing`. Titles should be ignored; see issue #897. /// /// # CamelCaseThing +//~^ doc_markdown /// /// Not a title #897 CamelCaseThing +//~^ doc_markdown /// be_sure_we_got_to_the_end_of_it +//~^ doc_markdown fn issue897() { } @@ -115,6 +133,7 @@ fn issue897() { /// I am confused by brackets? (foo `x_y`) /// I am confused by brackets? (`x_y` foo) /// be_sure_we_got_to_the_end_of_it +//~^ doc_markdown fn issue900() { } @@ -128,6 +147,7 @@ fn issue900() { /// [iterator]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html /// [helper_types]: ../helper_types/index.html /// be_sure_we_got_to_the_end_of_it +//~^ doc_markdown fn issue883() { } @@ -146,6 +166,9 @@ That's in a code block: `PackedNode` And BarQuz too. be_sure_we_got_to_the_end_of_it */ +//~^^^ doc_markdown +//~^^^ doc_markdown +//~^^^^^^^^^^ doc_markdown fn issue1073() { } @@ -157,6 +180,9 @@ That's in a code block: PackedNode And BarQuz too. be_sure_we_got_to_the_end_of_it */ +//~^^ doc_markdown +//~^^^^ doc_markdown +//~^^^^^^^^^^ doc_markdown fn issue1073_alt() { } @@ -167,6 +193,7 @@ fn issue1073_alt() { /// StillDont /// ```` /// be_sure_we_got_to_the_end_of_it +//~^ doc_markdown fn four_quotes() { } @@ -186,6 +213,7 @@ fn issue_1469() {} fn issue_1920() {} /// An iterator over mycrate::Collection's values. +//~^ doc_markdown /// It should not lint a `'static` lifetime in ticks. fn issue_2210() {} @@ -210,6 +238,7 @@ fn intra_doc_link() {} fn issue_2581() {} /// Foo \[bar\] \[baz\] \[qux\]. DocMarkdownLint +//~^ doc_markdown fn lint_after_escaped_chars() {} // issue #7033 - generic_const_exprs ICE @@ -233,17 +262,22 @@ where [(); N.checked_next_power_of_two().unwrap()]: { fn issue_11568() {} /// There is no try (do() or do_not()). +//~^ doc_markdown +//~| doc_markdown fn parenthesized_word() {} /// ABes +//~^ doc_markdown /// OSes /// UXes fn plural_acronym_test() {} extern "C" { /// foo() + //~^ doc_markdown fn in_extern(); } /// https://github.com/rust-lang/rust-clippy/pull/12836 +//~^ doc_markdown fn check_autofix_for_base_urls() {} diff --git a/tests/ui/doc/doc-fixable.stderr b/tests/ui/doc/doc-fixable.stderr index 54d735814855..d67da75a230c 100644 --- a/tests/ui/doc/doc-fixable.stderr +++ b/tests/ui/doc/doc-fixable.stderr @@ -25,7 +25,7 @@ LL + /// The foo_bar function does _nothing_. See also `foo::bar`. (note the dot | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:10:83 + --> tests/ui/doc/doc-fixable.rs:12:83 | LL | /// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. But not Foo::some_fun | ^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + /// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. B | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:12:13 + --> tests/ui/doc/doc-fixable.rs:15:13 | LL | /// Here be ::a::global:path, and _::another::global::path_. :: is not a path though. | ^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + /// Here be `::a::global:path`, and _::another::global::path_. :: is not a | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:12:36 + --> tests/ui/doc/doc-fixable.rs:15:36 | LL | /// Here be ::a::global:path, and _::another::global::path_. :: is not a path though. | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + /// Here be ::a::global:path, and _`::another::global::path`_. :: is not a | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:13:25 + --> tests/ui/doc/doc-fixable.rs:18:25 | LL | /// Import an item from ::awesome::global::blob:: (Intended postfix) | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + /// Import an item from `::awesome::global::blob::` (Intended postfix) | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:14:31 + --> tests/ui/doc/doc-fixable.rs:20:31 | LL | /// These are the options for ::Cat: (Intended trailing single colon, shouldn't be linted) | ^^^^^ @@ -85,7 +85,7 @@ LL + /// These are the options for `::Cat`: (Intended trailing single colon, sho | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:15:22 + --> tests/ui/doc/doc-fixable.rs:22:22 | LL | /// That's not code ~NotInCodeBlock~. | ^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL + /// That's not code ~`NotInCodeBlock`~. | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:16:5 + --> tests/ui/doc/doc-fixable.rs:24:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:30:5 + --> tests/ui/doc/doc-fixable.rs:39:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:37:5 + --> tests/ui/doc/doc-fixable.rs:47:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:51:5 + --> tests/ui/doc/doc-fixable.rs:62:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -145,7 +145,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:79:5 + --> tests/ui/doc/doc-fixable.rs:91:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:96:5 + --> tests/ui/doc/doc-fixable.rs:109:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -169,7 +169,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:104:8 + --> tests/ui/doc/doc-fixable.rs:118:8 | LL | /// ## CamelCaseThing | ^^^^^^^^^^^^^^ @@ -181,7 +181,7 @@ LL + /// ## `CamelCaseThing` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:107:7 + --> tests/ui/doc/doc-fixable.rs:122:7 | LL | /// # CamelCaseThing | ^^^^^^^^^^^^^^ @@ -193,7 +193,7 @@ LL + /// # `CamelCaseThing` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:109:22 + --> tests/ui/doc/doc-fixable.rs:125:22 | LL | /// Not a title #897 CamelCaseThing | ^^^^^^^^^^^^^^ @@ -205,7 +205,7 @@ LL + /// Not a title #897 `CamelCaseThing` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:110:5 + --> tests/ui/doc/doc-fixable.rs:127:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +217,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:117:5 + --> tests/ui/doc/doc-fixable.rs:135:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -229,7 +229,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:130:5 + --> tests/ui/doc/doc-fixable.rs:149:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,7 +241,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:141:43 + --> tests/ui/doc/doc-fixable.rs:161:43 | LL | /** E.g., serialization of an empty list: FooBar | ^^^^^^ @@ -253,7 +253,7 @@ LL + /** E.g., serialization of an empty list: `FooBar` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:146:5 + --> tests/ui/doc/doc-fixable.rs:166:5 | LL | And BarQuz too. | ^^^^^^ @@ -265,7 +265,7 @@ LL + And `BarQuz` too. | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:147:1 + --> tests/ui/doc/doc-fixable.rs:167:1 | LL | be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -277,7 +277,7 @@ LL + `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:152:43 + --> tests/ui/doc/doc-fixable.rs:175:43 | LL | /** E.g., serialization of an empty list: FooBar | ^^^^^^ @@ -289,7 +289,7 @@ LL + /** E.g., serialization of an empty list: `FooBar` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:157:5 + --> tests/ui/doc/doc-fixable.rs:180:5 | LL | And BarQuz too. | ^^^^^^ @@ -301,7 +301,7 @@ LL + And `BarQuz` too. | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:158:1 + --> tests/ui/doc/doc-fixable.rs:181:1 | LL | be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -313,7 +313,7 @@ LL + `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:169:5 + --> tests/ui/doc/doc-fixable.rs:195:5 | LL | /// be_sure_we_got_to_the_end_of_it | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -325,7 +325,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:188:22 + --> tests/ui/doc/doc-fixable.rs:215:22 | LL | /// An iterator over mycrate::Collection's values. | ^^^^^^^^^^^^^^^^^^^ @@ -337,7 +337,7 @@ LL + /// An iterator over `mycrate::Collection`'s values. | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:212:34 + --> tests/ui/doc/doc-fixable.rs:240:34 | LL | /// Foo \[bar\] \[baz\] \[qux\]. DocMarkdownLint | ^^^^^^^^^^^^^^^ @@ -349,7 +349,7 @@ LL + /// Foo \[bar\] \[baz\] \[qux\]. `DocMarkdownLint` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:235:22 + --> tests/ui/doc/doc-fixable.rs:264:22 | LL | /// There is no try (do() or do_not()). | ^^^^ @@ -361,7 +361,7 @@ LL + /// There is no try (`do()` or do_not()). | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:235:30 + --> tests/ui/doc/doc-fixable.rs:264:30 | LL | /// There is no try (do() or do_not()). | ^^^^^^^^ @@ -373,7 +373,7 @@ LL + /// There is no try (do() or `do_not()`). | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:238:5 + --> tests/ui/doc/doc-fixable.rs:269:5 | LL | /// ABes | ^^^^ @@ -385,7 +385,7 @@ LL + /// `ABes` | error: item in documentation is missing backticks - --> tests/ui/doc/doc-fixable.rs:244:9 + --> tests/ui/doc/doc-fixable.rs:276:9 | LL | /// foo() | ^^^^^ @@ -397,7 +397,7 @@ LL + /// `foo()` | error: you should put bare URLs between `<`/`>` or make a proper Markdown link - --> tests/ui/doc/doc-fixable.rs:248:5 + --> tests/ui/doc/doc-fixable.rs:281:5 | LL | /// https://github.com/rust-lang/rust-clippy/pull/12836 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `` diff --git a/tests/ui/doc/doc_include_without_cfg.fixed b/tests/ui/doc/doc_include_without_cfg.fixed index d4ae810d7385..a05954adf5a5 100644 --- a/tests/ui/doc/doc_include_without_cfg.fixed +++ b/tests/ui/doc/doc_include_without_cfg.fixed @@ -1,7 +1,8 @@ #![warn(clippy::doc_include_without_cfg)] // Should not lint. #![doc(html_playground_url = "https://playground.example.com/")] -#![cfg_attr(doc, doc = include_str!("../approx_const.rs"))] //~ doc_include_without_cfg +#![cfg_attr(doc, doc = include_str!("../approx_const.rs"))] +//~^ doc_include_without_cfg // Should not lint. #![cfg_attr(feature = "whatever", doc = include_str!("../approx_const.rs"))] #![cfg_attr(doc, doc = include_str!("../approx_const.rs"))] @@ -28,7 +29,8 @@ tst! { /// This is a test with no included file } -#[cfg_attr(doc, doc = include_str!("../approx_const.rs"))] //~ doc_include_without_cfg +#[cfg_attr(doc, doc = include_str!("../approx_const.rs"))] +//~^ doc_include_without_cfg // Should not lint. #[doc = man_link!("bla", "blob")] #[cfg_attr(feature = "whatever", doc = include_str!("../approx_const.rs"))] diff --git a/tests/ui/doc/doc_include_without_cfg.rs b/tests/ui/doc/doc_include_without_cfg.rs index c82f6bf20356..26aa7a3a706a 100644 --- a/tests/ui/doc/doc_include_without_cfg.rs +++ b/tests/ui/doc/doc_include_without_cfg.rs @@ -1,7 +1,8 @@ #![warn(clippy::doc_include_without_cfg)] // Should not lint. #![doc(html_playground_url = "https://playground.example.com/")] -#![doc = include_str!("../approx_const.rs")] //~ doc_include_without_cfg +#![doc = include_str!("../approx_const.rs")] +//~^ doc_include_without_cfg // Should not lint. #![cfg_attr(feature = "whatever", doc = include_str!("../approx_const.rs"))] #![cfg_attr(doc, doc = include_str!("../approx_const.rs"))] @@ -28,7 +29,8 @@ tst! { /// This is a test with no included file } -#[doc = include_str!("../approx_const.rs")] //~ doc_include_without_cfg +#[doc = include_str!("../approx_const.rs")] +//~^ doc_include_without_cfg // Should not lint. #[doc = man_link!("bla", "blob")] #[cfg_attr(feature = "whatever", doc = include_str!("../approx_const.rs"))] diff --git a/tests/ui/doc/doc_include_without_cfg.stderr b/tests/ui/doc/doc_include_without_cfg.stderr index 17ea53c7c318..24991df581e8 100644 --- a/tests/ui/doc/doc_include_without_cfg.stderr +++ b/tests/ui/doc/doc_include_without_cfg.stderr @@ -8,7 +8,7 @@ LL | #![doc = include_str!("../approx_const.rs")] = help: to override `-D warnings` add `#[allow(clippy::doc_include_without_cfg)]` error: included a file in documentation unconditionally - --> tests/ui/doc/doc_include_without_cfg.rs:31:1 + --> tests/ui/doc/doc_include_without_cfg.rs:32:1 | LL | #[doc = include_str!("../approx_const.rs")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `cfg_attr(doc, doc = "...")`: `#[cfg_attr(doc, doc = include_str!("../approx_const.rs"))]` diff --git a/tests/ui/doc/doc_nested_refdef_list_item.fixed b/tests/ui/doc/doc_nested_refdef_list_item.fixed index fcfcfcc40736..065f4486e390 100644 --- a/tests/ui/doc/doc_nested_refdef_list_item.fixed +++ b/tests/ui/doc/doc_nested_refdef_list_item.fixed @@ -69,3 +69,11 @@ pub struct NotEmpty; /// - [link]\: notdef /// inner text pub struct NotEmptyTight; + +/// ## Heading +/// +/// - [x][] - Done +//~^ ERROR: link reference defined in list item +/// - [ ][] - Not Done +//~^ ERROR: link reference defined in list item +pub struct GithubCheckboxes; diff --git a/tests/ui/doc/doc_nested_refdef_list_item.rs b/tests/ui/doc/doc_nested_refdef_list_item.rs index 53368de4616d..c7eab50c8b38 100644 --- a/tests/ui/doc/doc_nested_refdef_list_item.rs +++ b/tests/ui/doc/doc_nested_refdef_list_item.rs @@ -69,3 +69,11 @@ pub struct NotEmpty; /// - [link]\: notdef /// inner text pub struct NotEmptyTight; + +/// ## Heading +/// +/// - [x] - Done +//~^ ERROR: link reference defined in list item +/// - [ ] - Not Done +//~^ ERROR: link reference defined in list item +pub struct GithubCheckboxes; diff --git a/tests/ui/doc/doc_nested_refdef_list_item.stderr b/tests/ui/doc/doc_nested_refdef_list_item.stderr index 27314c7e968d..5a815dabf4d8 100644 --- a/tests/ui/doc/doc_nested_refdef_list_item.stderr +++ b/tests/ui/doc/doc_nested_refdef_list_item.stderr @@ -144,5 +144,29 @@ help: for an intra-doc link, add `[]` between the label and the colon LL | /// - [link][]: def "title" | ++ -error: aborting due to 12 previous errors +error: link reference defined in list item + --> tests/ui/doc/doc_nested_refdef_list_item.rs:75:7 + | +LL | /// - [x] - Done + | ^^^ + | + = help: link definitions are not shown in rendered documentation +help: for an intra-doc link, add `[]` between the label and the colon + | +LL | /// - [x][] - Done + | ++ + +error: link reference defined in list item + --> tests/ui/doc/doc_nested_refdef_list_item.rs:77:7 + | +LL | /// - [ ] - Not Done + | ^^^ + | + = help: link definitions are not shown in rendered documentation +help: for an intra-doc link, add `[]` between the label and the colon + | +LL | /// - [ ][] - Not Done + | ++ + +error: aborting due to 14 previous errors diff --git a/tests/ui/doc/footnote_issue_13183.rs b/tests/ui/doc/footnote_issue_13183.rs index a18b4c3ac539..dbb01bd5155b 100644 --- a/tests/ui/doc/footnote_issue_13183.rs +++ b/tests/ui/doc/footnote_issue_13183.rs @@ -1,3 +1,4 @@ +//@ check-pass // This is a regression test for . // It should not warn on missing backticks on footnote references. diff --git a/tests/ui/doc/issue_12795.fixed b/tests/ui/doc/issue_12795.fixed index ade23bf975c2..4172438a82a6 100644 --- a/tests/ui/doc/issue_12795.fixed +++ b/tests/ui/doc/issue_12795.fixed @@ -1,9 +1,9 @@ #![warn(clippy::doc_markdown)] //! A comment with `a_b(x)` and `a_c` in it and (`a_b((c))` ) too and (maybe `a_b((c))`) -//~^ ERROR: item in documentation is missing backticks -//~| ERROR: item in documentation is missing backticks -//~| ERROR: item in documentation is missing backticks -//~| ERROR: item in documentation is missing backticks +//~^ doc_markdown +//~| doc_markdown +//~| doc_markdown +//~| doc_markdown pub fn main() {} diff --git a/tests/ui/doc/issue_12795.rs b/tests/ui/doc/issue_12795.rs index 6d94a07e3036..dbc03cc70865 100644 --- a/tests/ui/doc/issue_12795.rs +++ b/tests/ui/doc/issue_12795.rs @@ -1,9 +1,9 @@ #![warn(clippy::doc_markdown)] //! A comment with a_b(x) and a_c in it and (a_b((c)) ) too and (maybe a_b((c))) -//~^ ERROR: item in documentation is missing backticks -//~| ERROR: item in documentation is missing backticks -//~| ERROR: item in documentation is missing backticks -//~| ERROR: item in documentation is missing backticks +//~^ doc_markdown +//~| doc_markdown +//~| doc_markdown +//~| doc_markdown pub fn main() {} diff --git a/tests/ui/doc/issue_1832.rs b/tests/ui/doc/issue_1832.rs index 10586f16d466..9678badd11c8 100644 --- a/tests/ui/doc/issue_1832.rs +++ b/tests/ui/doc/issue_1832.rs @@ -1,3 +1,4 @@ +//@ check-pass /// Ok: /// /// Not ok: http://www.unicode.org diff --git a/tests/ui/doc/issue_902.rs b/tests/ui/doc/issue_902.rs index 4b0c835dd3f0..1be6db01dcb2 100644 --- a/tests/ui/doc/issue_902.rs +++ b/tests/ui/doc/issue_902.rs @@ -1,3 +1,4 @@ +//@ check-pass /// See [NIST SP 800-56A, revision 2]. /// /// [NIST SP 800-56A, revision 2]: diff --git a/tests/ui/doc/issue_9473.fixed b/tests/ui/doc/issue_9473.fixed index 276ce7620ca7..2d910c43b263 100644 --- a/tests/ui/doc/issue_9473.fixed +++ b/tests/ui/doc/issue_9473.fixed @@ -6,4 +6,5 @@ pub struct Foo(u32); // Should warn. /// Blah blah blah [FooBar]<[FooBar]>[`FooBar`]. +//~^ doc_markdown pub struct FooBar(u32); diff --git a/tests/ui/doc/issue_9473.rs b/tests/ui/doc/issue_9473.rs index 52527f7106d1..e5798685382a 100644 --- a/tests/ui/doc/issue_9473.rs +++ b/tests/ui/doc/issue_9473.rs @@ -6,4 +6,5 @@ pub struct Foo(u32); // Should warn. /// Blah blah blah [FooBar]<[FooBar]>[FooBar]. +//~^ doc_markdown pub struct FooBar(u32); diff --git a/tests/ui/doc/link_adjacent.fixed b/tests/ui/doc/link_adjacent.fixed new file mode 100644 index 000000000000..0ac297a6b197 --- /dev/null +++ b/tests/ui/doc/link_adjacent.fixed @@ -0,0 +1,52 @@ +#![warn(clippy::doc_link_code)] + +//! Test case for code links that are adjacent to code text. +//! +//! This is not an example: `first``second` +//! +//! Neither is this: [`first`](x) +//! +//! Neither is this: [`first`](x) `second` +//! +//! Neither is this: [first](x)`second` +//! +//! This is: [first](x)second +//~^ ERROR: adjacent +//! +//! So is this first[second](x) +//~^ ERROR: adjacent +//! +//! So is this [first](x)[second](x) +//~^ ERROR: adjacent +//! +//! So is this [first](x)[second](x)[third](x) +//~^ ERROR: adjacent +//! +//! So is this [first](x)second[third](x) +//~^ ERROR: adjacent + +/// Test case for code links that are adjacent to code text. +/// +/// This is not an example: `first``second` arst +/// +/// Neither is this: [`first`](x) arst +/// +/// Neither is this: [`first`](x) `second` arst +/// +/// Neither is this: [first](x)`second` arst +/// +/// This is: [first](x)second arst +//~^ ERROR: adjacent +/// +/// So is this first[second](x) arst +//~^ ERROR: adjacent +/// +/// So is this [first](x)[second](x) arst +//~^ ERROR: adjacent +/// +/// So is this [first](x)[second](x)[third](x) arst +//~^ ERROR: adjacent +/// +/// So is this [first](x)second[third](x) arst +//~^ ERROR: adjacent +pub struct WithTrailing; diff --git a/tests/ui/doc/link_adjacent.rs b/tests/ui/doc/link_adjacent.rs new file mode 100644 index 000000000000..af6755eeff61 --- /dev/null +++ b/tests/ui/doc/link_adjacent.rs @@ -0,0 +1,52 @@ +#![warn(clippy::doc_link_code)] + +//! Test case for code links that are adjacent to code text. +//! +//! This is not an example: `first``second` +//! +//! Neither is this: [`first`](x) +//! +//! Neither is this: [`first`](x) `second` +//! +//! Neither is this: [first](x)`second` +//! +//! This is: [`first`](x)`second` +//~^ ERROR: adjacent +//! +//! So is this `first`[`second`](x) +//~^ ERROR: adjacent +//! +//! So is this [`first`](x)[`second`](x) +//~^ ERROR: adjacent +//! +//! So is this [`first`](x)[`second`](x)[`third`](x) +//~^ ERROR: adjacent +//! +//! So is this [`first`](x)`second`[`third`](x) +//~^ ERROR: adjacent + +/// Test case for code links that are adjacent to code text. +/// +/// This is not an example: `first``second` arst +/// +/// Neither is this: [`first`](x) arst +/// +/// Neither is this: [`first`](x) `second` arst +/// +/// Neither is this: [first](x)`second` arst +/// +/// This is: [`first`](x)`second` arst +//~^ ERROR: adjacent +/// +/// So is this `first`[`second`](x) arst +//~^ ERROR: adjacent +/// +/// So is this [`first`](x)[`second`](x) arst +//~^ ERROR: adjacent +/// +/// So is this [`first`](x)[`second`](x)[`third`](x) arst +//~^ ERROR: adjacent +/// +/// So is this [`first`](x)`second`[`third`](x) arst +//~^ ERROR: adjacent +pub struct WithTrailing; diff --git a/tests/ui/doc/link_adjacent.stderr b/tests/ui/doc/link_adjacent.stderr new file mode 100644 index 000000000000..27e8a73c7083 --- /dev/null +++ b/tests/ui/doc/link_adjacent.stderr @@ -0,0 +1,134 @@ +error: code link adjacent to code text + --> tests/ui/doc/link_adjacent.rs:13:14 + | +LL | //! This is: [`first`](x)`second` + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: separate code snippets will be shown with a gap + = note: `-D clippy::doc-link-code` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::doc_link_code)]` +help: wrap the entire group in `` tags + | +LL - //! This is: [`first`](x)`second` +LL + //! This is: [first](x)second + | + +error: code link adjacent to code text + --> tests/ui/doc/link_adjacent.rs:16:16 + | +LL | //! So is this `first`[`second`](x) + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: separate code snippets will be shown with a gap +help: wrap the entire group in `` tags + | +LL - //! So is this `first`[`second`](x) +LL + //! So is this first[second](x) + | + +error: code link adjacent to code text + --> tests/ui/doc/link_adjacent.rs:19:16 + | +LL | //! So is this [`first`](x)[`second`](x) + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: separate code snippets will be shown with a gap +help: wrap the entire group in `` tags + | +LL - //! So is this [`first`](x)[`second`](x) +LL + //! So is this [first](x)[second](x) + | + +error: code link adjacent to code text + --> tests/ui/doc/link_adjacent.rs:22:16 + | +LL | //! So is this [`first`](x)[`second`](x)[`third`](x) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: separate code snippets will be shown with a gap +help: wrap the entire group in `` tags + | +LL - //! So is this [`first`](x)[`second`](x)[`third`](x) +LL + //! So is this [first](x)[second](x)[third](x) + | + +error: code link adjacent to code text + --> tests/ui/doc/link_adjacent.rs:25:16 + | +LL | //! So is this [`first`](x)`second`[`third`](x) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: separate code snippets will be shown with a gap +help: wrap the entire group in `` tags + | +LL - //! So is this [`first`](x)`second`[`third`](x) +LL + //! So is this [first](x)second[third](x) + | + +error: code link adjacent to code text + --> tests/ui/doc/link_adjacent.rs:38:14 + | +LL | /// This is: [`first`](x)`second` arst + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: separate code snippets will be shown with a gap +help: wrap the entire group in `` tags + | +LL - /// This is: [`first`](x)`second` arst +LL + /// This is: [first](x)second arst + | + +error: code link adjacent to code text + --> tests/ui/doc/link_adjacent.rs:41:16 + | +LL | /// So is this `first`[`second`](x) arst + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: separate code snippets will be shown with a gap +help: wrap the entire group in `` tags + | +LL - /// So is this `first`[`second`](x) arst +LL + /// So is this first[second](x) arst + | + +error: code link adjacent to code text + --> tests/ui/doc/link_adjacent.rs:44:16 + | +LL | /// So is this [`first`](x)[`second`](x) arst + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: separate code snippets will be shown with a gap +help: wrap the entire group in `` tags + | +LL - /// So is this [`first`](x)[`second`](x) arst +LL + /// So is this [first](x)[second](x) arst + | + +error: code link adjacent to code text + --> tests/ui/doc/link_adjacent.rs:47:16 + | +LL | /// So is this [`first`](x)[`second`](x)[`third`](x) arst + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: separate code snippets will be shown with a gap +help: wrap the entire group in `` tags + | +LL - /// So is this [`first`](x)[`second`](x)[`third`](x) arst +LL + /// So is this [first](x)[second](x)[third](x) arst + | + +error: code link adjacent to code text + --> tests/ui/doc/link_adjacent.rs:50:16 + | +LL | /// So is this [`first`](x)`second`[`third`](x) arst + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: separate code snippets will be shown with a gap +help: wrap the entire group in `` tags + | +LL - /// So is this [`first`](x)`second`[`third`](x) arst +LL + /// So is this [first](x)second[third](x) arst + | + +error: aborting due to 10 previous errors + diff --git a/tests/ui/doc/needless_doctest_main.rs b/tests/ui/doc/needless_doctest_main.rs index f1a2c0575ee5..633a435ca5ed 100644 --- a/tests/ui/doc/needless_doctest_main.rs +++ b/tests/ui/doc/needless_doctest_main.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::needless_doctest_main)] //! issue 10491: //! ```rust,no_test diff --git a/tests/ui/doc/unbalanced_ticks.rs b/tests/ui/doc/unbalanced_ticks.rs index a065654e319d..76befb15db80 100644 --- a/tests/ui/doc/unbalanced_ticks.rs +++ b/tests/ui/doc/unbalanced_ticks.rs @@ -5,20 +5,20 @@ #![warn(clippy::doc_markdown)] /// This is a doc comment with `unbalanced_tick marks and several words that -//~^ ERROR: backticks are unbalanced +//~^ doc_markdown /// should be `encompassed_by` tick marks because they `contain_underscores`. /// Because of the initial `unbalanced_tick` pair, the error message is /// very `confusing_and_misleading`. fn main() {} /// This paragraph has `unbalanced_tick marks and should stop_linting. -//~^ ERROR: backticks are unbalanced +//~^ doc_markdown /// /// This paragraph is fine and should_be linted normally. -//~^ ERROR: item in documentation is missing backticks +//~^ doc_markdown /// /// Double unbalanced backtick from ``here to here` should lint. -//~^ ERROR: backticks are unbalanced +//~^ doc_markdown /// /// Double balanced back ticks ``start end`` is fine. fn multiple_paragraphs() {} @@ -32,15 +32,15 @@ fn in_code_block() {} /// # `Fine` /// /// ## not_fine -//~^ ERROR: item in documentation is missing backticks +//~^ doc_markdown /// /// ### `unbalanced -//~^ ERROR: backticks are unbalanced +//~^ doc_markdown /// /// - This `item has unbalanced tick marks -//~^ ERROR: backticks are unbalanced +//~^ doc_markdown /// - This item needs backticks_here -//~^ ERROR: item in documentation is missing backticks +//~^ doc_markdown fn other_markdown() {} #[rustfmt::skip] @@ -51,7 +51,7 @@ fn other_markdown() {} fn issue_7421() {} /// ` -//~^ ERROR: backticks are unbalanced +//~^ doc_markdown fn escape_0() {} /// Escaped \` backticks don't count. @@ -61,7 +61,7 @@ fn escape_1() {} fn escape_2() {} /// Escaped \` ` backticks don't count, but unescaped backticks do. -//~^ ERROR: backticks are unbalanced +//~^ doc_markdown fn escape_3() {} /// Backslashes ` \` within code blocks don't count. @@ -80,5 +80,6 @@ impl Foo for Bar { /// ---------------------------| -------------------- | --------------------- | ... | ----- /// ``: | Some(Month::January) | Some(Month::February) | ... | /// Some(Month::December) + //~^^^^ doc_markdown fn bar() {} } diff --git a/tests/ui/doc_errors.rs b/tests/ui/doc_errors.rs index 9b3783aaf09d..f67e3216c01e 100644 --- a/tests/ui/doc_errors.rs +++ b/tests/ui/doc_errors.rs @@ -5,25 +5,28 @@ use std::io; pub fn pub_fn_missing_errors_header() -> Result<(), ()> { - //~^ ERROR: docs for function returning `Result` missing `# Errors` section - //~| NOTE: `-D clippy::missing-errors-doc` implied by `-D warnings` + //~^ missing_errors_doc + unimplemented!(); } pub async fn async_pub_fn_missing_errors_header() -> Result<(), ()> { - //~^ ERROR: docs for function returning `Result` missing `# Errors` section + //~^ missing_errors_doc + unimplemented!(); } /// This is not sufficiently documented. pub fn pub_fn_returning_io_result() -> io::Result<()> { - //~^ ERROR: docs for function returning `Result` missing `# Errors` section + //~^ missing_errors_doc + unimplemented!(); } /// This is not sufficiently documented. pub async fn async_pub_fn_returning_io_result() -> io::Result<()> { - //~^ ERROR: docs for function returning `Result` missing `# Errors` section + //~^ missing_errors_doc + unimplemented!(); } @@ -54,13 +57,15 @@ pub struct Struct1; impl Struct1 { /// This is not sufficiently documented. pub fn pub_method_missing_errors_header() -> Result<(), ()> { - //~^ ERROR: docs for function returning `Result` missing `# Errors` section + //~^ missing_errors_doc + unimplemented!(); } /// This is not sufficiently documented. pub async fn async_pub_method_missing_errors_header() -> Result<(), ()> { - //~^ ERROR: docs for function returning `Result` missing `# Errors` section + //~^ missing_errors_doc + unimplemented!(); } @@ -111,7 +116,7 @@ impl Struct1 { pub trait Trait1 { /// This is not sufficiently documented. fn trait_method_missing_errors_header() -> Result<(), ()>; - //~^ ERROR: docs for function returning `Result` missing `# Errors` section + //~^ missing_errors_doc /// # Errors /// A description of the errors goes here. diff --git a/tests/ui/doc_errors.stderr b/tests/ui/doc_errors.stderr index c5b9479adace..aeb2516e5123 100644 --- a/tests/ui/doc_errors.stderr +++ b/tests/ui/doc_errors.stderr @@ -14,31 +14,31 @@ LL | pub async fn async_pub_fn_missing_errors_header() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function returning `Result` missing `# Errors` section - --> tests/ui/doc_errors.rs:19:1 + --> tests/ui/doc_errors.rs:20:1 | LL | pub fn pub_fn_returning_io_result() -> io::Result<()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function returning `Result` missing `# Errors` section - --> tests/ui/doc_errors.rs:25:1 + --> tests/ui/doc_errors.rs:27:1 | LL | pub async fn async_pub_fn_returning_io_result() -> io::Result<()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function returning `Result` missing `# Errors` section - --> tests/ui/doc_errors.rs:56:5 + --> tests/ui/doc_errors.rs:59:5 | LL | pub fn pub_method_missing_errors_header() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function returning `Result` missing `# Errors` section - --> tests/ui/doc_errors.rs:62:5 + --> tests/ui/doc_errors.rs:66:5 | LL | pub async fn async_pub_method_missing_errors_header() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function returning `Result` missing `# Errors` section - --> tests/ui/doc_errors.rs:113:5 + --> tests/ui/doc_errors.rs:118:5 | LL | fn trait_method_missing_errors_header() -> Result<(), ()>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/doc_link_with_quotes.rs b/tests/ui/doc_link_with_quotes.rs index 48e1b1819c6f..0c0e273da6db 100644 --- a/tests/ui/doc_link_with_quotes.rs +++ b/tests/ui/doc_link_with_quotes.rs @@ -5,14 +5,13 @@ fn main() { } /// Calls ['bar'] uselessly -//~^ ERROR: possible intra-doc link using quotes instead of backticks -//~| NOTE: `-D clippy::doc-link-with-quotes` implied by `-D warnings` +//~^ doc_link_with_quotes pub fn foo() { bar() } /// Calls ["bar"] uselessly -//~^ ERROR: possible intra-doc link using quotes instead of backticks +//~^ doc_link_with_quotes pub fn foo2() { bar() } diff --git a/tests/ui/doc_link_with_quotes.stderr b/tests/ui/doc_link_with_quotes.stderr index e4be59c65719..47c60390310c 100644 --- a/tests/ui/doc_link_with_quotes.stderr +++ b/tests/ui/doc_link_with_quotes.stderr @@ -8,7 +8,7 @@ LL | /// Calls ['bar'] uselessly = help: to override `-D warnings` add `#[allow(clippy::doc_link_with_quotes)]` error: possible intra-doc link using quotes instead of backticks - --> tests/ui/doc_link_with_quotes.rs:14:12 + --> tests/ui/doc_link_with_quotes.rs:13:12 | LL | /// Calls ["bar"] uselessly | ^^^^^ diff --git a/tests/ui/doc_unsafe.rs b/tests/ui/doc_unsafe.rs index f7f41c915e3f..1bdf01e4e22e 100644 --- a/tests/ui/doc_unsafe.rs +++ b/tests/ui/doc_unsafe.rs @@ -7,6 +7,7 @@ use proc_macros::external; /// This is not sufficiently documented pub unsafe fn destroy_the_planet() { + //~^ missing_safety_doc unimplemented!(); } @@ -30,6 +31,7 @@ mod private_mod { } pub unsafe fn republished() { + //~^ missing_safety_doc unimplemented!(); } } @@ -38,12 +40,14 @@ pub use private_mod::republished; pub trait SafeTraitUnsafeMethods { unsafe fn woefully_underdocumented(self); + //~^ missing_safety_doc /// # Safety unsafe fn at_least_somewhat_documented(self); } pub unsafe trait UnsafeTrait { + //~^ missing_safety_doc fn method(); } @@ -74,6 +78,7 @@ unsafe impl DocumentedUnsafeTrait for Struct { impl Struct { pub unsafe fn more_undocumented_unsafe() -> Self { + //~^ missing_safety_doc unimplemented!(); } @@ -90,6 +95,7 @@ impl Struct { macro_rules! very_unsafe { () => { pub unsafe fn whee() { + //~^ missing_safety_doc unimplemented!() } diff --git a/tests/ui/doc_unsafe.stderr b/tests/ui/doc_unsafe.stderr index 929afbceb879..6e128133d498 100644 --- a/tests/ui/doc_unsafe.stderr +++ b/tests/ui/doc_unsafe.stderr @@ -8,31 +8,31 @@ LL | pub unsafe fn destroy_the_planet() { = help: to override `-D warnings` add `#[allow(clippy::missing_safety_doc)]` error: unsafe function's docs are missing a `# Safety` section - --> tests/ui/doc_unsafe.rs:32:5 + --> tests/ui/doc_unsafe.rs:33:5 | LL | pub unsafe fn republished() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe function's docs are missing a `# Safety` section - --> tests/ui/doc_unsafe.rs:40:5 + --> tests/ui/doc_unsafe.rs:42:5 | LL | unsafe fn woefully_underdocumented(self); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for unsafe trait missing `# Safety` section - --> tests/ui/doc_unsafe.rs:46:1 + --> tests/ui/doc_unsafe.rs:49:1 | LL | pub unsafe trait UnsafeTrait { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe function's docs are missing a `# Safety` section - --> tests/ui/doc_unsafe.rs:76:5 + --> tests/ui/doc_unsafe.rs:80:5 | LL | pub unsafe fn more_undocumented_unsafe() -> Self { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe function's docs are missing a `# Safety` section - --> tests/ui/doc_unsafe.rs:92:9 + --> tests/ui/doc_unsafe.rs:97:9 | LL | pub unsafe fn whee() { | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/double_comparison.fixed b/tests/ui/double_comparison.fixed index 788f3224b418..685e3319bf9a 100644 --- a/tests/ui/double_comparison.fixed +++ b/tests/ui/double_comparison.fixed @@ -4,27 +4,35 @@ fn main() { let x = 1; let y = 2; if x <= y { + //~^ double_comparisons // do something } if x <= y { + //~^ double_comparisons // do something } if x >= y { + //~^ double_comparisons // do something } if x >= y { + //~^ double_comparisons // do something } if x != y { + //~^ double_comparisons // do something } if x != y { + //~^ double_comparisons // do something } if x == y { + //~^ double_comparisons // do something } if x == y { + //~^ double_comparisons // do something } } diff --git a/tests/ui/double_comparison.rs b/tests/ui/double_comparison.rs index 245a83d5709d..3670a050e88d 100644 --- a/tests/ui/double_comparison.rs +++ b/tests/ui/double_comparison.rs @@ -4,27 +4,35 @@ fn main() { let x = 1; let y = 2; if x == y || x < y { + //~^ double_comparisons // do something } if x < y || x == y { + //~^ double_comparisons // do something } if x == y || x > y { + //~^ double_comparisons // do something } if x > y || x == y { + //~^ double_comparisons // do something } if x < y || x > y { + //~^ double_comparisons // do something } if x > y || x < y { + //~^ double_comparisons // do something } if x <= y && x >= y { + //~^ double_comparisons // do something } if x >= y && x <= y { + //~^ double_comparisons // do something } } diff --git a/tests/ui/double_comparison.stderr b/tests/ui/double_comparison.stderr index 01ba7a8ee108..984614c203eb 100644 --- a/tests/ui/double_comparison.stderr +++ b/tests/ui/double_comparison.stderr @@ -8,43 +8,43 @@ LL | if x == y || x < y { = help: to override `-D warnings` add `#[allow(clippy::double_comparisons)]` error: this binary expression can be simplified - --> tests/ui/double_comparison.rs:9:8 + --> tests/ui/double_comparison.rs:10:8 | LL | if x < y || x == y { | ^^^^^^^^^^^^^^^ help: try: `x <= y` error: this binary expression can be simplified - --> tests/ui/double_comparison.rs:12:8 + --> tests/ui/double_comparison.rs:14:8 | LL | if x == y || x > y { | ^^^^^^^^^^^^^^^ help: try: `x >= y` error: this binary expression can be simplified - --> tests/ui/double_comparison.rs:15:8 + --> tests/ui/double_comparison.rs:18:8 | LL | if x > y || x == y { | ^^^^^^^^^^^^^^^ help: try: `x >= y` error: this binary expression can be simplified - --> tests/ui/double_comparison.rs:18:8 + --> tests/ui/double_comparison.rs:22:8 | LL | if x < y || x > y { | ^^^^^^^^^^^^^^ help: try: `x != y` error: this binary expression can be simplified - --> tests/ui/double_comparison.rs:21:8 + --> tests/ui/double_comparison.rs:26:8 | LL | if x > y || x < y { | ^^^^^^^^^^^^^^ help: try: `x != y` error: this binary expression can be simplified - --> tests/ui/double_comparison.rs:24:8 + --> tests/ui/double_comparison.rs:30:8 | LL | if x <= y && x >= y { | ^^^^^^^^^^^^^^^^ help: try: `x == y` error: this binary expression can be simplified - --> tests/ui/double_comparison.rs:27:8 + --> tests/ui/double_comparison.rs:34:8 | LL | if x >= y && x <= y { | ^^^^^^^^^^^^^^^^ help: try: `x == y` diff --git a/tests/ui/double_ended_iterator_last.fixed b/tests/ui/double_ended_iterator_last.fixed index 06c48e337537..17d0d71a8854 100644 --- a/tests/ui/double_ended_iterator_last.fixed +++ b/tests/ui/double_ended_iterator_last.fixed @@ -2,7 +2,7 @@ // Typical case pub fn last_arg(s: &str) -> Option<&str> { - s.split(' ').next_back() + s.split(' ').next_back() //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator` } fn main() { @@ -19,7 +19,7 @@ fn main() { Some(()) } } - let _ = DeIterator.next_back(); + let _ = DeIterator.next_back(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator` // Should not apply to other methods of Iterator let _ = DeIterator.count(); @@ -51,3 +51,42 @@ fn main() { } let _ = CustomLast.last(); } + +fn issue_14139() { + let mut index = [true, true, false, false, false, true].iter(); + let mut subindex = index.by_ref().take(3); + let _ = subindex.next_back(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator` + + let mut index = [true, true, false, false, false, true].iter(); + let mut subindex = index.by_ref().take(3); + let _ = subindex.next_back(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator` + + let mut index = [true, true, false, false, false, true].iter(); + let mut subindex = index.by_ref().take(3); + let subindex = &mut subindex; + let _ = subindex.next_back(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator` + + let mut index = [true, true, false, false, false, true].iter(); + let mut subindex = index.by_ref().take(3); + let subindex = &mut subindex; + let _ = subindex.next_back(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator` + + let mut index = [true, true, false, false, false, true].iter(); + let (mut subindex, _) = (index.by_ref().take(3), 42); + let _ = subindex.next_back(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator` +} + +fn drop_order() { + struct S(&'static str); + impl std::ops::Drop for S { + fn drop(&mut self) { + println!("Dropping {}", self.0); + } + } + + let v = vec![S("one"), S("two"), S("three")]; + let mut v = v.into_iter(); + println!("Last element is {}", v.next_back().unwrap().0); + //~^ ERROR: called `Iterator::last` on a `DoubleEndedIterator` + println!("Done"); +} diff --git a/tests/ui/double_ended_iterator_last.rs b/tests/ui/double_ended_iterator_last.rs index 9c13b496d117..41bc669b1719 100644 --- a/tests/ui/double_ended_iterator_last.rs +++ b/tests/ui/double_ended_iterator_last.rs @@ -2,7 +2,7 @@ // Typical case pub fn last_arg(s: &str) -> Option<&str> { - s.split(' ').last() + s.split(' ').last() //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator` } fn main() { @@ -19,7 +19,7 @@ fn main() { Some(()) } } - let _ = DeIterator.last(); + let _ = DeIterator.last(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator` // Should not apply to other methods of Iterator let _ = DeIterator.count(); @@ -51,3 +51,42 @@ fn main() { } let _ = CustomLast.last(); } + +fn issue_14139() { + let mut index = [true, true, false, false, false, true].iter(); + let subindex = index.by_ref().take(3); + let _ = subindex.last(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator` + + let mut index = [true, true, false, false, false, true].iter(); + let mut subindex = index.by_ref().take(3); + let _ = subindex.last(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator` + + let mut index = [true, true, false, false, false, true].iter(); + let mut subindex = index.by_ref().take(3); + let subindex = &mut subindex; + let _ = subindex.last(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator` + + let mut index = [true, true, false, false, false, true].iter(); + let mut subindex = index.by_ref().take(3); + let subindex = &mut subindex; + let _ = subindex.last(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator` + + let mut index = [true, true, false, false, false, true].iter(); + let (subindex, _) = (index.by_ref().take(3), 42); + let _ = subindex.last(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator` +} + +fn drop_order() { + struct S(&'static str); + impl std::ops::Drop for S { + fn drop(&mut self) { + println!("Dropping {}", self.0); + } + } + + let v = vec![S("one"), S("two"), S("three")]; + let v = v.into_iter(); + println!("Last element is {}", v.last().unwrap().0); + //~^ ERROR: called `Iterator::last` on a `DoubleEndedIterator` + println!("Done"); +} diff --git a/tests/ui/double_ended_iterator_last.stderr b/tests/ui/double_ended_iterator_last.stderr index b795c18a736e..1702a24d7a05 100644 --- a/tests/ui/double_ended_iterator_last.stderr +++ b/tests/ui/double_ended_iterator_last.stderr @@ -1,17 +1,82 @@ error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator - --> tests/ui/double_ended_iterator_last.rs:5:18 + --> tests/ui/double_ended_iterator_last.rs:5:5 | LL | s.split(' ').last() - | ^^^^^^ help: try: `next_back()` + | ^^^^^^^^^^^^^------ + | | + | help: try: `next_back()` | = note: `-D clippy::double-ended-iterator-last` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::double_ended_iterator_last)]` error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator - --> tests/ui/double_ended_iterator_last.rs:22:24 + --> tests/ui/double_ended_iterator_last.rs:22:13 | LL | let _ = DeIterator.last(); - | ^^^^^^ help: try: `next_back()` + | ^^^^^^^^^^^------ + | | + | help: try: `next_back()` -error: aborting due to 2 previous errors +error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator + --> tests/ui/double_ended_iterator_last.rs:58:13 + | +LL | let _ = subindex.last(); + | ^^^^^^^^^^^^^^^ + | +help: try + | +LL ~ let mut subindex = index.by_ref().take(3); +LL ~ let _ = subindex.next_back(); + | + +error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator + --> tests/ui/double_ended_iterator_last.rs:62:13 + | +LL | let _ = subindex.last(); + | ^^^^^^^^^------ + | | + | help: try: `next_back()` + +error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator + --> tests/ui/double_ended_iterator_last.rs:67:13 + | +LL | let _ = subindex.last(); + | ^^^^^^^^^------ + | | + | help: try: `next_back()` + +error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator + --> tests/ui/double_ended_iterator_last.rs:72:13 + | +LL | let _ = subindex.last(); + | ^^^^^^^^^------ + | | + | help: try: `next_back()` + +error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator + --> tests/ui/double_ended_iterator_last.rs:76:13 + | +LL | let _ = subindex.last(); + | ^^^^^^^^^^^^^^^ + | +help: try + | +LL ~ let (mut subindex, _) = (index.by_ref().take(3), 42); +LL ~ let _ = subindex.next_back(); + | + +error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator + --> tests/ui/double_ended_iterator_last.rs:89:36 + | +LL | println!("Last element is {}", v.last().unwrap().0); + | ^^^^^^^^ + | + = note: this change will alter drop order which may be undesirable +help: try + | +LL ~ let mut v = v.into_iter(); +LL ~ println!("Last element is {}", v.next_back().unwrap().0); + | + +error: aborting due to 8 previous errors diff --git a/tests/ui/double_ended_iterator_last_unfixable.rs b/tests/ui/double_ended_iterator_last_unfixable.rs new file mode 100644 index 000000000000..3f125c7f20c1 --- /dev/null +++ b/tests/ui/double_ended_iterator_last_unfixable.rs @@ -0,0 +1,23 @@ +//@no-rustfix +#![warn(clippy::double_ended_iterator_last)] + +fn main() { + let mut index = [true, true, false, false, false, true].iter(); + let subindex = (index.by_ref().take(3), 42); + let _ = subindex.0.last(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator` +} + +fn drop_order() { + struct S(&'static str); + impl std::ops::Drop for S { + fn drop(&mut self) { + println!("Dropping {}", self.0); + } + } + + let v = vec![S("one"), S("two"), S("three")]; + let v = (v.into_iter(), 42); + println!("Last element is {}", v.0.last().unwrap().0); + //~^ ERROR: called `Iterator::last` on a `DoubleEndedIterator` + println!("Done"); +} diff --git a/tests/ui/double_ended_iterator_last_unfixable.stderr b/tests/ui/double_ended_iterator_last_unfixable.stderr new file mode 100644 index 000000000000..f4be757d00d2 --- /dev/null +++ b/tests/ui/double_ended_iterator_last_unfixable.stderr @@ -0,0 +1,33 @@ +error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator + --> tests/ui/double_ended_iterator_last_unfixable.rs:7:13 + | +LL | let _ = subindex.0.last(); + | ^^^^^^^^^^^------ + | | + | help: try: `next_back()` + | +note: this must be made mutable to use `.next_back()` + --> tests/ui/double_ended_iterator_last_unfixable.rs:7:13 + | +LL | let _ = subindex.0.last(); + | ^^^^^^^^^^ + = note: `-D clippy::double-ended-iterator-last` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::double_ended_iterator_last)]` + +error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator + --> tests/ui/double_ended_iterator_last_unfixable.rs:20:36 + | +LL | println!("Last element is {}", v.0.last().unwrap().0); + | ^^^^------ + | | + | help: try: `next_back()` + | + = note: this change will alter drop order which may be undesirable +note: this must be made mutable to use `.next_back()` + --> tests/ui/double_ended_iterator_last_unfixable.rs:20:36 + | +LL | println!("Last element is {}", v.0.last().unwrap().0); + | ^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/double_must_use.rs b/tests/ui/double_must_use.rs index 4460aeb075bf..3d4aaa9baa49 100644 --- a/tests/ui/double_must_use.rs +++ b/tests/ui/double_must_use.rs @@ -3,19 +3,22 @@ #[must_use] pub fn must_use_result() -> Result<(), ()> { - //~^ ERROR: this function has a `#[must_use]` attribute with no message, but returns a type already + //~^ double_must_use + unimplemented!(); } #[must_use] pub fn must_use_tuple() -> (Result<(), ()>, u8) { - //~^ ERROR: this function has a `#[must_use]` attribute with no message, but returns a type already + //~^ double_must_use + unimplemented!(); } #[must_use] pub fn must_use_array() -> [Result<(), ()>; 1] { - //~^ ERROR: this function has a `#[must_use]` attribute with no message, but returns a type already + //~^ double_must_use + unimplemented!(); } @@ -32,7 +35,8 @@ async fn async_must_use() -> usize { #[must_use] async fn async_must_use_result() -> Result<(), ()> { - //~^ ERROR: this function has a `#[must_use]` attribute with no message, but returns a type already + //~^ double_must_use + Ok(()) } diff --git a/tests/ui/double_must_use.stderr b/tests/ui/double_must_use.stderr index b26d1e48a8b8..555dd8902cac 100644 --- a/tests/ui/double_must_use.stderr +++ b/tests/ui/double_must_use.stderr @@ -9,7 +9,7 @@ LL | pub fn must_use_result() -> Result<(), ()> { = help: to override `-D warnings` add `#[allow(clippy::double_must_use)]` error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]` - --> tests/ui/double_must_use.rs:11:1 + --> tests/ui/double_must_use.rs:12:1 | LL | pub fn must_use_tuple() -> (Result<(), ()>, u8) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | pub fn must_use_tuple() -> (Result<(), ()>, u8) { = help: either add some descriptive message or remove the attribute error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]` - --> tests/ui/double_must_use.rs:17:1 + --> tests/ui/double_must_use.rs:19:1 | LL | pub fn must_use_array() -> [Result<(), ()>; 1] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | pub fn must_use_array() -> [Result<(), ()>; 1] { = help: either add some descriptive message or remove the attribute error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]` - --> tests/ui/double_must_use.rs:34:1 + --> tests/ui/double_must_use.rs:37:1 | LL | async fn async_must_use_result() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/double_parens.rs b/tests/ui/double_parens.rs index ab1459eed48b..7c976015b4e7 100644 --- a/tests/ui/double_parens.rs +++ b/tests/ui/double_parens.rs @@ -13,28 +13,33 @@ impl DummyStruct { fn simple_double_parens() -> i32 { ((0)) - //~^ ERROR: consider removing unnecessary double parentheses - //~| NOTE: `-D clippy::double-parens` implied by `-D warnings` + //~^ double_parens + + } fn fn_double_parens() { dummy_fn((0)); - //~^ ERROR: consider removing unnecessary double parentheses + //~^ double_parens + } fn method_double_parens(x: DummyStruct) { x.dummy_method((0)); - //~^ ERROR: consider removing unnecessary double parentheses + //~^ double_parens + } fn tuple_double_parens() -> (i32, i32) { ((1, 2)) - //~^ ERROR: consider removing unnecessary double parentheses + //~^ double_parens + } fn unit_double_parens() { (()) - //~^ ERROR: consider removing unnecessary double parentheses + //~^ double_parens + } fn fn_tuple_ok() { @@ -57,7 +62,8 @@ fn method_unit_ok(x: DummyStruct) { fn inside_macro() { assert_eq!((1, 2), (1, 2), "Error"); assert_eq!(((1, 2)), (1, 2), "Error"); - //~^ ERROR: consider removing unnecessary double parentheses + //~^ double_parens + } fn main() {} diff --git a/tests/ui/double_parens.stderr b/tests/ui/double_parens.stderr index aba301e9f072..e119f54949b1 100644 --- a/tests/ui/double_parens.stderr +++ b/tests/ui/double_parens.stderr @@ -8,31 +8,31 @@ LL | ((0)) = help: to override `-D warnings` add `#[allow(clippy::double_parens)]` error: consider removing unnecessary double parentheses - --> tests/ui/double_parens.rs:21:14 + --> tests/ui/double_parens.rs:22:14 | LL | dummy_fn((0)); | ^^^ error: consider removing unnecessary double parentheses - --> tests/ui/double_parens.rs:26:20 + --> tests/ui/double_parens.rs:28:20 | LL | x.dummy_method((0)); | ^^^ error: consider removing unnecessary double parentheses - --> tests/ui/double_parens.rs:31:5 + --> tests/ui/double_parens.rs:34:5 | LL | ((1, 2)) | ^^^^^^^^ error: consider removing unnecessary double parentheses - --> tests/ui/double_parens.rs:36:5 + --> tests/ui/double_parens.rs:40:5 | LL | (()) | ^^^^ error: consider removing unnecessary double parentheses - --> tests/ui/double_parens.rs:59:16 + --> tests/ui/double_parens.rs:64:16 | LL | assert_eq!(((1, 2)), (1, 2), "Error"); | ^^^^^^^^ diff --git a/tests/ui/drain_collect.fixed b/tests/ui/drain_collect.fixed index 6f597243fe6f..7ae971d975b1 100644 --- a/tests/ui/drain_collect.fixed +++ b/tests/ui/drain_collect.fixed @@ -5,6 +5,7 @@ use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque}; fn binaryheap(b: &mut BinaryHeap) -> BinaryHeap { std::mem::take(b) + //~^ drain_collect } fn binaryheap_dont_lint(b: &mut BinaryHeap) -> HashSet { @@ -13,6 +14,7 @@ fn binaryheap_dont_lint(b: &mut BinaryHeap) -> HashSet { fn hashmap(b: &mut HashMap) -> HashMap { std::mem::take(b) + //~^ drain_collect } fn hashmap_dont_lint(b: &mut HashMap) -> Vec<(i32, i32)> { @@ -21,6 +23,7 @@ fn hashmap_dont_lint(b: &mut HashMap) -> Vec<(i32, i32)> { fn hashset(b: &mut HashSet) -> HashSet { std::mem::take(b) + //~^ drain_collect } fn hashset_dont_lint(b: &mut HashSet) -> Vec { @@ -29,6 +32,7 @@ fn hashset_dont_lint(b: &mut HashSet) -> Vec { fn vecdeque(b: &mut VecDeque) -> VecDeque { std::mem::take(b) + //~^ drain_collect } fn vecdeque_dont_lint(b: &mut VecDeque) -> HashSet { @@ -37,23 +41,28 @@ fn vecdeque_dont_lint(b: &mut VecDeque) -> HashSet { fn vec(b: &mut Vec) -> Vec { std::mem::take(b) + //~^ drain_collect } fn vec2(b: &mut Vec) -> Vec { std::mem::take(b) + //~^ drain_collect } fn vec3(b: &mut Vec) -> Vec { std::mem::take(b) + //~^ drain_collect } fn vec4(b: &mut Vec) -> Vec { std::mem::take(b) + //~^ drain_collect } fn vec_no_reborrow() -> Vec { let mut b = vec![1, 2, 3]; std::mem::take(&mut b) + //~^ drain_collect } fn vec_dont_lint(b: &mut Vec) -> HashSet { @@ -62,6 +71,7 @@ fn vec_dont_lint(b: &mut Vec) -> HashSet { fn string(b: &mut String) -> String { std::mem::take(b) + //~^ drain_collect } fn string_dont_lint(b: &mut String) -> HashSet { diff --git a/tests/ui/drain_collect.rs b/tests/ui/drain_collect.rs index 353aac4da9a4..e99d84fa8b66 100644 --- a/tests/ui/drain_collect.rs +++ b/tests/ui/drain_collect.rs @@ -5,6 +5,7 @@ use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque}; fn binaryheap(b: &mut BinaryHeap) -> BinaryHeap { b.drain().collect() + //~^ drain_collect } fn binaryheap_dont_lint(b: &mut BinaryHeap) -> HashSet { @@ -13,6 +14,7 @@ fn binaryheap_dont_lint(b: &mut BinaryHeap) -> HashSet { fn hashmap(b: &mut HashMap) -> HashMap { b.drain().collect() + //~^ drain_collect } fn hashmap_dont_lint(b: &mut HashMap) -> Vec<(i32, i32)> { @@ -21,6 +23,7 @@ fn hashmap_dont_lint(b: &mut HashMap) -> Vec<(i32, i32)> { fn hashset(b: &mut HashSet) -> HashSet { b.drain().collect() + //~^ drain_collect } fn hashset_dont_lint(b: &mut HashSet) -> Vec { @@ -29,6 +32,7 @@ fn hashset_dont_lint(b: &mut HashSet) -> Vec { fn vecdeque(b: &mut VecDeque) -> VecDeque { b.drain(..).collect() + //~^ drain_collect } fn vecdeque_dont_lint(b: &mut VecDeque) -> HashSet { @@ -37,23 +41,28 @@ fn vecdeque_dont_lint(b: &mut VecDeque) -> HashSet { fn vec(b: &mut Vec) -> Vec { b.drain(..).collect() + //~^ drain_collect } fn vec2(b: &mut Vec) -> Vec { b.drain(0..).collect() + //~^ drain_collect } fn vec3(b: &mut Vec) -> Vec { b.drain(..b.len()).collect() + //~^ drain_collect } fn vec4(b: &mut Vec) -> Vec { b.drain(0..b.len()).collect() + //~^ drain_collect } fn vec_no_reborrow() -> Vec { let mut b = vec![1, 2, 3]; b.drain(..).collect() + //~^ drain_collect } fn vec_dont_lint(b: &mut Vec) -> HashSet { @@ -62,6 +71,7 @@ fn vec_dont_lint(b: &mut Vec) -> HashSet { fn string(b: &mut String) -> String { b.drain(..).collect() + //~^ drain_collect } fn string_dont_lint(b: &mut String) -> HashSet { diff --git a/tests/ui/drain_collect.stderr b/tests/ui/drain_collect.stderr index 1dfd0f1e3463..cfb1e01b65cf 100644 --- a/tests/ui/drain_collect.stderr +++ b/tests/ui/drain_collect.stderr @@ -11,25 +11,19 @@ LL | #![deny(clippy::drain_collect)] | ^^^^^^^^^^^^^^^^^^^^^ error: you seem to be trying to move all elements into a new `HashMap` - --> tests/ui/drain_collect.rs:15:5 + --> tests/ui/drain_collect.rs:16:5 | LL | b.drain().collect() | ^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` error: you seem to be trying to move all elements into a new `HashSet` - --> tests/ui/drain_collect.rs:23:5 + --> tests/ui/drain_collect.rs:25:5 | LL | b.drain().collect() | ^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` error: you seem to be trying to move all elements into a new `Vec` - --> tests/ui/drain_collect.rs:31:5 - | -LL | b.drain(..).collect() - | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` - -error: you seem to be trying to move all elements into a new `Vec` - --> tests/ui/drain_collect.rs:39:5 + --> tests/ui/drain_collect.rs:34:5 | LL | b.drain(..).collect() | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` @@ -37,29 +31,35 @@ LL | b.drain(..).collect() error: you seem to be trying to move all elements into a new `Vec` --> tests/ui/drain_collect.rs:43:5 | +LL | b.drain(..).collect() + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` + +error: you seem to be trying to move all elements into a new `Vec` + --> tests/ui/drain_collect.rs:48:5 + | LL | b.drain(0..).collect() | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` error: you seem to be trying to move all elements into a new `Vec` - --> tests/ui/drain_collect.rs:47:5 + --> tests/ui/drain_collect.rs:53:5 | LL | b.drain(..b.len()).collect() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` error: you seem to be trying to move all elements into a new `Vec` - --> tests/ui/drain_collect.rs:51:5 + --> tests/ui/drain_collect.rs:58:5 | LL | b.drain(0..b.len()).collect() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` error: you seem to be trying to move all elements into a new `Vec` - --> tests/ui/drain_collect.rs:56:5 + --> tests/ui/drain_collect.rs:64:5 | LL | b.drain(..).collect() | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(&mut b)` error: you seem to be trying to move all elements into a new `String` - --> tests/ui/drain_collect.rs:64:5 + --> tests/ui/drain_collect.rs:73:5 | LL | b.drain(..).collect() | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)` diff --git a/tests/ui/drain_collect_nostd.fixed b/tests/ui/drain_collect_nostd.fixed index a4ab2956f2a6..4741922d1dc4 100644 --- a/tests/ui/drain_collect_nostd.fixed +++ b/tests/ui/drain_collect_nostd.fixed @@ -5,4 +5,5 @@ use alloc::vec::Vec; fn remove_all(v: &mut Vec) -> Vec { core::mem::take(v) + //~^ drain_collect } diff --git a/tests/ui/drain_collect_nostd.rs b/tests/ui/drain_collect_nostd.rs index a8be1ce6bbd3..69dcb1c41658 100644 --- a/tests/ui/drain_collect_nostd.rs +++ b/tests/ui/drain_collect_nostd.rs @@ -5,4 +5,5 @@ use alloc::vec::Vec; fn remove_all(v: &mut Vec) -> Vec { v.drain(..).collect() + //~^ drain_collect } diff --git a/tests/ui/drop_non_drop.rs b/tests/ui/drop_non_drop.rs index 6dbcb7777d49..0345e8670ab8 100644 --- a/tests/ui/drop_non_drop.rs +++ b/tests/ui/drop_non_drop.rs @@ -20,7 +20,8 @@ fn main() { struct Foo; // Lint drop(Foo); - //~^ ERROR: call to `std::mem::drop` with a value that does not implement `Drop`. Drop + //~^ drop_non_drop + // Don't lint drop(make_result(Foo)); // Don't lint @@ -36,7 +37,8 @@ fn main() { struct Baz(T); // Lint drop(Baz(Foo)); - //~^ ERROR: call to `std::mem::drop` with a value that does not implement `Drop`. Drop + //~^ drop_non_drop + // Don't lint drop(Baz(Bar)); } diff --git a/tests/ui/drop_non_drop.stderr b/tests/ui/drop_non_drop.stderr index fac89bf1f26a..b431c62c92c5 100644 --- a/tests/ui/drop_non_drop.stderr +++ b/tests/ui/drop_non_drop.stderr @@ -13,13 +13,13 @@ LL | drop(Foo); = help: to override `-D warnings` add `#[allow(clippy::drop_non_drop)]` error: call to `std::mem::drop` with a value that does not implement `Drop`. Dropping such a type only extends its contained lifetimes - --> tests/ui/drop_non_drop.rs:38:5 + --> tests/ui/drop_non_drop.rs:39:5 | LL | drop(Baz(Foo)); | ^^^^^^^^^^^^^^ | note: argument has type `main::Baz` - --> tests/ui/drop_non_drop.rs:38:10 + --> tests/ui/drop_non_drop.rs:39:10 | LL | drop(Baz(Foo)); | ^^^^^^^^ diff --git a/tests/ui/duplicate_underscore_argument.rs b/tests/ui/duplicate_underscore_argument.rs index a725538436cb..b71f5a20a843 100644 --- a/tests/ui/duplicate_underscore_argument.rs +++ b/tests/ui/duplicate_underscore_argument.rs @@ -1,8 +1,8 @@ #![warn(clippy::duplicate_underscore_argument)] fn join_the_dark_side(darth: i32, _darth: i32) {} -//~^ ERROR: `darth` already exists, having another argument having almost the same name ma -//~| NOTE: `-D clippy::duplicate-underscore-argument` implied by `-D warnings` +//~^ duplicate_underscore_argument + fn join_the_light_side(knight: i32, _master: i32) {} // the Force is strong with this one fn main() { diff --git a/tests/ui/duration_subsec.fixed b/tests/ui/duration_subsec.fixed index 114c516ed1a1..a8c2f78ca383 100644 --- a/tests/ui/duration_subsec.fixed +++ b/tests/ui/duration_subsec.fixed @@ -7,21 +7,26 @@ fn main() { let dur = Duration::new(5, 0); let bad_millis_1 = dur.subsec_millis(); + //~^ duration_subsec let bad_millis_2 = dur.subsec_millis(); + //~^ duration_subsec let good_millis = dur.subsec_millis(); assert_eq!(bad_millis_1, good_millis); assert_eq!(bad_millis_2, good_millis); let bad_micros = dur.subsec_micros(); + //~^ duration_subsec let good_micros = dur.subsec_micros(); assert_eq!(bad_micros, good_micros); // Handle refs let _ = (&dur).subsec_micros(); + //~^ duration_subsec // Handle constants const NANOS_IN_MICRO: u32 = 1_000; let _ = dur.subsec_micros(); + //~^ duration_subsec // Other literals aren't linted let _ = dur.subsec_nanos() / 699; diff --git a/tests/ui/duration_subsec.rs b/tests/ui/duration_subsec.rs index 8469fe086b10..582f4717de27 100644 --- a/tests/ui/duration_subsec.rs +++ b/tests/ui/duration_subsec.rs @@ -7,21 +7,26 @@ fn main() { let dur = Duration::new(5, 0); let bad_millis_1 = dur.subsec_micros() / 1_000; + //~^ duration_subsec let bad_millis_2 = dur.subsec_nanos() / 1_000_000; + //~^ duration_subsec let good_millis = dur.subsec_millis(); assert_eq!(bad_millis_1, good_millis); assert_eq!(bad_millis_2, good_millis); let bad_micros = dur.subsec_nanos() / 1_000; + //~^ duration_subsec let good_micros = dur.subsec_micros(); assert_eq!(bad_micros, good_micros); // Handle refs let _ = (&dur).subsec_nanos() / 1_000; + //~^ duration_subsec // Handle constants const NANOS_IN_MICRO: u32 = 1_000; let _ = dur.subsec_nanos() / NANOS_IN_MICRO; + //~^ duration_subsec // Other literals aren't linted let _ = dur.subsec_nanos() / 699; diff --git a/tests/ui/duration_subsec.stderr b/tests/ui/duration_subsec.stderr index 55e44f149cf1..1a41742e1fa6 100644 --- a/tests/ui/duration_subsec.stderr +++ b/tests/ui/duration_subsec.stderr @@ -8,25 +8,25 @@ LL | let bad_millis_1 = dur.subsec_micros() / 1_000; = help: to override `-D warnings` add `#[allow(clippy::duration_subsec)]` error: calling `subsec_millis()` is more concise than this calculation - --> tests/ui/duration_subsec.rs:10:24 + --> tests/ui/duration_subsec.rs:11:24 | LL | let bad_millis_2 = dur.subsec_nanos() / 1_000_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_millis()` error: calling `subsec_micros()` is more concise than this calculation - --> tests/ui/duration_subsec.rs:15:22 + --> tests/ui/duration_subsec.rs:17:22 | LL | let bad_micros = dur.subsec_nanos() / 1_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_micros()` error: calling `subsec_micros()` is more concise than this calculation - --> tests/ui/duration_subsec.rs:20:13 + --> tests/ui/duration_subsec.rs:23:13 | LL | let _ = (&dur).subsec_nanos() / 1_000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(&dur).subsec_micros()` error: calling `subsec_micros()` is more concise than this calculation - --> tests/ui/duration_subsec.rs:24:13 + --> tests/ui/duration_subsec.rs:28:13 | LL | let _ = dur.subsec_nanos() / NANOS_IN_MICRO; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `dur.subsec_micros()` diff --git a/tests/ui/eager_transmute.fixed b/tests/ui/eager_transmute.fixed index ba4342462dca..14cbb6113e62 100644 --- a/tests/ui/eager_transmute.fixed +++ b/tests/ui/eager_transmute.fixed @@ -19,20 +19,27 @@ struct Data { fn int_to_opcode(op: u8) -> Option { (op < 4).then(|| unsafe { std::mem::transmute(op) }) + //~^ eager_transmute } fn f(op: u8, op2: Data, unrelated: u8) { true.then_some(unsafe { std::mem::transmute::<_, Opcode>(op) }); (unrelated < 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) }); (op < 4).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) }); + //~^ eager_transmute (op > 4).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) }); + //~^ eager_transmute (op == 0).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) }); + //~^ eager_transmute let _: Option = (op > 0 && op < 10).then(|| unsafe { std::mem::transmute(op) }); + //~^ eager_transmute let _: Option = (op > 0 && op < 10 && unrelated == 0).then(|| unsafe { std::mem::transmute(op) }); + //~^ eager_transmute // lint even when the transmutable goes through field/array accesses let _: Option = (op2.foo[0] > 0 && op2.foo[0] < 10).then(|| unsafe { std::mem::transmute(op2.foo[0]) }); + //~^ eager_transmute // don't lint: wrong index used in the transmute let _: Option = (op2.foo[0] > 0 && op2.foo[0] < 10).then_some(unsafe { std::mem::transmute(op2.foo[1]) }); @@ -45,11 +52,17 @@ fn f(op: u8, op2: Data, unrelated: u8) { // range contains checks let _: Option = (1..=3).contains(&op).then(|| unsafe { std::mem::transmute(op) }); + //~^ eager_transmute let _: Option = ((1..=3).contains(&op) || op == 4).then(|| unsafe { std::mem::transmute(op) }); + //~^ eager_transmute let _: Option = (1..3).contains(&op).then(|| unsafe { std::mem::transmute(op) }); + //~^ eager_transmute let _: Option = (1..).contains(&op).then(|| unsafe { std::mem::transmute(op) }); + //~^ eager_transmute let _: Option = (..3).contains(&op).then(|| unsafe { std::mem::transmute(op) }); + //~^ eager_transmute let _: Option = (..=3).contains(&op).then(|| unsafe { std::mem::transmute(op) }); + //~^ eager_transmute // unrelated binding in contains let _: Option = (1..=3) @@ -59,6 +72,7 @@ fn f(op: u8, op2: Data, unrelated: u8) { unsafe fn f2(op: u8) { (op < 4).then(|| std::mem::transmute::<_, Opcode>(op)); + //~^ eager_transmute } #[rustc_layout_scalar_valid_range_end(254)] @@ -88,18 +102,21 @@ impls!(NonMaxU8, NonZeroNonMaxU8); fn niche_tests(v1: u8, v2: NonZero, v3: NonZeroNonMaxU8) { // u8 -> NonZero, do lint let _: Option> = (v1 > 0).then(|| unsafe { std::mem::transmute(v1) }); + //~^ eager_transmute // NonZero -> u8, don't lint, target type has no niche and therefore a higher validity range let _: Option = (v2 > NonZero::new(1u8).unwrap()).then_some(unsafe { std::mem::transmute(v2) }); // NonZero -> NonMaxU8, do lint, different niche let _: Option = (v2 < NonZero::new(255u8).unwrap()).then(|| unsafe { std::mem::transmute(v2) }); + //~^ eager_transmute // NonZeroNonMaxU8 -> NonMaxU8, don't lint, target type has more validity let _: Option = (v3 < 255).then_some(unsafe { std::mem::transmute(v2) }); // NonZero -> NonZeroNonMaxU8, do lint, target type has less validity let _: Option = (v2 < NonZero::new(255u8).unwrap()).then(|| unsafe { std::mem::transmute(v2) }); + //~^ eager_transmute } fn main() {} diff --git a/tests/ui/eager_transmute.rs b/tests/ui/eager_transmute.rs index 9750e87ce574..48d7d50cdaef 100644 --- a/tests/ui/eager_transmute.rs +++ b/tests/ui/eager_transmute.rs @@ -19,20 +19,27 @@ struct Data { fn int_to_opcode(op: u8) -> Option { (op < 4).then_some(unsafe { std::mem::transmute(op) }) + //~^ eager_transmute } fn f(op: u8, op2: Data, unrelated: u8) { true.then_some(unsafe { std::mem::transmute::<_, Opcode>(op) }); (unrelated < 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) }); (op < 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) }); + //~^ eager_transmute (op > 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) }); + //~^ eager_transmute (op == 0).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) }); + //~^ eager_transmute let _: Option = (op > 0 && op < 10).then_some(unsafe { std::mem::transmute(op) }); + //~^ eager_transmute let _: Option = (op > 0 && op < 10 && unrelated == 0).then_some(unsafe { std::mem::transmute(op) }); + //~^ eager_transmute // lint even when the transmutable goes through field/array accesses let _: Option = (op2.foo[0] > 0 && op2.foo[0] < 10).then_some(unsafe { std::mem::transmute(op2.foo[0]) }); + //~^ eager_transmute // don't lint: wrong index used in the transmute let _: Option = (op2.foo[0] > 0 && op2.foo[0] < 10).then_some(unsafe { std::mem::transmute(op2.foo[1]) }); @@ -45,11 +52,17 @@ fn f(op: u8, op2: Data, unrelated: u8) { // range contains checks let _: Option = (1..=3).contains(&op).then_some(unsafe { std::mem::transmute(op) }); + //~^ eager_transmute let _: Option = ((1..=3).contains(&op) || op == 4).then_some(unsafe { std::mem::transmute(op) }); + //~^ eager_transmute let _: Option = (1..3).contains(&op).then_some(unsafe { std::mem::transmute(op) }); + //~^ eager_transmute let _: Option = (1..).contains(&op).then_some(unsafe { std::mem::transmute(op) }); + //~^ eager_transmute let _: Option = (..3).contains(&op).then_some(unsafe { std::mem::transmute(op) }); + //~^ eager_transmute let _: Option = (..=3).contains(&op).then_some(unsafe { std::mem::transmute(op) }); + //~^ eager_transmute // unrelated binding in contains let _: Option = (1..=3) @@ -59,6 +72,7 @@ fn f(op: u8, op2: Data, unrelated: u8) { unsafe fn f2(op: u8) { (op < 4).then_some(std::mem::transmute::<_, Opcode>(op)); + //~^ eager_transmute } #[rustc_layout_scalar_valid_range_end(254)] @@ -88,18 +102,21 @@ impls!(NonMaxU8, NonZeroNonMaxU8); fn niche_tests(v1: u8, v2: NonZero, v3: NonZeroNonMaxU8) { // u8 -> NonZero, do lint let _: Option> = (v1 > 0).then_some(unsafe { std::mem::transmute(v1) }); + //~^ eager_transmute // NonZero -> u8, don't lint, target type has no niche and therefore a higher validity range let _: Option = (v2 > NonZero::new(1u8).unwrap()).then_some(unsafe { std::mem::transmute(v2) }); // NonZero -> NonMaxU8, do lint, different niche let _: Option = (v2 < NonZero::new(255u8).unwrap()).then_some(unsafe { std::mem::transmute(v2) }); + //~^ eager_transmute // NonZeroNonMaxU8 -> NonMaxU8, don't lint, target type has more validity let _: Option = (v3 < 255).then_some(unsafe { std::mem::transmute(v2) }); // NonZero -> NonZeroNonMaxU8, do lint, target type has less validity let _: Option = (v2 < NonZero::new(255u8).unwrap()).then_some(unsafe { std::mem::transmute(v2) }); + //~^ eager_transmute } fn main() {} diff --git a/tests/ui/eager_transmute.stderr b/tests/ui/eager_transmute.stderr index 68690c3730d8..54850d110eb2 100644 --- a/tests/ui/eager_transmute.stderr +++ b/tests/ui/eager_transmute.stderr @@ -13,7 +13,7 @@ LL + (op < 4).then(|| unsafe { std::mem::transmute(op) }) | error: this transmute is always evaluated eagerly, even if the condition is false - --> tests/ui/eager_transmute.rs:27:33 + --> tests/ui/eager_transmute.rs:28:33 | LL | (op < 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + (op < 4).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) }); | error: this transmute is always evaluated eagerly, even if the condition is false - --> tests/ui/eager_transmute.rs:28:33 + --> tests/ui/eager_transmute.rs:30:33 | LL | (op > 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + (op > 4).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) }); | error: this transmute is always evaluated eagerly, even if the condition is false - --> tests/ui/eager_transmute.rs:29:34 + --> tests/ui/eager_transmute.rs:32:34 | LL | (op == 0).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + (op == 0).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) }); | error: this transmute is always evaluated eagerly, even if the condition is false - --> tests/ui/eager_transmute.rs:31:68 + --> tests/ui/eager_transmute.rs:35:68 | LL | let _: Option = (op > 0 && op < 10).then_some(unsafe { std::mem::transmute(op) }); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + let _: Option = (op > 0 && op < 10).then(|| unsafe { std::mem:: | error: this transmute is always evaluated eagerly, even if the condition is false - --> tests/ui/eager_transmute.rs:32:86 + --> tests/ui/eager_transmute.rs:37:86 | LL | let _: Option = (op > 0 && op < 10 && unrelated == 0).then_some(unsafe { std::mem::transmute(op) }); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + let _: Option = (op > 0 && op < 10 && unrelated == 0).then(|| u | error: this transmute is always evaluated eagerly, even if the condition is false - --> tests/ui/eager_transmute.rs:35:84 + --> tests/ui/eager_transmute.rs:41:84 | LL | let _: Option = (op2.foo[0] > 0 && op2.foo[0] < 10).then_some(unsafe { std::mem::transmute(op2.foo[0]) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + let _: Option = (op2.foo[0] > 0 && op2.foo[0] < 10).then(|| uns | error: this transmute is always evaluated eagerly, even if the condition is false - --> tests/ui/eager_transmute.rs:47:70 + --> tests/ui/eager_transmute.rs:54:70 | LL | let _: Option = (1..=3).contains(&op).then_some(unsafe { std::mem::transmute(op) }); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL + let _: Option = (1..=3).contains(&op).then(|| unsafe { std::mem | error: this transmute is always evaluated eagerly, even if the condition is false - --> tests/ui/eager_transmute.rs:48:83 + --> tests/ui/eager_transmute.rs:56:83 | LL | let _: Option = ((1..=3).contains(&op) || op == 4).then_some(unsafe { std::mem::transmute(op) }); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL + let _: Option = ((1..=3).contains(&op) || op == 4).then(|| unsa | error: this transmute is always evaluated eagerly, even if the condition is false - --> tests/ui/eager_transmute.rs:49:69 + --> tests/ui/eager_transmute.rs:58:69 | LL | let _: Option = (1..3).contains(&op).then_some(unsafe { std::mem::transmute(op) }); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL + let _: Option = (1..3).contains(&op).then(|| unsafe { std::mem: | error: this transmute is always evaluated eagerly, even if the condition is false - --> tests/ui/eager_transmute.rs:50:68 + --> tests/ui/eager_transmute.rs:60:68 | LL | let _: Option = (1..).contains(&op).then_some(unsafe { std::mem::transmute(op) }); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL + let _: Option = (1..).contains(&op).then(|| unsafe { std::mem:: | error: this transmute is always evaluated eagerly, even if the condition is false - --> tests/ui/eager_transmute.rs:51:68 + --> tests/ui/eager_transmute.rs:62:68 | LL | let _: Option = (..3).contains(&op).then_some(unsafe { std::mem::transmute(op) }); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -145,7 +145,7 @@ LL + let _: Option = (..3).contains(&op).then(|| unsafe { std::mem:: | error: this transmute is always evaluated eagerly, even if the condition is false - --> tests/ui/eager_transmute.rs:52:69 + --> tests/ui/eager_transmute.rs:64:69 | LL | let _: Option = (..=3).contains(&op).then_some(unsafe { std::mem::transmute(op) }); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL + let _: Option = (..=3).contains(&op).then(|| unsafe { std::mem: | error: this transmute is always evaluated eagerly, even if the condition is false - --> tests/ui/eager_transmute.rs:61:24 + --> tests/ui/eager_transmute.rs:74:24 | LL | (op < 4).then_some(std::mem::transmute::<_, Opcode>(op)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -169,7 +169,7 @@ LL + (op < 4).then(|| std::mem::transmute::<_, Opcode>(op)); | error: this transmute is always evaluated eagerly, even if the condition is false - --> tests/ui/eager_transmute.rs:90:62 + --> tests/ui/eager_transmute.rs:104:62 | LL | let _: Option> = (v1 > 0).then_some(unsafe { std::mem::transmute(v1) }); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -181,7 +181,7 @@ LL + let _: Option> = (v1 > 0).then(|| unsafe { std::mem::transm | error: this transmute is always evaluated eagerly, even if the condition is false - --> tests/ui/eager_transmute.rs:96:86 + --> tests/ui/eager_transmute.rs:111:86 | LL | let _: Option = (v2 < NonZero::new(255u8).unwrap()).then_some(unsafe { std::mem::transmute(v2) }); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -193,7 +193,7 @@ LL + let _: Option = (v2 < NonZero::new(255u8).unwrap()).then(|| u | error: this transmute is always evaluated eagerly, even if the condition is false - --> tests/ui/eager_transmute.rs:102:93 + --> tests/ui/eager_transmute.rs:118:93 | LL | let _: Option = (v2 < NonZero::new(255u8).unwrap()).then_some(unsafe { std::mem::transmute(v2) }); | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/elidable_lifetime_names.fixed b/tests/ui/elidable_lifetime_names.fixed new file mode 100644 index 000000000000..abeee5c4cef3 --- /dev/null +++ b/tests/ui/elidable_lifetime_names.fixed @@ -0,0 +1,194 @@ +#![warn(clippy::needless_lifetimes, clippy::elidable_lifetime_names)] + +type Ref<'r> = &'r u8; + +// No error; same lifetime on two params. +fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) {} + +//~v ERROR: could be elided: 'a, 'b +fn lifetime_param_2(_x: Ref<'_>, _y: &u8) {} + +// No error; bounded lifetime. +fn lifetime_param_3<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) {} + +// No error; bounded lifetime. +fn lifetime_param_4<'a, 'b>(_x: Ref<'a>, _y: &'b u8) +where + 'b: 'a, +{ +} + +struct Lt<'a, I: 'static> { + x: &'a I, +} + +// No error; fn bound references `'a`. +fn fn_bound<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> +where + F: Fn(Lt<'a, I>) -> Lt<'a, I>, +{ + unreachable!() +} + +//~v ERROR: could be elided: 'a +fn fn_bound_2(_m: Lt<'_, I>, _f: F) -> Lt<'_, I> +where + for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I>, +{ + unreachable!() +} + +struct Foo<'a>(&'a u8); + +//~v ERROR: could be elided: 'a +fn struct_with_lt(_foo: Foo<'_>) -> &str { + unimplemented!() +} + +// No warning; two input lifetimes (named on the reference, anonymous on `Foo`). +fn struct_with_lt2<'a>(_foo: &'a Foo) -> &'a str { + unimplemented!() +} + +// No warning; two input lifetimes (anonymous on the reference, named on `Foo`). +fn struct_with_lt3<'a>(_foo: &Foo<'a>) -> &'a str { + unimplemented!() +} + +//~v ERROR: could be elided: 'b +fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str { + unimplemented!() +} + +type FooAlias<'a> = Foo<'a>; + +//~v ERROR: could be elided: 'a +fn alias_with_lt(_foo: FooAlias<'_>) -> &str { + unimplemented!() +} + +// No warning; two input lifetimes (named on the reference, anonymous on `FooAlias`). +fn alias_with_lt2<'a>(_foo: &'a FooAlias) -> &'a str { + unimplemented!() +} + +// No warning; two input lifetimes (anonymous on the reference, named on `FooAlias`). +fn alias_with_lt3<'a>(_foo: &FooAlias<'a>) -> &'a str { + unimplemented!() +} + +//~v ERROR: could be elided: 'b +fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str { + unimplemented!() +} + +// Issue #3284: give hint regarding lifetime in return type. +struct Cow<'a> { + x: &'a str, +} + +//~v ERROR: could be elided: 'a +fn out_return_type_lts(e: &str) -> Cow<'_> { + unimplemented!() +} + +mod issue2944 { + trait Foo {} + struct Bar; + struct Baz<'a> { + bar: &'a Bar, + } + + //~v ERROR: could be elided: 'a + impl Foo for Baz<'_> {} + impl Bar { + //~v ERROR: could be elided: 'a + fn baz(&self) -> impl Foo + '_ { + Baz { bar: self } + } + } +} + +mod issue13923 { + struct Py<'py> { + data: &'py str, + } + + enum Content<'t, 'py> { + Py(Py<'py>), + T1(&'t str), + T2(&'t str), + } + + enum ContentString<'t> { + T1(&'t str), + T2(&'t str), + } + + impl<'t, 'py> ContentString<'t> { + // `'py` cannot be elided + fn map_content1(self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> { + match self { + Self::T1(content) => Content::T1(f(content)), + Self::T2(content) => Content::T2(f(content)), + } + } + } + + //~v ERROR: could be elided: 'py + impl<'t> ContentString<'t> { + // `'py` can be elided because of `&self` + fn map_content2(&self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, '_> { + match self { + Self::T1(content) => Content::T1(f(content)), + Self::T2(content) => Content::T2(f(content)), + } + } + } + + //~v ERROR: could be elided: 'py + impl<'t> ContentString<'t> { + // `'py` can be elided because of `&'_ self` + fn map_content3(&'_ self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, '_> { + match self { + Self::T1(content) => Content::T1(f(content)), + Self::T2(content) => Content::T2(f(content)), + } + } + } + + impl<'t, 'py> ContentString<'t> { + // `'py` should not be elided as the default lifetime, even if working, could be named as `'t` + fn map_content4(self, f: impl FnOnce(&'t str) -> &'t str, o: &'t str) -> Content<'t, 'py> { + match self { + Self::T1(content) => Content::T1(f(content)), + Self::T2(_) => Content::T2(o), + } + } + } + + //~v ERROR: could be elided: 'py + impl<'t> ContentString<'t> { + // `'py` can be elided because of `&Self` + fn map_content5( + self: std::pin::Pin<&Self>, + f: impl FnOnce(&'t str) -> &'t str, + o: &'t str, + ) -> Content<'t, '_> { + match *self { + Self::T1(content) => Content::T1(f(content)), + Self::T2(_) => Content::T2(o), + } + } + } + + struct Cx<'a, 'b> { + a: &'a u32, + b: &'b u32, + } + + // `'c` cannot be elided because we have several input lifetimes + fn one_explicit<'b>(x: Cx<'_, 'b>) -> &'b u32 { + x.b + } +} diff --git a/tests/ui/elidable_lifetime_names.rs b/tests/ui/elidable_lifetime_names.rs new file mode 100644 index 000000000000..fae3577a8e96 --- /dev/null +++ b/tests/ui/elidable_lifetime_names.rs @@ -0,0 +1,194 @@ +#![warn(clippy::needless_lifetimes, clippy::elidable_lifetime_names)] + +type Ref<'r> = &'r u8; + +// No error; same lifetime on two params. +fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) {} + +//~v ERROR: could be elided: 'a, 'b +fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {} + +// No error; bounded lifetime. +fn lifetime_param_3<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) {} + +// No error; bounded lifetime. +fn lifetime_param_4<'a, 'b>(_x: Ref<'a>, _y: &'b u8) +where + 'b: 'a, +{ +} + +struct Lt<'a, I: 'static> { + x: &'a I, +} + +// No error; fn bound references `'a`. +fn fn_bound<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> +where + F: Fn(Lt<'a, I>) -> Lt<'a, I>, +{ + unreachable!() +} + +//~v ERROR: could be elided: 'a +fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> +where + for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I>, +{ + unreachable!() +} + +struct Foo<'a>(&'a u8); + +//~v ERROR: could be elided: 'a +fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { + unimplemented!() +} + +// No warning; two input lifetimes (named on the reference, anonymous on `Foo`). +fn struct_with_lt2<'a>(_foo: &'a Foo) -> &'a str { + unimplemented!() +} + +// No warning; two input lifetimes (anonymous on the reference, named on `Foo`). +fn struct_with_lt3<'a>(_foo: &Foo<'a>) -> &'a str { + unimplemented!() +} + +//~v ERROR: could be elided: 'b +fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str { + unimplemented!() +} + +type FooAlias<'a> = Foo<'a>; + +//~v ERROR: could be elided: 'a +fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { + unimplemented!() +} + +// No warning; two input lifetimes (named on the reference, anonymous on `FooAlias`). +fn alias_with_lt2<'a>(_foo: &'a FooAlias) -> &'a str { + unimplemented!() +} + +// No warning; two input lifetimes (anonymous on the reference, named on `FooAlias`). +fn alias_with_lt3<'a>(_foo: &FooAlias<'a>) -> &'a str { + unimplemented!() +} + +//~v ERROR: could be elided: 'b +fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str { + unimplemented!() +} + +// Issue #3284: give hint regarding lifetime in return type. +struct Cow<'a> { + x: &'a str, +} + +//~v ERROR: could be elided: 'a +fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> { + unimplemented!() +} + +mod issue2944 { + trait Foo {} + struct Bar; + struct Baz<'a> { + bar: &'a Bar, + } + + //~v ERROR: could be elided: 'a + impl<'a> Foo for Baz<'a> {} + impl Bar { + //~v ERROR: could be elided: 'a + fn baz<'a>(&'a self) -> impl Foo + 'a { + Baz { bar: self } + } + } +} + +mod issue13923 { + struct Py<'py> { + data: &'py str, + } + + enum Content<'t, 'py> { + Py(Py<'py>), + T1(&'t str), + T2(&'t str), + } + + enum ContentString<'t> { + T1(&'t str), + T2(&'t str), + } + + impl<'t, 'py> ContentString<'t> { + // `'py` cannot be elided + fn map_content1(self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> { + match self { + Self::T1(content) => Content::T1(f(content)), + Self::T2(content) => Content::T2(f(content)), + } + } + } + + //~v ERROR: could be elided: 'py + impl<'t, 'py> ContentString<'t> { + // `'py` can be elided because of `&self` + fn map_content2(&self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> { + match self { + Self::T1(content) => Content::T1(f(content)), + Self::T2(content) => Content::T2(f(content)), + } + } + } + + //~v ERROR: could be elided: 'py + impl<'t, 'py> ContentString<'t> { + // `'py` can be elided because of `&'_ self` + fn map_content3(&'_ self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> { + match self { + Self::T1(content) => Content::T1(f(content)), + Self::T2(content) => Content::T2(f(content)), + } + } + } + + impl<'t, 'py> ContentString<'t> { + // `'py` should not be elided as the default lifetime, even if working, could be named as `'t` + fn map_content4(self, f: impl FnOnce(&'t str) -> &'t str, o: &'t str) -> Content<'t, 'py> { + match self { + Self::T1(content) => Content::T1(f(content)), + Self::T2(_) => Content::T2(o), + } + } + } + + //~v ERROR: could be elided: 'py + impl<'t, 'py> ContentString<'t> { + // `'py` can be elided because of `&Self` + fn map_content5( + self: std::pin::Pin<&Self>, + f: impl FnOnce(&'t str) -> &'t str, + o: &'t str, + ) -> Content<'t, 'py> { + match *self { + Self::T1(content) => Content::T1(f(content)), + Self::T2(_) => Content::T2(o), + } + } + } + + struct Cx<'a, 'b> { + a: &'a u32, + b: &'b u32, + } + + // `'c` cannot be elided because we have several input lifetimes + fn one_explicit<'b>(x: Cx<'_, 'b>) -> &'b u32 { + x.b + } +} diff --git a/tests/ui/elidable_lifetime_names.stderr b/tests/ui/elidable_lifetime_names.stderr new file mode 100644 index 000000000000..a60dfc697564 --- /dev/null +++ b/tests/ui/elidable_lifetime_names.stderr @@ -0,0 +1,162 @@ +error: the following explicit lifetimes could be elided: 'a, 'b + --> tests/ui/elidable_lifetime_names.rs:9:21 + | +LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {} + | ^^ ^^ ^^ ^^ + | + = note: `-D clippy::elidable-lifetime-names` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::elidable_lifetime_names)]` +help: elide the lifetimes + | +LL - fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {} +LL + fn lifetime_param_2(_x: Ref<'_>, _y: &u8) {} + | + +error: the following explicit lifetimes could be elided: 'a + --> tests/ui/elidable_lifetime_names.rs:34:15 + | +LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> + | ^^ ^^ ^^ + | +help: elide the lifetimes + | +LL - fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> +LL + fn fn_bound_2(_m: Lt<'_, I>, _f: F) -> Lt<'_, I> + | + +error: the following explicit lifetimes could be elided: 'a + --> tests/ui/elidable_lifetime_names.rs:44:19 + | +LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { + | ^^ ^^ ^^ + | +help: elide the lifetimes + | +LL - fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { +LL + fn struct_with_lt(_foo: Foo<'_>) -> &str { + | + +error: the following explicit lifetimes could be elided: 'b + --> tests/ui/elidable_lifetime_names.rs:59:25 + | +LL | fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str { + | ^^ ^^ + | +help: elide the lifetimes + | +LL - fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str { +LL + fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str { + | + +error: the following explicit lifetimes could be elided: 'a + --> tests/ui/elidable_lifetime_names.rs:66:18 + | +LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { + | ^^ ^^ ^^ + | +help: elide the lifetimes + | +LL - fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { +LL + fn alias_with_lt(_foo: FooAlias<'_>) -> &str { + | + +error: the following explicit lifetimes could be elided: 'b + --> tests/ui/elidable_lifetime_names.rs:81:24 + | +LL | fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str { + | ^^ ^^ + | +help: elide the lifetimes + | +LL - fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str { +LL + fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str { + | + +error: the following explicit lifetimes could be elided: 'a + --> tests/ui/elidable_lifetime_names.rs:91:24 + | +LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> { + | ^^ ^^ ^^ + | +help: elide the lifetimes + | +LL - fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> { +LL + fn out_return_type_lts(e: &str) -> Cow<'_> { + | + +error: the following explicit lifetimes could be elided: 'a + --> tests/ui/elidable_lifetime_names.rs:103:10 + | +LL | impl<'a> Foo for Baz<'a> {} + | ^^ ^^ + | +help: elide the lifetimes + | +LL - impl<'a> Foo for Baz<'a> {} +LL + impl Foo for Baz<'_> {} + | + +error: the following explicit lifetimes could be elided: 'a + --> tests/ui/elidable_lifetime_names.rs:106:16 + | +LL | fn baz<'a>(&'a self) -> impl Foo + 'a { + | ^^ ^^ ^^ + | +help: elide the lifetimes + | +LL - fn baz<'a>(&'a self) -> impl Foo + 'a { +LL + fn baz(&self) -> impl Foo + '_ { + | + +error: the following explicit lifetimes could be elided: 'py + --> tests/ui/elidable_lifetime_names.rs:139:14 + | +LL | impl<'t, 'py> ContentString<'t> { + | ^^^ +LL | // `'py` can be elided because of `&self` +LL | fn map_content2(&self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> { + | ^^^ + | +help: elide the lifetimes + | +LL ~ impl<'t> ContentString<'t> { +LL | // `'py` can be elided because of `&self` +LL ~ fn map_content2(&self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, '_> { + | + +error: the following explicit lifetimes could be elided: 'py + --> tests/ui/elidable_lifetime_names.rs:150:14 + | +LL | impl<'t, 'py> ContentString<'t> { + | ^^^ +LL | // `'py` can be elided because of `&'_ self` +LL | fn map_content3(&'_ self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> { + | ^^^ + | +help: elide the lifetimes + | +LL ~ impl<'t> ContentString<'t> { +LL | // `'py` can be elided because of `&'_ self` +LL ~ fn map_content3(&'_ self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, '_> { + | + +error: the following explicit lifetimes could be elided: 'py + --> tests/ui/elidable_lifetime_names.rs:171:14 + | +LL | impl<'t, 'py> ContentString<'t> { + | ^^^ +... +LL | ) -> Content<'t, 'py> { + | ^^^ + | +help: elide the lifetimes + | +LL ~ impl<'t> ContentString<'t> { +LL | // `'py` can be elided because of `&Self` +... +LL | o: &'t str, +LL ~ ) -> Content<'t, '_> { + | + +error: aborting due to 12 previous errors + diff --git a/tests/ui/else_if_without_else.rs b/tests/ui/else_if_without_else.rs index b04c22fa2aed..05d56600e100 100644 --- a/tests/ui/else_if_without_else.rs +++ b/tests/ui/else_if_without_else.rs @@ -49,7 +49,8 @@ fn main() { if bla1() { println!("if"); } else if bla2() { - //~^ ERROR: `if` expression with an `else if`, but without a final `else` + //~^ else_if_without_else + println!("else if"); } @@ -58,7 +59,8 @@ fn main() { } else if bla2() { println!("else if 1"); } else if bla3() { - //~^ ERROR: `if` expression with an `else if`, but without a final `else` + //~^ else_if_without_else + println!("else if 2"); } @@ -85,7 +87,8 @@ fn main() { } else if bla4() { println!("else if 3"); } else if bla5() { - //~^ ERROR: `if` expression with an `else if`, but without a final `else` + //~^ else_if_without_else + println!("else if 4"); } @@ -115,7 +118,8 @@ fn main() { } else if bla4() { println!("else if 3"); } else if bla5() { - //~^ ERROR: `if` expression with an `else if`, but without a final `else` + //~^ else_if_without_else + println!("else if 4"); } } diff --git a/tests/ui/else_if_without_else.stderr b/tests/ui/else_if_without_else.stderr index bc7174852293..ac7802345b97 100644 --- a/tests/ui/else_if_without_else.stderr +++ b/tests/ui/else_if_without_else.stderr @@ -4,6 +4,7 @@ error: `if` expression with an `else if`, but without a final `else` LL | } else if bla2() { | ____________^ LL | | +LL | | LL | | println!("else if"); LL | | } | |_____^ @@ -13,11 +14,12 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::else_if_without_else)]` error: `if` expression with an `else if`, but without a final `else` - --> tests/ui/else_if_without_else.rs:60:12 + --> tests/ui/else_if_without_else.rs:61:12 | LL | } else if bla3() { | ____________^ LL | | +LL | | LL | | println!("else if 2"); LL | | } | |_____^ @@ -25,11 +27,12 @@ LL | | } = help: add an `else` block here error: `if` expression with an `else if`, but without a final `else` - --> tests/ui/else_if_without_else.rs:87:12 + --> tests/ui/else_if_without_else.rs:89:12 | LL | } else if bla5() { | ____________^ LL | | +LL | | LL | | println!("else if 4"); LL | | } | |_____^ @@ -37,11 +40,12 @@ LL | | } = help: add an `else` block here error: `if` expression with an `else if`, but without a final `else` - --> tests/ui/else_if_without_else.rs:117:16 + --> tests/ui/else_if_without_else.rs:120:16 | LL | } else if bla5() { | ________________^ LL | | +LL | | LL | | println!("else if 4"); LL | | } | |_________^ diff --git a/tests/ui/empty_docs.rs b/tests/ui/empty_docs.rs index 00e64eebc5fb..d7768e07901a 100644 --- a/tests/ui/empty_docs.rs +++ b/tests/ui/empty_docs.rs @@ -7,6 +7,7 @@ mod outer { //! + //~^ empty_docs /// this is a struct struct Bananas { @@ -15,8 +16,10 @@ mod outer { } /// + //~^ empty_docs enum Warn { /// + //~^ empty_docs A, B, } @@ -28,16 +31,19 @@ mod outer { } #[doc = ""] + //~^ empty_docs fn warn_about_this() {} #[doc = ""] #[doc = ""] + //~^^ empty_docs fn this_doesn_warn() {} #[doc = "a fine function"] fn this_is_fine() {} /// + //~^ empty_docs mod inner { /// fn dont_warn_inner_outer() { @@ -51,6 +57,7 @@ mod outer { fn warn() { /*! */ + //~^ empty_docs } fn dont_warn() { @@ -59,6 +66,7 @@ mod outer { trait NoDoc { /// + //~^ empty_docs fn some() {} } } @@ -67,6 +75,7 @@ mod outer { /// lint y x: i32, /// + //~^ empty_docs y: i32, } } diff --git a/tests/ui/empty_docs.stderr b/tests/ui/empty_docs.stderr index 5fd7272d7c16..2eba6806852b 100644 --- a/tests/ui/empty_docs.stderr +++ b/tests/ui/empty_docs.stderr @@ -9,7 +9,7 @@ LL | //! = help: to override `-D warnings` add `#[allow(clippy::empty_docs)]` error: empty doc comment - --> tests/ui/empty_docs.rs:17:5 + --> tests/ui/empty_docs.rs:18:5 | LL | /// | ^^^ @@ -17,7 +17,7 @@ LL | /// = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:19:9 + --> tests/ui/empty_docs.rs:21:9 | LL | /// | ^^^ @@ -25,7 +25,7 @@ LL | /// = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:30:13 + --> tests/ui/empty_docs.rs:33:13 | LL | #[doc = ""] | ^^ @@ -33,7 +33,7 @@ LL | #[doc = ""] = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:33:13 + --> tests/ui/empty_docs.rs:37:13 | LL | #[doc = ""] | _____________^ @@ -43,7 +43,7 @@ LL | | #[doc = ""] = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:40:5 + --> tests/ui/empty_docs.rs:45:5 | LL | /// | ^^^ @@ -51,7 +51,7 @@ LL | /// = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:53:13 + --> tests/ui/empty_docs.rs:59:13 | LL | /*! */ | ^^^^^^ @@ -59,7 +59,7 @@ LL | /*! */ = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:61:13 + --> tests/ui/empty_docs.rs:68:13 | LL | /// | ^^^ @@ -67,7 +67,7 @@ LL | /// = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:69:9 + --> tests/ui/empty_docs.rs:77:9 | LL | /// | ^^^ diff --git a/tests/ui/empty_drop.rs b/tests/ui/empty_drop.rs index 74822ea50ec7..5793f783a724 100644 --- a/tests/ui/empty_drop.rs +++ b/tests/ui/empty_drop.rs @@ -5,6 +5,7 @@ struct Foo; impl Drop for Foo { + //~^ empty_drop fn drop(&mut self) {} } @@ -21,6 +22,7 @@ impl Drop for Bar { struct Baz; impl Drop for Baz { + //~^ empty_drop fn drop(&mut self) { {} } diff --git a/tests/ui/empty_drop.stderr b/tests/ui/empty_drop.stderr index d4d020fec30c..3073bf553969 100644 --- a/tests/ui/empty_drop.stderr +++ b/tests/ui/empty_drop.stderr @@ -2,6 +2,7 @@ error: empty drop implementation --> tests/ui/empty_drop.rs:7:1 | LL | / impl Drop for Foo { +LL | | LL | | fn drop(&mut self) {} LL | | } | |_^ @@ -11,9 +12,10 @@ LL | | } = help: try removing this impl error: empty drop implementation - --> tests/ui/empty_drop.rs:23:1 + --> tests/ui/empty_drop.rs:24:1 | LL | / impl Drop for Baz { +LL | | LL | | fn drop(&mut self) { LL | | {} LL | | } diff --git a/tests/ui/empty_enum.rs b/tests/ui/empty_enum.rs index 77357c15d957..439fd0974f5f 100644 --- a/tests/ui/empty_enum.rs +++ b/tests/ui/empty_enum.rs @@ -3,6 +3,6 @@ // Enable never type to test empty enum lint #![feature(never_type)] enum Empty {} -//~^ ERROR: enum with no variants +//~^ empty_enum fn main() {} diff --git a/tests/ui/empty_enum_variants_with_brackets.fixed b/tests/ui/empty_enum_variants_with_brackets.fixed index 1a5e78dd47fe..885f6a50025e 100644 --- a/tests/ui/empty_enum_variants_with_brackets.fixed +++ b/tests/ui/empty_enum_variants_with_brackets.fixed @@ -4,16 +4,20 @@ pub enum PublicTestEnum { NonEmptyBraces { x: i32, y: i32 }, // No error NonEmptyParentheses(i32, i32), // No error - EmptyBraces, //~ ERROR: enum variant has empty brackets - EmptyParentheses, //~ ERROR: enum variant has empty brackets + EmptyBraces, + //~^ empty_enum_variants_with_brackets + EmptyParentheses, + //~^ empty_enum_variants_with_brackets } enum TestEnum { NonEmptyBraces { x: i32, y: i32 }, // No error NonEmptyParentheses(i32, i32), // No error - EmptyBraces, //~ ERROR: enum variant has empty brackets - EmptyParentheses, //~ ERROR: enum variant has empty brackets - AnotherEnum, // No error + EmptyBraces, + //~^ empty_enum_variants_with_brackets + EmptyParentheses, + //~^ empty_enum_variants_with_brackets + AnotherEnum, // No error } enum TestEnumWithFeatures { diff --git a/tests/ui/empty_enum_variants_with_brackets.rs b/tests/ui/empty_enum_variants_with_brackets.rs index ca20b969a240..092712ee2ead 100644 --- a/tests/ui/empty_enum_variants_with_brackets.rs +++ b/tests/ui/empty_enum_variants_with_brackets.rs @@ -4,16 +4,20 @@ pub enum PublicTestEnum { NonEmptyBraces { x: i32, y: i32 }, // No error NonEmptyParentheses(i32, i32), // No error - EmptyBraces {}, //~ ERROR: enum variant has empty brackets - EmptyParentheses(), //~ ERROR: enum variant has empty brackets + EmptyBraces {}, + //~^ empty_enum_variants_with_brackets + EmptyParentheses(), + //~^ empty_enum_variants_with_brackets } enum TestEnum { NonEmptyBraces { x: i32, y: i32 }, // No error NonEmptyParentheses(i32, i32), // No error - EmptyBraces {}, //~ ERROR: enum variant has empty brackets - EmptyParentheses(), //~ ERROR: enum variant has empty brackets - AnotherEnum, // No error + EmptyBraces {}, + //~^ empty_enum_variants_with_brackets + EmptyParentheses(), + //~^ empty_enum_variants_with_brackets + AnotherEnum, // No error } enum TestEnumWithFeatures { diff --git a/tests/ui/empty_enum_variants_with_brackets.stderr b/tests/ui/empty_enum_variants_with_brackets.stderr index 2b187b8f755b..a9ae3b476dd6 100644 --- a/tests/ui/empty_enum_variants_with_brackets.stderr +++ b/tests/ui/empty_enum_variants_with_brackets.stderr @@ -9,7 +9,7 @@ LL | EmptyBraces {}, = help: remove the brackets error: enum variant has empty brackets - --> tests/ui/empty_enum_variants_with_brackets.rs:8:21 + --> tests/ui/empty_enum_variants_with_brackets.rs:9:21 | LL | EmptyParentheses(), | ^^ @@ -17,7 +17,7 @@ LL | EmptyParentheses(), = help: remove the brackets error: enum variant has empty brackets - --> tests/ui/empty_enum_variants_with_brackets.rs:14:16 + --> tests/ui/empty_enum_variants_with_brackets.rs:16:16 | LL | EmptyBraces {}, | ^^^ @@ -25,7 +25,7 @@ LL | EmptyBraces {}, = help: remove the brackets error: enum variant has empty brackets - --> tests/ui/empty_enum_variants_with_brackets.rs:15:21 + --> tests/ui/empty_enum_variants_with_brackets.rs:18:21 | LL | EmptyParentheses(), | ^^ diff --git a/tests/ui/empty_enum_without_never_type.rs b/tests/ui/empty_enum_without_never_type.rs index 386677352e29..3661a1537208 100644 --- a/tests/ui/empty_enum_without_never_type.rs +++ b/tests/ui/empty_enum_without_never_type.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(dead_code)] #![warn(clippy::empty_enum)] diff --git a/tests/ui/empty_line_after/doc_comments.1.fixed b/tests/ui/empty_line_after/doc_comments.1.fixed index 3772b465fdb2..e4ba09ea1d47 100644 --- a/tests/ui/empty_line_after/doc_comments.1.fixed +++ b/tests/ui/empty_line_after/doc_comments.1.fixed @@ -138,6 +138,7 @@ trait Foo { impl Foo for LineComment { /// comment on assoc item + //~^ empty_line_after_doc_comments fn bar() {} } diff --git a/tests/ui/empty_line_after/doc_comments.2.fixed b/tests/ui/empty_line_after/doc_comments.2.fixed index 3028d03b6699..a20f9bc20eb5 100644 --- a/tests/ui/empty_line_after/doc_comments.2.fixed +++ b/tests/ui/empty_line_after/doc_comments.2.fixed @@ -146,7 +146,9 @@ trait Foo { } impl Foo for LineComment { - /// comment on assoc item + // /// comment on assoc item + //~^ empty_line_after_doc_comments + fn bar() {} } diff --git a/tests/ui/empty_line_after/doc_comments.rs b/tests/ui/empty_line_after/doc_comments.rs index ae4ebc271fa1..9e3ddfd5abe1 100644 --- a/tests/ui/empty_line_after/doc_comments.rs +++ b/tests/ui/empty_line_after/doc_comments.rs @@ -150,6 +150,7 @@ trait Foo { impl Foo for LineComment { /// comment on assoc item + //~^ empty_line_after_doc_comments fn bar() {} } diff --git a/tests/ui/empty_line_after/doc_comments.stderr b/tests/ui/empty_line_after/doc_comments.stderr index ca05a1b03eb1..fe25ba9afcb9 100644 --- a/tests/ui/empty_line_after/doc_comments.stderr +++ b/tests/ui/empty_line_after/doc_comments.stderr @@ -176,12 +176,17 @@ error: empty line after doc comment --> tests/ui/empty_line_after/doc_comments.rs:152:5 | LL | / /// comment on assoc item +LL | | LL | | | |_^ LL | fn bar() {} | ------ the comment documents this function | = help: if the empty line is unintentional, remove it +help: if the doc comment should not document `bar` comment it out + | +LL | // /// comment on assoc item + | ++ error: aborting due to 11 previous errors diff --git a/tests/ui/empty_loop.rs b/tests/ui/empty_loop.rs index be347563135c..e2d4ff84b56a 100644 --- a/tests/ui/empty_loop.rs +++ b/tests/ui/empty_loop.rs @@ -7,14 +7,17 @@ use proc_macros::{external, inline_macros}; fn should_trigger() { loop {} + //~^ empty_loop #[allow(clippy::never_loop)] loop { loop {} + //~^ empty_loop } #[allow(clippy::never_loop)] 'outer: loop { 'inner: loop {} + //~^ empty_loop } } diff --git a/tests/ui/empty_loop.stderr b/tests/ui/empty_loop.stderr index 3ac93f4ece0c..bc723ceefbb3 100644 --- a/tests/ui/empty_loop.stderr +++ b/tests/ui/empty_loop.stderr @@ -9,7 +9,7 @@ LL | loop {} = help: to override `-D warnings` add `#[allow(clippy::empty_loop)]` error: empty `loop {}` wastes CPU cycles - --> tests/ui/empty_loop.rs:12:9 + --> tests/ui/empty_loop.rs:13:9 | LL | loop {} | ^^^^^^^ @@ -17,7 +17,7 @@ LL | loop {} = help: you should either use `panic!()` or add `std::thread::sleep(..);` to the loop body error: empty `loop {}` wastes CPU cycles - --> tests/ui/empty_loop.rs:17:9 + --> tests/ui/empty_loop.rs:19:9 | LL | 'inner: loop {} | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/empty_loop_no_std.rs b/tests/ui/empty_loop_no_std.rs index 9bfcbfba9697..6407bd678f9c 100644 --- a/tests/ui/empty_loop_no_std.rs +++ b/tests/ui/empty_loop_no_std.rs @@ -8,5 +8,5 @@ pub fn main(argc: isize, argv: *const *const u8) -> isize { // This should trigger the lint loop {} - //~^ ERROR: empty `loop {}` wastes CPU cycles + //~^ empty_loop } diff --git a/tests/ui/empty_structs_with_brackets.fixed b/tests/ui/empty_structs_with_brackets.fixed index 80572645f5d1..b1600862a8f6 100644 --- a/tests/ui/empty_structs_with_brackets.fixed +++ b/tests/ui/empty_structs_with_brackets.fixed @@ -2,7 +2,9 @@ #![allow(dead_code)] pub struct MyEmptyStruct; // should trigger lint +//~^ empty_structs_with_brackets struct MyEmptyTupleStruct; // should trigger lint +//~^ empty_structs_with_brackets // should not trigger lint struct MyCfgStruct { diff --git a/tests/ui/empty_structs_with_brackets.rs b/tests/ui/empty_structs_with_brackets.rs index 8fb3e247a419..1f69c4be9ec7 100644 --- a/tests/ui/empty_structs_with_brackets.rs +++ b/tests/ui/empty_structs_with_brackets.rs @@ -2,7 +2,9 @@ #![allow(dead_code)] pub struct MyEmptyStruct {} // should trigger lint +//~^ empty_structs_with_brackets struct MyEmptyTupleStruct(); // should trigger lint +//~^ empty_structs_with_brackets // should not trigger lint struct MyCfgStruct { diff --git a/tests/ui/empty_structs_with_brackets.stderr b/tests/ui/empty_structs_with_brackets.stderr index e57249aec023..86ef43aa9600 100644 --- a/tests/ui/empty_structs_with_brackets.stderr +++ b/tests/ui/empty_structs_with_brackets.stderr @@ -9,7 +9,7 @@ LL | pub struct MyEmptyStruct {} // should trigger lint = help: remove the brackets error: found empty brackets on struct declaration - --> tests/ui/empty_structs_with_brackets.rs:5:26 + --> tests/ui/empty_structs_with_brackets.rs:6:26 | LL | struct MyEmptyTupleStruct(); // should trigger lint | ^^^ diff --git a/tests/ui/endian_bytes.rs b/tests/ui/endian_bytes.rs index 580fc2fc24d7..879467c7f6e2 100644 --- a/tests/ui/endian_bytes.rs +++ b/tests/ui/endian_bytes.rs @@ -7,62 +7,118 @@ macro_rules! fn_body { () => { 2u8.to_ne_bytes(); + //~^ host_endian_bytes 2i8.to_ne_bytes(); + //~^ host_endian_bytes 2u16.to_ne_bytes(); + //~^ host_endian_bytes 2i16.to_ne_bytes(); + //~^ host_endian_bytes 2u32.to_ne_bytes(); + //~^ host_endian_bytes 2i32.to_ne_bytes(); + //~^ host_endian_bytes 2u64.to_ne_bytes(); + //~^ host_endian_bytes 2i64.to_ne_bytes(); + //~^ host_endian_bytes 2u128.to_ne_bytes(); + //~^ host_endian_bytes 2i128.to_ne_bytes(); + //~^ host_endian_bytes 2.0f32.to_ne_bytes(); + //~^ host_endian_bytes 2.0f64.to_ne_bytes(); + //~^ host_endian_bytes 2usize.to_ne_bytes(); + //~^ host_endian_bytes 2isize.to_ne_bytes(); + //~^ host_endian_bytes u8::from_ne_bytes(todo!()); + //~^ host_endian_bytes i8::from_ne_bytes(todo!()); + //~^ host_endian_bytes u16::from_ne_bytes(todo!()); + //~^ host_endian_bytes i16::from_ne_bytes(todo!()); + //~^ host_endian_bytes u32::from_ne_bytes(todo!()); + //~^ host_endian_bytes i32::from_ne_bytes(todo!()); + //~^ host_endian_bytes u64::from_ne_bytes(todo!()); + //~^ host_endian_bytes i64::from_ne_bytes(todo!()); + //~^ host_endian_bytes u128::from_ne_bytes(todo!()); + //~^ host_endian_bytes i128::from_ne_bytes(todo!()); + //~^ host_endian_bytes usize::from_ne_bytes(todo!()); + //~^ host_endian_bytes isize::from_ne_bytes(todo!()); + //~^ host_endian_bytes f32::from_ne_bytes(todo!()); + //~^ host_endian_bytes f64::from_ne_bytes(todo!()); + //~^ host_endian_bytes 2u8.to_le_bytes(); + //~^ little_endian_bytes 2i8.to_le_bytes(); + //~^ little_endian_bytes 2u16.to_le_bytes(); + //~^ little_endian_bytes 2i16.to_le_bytes(); + //~^ little_endian_bytes 2u32.to_le_bytes(); + //~^ little_endian_bytes 2i32.to_le_bytes(); + //~^ little_endian_bytes 2u64.to_le_bytes(); + //~^ little_endian_bytes 2i64.to_le_bytes(); + //~^ little_endian_bytes 2u128.to_le_bytes(); + //~^ little_endian_bytes 2i128.to_le_bytes(); + //~^ little_endian_bytes 2.0f32.to_le_bytes(); + //~^ little_endian_bytes 2.0f64.to_le_bytes(); + //~^ little_endian_bytes 2usize.to_le_bytes(); + //~^ little_endian_bytes 2isize.to_le_bytes(); + //~^ little_endian_bytes u8::from_le_bytes(todo!()); + //~^ little_endian_bytes i8::from_le_bytes(todo!()); + //~^ little_endian_bytes u16::from_le_bytes(todo!()); + //~^ little_endian_bytes i16::from_le_bytes(todo!()); + //~^ little_endian_bytes u32::from_le_bytes(todo!()); + //~^ little_endian_bytes i32::from_le_bytes(todo!()); + //~^ little_endian_bytes u64::from_le_bytes(todo!()); + //~^ little_endian_bytes i64::from_le_bytes(todo!()); + //~^ little_endian_bytes u128::from_le_bytes(todo!()); + //~^ little_endian_bytes i128::from_le_bytes(todo!()); + //~^ little_endian_bytes usize::from_le_bytes(todo!()); + //~^ little_endian_bytes isize::from_le_bytes(todo!()); + //~^ little_endian_bytes f32::from_le_bytes(todo!()); + //~^ little_endian_bytes f64::from_le_bytes(todo!()); + //~^ little_endian_bytes }; } @@ -70,13 +126,43 @@ macro_rules! fn_body { macro_rules! fn_body_smol { () => { 2u8.to_ne_bytes(); + //~^ host_endian_bytes + //~| host_endian_bytes + //~| host_endian_bytes + //~| host_endian_bytes + //~| host_endian_bytes u8::from_ne_bytes(todo!()); + //~^ host_endian_bytes + //~| host_endian_bytes + //~| host_endian_bytes + //~| host_endian_bytes + //~| host_endian_bytes 2u8.to_le_bytes(); + //~^ little_endian_bytes + //~| little_endian_bytes + //~| little_endian_bytes + //~| little_endian_bytes + //~| little_endian_bytes u8::from_le_bytes(todo!()); + //~^ little_endian_bytes + //~| little_endian_bytes + //~| little_endian_bytes + //~| little_endian_bytes + //~| little_endian_bytes 2u8.to_be_bytes(); + //~^ big_endian_bytes + //~| big_endian_bytes + //~| big_endian_bytes + //~| big_endian_bytes + //~| big_endian_bytes u8::from_be_bytes(todo!()); + //~^ big_endian_bytes + //~| big_endian_bytes + //~| big_endian_bytes + //~| big_endian_bytes + //~| big_endian_bytes }; } diff --git a/tests/ui/endian_bytes.stderr b/tests/ui/endian_bytes.stderr index fd19ec45872b..edc2a3309f24 100644 --- a/tests/ui/endian_bytes.stderr +++ b/tests/ui/endian_bytes.stderr @@ -13,7 +13,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `i8::to_ne_bytes` method - --> tests/ui/endian_bytes.rs:10:9 + --> tests/ui/endian_bytes.rs:11:9 | LL | 2i8.to_ne_bytes(); | ^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u16::to_ne_bytes` method - --> tests/ui/endian_bytes.rs:11:9 + --> tests/ui/endian_bytes.rs:13:9 | LL | 2u16.to_ne_bytes(); | ^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `i16::to_ne_bytes` method - --> tests/ui/endian_bytes.rs:12:9 + --> tests/ui/endian_bytes.rs:15:9 | LL | 2i16.to_ne_bytes(); | ^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u32::to_ne_bytes` method - --> tests/ui/endian_bytes.rs:13:9 + --> tests/ui/endian_bytes.rs:17:9 | LL | 2u32.to_ne_bytes(); | ^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `i32::to_ne_bytes` method - --> tests/ui/endian_bytes.rs:14:9 + --> tests/ui/endian_bytes.rs:19:9 | LL | 2i32.to_ne_bytes(); | ^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u64::to_ne_bytes` method - --> tests/ui/endian_bytes.rs:15:9 + --> tests/ui/endian_bytes.rs:21:9 | LL | 2u64.to_ne_bytes(); | ^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `i64::to_ne_bytes` method - --> tests/ui/endian_bytes.rs:16:9 + --> tests/ui/endian_bytes.rs:23:9 | LL | 2i64.to_ne_bytes(); | ^^^^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u128::to_ne_bytes` method - --> tests/ui/endian_bytes.rs:17:9 + --> tests/ui/endian_bytes.rs:25:9 | LL | 2u128.to_ne_bytes(); | ^^^^^^^^^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `i128::to_ne_bytes` method - --> tests/ui/endian_bytes.rs:18:9 + --> tests/ui/endian_bytes.rs:27:9 | LL | 2i128.to_ne_bytes(); | ^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `f32::to_ne_bytes` method - --> tests/ui/endian_bytes.rs:19:9 + --> tests/ui/endian_bytes.rs:29:9 | LL | 2.0f32.to_ne_bytes(); | ^^^^^^^^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `f64::to_ne_bytes` method - --> tests/ui/endian_bytes.rs:20:9 + --> tests/ui/endian_bytes.rs:31:9 | LL | 2.0f64.to_ne_bytes(); | ^^^^^^^^^^^^^^^^^^^^ @@ -145,7 +145,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `usize::to_ne_bytes` method - --> tests/ui/endian_bytes.rs:21:9 + --> tests/ui/endian_bytes.rs:33:9 | LL | 2usize.to_ne_bytes(); | ^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `isize::to_ne_bytes` method - --> tests/ui/endian_bytes.rs:22:9 + --> tests/ui/endian_bytes.rs:35:9 | LL | 2isize.to_ne_bytes(); | ^^^^^^^^^^^^^^^^^^^^ @@ -169,7 +169,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u8::from_ne_bytes` - --> tests/ui/endian_bytes.rs:23:9 + --> tests/ui/endian_bytes.rs:37:9 | LL | u8::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -181,7 +181,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `i8::from_ne_bytes` - --> tests/ui/endian_bytes.rs:24:9 + --> tests/ui/endian_bytes.rs:39:9 | LL | i8::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -193,7 +193,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u16::from_ne_bytes` - --> tests/ui/endian_bytes.rs:25:9 + --> tests/ui/endian_bytes.rs:41:9 | LL | u16::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -205,7 +205,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `i16::from_ne_bytes` - --> tests/ui/endian_bytes.rs:26:9 + --> tests/ui/endian_bytes.rs:43:9 | LL | i16::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +217,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u32::from_ne_bytes` - --> tests/ui/endian_bytes.rs:27:9 + --> tests/ui/endian_bytes.rs:45:9 | LL | u32::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -229,7 +229,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `i32::from_ne_bytes` - --> tests/ui/endian_bytes.rs:28:9 + --> tests/ui/endian_bytes.rs:47:9 | LL | i32::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,7 +241,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u64::from_ne_bytes` - --> tests/ui/endian_bytes.rs:29:9 + --> tests/ui/endian_bytes.rs:49:9 | LL | u64::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -253,7 +253,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `i64::from_ne_bytes` - --> tests/ui/endian_bytes.rs:30:9 + --> tests/ui/endian_bytes.rs:51:9 | LL | i64::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -265,7 +265,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u128::from_ne_bytes` - --> tests/ui/endian_bytes.rs:31:9 + --> tests/ui/endian_bytes.rs:53:9 | LL | u128::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -277,7 +277,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `i128::from_ne_bytes` - --> tests/ui/endian_bytes.rs:32:9 + --> tests/ui/endian_bytes.rs:55:9 | LL | i128::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -289,7 +289,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `usize::from_ne_bytes` - --> tests/ui/endian_bytes.rs:33:9 + --> tests/ui/endian_bytes.rs:57:9 | LL | usize::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -301,7 +301,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `isize::from_ne_bytes` - --> tests/ui/endian_bytes.rs:34:9 + --> tests/ui/endian_bytes.rs:59:9 | LL | isize::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -313,7 +313,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `f32::from_ne_bytes` - --> tests/ui/endian_bytes.rs:35:9 + --> tests/ui/endian_bytes.rs:61:9 | LL | f32::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -325,7 +325,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `f64::from_ne_bytes` - --> tests/ui/endian_bytes.rs:36:9 + --> tests/ui/endian_bytes.rs:63:9 | LL | f64::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -337,7 +337,7 @@ LL | fn host() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u8::to_le_bytes` method - --> tests/ui/endian_bytes.rs:38:9 + --> tests/ui/endian_bytes.rs:66:9 | LL | 2u8.to_le_bytes(); | ^^^^^^^^^^^^^^^^^ @@ -351,7 +351,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `i8::to_le_bytes` method - --> tests/ui/endian_bytes.rs:39:9 + --> tests/ui/endian_bytes.rs:68:9 | LL | 2i8.to_le_bytes(); | ^^^^^^^^^^^^^^^^^ @@ -363,7 +363,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u16::to_le_bytes` method - --> tests/ui/endian_bytes.rs:40:9 + --> tests/ui/endian_bytes.rs:70:9 | LL | 2u16.to_le_bytes(); | ^^^^^^^^^^^^^^^^^^ @@ -375,7 +375,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `i16::to_le_bytes` method - --> tests/ui/endian_bytes.rs:41:9 + --> tests/ui/endian_bytes.rs:72:9 | LL | 2i16.to_le_bytes(); | ^^^^^^^^^^^^^^^^^^ @@ -387,7 +387,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u32::to_le_bytes` method - --> tests/ui/endian_bytes.rs:42:9 + --> tests/ui/endian_bytes.rs:74:9 | LL | 2u32.to_le_bytes(); | ^^^^^^^^^^^^^^^^^^ @@ -399,7 +399,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `i32::to_le_bytes` method - --> tests/ui/endian_bytes.rs:43:9 + --> tests/ui/endian_bytes.rs:76:9 | LL | 2i32.to_le_bytes(); | ^^^^^^^^^^^^^^^^^^ @@ -411,7 +411,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u64::to_le_bytes` method - --> tests/ui/endian_bytes.rs:44:9 + --> tests/ui/endian_bytes.rs:78:9 | LL | 2u64.to_le_bytes(); | ^^^^^^^^^^^^^^^^^^ @@ -423,7 +423,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `i64::to_le_bytes` method - --> tests/ui/endian_bytes.rs:45:9 + --> tests/ui/endian_bytes.rs:80:9 | LL | 2i64.to_le_bytes(); | ^^^^^^^^^^^^^^^^^^ @@ -435,7 +435,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u128::to_le_bytes` method - --> tests/ui/endian_bytes.rs:46:9 + --> tests/ui/endian_bytes.rs:82:9 | LL | 2u128.to_le_bytes(); | ^^^^^^^^^^^^^^^^^^^ @@ -447,7 +447,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `i128::to_le_bytes` method - --> tests/ui/endian_bytes.rs:47:9 + --> tests/ui/endian_bytes.rs:84:9 | LL | 2i128.to_le_bytes(); | ^^^^^^^^^^^^^^^^^^^ @@ -459,7 +459,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `f32::to_le_bytes` method - --> tests/ui/endian_bytes.rs:48:9 + --> tests/ui/endian_bytes.rs:86:9 | LL | 2.0f32.to_le_bytes(); | ^^^^^^^^^^^^^^^^^^^^ @@ -471,7 +471,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `f64::to_le_bytes` method - --> tests/ui/endian_bytes.rs:49:9 + --> tests/ui/endian_bytes.rs:88:9 | LL | 2.0f64.to_le_bytes(); | ^^^^^^^^^^^^^^^^^^^^ @@ -483,7 +483,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `usize::to_le_bytes` method - --> tests/ui/endian_bytes.rs:50:9 + --> tests/ui/endian_bytes.rs:90:9 | LL | 2usize.to_le_bytes(); | ^^^^^^^^^^^^^^^^^^^^ @@ -495,7 +495,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `isize::to_le_bytes` method - --> tests/ui/endian_bytes.rs:51:9 + --> tests/ui/endian_bytes.rs:92:9 | LL | 2isize.to_le_bytes(); | ^^^^^^^^^^^^^^^^^^^^ @@ -507,7 +507,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u8::from_le_bytes` - --> tests/ui/endian_bytes.rs:52:9 + --> tests/ui/endian_bytes.rs:94:9 | LL | u8::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -519,7 +519,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `i8::from_le_bytes` - --> tests/ui/endian_bytes.rs:53:9 + --> tests/ui/endian_bytes.rs:96:9 | LL | i8::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -531,7 +531,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u16::from_le_bytes` - --> tests/ui/endian_bytes.rs:54:9 + --> tests/ui/endian_bytes.rs:98:9 | LL | u16::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -543,7 +543,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `i16::from_le_bytes` - --> tests/ui/endian_bytes.rs:55:9 + --> tests/ui/endian_bytes.rs:100:9 | LL | i16::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -555,7 +555,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u32::from_le_bytes` - --> tests/ui/endian_bytes.rs:56:9 + --> tests/ui/endian_bytes.rs:102:9 | LL | u32::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -567,7 +567,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `i32::from_le_bytes` - --> tests/ui/endian_bytes.rs:57:9 + --> tests/ui/endian_bytes.rs:104:9 | LL | i32::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -579,7 +579,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u64::from_le_bytes` - --> tests/ui/endian_bytes.rs:58:9 + --> tests/ui/endian_bytes.rs:106:9 | LL | u64::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -591,7 +591,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `i64::from_le_bytes` - --> tests/ui/endian_bytes.rs:59:9 + --> tests/ui/endian_bytes.rs:108:9 | LL | i64::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -603,7 +603,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u128::from_le_bytes` - --> tests/ui/endian_bytes.rs:60:9 + --> tests/ui/endian_bytes.rs:110:9 | LL | u128::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -615,7 +615,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `i128::from_le_bytes` - --> tests/ui/endian_bytes.rs:61:9 + --> tests/ui/endian_bytes.rs:112:9 | LL | i128::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -627,7 +627,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `usize::from_le_bytes` - --> tests/ui/endian_bytes.rs:62:9 + --> tests/ui/endian_bytes.rs:114:9 | LL | usize::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -639,7 +639,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `isize::from_le_bytes` - --> tests/ui/endian_bytes.rs:63:9 + --> tests/ui/endian_bytes.rs:116:9 | LL | isize::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -651,7 +651,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `f32::from_le_bytes` - --> tests/ui/endian_bytes.rs:64:9 + --> tests/ui/endian_bytes.rs:118:9 | LL | f32::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -663,7 +663,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `f64::from_le_bytes` - --> tests/ui/endian_bytes.rs:65:9 + --> tests/ui/endian_bytes.rs:120:9 | LL | f64::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -675,7 +675,7 @@ LL | fn little() { fn_body!(); } = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u8::to_ne_bytes` method - --> tests/ui/endian_bytes.rs:72:9 + --> tests/ui/endian_bytes.rs:128:9 | LL | 2u8.to_ne_bytes(); | ^^^^^^^^^^^^^^^^^ @@ -687,7 +687,7 @@ LL | fn host_encourage_little() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u8::from_ne_bytes` - --> tests/ui/endian_bytes.rs:73:9 + --> tests/ui/endian_bytes.rs:134:9 | LL | u8::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -699,7 +699,7 @@ LL | fn host_encourage_little() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u8::to_be_bytes` method - --> tests/ui/endian_bytes.rs:78:9 + --> tests/ui/endian_bytes.rs:154:9 | LL | 2u8.to_be_bytes(); | ^^^^^^^^^^^^^^^^^ @@ -713,7 +713,7 @@ LL | fn host_encourage_little() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u8::from_be_bytes` - --> tests/ui/endian_bytes.rs:79:9 + --> tests/ui/endian_bytes.rs:160:9 | LL | u8::from_be_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -725,7 +725,7 @@ LL | fn host_encourage_little() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u8::to_ne_bytes` method - --> tests/ui/endian_bytes.rs:72:9 + --> tests/ui/endian_bytes.rs:128:9 | LL | 2u8.to_ne_bytes(); | ^^^^^^^^^^^^^^^^^ @@ -737,7 +737,7 @@ LL | fn host_encourage_big() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u8::from_ne_bytes` - --> tests/ui/endian_bytes.rs:73:9 + --> tests/ui/endian_bytes.rs:134:9 | LL | u8::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -749,7 +749,7 @@ LL | fn host_encourage_big() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u8::to_le_bytes` method - --> tests/ui/endian_bytes.rs:75:9 + --> tests/ui/endian_bytes.rs:141:9 | LL | 2u8.to_le_bytes(); | ^^^^^^^^^^^^^^^^^ @@ -761,7 +761,7 @@ LL | fn host_encourage_big() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u8::from_le_bytes` - --> tests/ui/endian_bytes.rs:76:9 + --> tests/ui/endian_bytes.rs:147:9 | LL | u8::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -773,7 +773,7 @@ LL | fn host_encourage_big() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u8::to_ne_bytes` method - --> tests/ui/endian_bytes.rs:72:9 + --> tests/ui/endian_bytes.rs:128:9 | LL | 2u8.to_ne_bytes(); | ^^^^^^^^^^^^^^^^^ @@ -784,7 +784,7 @@ LL | fn no_help() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u8::from_ne_bytes` - --> tests/ui/endian_bytes.rs:73:9 + --> tests/ui/endian_bytes.rs:134:9 | LL | u8::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -795,7 +795,7 @@ LL | fn no_help() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u8::to_le_bytes` method - --> tests/ui/endian_bytes.rs:75:9 + --> tests/ui/endian_bytes.rs:141:9 | LL | 2u8.to_le_bytes(); | ^^^^^^^^^^^^^^^^^ @@ -806,7 +806,7 @@ LL | fn no_help() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u8::from_le_bytes` - --> tests/ui/endian_bytes.rs:76:9 + --> tests/ui/endian_bytes.rs:147:9 | LL | u8::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -817,7 +817,7 @@ LL | fn no_help() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u8::to_be_bytes` method - --> tests/ui/endian_bytes.rs:78:9 + --> tests/ui/endian_bytes.rs:154:9 | LL | 2u8.to_be_bytes(); | ^^^^^^^^^^^^^^^^^ @@ -828,7 +828,7 @@ LL | fn no_help() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u8::from_be_bytes` - --> tests/ui/endian_bytes.rs:79:9 + --> tests/ui/endian_bytes.rs:160:9 | LL | u8::from_be_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -839,7 +839,7 @@ LL | fn no_help() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u8::to_le_bytes` method - --> tests/ui/endian_bytes.rs:75:9 + --> tests/ui/endian_bytes.rs:141:9 | LL | 2u8.to_le_bytes(); | ^^^^^^^^^^^^^^^^^ @@ -851,7 +851,7 @@ LL | fn little_encourage_host() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u8::from_le_bytes` - --> tests/ui/endian_bytes.rs:76:9 + --> tests/ui/endian_bytes.rs:147:9 | LL | u8::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -863,7 +863,7 @@ LL | fn little_encourage_host() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u8::to_be_bytes` method - --> tests/ui/endian_bytes.rs:78:9 + --> tests/ui/endian_bytes.rs:154:9 | LL | 2u8.to_be_bytes(); | ^^^^^^^^^^^^^^^^^ @@ -875,7 +875,7 @@ LL | fn little_encourage_host() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u8::from_be_bytes` - --> tests/ui/endian_bytes.rs:79:9 + --> tests/ui/endian_bytes.rs:160:9 | LL | u8::from_be_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -887,7 +887,7 @@ LL | fn little_encourage_host() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u8::to_ne_bytes` method - --> tests/ui/endian_bytes.rs:72:9 + --> tests/ui/endian_bytes.rs:128:9 | LL | 2u8.to_ne_bytes(); | ^^^^^^^^^^^^^^^^^ @@ -899,7 +899,7 @@ LL | fn little_encourage_big() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u8::from_ne_bytes` - --> tests/ui/endian_bytes.rs:73:9 + --> tests/ui/endian_bytes.rs:134:9 | LL | u8::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -911,7 +911,7 @@ LL | fn little_encourage_big() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u8::to_le_bytes` method - --> tests/ui/endian_bytes.rs:75:9 + --> tests/ui/endian_bytes.rs:141:9 | LL | 2u8.to_le_bytes(); | ^^^^^^^^^^^^^^^^^ @@ -923,7 +923,7 @@ LL | fn little_encourage_big() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u8::from_le_bytes` - --> tests/ui/endian_bytes.rs:76:9 + --> tests/ui/endian_bytes.rs:147:9 | LL | u8::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -935,7 +935,7 @@ LL | fn little_encourage_big() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u8::to_le_bytes` method - --> tests/ui/endian_bytes.rs:75:9 + --> tests/ui/endian_bytes.rs:141:9 | LL | 2u8.to_le_bytes(); | ^^^^^^^^^^^^^^^^^ @@ -947,7 +947,7 @@ LL | fn big_encourage_host() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u8::from_le_bytes` - --> tests/ui/endian_bytes.rs:76:9 + --> tests/ui/endian_bytes.rs:147:9 | LL | u8::from_le_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -959,7 +959,7 @@ LL | fn big_encourage_host() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u8::to_be_bytes` method - --> tests/ui/endian_bytes.rs:78:9 + --> tests/ui/endian_bytes.rs:154:9 | LL | 2u8.to_be_bytes(); | ^^^^^^^^^^^^^^^^^ @@ -971,7 +971,7 @@ LL | fn big_encourage_host() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u8::from_be_bytes` - --> tests/ui/endian_bytes.rs:79:9 + --> tests/ui/endian_bytes.rs:160:9 | LL | u8::from_be_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -983,7 +983,7 @@ LL | fn big_encourage_host() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u8::to_ne_bytes` method - --> tests/ui/endian_bytes.rs:72:9 + --> tests/ui/endian_bytes.rs:128:9 | LL | 2u8.to_ne_bytes(); | ^^^^^^^^^^^^^^^^^ @@ -995,7 +995,7 @@ LL | fn big_encourage_little() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u8::from_ne_bytes` - --> tests/ui/endian_bytes.rs:73:9 + --> tests/ui/endian_bytes.rs:134:9 | LL | u8::from_ne_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1007,7 +1007,7 @@ LL | fn big_encourage_little() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the `u8::to_be_bytes` method - --> tests/ui/endian_bytes.rs:78:9 + --> tests/ui/endian_bytes.rs:154:9 | LL | 2u8.to_be_bytes(); | ^^^^^^^^^^^^^^^^^ @@ -1019,7 +1019,7 @@ LL | fn big_encourage_little() { fn_body_smol!(); } = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the function `u8::from_be_bytes` - --> tests/ui/endian_bytes.rs:79:9 + --> tests/ui/endian_bytes.rs:160:9 | LL | u8::from_be_bytes(todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/entry.fixed b/tests/ui/entry.fixed index abdfae2a3e13..69452a8d9a67 100644 --- a/tests/ui/entry.fixed +++ b/tests/ui/entry.fixed @@ -25,6 +25,7 @@ fn hash_map(m: &mut HashMap, m2: &mut HashMa // semicolon on insert, use or_insert_with(..) m.entry(k).or_insert_with(|| { + //~^ map_entry if true { v } else { @@ -34,6 +35,7 @@ fn hash_map(m: &mut HashMap, m2: &mut HashMa // semicolon on if, use or_insert_with(..) m.entry(k).or_insert_with(|| { + //~^ map_entry if true { v } else { @@ -43,6 +45,7 @@ fn hash_map(m: &mut HashMap, m2: &mut HashMa // early return, use if let if let std::collections::hash_map::Entry::Vacant(e) = m.entry(k) { + //~^ map_entry if true { e.insert(v); } else { @@ -53,12 +56,14 @@ fn hash_map(m: &mut HashMap, m2: &mut HashMa // use or_insert_with(..) m.entry(k).or_insert_with(|| { + //~^ map_entry foo(); v }); // semicolon on insert and match, use or_insert_with(..) m.entry(k).or_insert_with(|| { + //~^ map_entry match 0 { 1 if true => { v @@ -71,6 +76,7 @@ fn hash_map(m: &mut HashMap, m2: &mut HashMa // one branch doesn't insert, use if let if let std::collections::hash_map::Entry::Vacant(e) = m.entry(k) { + //~^ map_entry match 0 { 0 => foo(), _ => { @@ -81,6 +87,7 @@ fn hash_map(m: &mut HashMap, m2: &mut HashMa // use or_insert_with m.entry(k).or_insert_with(|| { + //~^ map_entry foo(); match 0 { 0 if false => { @@ -145,6 +152,7 @@ fn hash_map(m: &mut HashMap, m2: &mut HashMa // or_insert_with. Partial move of a local declared in the closure is ok. m.entry(k).or_insert_with(|| { + //~^ map_entry let x = (String::new(), String::new()); let _ = x.0; v @@ -178,6 +186,7 @@ pub fn issue_11935() { fn issue12489(map: &mut HashMap) -> Option<()> { if let std::collections::hash_map::Entry::Vacant(e) = map.entry(1) { + //~^ map_entry let Some(1) = Some(2) else { return None; }; @@ -186,4 +195,35 @@ fn issue12489(map: &mut HashMap) -> Option<()> { Some(()) } +mod issue13934 { + use std::collections::HashMap; + + struct Member {} + + pub struct Foo { + members: HashMap, + } + + impl Foo { + pub fn should_also_not_cause_lint(&mut self, input: u8) { + if self.members.contains_key(&input) { + todo!(); + } else { + self.other(); + self.members.insert(input, Member {}); + } + } + + fn other(&self) {} + } +} + +fn issue11976() { + let mut hashmap = std::collections::HashMap::new(); + if !hashmap.contains_key(&0) { + let _ = || hashmap.get(&0); + hashmap.insert(0, 0); + } +} + fn main() {} diff --git a/tests/ui/entry.rs b/tests/ui/entry.rs index 7774f99a2a22..3578324f01c5 100644 --- a/tests/ui/entry.rs +++ b/tests/ui/entry.rs @@ -22,11 +22,13 @@ fn foo() {} fn hash_map(m: &mut HashMap, m2: &mut HashMap, k: K, k2: K, v: V, v2: V) { // or_insert(v) if !m.contains_key(&k) { + //~^ map_entry m.insert(k, v); } // semicolon on insert, use or_insert_with(..) if !m.contains_key(&k) { + //~^ map_entry if true { m.insert(k, v); } else { @@ -36,6 +38,7 @@ fn hash_map(m: &mut HashMap, m2: &mut HashMa // semicolon on if, use or_insert_with(..) if !m.contains_key(&k) { + //~^ map_entry if true { m.insert(k, v) } else { @@ -45,6 +48,7 @@ fn hash_map(m: &mut HashMap, m2: &mut HashMa // early return, use if let if !m.contains_key(&k) { + //~^ map_entry if true { m.insert(k, v); } else { @@ -55,12 +59,14 @@ fn hash_map(m: &mut HashMap, m2: &mut HashMa // use or_insert_with(..) if !m.contains_key(&k) { + //~^ map_entry foo(); m.insert(k, v); } // semicolon on insert and match, use or_insert_with(..) if !m.contains_key(&k) { + //~^ map_entry match 0 { 1 if true => { m.insert(k, v); @@ -73,6 +79,7 @@ fn hash_map(m: &mut HashMap, m2: &mut HashMa // one branch doesn't insert, use if let if !m.contains_key(&k) { + //~^ map_entry match 0 { 0 => foo(), _ => { @@ -83,6 +90,7 @@ fn hash_map(m: &mut HashMap, m2: &mut HashMa // use or_insert_with if !m.contains_key(&k) { + //~^ map_entry foo(); match 0 { 0 if false => { @@ -117,6 +125,7 @@ fn hash_map(m: &mut HashMap, m2: &mut HashMa // macro_expansion test, use or_insert(..) if !m.contains_key(&m!(k)) { + //~^ map_entry m.insert(m!(k), m!(v)); } @@ -149,6 +158,7 @@ fn hash_map(m: &mut HashMap, m2: &mut HashMa // or_insert_with. Partial move of a local declared in the closure is ok. if !m.contains_key(&k) { + //~^ map_entry let x = (String::new(), String::new()); let _ = x.0; m.insert(k, v); @@ -182,6 +192,7 @@ pub fn issue_11935() { fn issue12489(map: &mut HashMap) -> Option<()> { if !map.contains_key(&1) { + //~^ map_entry let Some(1) = Some(2) else { return None; }; @@ -190,4 +201,35 @@ fn issue12489(map: &mut HashMap) -> Option<()> { Some(()) } +mod issue13934 { + use std::collections::HashMap; + + struct Member {} + + pub struct Foo { + members: HashMap, + } + + impl Foo { + pub fn should_also_not_cause_lint(&mut self, input: u8) { + if self.members.contains_key(&input) { + todo!(); + } else { + self.other(); + self.members.insert(input, Member {}); + } + } + + fn other(&self) {} + } +} + +fn issue11976() { + let mut hashmap = std::collections::HashMap::new(); + if !hashmap.contains_key(&0) { + let _ = || hashmap.get(&0); + hashmap.insert(0, 0); + } +} + fn main() {} diff --git a/tests/ui/entry.stderr b/tests/ui/entry.stderr index 4b6bd3b4a258..009b78d29073 100644 --- a/tests/ui/entry.stderr +++ b/tests/ui/entry.stderr @@ -2,6 +2,7 @@ error: usage of `contains_key` followed by `insert` on a `HashMap` --> tests/ui/entry.rs:24:5 | LL | / if !m.contains_key(&k) { +LL | | LL | | m.insert(k, v); LL | | } | |_____^ help: try: `m.entry(k).or_insert(v);` @@ -10,12 +11,12 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::map_entry)]` error: usage of `contains_key` followed by `insert` on a `HashMap` - --> tests/ui/entry.rs:29:5 + --> tests/ui/entry.rs:30:5 | LL | / if !m.contains_key(&k) { +LL | | LL | | if true { LL | | m.insert(k, v); -LL | | } else { ... | LL | | } | |_____^ @@ -23,6 +24,7 @@ LL | | } help: try | LL ~ m.entry(k).or_insert_with(|| { +LL + LL + if true { LL + v LL + } else { @@ -32,13 +34,13 @@ LL + }); | error: usage of `contains_key` followed by `insert` on a `HashMap` - --> tests/ui/entry.rs:38:5 + --> tests/ui/entry.rs:40:5 | LL | / if !m.contains_key(&k) { +LL | | LL | | if true { LL | | m.insert(k, v) -LL | | } else { -LL | | m.insert(k, v2) +... | LL | | }; LL | | } | |_____^ @@ -46,6 +48,7 @@ LL | | } help: try | LL ~ m.entry(k).or_insert_with(|| { +LL + LL + if true { LL + v LL + } else { @@ -55,12 +58,12 @@ LL + }); | error: usage of `contains_key` followed by `insert` on a `HashMap` - --> tests/ui/entry.rs:47:5 + --> tests/ui/entry.rs:50:5 | LL | / if !m.contains_key(&k) { +LL | | LL | | if true { LL | | m.insert(k, v); -LL | | } else { ... | LL | | } | |_____^ @@ -68,6 +71,7 @@ LL | | } help: try | LL ~ if let std::collections::hash_map::Entry::Vacant(e) = m.entry(k) { +LL + LL + if true { LL + e.insert(v); LL + } else { @@ -78,9 +82,10 @@ LL + } | error: usage of `contains_key` followed by `insert` on a `HashMap` - --> tests/ui/entry.rs:57:5 + --> tests/ui/entry.rs:61:5 | LL | / if !m.contains_key(&k) { +LL | | LL | | foo(); LL | | m.insert(k, v); LL | | } @@ -89,18 +94,19 @@ LL | | } help: try | LL ~ m.entry(k).or_insert_with(|| { +LL + LL + foo(); LL + v LL + }); | error: usage of `contains_key` followed by `insert` on a `HashMap` - --> tests/ui/entry.rs:63:5 + --> tests/ui/entry.rs:68:5 | LL | / if !m.contains_key(&k) { +LL | | LL | | match 0 { LL | | 1 if true => { -LL | | m.insert(k, v); ... | LL | | }; LL | | } @@ -109,6 +115,7 @@ LL | | } help: try | LL ~ m.entry(k).or_insert_with(|| { +LL + LL + match 0 { LL + 1 if true => { LL + v @@ -121,12 +128,12 @@ LL + }); | error: usage of `contains_key` followed by `insert` on a `HashMap` - --> tests/ui/entry.rs:75:5 + --> tests/ui/entry.rs:81:5 | LL | / if !m.contains_key(&k) { +LL | | LL | | match 0 { LL | | 0 => foo(), -LL | | _ => { ... | LL | | }; LL | | } @@ -135,6 +142,7 @@ LL | | } help: try | LL ~ if let std::collections::hash_map::Entry::Vacant(e) = m.entry(k) { +LL + LL + match 0 { LL + 0 => foo(), LL + _ => { @@ -145,12 +153,12 @@ LL + } | error: usage of `contains_key` followed by `insert` on a `HashMap` - --> tests/ui/entry.rs:85:5 + --> tests/ui/entry.rs:92:5 | LL | / if !m.contains_key(&k) { +LL | | LL | | foo(); LL | | match 0 { -LL | | 0 if false => { ... | LL | | } | |_____^ @@ -158,6 +166,7 @@ LL | | } help: try | LL ~ m.entry(k).or_insert_with(|| { +LL + LL + foo(); LL + match 0 { LL + 0 if false => { @@ -185,17 +194,19 @@ LL + }); | error: usage of `contains_key` followed by `insert` on a `HashMap` - --> tests/ui/entry.rs:119:5 + --> tests/ui/entry.rs:127:5 | LL | / if !m.contains_key(&m!(k)) { +LL | | LL | | m.insert(m!(k), m!(v)); LL | | } | |_____^ help: try: `m.entry(m!(k)).or_insert_with(|| m!(v));` error: usage of `contains_key` followed by `insert` on a `HashMap` - --> tests/ui/entry.rs:151:5 + --> tests/ui/entry.rs:160:5 | LL | / if !m.contains_key(&k) { +LL | | LL | | let x = (String::new(), String::new()); LL | | let _ = x.0; LL | | m.insert(k, v); @@ -205,6 +216,7 @@ LL | | } help: try | LL ~ m.entry(k).or_insert_with(|| { +LL + LL + let x = (String::new(), String::new()); LL + let _ = x.0; LL + v @@ -212,9 +224,10 @@ LL + }); | error: usage of `contains_key` followed by `insert` on a `HashMap` - --> tests/ui/entry.rs:184:5 + --> tests/ui/entry.rs:194:5 | LL | / if !map.contains_key(&1) { +LL | | LL | | let Some(1) = Some(2) else { LL | | return None; LL | | }; @@ -225,6 +238,7 @@ LL | | } help: try | LL ~ if let std::collections::hash_map::Entry::Vacant(e) = map.entry(1) { +LL + LL + let Some(1) = Some(2) else { LL + return None; LL + }; diff --git a/tests/ui/entry_btree.fixed b/tests/ui/entry_btree.fixed index 228212c79eaf..1218202f02b9 100644 --- a/tests/ui/entry_btree.fixed +++ b/tests/ui/entry_btree.fixed @@ -8,6 +8,7 @@ fn foo() {} fn btree_map(m: &mut BTreeMap, k: K, v: V) { // insert then do something, use if let if let std::collections::btree_map::Entry::Vacant(e) = m.entry(k) { + //~^ map_entry e.insert(v); foo(); } diff --git a/tests/ui/entry_btree.rs b/tests/ui/entry_btree.rs index 44703c567113..b795e32158ad 100644 --- a/tests/ui/entry_btree.rs +++ b/tests/ui/entry_btree.rs @@ -8,6 +8,7 @@ fn foo() {} fn btree_map(m: &mut BTreeMap, k: K, v: V) { // insert then do something, use if let if !m.contains_key(&k) { + //~^ map_entry m.insert(k, v); foo(); } diff --git a/tests/ui/entry_btree.stderr b/tests/ui/entry_btree.stderr index 290e6b788054..671340b89532 100644 --- a/tests/ui/entry_btree.stderr +++ b/tests/ui/entry_btree.stderr @@ -2,6 +2,7 @@ error: usage of `contains_key` followed by `insert` on a `BTreeMap` --> tests/ui/entry_btree.rs:10:5 | LL | / if !m.contains_key(&k) { +LL | | LL | | m.insert(k, v); LL | | foo(); LL | | } @@ -12,6 +13,7 @@ LL | | } help: try | LL ~ if let std::collections::btree_map::Entry::Vacant(e) = m.entry(k) { +LL + LL + e.insert(v); LL + foo(); LL + } diff --git a/tests/ui/entry_with_else.fixed b/tests/ui/entry_with_else.fixed index 34804b9ee5d7..76e6998235c2 100644 --- a/tests/ui/entry_with_else.fixed +++ b/tests/ui/entry_with_else.fixed @@ -13,6 +13,7 @@ fn foo() {} fn insert_if_absent0(m: &mut HashMap, k: K, v: V, v2: V) { match m.entry(k) { std::collections::hash_map::Entry::Vacant(e) => { + //~^ map_entry e.insert(v); } std::collections::hash_map::Entry::Occupied(mut e) => { @@ -22,6 +23,7 @@ fn insert_if_absent0(m: &mut HashMap, k: K, match m.entry(k) { std::collections::hash_map::Entry::Occupied(mut e) => { + //~^ map_entry e.insert(v); } std::collections::hash_map::Entry::Vacant(e) => { @@ -30,6 +32,7 @@ fn insert_if_absent0(m: &mut HashMap, k: K, } if let std::collections::hash_map::Entry::Vacant(e) = m.entry(k) { + //~^ map_entry e.insert(v); } else { foo(); @@ -38,11 +41,13 @@ fn insert_if_absent0(m: &mut HashMap, k: K, if let std::collections::hash_map::Entry::Occupied(mut e) = m.entry(k) { e.insert(v); } else { + //~^ map_entry foo(); } match m.entry(k) { std::collections::hash_map::Entry::Vacant(e) => { + //~^ map_entry e.insert(v); } std::collections::hash_map::Entry::Occupied(mut e) => { @@ -52,6 +57,7 @@ fn insert_if_absent0(m: &mut HashMap, k: K, match m.entry(k) { std::collections::hash_map::Entry::Occupied(mut e) => { + //~^ map_entry if true { Some(e.insert(v)) } else { Some(e.insert(v2)) } } std::collections::hash_map::Entry::Vacant(e) => { @@ -61,6 +67,7 @@ fn insert_if_absent0(m: &mut HashMap, k: K, }; if let std::collections::hash_map::Entry::Occupied(mut e) = m.entry(k) { + //~^ map_entry foo(); Some(e.insert(v)) } else { diff --git a/tests/ui/entry_with_else.rs b/tests/ui/entry_with_else.rs index 0515748fd733..1669cdc0c7cf 100644 --- a/tests/ui/entry_with_else.rs +++ b/tests/ui/entry_with_else.rs @@ -12,42 +12,49 @@ fn foo() {} fn insert_if_absent0(m: &mut HashMap, k: K, v: V, v2: V) { if !m.contains_key(&k) { + //~^ map_entry m.insert(k, v); } else { m.insert(k, v2); } if m.contains_key(&k) { + //~^ map_entry m.insert(k, v); } else { m.insert(k, v2); } if !m.contains_key(&k) { + //~^ map_entry m.insert(k, v); } else { foo(); } if !m.contains_key(&k) { + //~^ map_entry foo(); } else { m.insert(k, v); } if !m.contains_key(&k) { + //~^ map_entry m.insert(k, v); } else { m.insert(k, v2); } if m.contains_key(&k) { + //~^ map_entry if true { m.insert(k, v) } else { m.insert(k, v2) } } else { m.insert(k, v) }; if m.contains_key(&k) { + //~^ map_entry foo(); m.insert(k, v) } else { diff --git a/tests/ui/entry_with_else.stderr b/tests/ui/entry_with_else.stderr index 26b21b076b6c..d483ac95ad5b 100644 --- a/tests/ui/entry_with_else.stderr +++ b/tests/ui/entry_with_else.stderr @@ -2,6 +2,7 @@ error: usage of `contains_key` followed by `insert` on a `HashMap` --> tests/ui/entry_with_else.rs:14:5 | LL | / if !m.contains_key(&k) { +LL | | LL | | m.insert(k, v); LL | | } else { LL | | m.insert(k, v2); @@ -14,6 +15,7 @@ help: try | LL ~ match m.entry(k) { LL + std::collections::hash_map::Entry::Vacant(e) => { +LL + LL + e.insert(v); LL + } LL + std::collections::hash_map::Entry::Occupied(mut e) => { @@ -23,9 +25,10 @@ LL + } | error: usage of `contains_key` followed by `insert` on a `HashMap` - --> tests/ui/entry_with_else.rs:20:5 + --> tests/ui/entry_with_else.rs:21:5 | LL | / if m.contains_key(&k) { +LL | | LL | | m.insert(k, v); LL | | } else { LL | | m.insert(k, v2); @@ -36,6 +39,7 @@ help: try | LL ~ match m.entry(k) { LL + std::collections::hash_map::Entry::Occupied(mut e) => { +LL + LL + e.insert(v); LL + } LL + std::collections::hash_map::Entry::Vacant(e) => { @@ -45,9 +49,10 @@ LL + } | error: usage of `contains_key` followed by `insert` on a `HashMap` - --> tests/ui/entry_with_else.rs:26:5 + --> tests/ui/entry_with_else.rs:28:5 | LL | / if !m.contains_key(&k) { +LL | | LL | | m.insert(k, v); LL | | } else { LL | | foo(); @@ -57,6 +62,7 @@ LL | | } help: try | LL ~ if let std::collections::hash_map::Entry::Vacant(e) = m.entry(k) { +LL + LL + e.insert(v); LL + } else { LL + foo(); @@ -64,9 +70,10 @@ LL + } | error: usage of `contains_key` followed by `insert` on a `HashMap` - --> tests/ui/entry_with_else.rs:32:5 + --> tests/ui/entry_with_else.rs:35:5 | LL | / if !m.contains_key(&k) { +LL | | LL | | foo(); LL | | } else { LL | | m.insert(k, v); @@ -78,14 +85,16 @@ help: try LL ~ if let std::collections::hash_map::Entry::Occupied(mut e) = m.entry(k) { LL + e.insert(v); LL + } else { +LL + LL + foo(); LL + } | error: usage of `contains_key` followed by `insert` on a `HashMap` - --> tests/ui/entry_with_else.rs:38:5 + --> tests/ui/entry_with_else.rs:42:5 | LL | / if !m.contains_key(&k) { +LL | | LL | | m.insert(k, v); LL | | } else { LL | | m.insert(k, v2); @@ -96,6 +105,7 @@ help: try | LL ~ match m.entry(k) { LL + std::collections::hash_map::Entry::Vacant(e) => { +LL + LL + e.insert(v); LL + } LL + std::collections::hash_map::Entry::Occupied(mut e) => { @@ -105,9 +115,10 @@ LL + } | error: usage of `contains_key` followed by `insert` on a `HashMap` - --> tests/ui/entry_with_else.rs:44:5 + --> tests/ui/entry_with_else.rs:49:5 | LL | / if m.contains_key(&k) { +LL | | LL | | if true { m.insert(k, v) } else { m.insert(k, v2) } LL | | } else { LL | | m.insert(k, v) @@ -118,6 +129,7 @@ help: try | LL ~ match m.entry(k) { LL + std::collections::hash_map::Entry::Occupied(mut e) => { +LL + LL + if true { Some(e.insert(v)) } else { Some(e.insert(v2)) } LL + } LL + std::collections::hash_map::Entry::Vacant(e) => { @@ -128,9 +140,10 @@ LL ~ }; | error: usage of `contains_key` followed by `insert` on a `HashMap` - --> tests/ui/entry_with_else.rs:50:5 + --> tests/ui/entry_with_else.rs:56:5 | LL | / if m.contains_key(&k) { +LL | | LL | | foo(); LL | | m.insert(k, v) LL | | } else { @@ -141,6 +154,7 @@ LL | | }; help: try | LL ~ if let std::collections::hash_map::Entry::Occupied(mut e) = m.entry(k) { +LL + LL + foo(); LL + Some(e.insert(v)) LL + } else { diff --git a/tests/ui/enum_clike_unportable_variant.rs b/tests/ui/enum_clike_unportable_variant.rs index 37849179d6a0..4ff2024b25e9 100644 --- a/tests/ui/enum_clike_unportable_variant.rs +++ b/tests/ui/enum_clike_unportable_variant.rs @@ -6,8 +6,7 @@ #[repr(usize)] enum NonPortable { X = 0x1_0000_0000, - //~^ ERROR: C-like enum variant discriminant is not portable to 32-bit targets - //~| NOTE: `-D clippy::enum-clike-unportable-variant` implied by `-D warnings` + //~^ enum_clike_unportable_variant Y = 0, Z = 0x7FFF_FFFF, A = 0xFFFF_FFFF, @@ -15,11 +14,11 @@ enum NonPortable { enum NonPortableNoHint { X = 0x1_0000_0000, - //~^ ERROR: C-like enum variant discriminant is not portable to 32-bit targets + //~^ enum_clike_unportable_variant Y = 0, Z = 0x7FFF_FFFF, A = 0xFFFF_FFFF, - //~^ ERROR: C-like enum variant discriminant is not portable to 32-bit targets + //~^ enum_clike_unportable_variant } #[repr(isize)] @@ -27,27 +26,27 @@ enum NonPortableSigned { X = -1, Y = 0x7FFF_FFFF, Z = 0xFFFF_FFFF, - //~^ ERROR: C-like enum variant discriminant is not portable to 32-bit targets + //~^ enum_clike_unportable_variant A = 0x1_0000_0000, - //~^ ERROR: C-like enum variant discriminant is not portable to 32-bit targets + //~^ enum_clike_unportable_variant B = i32::MIN as isize, C = (i32::MIN as isize) - 1, - //~^ ERROR: C-like enum variant discriminant is not portable to 32-bit targets + //~^ enum_clike_unportable_variant } enum NonPortableSignedNoHint { X = -1, Y = 0x7FFF_FFFF, Z = 0xFFFF_FFFF, - //~^ ERROR: C-like enum variant discriminant is not portable to 32-bit targets + //~^ enum_clike_unportable_variant A = 0x1_0000_0000, - //~^ ERROR: C-like enum variant discriminant is not portable to 32-bit targets + //~^ enum_clike_unportable_variant } #[repr(usize)] enum NonPortable2 { X = ::Number, - //~^ ERROR: C-like enum variant discriminant is not portable to 32-bit targets + //~^ enum_clike_unportable_variant Y = 0, } diff --git a/tests/ui/enum_clike_unportable_variant.stderr b/tests/ui/enum_clike_unportable_variant.stderr index 741de179a497..5a022a6fe8a6 100644 --- a/tests/ui/enum_clike_unportable_variant.stderr +++ b/tests/ui/enum_clike_unportable_variant.stderr @@ -8,49 +8,49 @@ LL | X = 0x1_0000_0000, = help: to override `-D warnings` add `#[allow(clippy::enum_clike_unportable_variant)]` error: C-like enum variant discriminant is not portable to 32-bit targets - --> tests/ui/enum_clike_unportable_variant.rs:17:5 + --> tests/ui/enum_clike_unportable_variant.rs:16:5 | LL | X = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ error: C-like enum variant discriminant is not portable to 32-bit targets - --> tests/ui/enum_clike_unportable_variant.rs:21:5 + --> tests/ui/enum_clike_unportable_variant.rs:20:5 | LL | A = 0xFFFF_FFFF, | ^^^^^^^^^^^^^^^ error: C-like enum variant discriminant is not portable to 32-bit targets - --> tests/ui/enum_clike_unportable_variant.rs:29:5 + --> tests/ui/enum_clike_unportable_variant.rs:28:5 | LL | Z = 0xFFFF_FFFF, | ^^^^^^^^^^^^^^^ error: C-like enum variant discriminant is not portable to 32-bit targets - --> tests/ui/enum_clike_unportable_variant.rs:31:5 + --> tests/ui/enum_clike_unportable_variant.rs:30:5 | LL | A = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ error: C-like enum variant discriminant is not portable to 32-bit targets - --> tests/ui/enum_clike_unportable_variant.rs:34:5 + --> tests/ui/enum_clike_unportable_variant.rs:33:5 | LL | C = (i32::MIN as isize) - 1, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: C-like enum variant discriminant is not portable to 32-bit targets - --> tests/ui/enum_clike_unportable_variant.rs:41:5 + --> tests/ui/enum_clike_unportable_variant.rs:40:5 | LL | Z = 0xFFFF_FFFF, | ^^^^^^^^^^^^^^^ error: C-like enum variant discriminant is not portable to 32-bit targets - --> tests/ui/enum_clike_unportable_variant.rs:43:5 + --> tests/ui/enum_clike_unportable_variant.rs:42:5 | LL | A = 0x1_0000_0000, | ^^^^^^^^^^^^^^^^^ error: C-like enum variant discriminant is not portable to 32-bit targets - --> tests/ui/enum_clike_unportable_variant.rs:49:5 + --> tests/ui/enum_clike_unportable_variant.rs:48:5 | LL | X = ::Number, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/enum_glob_use.fixed b/tests/ui/enum_glob_use.fixed index 3c0db9beb1a6..881493f3d5ff 100644 --- a/tests/ui/enum_glob_use.fixed +++ b/tests/ui/enum_glob_use.fixed @@ -3,16 +3,19 @@ #![warn(unused_imports)] use std::cmp::Ordering::Less; +//~^ enum_glob_use enum Enum { Foo, } use self::Enum::Foo; +//~^ enum_glob_use mod in_fn_test { fn blarg() { use crate::Enum::Foo; + //~^ enum_glob_use let _ = Foo; } diff --git a/tests/ui/enum_glob_use.rs b/tests/ui/enum_glob_use.rs index 2538477f7978..a510462ecb2f 100644 --- a/tests/ui/enum_glob_use.rs +++ b/tests/ui/enum_glob_use.rs @@ -3,16 +3,19 @@ #![warn(unused_imports)] use std::cmp::Ordering::*; +//~^ enum_glob_use enum Enum { Foo, } use self::Enum::*; +//~^ enum_glob_use mod in_fn_test { fn blarg() { use crate::Enum::*; + //~^ enum_glob_use let _ = Foo; } diff --git a/tests/ui/enum_glob_use.stderr b/tests/ui/enum_glob_use.stderr index 6825383b769d..a2cef8008e21 100644 --- a/tests/ui/enum_glob_use.stderr +++ b/tests/ui/enum_glob_use.stderr @@ -8,13 +8,13 @@ LL | use std::cmp::Ordering::*; = help: to override `-D warnings` add `#[allow(clippy::enum_glob_use)]` error: usage of wildcard import for enum variants - --> tests/ui/enum_glob_use.rs:11:5 + --> tests/ui/enum_glob_use.rs:12:5 | LL | use self::Enum::*; | ^^^^^^^^^^^^^ help: try: `self::Enum::Foo` error: usage of wildcard import for enum variants - --> tests/ui/enum_glob_use.rs:15:13 + --> tests/ui/enum_glob_use.rs:17:13 | LL | use crate::Enum::*; | ^^^^^^^^^^^^^^ help: try: `crate::Enum::Foo` diff --git a/tests/ui/enum_variants.rs b/tests/ui/enum_variants.rs index ddf2dfdaea9b..f7bbf83654f1 100644 --- a/tests/ui/enum_variants.rs +++ b/tests/ui/enum_variants.rs @@ -12,10 +12,9 @@ enum FakeCallType2 { } enum Foo { - //~^ ERROR: all variants have the same prefix: `c` + //~^ enum_variant_names cFoo, - //~^ ERROR: variant name ends with the enum's name - //~| NOTE: `-D clippy::enum-variant-names` implied by `-D warnings` + //~^ enum_variant_names cBar, cBaz, } @@ -26,13 +25,13 @@ enum Fooo { } enum Food { - //~^ ERROR: all variants have the same prefix: `Food` + //~^ enum_variant_names FoodGood, - //~^ ERROR: variant name starts with the enum's name + //~^ enum_variant_names FoodMiddle, - //~^ ERROR: variant name starts with the enum's name + //~^ enum_variant_names FoodBad, - //~^ ERROR: variant name starts with the enum's name + //~^ enum_variant_names } enum Stuff { @@ -40,7 +39,7 @@ enum Stuff { } enum BadCallType { - //~^ ERROR: all variants have the same prefix: `CallType` + //~^ enum_variant_names CallTypeCall, CallTypeCreate, CallTypeDestroy, @@ -53,7 +52,7 @@ enum TwoCallType { } enum Consts { - //~^ ERROR: all variants have the same prefix: `Constant` + //~^ enum_variant_names ConstantInt, ConstantCake, ConstantLie, @@ -66,7 +65,7 @@ enum Two { } enum Something { - //~^ ERROR: all variants have the same prefix: `C` + //~^ enum_variant_names CCall, CCreate, CCryogenize, @@ -89,7 +88,7 @@ enum Sealll { } enum Seallll { - //~^ ERROR: all variants have the same prefix: `WithOut` + //~^ enum_variant_names WithOutCake, WithOutTea, WithOut, @@ -145,14 +144,14 @@ pub enum NetworkLayer { // should lint suggesting `IData`, not only `Data` (see #4639) enum IDataRequest { - //~^ ERROR: all variants have the same postfix: `IData` + //~^ enum_variant_names PutIData(String), GetIData(String), DeleteUnpubIData(String), } enum HIDataRequest { - //~^ ERROR: all variants have the same postfix: `HIData` + //~^ enum_variant_names PutHIData(String), GetHIData(String), DeleteUnpubHIData(String), @@ -173,7 +172,7 @@ enum Phase { mod issue9018 { enum DoLint { - //~^ ERROR: all variants have the same prefix: `_Type` + //~^ enum_variant_names _TypeCreate, _TypeRead, _TypeUpdate, @@ -181,7 +180,7 @@ mod issue9018 { } enum DoLintToo { - //~^ ERROR: all variants have the same postfix: `Type` + //~^ enum_variant_names _CreateType, _UpdateType, _DeleteType, @@ -210,12 +209,12 @@ mod issue11494 { Valid, Invalid, DataDependent, - //~^ ERROR: variant name starts with the enum's name + //~^ enum_variant_names } enum Datas { DatasDependent, - //~^ ERROR: variant name starts with the enum's name + //~^ enum_variant_names Valid, Invalid, } diff --git a/tests/ui/enum_variants.stderr b/tests/ui/enum_variants.stderr index ecca6c833ac5..cca9d50033cf 100644 --- a/tests/ui/enum_variants.stderr +++ b/tests/ui/enum_variants.stderr @@ -21,25 +21,25 @@ LL | | } = help: remove the prefixes and use full paths to the variants instead of glob imports error: variant name starts with the enum's name - --> tests/ui/enum_variants.rs:30:5 + --> tests/ui/enum_variants.rs:29:5 | LL | FoodGood, | ^^^^^^^^ error: variant name starts with the enum's name - --> tests/ui/enum_variants.rs:32:5 + --> tests/ui/enum_variants.rs:31:5 | LL | FoodMiddle, | ^^^^^^^^^^ error: variant name starts with the enum's name - --> tests/ui/enum_variants.rs:34:5 + --> tests/ui/enum_variants.rs:33:5 | LL | FoodBad, | ^^^^^^^ error: all variants have the same prefix: `Food` - --> tests/ui/enum_variants.rs:28:1 + --> tests/ui/enum_variants.rs:27:1 | LL | / enum Food { LL | | @@ -51,7 +51,7 @@ LL | | } = help: remove the prefixes and use full paths to the variants instead of glob imports error: all variants have the same prefix: `CallType` - --> tests/ui/enum_variants.rs:42:1 + --> tests/ui/enum_variants.rs:41:1 | LL | / enum BadCallType { LL | | @@ -64,7 +64,7 @@ LL | | } = help: remove the prefixes and use full paths to the variants instead of glob imports error: all variants have the same prefix: `Constant` - --> tests/ui/enum_variants.rs:55:1 + --> tests/ui/enum_variants.rs:54:1 | LL | / enum Consts { LL | | @@ -77,7 +77,7 @@ LL | | } = help: remove the prefixes and use full paths to the variants instead of glob imports error: all variants have the same prefix: `C` - --> tests/ui/enum_variants.rs:68:1 + --> tests/ui/enum_variants.rs:67:1 | LL | / enum Something { LL | | @@ -90,7 +90,7 @@ LL | | } = help: remove the prefixes and use full paths to the variants instead of glob imports error: all variants have the same prefix: `WithOut` - --> tests/ui/enum_variants.rs:91:1 + --> tests/ui/enum_variants.rs:90:1 | LL | / enum Seallll { LL | | @@ -103,7 +103,7 @@ LL | | } = help: remove the prefixes and use full paths to the variants instead of glob imports error: all variants have the same postfix: `IData` - --> tests/ui/enum_variants.rs:147:1 + --> tests/ui/enum_variants.rs:146:1 | LL | / enum IDataRequest { LL | | @@ -116,7 +116,7 @@ LL | | } = help: remove the postfixes and use full paths to the variants instead of glob imports error: all variants have the same postfix: `HIData` - --> tests/ui/enum_variants.rs:154:1 + --> tests/ui/enum_variants.rs:153:1 | LL | / enum HIDataRequest { LL | | @@ -129,7 +129,7 @@ LL | | } = help: remove the postfixes and use full paths to the variants instead of glob imports error: all variants have the same prefix: `_Type` - --> tests/ui/enum_variants.rs:175:5 + --> tests/ui/enum_variants.rs:174:5 | LL | / enum DoLint { LL | | @@ -143,7 +143,7 @@ LL | | } = help: remove the prefixes and use full paths to the variants instead of glob imports error: all variants have the same postfix: `Type` - --> tests/ui/enum_variants.rs:183:5 + --> tests/ui/enum_variants.rs:182:5 | LL | / enum DoLintToo { LL | | @@ -156,13 +156,13 @@ LL | | } = help: remove the postfixes and use full paths to the variants instead of glob imports error: variant name starts with the enum's name - --> tests/ui/enum_variants.rs:212:9 + --> tests/ui/enum_variants.rs:211:9 | LL | DataDependent, | ^^^^^^^^^^^^^ error: variant name starts with the enum's name - --> tests/ui/enum_variants.rs:217:9 + --> tests/ui/enum_variants.rs:216:9 | LL | DatasDependent, | ^^^^^^^^^^^^^^ diff --git a/tests/ui/eprint_with_newline.fixed b/tests/ui/eprint_with_newline.fixed index 7383d784c841..c50a707ace92 100644 --- a/tests/ui/eprint_with_newline.fixed +++ b/tests/ui/eprint_with_newline.fixed @@ -3,16 +3,19 @@ fn main() { eprintln!("Hello"); - //~^ ERROR: using `eprint!()` with a format string that ends in a single newline - //~| NOTE: `-D clippy::print-with-newline` implied by `-D warnings` + //~^ print_with_newline + eprintln!("Hello {}", "world"); - //~^ ERROR: using `eprint!()` with a format string that ends in a single newline + //~^ print_with_newline + eprintln!("Hello {} {}", "world", "#2"); - //~^ ERROR: using `eprint!()` with a format string that ends in a single newline + //~^ print_with_newline + eprintln!("{}", 1265); - //~^ ERROR: using `eprint!()` with a format string that ends in a single newline + //~^ print_with_newline + eprintln!(); - //~^ ERROR: using `eprint!()` with a format string that ends in a single newline + //~^ print_with_newline // these are all fine eprint!(""); @@ -35,7 +38,8 @@ fn main() { // #3514 eprint!("\\n"); eprintln!("\\"); - //~^ ERROR: using `eprint!()` with a format string that ends in a single newline + //~^ print_with_newline + eprint!("\\\\n"); // Raw strings @@ -44,11 +48,11 @@ fn main() { // Literal newlines should also fail eprintln!( - //~^ ERROR: using `eprint!()` with a format string that ends in a single newline + //~^ print_with_newline ); eprintln!( - //~^ ERROR: using `eprint!()` with a format string that ends in a single newline + //~^ print_with_newline ); @@ -56,7 +60,8 @@ fn main() { eprint!("\r\n"); eprint!("foo\r\n"); eprintln!("\\r"); - //~^ ERROR: using `eprint!()` with a format string that ends in a single newline + //~^ print_with_newline + eprint!("foo\rbar\n"); // Ignore expanded format strings diff --git a/tests/ui/eprint_with_newline.rs b/tests/ui/eprint_with_newline.rs index 5b114056411d..2c90480bdc78 100644 --- a/tests/ui/eprint_with_newline.rs +++ b/tests/ui/eprint_with_newline.rs @@ -3,16 +3,19 @@ fn main() { eprint!("Hello\n"); - //~^ ERROR: using `eprint!()` with a format string that ends in a single newline - //~| NOTE: `-D clippy::print-with-newline` implied by `-D warnings` + //~^ print_with_newline + eprint!("Hello {}\n", "world"); - //~^ ERROR: using `eprint!()` with a format string that ends in a single newline + //~^ print_with_newline + eprint!("Hello {} {}\n", "world", "#2"); - //~^ ERROR: using `eprint!()` with a format string that ends in a single newline + //~^ print_with_newline + eprint!("{}\n", 1265); - //~^ ERROR: using `eprint!()` with a format string that ends in a single newline + //~^ print_with_newline + eprint!("\n"); - //~^ ERROR: using `eprint!()` with a format string that ends in a single newline + //~^ print_with_newline // these are all fine eprint!(""); @@ -35,7 +38,8 @@ fn main() { // #3514 eprint!("\\n"); eprint!("\\\n"); - //~^ ERROR: using `eprint!()` with a format string that ends in a single newline + //~^ print_with_newline + eprint!("\\\\n"); // Raw strings @@ -44,12 +48,12 @@ fn main() { // Literal newlines should also fail eprint!( - //~^ ERROR: using `eprint!()` with a format string that ends in a single newline + //~^ print_with_newline " " ); eprint!( - //~^ ERROR: using `eprint!()` with a format string that ends in a single newline + //~^ print_with_newline r" " ); @@ -58,7 +62,8 @@ fn main() { eprint!("\r\n"); eprint!("foo\r\n"); eprint!("\\r\n"); - //~^ ERROR: using `eprint!()` with a format string that ends in a single newline + //~^ print_with_newline + eprint!("foo\rbar\n"); // Ignore expanded format strings diff --git a/tests/ui/eprint_with_newline.stderr b/tests/ui/eprint_with_newline.stderr index de450090a66e..c78cffd40c99 100644 --- a/tests/ui/eprint_with_newline.stderr +++ b/tests/ui/eprint_with_newline.stderr @@ -25,7 +25,7 @@ LL + eprintln!("Hello {}", "world"); | error: using `eprint!()` with a format string that ends in a single newline - --> tests/ui/eprint_with_newline.rs:10:5 + --> tests/ui/eprint_with_newline.rs:11:5 | LL | eprint!("Hello {} {}\n", "world", "#2"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + eprintln!("Hello {} {}", "world", "#2"); | error: using `eprint!()` with a format string that ends in a single newline - --> tests/ui/eprint_with_newline.rs:12:5 + --> tests/ui/eprint_with_newline.rs:14:5 | LL | eprint!("{}\n", 1265); | ^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + eprintln!("{}", 1265); | error: using `eprint!()` with a format string that ends in a single newline - --> tests/ui/eprint_with_newline.rs:14:5 + --> tests/ui/eprint_with_newline.rs:17:5 | LL | eprint!("\n"); | ^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + eprintln!(); | error: using `eprint!()` with a format string that ends in a single newline - --> tests/ui/eprint_with_newline.rs:37:5 + --> tests/ui/eprint_with_newline.rs:40:5 | LL | eprint!("\\\n"); | ^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + eprintln!("\\"); | error: using `eprint!()` with a format string that ends in a single newline - --> tests/ui/eprint_with_newline.rs:46:5 + --> tests/ui/eprint_with_newline.rs:50:5 | LL | / eprint!( LL | | @@ -90,7 +90,7 @@ LL ~ | error: using `eprint!()` with a format string that ends in a single newline - --> tests/ui/eprint_with_newline.rs:51:5 + --> tests/ui/eprint_with_newline.rs:55:5 | LL | / eprint!( LL | | @@ -107,7 +107,7 @@ LL ~ | error: using `eprint!()` with a format string that ends in a single newline - --> tests/ui/eprint_with_newline.rs:60:5 + --> tests/ui/eprint_with_newline.rs:64:5 | LL | eprint!("\\r\n"); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/eq_op.rs b/tests/ui/eq_op.rs index 7c2c13187518..ced0452ee9a8 100644 --- a/tests/ui/eq_op.rs +++ b/tests/ui/eq_op.rs @@ -5,80 +5,96 @@ fn main() { // simple values and comparisons let _ = 1 == 1; - //~^ ERROR: equal expressions as operands to `==` - //~| NOTE: `-D clippy::eq-op` implied by `-D warnings` + //~^ eq_op + let _ = "no" == "no"; - //~^ ERROR: equal expressions as operands to `==` + //~^ eq_op + // even though I agree that no means no ;-) let _ = false != false; - //~^ ERROR: equal expressions as operands to `!=` + //~^ eq_op + let _ = 1.5 < 1.5; - //~^ ERROR: equal expressions as operands to `<` + //~^ eq_op + let _ = 1u64 >= 1u64; - //~^ ERROR: equal expressions as operands to `>=` + //~^ eq_op + let x = f32::NAN; let _ = x != x; - //~^ ERROR: equal expressions as operands to `!=` - //~| NOTE: if you intended to check if the operand is NaN, use `.is_nan()` instead + //~^ eq_op // casts, methods, parentheses let _ = (1u32 as u64) & (1u32 as u64); - //~^ ERROR: equal expressions as operands to `&` + //~^ eq_op + #[rustfmt::skip] { let _ = 1 ^ ((((((1)))))); - //~^ ERROR: equal expressions as operands to `^` + //~^ eq_op + }; // unary and binary operators let _ = (-(2) < -(2)); - //~^ ERROR: equal expressions as operands to `<` + //~^ eq_op + let _ = ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); - //~^ ERROR: equal expressions as operands to `==` - //~| ERROR: equal expressions as operands to `&` - //~| ERROR: equal expressions as operands to `&` + //~^ eq_op + //~| eq_op + //~| eq_op + let _ = (1 * 2) + (3 * 4) == 1 * 2 + 3 * 4; - //~^ ERROR: equal expressions as operands to `==` + //~^ eq_op // various other things let _ = ([1] != [1]); - //~^ ERROR: equal expressions as operands to `!=` + //~^ eq_op + let _ = ((1, 2) != (1, 2)); - //~^ ERROR: equal expressions as operands to `!=` + //~^ eq_op + let _ = vec![1, 2, 3] == vec![1, 2, 3]; //no error yet, as we don't match macros // const folding let _ = 1 + 1 == 2; - //~^ ERROR: equal expressions as operands to `==` + //~^ eq_op + let _ = 1 - 1 == 0; - //~^ ERROR: equal expressions as operands to `==` - //~| ERROR: equal expressions as operands to `-` + //~^ eq_op + //~| eq_op let _ = 1 - 1; - //~^ ERROR: equal expressions as operands to `-` + //~^ eq_op + let _ = 1 / 1; - //~^ ERROR: equal expressions as operands to `/` + //~^ eq_op + let _ = true && true; - //~^ ERROR: equal expressions as operands to `&&` + //~^ eq_op let _ = true || true; - //~^ ERROR: equal expressions as operands to `||` + //~^ eq_op let a: u32 = 0; let b: u32 = 0; let _ = a == b && b == a; - //~^ ERROR: equal expressions as operands to `&&` + //~^ eq_op + let _ = a != b && b != a; - //~^ ERROR: equal expressions as operands to `&&` + //~^ eq_op + let _ = a < b && b > a; - //~^ ERROR: equal expressions as operands to `&&` + //~^ eq_op + let _ = a <= b && b >= a; - //~^ ERROR: equal expressions as operands to `&&` + //~^ eq_op let mut a = vec![1]; let _ = a == a; - //~^ ERROR: equal expressions as operands to `==` + //~^ eq_op + let _ = 2 * a.len() == 2 * a.len(); // ok, functions let _ = a.pop() == a.pop(); // ok, functions @@ -89,7 +105,7 @@ fn main() { const B: u32 = 10; const C: u32 = A / B; // ok, different named constants const D: u32 = A / A; - //~^ ERROR: equal expressions as operands to `/` + //~^ eq_op } macro_rules! check_if_named_foo { @@ -121,7 +137,7 @@ struct Nested { fn check_nested(n1: &Nested, n2: &Nested) -> bool { // `n2.inner.0.0` mistyped as `n1.inner.0.0` (n1.inner.0).0 == (n1.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.2).0 - //~^ ERROR: equal expressions as operands to `==` + //~^ eq_op } #[test] diff --git a/tests/ui/eq_op.stderr b/tests/ui/eq_op.stderr index bd3c115d8b8b..1696f09d6d17 100644 --- a/tests/ui/eq_op.stderr +++ b/tests/ui/eq_op.stderr @@ -14,25 +14,25 @@ LL | let _ = "no" == "no"; | ^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> tests/ui/eq_op.rs:13:13 + --> tests/ui/eq_op.rs:14:13 | LL | let _ = false != false; | ^^^^^^^^^^^^^^ error: equal expressions as operands to `<` - --> tests/ui/eq_op.rs:15:13 + --> tests/ui/eq_op.rs:17:13 | LL | let _ = 1.5 < 1.5; | ^^^^^^^^^ error: equal expressions as operands to `>=` - --> tests/ui/eq_op.rs:17:13 + --> tests/ui/eq_op.rs:20:13 | LL | let _ = 1u64 >= 1u64; | ^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> tests/ui/eq_op.rs:20:13 + --> tests/ui/eq_op.rs:24:13 | LL | let _ = x != x; | ^^^^^^ @@ -40,139 +40,139 @@ LL | let _ = x != x; = note: if you intended to check if the operand is NaN, use `.is_nan()` instead error: equal expressions as operands to `&` - --> tests/ui/eq_op.rs:25:13 + --> tests/ui/eq_op.rs:28:13 | LL | let _ = (1u32 as u64) & (1u32 as u64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `^` - --> tests/ui/eq_op.rs:29:17 + --> tests/ui/eq_op.rs:33:17 | LL | let _ = 1 ^ ((((((1)))))); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `<` - --> tests/ui/eq_op.rs:34:13 + --> tests/ui/eq_op.rs:39:13 | LL | let _ = (-(2) < -(2)); | ^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> tests/ui/eq_op.rs:36:13 + --> tests/ui/eq_op.rs:42:13 | LL | let _ = ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&` - --> tests/ui/eq_op.rs:36:14 + --> tests/ui/eq_op.rs:42:14 | LL | let _ = ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&` - --> tests/ui/eq_op.rs:36:35 + --> tests/ui/eq_op.rs:42:35 | LL | let _ = ((1 + 1) & (1 + 1) == (1 + 1) & (1 + 1)); | ^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> tests/ui/eq_op.rs:40:13 + --> tests/ui/eq_op.rs:47:13 | LL | let _ = (1 * 2) + (3 * 4) == 1 * 2 + 3 * 4; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> tests/ui/eq_op.rs:44:13 + --> tests/ui/eq_op.rs:51:13 | LL | let _ = ([1] != [1]); | ^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> tests/ui/eq_op.rs:46:13 + --> tests/ui/eq_op.rs:54:13 | LL | let _ = ((1, 2) != (1, 2)); | ^^^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> tests/ui/eq_op.rs:51:13 + --> tests/ui/eq_op.rs:60:13 | LL | let _ = 1 + 1 == 2; | ^^^^^^^^^^ error: equal expressions as operands to `==` - --> tests/ui/eq_op.rs:53:13 + --> tests/ui/eq_op.rs:63:13 | LL | let _ = 1 - 1 == 0; | ^^^^^^^^^^ error: equal expressions as operands to `-` - --> tests/ui/eq_op.rs:53:13 + --> tests/ui/eq_op.rs:63:13 | LL | let _ = 1 - 1 == 0; | ^^^^^ error: equal expressions as operands to `-` - --> tests/ui/eq_op.rs:57:13 + --> tests/ui/eq_op.rs:67:13 | LL | let _ = 1 - 1; | ^^^^^ error: equal expressions as operands to `/` - --> tests/ui/eq_op.rs:59:13 + --> tests/ui/eq_op.rs:70:13 | LL | let _ = 1 / 1; | ^^^^^ error: equal expressions as operands to `&&` - --> tests/ui/eq_op.rs:61:13 + --> tests/ui/eq_op.rs:73:13 | LL | let _ = true && true; | ^^^^^^^^^^^^ error: equal expressions as operands to `||` - --> tests/ui/eq_op.rs:64:13 + --> tests/ui/eq_op.rs:76:13 | LL | let _ = true || true; | ^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> tests/ui/eq_op.rs:70:13 + --> tests/ui/eq_op.rs:82:13 | LL | let _ = a == b && b == a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> tests/ui/eq_op.rs:72:13 + --> tests/ui/eq_op.rs:85:13 | LL | let _ = a != b && b != a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> tests/ui/eq_op.rs:74:13 + --> tests/ui/eq_op.rs:88:13 | LL | let _ = a < b && b > a; | ^^^^^^^^^^^^^^ error: equal expressions as operands to `&&` - --> tests/ui/eq_op.rs:76:13 + --> tests/ui/eq_op.rs:91:13 | LL | let _ = a <= b && b >= a; | ^^^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> tests/ui/eq_op.rs:80:13 + --> tests/ui/eq_op.rs:95:13 | LL | let _ = a == a; | ^^^^^^ error: equal expressions as operands to `/` - --> tests/ui/eq_op.rs:91:20 + --> tests/ui/eq_op.rs:107:20 | LL | const D: u32 = A / A; | ^^^^^ error: equal expressions as operands to `==` - --> tests/ui/eq_op.rs:123:5 + --> tests/ui/eq_op.rs:139:5 | LL | (n1.inner.0).0 == (n1.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.2).0 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/eq_op_macros.rs b/tests/ui/eq_op_macros.rs index a511af4a31c8..82242d0eb196 100644 --- a/tests/ui/eq_op_macros.rs +++ b/tests/ui/eq_op_macros.rs @@ -6,9 +6,13 @@ macro_rules! assert_in_macro_def { () => { let a = 42; assert_eq!(a, a); + //~^ eq_op assert_ne!(a, a); + //~^ eq_op debug_assert_eq!(a, a); + //~^ eq_op debug_assert_ne!(a, a); + //~^ eq_op }; } @@ -21,9 +25,11 @@ fn main() { // lint identical args in `assert_eq!` assert_eq!(a, a); - //~^ ERROR: identical args used in this `assert_eq!` macro call + //~^ eq_op + assert_eq!(a + 1, a + 1); - //~^ ERROR: identical args used in this `assert_eq!` macro call + //~^ eq_op + // ok assert_eq!(a, b); assert_eq!(a, a + 1); @@ -31,9 +37,11 @@ fn main() { // lint identical args in `assert_ne!` assert_ne!(a, a); - //~^ ERROR: identical args used in this `assert_ne!` macro call + //~^ eq_op + assert_ne!(a + 1, a + 1); - //~^ ERROR: identical args used in this `assert_ne!` macro call + //~^ eq_op + // ok assert_ne!(a, b); assert_ne!(a, a + 1); @@ -41,9 +49,11 @@ fn main() { // lint identical args in `debug_assert_eq!` debug_assert_eq!(a, a); - //~^ ERROR: identical args used in this `debug_assert_eq!` macro call + //~^ eq_op + debug_assert_eq!(a + 1, a + 1); - //~^ ERROR: identical args used in this `debug_assert_eq!` macro call + //~^ eq_op + // ok debug_assert_eq!(a, b); debug_assert_eq!(a, a + 1); @@ -51,9 +61,11 @@ fn main() { // lint identical args in `debug_assert_ne!` debug_assert_ne!(a, a); - //~^ ERROR: identical args used in this `debug_assert_ne!` macro call + //~^ eq_op + debug_assert_ne!(a + 1, a + 1); - //~^ ERROR: identical args used in this `debug_assert_ne!` macro call + //~^ eq_op + // ok debug_assert_ne!(a, b); debug_assert_ne!(a, a + 1); diff --git a/tests/ui/eq_op_macros.stderr b/tests/ui/eq_op_macros.stderr index b114db0ca98e..72315e87bfef 100644 --- a/tests/ui/eq_op_macros.stderr +++ b/tests/ui/eq_op_macros.stderr @@ -12,7 +12,7 @@ LL | assert_in_macro_def!(); = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info) error: identical args used in this `assert_ne!` macro call - --> tests/ui/eq_op_macros.rs:9:20 + --> tests/ui/eq_op_macros.rs:10:20 | LL | assert_ne!(a, a); | ^^^^ @@ -23,7 +23,7 @@ LL | assert_in_macro_def!(); = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info) error: identical args used in this `debug_assert_eq!` macro call - --> tests/ui/eq_op_macros.rs:10:26 + --> tests/ui/eq_op_macros.rs:12:26 | LL | debug_assert_eq!(a, a); | ^^^^ @@ -34,7 +34,7 @@ LL | assert_in_macro_def!(); = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info) error: identical args used in this `debug_assert_ne!` macro call - --> tests/ui/eq_op_macros.rs:11:26 + --> tests/ui/eq_op_macros.rs:14:26 | LL | debug_assert_ne!(a, a); | ^^^^ @@ -45,49 +45,49 @@ LL | assert_in_macro_def!(); = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info) error: identical args used in this `assert_eq!` macro call - --> tests/ui/eq_op_macros.rs:23:16 + --> tests/ui/eq_op_macros.rs:27:16 | LL | assert_eq!(a, a); | ^^^^ error: identical args used in this `assert_eq!` macro call - --> tests/ui/eq_op_macros.rs:25:16 + --> tests/ui/eq_op_macros.rs:30:16 | LL | assert_eq!(a + 1, a + 1); | ^^^^^^^^^^^^ error: identical args used in this `assert_ne!` macro call - --> tests/ui/eq_op_macros.rs:33:16 + --> tests/ui/eq_op_macros.rs:39:16 | LL | assert_ne!(a, a); | ^^^^ error: identical args used in this `assert_ne!` macro call - --> tests/ui/eq_op_macros.rs:35:16 + --> tests/ui/eq_op_macros.rs:42:16 | LL | assert_ne!(a + 1, a + 1); | ^^^^^^^^^^^^ error: identical args used in this `debug_assert_eq!` macro call - --> tests/ui/eq_op_macros.rs:43:22 + --> tests/ui/eq_op_macros.rs:51:22 | LL | debug_assert_eq!(a, a); | ^^^^ error: identical args used in this `debug_assert_eq!` macro call - --> tests/ui/eq_op_macros.rs:45:22 + --> tests/ui/eq_op_macros.rs:54:22 | LL | debug_assert_eq!(a + 1, a + 1); | ^^^^^^^^^^^^ error: identical args used in this `debug_assert_ne!` macro call - --> tests/ui/eq_op_macros.rs:53:22 + --> tests/ui/eq_op_macros.rs:63:22 | LL | debug_assert_ne!(a, a); | ^^^^ error: identical args used in this `debug_assert_ne!` macro call - --> tests/ui/eq_op_macros.rs:55:22 + --> tests/ui/eq_op_macros.rs:66:22 | LL | debug_assert_ne!(a + 1, a + 1); | ^^^^^^^^^^^^ diff --git a/tests/ui/equatable_if_let.fixed b/tests/ui/equatable_if_let.fixed index 2b523e1e185c..166b1387ba26 100644 --- a/tests/ui/equatable_if_let.fixed +++ b/tests/ui/equatable_if_let.fixed @@ -62,13 +62,21 @@ fn main() { // true if a == 2 {} + //~^ equatable_if_let if a.cmp(&b) == Ordering::Greater {} + //~^ equatable_if_let if c == Some(2) {} + //~^ equatable_if_let if d == (Struct { a: 2, b: false }) {} + //~^ equatable_if_let if e == Enum::TupleVariant(32, 64) {} + //~^ equatable_if_let if e == (Enum::RecordVariant { a: 64, b: 32 }) {} + //~^ equatable_if_let if e == Enum::UnitVariant {} + //~^ equatable_if_let if (e, &d) == (Enum::UnitVariant, &Struct { a: 2, b: false }) {} + //~^ equatable_if_let // false @@ -78,12 +86,18 @@ fn main() { if let Struct { a, b: false } = d {} if let Struct { a: 2, b: x } = d {} if matches!(f, NotPartialEq::A) {} + //~^ equatable_if_let if g == NotStructuralEq::A {} + //~^ equatable_if_let if matches!(Some(f), Some(NotPartialEq::A)) {} + //~^ equatable_if_let if Some(g) == Some(NotStructuralEq::A) {} + //~^ equatable_if_let if matches!(h, NoPartialEqStruct { a: 2, b: false }) {} + //~^ equatable_if_let if "abc" == inline!("abc") { + //~^ equatable_if_let println!("OK"); } diff --git a/tests/ui/equatable_if_let.rs b/tests/ui/equatable_if_let.rs index f7e3bb2964da..09c2483ae6d4 100644 --- a/tests/ui/equatable_if_let.rs +++ b/tests/ui/equatable_if_let.rs @@ -62,13 +62,21 @@ fn main() { // true if let 2 = a {} + //~^ equatable_if_let if let Ordering::Greater = a.cmp(&b) {} + //~^ equatable_if_let if let Some(2) = c {} + //~^ equatable_if_let if let Struct { a: 2, b: false } = d {} + //~^ equatable_if_let if let Enum::TupleVariant(32, 64) = e {} + //~^ equatable_if_let if let Enum::RecordVariant { a: 64, b: 32 } = e {} + //~^ equatable_if_let if let Enum::UnitVariant = e {} + //~^ equatable_if_let if let (Enum::UnitVariant, &Struct { a: 2, b: false }) = (e, &d) {} + //~^ equatable_if_let // false @@ -78,12 +86,18 @@ fn main() { if let Struct { a, b: false } = d {} if let Struct { a: 2, b: x } = d {} if let NotPartialEq::A = f {} + //~^ equatable_if_let if let NotStructuralEq::A = g {} + //~^ equatable_if_let if let Some(NotPartialEq::A) = Some(f) {} + //~^ equatable_if_let if let Some(NotStructuralEq::A) = Some(g) {} + //~^ equatable_if_let if let NoPartialEqStruct { a: 2, b: false } = h {} + //~^ equatable_if_let if let inline!("abc") = "abc" { + //~^ equatable_if_let println!("OK"); } diff --git a/tests/ui/equatable_if_let.stderr b/tests/ui/equatable_if_let.stderr index 9e93a33cd7e2..81e0e15a5c74 100644 --- a/tests/ui/equatable_if_let.stderr +++ b/tests/ui/equatable_if_let.stderr @@ -8,79 +8,79 @@ LL | if let 2 = a {} = help: to override `-D warnings` add `#[allow(clippy::equatable_if_let)]` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:65:8 + --> tests/ui/equatable_if_let.rs:66:8 | LL | if let Ordering::Greater = a.cmp(&b) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.cmp(&b) == Ordering::Greater` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:66:8 + --> tests/ui/equatable_if_let.rs:68:8 | LL | if let Some(2) = c {} | ^^^^^^^^^^^^^^^ help: try: `c == Some(2)` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:67:8 + --> tests/ui/equatable_if_let.rs:70:8 | LL | if let Struct { a: 2, b: false } = d {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `d == (Struct { a: 2, b: false })` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:68:8 + --> tests/ui/equatable_if_let.rs:72:8 | LL | if let Enum::TupleVariant(32, 64) = e {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::TupleVariant(32, 64)` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:69:8 + --> tests/ui/equatable_if_let.rs:74:8 | LL | if let Enum::RecordVariant { a: 64, b: 32 } = e {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == (Enum::RecordVariant { a: 64, b: 32 })` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:70:8 + --> tests/ui/equatable_if_let.rs:76:8 | LL | if let Enum::UnitVariant = e {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::UnitVariant` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:71:8 + --> tests/ui/equatable_if_let.rs:78:8 | LL | if let (Enum::UnitVariant, &Struct { a: 2, b: false }) = (e, &d) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(e, &d) == (Enum::UnitVariant, &Struct { a: 2, b: false })` error: this pattern matching can be expressed using `matches!` - --> tests/ui/equatable_if_let.rs:80:8 + --> tests/ui/equatable_if_let.rs:88:8 | LL | if let NotPartialEq::A = f {} | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(f, NotPartialEq::A)` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:81:8 + --> tests/ui/equatable_if_let.rs:90:8 | LL | if let NotStructuralEq::A = g {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `g == NotStructuralEq::A` error: this pattern matching can be expressed using `matches!` - --> tests/ui/equatable_if_let.rs:82:8 + --> tests/ui/equatable_if_let.rs:92:8 | LL | if let Some(NotPartialEq::A) = Some(f) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(Some(f), Some(NotPartialEq::A))` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:83:8 + --> tests/ui/equatable_if_let.rs:94:8 | LL | if let Some(NotStructuralEq::A) = Some(g) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(g) == Some(NotStructuralEq::A)` error: this pattern matching can be expressed using `matches!` - --> tests/ui/equatable_if_let.rs:84:8 + --> tests/ui/equatable_if_let.rs:96:8 | LL | if let NoPartialEqStruct { a: 2, b: false } = h {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(h, NoPartialEqStruct { a: 2, b: false })` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:86:8 + --> tests/ui/equatable_if_let.rs:99:8 | LL | if let inline!("abc") = "abc" { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"abc" == inline!("abc")` diff --git a/tests/ui/erasing_op.rs b/tests/ui/erasing_op.rs index 00c74f23fed0..9237b9eb11f0 100644 --- a/tests/ui/erasing_op.rs +++ b/tests/ui/erasing_op.rs @@ -33,17 +33,20 @@ impl core::ops::Mul for Vec1 { #[warn(clippy::erasing_op)] fn test(x: u8) { x * 0; - //~^ ERROR: this operation will always return zero. This is likely not the intended ou - //~| NOTE: `-D clippy::erasing-op` implied by `-D warnings` + //~^ erasing_op + 0 & x; - //~^ ERROR: this operation will always return zero. This is likely not the intended ou + //~^ erasing_op + 0 / x; - //~^ ERROR: this operation will always return zero. This is likely not the intended ou + //~^ erasing_op + 0 * Meter; // no error: Output type is different from the non-zero argument 0 * Vec1 { x: 5 }; - //~^ ERROR: this operation will always return zero. This is likely not the intended ou + //~^ erasing_op + Vec1 { x: 5 } * 0; - //~^ ERROR: this operation will always return zero. This is likely not the intended ou + //~^ erasing_op } fn main() { diff --git a/tests/ui/erasing_op.stderr b/tests/ui/erasing_op.stderr index 6ed8bffeb24d..94730b066801 100644 --- a/tests/ui/erasing_op.stderr +++ b/tests/ui/erasing_op.stderr @@ -14,19 +14,19 @@ LL | 0 & x; | ^^^^^ error: this operation will always return zero. This is likely not the intended outcome - --> tests/ui/erasing_op.rs:40:5 + --> tests/ui/erasing_op.rs:41:5 | LL | 0 / x; | ^^^^^ error: this operation will always return zero. This is likely not the intended outcome - --> tests/ui/erasing_op.rs:43:5 + --> tests/ui/erasing_op.rs:45:5 | LL | 0 * Vec1 { x: 5 }; | ^^^^^^^^^^^^^^^^^ error: this operation will always return zero. This is likely not the intended outcome - --> tests/ui/erasing_op.rs:45:5 + --> tests/ui/erasing_op.rs:48:5 | LL | Vec1 { x: 5 } * 0; | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/err_expect.fixed b/tests/ui/err_expect.fixed index abbc6dbebedb..9e1a3a0c739c 100644 --- a/tests/ui/err_expect.fixed +++ b/tests/ui/err_expect.fixed @@ -8,6 +8,7 @@ struct MyTypeDebug; fn main() { let test_debug: Result = Ok(MyTypeDebug); test_debug.expect_err("Testing debug type"); + //~^ err_expect let test_non_debug: Result = Ok(MyTypeNonDebug); test_non_debug.err().expect("Testing non debug type"); @@ -23,4 +24,5 @@ fn msrv_1_16() { fn msrv_1_17() { let x: Result = Ok(17); x.expect_err("17"); + //~^ err_expect } diff --git a/tests/ui/err_expect.rs b/tests/ui/err_expect.rs index 0c7ad185dfbe..8e9063a2e1d4 100644 --- a/tests/ui/err_expect.rs +++ b/tests/ui/err_expect.rs @@ -8,6 +8,7 @@ struct MyTypeDebug; fn main() { let test_debug: Result = Ok(MyTypeDebug); test_debug.err().expect("Testing debug type"); + //~^ err_expect let test_non_debug: Result = Ok(MyTypeNonDebug); test_non_debug.err().expect("Testing non debug type"); @@ -23,4 +24,5 @@ fn msrv_1_16() { fn msrv_1_17() { let x: Result = Ok(17); x.err().expect("17"); + //~^ err_expect } diff --git a/tests/ui/err_expect.stderr b/tests/ui/err_expect.stderr index 68f39cc45c5b..5b591e1604db 100644 --- a/tests/ui/err_expect.stderr +++ b/tests/ui/err_expect.stderr @@ -8,7 +8,7 @@ LL | test_debug.err().expect("Testing debug type"); = help: to override `-D warnings` add `#[allow(clippy::err_expect)]` error: called `.err().expect()` on a `Result` value - --> tests/ui/err_expect.rs:25:7 + --> tests/ui/err_expect.rs:26:7 | LL | x.err().expect("17"); | ^^^^^^^^^^^^ help: try: `expect_err` diff --git a/tests/ui/error_impl_error.rs b/tests/ui/error_impl_error.rs index 05003f7d047c..5c88888f38ea 100644 --- a/tests/ui/error_impl_error.rs +++ b/tests/ui/error_impl_error.rs @@ -5,7 +5,7 @@ pub mod a { #[derive(Debug)] pub struct Error; - //~^ ERROR: exported type named `Error` that implements `Error` + //~^ error_impl_error impl std::fmt::Display for Error { fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -19,7 +19,7 @@ pub mod a { mod b { #[derive(Debug)] pub(super) enum Error {} - //~^ ERROR: exported type named `Error` that implements `Error` + //~^ error_impl_error impl std::fmt::Display for Error { fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -32,7 +32,7 @@ mod b { pub mod c { pub union Error { - //~^ ERROR: exported type named `Error` that implements `Error` + //~^ error_impl_error a: u32, b: u32, } @@ -54,7 +54,7 @@ pub mod c { pub mod d { pub type Error = std::fmt::Error; - //~^ ERROR: exported type alias named `Error` that implements `Error` + //~^ error_impl_error } mod e { diff --git a/tests/ui/eta.fixed b/tests/ui/eta.fixed index abccc30ef87d..0ba631fda051 100644 --- a/tests/ui/eta.fixed +++ b/tests/ui/eta.fixed @@ -29,12 +29,19 @@ macro_rules! closure_mac { fn main() { let a = Some(1u8).map(foo); + //~^ redundant_closure let c = Some(1u8).map(|a| {1+2; foo}(a)); true.then(|| mac!()); // don't lint function in macro expansion Some(1).map(closure_mac!()); // don't lint closure in macro expansion let _: Option> = true.then(std::vec::Vec::new); // special case vec! + // + //~^^ redundant_closure let d = Some(1u8).map(|a| foo(foo2(a))); //is adjusted? + // + //~^^ redundant_closure all(&[1, 2, 3], &&2, below); //is adjusted + // + //~^^ redundant_closure unsafe { Some(1u8).map(|a| unsafe_fn(a)); // unsafe fn } @@ -42,6 +49,7 @@ fn main() { // See #815 let e = Some(1u8).map(|a| divergent(a)); let e = Some(1u8).map(generic); + //~^ redundant_closure let e = Some(1u8).map(generic); // See #515 let a: Option)>> = @@ -94,16 +102,22 @@ impl<'a> std::ops::Deref for TestStruct<'a> { fn test_redundant_closures_containing_method_calls() { let i = 10; let e = Some(TestStruct { some_ref: &i }).map(TestStruct::foo); + //~^ redundant_closure_for_method_calls let e = Some(TestStruct { some_ref: &i }).map(TestTrait::trait_foo); + //~^ redundant_closure_for_method_calls let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo_ref()); let e = Some(&mut vec![1, 2, 3]).map(std::vec::Vec::clear); + //~^ redundant_closure_for_method_calls unsafe { let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo_unsafe()); } let e = Some("str").map(std::string::ToString::to_string); + //~^ redundant_closure_for_method_calls let e = Some('a').map(char::to_uppercase); + //~^ redundant_closure_for_method_calls let e: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(|c| c.len_utf8()).collect(); let e: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(char::to_ascii_uppercase).collect(); + //~^ redundant_closure_for_method_calls let e = Some(PathBuf::new()).as_ref().and_then(|s| s.to_str()); let c = Some(TestStruct { some_ref: &i }) .as_ref() @@ -120,6 +134,7 @@ fn test_redundant_closures_containing_method_calls() { fn issue14096() { let x = Some("42"); let _ = x.map(str::parse::); + //~^ redundant_closure_for_method_calls } } @@ -172,6 +187,7 @@ fn generic(_: T) -> u8 { fn passes_fn_mut(mut x: Box) { requires_fn_once(x); + //~^ redundant_closure } fn requires_fn_once(_: T) {} @@ -179,11 +195,13 @@ fn test_redundant_closure_with_function_pointer() { type FnPtrType = fn(u8); let foo_ptr: FnPtrType = foo; let a = Some(1u8).map(foo_ptr); + //~^ redundant_closure } fn test_redundant_closure_with_another_closure() { let closure = |a| println!("{}", a); let a = Some(1u8).map(closure); + //~^ redundant_closure } fn make_lazy(f: impl Fn() -> fn(u8) -> u8) -> impl Fn(u8) -> u8 { @@ -216,8 +234,11 @@ fn mutable_closure_used_again(x: Vec, y: Vec, z: Vec) { let mut res = Vec::new(); let mut add_to_res = |n| res.push(n); x.into_iter().for_each(&mut add_to_res); + //~^ redundant_closure y.into_iter().for_each(&mut add_to_res); + //~^ redundant_closure z.into_iter().for_each(add_to_res); + //~^ redundant_closure } fn mutable_closure_in_loop() { @@ -225,10 +246,12 @@ fn mutable_closure_in_loop() { let mut closure = |n| value += n; for _ in 0..5 { Some(1).map(&mut closure); + //~^ redundant_closure let mut value = 0; let mut in_loop = |n| value += n; Some(1).map(in_loop); + //~^ redundant_closure } } @@ -322,13 +345,16 @@ fn not_general_enough() { pub fn mutable_impl_fn_mut(mut f: impl FnMut(), mut f_used_once: impl FnMut()) -> impl FnMut() { fn takes_fn_mut(_: impl FnMut()) {} takes_fn_mut(&mut f); + //~^ redundant_closure fn takes_fn_once(_: impl FnOnce()) {} takes_fn_once(&mut f); + //~^ redundant_closure f(); move || takes_fn_mut(&mut f_used_once) + //~^ redundant_closure } impl dyn TestTrait + '_ { @@ -341,16 +367,20 @@ impl dyn TestTrait + '_ { fn angle_brackets_and_args() { let array_opt: Option<&[u8; 3]> = Some(&[4, 8, 7]); array_opt.map(<[u8; 3]>::as_slice); + //~^ redundant_closure_for_method_calls let slice_opt: Option<&[u8]> = Some(b"slice"); slice_opt.map(<[u8]>::len); + //~^ redundant_closure_for_method_calls let ptr_opt: Option<*const usize> = Some(&487); ptr_opt.map(<*const usize>::is_null); + //~^ redundant_closure_for_method_calls let test_struct = TestStruct { some_ref: &487 }; let dyn_opt: Option<&dyn TestTrait> = Some(&test_struct); dyn_opt.map(::method_on_dyn); + //~^ redundant_closure_for_method_calls } // https://github.com/rust-lang/rust-clippy/issues/12199 @@ -411,6 +441,7 @@ fn _mixed_late_bound_and_early_bound_regions() { *y } let _ = f(&0, f2); + //~^ redundant_closure } fn _closure_with_types() { @@ -439,10 +470,12 @@ mod issue_10854 { pub fn calls_test(test: Option) -> Option { test.map(Test::method) + //~^ redundant_closure_for_method_calls } pub fn calls_outer(test: Option) -> Option { test.map(super::Outer::method) + //~^ redundant_closure_for_method_calls } } @@ -456,6 +489,7 @@ mod issue_10854 { pub fn calls_into_mod(test: Option) -> Option { test.map(test_mod::Test::method) + //~^ redundant_closure_for_method_calls } mod a { @@ -463,6 +497,7 @@ mod issue_10854 { pub mod c { pub fn extreme_nesting(test: Option) -> Option { test.map(crate::issue_10854::d::Test::method) + //~^ redundant_closure_for_method_calls } } } @@ -482,10 +517,12 @@ mod issue_10854 { mod issue_12853 { fn f_by_value(f: F) { let x = Box::new(|| None.map(&f)); + //~^ redundant_closure x(); } fn f_by_ref(f: &F) { let x = Box::new(|| None.map(f)); + //~^ redundant_closure x(); } } @@ -503,5 +540,6 @@ mod issue_13073 { let _field = bind.as_deref().or_else(|| get_default()).unwrap(); // should lint let _field = bind.or_else(get_default).unwrap(); + //~^ redundant_closure } } diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index 9bcee4eba340..4d8b29d450c5 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -29,12 +29,19 @@ macro_rules! closure_mac { fn main() { let a = Some(1u8).map(|a| foo(a)); + //~^ redundant_closure let c = Some(1u8).map(|a| {1+2; foo}(a)); true.then(|| mac!()); // don't lint function in macro expansion Some(1).map(closure_mac!()); // don't lint closure in macro expansion let _: Option> = true.then(|| vec![]); // special case vec! + // + //~^^ redundant_closure let d = Some(1u8).map(|a| foo((|b| foo2(b))(a))); //is adjusted? + // + //~^^ redundant_closure all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted + // + //~^^ redundant_closure unsafe { Some(1u8).map(|a| unsafe_fn(a)); // unsafe fn } @@ -42,6 +49,7 @@ fn main() { // See #815 let e = Some(1u8).map(|a| divergent(a)); let e = Some(1u8).map(|a| generic(a)); + //~^ redundant_closure let e = Some(1u8).map(generic); // See #515 let a: Option)>> = @@ -94,16 +102,22 @@ impl<'a> std::ops::Deref for TestStruct<'a> { fn test_redundant_closures_containing_method_calls() { let i = 10; let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); + //~^ redundant_closure_for_method_calls let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo()); + //~^ redundant_closure_for_method_calls let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo_ref()); let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear()); + //~^ redundant_closure_for_method_calls unsafe { let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo_unsafe()); } let e = Some("str").map(|s| s.to_string()); + //~^ redundant_closure_for_method_calls let e = Some('a').map(|s| s.to_uppercase()); + //~^ redundant_closure_for_method_calls let e: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(|c| c.len_utf8()).collect(); let e: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect(); + //~^ redundant_closure_for_method_calls let e = Some(PathBuf::new()).as_ref().and_then(|s| s.to_str()); let c = Some(TestStruct { some_ref: &i }) .as_ref() @@ -120,6 +134,7 @@ fn test_redundant_closures_containing_method_calls() { fn issue14096() { let x = Some("42"); let _ = x.map(|x| x.parse::()); + //~^ redundant_closure_for_method_calls } } @@ -172,6 +187,7 @@ fn generic(_: T) -> u8 { fn passes_fn_mut(mut x: Box) { requires_fn_once(|| x()); + //~^ redundant_closure } fn requires_fn_once(_: T) {} @@ -179,11 +195,13 @@ fn test_redundant_closure_with_function_pointer() { type FnPtrType = fn(u8); let foo_ptr: FnPtrType = foo; let a = Some(1u8).map(|a| foo_ptr(a)); + //~^ redundant_closure } fn test_redundant_closure_with_another_closure() { let closure = |a| println!("{}", a); let a = Some(1u8).map(|a| closure(a)); + //~^ redundant_closure } fn make_lazy(f: impl Fn() -> fn(u8) -> u8) -> impl Fn(u8) -> u8 { @@ -216,8 +234,11 @@ fn mutable_closure_used_again(x: Vec, y: Vec, z: Vec) { let mut res = Vec::new(); let mut add_to_res = |n| res.push(n); x.into_iter().for_each(|x| add_to_res(x)); + //~^ redundant_closure y.into_iter().for_each(|x| add_to_res(x)); + //~^ redundant_closure z.into_iter().for_each(|x| add_to_res(x)); + //~^ redundant_closure } fn mutable_closure_in_loop() { @@ -225,10 +246,12 @@ fn mutable_closure_in_loop() { let mut closure = |n| value += n; for _ in 0..5 { Some(1).map(|n| closure(n)); + //~^ redundant_closure let mut value = 0; let mut in_loop = |n| value += n; Some(1).map(|n| in_loop(n)); + //~^ redundant_closure } } @@ -322,13 +345,16 @@ fn not_general_enough() { pub fn mutable_impl_fn_mut(mut f: impl FnMut(), mut f_used_once: impl FnMut()) -> impl FnMut() { fn takes_fn_mut(_: impl FnMut()) {} takes_fn_mut(|| f()); + //~^ redundant_closure fn takes_fn_once(_: impl FnOnce()) {} takes_fn_once(|| f()); + //~^ redundant_closure f(); move || takes_fn_mut(|| f_used_once()) + //~^ redundant_closure } impl dyn TestTrait + '_ { @@ -341,16 +367,20 @@ impl dyn TestTrait + '_ { fn angle_brackets_and_args() { let array_opt: Option<&[u8; 3]> = Some(&[4, 8, 7]); array_opt.map(|a| a.as_slice()); + //~^ redundant_closure_for_method_calls let slice_opt: Option<&[u8]> = Some(b"slice"); slice_opt.map(|s| s.len()); + //~^ redundant_closure_for_method_calls let ptr_opt: Option<*const usize> = Some(&487); ptr_opt.map(|p| p.is_null()); + //~^ redundant_closure_for_method_calls let test_struct = TestStruct { some_ref: &487 }; let dyn_opt: Option<&dyn TestTrait> = Some(&test_struct); dyn_opt.map(|d| d.method_on_dyn()); + //~^ redundant_closure_for_method_calls } // https://github.com/rust-lang/rust-clippy/issues/12199 @@ -411,6 +441,7 @@ fn _mixed_late_bound_and_early_bound_regions() { *y } let _ = f(&0, |x, y| f2(x, y)); + //~^ redundant_closure } fn _closure_with_types() { @@ -439,10 +470,12 @@ mod issue_10854 { pub fn calls_test(test: Option) -> Option { test.map(|t| t.method()) + //~^ redundant_closure_for_method_calls } pub fn calls_outer(test: Option) -> Option { test.map(|t| t.method()) + //~^ redundant_closure_for_method_calls } } @@ -456,6 +489,7 @@ mod issue_10854 { pub fn calls_into_mod(test: Option) -> Option { test.map(|t| t.method()) + //~^ redundant_closure_for_method_calls } mod a { @@ -463,6 +497,7 @@ mod issue_10854 { pub mod c { pub fn extreme_nesting(test: Option) -> Option { test.map(|t| t.method()) + //~^ redundant_closure_for_method_calls } } } @@ -482,10 +517,12 @@ mod issue_10854 { mod issue_12853 { fn f_by_value(f: F) { let x = Box::new(|| None.map(|x| f(x))); + //~^ redundant_closure x(); } fn f_by_ref(f: &F) { let x = Box::new(|| None.map(|x| f(x))); + //~^ redundant_closure x(); } } @@ -503,5 +540,6 @@ mod issue_13073 { let _field = bind.as_deref().or_else(|| get_default()).unwrap(); // should lint let _field = bind.or_else(|| get_default()).unwrap(); + //~^ redundant_closure } } diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr index ac58e87bc5ec..8bc08add2fab 100644 --- a/tests/ui/eta.stderr +++ b/tests/ui/eta.stderr @@ -8,31 +8,31 @@ LL | let a = Some(1u8).map(|a| foo(a)); = help: to override `-D warnings` add `#[allow(clippy::redundant_closure)]` error: redundant closure - --> tests/ui/eta.rs:35:40 + --> tests/ui/eta.rs:36:40 | LL | let _: Option> = true.then(|| vec![]); // special case vec! | ^^^^^^^^^ help: replace the closure with `Vec::new`: `std::vec::Vec::new` error: redundant closure - --> tests/ui/eta.rs:36:35 + --> tests/ui/eta.rs:39:35 | LL | let d = Some(1u8).map(|a| foo((|b| foo2(b))(a))); //is adjusted? | ^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo2` error: redundant closure - --> tests/ui/eta.rs:37:26 + --> tests/ui/eta.rs:42:26 | LL | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted | ^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `below` error: redundant closure - --> tests/ui/eta.rs:44:27 + --> tests/ui/eta.rs:51:27 | LL | let e = Some(1u8).map(|a| generic(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `generic` error: redundant closure - --> tests/ui/eta.rs:96:51 + --> tests/ui/eta.rs:104:51 | LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); | ^^^^^^^^^^^ help: replace the closure with the method itself: `TestStruct::foo` @@ -41,175 +41,175 @@ LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); = help: to override `-D warnings` add `#[allow(clippy::redundant_closure_for_method_calls)]` error: redundant closure - --> tests/ui/eta.rs:97:51 + --> tests/ui/eta.rs:106:51 | LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo()); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `TestTrait::trait_foo` error: redundant closure - --> tests/ui/eta.rs:99:42 + --> tests/ui/eta.rs:109:42 | LL | let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear()); | ^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::vec::Vec::clear` error: redundant closure - --> tests/ui/eta.rs:103:29 + --> tests/ui/eta.rs:114:29 | LL | let e = Some("str").map(|s| s.to_string()); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::string::ToString::to_string` error: redundant closure - --> tests/ui/eta.rs:104:27 + --> tests/ui/eta.rs:116:27 | LL | let e = Some('a').map(|s| s.to_uppercase()); | ^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_uppercase` error: redundant closure - --> tests/ui/eta.rs:106:65 + --> tests/ui/eta.rs:119:65 | LL | let e: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_ascii_uppercase` error: redundant closure - --> tests/ui/eta.rs:122:23 + --> tests/ui/eta.rs:136:23 | LL | let _ = x.map(|x| x.parse::()); | ^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `str::parse::` error: redundant closure - --> tests/ui/eta.rs:174:22 + --> tests/ui/eta.rs:189:22 | LL | requires_fn_once(|| x()); | ^^^^^^ help: replace the closure with the function itself: `x` error: redundant closure - --> tests/ui/eta.rs:181:27 + --> tests/ui/eta.rs:197:27 | LL | let a = Some(1u8).map(|a| foo_ptr(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo_ptr` error: redundant closure - --> tests/ui/eta.rs:186:27 + --> tests/ui/eta.rs:203:27 | LL | let a = Some(1u8).map(|a| closure(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `closure` error: redundant closure - --> tests/ui/eta.rs:218:28 + --> tests/ui/eta.rs:236:28 | LL | x.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res` error: redundant closure - --> tests/ui/eta.rs:219:28 + --> tests/ui/eta.rs:238:28 | LL | y.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res` error: redundant closure - --> tests/ui/eta.rs:220:28 + --> tests/ui/eta.rs:240:28 | LL | z.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `add_to_res` error: redundant closure - --> tests/ui/eta.rs:227:21 + --> tests/ui/eta.rs:248:21 | LL | Some(1).map(|n| closure(n)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut closure` error: redundant closure - --> tests/ui/eta.rs:231:21 + --> tests/ui/eta.rs:253:21 | LL | Some(1).map(|n| in_loop(n)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `in_loop` error: redundant closure - --> tests/ui/eta.rs:324:18 + --> tests/ui/eta.rs:347:18 | LL | takes_fn_mut(|| f()); | ^^^^^^ help: replace the closure with the function itself: `&mut f` error: redundant closure - --> tests/ui/eta.rs:327:19 + --> tests/ui/eta.rs:351:19 | LL | takes_fn_once(|| f()); | ^^^^^^ help: replace the closure with the function itself: `&mut f` error: redundant closure - --> tests/ui/eta.rs:331:26 + --> tests/ui/eta.rs:356:26 | LL | move || takes_fn_mut(|| f_used_once()) | ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut f_used_once` error: redundant closure - --> tests/ui/eta.rs:343:19 + --> tests/ui/eta.rs:369:19 | LL | array_opt.map(|a| a.as_slice()); | ^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8; 3]>::as_slice` error: redundant closure - --> tests/ui/eta.rs:346:19 + --> tests/ui/eta.rs:373:19 | LL | slice_opt.map(|s| s.len()); | ^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8]>::len` error: redundant closure - --> tests/ui/eta.rs:349:17 + --> tests/ui/eta.rs:377:17 | LL | ptr_opt.map(|p| p.is_null()); | ^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<*const usize>::is_null` error: redundant closure - --> tests/ui/eta.rs:353:17 + --> tests/ui/eta.rs:382:17 | LL | dyn_opt.map(|d| d.method_on_dyn()); | ^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `::method_on_dyn` error: redundant closure - --> tests/ui/eta.rs:413:19 + --> tests/ui/eta.rs:443:19 | LL | let _ = f(&0, |x, y| f2(x, y)); | ^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `f2` error: redundant closure - --> tests/ui/eta.rs:441:22 + --> tests/ui/eta.rs:472:22 | LL | test.map(|t| t.method()) | ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `Test::method` error: redundant closure - --> tests/ui/eta.rs:445:22 + --> tests/ui/eta.rs:477:22 | LL | test.map(|t| t.method()) | ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `super::Outer::method` error: redundant closure - --> tests/ui/eta.rs:458:18 + --> tests/ui/eta.rs:491:18 | LL | test.map(|t| t.method()) | ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `test_mod::Test::method` error: redundant closure - --> tests/ui/eta.rs:465:30 + --> tests/ui/eta.rs:499:30 | LL | test.map(|t| t.method()) | ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `crate::issue_10854::d::Test::method` error: redundant closure - --> tests/ui/eta.rs:484:38 + --> tests/ui/eta.rs:519:38 | LL | let x = Box::new(|| None.map(|x| f(x))); | ^^^^^^^^ help: replace the closure with the function itself: `&f` error: redundant closure - --> tests/ui/eta.rs:488:38 + --> tests/ui/eta.rs:524:38 | LL | let x = Box::new(|| None.map(|x| f(x))); | ^^^^^^^^ help: replace the closure with the function itself: `f` error: redundant closure - --> tests/ui/eta.rs:505:35 + --> tests/ui/eta.rs:542:35 | LL | let _field = bind.or_else(|| get_default()).unwrap(); | ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `get_default` diff --git a/tests/ui/eta_nostd.fixed b/tests/ui/eta_nostd.fixed index 23059c52b67f..134af34a826a 100644 --- a/tests/ui/eta_nostd.fixed +++ b/tests/ui/eta_nostd.fixed @@ -7,4 +7,5 @@ use alloc::vec::Vec; fn issue_13895() { let _: Option> = true.then(alloc::vec::Vec::new); + //~^ redundant_closure } diff --git a/tests/ui/eta_nostd.rs b/tests/ui/eta_nostd.rs index ae44ac348c64..8d0541bedb2e 100644 --- a/tests/ui/eta_nostd.rs +++ b/tests/ui/eta_nostd.rs @@ -7,4 +7,5 @@ use alloc::vec::Vec; fn issue_13895() { let _: Option> = true.then(|| vec![]); + //~^ redundant_closure } diff --git a/tests/ui/excessive_precision.fixed b/tests/ui/excessive_precision.fixed index 372f64f7d99e..99d09774d16d 100644 --- a/tests/ui/excessive_precision.fixed +++ b/tests/ui/excessive_precision.fixed @@ -18,16 +18,22 @@ fn main() { const GOOD64_DOT: f32 = 10_000_000_000_000_000.0; const BAD32_1: f32 = 0.123_456_79_f32; + //~^ excessive_precision const BAD32_2: f32 = 0.123_456_79; + //~^ excessive_precision const BAD32_3: f32 = 0.1; + //~^ excessive_precision const BAD32_EDGE: f32 = 1.000_001; + //~^ excessive_precision const BAD64_1: f64 = 0.123_456_789_012_345_67f64; const BAD64_2: f64 = 0.123_456_789_012_345_67; const BAD64_3: f64 = 0.1; + //~^ excessive_precision // Literal as param println!("{:?}", 8.888_888_888_888_89); + //~^ excessive_precision // // TODO add inferred type tests for f32 // Locals @@ -39,8 +45,11 @@ fn main() { let good64_inf = 0.123_456_789_012; let bad32: f32 = 1.123_456_8; + //~^ excessive_precision let bad32_suf: f32 = 1.123_456_8_f32; + //~^ excessive_precision let bad32_inf = 1.123_456_8_f32; + //~^ excessive_precision let bad64: f64 = 0.123_456_789_012_345_67; let bad64_suf: f64 = 0.123_456_789_012_345_67f64; @@ -51,14 +60,18 @@ fn main() { let good_vec64: Vec = vec![0.123_456_789]; let bad_vec32: Vec = vec![0.123_456_79]; + //~^ excessive_precision let bad_vec64: Vec = vec![0.123_456_789_123_456_78]; + //~^ excessive_precision // Exponential float notation let good_e32: f32 = 1e-10; let bad_e32: f32 = 1.123_456_8e-10; + //~^ excessive_precision let good_bige32: f32 = 1E-10; let bad_bige32: f32 = 1.123_456_8E-10; + //~^ excessive_precision // Inferred type let good_inferred: f32 = 1f32 * 1_000_000_000.; @@ -68,9 +81,11 @@ fn main() { // issue #7744 let _ = 2.225_073_858_507_201e-308_f64; + //~^ excessive_precision // issue #7745 let _ = 0_f64; + //~^ excessive_precision // issue #9910 const INF1: f32 = 1.0e+33f32; @@ -81,5 +96,6 @@ fn main() { // issue #12954 const _: f64 = 3.0; + //~^ excessive_precision const _: f64 = 3.0000000000000000; } diff --git a/tests/ui/excessive_precision.rs b/tests/ui/excessive_precision.rs index 1e40efbf2452..a542fb2e7e3c 100644 --- a/tests/ui/excessive_precision.rs +++ b/tests/ui/excessive_precision.rs @@ -18,16 +18,22 @@ fn main() { const GOOD64_DOT: f32 = 10_000_000_000_000_000.0; const BAD32_1: f32 = 0.123_456_789_f32; + //~^ excessive_precision const BAD32_2: f32 = 0.123_456_789; + //~^ excessive_precision const BAD32_3: f32 = 0.100_000_000_000_1; + //~^ excessive_precision const BAD32_EDGE: f32 = 1.000_000_9; + //~^ excessive_precision const BAD64_1: f64 = 0.123_456_789_012_345_67f64; const BAD64_2: f64 = 0.123_456_789_012_345_67; const BAD64_3: f64 = 0.100_000_000_000_000_000_1; + //~^ excessive_precision // Literal as param println!("{:?}", 8.888_888_888_888_888_888_888); + //~^ excessive_precision // // TODO add inferred type tests for f32 // Locals @@ -39,8 +45,11 @@ fn main() { let good64_inf = 0.123_456_789_012; let bad32: f32 = 1.123_456_789; + //~^ excessive_precision let bad32_suf: f32 = 1.123_456_789_f32; + //~^ excessive_precision let bad32_inf = 1.123_456_789_f32; + //~^ excessive_precision let bad64: f64 = 0.123_456_789_012_345_67; let bad64_suf: f64 = 0.123_456_789_012_345_67f64; @@ -51,14 +60,18 @@ fn main() { let good_vec64: Vec = vec![0.123_456_789]; let bad_vec32: Vec = vec![0.123_456_789]; + //~^ excessive_precision let bad_vec64: Vec = vec![0.123_456_789_123_456_789]; + //~^ excessive_precision // Exponential float notation let good_e32: f32 = 1e-10; let bad_e32: f32 = 1.123_456_788_888e-10; + //~^ excessive_precision let good_bige32: f32 = 1E-10; let bad_bige32: f32 = 1.123_456_788_888E-10; + //~^ excessive_precision // Inferred type let good_inferred: f32 = 1f32 * 1_000_000_000.; @@ -68,9 +81,11 @@ fn main() { // issue #7744 let _ = 2.225_073_858_507_201_1e-308_f64; + //~^ excessive_precision // issue #7745 let _ = 1.000_000_000_000_001e-324_f64; + //~^ excessive_precision // issue #9910 const INF1: f32 = 1.0e+33f32; @@ -81,5 +96,6 @@ fn main() { // issue #12954 const _: f64 = 3.0000000000000000e+00; + //~^ excessive_precision const _: f64 = 3.0000000000000000; } diff --git a/tests/ui/excessive_precision.stderr b/tests/ui/excessive_precision.stderr index b1f12eed4200..934a367e1065 100644 --- a/tests/ui/excessive_precision.stderr +++ b/tests/ui/excessive_precision.stderr @@ -13,7 +13,7 @@ LL + const BAD32_1: f32 = 0.123_456_79_f32; | error: float has excessive precision - --> tests/ui/excessive_precision.rs:21:26 + --> tests/ui/excessive_precision.rs:22:26 | LL | const BAD32_2: f32 = 0.123_456_789; | ^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + const BAD32_2: f32 = 0.123_456_79; | error: float has excessive precision - --> tests/ui/excessive_precision.rs:22:26 + --> tests/ui/excessive_precision.rs:24:26 | LL | const BAD32_3: f32 = 0.100_000_000_000_1; | ^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + const BAD32_3: f32 = 0.1; | error: float has excessive precision - --> tests/ui/excessive_precision.rs:23:29 + --> tests/ui/excessive_precision.rs:26:29 | LL | const BAD32_EDGE: f32 = 1.000_000_9; | ^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + const BAD32_EDGE: f32 = 1.000_001; | error: float has excessive precision - --> tests/ui/excessive_precision.rs:27:26 + --> tests/ui/excessive_precision.rs:31:26 | LL | const BAD64_3: f64 = 0.100_000_000_000_000_000_1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + const BAD64_3: f64 = 0.1; | error: float has excessive precision - --> tests/ui/excessive_precision.rs:30:22 + --> tests/ui/excessive_precision.rs:35:22 | LL | println!("{:?}", 8.888_888_888_888_888_888_888); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + println!("{:?}", 8.888_888_888_888_89); | error: float has excessive precision - --> tests/ui/excessive_precision.rs:41:22 + --> tests/ui/excessive_precision.rs:47:22 | LL | let bad32: f32 = 1.123_456_789; | ^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + let bad32: f32 = 1.123_456_8; | error: float has excessive precision - --> tests/ui/excessive_precision.rs:42:26 + --> tests/ui/excessive_precision.rs:49:26 | LL | let bad32_suf: f32 = 1.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL + let bad32_suf: f32 = 1.123_456_8_f32; | error: float has excessive precision - --> tests/ui/excessive_precision.rs:43:21 + --> tests/ui/excessive_precision.rs:51:21 | LL | let bad32_inf = 1.123_456_789_f32; | ^^^^^^^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL + let bad32_inf = 1.123_456_8_f32; | error: float has excessive precision - --> tests/ui/excessive_precision.rs:53:36 + --> tests/ui/excessive_precision.rs:62:36 | LL | let bad_vec32: Vec = vec![0.123_456_789]; | ^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL + let bad_vec32: Vec = vec![0.123_456_79]; | error: float has excessive precision - --> tests/ui/excessive_precision.rs:54:36 + --> tests/ui/excessive_precision.rs:64:36 | LL | let bad_vec64: Vec = vec![0.123_456_789_123_456_789]; | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL + let bad_vec64: Vec = vec![0.123_456_789_123_456_78]; | error: float has excessive precision - --> tests/ui/excessive_precision.rs:58:24 + --> tests/ui/excessive_precision.rs:69:24 | LL | let bad_e32: f32 = 1.123_456_788_888e-10; | ^^^^^^^^^^^^^^^^^^^^^ @@ -145,7 +145,7 @@ LL + let bad_e32: f32 = 1.123_456_8e-10; | error: float has excessive precision - --> tests/ui/excessive_precision.rs:61:27 + --> tests/ui/excessive_precision.rs:73:27 | LL | let bad_bige32: f32 = 1.123_456_788_888E-10; | ^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL + let bad_bige32: f32 = 1.123_456_8E-10; | error: float has excessive precision - --> tests/ui/excessive_precision.rs:70:13 + --> tests/ui/excessive_precision.rs:83:13 | LL | let _ = 2.225_073_858_507_201_1e-308_f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -169,7 +169,7 @@ LL + let _ = 2.225_073_858_507_201e-308_f64; | error: float has excessive precision - --> tests/ui/excessive_precision.rs:73:13 + --> tests/ui/excessive_precision.rs:87:13 | LL | let _ = 1.000_000_000_000_001e-324_f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -181,7 +181,7 @@ LL + let _ = 0_f64; | error: float has excessive precision - --> tests/ui/excessive_precision.rs:83:20 + --> tests/ui/excessive_precision.rs:98:20 | LL | const _: f64 = 3.0000000000000000e+00; | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/exhaustive_items.fixed b/tests/ui/exhaustive_items.fixed index 1bf33a5f2f13..79c74aeefbd8 100644 --- a/tests/ui/exhaustive_items.fixed +++ b/tests/ui/exhaustive_items.fixed @@ -8,6 +8,7 @@ fn main() { pub mod enums { #[non_exhaustive] pub enum Exhaustive { + //~^ exhaustive_enums Foo, Bar, Baz, @@ -18,6 +19,7 @@ pub mod enums { #[repr(C)] #[non_exhaustive] pub enum ExhaustiveWithAttrs { + //~^ exhaustive_enums Foo, Bar, Baz, @@ -54,6 +56,7 @@ pub mod enums { pub mod structs { #[non_exhaustive] pub struct Exhaustive { + //~^ exhaustive_structs pub foo: u8, pub bar: String, } diff --git a/tests/ui/exhaustive_items.rs b/tests/ui/exhaustive_items.rs index 1328791e186d..4e851f4c492e 100644 --- a/tests/ui/exhaustive_items.rs +++ b/tests/ui/exhaustive_items.rs @@ -7,6 +7,7 @@ fn main() { pub mod enums { pub enum Exhaustive { + //~^ exhaustive_enums Foo, Bar, Baz, @@ -16,6 +17,7 @@ pub mod enums { /// Some docs #[repr(C)] pub enum ExhaustiveWithAttrs { + //~^ exhaustive_enums Foo, Bar, Baz, @@ -51,6 +53,7 @@ pub mod enums { pub mod structs { pub struct Exhaustive { + //~^ exhaustive_structs pub foo: u8, pub bar: String, } diff --git a/tests/ui/exhaustive_items.stderr b/tests/ui/exhaustive_items.stderr index 536fbe8d790f..c92c8a9efaae 100644 --- a/tests/ui/exhaustive_items.stderr +++ b/tests/ui/exhaustive_items.stderr @@ -2,6 +2,7 @@ error: exported enums should not be exhaustive --> tests/ui/exhaustive_items.rs:9:5 | LL | / pub enum Exhaustive { +LL | | LL | | Foo, LL | | Bar, LL | | Baz, @@ -21,9 +22,10 @@ LL ~ pub enum Exhaustive { | error: exported enums should not be exhaustive - --> tests/ui/exhaustive_items.rs:18:5 + --> tests/ui/exhaustive_items.rs:19:5 | LL | / pub enum ExhaustiveWithAttrs { +LL | | LL | | Foo, LL | | Bar, LL | | Baz, @@ -38,9 +40,10 @@ LL ~ pub enum ExhaustiveWithAttrs { | error: exported structs should not be exhaustive - --> tests/ui/exhaustive_items.rs:53:5 + --> tests/ui/exhaustive_items.rs:55:5 | LL | / pub struct Exhaustive { +LL | | LL | | pub foo: u8, LL | | pub bar: String, LL | | } diff --git a/tests/ui/exit1.rs b/tests/ui/exit1.rs index 36b3c42fd995..be8752cc7d8e 100644 --- a/tests/ui/exit1.rs +++ b/tests/ui/exit1.rs @@ -3,8 +3,7 @@ fn not_main() { if true { std::process::exit(4); - //~^ ERROR: usage of `process::exit` - //~| NOTE: `-D clippy::exit` implied by `-D warnings` + //~^ exit } } diff --git a/tests/ui/exit2.rs b/tests/ui/exit2.rs index 9bbb7b073a4b..2be8a84b6d4b 100644 --- a/tests/ui/exit2.rs +++ b/tests/ui/exit2.rs @@ -2,8 +2,7 @@ fn also_not_main() { std::process::exit(3); - //~^ ERROR: usage of `process::exit` - //~| NOTE: `-D clippy::exit` implied by `-D warnings` + //~^ exit } fn main() { diff --git a/tests/ui/exit3.rs b/tests/ui/exit3.rs index cab908aafd33..a8af1b225788 100644 --- a/tests/ui/exit3.rs +++ b/tests/ui/exit3.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::exit)] fn main() { diff --git a/tests/ui/expect.rs b/tests/ui/expect.rs index f15b3d37e154..8f7379f00214 100644 --- a/tests/ui/expect.rs +++ b/tests/ui/expect.rs @@ -4,15 +4,16 @@ fn expect_option() { let opt = Some(0); let _ = opt.expect(""); - //~^ ERROR: used `expect()` on an `Option` value + //~^ expect_used } fn expect_result() { let res: Result = Ok(0); let _ = res.expect(""); - //~^ ERROR: used `expect()` on a `Result` value + //~^ expect_used + let _ = res.expect_err(""); - //~^ ERROR: used `expect_err()` on a `Result` value + //~^ expect_used } fn main() { diff --git a/tests/ui/expect.stderr b/tests/ui/expect.stderr index c0ba3390aac5..70cf3072003e 100644 --- a/tests/ui/expect.stderr +++ b/tests/ui/expect.stderr @@ -17,7 +17,7 @@ LL | let _ = res.expect(""); = note: if this value is an `Err`, it will panic error: used `expect_err()` on a `Result` value - --> tests/ui/expect.rs:14:13 + --> tests/ui/expect.rs:15:13 | LL | let _ = res.expect_err(""); | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/expect_fun_call.fixed b/tests/ui/expect_fun_call.fixed index 8f800c71941a..73eaebf773c8 100644 --- a/tests/ui/expect_fun_call.fixed +++ b/tests/ui/expect_fun_call.fixed @@ -33,12 +33,15 @@ fn main() { let error_code = 123_i32; let with_none_and_format: Option = None; with_none_and_format.unwrap_or_else(|| panic!("Error {}: fake error", error_code)); + //~^ expect_fun_call let with_none_and_as_str: Option = None; with_none_and_as_str.unwrap_or_else(|| panic!("Error {}: fake error", error_code)); + //~^ expect_fun_call let with_none_and_format_with_macro: Option = None; with_none_and_format_with_macro.unwrap_or_else(|| panic!("Error {}: fake error", one!())); + //~^ expect_fun_call let with_ok: Result<(), ()> = Ok(()); with_ok.expect("error"); @@ -49,9 +52,11 @@ fn main() { let error_code = 123_i32; let with_err_and_format: Result<(), ()> = Err(()); with_err_and_format.unwrap_or_else(|_| panic!("Error {}: fake error", error_code)); + //~^ expect_fun_call let with_err_and_as_str: Result<(), ()> = Err(()); with_err_and_as_str.unwrap_or_else(|_| panic!("Error {}: fake error", error_code)); + //~^ expect_fun_call let with_dummy_type = Foo::new(); with_dummy_type.expect("another test string"); @@ -64,6 +69,7 @@ fn main() { //Issue #2937 Some("foo").unwrap_or_else(|| panic!("{} {}", 1, 2)); + //~^ expect_fun_call //Issue #2979 - this should not lint { @@ -85,26 +91,35 @@ fn main() { } Some("foo").unwrap_or_else(|| { panic!("{}", get_string()) }); + //~^ expect_fun_call Some("foo").unwrap_or_else(|| { panic!("{}", get_string()) }); + //~^ expect_fun_call Some("foo").unwrap_or_else(|| { panic!("{}", get_string()) }); + //~^ expect_fun_call Some("foo").unwrap_or_else(|| { panic!("{}", get_static_str()) }); + //~^ expect_fun_call Some("foo").unwrap_or_else(|| { panic!("{}", get_non_static_str(&0).to_string()) }); + //~^ expect_fun_call } //Issue #3839 Some(true).unwrap_or_else(|| panic!("key {}, {}", 1, 2)); + //~^ expect_fun_call //Issue #4912 - the receiver is a &Option { let opt = Some(1); let opt_ref = &opt; opt_ref.unwrap_or_else(|| panic!("{:?}", opt_ref)); + //~^ expect_fun_call } let format_capture: Option = None; format_capture.unwrap_or_else(|| panic!("{error_code}")); + //~^ expect_fun_call let format_capture_and_value: Option = None; format_capture_and_value.unwrap_or_else(|| panic!("{error_code}, {}", 1)); + //~^ expect_fun_call } diff --git a/tests/ui/expect_fun_call.rs b/tests/ui/expect_fun_call.rs index b5cfafb2993e..ecebc9ebfb6f 100644 --- a/tests/ui/expect_fun_call.rs +++ b/tests/ui/expect_fun_call.rs @@ -33,12 +33,15 @@ fn main() { let error_code = 123_i32; let with_none_and_format: Option = None; with_none_and_format.expect(&format!("Error {}: fake error", error_code)); + //~^ expect_fun_call let with_none_and_as_str: Option = None; with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); + //~^ expect_fun_call let with_none_and_format_with_macro: Option = None; with_none_and_format_with_macro.expect(format!("Error {}: fake error", one!()).as_str()); + //~^ expect_fun_call let with_ok: Result<(), ()> = Ok(()); with_ok.expect("error"); @@ -49,9 +52,11 @@ fn main() { let error_code = 123_i32; let with_err_and_format: Result<(), ()> = Err(()); with_err_and_format.expect(&format!("Error {}: fake error", error_code)); + //~^ expect_fun_call let with_err_and_as_str: Result<(), ()> = Err(()); with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); + //~^ expect_fun_call let with_dummy_type = Foo::new(); with_dummy_type.expect("another test string"); @@ -64,6 +69,7 @@ fn main() { //Issue #2937 Some("foo").expect(format!("{} {}", 1, 2).as_ref()); + //~^ expect_fun_call //Issue #2979 - this should not lint { @@ -85,26 +91,35 @@ fn main() { } Some("foo").expect(&get_string()); + //~^ expect_fun_call Some("foo").expect(get_string().as_ref()); + //~^ expect_fun_call Some("foo").expect(get_string().as_str()); + //~^ expect_fun_call Some("foo").expect(get_static_str()); + //~^ expect_fun_call Some("foo").expect(get_non_static_str(&0)); + //~^ expect_fun_call } //Issue #3839 Some(true).expect(&format!("key {}, {}", 1, 2)); + //~^ expect_fun_call //Issue #4912 - the receiver is a &Option { let opt = Some(1); let opt_ref = &opt; opt_ref.expect(&format!("{:?}", opt_ref)); + //~^ expect_fun_call } let format_capture: Option = None; format_capture.expect(&format!("{error_code}")); + //~^ expect_fun_call let format_capture_and_value: Option = None; format_capture_and_value.expect(&format!("{error_code}, {}", 1)); + //~^ expect_fun_call } diff --git a/tests/ui/expect_fun_call.stderr b/tests/ui/expect_fun_call.stderr index 050c039f834d..36713196cb92 100644 --- a/tests/ui/expect_fun_call.stderr +++ b/tests/ui/expect_fun_call.stderr @@ -8,85 +8,85 @@ LL | with_none_and_format.expect(&format!("Error {}: fake error", error_code = help: to override `-D warnings` add `#[allow(clippy::expect_fun_call)]` error: function call inside of `expect` - --> tests/ui/expect_fun_call.rs:38:26 + --> tests/ui/expect_fun_call.rs:39:26 | LL | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))` error: function call inside of `expect` - --> tests/ui/expect_fun_call.rs:41:37 + --> tests/ui/expect_fun_call.rs:43:37 | LL | with_none_and_format_with_macro.expect(format!("Error {}: fake error", one!()).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("Error {}: fake error", one!()))` error: function call inside of `expect` - --> tests/ui/expect_fun_call.rs:51:25 + --> tests/ui/expect_fun_call.rs:54:25 | LL | with_err_and_format.expect(&format!("Error {}: fake error", error_code)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` error: function call inside of `expect` - --> tests/ui/expect_fun_call.rs:54:25 + --> tests/ui/expect_fun_call.rs:58:25 | LL | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))` error: function call inside of `expect` - --> tests/ui/expect_fun_call.rs:66:17 + --> tests/ui/expect_fun_call.rs:71:17 | LL | Some("foo").expect(format!("{} {}", 1, 2).as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{} {}", 1, 2))` error: function call inside of `expect` - --> tests/ui/expect_fun_call.rs:87:21 + --> tests/ui/expect_fun_call.rs:93:21 | LL | Some("foo").expect(&get_string()); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_string()) })` error: function call inside of `expect` - --> tests/ui/expect_fun_call.rs:88:21 + --> tests/ui/expect_fun_call.rs:95:21 | LL | Some("foo").expect(get_string().as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_string()) })` error: function call inside of `expect` - --> tests/ui/expect_fun_call.rs:89:21 + --> tests/ui/expect_fun_call.rs:97:21 | LL | Some("foo").expect(get_string().as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_string()) })` error: function call inside of `expect` - --> tests/ui/expect_fun_call.rs:91:21 + --> tests/ui/expect_fun_call.rs:100:21 | LL | Some("foo").expect(get_static_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_static_str()) })` error: function call inside of `expect` - --> tests/ui/expect_fun_call.rs:92:21 + --> tests/ui/expect_fun_call.rs:102:21 | LL | Some("foo").expect(get_non_static_str(&0)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_non_static_str(&0).to_string()) })` error: function call inside of `expect` - --> tests/ui/expect_fun_call.rs:96:16 + --> tests/ui/expect_fun_call.rs:107:16 | LL | Some(true).expect(&format!("key {}, {}", 1, 2)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("key {}, {}", 1, 2))` error: function call inside of `expect` - --> tests/ui/expect_fun_call.rs:102:17 + --> tests/ui/expect_fun_call.rs:114:17 | LL | opt_ref.expect(&format!("{:?}", opt_ref)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{:?}", opt_ref))` error: function call inside of `expect` - --> tests/ui/expect_fun_call.rs:106:20 + --> tests/ui/expect_fun_call.rs:119:20 | LL | format_capture.expect(&format!("{error_code}")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{error_code}"))` error: function call inside of `expect` - --> tests/ui/expect_fun_call.rs:109:30 + --> tests/ui/expect_fun_call.rs:123:30 | LL | format_capture_and_value.expect(&format!("{error_code}, {}", 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{error_code}, {}", 1))` diff --git a/tests/ui/expect_tool_lint_rfc_2383.rs b/tests/ui/expect_tool_lint_rfc_2383.rs index 2634c56794e7..2295691c8127 100644 --- a/tests/ui/expect_tool_lint_rfc_2383.rs +++ b/tests/ui/expect_tool_lint_rfc_2383.rs @@ -30,11 +30,14 @@ mod rustc_warn { #[expect(dead_code)] //~^ ERROR: this lint expectation is unfulfilled //~| NOTE: `-D unfulfilled-lint-expectations` implied by `-D warnings` + //~| HELP: to override `-D warnings` add `#[allow(unfulfilled_lint_expectations)]` pub fn rustc_lints() { let x = 42; #[expect(invalid_nan_comparisons)] //~^ ERROR: this lint expectation is unfulfilled + //~| NOTE: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + //~| ERROR: this lint expectation is unfulfilled let _b = x == 5; } } diff --git a/tests/ui/expect_tool_lint_rfc_2383.stderr b/tests/ui/expect_tool_lint_rfc_2383.stderr index 028e22ca724e..b274d5c23693 100644 --- a/tests/ui/expect_tool_lint_rfc_2383.stderr +++ b/tests/ui/expect_tool_lint_rfc_2383.stderr @@ -8,13 +8,13 @@ LL | #[expect(dead_code)] = help: to override `-D warnings` add `#[allow(unfulfilled_lint_expectations)]` error: this lint expectation is unfulfilled - --> tests/ui/expect_tool_lint_rfc_2383.rs:36:18 + --> tests/ui/expect_tool_lint_rfc_2383.rs:37:18 | LL | #[expect(invalid_nan_comparisons)] | ^^^^^^^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> tests/ui/expect_tool_lint_rfc_2383.rs:36:18 + --> tests/ui/expect_tool_lint_rfc_2383.rs:37:18 | LL | #[expect(invalid_nan_comparisons)] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,25 +22,25 @@ LL | #[expect(invalid_nan_comparisons)] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: this lint expectation is unfulfilled - --> tests/ui/expect_tool_lint_rfc_2383.rs:107:14 + --> tests/ui/expect_tool_lint_rfc_2383.rs:110:14 | LL | #[expect(clippy::almost_swapped)] | ^^^^^^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> tests/ui/expect_tool_lint_rfc_2383.rs:115:14 + --> tests/ui/expect_tool_lint_rfc_2383.rs:118:14 | LL | #[expect(clippy::bytes_nth)] | ^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> tests/ui/expect_tool_lint_rfc_2383.rs:121:14 + --> tests/ui/expect_tool_lint_rfc_2383.rs:124:14 | LL | #[expect(clippy::if_same_then_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> tests/ui/expect_tool_lint_rfc_2383.rs:127:14 + --> tests/ui/expect_tool_lint_rfc_2383.rs:130:14 | LL | #[expect(clippy::overly_complex_bool_expr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/explicit_auto_deref.fixed b/tests/ui/explicit_auto_deref.fixed index 9d476259b87e..7235f7d5b82a 100644 --- a/tests/ui/explicit_auto_deref.fixed +++ b/tests/ui/explicit_auto_deref.fixed @@ -67,43 +67,55 @@ fn main() { let s = String::new(); let _: &str = &s; + //~^ explicit_auto_deref let _: &str = &{ String::new() }; + //~^ explicit_auto_deref let _: &str = &mut { String::new() }; + //~^ explicit_auto_deref let _ = &*s; // Don't lint. Inferred type would change. let _: &_ = &*s; // Don't lint. Inferred type would change. f_str(&s); + //~^ explicit_auto_deref f_t(&*s); // Don't lint. Inferred type would change. f_ref_t(&*s); // Don't lint. Inferred type would change. f_str_t(&s, &*s); // Don't lint second param. + // + //~^^ explicit_auto_deref let b = Box::new(Box::new(Box::new(5))); let _: &Box = &b; + //~^ explicit_auto_deref let _: &Box<_> = &**b; // Don't lint. Inferred type would change. f_box_t(&**b); // Don't lint. Inferred type would change. let c = |_x: &str| (); c(&s); + //~^ explicit_auto_deref let c = |_x| (); c(&*s); // Don't lint. Inferred type would change. fn _f(x: &String) -> &str { x + //~^ explicit_auto_deref } fn _f1(x: &String) -> &str { { x } + //~^ explicit_auto_deref } fn _f2(x: &String) -> &str { { x } + //~^ explicit_auto_deref } fn _f3(x: &Box>>) -> &Box { x + //~^ explicit_auto_deref } fn _f4( @@ -121,25 +133,38 @@ fn main() { f11: &dyn CallableT, ) { f1(&x); + //~^ explicit_auto_deref f2(&x); + //~^ explicit_auto_deref f3(&x); + //~^ explicit_auto_deref f4.callable_str()(&x); + //~^ explicit_auto_deref f5(&x); + //~^ explicit_auto_deref f6(&x); + //~^ explicit_auto_deref f7.callable_str()(&x); + //~^ explicit_auto_deref f8.callable_t()(&x); + //~^ explicit_auto_deref f9(&x); + //~^ explicit_auto_deref f10(&x); + //~^ explicit_auto_deref f11.callable_t()(&x); + //~^ explicit_auto_deref } struct S1<'a>(&'a str); let _ = S1(&s); + //~^ explicit_auto_deref struct S2<'a> { s: &'a str, } let _ = S2 { s: &s }; + //~^ explicit_auto_deref struct S3<'a, T: ?Sized>(&'a T); let _ = S3(&*s); // Don't lint. Inferred type would change. @@ -156,11 +181,15 @@ fn main() { impl<'a> E1<'a> { fn m1(s: &'a String) { let _ = Self::S1(s); + //~^ explicit_auto_deref let _ = Self::S2 { s: s }; + //~^ explicit_auto_deref } } let _ = E1::S1(&s); + //~^ explicit_auto_deref let _ = E1::S2 { s: &s }; + //~^ explicit_auto_deref enum E2<'a, T: ?Sized> { S1(&'a T), @@ -179,7 +208,9 @@ fn main() { let b = Box::new(Box::new(S5 { foo: 5 })); let _ = b.foo; let _ = b.foo; + //~^ explicit_auto_deref let _ = b.foo; + //~^ explicit_auto_deref struct S6 { foo: S5, @@ -195,8 +226,10 @@ fn main() { let ref_str = &"foo"; let _ = f_str(ref_str); + //~^ explicit_auto_deref let ref_ref_str = &ref_str; let _ = f_str(ref_ref_str); + //~^ explicit_auto_deref fn _f5(x: &u32) -> u32 { if true { @@ -207,7 +240,11 @@ fn main() { } f_str(&ref_str); // `needless_borrow` will suggest removing both references + // + //~^^ explicit_auto_deref f_str(&ref_str); // `needless_borrow` will suggest removing only one reference + // + //~^^ explicit_auto_deref let x = &&40; unsafe { @@ -217,6 +254,7 @@ fn main() { let s = &"str"; let _ = || return *s; let _ = || -> &'static str { return s }; + //~^ explicit_auto_deref struct X; struct Y(X); @@ -236,6 +274,7 @@ fn main() { fn deref_to_u>(x: &T) -> &U { x + //~^ explicit_auto_deref } let _ = |x: &'static Box>| -> &'static dyn Iterator { &**x }; @@ -259,11 +298,14 @@ fn main() { let c1 = |_: &Vec<&u32>| {}; let x = &&vec![&1u32]; c1(x); + //~^ explicit_auto_deref let _ = for<'a, 'b> |x: &'a &'a Vec<&'b u32>, b: bool| -> &'a Vec<&'b u32> { if b { return x; + //~^ explicit_auto_deref } x + //~^ explicit_auto_deref }; trait WithAssoc { @@ -298,6 +340,7 @@ fn main() { // Issue #11366 let _: &mut u32 = match &mut Some(&mut 0u32) { Some(x) => x, + //~^ explicit_auto_deref None => panic!(), }; @@ -331,18 +374,23 @@ fn main() { }; let _ = &mut (*x.u).x; let _ = &mut { x.u }.x; + //~^ explicit_auto_deref let _ = &mut ({ *x.u }).x; let mut x = U { u: Wrap(core::mem::ManuallyDrop::new(S8 { x: "" })), }; let _ = &mut (*x.u).x; + //~^ explicit_auto_deref let _ = &mut { x.u }.x; + //~^ explicit_auto_deref let _ = &mut ({ **x.u }).x; let mut x = U { u: Wrap(S8 { x: "" }) }; let _ = &mut x.u.x; + //~^ explicit_auto_deref let _ = &mut { x.u }.x; + //~^ explicit_auto_deref let _ = &mut ({ *x.u }).x; } } @@ -366,6 +414,7 @@ mod issue_12969 { let wrapped_bar = Wrapper(""); foo(&wrapped_bar); + //~^ explicit_auto_deref } } diff --git a/tests/ui/explicit_auto_deref.rs b/tests/ui/explicit_auto_deref.rs index 23307c837f0e..c4d2b28ff4b5 100644 --- a/tests/ui/explicit_auto_deref.rs +++ b/tests/ui/explicit_auto_deref.rs @@ -67,43 +67,55 @@ fn main() { let s = String::new(); let _: &str = &*s; + //~^ explicit_auto_deref let _: &str = &*{ String::new() }; + //~^ explicit_auto_deref let _: &str = &mut *{ String::new() }; + //~^ explicit_auto_deref let _ = &*s; // Don't lint. Inferred type would change. let _: &_ = &*s; // Don't lint. Inferred type would change. f_str(&*s); + //~^ explicit_auto_deref f_t(&*s); // Don't lint. Inferred type would change. f_ref_t(&*s); // Don't lint. Inferred type would change. f_str_t(&*s, &*s); // Don't lint second param. + // + //~^^ explicit_auto_deref let b = Box::new(Box::new(Box::new(5))); let _: &Box = &**b; + //~^ explicit_auto_deref let _: &Box<_> = &**b; // Don't lint. Inferred type would change. f_box_t(&**b); // Don't lint. Inferred type would change. let c = |_x: &str| (); c(&*s); + //~^ explicit_auto_deref let c = |_x| (); c(&*s); // Don't lint. Inferred type would change. fn _f(x: &String) -> &str { &**x + //~^ explicit_auto_deref } fn _f1(x: &String) -> &str { { &**x } + //~^ explicit_auto_deref } fn _f2(x: &String) -> &str { &**{ x } + //~^ explicit_auto_deref } fn _f3(x: &Box>>) -> &Box { &***x + //~^ explicit_auto_deref } fn _f4( @@ -121,25 +133,38 @@ fn main() { f11: &dyn CallableT, ) { f1(&*x); + //~^ explicit_auto_deref f2(&*x); + //~^ explicit_auto_deref f3(&*x); + //~^ explicit_auto_deref f4.callable_str()(&*x); + //~^ explicit_auto_deref f5(&*x); + //~^ explicit_auto_deref f6(&*x); + //~^ explicit_auto_deref f7.callable_str()(&*x); + //~^ explicit_auto_deref f8.callable_t()(&*x); + //~^ explicit_auto_deref f9(&*x); + //~^ explicit_auto_deref f10(&*x); + //~^ explicit_auto_deref f11.callable_t()(&*x); + //~^ explicit_auto_deref } struct S1<'a>(&'a str); let _ = S1(&*s); + //~^ explicit_auto_deref struct S2<'a> { s: &'a str, } let _ = S2 { s: &*s }; + //~^ explicit_auto_deref struct S3<'a, T: ?Sized>(&'a T); let _ = S3(&*s); // Don't lint. Inferred type would change. @@ -156,11 +181,15 @@ fn main() { impl<'a> E1<'a> { fn m1(s: &'a String) { let _ = Self::S1(&**s); + //~^ explicit_auto_deref let _ = Self::S2 { s: &**s }; + //~^ explicit_auto_deref } } let _ = E1::S1(&*s); + //~^ explicit_auto_deref let _ = E1::S2 { s: &*s }; + //~^ explicit_auto_deref enum E2<'a, T: ?Sized> { S1(&'a T), @@ -179,7 +208,9 @@ fn main() { let b = Box::new(Box::new(S5 { foo: 5 })); let _ = b.foo; let _ = (*b).foo; + //~^ explicit_auto_deref let _ = (**b).foo; + //~^ explicit_auto_deref struct S6 { foo: S5, @@ -195,8 +226,10 @@ fn main() { let ref_str = &"foo"; let _ = f_str(*ref_str); + //~^ explicit_auto_deref let ref_ref_str = &ref_str; let _ = f_str(**ref_ref_str); + //~^ explicit_auto_deref fn _f5(x: &u32) -> u32 { if true { @@ -207,7 +240,11 @@ fn main() { } f_str(&&*ref_str); // `needless_borrow` will suggest removing both references + // + //~^^ explicit_auto_deref f_str(&&**ref_str); // `needless_borrow` will suggest removing only one reference + // + //~^^ explicit_auto_deref let x = &&40; unsafe { @@ -217,6 +254,7 @@ fn main() { let s = &"str"; let _ = || return *s; let _ = || -> &'static str { return *s }; + //~^ explicit_auto_deref struct X; struct Y(X); @@ -236,6 +274,7 @@ fn main() { fn deref_to_u>(x: &T) -> &U { &**x + //~^ explicit_auto_deref } let _ = |x: &'static Box>| -> &'static dyn Iterator { &**x }; @@ -259,11 +298,14 @@ fn main() { let c1 = |_: &Vec<&u32>| {}; let x = &&vec![&1u32]; c1(*x); + //~^ explicit_auto_deref let _ = for<'a, 'b> |x: &'a &'a Vec<&'b u32>, b: bool| -> &'a Vec<&'b u32> { if b { return *x; + //~^ explicit_auto_deref } *x + //~^ explicit_auto_deref }; trait WithAssoc { @@ -298,6 +340,7 @@ fn main() { // Issue #11366 let _: &mut u32 = match &mut Some(&mut 0u32) { Some(x) => &mut *x, + //~^ explicit_auto_deref None => panic!(), }; @@ -331,18 +374,23 @@ fn main() { }; let _ = &mut (*x.u).x; let _ = &mut (*{ x.u }).x; + //~^ explicit_auto_deref let _ = &mut ({ *x.u }).x; let mut x = U { u: Wrap(core::mem::ManuallyDrop::new(S8 { x: "" })), }; let _ = &mut (**x.u).x; + //~^ explicit_auto_deref let _ = &mut (**{ x.u }).x; + //~^ explicit_auto_deref let _ = &mut ({ **x.u }).x; let mut x = U { u: Wrap(S8 { x: "" }) }; let _ = &mut (*x.u).x; + //~^ explicit_auto_deref let _ = &mut (*{ x.u }).x; + //~^ explicit_auto_deref let _ = &mut ({ *x.u }).x; } } @@ -366,6 +414,7 @@ mod issue_12969 { let wrapped_bar = Wrapper(""); foo(&*wrapped_bar); + //~^ explicit_auto_deref } } diff --git a/tests/ui/explicit_auto_deref.stderr b/tests/ui/explicit_auto_deref.stderr index 0b05a554eb11..ba4cd86e0b5a 100644 --- a/tests/ui/explicit_auto_deref.stderr +++ b/tests/ui/explicit_auto_deref.stderr @@ -8,271 +8,271 @@ LL | let _: &str = &*s; = help: to override `-D warnings` add `#[allow(clippy::explicit_auto_deref)]` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:70:19 + --> tests/ui/explicit_auto_deref.rs:71:19 | LL | let _: &str = &*{ String::new() }; | ^^^^^^^^^^^^^^^^^^^ help: try: `&{ String::new() }` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:71:19 + --> tests/ui/explicit_auto_deref.rs:73:19 | LL | let _: &str = &mut *{ String::new() }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut { String::new() }` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:75:11 + --> tests/ui/explicit_auto_deref.rs:78:11 | LL | f_str(&*s); | ^^^ help: try: `&s` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:79:13 + --> tests/ui/explicit_auto_deref.rs:83:13 | LL | f_str_t(&*s, &*s); // Don't lint second param. | ^^^ help: try: `&s` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:82:24 + --> tests/ui/explicit_auto_deref.rs:88:24 | LL | let _: &Box = &**b; | ^^^^ help: try: `&b` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:88:7 + --> tests/ui/explicit_auto_deref.rs:95:7 | LL | c(&*s); | ^^^ help: try: `&s` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:94:9 + --> tests/ui/explicit_auto_deref.rs:102:9 | LL | &**x | ^^^^ help: try: `x` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:98:11 + --> tests/ui/explicit_auto_deref.rs:107:11 | LL | { &**x } | ^^^^ help: try: `x` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:102:9 + --> tests/ui/explicit_auto_deref.rs:112:9 | LL | &**{ x } | ^^^^^^^^ help: try: `{ x }` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:106:9 + --> tests/ui/explicit_auto_deref.rs:117:9 | LL | &***x | ^^^^^ help: try: `x` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:123:12 + --> tests/ui/explicit_auto_deref.rs:135:12 | LL | f1(&*x); | ^^^ help: try: `&x` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:124:12 + --> tests/ui/explicit_auto_deref.rs:137:12 | LL | f2(&*x); | ^^^ help: try: `&x` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:125:12 + --> tests/ui/explicit_auto_deref.rs:139:12 | LL | f3(&*x); | ^^^ help: try: `&x` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:126:27 + --> tests/ui/explicit_auto_deref.rs:141:27 | LL | f4.callable_str()(&*x); | ^^^ help: try: `&x` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:127:12 + --> tests/ui/explicit_auto_deref.rs:143:12 | LL | f5(&*x); | ^^^ help: try: `&x` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:128:12 + --> tests/ui/explicit_auto_deref.rs:145:12 | LL | f6(&*x); | ^^^ help: try: `&x` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:129:27 + --> tests/ui/explicit_auto_deref.rs:147:27 | LL | f7.callable_str()(&*x); | ^^^ help: try: `&x` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:130:25 + --> tests/ui/explicit_auto_deref.rs:149:25 | LL | f8.callable_t()(&*x); | ^^^ help: try: `&x` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:131:12 + --> tests/ui/explicit_auto_deref.rs:151:12 | LL | f9(&*x); | ^^^ help: try: `&x` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:132:13 + --> tests/ui/explicit_auto_deref.rs:153:13 | LL | f10(&*x); | ^^^ help: try: `&x` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:133:26 + --> tests/ui/explicit_auto_deref.rs:155:26 | LL | f11.callable_t()(&*x); | ^^^ help: try: `&x` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:137:16 + --> tests/ui/explicit_auto_deref.rs:160:16 | LL | let _ = S1(&*s); | ^^^ help: try: `&s` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:142:21 + --> tests/ui/explicit_auto_deref.rs:166:21 | LL | let _ = S2 { s: &*s }; | ^^^ help: try: `&s` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:158:30 + --> tests/ui/explicit_auto_deref.rs:183:30 | LL | let _ = Self::S1(&**s); | ^^^^ help: try: `s` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:159:35 + --> tests/ui/explicit_auto_deref.rs:185:35 | LL | let _ = Self::S2 { s: &**s }; | ^^^^ help: try: `s` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:162:20 + --> tests/ui/explicit_auto_deref.rs:189:20 | LL | let _ = E1::S1(&*s); | ^^^ help: try: `&s` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:163:25 + --> tests/ui/explicit_auto_deref.rs:191:25 | LL | let _ = E1::S2 { s: &*s }; | ^^^ help: try: `&s` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:181:13 + --> tests/ui/explicit_auto_deref.rs:210:13 | LL | let _ = (*b).foo; | ^^^^ help: try: `b` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:182:13 + --> tests/ui/explicit_auto_deref.rs:212:13 | LL | let _ = (**b).foo; | ^^^^^ help: try: `b` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:197:19 + --> tests/ui/explicit_auto_deref.rs:228:19 | LL | let _ = f_str(*ref_str); | ^^^^^^^^ help: try: `ref_str` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:199:19 + --> tests/ui/explicit_auto_deref.rs:231:19 | LL | let _ = f_str(**ref_ref_str); | ^^^^^^^^^^^^^ help: try: `ref_ref_str` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:209:12 + --> tests/ui/explicit_auto_deref.rs:242:12 | LL | f_str(&&*ref_str); // `needless_borrow` will suggest removing both references | ^^^^^^^^^ help: try: `ref_str` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:210:12 + --> tests/ui/explicit_auto_deref.rs:245:12 | LL | f_str(&&**ref_str); // `needless_borrow` will suggest removing only one reference | ^^^^^^^^^^ help: try: `ref_str` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:219:41 + --> tests/ui/explicit_auto_deref.rs:256:41 | LL | let _ = || -> &'static str { return *s }; | ^^ help: try: `s` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:238:9 + --> tests/ui/explicit_auto_deref.rs:276:9 | LL | &**x | ^^^^ help: try: `x` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:261:8 + --> tests/ui/explicit_auto_deref.rs:300:8 | LL | c1(*x); | ^^ help: try: `x` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:264:20 + --> tests/ui/explicit_auto_deref.rs:304:20 | LL | return *x; | ^^ help: try: `x` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:266:9 + --> tests/ui/explicit_auto_deref.rs:307:9 | LL | *x | ^^ help: try: `x` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:300:20 + --> tests/ui/explicit_auto_deref.rs:342:20 | LL | Some(x) => &mut *x, | ^^^^^^^ help: try: `x` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:333:22 + --> tests/ui/explicit_auto_deref.rs:376:22 | LL | let _ = &mut (*{ x.u }).x; | ^^^^^^^^^^ help: try: `{ x.u }` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:339:22 + --> tests/ui/explicit_auto_deref.rs:383:22 | LL | let _ = &mut (**x.u).x; | ^^^^^^^ help: try: `(*x.u)` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:340:22 + --> tests/ui/explicit_auto_deref.rs:385:22 | LL | let _ = &mut (**{ x.u }).x; | ^^^^^^^^^^^ help: try: `{ x.u }` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:344:22 + --> tests/ui/explicit_auto_deref.rs:390:22 | LL | let _ = &mut (*x.u).x; | ^^^^^^ help: try: `x.u` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:345:22 + --> tests/ui/explicit_auto_deref.rs:392:22 | LL | let _ = &mut (*{ x.u }).x; | ^^^^^^^^^^ help: try: `{ x.u }` error: deref which would be done by auto-deref - --> tests/ui/explicit_auto_deref.rs:368:13 + --> tests/ui/explicit_auto_deref.rs:416:13 | LL | foo(&*wrapped_bar); | ^^^^^^^^^^^^^ help: try: `&wrapped_bar` diff --git a/tests/ui/explicit_counter_loop.rs b/tests/ui/explicit_counter_loop.rs index 28b477b69215..8340d99ace22 100644 --- a/tests/ui/explicit_counter_loop.rs +++ b/tests/ui/explicit_counter_loop.rs @@ -5,27 +5,30 @@ fn main() { let mut vec = vec![1, 2, 3, 4]; let mut _index = 0; for _v in &vec { - //~^ ERROR: the variable `_index` is used as a loop counter - //~| NOTE: `-D clippy::explicit-counter-loop` implied by `-D warnings` + //~^ explicit_counter_loop + _index += 1 } let mut _index = 1; _index = 0; for _v in &vec { - //~^ ERROR: the variable `_index` is used as a loop counter + //~^ explicit_counter_loop + _index += 1 } let mut _index = 0; for _v in &mut vec { - //~^ ERROR: the variable `_index` is used as a loop counter + //~^ explicit_counter_loop + _index += 1; } let mut _index = 0; for _v in vec { - //~^ ERROR: the variable `_index` is used as a loop counter + //~^ explicit_counter_loop + _index += 1; } @@ -113,7 +116,8 @@ mod issue_1219 { let text = "banana"; let mut count = 0; for ch in text.chars() { - //~^ ERROR: the variable `count` is used as a loop counter + //~^ explicit_counter_loop + println!("{}", count); count += 1; if ch == 'a' { @@ -125,7 +129,8 @@ mod issue_1219 { let text = "banana"; let mut count = 0; for ch in text.chars() { - //~^ ERROR: the variable `count` is used as a loop counter + //~^ explicit_counter_loop + println!("{}", count); count += 1; for i in 0..2 { @@ -184,7 +189,8 @@ mod issue_1670 { pub fn test() { let mut count = 0; for _i in 3..10 { - //~^ ERROR: the variable `count` is used as a loop counter + //~^ explicit_counter_loop + count += 1; } } @@ -225,7 +231,8 @@ mod issue_7920 { // should suggest `enumerate` for _item in slice { - //~^ ERROR: the variable `idx_usize` is used as a loop counter + //~^ explicit_counter_loop + if idx_usize == index_usize { break; } @@ -238,8 +245,8 @@ mod issue_7920 { // should suggest `zip` for _item in slice { - //~^ ERROR: the variable `idx_u32` is used as a loop counter - //~| NOTE: `idx_u32` is of type `u32`, making it ineligible for `Iterator::enumera + //~^ explicit_counter_loop + if idx_u32 == index_u32 { break; } @@ -284,6 +291,7 @@ mod issue_13123 { let mut vec = vec![1, 2, 3, 4]; let mut _index = 0; 'label: for v in vec { + //~^ explicit_counter_loop _index += 1; if v == 1 { break 'label; diff --git a/tests/ui/explicit_counter_loop.stderr b/tests/ui/explicit_counter_loop.stderr index 1b2d1f8570a3..a73516558c20 100644 --- a/tests/ui/explicit_counter_loop.stderr +++ b/tests/ui/explicit_counter_loop.stderr @@ -14,43 +14,43 @@ LL | for _v in &vec { | ^^^^^^^^^^^^^^ help: consider using: `for (_index, _v) in vec.iter().enumerate()` error: the variable `_index` is used as a loop counter - --> tests/ui/explicit_counter_loop.rs:21:5 + --> tests/ui/explicit_counter_loop.rs:22:5 | LL | for _v in &mut vec { | ^^^^^^^^^^^^^^^^^^ help: consider using: `for (_index, _v) in vec.iter_mut().enumerate()` error: the variable `_index` is used as a loop counter - --> tests/ui/explicit_counter_loop.rs:27:5 + --> tests/ui/explicit_counter_loop.rs:29:5 | LL | for _v in vec { | ^^^^^^^^^^^^^ help: consider using: `for (_index, _v) in vec.into_iter().enumerate()` error: the variable `count` is used as a loop counter - --> tests/ui/explicit_counter_loop.rs:115:9 + --> tests/ui/explicit_counter_loop.rs:118:9 | LL | for ch in text.chars() { | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `for (count, ch) in text.chars().enumerate()` error: the variable `count` is used as a loop counter - --> tests/ui/explicit_counter_loop.rs:127:9 + --> tests/ui/explicit_counter_loop.rs:131:9 | LL | for ch in text.chars() { | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `for (count, ch) in text.chars().enumerate()` error: the variable `count` is used as a loop counter - --> tests/ui/explicit_counter_loop.rs:186:9 + --> tests/ui/explicit_counter_loop.rs:191:9 | LL | for _i in 3..10 { | ^^^^^^^^^^^^^^^ help: consider using: `for (count, _i) in (3..10).enumerate()` error: the variable `idx_usize` is used as a loop counter - --> tests/ui/explicit_counter_loop.rs:227:9 + --> tests/ui/explicit_counter_loop.rs:233:9 | LL | for _item in slice { | ^^^^^^^^^^^^^^^^^^ help: consider using: `for (idx_usize, _item) in slice.iter().enumerate()` error: the variable `idx_u32` is used as a loop counter - --> tests/ui/explicit_counter_loop.rs:240:9 + --> tests/ui/explicit_counter_loop.rs:247:9 | LL | for _item in slice { | ^^^^^^^^^^^^^^^^^^ help: consider using: `for (idx_u32, _item) in (0_u32..).zip(slice.iter())` @@ -58,7 +58,7 @@ LL | for _item in slice { = note: `idx_u32` is of type `u32`, making it ineligible for `Iterator::enumerate` error: the variable `_index` is used as a loop counter - --> tests/ui/explicit_counter_loop.rs:286:9 + --> tests/ui/explicit_counter_loop.rs:293:9 | LL | 'label: for v in vec { | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `'label: for (_index, v) in vec.into_iter().enumerate()` diff --git a/tests/ui/explicit_deref_methods.fixed b/tests/ui/explicit_deref_methods.fixed index 7b2dd2fe6eb8..0d1a5f80f3d5 100644 --- a/tests/ui/explicit_deref_methods.fixed +++ b/tests/ui/explicit_deref_methods.fixed @@ -52,29 +52,40 @@ fn main() { // these should require linting let b: &str = &*a; + //~^ explicit_deref_methods let b: &mut str = &mut **a; + //~^ explicit_deref_methods // both derefs should get linted here let b: String = format!("{}, {}", &*a, &*a); + //~^ explicit_deref_methods + //~| explicit_deref_methods println!("{}", &*a); + //~^ explicit_deref_methods #[allow(clippy::match_single_binding)] match &*a { + //~^ explicit_deref_methods _ => (), } let b: String = concat(&*a); + //~^ explicit_deref_methods let b = just_return(a); + //~^ explicit_deref_methods let b: String = concat(just_return(a)); + //~^ explicit_deref_methods let b: &str = &**a; + //~^ explicit_deref_methods let opt_a = Some(a.clone()); let b = &*opt_a.unwrap(); + //~^ explicit_deref_methods // make sure `Aaa::deref` instead of `aaa.deref()` is not linted, as well as fully qualified // syntax @@ -112,6 +123,7 @@ fn main() { let b: &str = expr_deref!(a); let b: &str = expr_deref!(&*a); + //~^ explicit_deref_methods // The struct does not implement Deref trait #[derive(Copy, Clone)] diff --git a/tests/ui/explicit_deref_methods.rs b/tests/ui/explicit_deref_methods.rs index eb52cfb0d857..8d4a899cd260 100644 --- a/tests/ui/explicit_deref_methods.rs +++ b/tests/ui/explicit_deref_methods.rs @@ -52,29 +52,40 @@ fn main() { // these should require linting let b: &str = a.deref(); + //~^ explicit_deref_methods let b: &mut str = a.deref_mut(); + //~^ explicit_deref_methods // both derefs should get linted here let b: String = format!("{}, {}", a.deref(), a.deref()); + //~^ explicit_deref_methods + //~| explicit_deref_methods println!("{}", a.deref()); + //~^ explicit_deref_methods #[allow(clippy::match_single_binding)] match a.deref() { + //~^ explicit_deref_methods _ => (), } let b: String = concat(a.deref()); + //~^ explicit_deref_methods let b = just_return(a).deref(); + //~^ explicit_deref_methods let b: String = concat(just_return(a).deref()); + //~^ explicit_deref_methods let b: &str = a.deref().deref(); + //~^ explicit_deref_methods let opt_a = Some(a.clone()); let b = opt_a.unwrap().deref(); + //~^ explicit_deref_methods // make sure `Aaa::deref` instead of `aaa.deref()` is not linted, as well as fully qualified // syntax @@ -112,6 +123,7 @@ fn main() { let b: &str = expr_deref!(a); let b: &str = expr_deref!(a.deref()); + //~^ explicit_deref_methods // The struct does not implement Deref trait #[derive(Copy, Clone)] diff --git a/tests/ui/explicit_deref_methods.stderr b/tests/ui/explicit_deref_methods.stderr index aab862baf599..2ca376cba00b 100644 --- a/tests/ui/explicit_deref_methods.stderr +++ b/tests/ui/explicit_deref_methods.stderr @@ -8,67 +8,67 @@ LL | let b: &str = a.deref(); = help: to override `-D warnings` add `#[allow(clippy::explicit_deref_methods)]` error: explicit `deref_mut` method call - --> tests/ui/explicit_deref_methods.rs:56:23 + --> tests/ui/explicit_deref_methods.rs:57:23 | LL | let b: &mut str = a.deref_mut(); | ^^^^^^^^^^^^^ help: try: `&mut **a` error: explicit `deref` method call - --> tests/ui/explicit_deref_methods.rs:59:39 + --> tests/ui/explicit_deref_methods.rs:61:39 | LL | let b: String = format!("{}, {}", a.deref(), a.deref()); | ^^^^^^^^^ help: try: `&*a` error: explicit `deref` method call - --> tests/ui/explicit_deref_methods.rs:59:50 + --> tests/ui/explicit_deref_methods.rs:61:50 | LL | let b: String = format!("{}, {}", a.deref(), a.deref()); | ^^^^^^^^^ help: try: `&*a` error: explicit `deref` method call - --> tests/ui/explicit_deref_methods.rs:61:20 + --> tests/ui/explicit_deref_methods.rs:65:20 | LL | println!("{}", a.deref()); | ^^^^^^^^^ help: try: `&*a` error: explicit `deref` method call - --> tests/ui/explicit_deref_methods.rs:64:11 + --> tests/ui/explicit_deref_methods.rs:69:11 | LL | match a.deref() { | ^^^^^^^^^ help: try: `&*a` error: explicit `deref` method call - --> tests/ui/explicit_deref_methods.rs:68:28 + --> tests/ui/explicit_deref_methods.rs:74:28 | LL | let b: String = concat(a.deref()); | ^^^^^^^^^ help: try: `&*a` error: explicit `deref` method call - --> tests/ui/explicit_deref_methods.rs:70:13 + --> tests/ui/explicit_deref_methods.rs:77:13 | LL | let b = just_return(a).deref(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `just_return(a)` error: explicit `deref` method call - --> tests/ui/explicit_deref_methods.rs:72:28 + --> tests/ui/explicit_deref_methods.rs:80:28 | LL | let b: String = concat(just_return(a).deref()); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `just_return(a)` error: explicit `deref` method call - --> tests/ui/explicit_deref_methods.rs:74:19 + --> tests/ui/explicit_deref_methods.rs:83:19 | LL | let b: &str = a.deref().deref(); | ^^^^^^^^^^^^^^^^^ help: try: `&**a` error: explicit `deref` method call - --> tests/ui/explicit_deref_methods.rs:77:13 + --> tests/ui/explicit_deref_methods.rs:87:13 | LL | let b = opt_a.unwrap().deref(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*opt_a.unwrap()` error: explicit `deref` method call - --> tests/ui/explicit_deref_methods.rs:114:31 + --> tests/ui/explicit_deref_methods.rs:125:31 | LL | let b: &str = expr_deref!(a.deref()); | ^^^^^^^^^ help: try: `&*a` diff --git a/tests/ui/explicit_into_iter_loop.fixed b/tests/ui/explicit_into_iter_loop.fixed index 6d67488a7130..2b68906ae39f 100644 --- a/tests/ui/explicit_into_iter_loop.fixed +++ b/tests/ui/explicit_into_iter_loop.fixed @@ -8,6 +8,7 @@ fn main() { for<'a> &'a T: IntoIterator, { for _ in iterator {} + //~^ explicit_into_iter_loop } struct T; @@ -21,9 +22,11 @@ fn main() { let mut t = T; for _ in &t {} + //~^ explicit_into_iter_loop let r = &t; for _ in r {} + //~^ explicit_into_iter_loop // No suggestion for this. // We'd have to suggest `for _ in *rr {}` which is less clear. @@ -32,6 +35,7 @@ fn main() { let mr = &mut t; for _ in &*mr {} + //~^ explicit_into_iter_loop struct U; impl IntoIterator for &mut U { @@ -44,9 +48,11 @@ fn main() { let mut u = U; for _ in &mut u {} + //~^ explicit_into_iter_loop let mr = &mut u; for _ in &mut *mr {} + //~^ explicit_into_iter_loop // Issue #6900 struct S; diff --git a/tests/ui/explicit_into_iter_loop.rs b/tests/ui/explicit_into_iter_loop.rs index 14630c07c5cc..ca335b62d906 100644 --- a/tests/ui/explicit_into_iter_loop.rs +++ b/tests/ui/explicit_into_iter_loop.rs @@ -8,6 +8,7 @@ fn main() { for<'a> &'a T: IntoIterator, { for _ in iterator.into_iter() {} + //~^ explicit_into_iter_loop } struct T; @@ -21,9 +22,11 @@ fn main() { let mut t = T; for _ in t.into_iter() {} + //~^ explicit_into_iter_loop let r = &t; for _ in r.into_iter() {} + //~^ explicit_into_iter_loop // No suggestion for this. // We'd have to suggest `for _ in *rr {}` which is less clear. @@ -32,6 +35,7 @@ fn main() { let mr = &mut t; for _ in mr.into_iter() {} + //~^ explicit_into_iter_loop struct U; impl IntoIterator for &mut U { @@ -44,9 +48,11 @@ fn main() { let mut u = U; for _ in u.into_iter() {} + //~^ explicit_into_iter_loop let mr = &mut u; for _ in mr.into_iter() {} + //~^ explicit_into_iter_loop // Issue #6900 struct S; diff --git a/tests/ui/explicit_into_iter_loop.stderr b/tests/ui/explicit_into_iter_loop.stderr index f0e2048e036f..1c3156755d4e 100644 --- a/tests/ui/explicit_into_iter_loop.stderr +++ b/tests/ui/explicit_into_iter_loop.stderr @@ -8,31 +8,31 @@ LL | for _ in iterator.into_iter() {} = help: to override `-D warnings` add `#[allow(clippy::explicit_into_iter_loop)]` error: it is more concise to loop over containers instead of using explicit iteration methods - --> tests/ui/explicit_into_iter_loop.rs:23:14 + --> tests/ui/explicit_into_iter_loop.rs:24:14 | LL | for _ in t.into_iter() {} | ^^^^^^^^^^^^^ help: to write this more concisely, try: `&t` error: it is more concise to loop over containers instead of using explicit iteration methods - --> tests/ui/explicit_into_iter_loop.rs:26:14 + --> tests/ui/explicit_into_iter_loop.rs:28:14 | LL | for _ in r.into_iter() {} | ^^^^^^^^^^^^^ help: to write this more concisely, try: `r` error: it is more concise to loop over containers instead of using explicit iteration methods - --> tests/ui/explicit_into_iter_loop.rs:34:14 + --> tests/ui/explicit_into_iter_loop.rs:37:14 | LL | for _ in mr.into_iter() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&*mr` error: it is more concise to loop over containers instead of using explicit iteration methods - --> tests/ui/explicit_into_iter_loop.rs:46:14 + --> tests/ui/explicit_into_iter_loop.rs:50:14 | LL | for _ in u.into_iter() {} | ^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut u` error: it is more concise to loop over containers instead of using explicit iteration methods - --> tests/ui/explicit_into_iter_loop.rs:49:14 + --> tests/ui/explicit_into_iter_loop.rs:54:14 | LL | for _ in mr.into_iter() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut *mr` diff --git a/tests/ui/explicit_iter_loop.fixed b/tests/ui/explicit_iter_loop.fixed index 1148f0f6c6a6..cd0898dfc367 100644 --- a/tests/ui/explicit_iter_loop.fixed +++ b/tests/ui/explicit_iter_loop.fixed @@ -16,10 +16,13 @@ fn main() { let mut vec = vec![1, 2, 3, 4]; for _ in &vec {} + //~^ explicit_iter_loop for _ in &mut vec {} + //~^ explicit_iter_loop let rvec = &vec; for _ in rvec {} + //~^ explicit_iter_loop let rmvec = &mut vec; for _ in rmvec.iter() {} @@ -29,36 +32,48 @@ fn main() { for _ in &mut vec {} // these are fine for _ in &[1, 2, 3] {} + //~^ explicit_iter_loop for _ in (&mut [1, 2, 3]).iter() {} for _ in &[0; 32] {} + //~^ explicit_iter_loop for _ in &[0; 33] {} + //~^ explicit_iter_loop let ll: LinkedList<()> = LinkedList::new(); for _ in &ll {} + //~^ explicit_iter_loop let rll = ≪ for _ in rll {} + //~^ explicit_iter_loop let vd: VecDeque<()> = VecDeque::new(); for _ in &vd {} + //~^ explicit_iter_loop let rvd = &vd; for _ in rvd {} + //~^ explicit_iter_loop let bh: BinaryHeap<()> = BinaryHeap::new(); for _ in &bh {} + //~^ explicit_iter_loop let hm: HashMap<(), ()> = HashMap::new(); for _ in &hm {} + //~^ explicit_iter_loop let bt: BTreeMap<(), ()> = BTreeMap::new(); for _ in &bt {} + //~^ explicit_iter_loop let hs: HashSet<()> = HashSet::new(); for _ in &hs {} + //~^ explicit_iter_loop let bs: BTreeSet<()> = BTreeSet::new(); for _ in &bs {} + //~^ explicit_iter_loop struct NoIntoIter(); impl NoIntoIter { @@ -148,10 +163,13 @@ fn main() { } let mut x = CustomType; for _ in &x {} + //~^ explicit_iter_loop for _ in &mut x {} + //~^ explicit_iter_loop let r = &x; for _ in r {} + //~^ explicit_iter_loop } #[clippy::msrv = "1.79"] diff --git a/tests/ui/explicit_iter_loop.rs b/tests/ui/explicit_iter_loop.rs index 4dda2f13e5b8..02405280ce42 100644 --- a/tests/ui/explicit_iter_loop.rs +++ b/tests/ui/explicit_iter_loop.rs @@ -16,10 +16,13 @@ fn main() { let mut vec = vec![1, 2, 3, 4]; for _ in vec.iter() {} + //~^ explicit_iter_loop for _ in vec.iter_mut() {} + //~^ explicit_iter_loop let rvec = &vec; for _ in rvec.iter() {} + //~^ explicit_iter_loop let rmvec = &mut vec; for _ in rmvec.iter() {} @@ -29,36 +32,48 @@ fn main() { for _ in &mut vec {} // these are fine for _ in [1, 2, 3].iter() {} + //~^ explicit_iter_loop for _ in (&mut [1, 2, 3]).iter() {} for _ in [0; 32].iter() {} + //~^ explicit_iter_loop for _ in [0; 33].iter() {} + //~^ explicit_iter_loop let ll: LinkedList<()> = LinkedList::new(); for _ in ll.iter() {} + //~^ explicit_iter_loop let rll = ≪ for _ in rll.iter() {} + //~^ explicit_iter_loop let vd: VecDeque<()> = VecDeque::new(); for _ in vd.iter() {} + //~^ explicit_iter_loop let rvd = &vd; for _ in rvd.iter() {} + //~^ explicit_iter_loop let bh: BinaryHeap<()> = BinaryHeap::new(); for _ in bh.iter() {} + //~^ explicit_iter_loop let hm: HashMap<(), ()> = HashMap::new(); for _ in hm.iter() {} + //~^ explicit_iter_loop let bt: BTreeMap<(), ()> = BTreeMap::new(); for _ in bt.iter() {} + //~^ explicit_iter_loop let hs: HashSet<()> = HashSet::new(); for _ in hs.iter() {} + //~^ explicit_iter_loop let bs: BTreeSet<()> = BTreeSet::new(); for _ in bs.iter() {} + //~^ explicit_iter_loop struct NoIntoIter(); impl NoIntoIter { @@ -148,10 +163,13 @@ fn main() { } let mut x = CustomType; for _ in x.iter() {} + //~^ explicit_iter_loop for _ in x.iter_mut() {} + //~^ explicit_iter_loop let r = &x; for _ in r.iter() {} + //~^ explicit_iter_loop } #[clippy::msrv = "1.79"] diff --git a/tests/ui/explicit_iter_loop.stderr b/tests/ui/explicit_iter_loop.stderr index c646e61aa045..3816bb4db98b 100644 --- a/tests/ui/explicit_iter_loop.stderr +++ b/tests/ui/explicit_iter_loop.stderr @@ -11,103 +11,103 @@ LL | #![deny(clippy::explicit_iter_loop)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> tests/ui/explicit_iter_loop.rs:19:14 + --> tests/ui/explicit_iter_loop.rs:20:14 | LL | for _ in vec.iter_mut() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> tests/ui/explicit_iter_loop.rs:22:14 + --> tests/ui/explicit_iter_loop.rs:24:14 | LL | for _ in rvec.iter() {} | ^^^^^^^^^^^ help: to write this more concisely, try: `rvec` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> tests/ui/explicit_iter_loop.rs:31:14 + --> tests/ui/explicit_iter_loop.rs:34:14 | LL | for _ in [1, 2, 3].iter() {} | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> tests/ui/explicit_iter_loop.rs:35:14 + --> tests/ui/explicit_iter_loop.rs:39:14 | LL | for _ in [0; 32].iter() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> tests/ui/explicit_iter_loop.rs:36:14 + --> tests/ui/explicit_iter_loop.rs:41:14 | LL | for _ in [0; 33].iter() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 33]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> tests/ui/explicit_iter_loop.rs:39:14 + --> tests/ui/explicit_iter_loop.rs:45:14 | LL | for _ in ll.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&ll` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> tests/ui/explicit_iter_loop.rs:41:14 + --> tests/ui/explicit_iter_loop.rs:48:14 | LL | for _ in rll.iter() {} | ^^^^^^^^^^ help: to write this more concisely, try: `rll` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> tests/ui/explicit_iter_loop.rs:44:14 + --> tests/ui/explicit_iter_loop.rs:52:14 | LL | for _ in vd.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&vd` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> tests/ui/explicit_iter_loop.rs:46:14 + --> tests/ui/explicit_iter_loop.rs:55:14 | LL | for _ in rvd.iter() {} | ^^^^^^^^^^ help: to write this more concisely, try: `rvd` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> tests/ui/explicit_iter_loop.rs:49:14 + --> tests/ui/explicit_iter_loop.rs:59:14 | LL | for _ in bh.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bh` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> tests/ui/explicit_iter_loop.rs:52:14 + --> tests/ui/explicit_iter_loop.rs:63:14 | LL | for _ in hm.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hm` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> tests/ui/explicit_iter_loop.rs:55:14 + --> tests/ui/explicit_iter_loop.rs:67:14 | LL | for _ in bt.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bt` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> tests/ui/explicit_iter_loop.rs:58:14 + --> tests/ui/explicit_iter_loop.rs:71:14 | LL | for _ in hs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hs` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> tests/ui/explicit_iter_loop.rs:61:14 + --> tests/ui/explicit_iter_loop.rs:75:14 | LL | for _ in bs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bs` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> tests/ui/explicit_iter_loop.rs:150:14 + --> tests/ui/explicit_iter_loop.rs:165:14 | LL | for _ in x.iter() {} | ^^^^^^^^ help: to write this more concisely, try: `&x` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> tests/ui/explicit_iter_loop.rs:151:14 + --> tests/ui/explicit_iter_loop.rs:167:14 | LL | for _ in x.iter_mut() {} | ^^^^^^^^^^^^ help: to write this more concisely, try: `&mut x` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> tests/ui/explicit_iter_loop.rs:154:14 + --> tests/ui/explicit_iter_loop.rs:171:14 | LL | for _ in r.iter() {} | ^^^^^^^^ help: to write this more concisely, try: `r` diff --git a/tests/ui/explicit_write.fixed b/tests/ui/explicit_write.fixed index 77a910dc1963..024999fc609e 100644 --- a/tests/ui/explicit_write.fixed +++ b/tests/ui/explicit_write.fixed @@ -21,23 +21,36 @@ fn main() { { use std::io::Write; print!("test"); + //~^ explicit_write eprint!("test"); + //~^ explicit_write println!("test"); + //~^ explicit_write eprintln!("test"); + //~^ explicit_write print!("test"); + //~^ explicit_write eprint!("test"); + //~^ explicit_write // including newlines println!("test\ntest"); + //~^ explicit_write eprintln!("test\ntest"); + //~^ explicit_write let value = 1; eprintln!("with {}", value); + //~^ explicit_write eprintln!("with {} {}", 2, value); + //~^ explicit_write eprintln!("with {value}"); + //~^ explicit_write eprintln!("macro arg {}", one!()); + //~^ explicit_write let width = 2; eprintln!("{:w$}", value, w = width); + //~^ explicit_write } // these should not warn, different destination { diff --git a/tests/ui/explicit_write.rs b/tests/ui/explicit_write.rs index c77956264f6d..c83c760d48c8 100644 --- a/tests/ui/explicit_write.rs +++ b/tests/ui/explicit_write.rs @@ -21,23 +21,36 @@ fn main() { { use std::io::Write; write!(std::io::stdout(), "test").unwrap(); + //~^ explicit_write write!(std::io::stderr(), "test").unwrap(); + //~^ explicit_write writeln!(std::io::stdout(), "test").unwrap(); + //~^ explicit_write writeln!(std::io::stderr(), "test").unwrap(); + //~^ explicit_write std::io::stdout().write_fmt(format_args!("test")).unwrap(); + //~^ explicit_write std::io::stderr().write_fmt(format_args!("test")).unwrap(); + //~^ explicit_write // including newlines writeln!(std::io::stdout(), "test\ntest").unwrap(); + //~^ explicit_write writeln!(std::io::stderr(), "test\ntest").unwrap(); + //~^ explicit_write let value = 1; writeln!(std::io::stderr(), "with {}", value).unwrap(); + //~^ explicit_write writeln!(std::io::stderr(), "with {} {}", 2, value).unwrap(); + //~^ explicit_write writeln!(std::io::stderr(), "with {value}").unwrap(); + //~^ explicit_write writeln!(std::io::stderr(), "macro arg {}", one!()).unwrap(); + //~^ explicit_write let width = 2; writeln!(std::io::stderr(), "{:w$}", value, w = width).unwrap(); + //~^ explicit_write } // these should not warn, different destination { diff --git a/tests/ui/explicit_write.stderr b/tests/ui/explicit_write.stderr index 0d22f02c36f2..670a0411b310 100644 --- a/tests/ui/explicit_write.stderr +++ b/tests/ui/explicit_write.stderr @@ -8,73 +8,73 @@ LL | write!(std::io::stdout(), "test").unwrap(); = help: to override `-D warnings` add `#[allow(clippy::explicit_write)]` error: use of `write!(stderr(), ...).unwrap()` - --> tests/ui/explicit_write.rs:24:9 + --> tests/ui/explicit_write.rs:25:9 | LL | write!(std::io::stderr(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprint!("test")` error: use of `writeln!(stdout(), ...).unwrap()` - --> tests/ui/explicit_write.rs:25:9 + --> tests/ui/explicit_write.rs:27:9 | LL | writeln!(std::io::stdout(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `println!("test")` error: use of `writeln!(stderr(), ...).unwrap()` - --> tests/ui/explicit_write.rs:26:9 + --> tests/ui/explicit_write.rs:29:9 | LL | writeln!(std::io::stderr(), "test").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("test")` error: use of `stdout().write_fmt(...).unwrap()` - --> tests/ui/explicit_write.rs:27:9 + --> tests/ui/explicit_write.rs:31:9 | LL | std::io::stdout().write_fmt(format_args!("test")).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `print!("test")` error: use of `stderr().write_fmt(...).unwrap()` - --> tests/ui/explicit_write.rs:28:9 + --> tests/ui/explicit_write.rs:33:9 | LL | std::io::stderr().write_fmt(format_args!("test")).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprint!("test")` error: use of `writeln!(stdout(), ...).unwrap()` - --> tests/ui/explicit_write.rs:31:9 + --> tests/ui/explicit_write.rs:37:9 | LL | writeln!(std::io::stdout(), "test\ntest").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `println!("test\ntest")` error: use of `writeln!(stderr(), ...).unwrap()` - --> tests/ui/explicit_write.rs:32:9 + --> tests/ui/explicit_write.rs:39:9 | LL | writeln!(std::io::stderr(), "test\ntest").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("test\ntest")` error: use of `writeln!(stderr(), ...).unwrap()` - --> tests/ui/explicit_write.rs:35:9 + --> tests/ui/explicit_write.rs:43:9 | LL | writeln!(std::io::stderr(), "with {}", value).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("with {}", value)` error: use of `writeln!(stderr(), ...).unwrap()` - --> tests/ui/explicit_write.rs:36:9 + --> tests/ui/explicit_write.rs:45:9 | LL | writeln!(std::io::stderr(), "with {} {}", 2, value).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("with {} {}", 2, value)` error: use of `writeln!(stderr(), ...).unwrap()` - --> tests/ui/explicit_write.rs:37:9 + --> tests/ui/explicit_write.rs:47:9 | LL | writeln!(std::io::stderr(), "with {value}").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("with {value}")` error: use of `writeln!(stderr(), ...).unwrap()` - --> tests/ui/explicit_write.rs:38:9 + --> tests/ui/explicit_write.rs:49:9 | LL | writeln!(std::io::stderr(), "macro arg {}", one!()).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("macro arg {}", one!())` error: use of `writeln!(stderr(), ...).unwrap()` - --> tests/ui/explicit_write.rs:40:9 + --> tests/ui/explicit_write.rs:52:9 | LL | writeln!(std::io::stderr(), "{:w$}", value, w = width).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `eprintln!("{:w$}", value, w = width)` diff --git a/tests/ui/extend_with_drain.fixed b/tests/ui/extend_with_drain.fixed index 856c1a42dafc..7b314381e9a3 100644 --- a/tests/ui/extend_with_drain.fixed +++ b/tests/ui/extend_with_drain.fixed @@ -6,15 +6,18 @@ fn main() { let mut vec1 = vec![0u8; 1024]; let mut vec2: std::vec::Vec = Vec::new(); vec2.append(&mut vec1); + //~^ extend_with_drain let mut vec3 = vec![0u8; 1024]; let mut vec4: std::vec::Vec = Vec::new(); vec4.append(&mut vec3); + //~^ extend_with_drain let mut vec11: std::vec::Vec = Vec::new(); vec11.append(&mut return_vector()); + //~^ extend_with_drain //won't get linted it doesn't move the entire content of a vec into another let mut test1 = vec![0u8, 10]; @@ -46,6 +49,7 @@ fn main() { let ref_x = &mut x; let mut y = Vec::new(); y.append(ref_x); + //~^ extend_with_drain } fn return_vector() -> Vec { diff --git a/tests/ui/extend_with_drain.rs b/tests/ui/extend_with_drain.rs index 7d538097639f..77214c053979 100644 --- a/tests/ui/extend_with_drain.rs +++ b/tests/ui/extend_with_drain.rs @@ -6,15 +6,18 @@ fn main() { let mut vec1 = vec![0u8; 1024]; let mut vec2: std::vec::Vec = Vec::new(); vec2.extend(vec1.drain(..)); + //~^ extend_with_drain let mut vec3 = vec![0u8; 1024]; let mut vec4: std::vec::Vec = Vec::new(); vec4.extend(vec3.drain(..)); + //~^ extend_with_drain let mut vec11: std::vec::Vec = Vec::new(); vec11.extend(return_vector().drain(..)); + //~^ extend_with_drain //won't get linted it doesn't move the entire content of a vec into another let mut test1 = vec![0u8, 10]; @@ -46,6 +49,7 @@ fn main() { let ref_x = &mut x; let mut y = Vec::new(); y.extend(ref_x.drain(..)); + //~^ extend_with_drain } fn return_vector() -> Vec { diff --git a/tests/ui/extend_with_drain.stderr b/tests/ui/extend_with_drain.stderr index 444cc82bbae7..2ee7aa7294e0 100644 --- a/tests/ui/extend_with_drain.stderr +++ b/tests/ui/extend_with_drain.stderr @@ -8,19 +8,19 @@ LL | vec2.extend(vec1.drain(..)); = help: to override `-D warnings` add `#[allow(clippy::extend_with_drain)]` error: use of `extend` instead of `append` for adding the full range of a second vector - --> tests/ui/extend_with_drain.rs:13:5 + --> tests/ui/extend_with_drain.rs:14:5 | LL | vec4.extend(vec3.drain(..)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec4.append(&mut vec3)` error: use of `extend` instead of `append` for adding the full range of a second vector - --> tests/ui/extend_with_drain.rs:17:5 + --> tests/ui/extend_with_drain.rs:19:5 | LL | vec11.extend(return_vector().drain(..)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec11.append(&mut return_vector())` error: use of `extend` instead of `append` for adding the full range of a second vector - --> tests/ui/extend_with_drain.rs:48:5 + --> tests/ui/extend_with_drain.rs:51:5 | LL | y.extend(ref_x.drain(..)); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `y.append(ref_x)` diff --git a/tests/ui/extra_unused_lifetimes.rs b/tests/ui/extra_unused_lifetimes.rs index aa964af3fc2d..5fdcd5a7e078 100644 --- a/tests/ui/extra_unused_lifetimes.rs +++ b/tests/ui/extra_unused_lifetimes.rs @@ -17,6 +17,7 @@ fn empty() {} fn used_lt<'a>(x: &'a u8) {} fn unused_lt<'a>(x: u8) {} +//~^ extra_unused_lifetimes fn unused_lt_transitive<'a, 'b: 'a>(x: &'b u8) { // 'a is useless here since it's not directly bound @@ -44,6 +45,7 @@ struct Bar; impl Bar { fn x<'a>(&self) {} + //~^ extra_unused_lifetimes } // test for #489 (used lifetimes in bounds) @@ -70,6 +72,7 @@ impl X { mod issue4291 { trait BadTrait { fn unused_lt<'a>(x: u8) {} + //~^ extra_unused_lifetimes } impl BadTrait for () { @@ -81,13 +84,16 @@ mod issue6437 { pub struct Scalar; impl<'a> std::ops::AddAssign<&Scalar> for &mut Scalar { + //~^ extra_unused_lifetimes fn add_assign(&mut self, _rhs: &Scalar) { unimplemented!(); } } impl<'b> Scalar { + //~^ extra_unused_lifetimes pub fn something<'c>() -> Self { + //~^ extra_unused_lifetimes Self } } @@ -117,6 +123,7 @@ mod second_case { // Should lint. The response to the above comment incorrectly called this a false positive. The // lifetime `'a` can be removed, as demonstrated below. impl<'a, T: Source + ?Sized + 'a> Source for Box { + //~^ extra_unused_lifetimes fn hey() {} } diff --git a/tests/ui/extra_unused_lifetimes.stderr b/tests/ui/extra_unused_lifetimes.stderr index 85fbb7568ff4..0cecbbe80f76 100644 --- a/tests/ui/extra_unused_lifetimes.stderr +++ b/tests/ui/extra_unused_lifetimes.stderr @@ -8,37 +8,37 @@ LL | fn unused_lt<'a>(x: u8) {} = help: to override `-D warnings` add `#[allow(clippy::extra_unused_lifetimes)]` error: this lifetime isn't used in the function definition - --> tests/ui/extra_unused_lifetimes.rs:46:10 + --> tests/ui/extra_unused_lifetimes.rs:47:10 | LL | fn x<'a>(&self) {} | ^^ error: this lifetime isn't used in the function definition - --> tests/ui/extra_unused_lifetimes.rs:72:22 + --> tests/ui/extra_unused_lifetimes.rs:74:22 | LL | fn unused_lt<'a>(x: u8) {} | ^^ error: this lifetime isn't used in the impl - --> tests/ui/extra_unused_lifetimes.rs:83:10 + --> tests/ui/extra_unused_lifetimes.rs:86:10 | LL | impl<'a> std::ops::AddAssign<&Scalar> for &mut Scalar { | ^^ error: this lifetime isn't used in the impl - --> tests/ui/extra_unused_lifetimes.rs:89:10 + --> tests/ui/extra_unused_lifetimes.rs:93:10 | LL | impl<'b> Scalar { | ^^ error: this lifetime isn't used in the function definition - --> tests/ui/extra_unused_lifetimes.rs:90:26 + --> tests/ui/extra_unused_lifetimes.rs:95:26 | LL | pub fn something<'c>() -> Self { | ^^ error: this lifetime isn't used in the impl - --> tests/ui/extra_unused_lifetimes.rs:119:10 + --> tests/ui/extra_unused_lifetimes.rs:125:10 | LL | impl<'a, T: Source + ?Sized + 'a> Source for Box { | ^^ diff --git a/tests/ui/extra_unused_type_parameters.fixed b/tests/ui/extra_unused_type_parameters.fixed index c9bebabdf17a..32d4f6c69390 100644 --- a/tests/ui/extra_unused_type_parameters.fixed +++ b/tests/ui/extra_unused_type_parameters.fixed @@ -7,14 +7,17 @@ extern crate proc_macros; use proc_macros::with_span; fn unused_ty(x: u8) { + //~^ extra_unused_type_parameters unimplemented!() } fn unused_multi(x: u8) { + //~^ extra_unused_type_parameters unimplemented!() } fn unused_with_lt<'a>(x: &'a u8) { + //~^ extra_unused_type_parameters unimplemented!() } @@ -27,10 +30,12 @@ fn used_ret(x: u8) -> T { } fn unused_bounded(x: U) { + //~^ extra_unused_type_parameters unimplemented!(); } fn some_unused(b: B, c: C) { + //~^ extra_unused_type_parameters unimplemented!(); } @@ -56,6 +61,7 @@ struct S; impl S { fn unused_ty_impl(&self) { + //~^ extra_unused_type_parameters unimplemented!() } } @@ -78,6 +84,7 @@ where } fn unused_opaque(dummy: impl Default) { + //~^ extra_unused_type_parameters unimplemented!() } @@ -91,6 +98,7 @@ mod unexported_trait_bounds { } fn unused_with_priv_trait_bound() { + //~^ extra_unused_type_parameters unimplemented!(); } } diff --git a/tests/ui/extra_unused_type_parameters.rs b/tests/ui/extra_unused_type_parameters.rs index 1bc0047adf01..c1e6f32ca12f 100644 --- a/tests/ui/extra_unused_type_parameters.rs +++ b/tests/ui/extra_unused_type_parameters.rs @@ -7,14 +7,17 @@ extern crate proc_macros; use proc_macros::with_span; fn unused_ty(x: u8) { + //~^ extra_unused_type_parameters unimplemented!() } fn unused_multi(x: u8) { + //~^ extra_unused_type_parameters unimplemented!() } fn unused_with_lt<'a, T>(x: &'a u8) { + //~^ extra_unused_type_parameters unimplemented!() } @@ -27,10 +30,12 @@ fn used_ret(x: u8) -> T { } fn unused_bounded(x: U) { + //~^ extra_unused_type_parameters unimplemented!(); } fn some_unused, E>(b: B, c: C) { + //~^ extra_unused_type_parameters unimplemented!(); } @@ -56,6 +61,7 @@ struct S; impl S { fn unused_ty_impl(&self) { + //~^ extra_unused_type_parameters unimplemented!() } } @@ -78,6 +84,7 @@ where } fn unused_opaque(dummy: impl Default) { + //~^ extra_unused_type_parameters unimplemented!() } @@ -91,6 +98,7 @@ mod unexported_trait_bounds { } fn unused_with_priv_trait_bound() { + //~^ extra_unused_type_parameters unimplemented!(); } } diff --git a/tests/ui/extra_unused_type_parameters.stderr b/tests/ui/extra_unused_type_parameters.stderr index 928c0038c2c3..5086826ae5c0 100644 --- a/tests/ui/extra_unused_type_parameters.stderr +++ b/tests/ui/extra_unused_type_parameters.stderr @@ -8,19 +8,19 @@ LL | fn unused_ty(x: u8) { = help: to override `-D warnings` add `#[allow(clippy::extra_unused_type_parameters)]` error: type parameters go unused in function definition: T, U - --> tests/ui/extra_unused_type_parameters.rs:13:16 + --> tests/ui/extra_unused_type_parameters.rs:14:16 | LL | fn unused_multi(x: u8) { | ^^^^^^ help: consider removing the parameters error: type parameter `T` goes unused in function definition - --> tests/ui/extra_unused_type_parameters.rs:17:21 + --> tests/ui/extra_unused_type_parameters.rs:19:21 | LL | fn unused_with_lt<'a, T>(x: &'a u8) { | ^^^ help: consider removing the parameter error: type parameters go unused in function definition: T, V - --> tests/ui/extra_unused_type_parameters.rs:29:19 + --> tests/ui/extra_unused_type_parameters.rs:32:19 | LL | fn unused_bounded(x: U) { | ^^^^^^^^^^^^ ^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL + fn unused_bounded(x: U) { | error: type parameters go unused in function definition: A, D, E - --> tests/ui/extra_unused_type_parameters.rs:33:16 + --> tests/ui/extra_unused_type_parameters.rs:37:16 | LL | fn some_unused, E>(b: B, c: C) { | ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -44,19 +44,19 @@ LL + fn some_unused(b: B, c: C) { | error: type parameter `T` goes unused in function definition - --> tests/ui/extra_unused_type_parameters.rs:58:22 + --> tests/ui/extra_unused_type_parameters.rs:63:22 | LL | fn unused_ty_impl(&self) { | ^^^ help: consider removing the parameter error: type parameters go unused in function definition: A, B - --> tests/ui/extra_unused_type_parameters.rs:80:17 + --> tests/ui/extra_unused_type_parameters.rs:86:17 | LL | fn unused_opaque(dummy: impl Default) { | ^^^^^^ help: consider removing the parameters error: type parameter `U` goes unused in function definition - --> tests/ui/extra_unused_type_parameters.rs:93:56 + --> tests/ui/extra_unused_type_parameters.rs:100:56 | LL | fn unused_with_priv_trait_bound() { | ^^^ help: consider removing the parameter diff --git a/tests/ui/extra_unused_type_parameters_unfixable.rs b/tests/ui/extra_unused_type_parameters_unfixable.rs index 65b53eb2e4b3..87ce517a0a45 100644 --- a/tests/ui/extra_unused_type_parameters_unfixable.rs +++ b/tests/ui/extra_unused_type_parameters_unfixable.rs @@ -1,7 +1,7 @@ #![warn(clippy::extra_unused_type_parameters)] fn unused_where_clause(x: U) -//~^ ERROR: type parameter `T` goes unused in function definition +//~^ extra_unused_type_parameters where T: Default, { @@ -9,7 +9,7 @@ where } fn unused_multi_where_clause(x: U) -//~^ ERROR: type parameters go unused in function definition: T, V +//~^ extra_unused_type_parameters where T: Default, { @@ -17,7 +17,7 @@ where } fn unused_all_where_clause() -//~^ ERROR: type parameters go unused in function definition: T, U, V +//~^ extra_unused_type_parameters where T: Default, { diff --git a/tests/ui/fallible_impl_from.rs b/tests/ui/fallible_impl_from.rs index a81e51fcac75..1c62c1e937b6 100644 --- a/tests/ui/fallible_impl_from.rs +++ b/tests/ui/fallible_impl_from.rs @@ -4,7 +4,8 @@ // docs example struct Foo(i32); impl From for Foo { - //~^ ERROR: consider implementing `TryFrom` instead + //~^ fallible_impl_from + fn from(s: String) -> Self { Foo(s.parse().unwrap()) } @@ -26,7 +27,8 @@ impl From for Valid { struct Invalid; impl From for Invalid { - //~^ ERROR: consider implementing `TryFrom` instead + //~^ fallible_impl_from + fn from(i: usize) -> Invalid { if i != 42 { panic!(); @@ -36,7 +38,8 @@ impl From for Invalid { } impl From> for Invalid { - //~^ ERROR: consider implementing `TryFrom` instead + //~^ fallible_impl_from + fn from(s: Option) -> Invalid { let s = s.unwrap(); if !s.is_empty() { @@ -55,7 +58,8 @@ impl ProjStrTrait for Box { type ProjString = String; } impl<'a> From<&'a mut as ProjStrTrait>::ProjString> for Invalid { - //~^ ERROR: consider implementing `TryFrom` instead + //~^ fallible_impl_from + fn from(s: &'a mut as ProjStrTrait>::ProjString) -> Invalid { if s.parse::().ok().unwrap() != 42 { panic!("{:?}", s); diff --git a/tests/ui/fallible_impl_from.stderr b/tests/ui/fallible_impl_from.stderr index cc3739031b76..d773fc3a6d7c 100644 --- a/tests/ui/fallible_impl_from.stderr +++ b/tests/ui/fallible_impl_from.stderr @@ -3,15 +3,15 @@ error: consider implementing `TryFrom` instead | LL | / impl From for Foo { LL | | +LL | | LL | | fn from(s: String) -> Self { -LL | | Foo(s.parse().unwrap()) -LL | | } +... | LL | | } | |_^ | = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail note: potential failure(s) - --> tests/ui/fallible_impl_from.rs:9:13 + --> tests/ui/fallible_impl_from.rs:10:13 | LL | Foo(s.parse().unwrap()) | ^^^^^^^^^^^^^^^^^^ @@ -22,38 +22,38 @@ LL | #![deny(clippy::fallible_impl_from)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: consider implementing `TryFrom` instead - --> tests/ui/fallible_impl_from.rs:28:1 + --> tests/ui/fallible_impl_from.rs:29:1 | LL | / impl From for Invalid { LL | | +LL | | LL | | fn from(i: usize) -> Invalid { -LL | | if i != 42 { ... | LL | | } | |_^ | = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail note: potential failure(s) - --> tests/ui/fallible_impl_from.rs:32:13 + --> tests/ui/fallible_impl_from.rs:34:13 | LL | panic!(); | ^^^^^^^^ = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: consider implementing `TryFrom` instead - --> tests/ui/fallible_impl_from.rs:38:1 + --> tests/ui/fallible_impl_from.rs:40:1 | LL | / impl From> for Invalid { LL | | +LL | | LL | | fn from(s: Option) -> Invalid { -LL | | let s = s.unwrap(); ... | LL | | } | |_^ | = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail note: potential failure(s) - --> tests/ui/fallible_impl_from.rs:41:17 + --> tests/ui/fallible_impl_from.rs:44:17 | LL | let s = s.unwrap(); | ^^^^^^^^^^ @@ -67,19 +67,19 @@ LL | panic!("{:?}", s); = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: consider implementing `TryFrom` instead - --> tests/ui/fallible_impl_from.rs:57:1 + --> tests/ui/fallible_impl_from.rs:60:1 | LL | / impl<'a> From<&'a mut as ProjStrTrait>::ProjString> for Invalid { LL | | +LL | | LL | | fn from(s: &'a mut as ProjStrTrait>::ProjString) -> Invalid { -LL | | if s.parse::().ok().unwrap() != 42 { ... | LL | | } | |_^ | = help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail note: potential failure(s) - --> tests/ui/fallible_impl_from.rs:60:12 + --> tests/ui/fallible_impl_from.rs:64:12 | LL | if s.parse::().ok().unwrap() != 42 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/field_reassign_with_default.rs b/tests/ui/field_reassign_with_default.rs index 2a432751952d..f3179b78ecb7 100644 --- a/tests/ui/field_reassign_with_default.rs +++ b/tests/ui/field_reassign_with_default.rs @@ -55,6 +55,7 @@ fn main() { // wrong, produces first error in stderr let mut a: A = Default::default(); a.i = 42; + //~^ field_reassign_with_default // right let mut a: A = Default::default(); @@ -95,17 +96,20 @@ fn main() { // wrong, produces second error in stderr let mut a: A = Default::default(); a.j = 43; + //~^ field_reassign_with_default a.i = 42; // wrong, produces third error in stderr let mut a: A = Default::default(); a.i = 42; + //~^ field_reassign_with_default a.j = 43; a.j = 44; // wrong, produces fourth error in stderr let mut a = A::default(); a.i = 42; + //~^ field_reassign_with_default // wrong, but does not produce an error in stderr, because we can't produce a correct kind of // suggestion with current implementation @@ -116,10 +120,12 @@ fn main() { // wrong, produces the fifth error in stderr let mut a: A = Default::default(); a.i = Default::default(); + //~^ field_reassign_with_default // wrong, produces the sixth error in stderr let mut a: A = Default::default(); a.i = Default::default(); + //~^ field_reassign_with_default a.j = 45; // right, because an assignment refers to another field @@ -142,6 +148,7 @@ fn main() { // don't expand macros in the suggestion (#6522) let mut a: C = C::default(); a.i = vec![1]; + //~^ field_reassign_with_default // Don't lint in external macros external! { @@ -160,9 +167,11 @@ fn main() { // be sure suggestion is correct with generics let mut a: Wrapper = Default::default(); a.i = true; + //~^ field_reassign_with_default let mut a: WrapperMulti = Default::default(); a.i = 42; + //~^ field_reassign_with_default // Don't lint in macros inline!( @@ -234,6 +243,7 @@ mod issue6312 { fn new(name: &str) -> Self { let mut f = ImplDropAllCopy::default(); f.name = name.len(); + //~^ field_reassign_with_default f } fn close(&self) {} @@ -250,6 +260,7 @@ mod issue6312 { fn new(name: &str) -> Self { let mut f = NoDropAllCopy::default(); f.name = name.len(); + //~^ field_reassign_with_default f } } diff --git a/tests/ui/field_reassign_with_default.stderr b/tests/ui/field_reassign_with_default.stderr index ae909475c6f2..19382e671510 100644 --- a/tests/ui/field_reassign_with_default.stderr +++ b/tests/ui/field_reassign_with_default.stderr @@ -13,121 +13,121 @@ LL | let mut a: A = Default::default(); = help: to override `-D warnings` add `#[allow(clippy::field_reassign_with_default)]` error: field assignment outside of initializer for an instance created with Default::default() - --> tests/ui/field_reassign_with_default.rs:97:5 + --> tests/ui/field_reassign_with_default.rs:98:5 | LL | a.j = 43; | ^^^^^^^^^ | note: consider initializing the variable with `main::A { j: 43, i: 42 }` and removing relevant reassignments - --> tests/ui/field_reassign_with_default.rs:96:5 + --> tests/ui/field_reassign_with_default.rs:97:5 | LL | let mut a: A = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> tests/ui/field_reassign_with_default.rs:102:5 + --> tests/ui/field_reassign_with_default.rs:104:5 | LL | a.i = 42; | ^^^^^^^^^ | note: consider initializing the variable with `main::A { i: 42, j: 44 }` and removing relevant reassignments - --> tests/ui/field_reassign_with_default.rs:101:5 + --> tests/ui/field_reassign_with_default.rs:103:5 | LL | let mut a: A = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> tests/ui/field_reassign_with_default.rs:108:5 + --> tests/ui/field_reassign_with_default.rs:111:5 | LL | a.i = 42; | ^^^^^^^^^ | note: consider initializing the variable with `main::A { i: 42, ..Default::default() }` and removing relevant reassignments - --> tests/ui/field_reassign_with_default.rs:107:5 + --> tests/ui/field_reassign_with_default.rs:110:5 | LL | let mut a = A::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: field assignment outside of initializer for an instance created with Default::default() - --> tests/ui/field_reassign_with_default.rs:118:5 - | -LL | a.i = Default::default(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: consider initializing the variable with `main::A { i: Default::default(), ..Default::default() }` and removing relevant reassignments - --> tests/ui/field_reassign_with_default.rs:117:5 - | -LL | let mut a: A = Default::default(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: field assignment outside of initializer for an instance created with Default::default() --> tests/ui/field_reassign_with_default.rs:122:5 | LL | a.i = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: consider initializing the variable with `main::A { i: Default::default(), j: 45 }` and removing relevant reassignments +note: consider initializing the variable with `main::A { i: Default::default(), ..Default::default() }` and removing relevant reassignments --> tests/ui/field_reassign_with_default.rs:121:5 | LL | let mut a: A = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> tests/ui/field_reassign_with_default.rs:144:5 + --> tests/ui/field_reassign_with_default.rs:127:5 + | +LL | a.i = Default::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: consider initializing the variable with `main::A { i: Default::default(), j: 45 }` and removing relevant reassignments + --> tests/ui/field_reassign_with_default.rs:126:5 + | +LL | let mut a: A = Default::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: field assignment outside of initializer for an instance created with Default::default() + --> tests/ui/field_reassign_with_default.rs:150:5 | LL | a.i = vec![1]; | ^^^^^^^^^^^^^^ | note: consider initializing the variable with `C { i: vec![1], ..Default::default() }` and removing relevant reassignments - --> tests/ui/field_reassign_with_default.rs:143:5 + --> tests/ui/field_reassign_with_default.rs:149:5 | LL | let mut a: C = C::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> tests/ui/field_reassign_with_default.rs:162:5 + --> tests/ui/field_reassign_with_default.rs:169:5 | LL | a.i = true; | ^^^^^^^^^^^ | note: consider initializing the variable with `Wrapper:: { i: true }` and removing relevant reassignments - --> tests/ui/field_reassign_with_default.rs:161:5 + --> tests/ui/field_reassign_with_default.rs:168:5 | LL | let mut a: Wrapper = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> tests/ui/field_reassign_with_default.rs:165:5 + --> tests/ui/field_reassign_with_default.rs:173:5 | LL | a.i = 42; | ^^^^^^^^^ | note: consider initializing the variable with `WrapperMulti:: { i: 42, ..Default::default() }` and removing relevant reassignments - --> tests/ui/field_reassign_with_default.rs:164:5 + --> tests/ui/field_reassign_with_default.rs:172:5 | LL | let mut a: WrapperMulti = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> tests/ui/field_reassign_with_default.rs:236:13 + --> tests/ui/field_reassign_with_default.rs:245:13 | LL | f.name = name.len(); | ^^^^^^^^^^^^^^^^^^^^ | note: consider initializing the variable with `issue6312::ImplDropAllCopy { name: name.len(), ..Default::default() }` and removing relevant reassignments - --> tests/ui/field_reassign_with_default.rs:235:13 + --> tests/ui/field_reassign_with_default.rs:244:13 | LL | let mut f = ImplDropAllCopy::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> tests/ui/field_reassign_with_default.rs:252:13 + --> tests/ui/field_reassign_with_default.rs:262:13 | LL | f.name = name.len(); | ^^^^^^^^^^^^^^^^^^^^ | note: consider initializing the variable with `issue6312::NoDropAllCopy { name: name.len(), ..Default::default() }` and removing relevant reassignments - --> tests/ui/field_reassign_with_default.rs:251:13 + --> tests/ui/field_reassign_with_default.rs:261:13 | LL | let mut f = NoDropAllCopy::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/field_scoped_visibility_modifiers.rs b/tests/ui/field_scoped_visibility_modifiers.rs index 5789dbf9b1d7..159cabad1b43 100644 --- a/tests/ui/field_scoped_visibility_modifiers.rs +++ b/tests/ui/field_scoped_visibility_modifiers.rs @@ -7,8 +7,11 @@ pub mod pub_module { private_field: bool, pub pub_field: bool, pub(crate) pub_crate_field: bool, + //~^ field_scoped_visibility_modifiers pub(in crate::pub_module) pub_in_path_field: bool, + //~^ field_scoped_visibility_modifiers pub(super) pub_super_field: bool, + //~^ field_scoped_visibility_modifiers #[allow(clippy::needless_pub_self)] pub(self) pub_self_field: bool, } diff --git a/tests/ui/field_scoped_visibility_modifiers.stderr b/tests/ui/field_scoped_visibility_modifiers.stderr index beea6c92107c..c0c202fd87af 100644 --- a/tests/ui/field_scoped_visibility_modifiers.stderr +++ b/tests/ui/field_scoped_visibility_modifiers.stderr @@ -9,7 +9,7 @@ LL | pub(crate) pub_crate_field: bool, = help: to override `-D warnings` add `#[allow(clippy::field_scoped_visibility_modifiers)]` error: scoped visibility modifier on a field - --> tests/ui/field_scoped_visibility_modifiers.rs:10:9 + --> tests/ui/field_scoped_visibility_modifiers.rs:11:9 | LL | pub(in crate::pub_module) pub_in_path_field: bool, | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | pub(in crate::pub_module) pub_in_path_field: bool, = help: consider making the field private and adding a scoped visibility method for it error: scoped visibility modifier on a field - --> tests/ui/field_scoped_visibility_modifiers.rs:11:9 + --> tests/ui/field_scoped_visibility_modifiers.rs:13:9 | LL | pub(super) pub_super_field: bool, | ^^^^^^^^^^ diff --git a/tests/ui/filetype_is_file.rs b/tests/ui/filetype_is_file.rs index 9e8a4c04324b..8ca01b91210f 100644 --- a/tests/ui/filetype_is_file.rs +++ b/tests/ui/filetype_is_file.rs @@ -7,19 +7,22 @@ fn main() -> std::io::Result<()> { // !filetype.is_dir() if fs::metadata("foo.txt")?.file_type().is_file() { - //~^ ERROR: `FileType::is_file()` only covers regular files + //~^ filetype_is_file + // read file } // positive of filetype.is_dir() if !fs::metadata("foo.txt")?.file_type().is_file() { - //~^ ERROR: `!FileType::is_file()` only denies regular files + //~^ filetype_is_file + // handle dir } // false positive of filetype.is_dir() if !fs::metadata("foo.txt")?.file_type().is_file().bitor(true) { - //~^ ERROR: `FileType::is_file()` only covers regular files + //~^ filetype_is_file + // ... } diff --git a/tests/ui/filetype_is_file.stderr b/tests/ui/filetype_is_file.stderr index 0c66910c1b61..b930ac929748 100644 --- a/tests/ui/filetype_is_file.stderr +++ b/tests/ui/filetype_is_file.stderr @@ -9,7 +9,7 @@ LL | if fs::metadata("foo.txt")?.file_type().is_file() { = help: to override `-D warnings` add `#[allow(clippy::filetype_is_file)]` error: `!FileType::is_file()` only denies regular files - --> tests/ui/filetype_is_file.rs:15:8 + --> tests/ui/filetype_is_file.rs:16:8 | LL | if !fs::metadata("foo.txt")?.file_type().is_file() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | if !fs::metadata("foo.txt")?.file_type().is_file() { = help: use `FileType::is_dir()` instead error: `FileType::is_file()` only covers regular files - --> tests/ui/filetype_is_file.rs:21:9 + --> tests/ui/filetype_is_file.rs:23:9 | LL | if !fs::metadata("foo.txt")?.file_type().is_file().bitor(true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/filter_map_bool_then.fixed b/tests/ui/filter_map_bool_then.fixed index 6a1b81fdbcbe..b3e112f19eb4 100644 --- a/tests/ui/filter_map_bool_then.fixed +++ b/tests/ui/filter_map_bool_then.fixed @@ -17,24 +17,30 @@ struct NonCopy; fn main() { let v = vec![1, 2, 3, 4, 5, 6]; v.clone().iter().filter(|&i| (i % 2 == 0)).map(|i| i + 1); + //~^ filter_map_bool_then v.clone().into_iter().filter(|&i| (i % 2 == 0)).map(|i| i + 1); + //~^ filter_map_bool_then v.clone() .into_iter() .filter(|&i| (i % 2 == 0)).map(|i| i + 1); + //~^ filter_map_bool_then v.clone() .into_iter() .filter(|&i| i != 1000) .filter(|&i| (i % 2 == 0)).map(|i| i + 1); + //~^ filter_map_bool_then v.iter() .copied() .filter(|&i| i != 1000) .filter(|&i| (i.clone() % 2 == 0)).map(|i| i + 1); + //~^ filter_map_bool_then // Despite this is non-copy, `is_copy` still returns true (at least now) because it's `&NonCopy`, // and any `&` is `Copy`. So since we can dereference it in `filter` (since it's then `&&NonCopy`), // we can lint this and still get the same input type. // See: let v = vec![NonCopy, NonCopy]; v.clone().iter().filter(|&i| (i == &NonCopy)).map(|i| i); + //~^ filter_map_bool_then // Do not lint let v = vec![NonCopy, NonCopy]; v.clone().into_iter().filter_map(|i| (i == NonCopy).then(|| i)); @@ -59,14 +65,17 @@ fn issue11309<'a>(iter: impl Iterator) -> Vec<&'a str fn issue11503() { let bools: &[bool] = &[true, false, false, true]; let _: Vec = bools.iter().enumerate().filter(|&(i, b)| *b).map(|(i, b)| i).collect(); + //~^ filter_map_bool_then // Need to insert multiple derefs if there is more than one layer of references let bools: &[&&bool] = &[&&true, &&false, &&false, &&true]; let _: Vec = bools.iter().enumerate().filter(|&(i, b)| ***b).map(|(i, b)| i).collect(); + //~^ filter_map_bool_then // Should also suggest derefs when going through a mutable reference let bools: &[&mut bool] = &[&mut true]; let _: Vec = bools.iter().enumerate().filter(|&(i, b)| **b).map(|(i, b)| i).collect(); + //~^ filter_map_bool_then // Should also suggest derefs when going through a custom deref struct DerefToBool; @@ -78,4 +87,5 @@ fn issue11503() { } let bools: &[&&DerefToBool] = &[&&DerefToBool]; let _: Vec = bools.iter().enumerate().filter(|&(i, b)| ****b).map(|(i, b)| i).collect(); + //~^ filter_map_bool_then } diff --git a/tests/ui/filter_map_bool_then.rs b/tests/ui/filter_map_bool_then.rs index a41e88f8805d..d996b3cb3c52 100644 --- a/tests/ui/filter_map_bool_then.rs +++ b/tests/ui/filter_map_bool_then.rs @@ -17,24 +17,30 @@ struct NonCopy; fn main() { let v = vec![1, 2, 3, 4, 5, 6]; v.clone().iter().filter_map(|i| (i % 2 == 0).then(|| i + 1)); + //~^ filter_map_bool_then v.clone().into_iter().filter_map(|i| (i % 2 == 0).then(|| i + 1)); + //~^ filter_map_bool_then v.clone() .into_iter() .filter_map(|i| -> Option<_> { (i % 2 == 0).then(|| i + 1) }); + //~^ filter_map_bool_then v.clone() .into_iter() .filter(|&i| i != 1000) .filter_map(|i| (i % 2 == 0).then(|| i + 1)); + //~^ filter_map_bool_then v.iter() .copied() .filter(|&i| i != 1000) .filter_map(|i| (i.clone() % 2 == 0).then(|| i + 1)); + //~^ filter_map_bool_then // Despite this is non-copy, `is_copy` still returns true (at least now) because it's `&NonCopy`, // and any `&` is `Copy`. So since we can dereference it in `filter` (since it's then `&&NonCopy`), // we can lint this and still get the same input type. // See: let v = vec![NonCopy, NonCopy]; v.clone().iter().filter_map(|i| (i == &NonCopy).then(|| i)); + //~^ filter_map_bool_then // Do not lint let v = vec![NonCopy, NonCopy]; v.clone().into_iter().filter_map(|i| (i == NonCopy).then(|| i)); @@ -59,14 +65,17 @@ fn issue11309<'a>(iter: impl Iterator) -> Vec<&'a str fn issue11503() { let bools: &[bool] = &[true, false, false, true]; let _: Vec = bools.iter().enumerate().filter_map(|(i, b)| b.then(|| i)).collect(); + //~^ filter_map_bool_then // Need to insert multiple derefs if there is more than one layer of references let bools: &[&&bool] = &[&&true, &&false, &&false, &&true]; let _: Vec = bools.iter().enumerate().filter_map(|(i, b)| b.then(|| i)).collect(); + //~^ filter_map_bool_then // Should also suggest derefs when going through a mutable reference let bools: &[&mut bool] = &[&mut true]; let _: Vec = bools.iter().enumerate().filter_map(|(i, b)| b.then(|| i)).collect(); + //~^ filter_map_bool_then // Should also suggest derefs when going through a custom deref struct DerefToBool; @@ -78,4 +87,5 @@ fn issue11503() { } let bools: &[&&DerefToBool] = &[&&DerefToBool]; let _: Vec = bools.iter().enumerate().filter_map(|(i, b)| b.then(|| i)).collect(); + //~^ filter_map_bool_then } diff --git a/tests/ui/filter_map_bool_then.stderr b/tests/ui/filter_map_bool_then.stderr index 088b9ba12867..aeb1baeb35e6 100644 --- a/tests/ui/filter_map_bool_then.stderr +++ b/tests/ui/filter_map_bool_then.stderr @@ -8,55 +8,55 @@ LL | v.clone().iter().filter_map(|i| (i % 2 == 0).then(|| i + 1)); = help: to override `-D warnings` add `#[allow(clippy::filter_map_bool_then)]` error: usage of `bool::then` in `filter_map` - --> tests/ui/filter_map_bool_then.rs:20:27 + --> tests/ui/filter_map_bool_then.rs:21:27 | LL | v.clone().into_iter().filter_map(|i| (i % 2 == 0).then(|| i + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `filter` then `map` instead: `filter(|&i| (i % 2 == 0)).map(|i| i + 1)` error: usage of `bool::then` in `filter_map` - --> tests/ui/filter_map_bool_then.rs:23:10 + --> tests/ui/filter_map_bool_then.rs:25:10 | LL | .filter_map(|i| -> Option<_> { (i % 2 == 0).then(|| i + 1) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `filter` then `map` instead: `filter(|&i| (i % 2 == 0)).map(|i| i + 1)` error: usage of `bool::then` in `filter_map` - --> tests/ui/filter_map_bool_then.rs:27:10 + --> tests/ui/filter_map_bool_then.rs:30:10 | LL | .filter_map(|i| (i % 2 == 0).then(|| i + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `filter` then `map` instead: `filter(|&i| (i % 2 == 0)).map(|i| i + 1)` error: usage of `bool::then` in `filter_map` - --> tests/ui/filter_map_bool_then.rs:31:10 + --> tests/ui/filter_map_bool_then.rs:35:10 | LL | .filter_map(|i| (i.clone() % 2 == 0).then(|| i + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `filter` then `map` instead: `filter(|&i| (i.clone() % 2 == 0)).map(|i| i + 1)` error: usage of `bool::then` in `filter_map` - --> tests/ui/filter_map_bool_then.rs:37:22 + --> tests/ui/filter_map_bool_then.rs:42:22 | LL | v.clone().iter().filter_map(|i| (i == &NonCopy).then(|| i)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `filter` then `map` instead: `filter(|&i| (i == &NonCopy)).map(|i| i)` error: usage of `bool::then` in `filter_map` - --> tests/ui/filter_map_bool_then.rs:61:50 + --> tests/ui/filter_map_bool_then.rs:67:50 | LL | let _: Vec = bools.iter().enumerate().filter_map(|(i, b)| b.then(|| i)).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `filter` then `map` instead: `filter(|&(i, b)| *b).map(|(i, b)| i)` error: usage of `bool::then` in `filter_map` - --> tests/ui/filter_map_bool_then.rs:65:50 + --> tests/ui/filter_map_bool_then.rs:72:50 | LL | let _: Vec = bools.iter().enumerate().filter_map(|(i, b)| b.then(|| i)).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `filter` then `map` instead: `filter(|&(i, b)| ***b).map(|(i, b)| i)` error: usage of `bool::then` in `filter_map` - --> tests/ui/filter_map_bool_then.rs:69:50 + --> tests/ui/filter_map_bool_then.rs:77:50 | LL | let _: Vec = bools.iter().enumerate().filter_map(|(i, b)| b.then(|| i)).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `filter` then `map` instead: `filter(|&(i, b)| **b).map(|(i, b)| i)` error: usage of `bool::then` in `filter_map` - --> tests/ui/filter_map_bool_then.rs:80:50 + --> tests/ui/filter_map_bool_then.rs:89:50 | LL | let _: Vec = bools.iter().enumerate().filter_map(|(i, b)| b.then(|| i)).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `filter` then `map` instead: `filter(|&(i, b)| ****b).map(|(i, b)| i)` diff --git a/tests/ui/filter_map_identity.fixed b/tests/ui/filter_map_identity.fixed index fdd020fcd773..c9e2c5f5049f 100644 --- a/tests/ui/filter_map_identity.fixed +++ b/tests/ui/filter_map_identity.fixed @@ -26,59 +26,75 @@ fn main() { { // into_iter copy_vec_non_inferred().into_iter().flatten(); - //~^ ERROR: use of + //~^ filter_map_identity + copy_vec_non_inferred().into_iter().flatten(); - //~^ ERROR: use of + //~^ filter_map_identity + copy_vec_non_inferred().into_iter().flatten(); - //~^ ERROR: use of + //~^ filter_map_identity + copy_vec_non_inferred().into_iter().flatten(); - //~^ ERROR: use of + //~^ filter_map_identity + copy_vec_non_inferred().into_iter().flatten(); - //~^ ERROR: use of + //~^ filter_map_identity non_copy_vec().into_iter().flatten(); - //~^ ERROR: use of - non_copy_vec().into_iter().flatten(); - //~^ ERROR: use of + //~^ filter_map_identity non_copy_vec().into_iter().flatten(); - //~^ ERROR: use of + //~^ filter_map_identity + non_copy_vec().into_iter().flatten(); - //~^ ERROR: use of + //~^ filter_map_identity + non_copy_vec().into_iter().flatten(); - //~^ ERROR: use of + //~^ filter_map_identity + non_copy_vec().into_iter().flatten(); - //~^ ERROR: use of + //~^ filter_map_identity + + non_copy_vec().into_iter().flatten(); + //~^ filter_map_identity copy_vec::().into_iter().flatten(); - //~^ ERROR: use of + //~^ filter_map_identity + copy_vec::().into_iter().flatten(); - //~^ ERROR: use of + //~^ filter_map_identity + copy_vec::().into_iter().flatten(); - //~^ ERROR: use of + //~^ filter_map_identity + copy_vec::().into_iter().flatten(); - //~^ ERROR: use of + //~^ filter_map_identity // we are forced to pass the type in the call. copy_vec::().into_iter().flatten(); - //~^ ERROR: use of + //~^ filter_map_identity + copy_vec::().into_iter().flatten(); - //~^ ERROR: use of + //~^ filter_map_identity + copy_vec::().into_iter().flatten(); - //~^ ERROR: use of + //~^ filter_map_identity + copy_vec::().into_iter().flatten(); - //~^ ERROR: use of + //~^ filter_map_identity + #[rustfmt::skip] copy_vec::().into_iter().flatten(); - //~^ ERROR: use of + //~^ filter_map_identity + #[rustfmt::skip] copy_vec::().into_iter().flatten(); - //~^ ERROR: use of + //~^ filter_map_identity // note, the compiler requires that we pass the type to `opaque`. This is mostly for reference, // it behaves the same as copy_vec. opaque::().into_iter().flatten(); - //~^ ERROR: use of + //~^ filter_map_identity } } diff --git a/tests/ui/filter_map_identity.rs b/tests/ui/filter_map_identity.rs index a626de9f5bbd..4c8d48f5221f 100644 --- a/tests/ui/filter_map_identity.rs +++ b/tests/ui/filter_map_identity.rs @@ -26,59 +26,75 @@ fn main() { { // into_iter copy_vec_non_inferred().into_iter().filter_map(|x| x); - //~^ ERROR: use of + //~^ filter_map_identity + copy_vec_non_inferred().into_iter().filter_map(std::convert::identity); - //~^ ERROR: use of + //~^ filter_map_identity + copy_vec_non_inferred().into_iter().filter_map(identity); - //~^ ERROR: use of + //~^ filter_map_identity + copy_vec_non_inferred().into_iter().filter_map(|x| return x); - //~^ ERROR: use of + //~^ filter_map_identity + copy_vec_non_inferred().into_iter().filter_map(|x| return x); - //~^ ERROR: use of + //~^ filter_map_identity non_copy_vec().into_iter().filter_map(|x| x); - //~^ ERROR: use of + //~^ filter_map_identity + non_copy_vec().into_iter().filter_map(|x| x); - //~^ ERROR: use of + //~^ filter_map_identity non_copy_vec().into_iter().filter_map(std::convert::identity); - //~^ ERROR: use of + //~^ filter_map_identity + non_copy_vec().into_iter().filter_map(identity); - //~^ ERROR: use of + //~^ filter_map_identity + non_copy_vec().into_iter().filter_map(|x| return x); - //~^ ERROR: use of + //~^ filter_map_identity + non_copy_vec().into_iter().filter_map(|x| return x); - //~^ ERROR: use of + //~^ filter_map_identity copy_vec::().into_iter().filter_map(|x: Option<_>| x); - //~^ ERROR: use of + //~^ filter_map_identity + copy_vec::().into_iter().filter_map(|x: Option<_>| x); - //~^ ERROR: use of + //~^ filter_map_identity + copy_vec::().into_iter().filter_map(|x: Option<_>| return x); - //~^ ERROR: use of + //~^ filter_map_identity + copy_vec::().into_iter().filter_map(|x: Option<_>| return x); - //~^ ERROR: use of + //~^ filter_map_identity // we are forced to pass the type in the call. copy_vec::().into_iter().filter_map(|x: Option| x); - //~^ ERROR: use of + //~^ filter_map_identity + copy_vec::().into_iter().filter_map(|x: Option| x); - //~^ ERROR: use of + //~^ filter_map_identity + copy_vec::().into_iter().filter_map(|x: Option| return x); - //~^ ERROR: use of + //~^ filter_map_identity + copy_vec::().into_iter().filter_map(|x: Option| return x); - //~^ ERROR: use of + //~^ filter_map_identity + #[rustfmt::skip] copy_vec::().into_iter().filter_map(|x: Option| -> Option {{ x }}); - //~^ ERROR: use of + //~^ filter_map_identity + #[rustfmt::skip] copy_vec::().into_iter().filter_map(|x: Option| -> Option {{ return x }}); - //~^ ERROR: use of + //~^ filter_map_identity // note, the compiler requires that we pass the type to `opaque`. This is mostly for reference, // it behaves the same as copy_vec. opaque::().into_iter().filter_map(|x| x); - //~^ ERROR: use of + //~^ filter_map_identity } } diff --git a/tests/ui/filter_map_identity.stderr b/tests/ui/filter_map_identity.stderr index 55068db4e9d0..26b6e0bc7b34 100644 --- a/tests/ui/filter_map_identity.stderr +++ b/tests/ui/filter_map_identity.stderr @@ -8,127 +8,127 @@ LL | copy_vec_non_inferred().into_iter().filter_map(|x| x); = help: to override `-D warnings` add `#[allow(clippy::filter_map_identity)]` error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:30:45 + --> tests/ui/filter_map_identity.rs:31:45 | LL | copy_vec_non_inferred().into_iter().filter_map(std::convert::identity); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:32:45 + --> tests/ui/filter_map_identity.rs:34:45 | LL | copy_vec_non_inferred().into_iter().filter_map(identity); | ^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:34:45 + --> tests/ui/filter_map_identity.rs:37:45 | LL | copy_vec_non_inferred().into_iter().filter_map(|x| return x); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:36:45 + --> tests/ui/filter_map_identity.rs:40:45 | LL | copy_vec_non_inferred().into_iter().filter_map(|x| return x); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:39:36 + --> tests/ui/filter_map_identity.rs:43:36 | LL | non_copy_vec().into_iter().filter_map(|x| x); | ^^^^^^^^^^^^^^^^^ help: try: `flatten()` error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:41:36 + --> tests/ui/filter_map_identity.rs:46:36 | LL | non_copy_vec().into_iter().filter_map(|x| x); | ^^^^^^^^^^^^^^^^^ help: try: `flatten()` error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:44:36 + --> tests/ui/filter_map_identity.rs:49:36 | LL | non_copy_vec().into_iter().filter_map(std::convert::identity); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:46:36 + --> tests/ui/filter_map_identity.rs:52:36 | LL | non_copy_vec().into_iter().filter_map(identity); | ^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:48:36 + --> tests/ui/filter_map_identity.rs:55:36 | LL | non_copy_vec().into_iter().filter_map(|x| return x); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:50:36 + --> tests/ui/filter_map_identity.rs:58:36 | LL | non_copy_vec().into_iter().filter_map(|x| return x); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:53:39 + --> tests/ui/filter_map_identity.rs:61:39 | LL | copy_vec::().into_iter().filter_map(|x: Option<_>| x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:55:39 + --> tests/ui/filter_map_identity.rs:64:39 | LL | copy_vec::().into_iter().filter_map(|x: Option<_>| x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` -error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:57:39 - | -LL | copy_vec::().into_iter().filter_map(|x: Option<_>| return x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` - -error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:59:39 - | -LL | copy_vec::().into_iter().filter_map(|x: Option<_>| return x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` - -error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:63:39 - | -LL | copy_vec::().into_iter().filter_map(|x: Option| x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` - -error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:65:39 - | -LL | copy_vec::().into_iter().filter_map(|x: Option| x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` - error: use of `filter_map` with an identity function --> tests/ui/filter_map_identity.rs:67:39 | -LL | copy_vec::().into_iter().filter_map(|x: Option| return x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` +LL | copy_vec::().into_iter().filter_map(|x: Option<_>| return x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:69:39 + --> tests/ui/filter_map_identity.rs:70:39 + | +LL | copy_vec::().into_iter().filter_map(|x: Option<_>| return x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: use of `filter_map` with an identity function + --> tests/ui/filter_map_identity.rs:74:39 + | +LL | copy_vec::().into_iter().filter_map(|x: Option| x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: use of `filter_map` with an identity function + --> tests/ui/filter_map_identity.rs:77:39 + | +LL | copy_vec::().into_iter().filter_map(|x: Option| x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: use of `filter_map` with an identity function + --> tests/ui/filter_map_identity.rs:80:39 | LL | copy_vec::().into_iter().filter_map(|x: Option| return x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:72:43 + --> tests/ui/filter_map_identity.rs:83:39 + | +LL | copy_vec::().into_iter().filter_map(|x: Option| return x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: use of `filter_map` with an identity function + --> tests/ui/filter_map_identity.rs:87:43 | LL | copy_vec::().into_iter().filter_map(|x: Option| -> Option {{ x }}); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:75:43 + --> tests/ui/filter_map_identity.rs:91:43 | LL | copy_vec::().into_iter().filter_map(|x: Option| -> Option {{ return x }}); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` error: use of `filter_map` with an identity function - --> tests/ui/filter_map_identity.rs:80:37 + --> tests/ui/filter_map_identity.rs:96:37 | LL | opaque::().into_iter().filter_map(|x| x); | ^^^^^^^^^^^^^^^^^ help: try: `flatten()` diff --git a/tests/ui/filter_map_next.rs b/tests/ui/filter_map_next.rs index 9077b8fca23e..2a2237ed16cf 100644 --- a/tests/ui/filter_map_next.rs +++ b/tests/ui/filter_map_next.rs @@ -5,8 +5,9 @@ fn main() { #[rustfmt::skip] let _: Option = vec![1, 2, 3, 4, 5, 6] - //~^ ERROR: called `filter_map(..).next()` on an `Iterator`. This is more succinctly e - //~| NOTE: `-D clippy::filter-map-next` implied by `-D warnings` + //~^ filter_map_next + + .into_iter() .filter_map(|x| { if x == 2 { diff --git a/tests/ui/filter_map_next.stderr b/tests/ui/filter_map_next.stderr index cd3ffe3aa7f0..974bb946d46a 100644 --- a/tests/ui/filter_map_next.stderr +++ b/tests/ui/filter_map_next.stderr @@ -3,9 +3,6 @@ error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly | LL | let _: Option = vec![1, 2, 3, 4, 5, 6] | __________________________^ -LL | | -LL | | -LL | | .into_iter() ... | LL | | }) LL | | .next(); diff --git a/tests/ui/filter_map_next_fixable.fixed b/tests/ui/filter_map_next_fixable.fixed index 193ac3aea433..285863ef340d 100644 --- a/tests/ui/filter_map_next_fixable.fixed +++ b/tests/ui/filter_map_next_fixable.fixed @@ -5,6 +5,7 @@ fn main() { let a = ["1", "lol", "3", "NaN", "5"]; let element: Option = a.iter().find_map(|s| s.parse().ok()); + //~^ filter_map_next assert_eq!(element, Some(1)); } @@ -18,4 +19,5 @@ fn msrv_1_29() { fn msrv_1_30() { let a = ["1", "lol", "3", "NaN", "5"]; let _: Option = a.iter().find_map(|s| s.parse().ok()); + //~^ filter_map_next } diff --git a/tests/ui/filter_map_next_fixable.rs b/tests/ui/filter_map_next_fixable.rs index dab8d289817e..af911689b7c7 100644 --- a/tests/ui/filter_map_next_fixable.rs +++ b/tests/ui/filter_map_next_fixable.rs @@ -5,6 +5,7 @@ fn main() { let a = ["1", "lol", "3", "NaN", "5"]; let element: Option = a.iter().filter_map(|s| s.parse().ok()).next(); + //~^ filter_map_next assert_eq!(element, Some(1)); } @@ -18,4 +19,5 @@ fn msrv_1_29() { fn msrv_1_30() { let a = ["1", "lol", "3", "NaN", "5"]; let _: Option = a.iter().filter_map(|s| s.parse().ok()).next(); + //~^ filter_map_next } diff --git a/tests/ui/filter_map_next_fixable.stderr b/tests/ui/filter_map_next_fixable.stderr index 2c6148f3f4b6..707dec8687b1 100644 --- a/tests/ui/filter_map_next_fixable.stderr +++ b/tests/ui/filter_map_next_fixable.stderr @@ -8,7 +8,7 @@ LL | let element: Option = a.iter().filter_map(|s| s.parse().ok()).next = help: to override `-D warnings` add `#[allow(clippy::filter_map_next)]` error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(..)` instead - --> tests/ui/filter_map_next_fixable.rs:20:26 + --> tests/ui/filter_map_next_fixable.rs:21:26 | LL | let _: Option = a.iter().filter_map(|s| s.parse().ok()).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.iter().find_map(|s| s.parse().ok())` diff --git a/tests/ui/find_map.rs b/tests/ui/find_map.rs index bbd395d50ef2..aba1f2cbe581 100644 --- a/tests/ui/find_map.rs +++ b/tests/ui/find_map.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::all, clippy::pedantic)] #![allow(clippy::useless_vec)] diff --git a/tests/ui/flat_map_identity.fixed b/tests/ui/flat_map_identity.fixed index c142cf719808..f62062326126 100644 --- a/tests/ui/flat_map_identity.fixed +++ b/tests/ui/flat_map_identity.fixed @@ -6,10 +6,13 @@ use std::convert; fn main() { let iterator = [[0, 1], [2, 3], [4, 5]].iter(); let _ = iterator.flatten(); + //~^ flat_map_identity let iterator = [[0, 1], [2, 3], [4, 5]].iter(); let _ = iterator.flatten(); + //~^ flat_map_identity let iterator = [[0, 1], [2, 3], [4, 5]].iter(); let _ = iterator.flatten(); + //~^ flat_map_identity } diff --git a/tests/ui/flat_map_identity.rs b/tests/ui/flat_map_identity.rs index 8505ba9005d3..c59e749474ee 100644 --- a/tests/ui/flat_map_identity.rs +++ b/tests/ui/flat_map_identity.rs @@ -6,10 +6,13 @@ use std::convert; fn main() { let iterator = [[0, 1], [2, 3], [4, 5]].iter(); let _ = iterator.flat_map(|x| x); + //~^ flat_map_identity let iterator = [[0, 1], [2, 3], [4, 5]].iter(); let _ = iterator.flat_map(convert::identity); + //~^ flat_map_identity let iterator = [[0, 1], [2, 3], [4, 5]].iter(); let _ = iterator.flat_map(|x| return x); + //~^ flat_map_identity } diff --git a/tests/ui/flat_map_identity.stderr b/tests/ui/flat_map_identity.stderr index 496fd972a498..75137f5d9e57 100644 --- a/tests/ui/flat_map_identity.stderr +++ b/tests/ui/flat_map_identity.stderr @@ -8,13 +8,13 @@ LL | let _ = iterator.flat_map(|x| x); = help: to override `-D warnings` add `#[allow(clippy::flat_map_identity)]` error: use of `flat_map` with an identity function - --> tests/ui/flat_map_identity.rs:11:22 + --> tests/ui/flat_map_identity.rs:12:22 | LL | let _ = iterator.flat_map(convert::identity); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` error: use of `flat_map` with an identity function - --> tests/ui/flat_map_identity.rs:14:22 + --> tests/ui/flat_map_identity.rs:16:22 | LL | let _ = iterator.flat_map(|x| return x); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` diff --git a/tests/ui/flat_map_option.fixed b/tests/ui/flat_map_option.fixed index e08d9a14533b..e65e77ab79dc 100644 --- a/tests/ui/flat_map_option.fixed +++ b/tests/ui/flat_map_option.fixed @@ -5,7 +5,9 @@ fn main() { // yay let c = |x| Some(x); let _ = [1].iter().filter_map(c); + //~^ flat_map_option let _ = [1].iter().filter_map(Some); + //~^ flat_map_option // nay let _ = [1].iter().flat_map(|_| &Some(1)); diff --git a/tests/ui/flat_map_option.rs b/tests/ui/flat_map_option.rs index 4d0f32ac0fda..6784100a4fc9 100644 --- a/tests/ui/flat_map_option.rs +++ b/tests/ui/flat_map_option.rs @@ -5,7 +5,9 @@ fn main() { // yay let c = |x| Some(x); let _ = [1].iter().flat_map(c); + //~^ flat_map_option let _ = [1].iter().flat_map(Some); + //~^ flat_map_option // nay let _ = [1].iter().flat_map(|_| &Some(1)); diff --git a/tests/ui/flat_map_option.stderr b/tests/ui/flat_map_option.stderr index 6e151965fad5..7f5f2c14ec8e 100644 --- a/tests/ui/flat_map_option.stderr +++ b/tests/ui/flat_map_option.stderr @@ -8,7 +8,7 @@ LL | let _ = [1].iter().flat_map(c); = help: to override `-D warnings` add `#[allow(clippy::flat_map_option)]` error: used `flat_map` where `filter_map` could be used instead - --> tests/ui/flat_map_option.rs:8:24 + --> tests/ui/flat_map_option.rs:9:24 | LL | let _ = [1].iter().flat_map(Some); | ^^^^^^^^ help: try: `filter_map` diff --git a/tests/ui/float_arithmetic.rs b/tests/ui/float_arithmetic.rs index 1647273c436d..3c447bc94c66 100644 --- a/tests/ui/float_arithmetic.rs +++ b/tests/ui/float_arithmetic.rs @@ -13,58 +13,70 @@ fn main() { let mut f = 1.0f32; f * 2.0; - //~^ ERROR: floating-point arithmetic detected - //~| NOTE: `-D clippy::float-arithmetic` implied by `-D warnings` + //~^ float_arithmetic + + 1.0 + f; - //~^ ERROR: floating-point arithmetic detected + //~^ float_arithmetic + f * 2.0; - //~^ ERROR: floating-point arithmetic detected + //~^ float_arithmetic + f / 2.0; - //~^ ERROR: floating-point arithmetic detected + //~^ float_arithmetic + f - 2.0 * 4.2; - //~^ ERROR: floating-point arithmetic detected + //~^ float_arithmetic + -f; - //~^ ERROR: floating-point arithmetic detected + //~^ float_arithmetic + f += 1.0; - //~^ ERROR: floating-point arithmetic detected + //~^ float_arithmetic + f -= 1.0; - //~^ ERROR: floating-point arithmetic detected + //~^ float_arithmetic + f *= 2.0; - //~^ ERROR: floating-point arithmetic detected + //~^ float_arithmetic + f /= 2.0; - //~^ ERROR: floating-point arithmetic detected + //~^ float_arithmetic + } // also warn about floating point arith with references involved pub fn float_arith_ref() { 3.1_f32 + &1.2_f32; - //~^ ERROR: floating-point arithmetic detected + //~^ float_arithmetic + &3.4_f32 + 1.5_f32; - //~^ ERROR: floating-point arithmetic detected + //~^ float_arithmetic + &3.5_f32 + &1.3_f32; - //~^ ERROR: floating-point arithmetic detected + //~^ float_arithmetic } pub fn float_foo(f: &f32) -> f32 { let a = 5.1; a + f - //~^ ERROR: floating-point arithmetic detected + //~^ float_arithmetic } pub fn float_bar(f1: &f32, f2: &f32) -> f32 { f1 + f2 - //~^ ERROR: floating-point arithmetic detected + //~^ float_arithmetic } pub fn float_baz(f1: f32, f2: &f32) -> f32 { f1 + f2 - //~^ ERROR: floating-point arithmetic detected + //~^ float_arithmetic } pub fn float_qux(f1: f32, f2: f32) -> f32 { (&f1 + &f2) - //~^ ERROR: floating-point arithmetic detected + //~^ float_arithmetic } diff --git a/tests/ui/float_arithmetic.stderr b/tests/ui/float_arithmetic.stderr index 66455f061455..8704f7bbd7c4 100644 --- a/tests/ui/float_arithmetic.stderr +++ b/tests/ui/float_arithmetic.stderr @@ -8,97 +8,97 @@ LL | f * 2.0; = help: to override `-D warnings` add `#[allow(clippy::float_arithmetic)]` error: floating-point arithmetic detected - --> tests/ui/float_arithmetic.rs:19:5 + --> tests/ui/float_arithmetic.rs:20:5 | LL | 1.0 + f; | ^^^^^^^ error: floating-point arithmetic detected - --> tests/ui/float_arithmetic.rs:21:5 + --> tests/ui/float_arithmetic.rs:23:5 | LL | f * 2.0; | ^^^^^^^ error: floating-point arithmetic detected - --> tests/ui/float_arithmetic.rs:23:5 + --> tests/ui/float_arithmetic.rs:26:5 | LL | f / 2.0; | ^^^^^^^ error: floating-point arithmetic detected - --> tests/ui/float_arithmetic.rs:25:5 + --> tests/ui/float_arithmetic.rs:29:5 | LL | f - 2.0 * 4.2; | ^^^^^^^^^^^^^ error: floating-point arithmetic detected - --> tests/ui/float_arithmetic.rs:27:5 + --> tests/ui/float_arithmetic.rs:32:5 | LL | -f; | ^^ error: floating-point arithmetic detected - --> tests/ui/float_arithmetic.rs:30:5 + --> tests/ui/float_arithmetic.rs:36:5 | LL | f += 1.0; | ^^^^^^^^ error: floating-point arithmetic detected - --> tests/ui/float_arithmetic.rs:32:5 + --> tests/ui/float_arithmetic.rs:39:5 | LL | f -= 1.0; | ^^^^^^^^ error: floating-point arithmetic detected - --> tests/ui/float_arithmetic.rs:34:5 + --> tests/ui/float_arithmetic.rs:42:5 | LL | f *= 2.0; | ^^^^^^^^ error: floating-point arithmetic detected - --> tests/ui/float_arithmetic.rs:36:5 + --> tests/ui/float_arithmetic.rs:45:5 | LL | f /= 2.0; | ^^^^^^^^ error: floating-point arithmetic detected - --> tests/ui/float_arithmetic.rs:43:5 + --> tests/ui/float_arithmetic.rs:53:5 | LL | 3.1_f32 + &1.2_f32; | ^^^^^^^^^^^^^^^^^^ error: floating-point arithmetic detected - --> tests/ui/float_arithmetic.rs:45:5 + --> tests/ui/float_arithmetic.rs:56:5 | LL | &3.4_f32 + 1.5_f32; | ^^^^^^^^^^^^^^^^^^ error: floating-point arithmetic detected - --> tests/ui/float_arithmetic.rs:47:5 + --> tests/ui/float_arithmetic.rs:59:5 | LL | &3.5_f32 + &1.3_f32; | ^^^^^^^^^^^^^^^^^^^ error: floating-point arithmetic detected - --> tests/ui/float_arithmetic.rs:53:5 + --> tests/ui/float_arithmetic.rs:65:5 | LL | a + f | ^^^^^ error: floating-point arithmetic detected - --> tests/ui/float_arithmetic.rs:58:5 + --> tests/ui/float_arithmetic.rs:70:5 | LL | f1 + f2 | ^^^^^^^ error: floating-point arithmetic detected - --> tests/ui/float_arithmetic.rs:63:5 + --> tests/ui/float_arithmetic.rs:75:5 | LL | f1 + f2 | ^^^^^^^ error: floating-point arithmetic detected - --> tests/ui/float_arithmetic.rs:68:5 + --> tests/ui/float_arithmetic.rs:80:5 | LL | (&f1 + &f2) | ^^^^^^^^^^^ diff --git a/tests/ui/float_cmp.rs b/tests/ui/float_cmp.rs index a1dfd1954fce..ce0ffd8a2192 100644 --- a/tests/ui/float_cmp.rs +++ b/tests/ui/float_cmp.rs @@ -70,17 +70,19 @@ fn main() { ONE != 0.0; // no error, comparison with zero is ok twice(ONE) != ONE; ONE as f64 != 2.0; - //~^ ERROR: strict comparison of `f32` or `f64` + //~^ float_cmp + ONE as f64 != 0.0; // no error, comparison with zero is ok let x: f64 = 1.0; x == 1.0; - //~^ ERROR: strict comparison of `f32` or `f64` + //~^ float_cmp + x != 0f64; // no error, comparison with zero is ok twice(x) != twice(ONE as f64); - //~^ ERROR: strict comparison of `f32` or `f64` + //~^ float_cmp x < 0.0; // no errors, lower or greater comparisons need no fuzzyness x > 0.0; @@ -101,15 +103,16 @@ fn main() { ZERO_ARRAY[i] == NON_ZERO_ARRAY[j]; // ok, because lhs is zero regardless of i NON_ZERO_ARRAY[i] == NON_ZERO_ARRAY[j]; - //~^ ERROR: strict comparison of `f32` or `f64` + //~^ float_cmp let a1: [f32; 1] = [0.0]; let a2: [f32; 1] = [1.1]; a1 == a2; - //~^ ERROR: strict comparison of `f32` or `f64` arrays + //~^ float_cmp + a1[0] == a2[0]; - //~^ ERROR: strict comparison of `f32` or `f64` + //~^ float_cmp // no errors - comparing signums is ok let x32 = 3.21f32; diff --git a/tests/ui/float_cmp.stderr b/tests/ui/float_cmp.stderr index d10da8a99a9d..e573c0baeac2 100644 --- a/tests/ui/float_cmp.stderr +++ b/tests/ui/float_cmp.stderr @@ -8,31 +8,31 @@ LL | ONE as f64 != 2.0; = help: to override `-D warnings` add `#[allow(clippy::float_cmp)]` error: strict comparison of `f32` or `f64` - --> tests/ui/float_cmp.rs:78:5 + --> tests/ui/float_cmp.rs:79:5 | LL | x == 1.0; | ^^^^^^^^ help: consider comparing them within some margin of error: `(x - 1.0).abs() < error_margin` error: strict comparison of `f32` or `f64` - --> tests/ui/float_cmp.rs:82:5 + --> tests/ui/float_cmp.rs:84:5 | LL | twice(x) != twice(ONE as f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider comparing them within some margin of error: `(twice(x) - twice(ONE as f64)).abs() > error_margin` error: strict comparison of `f32` or `f64` - --> tests/ui/float_cmp.rs:103:5 + --> tests/ui/float_cmp.rs:105:5 | LL | NON_ZERO_ARRAY[i] == NON_ZERO_ARRAY[j]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider comparing them within some margin of error: `(NON_ZERO_ARRAY[i] - NON_ZERO_ARRAY[j]).abs() < error_margin` error: strict comparison of `f32` or `f64` arrays - --> tests/ui/float_cmp.rs:109:5 + --> tests/ui/float_cmp.rs:111:5 | LL | a1 == a2; | ^^^^^^^^ error: strict comparison of `f32` or `f64` - --> tests/ui/float_cmp.rs:111:5 + --> tests/ui/float_cmp.rs:114:5 | LL | a1[0] == a2[0]; | ^^^^^^^^^^^^^^ help: consider comparing them within some margin of error: `(a1[0] - a2[0]).abs() < error_margin` diff --git a/tests/ui/float_cmp_const.rs b/tests/ui/float_cmp_const.rs index ba760a18f28a..3af53f2e84a2 100644 --- a/tests/ui/float_cmp_const.rs +++ b/tests/ui/float_cmp_const.rs @@ -13,22 +13,27 @@ fn eq_one(x: f32) -> bool { fn main() { // has errors 1f32 == ONE; - //~^ ERROR: strict comparison of `f32` or `f64` constant + //~^ float_cmp_const + TWO == ONE; - //~^ ERROR: strict comparison of `f32` or `f64` constant + //~^ float_cmp_const + TWO != ONE; - //~^ ERROR: strict comparison of `f32` or `f64` constant + //~^ float_cmp_const + ONE + ONE == TWO; - //~^ ERROR: strict comparison of `f32` or `f64` constant + //~^ float_cmp_const + let x = 1; x as f32 == ONE; - //~^ ERROR: strict comparison of `f32` or `f64` constant + //~^ float_cmp_const let v = 0.9; v == ONE; - //~^ ERROR: strict comparison of `f32` or `f64` constant + //~^ float_cmp_const + v != ONE; - //~^ ERROR: strict comparison of `f32` or `f64` constant + //~^ float_cmp_const // no errors, lower than or greater than comparisons v < ONE; @@ -61,5 +66,5 @@ fn main() { // has errors NON_ZERO_ARRAY == NON_ZERO_ARRAY2; - //~^ ERROR: strict comparison of `f32` or `f64` constant arrays + //~^ float_cmp_const } diff --git a/tests/ui/float_cmp_const.stderr b/tests/ui/float_cmp_const.stderr index e0cd6faf4b3a..482a55a54be6 100644 --- a/tests/ui/float_cmp_const.stderr +++ b/tests/ui/float_cmp_const.stderr @@ -8,43 +8,43 @@ LL | 1f32 == ONE; = help: to override `-D warnings` add `#[allow(clippy::float_cmp_const)]` error: strict comparison of `f32` or `f64` constant - --> tests/ui/float_cmp_const.rs:17:5 + --> tests/ui/float_cmp_const.rs:18:5 | LL | TWO == ONE; | ^^^^^^^^^^ help: consider comparing them within some margin of error: `(TWO - ONE).abs() < error_margin` error: strict comparison of `f32` or `f64` constant - --> tests/ui/float_cmp_const.rs:19:5 + --> tests/ui/float_cmp_const.rs:21:5 | LL | TWO != ONE; | ^^^^^^^^^^ help: consider comparing them within some margin of error: `(TWO - ONE).abs() > error_margin` error: strict comparison of `f32` or `f64` constant - --> tests/ui/float_cmp_const.rs:21:5 + --> tests/ui/float_cmp_const.rs:24:5 | LL | ONE + ONE == TWO; | ^^^^^^^^^^^^^^^^ help: consider comparing them within some margin of error: `(ONE + ONE - TWO).abs() < error_margin` error: strict comparison of `f32` or `f64` constant - --> tests/ui/float_cmp_const.rs:24:5 + --> tests/ui/float_cmp_const.rs:28:5 | LL | x as f32 == ONE; | ^^^^^^^^^^^^^^^ help: consider comparing them within some margin of error: `(x as f32 - ONE).abs() < error_margin` error: strict comparison of `f32` or `f64` constant - --> tests/ui/float_cmp_const.rs:28:5 + --> tests/ui/float_cmp_const.rs:32:5 | LL | v == ONE; | ^^^^^^^^ help: consider comparing them within some margin of error: `(v - ONE).abs() < error_margin` error: strict comparison of `f32` or `f64` constant - --> tests/ui/float_cmp_const.rs:30:5 + --> tests/ui/float_cmp_const.rs:35:5 | LL | v != ONE; | ^^^^^^^^ help: consider comparing them within some margin of error: `(v - ONE).abs() > error_margin` error: strict comparison of `f32` or `f64` constant arrays - --> tests/ui/float_cmp_const.rs:63:5 + --> tests/ui/float_cmp_const.rs:68:5 | LL | NON_ZERO_ARRAY == NON_ZERO_ARRAY2; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/float_equality_without_abs.rs b/tests/ui/float_equality_without_abs.rs index 500b3035390f..a1548db6710d 100644 --- a/tests/ui/float_equality_without_abs.rs +++ b/tests/ui/float_equality_without_abs.rs @@ -5,8 +5,7 @@ pub fn is_roughly_equal(a: f32, b: f32) -> bool { (a - b) < f32::EPSILON - //~^ ERROR: float equality check without `.abs()` - //~| NOTE: `-D clippy::float-equality-without-abs` implied by `-D warnings` + //~^ float_equality_without_abs } pub fn main() { @@ -16,26 +15,34 @@ pub fn main() { let b = 0.0500001; let _ = (a - b) < f32::EPSILON; - //~^ ERROR: float equality check without `.abs()` + //~^ float_equality_without_abs + let _ = a - b < f32::EPSILON; - //~^ ERROR: float equality check without `.abs()` + //~^ float_equality_without_abs + let _ = a - b.abs() < f32::EPSILON; - //~^ ERROR: float equality check without `.abs()` + //~^ float_equality_without_abs + let _ = (a as f64 - b as f64) < f64::EPSILON; - //~^ ERROR: float equality check without `.abs()` + //~^ float_equality_without_abs + let _ = 1.0 - 2.0 < f32::EPSILON; - //~^ ERROR: float equality check without `.abs()` + //~^ float_equality_without_abs let _ = f32::EPSILON > (a - b); - //~^ ERROR: float equality check without `.abs()` + //~^ float_equality_without_abs + let _ = f32::EPSILON > a - b; - //~^ ERROR: float equality check without `.abs()` + //~^ float_equality_without_abs + let _ = f32::EPSILON > a - b.abs(); - //~^ ERROR: float equality check without `.abs()` + //~^ float_equality_without_abs + let _ = f64::EPSILON > (a as f64 - b as f64); - //~^ ERROR: float equality check without `.abs()` + //~^ float_equality_without_abs + let _ = f32::EPSILON > 1.0 - 2.0; - //~^ ERROR: float equality check without `.abs()` + //~^ float_equality_without_abs // those are correct let _ = (a - b).abs() < f32::EPSILON; diff --git a/tests/ui/float_equality_without_abs.stderr b/tests/ui/float_equality_without_abs.stderr index cdaaf0cdbcf7..d4c89ce72ba9 100644 --- a/tests/ui/float_equality_without_abs.stderr +++ b/tests/ui/float_equality_without_abs.stderr @@ -10,7 +10,7 @@ LL | (a - b) < f32::EPSILON = help: to override `-D warnings` add `#[allow(clippy::float_equality_without_abs)]` error: float equality check without `.abs()` - --> tests/ui/float_equality_without_abs.rs:18:13 + --> tests/ui/float_equality_without_abs.rs:17:13 | LL | let _ = (a - b) < f32::EPSILON; | -------^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | let _ = a - b < f32::EPSILON; | help: add `.abs()`: `(a - b).abs()` error: float equality check without `.abs()` - --> tests/ui/float_equality_without_abs.rs:22:13 + --> tests/ui/float_equality_without_abs.rs:23:13 | LL | let _ = a - b.abs() < f32::EPSILON; | -----------^^^^^^^^^^^^^^^ @@ -34,7 +34,7 @@ LL | let _ = a - b.abs() < f32::EPSILON; | help: add `.abs()`: `(a - b.abs()).abs()` error: float equality check without `.abs()` - --> tests/ui/float_equality_without_abs.rs:24:13 + --> tests/ui/float_equality_without_abs.rs:26:13 | LL | let _ = (a as f64 - b as f64) < f64::EPSILON; | ---------------------^^^^^^^^^^^^^^^ @@ -42,7 +42,7 @@ LL | let _ = (a as f64 - b as f64) < f64::EPSILON; | help: add `.abs()`: `(a as f64 - b as f64).abs()` error: float equality check without `.abs()` - --> tests/ui/float_equality_without_abs.rs:26:13 + --> tests/ui/float_equality_without_abs.rs:29:13 | LL | let _ = 1.0 - 2.0 < f32::EPSILON; | ---------^^^^^^^^^^^^^^^ @@ -50,7 +50,7 @@ LL | let _ = 1.0 - 2.0 < f32::EPSILON; | help: add `.abs()`: `(1.0 - 2.0).abs()` error: float equality check without `.abs()` - --> tests/ui/float_equality_without_abs.rs:29:13 + --> tests/ui/float_equality_without_abs.rs:32:13 | LL | let _ = f32::EPSILON > (a - b); | ^^^^^^^^^^^^^^^------- @@ -58,7 +58,7 @@ LL | let _ = f32::EPSILON > (a - b); | help: add `.abs()`: `(a - b).abs()` error: float equality check without `.abs()` - --> tests/ui/float_equality_without_abs.rs:31:13 + --> tests/ui/float_equality_without_abs.rs:35:13 | LL | let _ = f32::EPSILON > a - b; | ^^^^^^^^^^^^^^^----- @@ -66,7 +66,7 @@ LL | let _ = f32::EPSILON > a - b; | help: add `.abs()`: `(a - b).abs()` error: float equality check without `.abs()` - --> tests/ui/float_equality_without_abs.rs:33:13 + --> tests/ui/float_equality_without_abs.rs:38:13 | LL | let _ = f32::EPSILON > a - b.abs(); | ^^^^^^^^^^^^^^^----------- @@ -74,7 +74,7 @@ LL | let _ = f32::EPSILON > a - b.abs(); | help: add `.abs()`: `(a - b.abs()).abs()` error: float equality check without `.abs()` - --> tests/ui/float_equality_without_abs.rs:35:13 + --> tests/ui/float_equality_without_abs.rs:41:13 | LL | let _ = f64::EPSILON > (a as f64 - b as f64); | ^^^^^^^^^^^^^^^--------------------- @@ -82,7 +82,7 @@ LL | let _ = f64::EPSILON > (a as f64 - b as f64); | help: add `.abs()`: `(a as f64 - b as f64).abs()` error: float equality check without `.abs()` - --> tests/ui/float_equality_without_abs.rs:37:13 + --> tests/ui/float_equality_without_abs.rs:44:13 | LL | let _ = f32::EPSILON > 1.0 - 2.0; | ^^^^^^^^^^^^^^^--------- diff --git a/tests/ui/floating_point_abs.fixed b/tests/ui/floating_point_abs.fixed index 33183c769724..e8d64a3d7c29 100644 --- a/tests/ui/floating_point_abs.fixed +++ b/tests/ui/floating_point_abs.fixed @@ -12,35 +12,43 @@ struct A { fn fake_abs1(num: f64) -> f64 { num.abs() + //~^ suboptimal_flops } fn fake_abs2(num: f64) -> f64 { num.abs() + //~^ suboptimal_flops } fn fake_abs3(a: A) -> f64 { a.a.abs() + //~^ suboptimal_flops } fn fake_abs4(num: f64) -> f64 { num.abs() + //~^ suboptimal_flops } fn fake_abs5(a: A) -> f64 { a.a.abs() + //~^ suboptimal_flops } fn fake_nabs1(num: f64) -> f64 { -num.abs() + //~^ suboptimal_flops } fn fake_nabs2(num: f64) -> f64 { -num.abs() + //~^ suboptimal_flops } fn fake_nabs3(a: A) -> A { A { a: -a.a.abs(), + //~^ suboptimal_flops b: a.b, } } diff --git a/tests/ui/floating_point_abs.rs b/tests/ui/floating_point_abs.rs index a08d5bbcef5c..a27279b0662f 100644 --- a/tests/ui/floating_point_abs.rs +++ b/tests/ui/floating_point_abs.rs @@ -12,35 +12,43 @@ struct A { fn fake_abs1(num: f64) -> f64 { if num >= 0.0 { num } else { -num } + //~^ suboptimal_flops } fn fake_abs2(num: f64) -> f64 { if 0.0 < num { num } else { -num } + //~^ suboptimal_flops } fn fake_abs3(a: A) -> f64 { if a.a > 0.0 { a.a } else { -a.a } + //~^ suboptimal_flops } fn fake_abs4(num: f64) -> f64 { if 0.0 >= num { -num } else { num } + //~^ suboptimal_flops } fn fake_abs5(a: A) -> f64 { if a.a < 0.0 { -a.a } else { a.a } + //~^ suboptimal_flops } fn fake_nabs1(num: f64) -> f64 { if num < 0.0 { num } else { -num } + //~^ suboptimal_flops } fn fake_nabs2(num: f64) -> f64 { if 0.0 >= num { num } else { -num } + //~^ suboptimal_flops } fn fake_nabs3(a: A) -> A { A { a: if a.a >= 0.0 { -a.a } else { a.a }, + //~^ suboptimal_flops b: a.b, } } diff --git a/tests/ui/floating_point_abs.stderr b/tests/ui/floating_point_abs.stderr index 0c1f68f3b7fd..f031ac25114d 100644 --- a/tests/ui/floating_point_abs.stderr +++ b/tests/ui/floating_point_abs.stderr @@ -8,43 +8,43 @@ LL | if num >= 0.0 { num } else { -num } = help: to override `-D warnings` add `#[allow(clippy::suboptimal_flops)]` error: manual implementation of `abs` method - --> tests/ui/floating_point_abs.rs:18:5 + --> tests/ui/floating_point_abs.rs:19:5 | LL | if 0.0 < num { num } else { -num } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.abs()` error: manual implementation of `abs` method - --> tests/ui/floating_point_abs.rs:22:5 + --> tests/ui/floating_point_abs.rs:24:5 | LL | if a.a > 0.0 { a.a } else { -a.a } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.a.abs()` error: manual implementation of `abs` method - --> tests/ui/floating_point_abs.rs:26:5 + --> tests/ui/floating_point_abs.rs:29:5 | LL | if 0.0 >= num { -num } else { num } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.abs()` error: manual implementation of `abs` method - --> tests/ui/floating_point_abs.rs:30:5 + --> tests/ui/floating_point_abs.rs:34:5 | LL | if a.a < 0.0 { -a.a } else { a.a } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.a.abs()` error: manual implementation of negation of `abs` method - --> tests/ui/floating_point_abs.rs:34:5 + --> tests/ui/floating_point_abs.rs:39:5 | LL | if num < 0.0 { num } else { -num } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-num.abs()` error: manual implementation of negation of `abs` method - --> tests/ui/floating_point_abs.rs:38:5 + --> tests/ui/floating_point_abs.rs:44:5 | LL | if 0.0 >= num { num } else { -num } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-num.abs()` error: manual implementation of negation of `abs` method - --> tests/ui/floating_point_abs.rs:43:12 + --> tests/ui/floating_point_abs.rs:50:12 | LL | a: if a.a >= 0.0 { -a.a } else { a.a }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-a.a.abs()` diff --git a/tests/ui/floating_point_arithmetic_nostd.rs b/tests/ui/floating_point_arithmetic_nostd.rs index 81e4e0380dad..c4456bf870cd 100644 --- a/tests/ui/floating_point_arithmetic_nostd.rs +++ b/tests/ui/floating_point_arithmetic_nostd.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![crate_type = "lib"] #![warn(clippy::imprecise_flops)] #![warn(clippy::suboptimal_flops)] diff --git a/tests/ui/floating_point_exp.fixed b/tests/ui/floating_point_exp.fixed index fbd91cbc9d70..72a6f4fcfbd3 100644 --- a/tests/ui/floating_point_exp.fixed +++ b/tests/ui/floating_point_exp.fixed @@ -6,15 +6,20 @@ fn main() { let x = 2f32; let _ = x.exp_m1(); + //~^ imprecise_flops let _ = x.exp_m1() + 2.0; + //~^ imprecise_flops let _ = (x as f32).exp_m1() + 2.0; + //~^ imprecise_flops // Cases where the lint shouldn't be applied let _ = x.exp() - 2.0; let _ = x.exp() - 1.0 * 2.0; let x = 2f64; let _ = x.exp_m1(); + //~^ imprecise_flops let _ = x.exp_m1() + 2.0; + //~^ imprecise_flops // Cases where the lint shouldn't be applied let _ = x.exp() - 2.0; let _ = x.exp() - 1.0 * 2.0; diff --git a/tests/ui/floating_point_exp.rs b/tests/ui/floating_point_exp.rs index 340bacaf56b5..ce584c038a49 100644 --- a/tests/ui/floating_point_exp.rs +++ b/tests/ui/floating_point_exp.rs @@ -6,15 +6,20 @@ fn main() { let x = 2f32; let _ = x.exp() - 1.0; + //~^ imprecise_flops let _ = x.exp() - 1.0 + 2.0; + //~^ imprecise_flops let _ = (x as f32).exp() - 1.0 + 2.0; + //~^ imprecise_flops // Cases where the lint shouldn't be applied let _ = x.exp() - 2.0; let _ = x.exp() - 1.0 * 2.0; let x = 2f64; let _ = x.exp() - 1.0; + //~^ imprecise_flops let _ = x.exp() - 1.0 + 2.0; + //~^ imprecise_flops // Cases where the lint shouldn't be applied let _ = x.exp() - 2.0; let _ = x.exp() - 1.0 * 2.0; diff --git a/tests/ui/floating_point_exp.stderr b/tests/ui/floating_point_exp.stderr index 6ce67254abc9..7736a8e7ac36 100644 --- a/tests/ui/floating_point_exp.stderr +++ b/tests/ui/floating_point_exp.stderr @@ -8,25 +8,25 @@ LL | let _ = x.exp() - 1.0; = help: to override `-D warnings` add `#[allow(clippy::imprecise_flops)]` error: (e.pow(x) - 1) can be computed more accurately - --> tests/ui/floating_point_exp.rs:9:13 + --> tests/ui/floating_point_exp.rs:10:13 | LL | let _ = x.exp() - 1.0 + 2.0; | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` error: (e.pow(x) - 1) can be computed more accurately - --> tests/ui/floating_point_exp.rs:10:13 + --> tests/ui/floating_point_exp.rs:12:13 | LL | let _ = (x as f32).exp() - 1.0 + 2.0; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x as f32).exp_m1()` error: (e.pow(x) - 1) can be computed more accurately - --> tests/ui/floating_point_exp.rs:16:13 + --> tests/ui/floating_point_exp.rs:19:13 | LL | let _ = x.exp() - 1.0; | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` error: (e.pow(x) - 1) can be computed more accurately - --> tests/ui/floating_point_exp.rs:17:13 + --> tests/ui/floating_point_exp.rs:21:13 | LL | let _ = x.exp() - 1.0 + 2.0; | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` diff --git a/tests/ui/floating_point_hypot.fixed b/tests/ui/floating_point_hypot.fixed index 75a224440b0d..1fa684e78e0b 100644 --- a/tests/ui/floating_point_hypot.fixed +++ b/tests/ui/floating_point_hypot.fixed @@ -4,8 +4,11 @@ fn main() { let x = 3f32; let y = 4f32; let _ = x.hypot(y); + //~^ imprecise_flops let _ = (x + 1f32).hypot(y); + //~^ imprecise_flops let _ = x.hypot(y); + //~^ imprecise_flops // Cases where the lint shouldn't be applied // TODO: linting this adds some complexity, but could be done let _ = x.mul_add(x, y * y).sqrt(); diff --git a/tests/ui/floating_point_hypot.rs b/tests/ui/floating_point_hypot.rs index ed4dbf6382e7..9b4e74d28d0f 100644 --- a/tests/ui/floating_point_hypot.rs +++ b/tests/ui/floating_point_hypot.rs @@ -4,8 +4,11 @@ fn main() { let x = 3f32; let y = 4f32; let _ = (x * x + y * y).sqrt(); + //~^ imprecise_flops let _ = ((x + 1f32) * (x + 1f32) + y * y).sqrt(); + //~^ imprecise_flops let _ = (x.powi(2) + y.powi(2)).sqrt(); + //~^ imprecise_flops // Cases where the lint shouldn't be applied // TODO: linting this adds some complexity, but could be done let _ = x.mul_add(x, y * y).sqrt(); diff --git a/tests/ui/floating_point_hypot.stderr b/tests/ui/floating_point_hypot.stderr index 8942e86910da..3526df2cf265 100644 --- a/tests/ui/floating_point_hypot.stderr +++ b/tests/ui/floating_point_hypot.stderr @@ -8,13 +8,13 @@ LL | let _ = (x * x + y * y).sqrt(); = help: to override `-D warnings` add `#[allow(clippy::imprecise_flops)]` error: hypotenuse can be computed more accurately - --> tests/ui/floating_point_hypot.rs:7:13 + --> tests/ui/floating_point_hypot.rs:8:13 | LL | let _ = ((x + 1f32) * (x + 1f32) + y * y).sqrt(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x + 1f32).hypot(y)` error: hypotenuse can be computed more accurately - --> tests/ui/floating_point_hypot.rs:8:13 + --> tests/ui/floating_point_hypot.rs:10:13 | LL | let _ = (x.powi(2) + y.powi(2)).sqrt(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.hypot(y)` diff --git a/tests/ui/floating_point_log.fixed b/tests/ui/floating_point_log.fixed index 75e9c40a5218..275c9b4a3ab9 100644 --- a/tests/ui/floating_point_log.fixed +++ b/tests/ui/floating_point_log.fixed @@ -9,31 +9,51 @@ const E: f32 = std::f32::consts::E; fn check_log_base() { let x = 1f32; let _ = x.log2(); + //~^ suboptimal_flops let _ = x.log10(); + //~^ suboptimal_flops let _ = x.ln(); + //~^ suboptimal_flops let _ = x.log2(); + //~^ suboptimal_flops let _ = x.ln(); + //~^ suboptimal_flops let _ = (x as f32).log2(); + //~^ suboptimal_flops let x = 1f64; let _ = x.log2(); + //~^ suboptimal_flops let _ = x.log10(); + //~^ suboptimal_flops let _ = x.ln(); + //~^ suboptimal_flops } fn check_ln1p() { let x = 1f32; let _ = 2.0f32.ln_1p(); + //~^ imprecise_flops let _ = 2.0f32.ln_1p(); + //~^ imprecise_flops let _ = x.ln_1p(); + //~^ imprecise_flops let _ = (x / 2.0).ln_1p(); + //~^ imprecise_flops let _ = x.powi(3).ln_1p(); + //~^ imprecise_flops let _ = (x.powi(3) / 2.0).ln_1p(); + //~^ imprecise_flops let _ = (std::f32::consts::E - 1.0).ln_1p(); + //~^ imprecise_flops let _ = x.ln_1p(); + //~^ imprecise_flops let _ = x.powi(3).ln_1p(); + //~^ imprecise_flops let _ = (x + 2.0).ln_1p(); + //~^ imprecise_flops let _ = (x / 2.0).ln_1p(); + //~^ imprecise_flops // Cases where the lint shouldn't be applied let _ = (1.0 + x + 2.0).ln(); let _ = (x + 1.0 + 2.0).ln(); @@ -42,14 +62,23 @@ fn check_ln1p() { let x = 1f64; let _ = 2.0f64.ln_1p(); + //~^ imprecise_flops let _ = 2.0f64.ln_1p(); + //~^ imprecise_flops let _ = x.ln_1p(); + //~^ imprecise_flops let _ = (x / 2.0).ln_1p(); + //~^ imprecise_flops let _ = x.powi(3).ln_1p(); + //~^ imprecise_flops let _ = x.ln_1p(); + //~^ imprecise_flops let _ = x.powi(3).ln_1p(); + //~^ imprecise_flops let _ = (x + 2.0).ln_1p(); + //~^ imprecise_flops let _ = (x / 2.0).ln_1p(); + //~^ imprecise_flops // Cases where the lint shouldn't be applied let _ = (1.0 + x + 2.0).ln(); let _ = (x + 1.0 + 2.0).ln(); diff --git a/tests/ui/floating_point_log.rs b/tests/ui/floating_point_log.rs index d68369a38618..a372ccbb9fb0 100644 --- a/tests/ui/floating_point_log.rs +++ b/tests/ui/floating_point_log.rs @@ -9,31 +9,51 @@ const E: f32 = std::f32::consts::E; fn check_log_base() { let x = 1f32; let _ = x.log(2f32); + //~^ suboptimal_flops let _ = x.log(10f32); + //~^ suboptimal_flops let _ = x.log(std::f32::consts::E); + //~^ suboptimal_flops let _ = x.log(TWO); + //~^ suboptimal_flops let _ = x.log(E); + //~^ suboptimal_flops let _ = (x as f32).log(2f32); + //~^ suboptimal_flops let x = 1f64; let _ = x.log(2f64); + //~^ suboptimal_flops let _ = x.log(10f64); + //~^ suboptimal_flops let _ = x.log(std::f64::consts::E); + //~^ suboptimal_flops } fn check_ln1p() { let x = 1f32; let _ = (1f32 + 2.).ln(); + //~^ imprecise_flops let _ = (1f32 + 2.0).ln(); + //~^ imprecise_flops let _ = (1.0 + x).ln(); + //~^ imprecise_flops let _ = (1.0 + x / 2.0).ln(); + //~^ imprecise_flops let _ = (1.0 + x.powi(3)).ln(); + //~^ imprecise_flops let _ = (1.0 + x.powi(3) / 2.0).ln(); + //~^ imprecise_flops let _ = (1.0 + (std::f32::consts::E - 1.0)).ln(); + //~^ imprecise_flops let _ = (x + 1.0).ln(); + //~^ imprecise_flops let _ = (x.powi(3) + 1.0).ln(); + //~^ imprecise_flops let _ = (x + 2.0 + 1.0).ln(); + //~^ imprecise_flops let _ = (x / 2.0 + 1.0).ln(); + //~^ imprecise_flops // Cases where the lint shouldn't be applied let _ = (1.0 + x + 2.0).ln(); let _ = (x + 1.0 + 2.0).ln(); @@ -42,14 +62,23 @@ fn check_ln1p() { let x = 1f64; let _ = (1f64 + 2.).ln(); + //~^ imprecise_flops let _ = (1f64 + 2.0).ln(); + //~^ imprecise_flops let _ = (1.0 + x).ln(); + //~^ imprecise_flops let _ = (1.0 + x / 2.0).ln(); + //~^ imprecise_flops let _ = (1.0 + x.powi(3)).ln(); + //~^ imprecise_flops let _ = (x + 1.0).ln(); + //~^ imprecise_flops let _ = (x.powi(3) + 1.0).ln(); + //~^ imprecise_flops let _ = (x + 2.0 + 1.0).ln(); + //~^ imprecise_flops let _ = (x / 2.0 + 1.0).ln(); + //~^ imprecise_flops // Cases where the lint shouldn't be applied let _ = (1.0 + x + 2.0).ln(); let _ = (x + 1.0 + 2.0).ln(); diff --git a/tests/ui/floating_point_log.stderr b/tests/ui/floating_point_log.stderr index 19c28de8e39a..e93b3af851cb 100644 --- a/tests/ui/floating_point_log.stderr +++ b/tests/ui/floating_point_log.stderr @@ -8,55 +8,55 @@ LL | let _ = x.log(2f32); = help: to override `-D warnings` add `#[allow(clippy::suboptimal_flops)]` error: logarithm for bases 2, 10 and e can be computed more accurately - --> tests/ui/floating_point_log.rs:12:13 + --> tests/ui/floating_point_log.rs:13:13 | LL | let _ = x.log(10f32); | ^^^^^^^^^^^^ help: consider using: `x.log10()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> tests/ui/floating_point_log.rs:13:13 + --> tests/ui/floating_point_log.rs:15:13 | LL | let _ = x.log(std::f32::consts::E); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.ln()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> tests/ui/floating_point_log.rs:14:13 + --> tests/ui/floating_point_log.rs:17:13 | LL | let _ = x.log(TWO); | ^^^^^^^^^^ help: consider using: `x.log2()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> tests/ui/floating_point_log.rs:15:13 + --> tests/ui/floating_point_log.rs:19:13 | LL | let _ = x.log(E); | ^^^^^^^^ help: consider using: `x.ln()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> tests/ui/floating_point_log.rs:16:13 + --> tests/ui/floating_point_log.rs:21:13 | LL | let _ = (x as f32).log(2f32); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x as f32).log2()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> tests/ui/floating_point_log.rs:19:13 + --> tests/ui/floating_point_log.rs:25:13 | LL | let _ = x.log(2f64); | ^^^^^^^^^^^ help: consider using: `x.log2()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> tests/ui/floating_point_log.rs:20:13 + --> tests/ui/floating_point_log.rs:27:13 | LL | let _ = x.log(10f64); | ^^^^^^^^^^^^ help: consider using: `x.log10()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> tests/ui/floating_point_log.rs:21:13 + --> tests/ui/floating_point_log.rs:29:13 | LL | let _ = x.log(std::f64::consts::E); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.ln()` error: ln(1 + x) can be computed more accurately - --> tests/ui/floating_point_log.rs:26:13 + --> tests/ui/floating_point_log.rs:35:13 | LL | let _ = (1f32 + 2.).ln(); | ^^^^^^^^^^^^^^^^ help: consider using: `2.0f32.ln_1p()` @@ -65,95 +65,41 @@ LL | let _ = (1f32 + 2.).ln(); = help: to override `-D warnings` add `#[allow(clippy::imprecise_flops)]` error: ln(1 + x) can be computed more accurately - --> tests/ui/floating_point_log.rs:27:13 + --> tests/ui/floating_point_log.rs:37:13 | LL | let _ = (1f32 + 2.0).ln(); | ^^^^^^^^^^^^^^^^^ help: consider using: `2.0f32.ln_1p()` error: ln(1 + x) can be computed more accurately - --> tests/ui/floating_point_log.rs:28:13 + --> tests/ui/floating_point_log.rs:39:13 | LL | let _ = (1.0 + x).ln(); | ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()` error: ln(1 + x) can be computed more accurately - --> tests/ui/floating_point_log.rs:29:13 + --> tests/ui/floating_point_log.rs:41:13 | LL | let _ = (1.0 + x / 2.0).ln(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x / 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately - --> tests/ui/floating_point_log.rs:30:13 + --> tests/ui/floating_point_log.rs:43:13 | LL | let _ = (1.0 + x.powi(3)).ln(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()` error: ln(1 + x) can be computed more accurately - --> tests/ui/floating_point_log.rs:31:13 + --> tests/ui/floating_point_log.rs:45:13 | LL | let _ = (1.0 + x.powi(3) / 2.0).ln(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x.powi(3) / 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately - --> tests/ui/floating_point_log.rs:32:13 + --> tests/ui/floating_point_log.rs:47:13 | LL | let _ = (1.0 + (std::f32::consts::E - 1.0)).ln(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(std::f32::consts::E - 1.0).ln_1p()` -error: ln(1 + x) can be computed more accurately - --> tests/ui/floating_point_log.rs:33:13 - | -LL | let _ = (x + 1.0).ln(); - | ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()` - -error: ln(1 + x) can be computed more accurately - --> tests/ui/floating_point_log.rs:34:13 - | -LL | let _ = (x.powi(3) + 1.0).ln(); - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()` - -error: ln(1 + x) can be computed more accurately - --> tests/ui/floating_point_log.rs:35:13 - | -LL | let _ = (x + 2.0 + 1.0).ln(); - | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x + 2.0).ln_1p()` - -error: ln(1 + x) can be computed more accurately - --> tests/ui/floating_point_log.rs:36:13 - | -LL | let _ = (x / 2.0 + 1.0).ln(); - | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x / 2.0).ln_1p()` - -error: ln(1 + x) can be computed more accurately - --> tests/ui/floating_point_log.rs:44:13 - | -LL | let _ = (1f64 + 2.).ln(); - | ^^^^^^^^^^^^^^^^ help: consider using: `2.0f64.ln_1p()` - -error: ln(1 + x) can be computed more accurately - --> tests/ui/floating_point_log.rs:45:13 - | -LL | let _ = (1f64 + 2.0).ln(); - | ^^^^^^^^^^^^^^^^^ help: consider using: `2.0f64.ln_1p()` - -error: ln(1 + x) can be computed more accurately - --> tests/ui/floating_point_log.rs:46:13 - | -LL | let _ = (1.0 + x).ln(); - | ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()` - -error: ln(1 + x) can be computed more accurately - --> tests/ui/floating_point_log.rs:47:13 - | -LL | let _ = (1.0 + x / 2.0).ln(); - | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x / 2.0).ln_1p()` - -error: ln(1 + x) can be computed more accurately - --> tests/ui/floating_point_log.rs:48:13 - | -LL | let _ = (1.0 + x.powi(3)).ln(); - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()` - error: ln(1 + x) can be computed more accurately --> tests/ui/floating_point_log.rs:49:13 | @@ -161,19 +107,73 @@ LL | let _ = (x + 1.0).ln(); | ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()` error: ln(1 + x) can be computed more accurately - --> tests/ui/floating_point_log.rs:50:13 + --> tests/ui/floating_point_log.rs:51:13 | LL | let _ = (x.powi(3) + 1.0).ln(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()` error: ln(1 + x) can be computed more accurately - --> tests/ui/floating_point_log.rs:51:13 + --> tests/ui/floating_point_log.rs:53:13 | LL | let _ = (x + 2.0 + 1.0).ln(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x + 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately - --> tests/ui/floating_point_log.rs:52:13 + --> tests/ui/floating_point_log.rs:55:13 + | +LL | let _ = (x / 2.0 + 1.0).ln(); + | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x / 2.0).ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> tests/ui/floating_point_log.rs:64:13 + | +LL | let _ = (1f64 + 2.).ln(); + | ^^^^^^^^^^^^^^^^ help: consider using: `2.0f64.ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> tests/ui/floating_point_log.rs:66:13 + | +LL | let _ = (1f64 + 2.0).ln(); + | ^^^^^^^^^^^^^^^^^ help: consider using: `2.0f64.ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> tests/ui/floating_point_log.rs:68:13 + | +LL | let _ = (1.0 + x).ln(); + | ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> tests/ui/floating_point_log.rs:70:13 + | +LL | let _ = (1.0 + x / 2.0).ln(); + | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x / 2.0).ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> tests/ui/floating_point_log.rs:72:13 + | +LL | let _ = (1.0 + x.powi(3)).ln(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> tests/ui/floating_point_log.rs:74:13 + | +LL | let _ = (x + 1.0).ln(); + | ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> tests/ui/floating_point_log.rs:76:13 + | +LL | let _ = (x.powi(3) + 1.0).ln(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> tests/ui/floating_point_log.rs:78:13 + | +LL | let _ = (x + 2.0 + 1.0).ln(); + | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x + 2.0).ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> tests/ui/floating_point_log.rs:80:13 | LL | let _ = (x / 2.0 + 1.0).ln(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x / 2.0).ln_1p()` diff --git a/tests/ui/floating_point_logbase.fixed b/tests/ui/floating_point_logbase.fixed index 451673d109c6..d03882c774c0 100644 --- a/tests/ui/floating_point_logbase.fixed +++ b/tests/ui/floating_point_logbase.fixed @@ -5,10 +5,15 @@ fn main() { let x = 3f32; let y = 5f32; let _ = x.log(y); + //~^ suboptimal_flops let _ = (x as f32).log(y); + //~^ suboptimal_flops let _ = x.log(y); + //~^ suboptimal_flops let _ = x.log(y); + //~^ suboptimal_flops let _ = x.log(y); + //~^ suboptimal_flops // Cases where the lint shouldn't be applied let _ = x.ln() / y.powf(3.2); let _ = x.powf(3.2) / y.powf(3.2); diff --git a/tests/ui/floating_point_logbase.rs b/tests/ui/floating_point_logbase.rs index c309114599d9..c29f4deb3738 100644 --- a/tests/ui/floating_point_logbase.rs +++ b/tests/ui/floating_point_logbase.rs @@ -5,10 +5,15 @@ fn main() { let x = 3f32; let y = 5f32; let _ = x.ln() / y.ln(); + //~^ suboptimal_flops let _ = (x as f32).ln() / y.ln(); + //~^ suboptimal_flops let _ = x.log2() / y.log2(); + //~^ suboptimal_flops let _ = x.log10() / y.log10(); + //~^ suboptimal_flops let _ = x.log(5f32) / y.log(5f32); + //~^ suboptimal_flops // Cases where the lint shouldn't be applied let _ = x.ln() / y.powf(3.2); let _ = x.powf(3.2) / y.powf(3.2); diff --git a/tests/ui/floating_point_logbase.stderr b/tests/ui/floating_point_logbase.stderr index 8dfc57b133c6..1f30e5cbc177 100644 --- a/tests/ui/floating_point_logbase.stderr +++ b/tests/ui/floating_point_logbase.stderr @@ -8,25 +8,25 @@ LL | let _ = x.ln() / y.ln(); = help: to override `-D warnings` add `#[allow(clippy::suboptimal_flops)]` error: log base can be expressed more clearly - --> tests/ui/floating_point_logbase.rs:8:13 + --> tests/ui/floating_point_logbase.rs:9:13 | LL | let _ = (x as f32).ln() / y.ln(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x as f32).log(y)` error: log base can be expressed more clearly - --> tests/ui/floating_point_logbase.rs:9:13 + --> tests/ui/floating_point_logbase.rs:11:13 | LL | let _ = x.log2() / y.log2(); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: log base can be expressed more clearly - --> tests/ui/floating_point_logbase.rs:10:13 + --> tests/ui/floating_point_logbase.rs:13:13 | LL | let _ = x.log10() / y.log10(); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: log base can be expressed more clearly - --> tests/ui/floating_point_logbase.rs:11:13 + --> tests/ui/floating_point_logbase.rs:15:13 | LL | let _ = x.log(5f32) / y.log(5f32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` diff --git a/tests/ui/floating_point_mul_add.fixed b/tests/ui/floating_point_mul_add.fixed index 164aac2601a5..83aeddb2a1f4 100644 --- a/tests/ui/floating_point_mul_add.fixed +++ b/tests/ui/floating_point_mul_add.fixed @@ -17,23 +17,36 @@ fn main() { let d: f64 = 0.0001; let _ = a.mul_add(b, c); + //~^ suboptimal_flops let _ = a.mul_add(b, -c); + //~^ suboptimal_flops let _ = a.mul_add(b, c); + //~^ suboptimal_flops let _ = a.mul_add(-b, c); + //~^ suboptimal_flops let _ = 2.0f64.mul_add(4.0, a); + //~^ suboptimal_flops let _ = 2.0f64.mul_add(4., a); + //~^ suboptimal_flops let _ = a.mul_add(b, c); + //~^ suboptimal_flops let _ = a.mul_add(b, c); + //~^ suboptimal_flops let _ = (a * b).mul_add(c, d); + //~^ suboptimal_flops let _ = a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c)) + c; + //~^ suboptimal_flops let _ = 1234.567_f64.mul_add(45.67834_f64, 0.0004_f64); + //~^ suboptimal_flops let _ = a.mul_add(a, b).sqrt(); + //~^ suboptimal_flops let u = 1usize; let _ = b.mul_add(-(u as f64), a); + //~^ suboptimal_flops // Cases where the lint shouldn't be applied let _ = (a * a + b * b).sqrt(); diff --git a/tests/ui/floating_point_mul_add.rs b/tests/ui/floating_point_mul_add.rs index ae024b7f224b..039ee8d053fc 100644 --- a/tests/ui/floating_point_mul_add.rs +++ b/tests/ui/floating_point_mul_add.rs @@ -17,23 +17,36 @@ fn main() { let d: f64 = 0.0001; let _ = a * b + c; + //~^ suboptimal_flops let _ = a * b - c; + //~^ suboptimal_flops let _ = c + a * b; + //~^ suboptimal_flops let _ = c - a * b; + //~^ suboptimal_flops let _ = a + 2.0 * 4.0; + //~^ suboptimal_flops let _ = a + 2. * 4.; + //~^ suboptimal_flops let _ = (a * b) + c; + //~^ suboptimal_flops let _ = c + (a * b); + //~^ suboptimal_flops let _ = a * b * c + d; + //~^ suboptimal_flops let _ = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c; + //~^ suboptimal_flops let _ = 1234.567_f64 * 45.67834_f64 + 0.0004_f64; + //~^ suboptimal_flops let _ = (a * a + b).sqrt(); + //~^ suboptimal_flops let u = 1usize; let _ = a - (b * u as f64); + //~^ suboptimal_flops // Cases where the lint shouldn't be applied let _ = (a * a + b * b).sqrt(); diff --git a/tests/ui/floating_point_mul_add.stderr b/tests/ui/floating_point_mul_add.stderr index 9c75909f7158..6482127bcc00 100644 --- a/tests/ui/floating_point_mul_add.stderr +++ b/tests/ui/floating_point_mul_add.stderr @@ -8,73 +8,73 @@ LL | let _ = a * b + c; = help: to override `-D warnings` add `#[allow(clippy::suboptimal_flops)]` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:20:13 + --> tests/ui/floating_point_mul_add.rs:21:13 | LL | let _ = a * b - c; | ^^^^^^^^^ help: consider using: `a.mul_add(b, -c)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:21:13 + --> tests/ui/floating_point_mul_add.rs:23:13 | LL | let _ = c + a * b; | ^^^^^^^^^ help: consider using: `a.mul_add(b, c)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:22:13 + --> tests/ui/floating_point_mul_add.rs:25:13 | LL | let _ = c - a * b; | ^^^^^^^^^ help: consider using: `a.mul_add(-b, c)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:23:13 + --> tests/ui/floating_point_mul_add.rs:27:13 | LL | let _ = a + 2.0 * 4.0; | ^^^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4.0, a)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:24:13 + --> tests/ui/floating_point_mul_add.rs:29:13 | LL | let _ = a + 2. * 4.; | ^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4., a)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:26:13 + --> tests/ui/floating_point_mul_add.rs:32:13 | LL | let _ = (a * b) + c; | ^^^^^^^^^^^ help: consider using: `a.mul_add(b, c)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:27:13 + --> tests/ui/floating_point_mul_add.rs:34:13 | LL | let _ = c + (a * b); | ^^^^^^^^^^^ help: consider using: `a.mul_add(b, c)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:28:13 + --> tests/ui/floating_point_mul_add.rs:36:13 | LL | let _ = a * b * c + d; | ^^^^^^^^^^^^^ help: consider using: `(a * b).mul_add(c, d)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:30:13 + --> tests/ui/floating_point_mul_add.rs:39:13 | LL | let _ = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c))` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:31:13 + --> tests/ui/floating_point_mul_add.rs:41:13 | LL | let _ = 1234.567_f64 * 45.67834_f64 + 0.0004_f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1234.567_f64.mul_add(45.67834_f64, 0.0004_f64)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:33:13 + --> tests/ui/floating_point_mul_add.rs:44:13 | LL | let _ = (a * a + b).sqrt(); | ^^^^^^^^^^^ help: consider using: `a.mul_add(a, b)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:36:13 + --> tests/ui/floating_point_mul_add.rs:48:13 | LL | let _ = a - (b * u as f64); | ^^^^^^^^^^^^^^^^^^ help: consider using: `b.mul_add(-(u as f64), a)` diff --git a/tests/ui/floating_point_powf.fixed b/tests/ui/floating_point_powf.fixed index 25f09a637951..293df9bfe9b9 100644 --- a/tests/ui/floating_point_powf.fixed +++ b/tests/ui/floating_point_powf.fixed @@ -6,24 +6,43 @@ fn main() { let x = 3f32; let _ = x.exp2(); + //~^ suboptimal_flops let _ = 3.1f32.exp2(); + //~^ suboptimal_flops let _ = (-3.1f32).exp2(); + //~^ suboptimal_flops let _ = x.exp(); + //~^ suboptimal_flops let _ = 3.1f32.exp(); + //~^ suboptimal_flops let _ = (-3.1f32).exp(); + //~^ suboptimal_flops let _ = x.sqrt(); + //~^ suboptimal_flops let _ = x.cbrt(); + //~^ imprecise_flops let _ = (x as f32).cbrt(); + //~^ imprecise_flops let _ = x.powi(3); + //~^ suboptimal_flops let _ = x.powi(-2); + //~^ suboptimal_flops let _ = x.powi(16_777_215); + //~^ suboptimal_flops let _ = x.powi(-16_777_215); + //~^ suboptimal_flops let _ = (x as f32).powi(-16_777_215); + //~^ suboptimal_flops let _ = (x as f32).powi(3); + //~^ suboptimal_flops let _ = (1.5_f32 + 1.0).cbrt(); + //~^ imprecise_flops let _ = 1.5_f64.cbrt(); + //~^ imprecise_flops let _ = 1.5_f64.sqrt(); + //~^ suboptimal_flops let _ = 1.5_f64.powi(3); + //~^ suboptimal_flops macro_rules! m { ($e:expr) => { @@ -32,6 +51,7 @@ fn main() { } let _ = (1f32 + m!(2.0)).exp2(); + //~^ suboptimal_flops // Cases where the lint shouldn't be applied let _ = x.powf(2.1); @@ -41,17 +61,29 @@ fn main() { let x = 3f64; let _ = x.exp2(); + //~^ suboptimal_flops let _ = 3.1f64.exp2(); + //~^ suboptimal_flops let _ = (-3.1f64).exp2(); + //~^ suboptimal_flops let _ = x.exp(); + //~^ suboptimal_flops let _ = 3.1f64.exp(); + //~^ suboptimal_flops let _ = (-3.1f64).exp(); + //~^ suboptimal_flops let _ = x.sqrt(); + //~^ suboptimal_flops let _ = x.cbrt(); + //~^ imprecise_flops let _ = x.powi(3); + //~^ suboptimal_flops let _ = x.powi(-2); + //~^ suboptimal_flops let _ = x.powi(-2_147_483_648); + //~^ suboptimal_flops let _ = x.powi(2_147_483_647); + //~^ suboptimal_flops // Cases where the lint shouldn't be applied let _ = x.powf(2.1); let _ = x.powf(-2.1); diff --git a/tests/ui/floating_point_powf.rs b/tests/ui/floating_point_powf.rs index 9e9878de4bad..5b1940a369a5 100644 --- a/tests/ui/floating_point_powf.rs +++ b/tests/ui/floating_point_powf.rs @@ -6,24 +6,43 @@ fn main() { let x = 3f32; let _ = 2f32.powf(x); + //~^ suboptimal_flops let _ = 2f32.powf(3.1); + //~^ suboptimal_flops let _ = 2f32.powf(-3.1); + //~^ suboptimal_flops let _ = std::f32::consts::E.powf(x); + //~^ suboptimal_flops let _ = std::f32::consts::E.powf(3.1); + //~^ suboptimal_flops let _ = std::f32::consts::E.powf(-3.1); + //~^ suboptimal_flops let _ = x.powf(1.0 / 2.0); + //~^ suboptimal_flops let _ = x.powf(1.0 / 3.0); + //~^ imprecise_flops let _ = (x as f32).powf(1.0 / 3.0); + //~^ imprecise_flops let _ = x.powf(3.0); + //~^ suboptimal_flops let _ = x.powf(-2.0); + //~^ suboptimal_flops let _ = x.powf(16_777_215.0); + //~^ suboptimal_flops let _ = x.powf(-16_777_215.0); + //~^ suboptimal_flops let _ = (x as f32).powf(-16_777_215.0); + //~^ suboptimal_flops let _ = (x as f32).powf(3.0); + //~^ suboptimal_flops let _ = (1.5_f32 + 1.0).powf(1.0 / 3.0); + //~^ imprecise_flops let _ = 1.5_f64.powf(1.0 / 3.0); + //~^ imprecise_flops let _ = 1.5_f64.powf(1.0 / 2.0); + //~^ suboptimal_flops let _ = 1.5_f64.powf(3.0); + //~^ suboptimal_flops macro_rules! m { ($e:expr) => { @@ -32,6 +51,7 @@ fn main() { } let _ = 2f32.powf(1f32 + m!(2.0)); + //~^ suboptimal_flops // Cases where the lint shouldn't be applied let _ = x.powf(2.1); @@ -41,17 +61,29 @@ fn main() { let x = 3f64; let _ = 2f64.powf(x); + //~^ suboptimal_flops let _ = 2f64.powf(3.1); + //~^ suboptimal_flops let _ = 2f64.powf(-3.1); + //~^ suboptimal_flops let _ = std::f64::consts::E.powf(x); + //~^ suboptimal_flops let _ = std::f64::consts::E.powf(3.1); + //~^ suboptimal_flops let _ = std::f64::consts::E.powf(-3.1); + //~^ suboptimal_flops let _ = x.powf(1.0 / 2.0); + //~^ suboptimal_flops let _ = x.powf(1.0 / 3.0); + //~^ imprecise_flops let _ = x.powf(3.0); + //~^ suboptimal_flops let _ = x.powf(-2.0); + //~^ suboptimal_flops let _ = x.powf(-2_147_483_648.0); + //~^ suboptimal_flops let _ = x.powf(2_147_483_647.0); + //~^ suboptimal_flops // Cases where the lint shouldn't be applied let _ = x.powf(2.1); let _ = x.powf(-2.1); diff --git a/tests/ui/floating_point_powf.stderr b/tests/ui/floating_point_powf.stderr index c944f14fa34d..dec30a94cc78 100644 --- a/tests/ui/floating_point_powf.stderr +++ b/tests/ui/floating_point_powf.stderr @@ -8,43 +8,43 @@ LL | let _ = 2f32.powf(x); = help: to override `-D warnings` add `#[allow(clippy::suboptimal_flops)]` error: exponent for bases 2 and e can be computed more accurately - --> tests/ui/floating_point_powf.rs:9:13 + --> tests/ui/floating_point_powf.rs:10:13 | LL | let _ = 2f32.powf(3.1); | ^^^^^^^^^^^^^^ help: consider using: `3.1f32.exp2()` error: exponent for bases 2 and e can be computed more accurately - --> tests/ui/floating_point_powf.rs:10:13 + --> tests/ui/floating_point_powf.rs:12:13 | LL | let _ = 2f32.powf(-3.1); | ^^^^^^^^^^^^^^^ help: consider using: `(-3.1f32).exp2()` error: exponent for bases 2 and e can be computed more accurately - --> tests/ui/floating_point_powf.rs:11:13 + --> tests/ui/floating_point_powf.rs:14:13 | LL | let _ = std::f32::consts::E.powf(x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()` error: exponent for bases 2 and e can be computed more accurately - --> tests/ui/floating_point_powf.rs:12:13 + --> tests/ui/floating_point_powf.rs:16:13 | LL | let _ = std::f32::consts::E.powf(3.1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `3.1f32.exp()` error: exponent for bases 2 and e can be computed more accurately - --> tests/ui/floating_point_powf.rs:13:13 + --> tests/ui/floating_point_powf.rs:18:13 | LL | let _ = std::f32::consts::E.powf(-3.1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-3.1f32).exp()` error: square-root of a number can be computed more efficiently and accurately - --> tests/ui/floating_point_powf.rs:14:13 + --> tests/ui/floating_point_powf.rs:20:13 | LL | let _ = x.powf(1.0 / 2.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()` error: cube-root of a number can be computed more accurately - --> tests/ui/floating_point_powf.rs:15:13 + --> tests/ui/floating_point_powf.rs:22:13 | LL | let _ = x.powf(1.0 / 3.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()` @@ -53,145 +53,145 @@ LL | let _ = x.powf(1.0 / 3.0); = help: to override `-D warnings` add `#[allow(clippy::imprecise_flops)]` error: cube-root of a number can be computed more accurately - --> tests/ui/floating_point_powf.rs:16:13 + --> tests/ui/floating_point_powf.rs:24:13 | LL | let _ = (x as f32).powf(1.0 / 3.0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x as f32).cbrt()` error: exponentiation with integer powers can be computed more efficiently - --> tests/ui/floating_point_powf.rs:17:13 + --> tests/ui/floating_point_powf.rs:26:13 | LL | let _ = x.powf(3.0); | ^^^^^^^^^^^ help: consider using: `x.powi(3)` error: exponentiation with integer powers can be computed more efficiently - --> tests/ui/floating_point_powf.rs:18:13 + --> tests/ui/floating_point_powf.rs:28:13 | LL | let _ = x.powf(-2.0); | ^^^^^^^^^^^^ help: consider using: `x.powi(-2)` error: exponentiation with integer powers can be computed more efficiently - --> tests/ui/floating_point_powf.rs:19:13 + --> tests/ui/floating_point_powf.rs:30:13 | LL | let _ = x.powf(16_777_215.0); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(16_777_215)` error: exponentiation with integer powers can be computed more efficiently - --> tests/ui/floating_point_powf.rs:20:13 + --> tests/ui/floating_point_powf.rs:32:13 | LL | let _ = x.powf(-16_777_215.0); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(-16_777_215)` error: exponentiation with integer powers can be computed more efficiently - --> tests/ui/floating_point_powf.rs:21:13 + --> tests/ui/floating_point_powf.rs:34:13 | LL | let _ = (x as f32).powf(-16_777_215.0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x as f32).powi(-16_777_215)` error: exponentiation with integer powers can be computed more efficiently - --> tests/ui/floating_point_powf.rs:22:13 + --> tests/ui/floating_point_powf.rs:36:13 | LL | let _ = (x as f32).powf(3.0); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x as f32).powi(3)` error: cube-root of a number can be computed more accurately - --> tests/ui/floating_point_powf.rs:23:13 + --> tests/ui/floating_point_powf.rs:38:13 | LL | let _ = (1.5_f32 + 1.0).powf(1.0 / 3.0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(1.5_f32 + 1.0).cbrt()` error: cube-root of a number can be computed more accurately - --> tests/ui/floating_point_powf.rs:24:13 + --> tests/ui/floating_point_powf.rs:40:13 | LL | let _ = 1.5_f64.powf(1.0 / 3.0); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1.5_f64.cbrt()` error: square-root of a number can be computed more efficiently and accurately - --> tests/ui/floating_point_powf.rs:25:13 + --> tests/ui/floating_point_powf.rs:42:13 | LL | let _ = 1.5_f64.powf(1.0 / 2.0); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1.5_f64.sqrt()` error: exponentiation with integer powers can be computed more efficiently - --> tests/ui/floating_point_powf.rs:26:13 + --> tests/ui/floating_point_powf.rs:44:13 | LL | let _ = 1.5_f64.powf(3.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `1.5_f64.powi(3)` error: exponent for bases 2 and e can be computed more accurately - --> tests/ui/floating_point_powf.rs:34:13 + --> tests/ui/floating_point_powf.rs:53:13 | LL | let _ = 2f32.powf(1f32 + m!(2.0)); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(1f32 + m!(2.0)).exp2()` error: exponent for bases 2 and e can be computed more accurately - --> tests/ui/floating_point_powf.rs:43:13 + --> tests/ui/floating_point_powf.rs:63:13 | LL | let _ = 2f64.powf(x); | ^^^^^^^^^^^^ help: consider using: `x.exp2()` error: exponent for bases 2 and e can be computed more accurately - --> tests/ui/floating_point_powf.rs:44:13 + --> tests/ui/floating_point_powf.rs:65:13 | LL | let _ = 2f64.powf(3.1); | ^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp2()` error: exponent for bases 2 and e can be computed more accurately - --> tests/ui/floating_point_powf.rs:45:13 + --> tests/ui/floating_point_powf.rs:67:13 | LL | let _ = 2f64.powf(-3.1); | ^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp2()` error: exponent for bases 2 and e can be computed more accurately - --> tests/ui/floating_point_powf.rs:46:13 + --> tests/ui/floating_point_powf.rs:69:13 | LL | let _ = std::f64::consts::E.powf(x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()` error: exponent for bases 2 and e can be computed more accurately - --> tests/ui/floating_point_powf.rs:47:13 + --> tests/ui/floating_point_powf.rs:71:13 | LL | let _ = std::f64::consts::E.powf(3.1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp()` error: exponent for bases 2 and e can be computed more accurately - --> tests/ui/floating_point_powf.rs:48:13 + --> tests/ui/floating_point_powf.rs:73:13 | LL | let _ = std::f64::consts::E.powf(-3.1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp()` error: square-root of a number can be computed more efficiently and accurately - --> tests/ui/floating_point_powf.rs:49:13 + --> tests/ui/floating_point_powf.rs:75:13 | LL | let _ = x.powf(1.0 / 2.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()` error: cube-root of a number can be computed more accurately - --> tests/ui/floating_point_powf.rs:50:13 + --> tests/ui/floating_point_powf.rs:77:13 | LL | let _ = x.powf(1.0 / 3.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()` error: exponentiation with integer powers can be computed more efficiently - --> tests/ui/floating_point_powf.rs:51:13 + --> tests/ui/floating_point_powf.rs:79:13 | LL | let _ = x.powf(3.0); | ^^^^^^^^^^^ help: consider using: `x.powi(3)` error: exponentiation with integer powers can be computed more efficiently - --> tests/ui/floating_point_powf.rs:52:13 + --> tests/ui/floating_point_powf.rs:81:13 | LL | let _ = x.powf(-2.0); | ^^^^^^^^^^^^ help: consider using: `x.powi(-2)` error: exponentiation with integer powers can be computed more efficiently - --> tests/ui/floating_point_powf.rs:53:13 + --> tests/ui/floating_point_powf.rs:83:13 | LL | let _ = x.powf(-2_147_483_648.0); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(-2_147_483_648)` error: exponentiation with integer powers can be computed more efficiently - --> tests/ui/floating_point_powf.rs:54:13 + --> tests/ui/floating_point_powf.rs:85:13 | LL | let _ = x.powf(2_147_483_647.0); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2_147_483_647)` diff --git a/tests/ui/floating_point_powi.fixed b/tests/ui/floating_point_powi.fixed index cb033c899f31..5f0618ab1c72 100644 --- a/tests/ui/floating_point_powi.fixed +++ b/tests/ui/floating_point_powi.fixed @@ -7,20 +7,34 @@ fn main() { let y = 4f32; let _ = x.mul_add(x, y); + //~^ suboptimal_flops let _ = x.mul_add(x, -y); + //~^ suboptimal_flops let _ = y.mul_add(y, x); + //~^ suboptimal_flops let _ = y.mul_add(-y, x); + //~^ suboptimal_flops let _ = (y as f32).mul_add(y as f32, x); + //~^ suboptimal_flops let _ = x.mul_add(x, y).sqrt(); + //~^ suboptimal_flops let _ = y.mul_add(y, x).sqrt(); + //~^ suboptimal_flops let _ = (x - 1.0).mul_add(x - 1.0, -y); + //~^ suboptimal_flops let _ = (x - 1.0).mul_add(x - 1.0, -y) + 3.0; + //~^ suboptimal_flops let _ = (x - 1.0).mul_add(x - 1.0, -(y + 3.0)); + //~^ suboptimal_flops let _ = (y + 1.0).mul_add(-(y + 1.0), x); + //~^ suboptimal_flops let _ = (3.0 * y).mul_add(-(3.0 * y), x); + //~^ suboptimal_flops let _ = (y + 1.0 + x).mul_add(-(y + 1.0 + x), x); + //~^ suboptimal_flops let _ = (y + 1.0 + 2.0).mul_add(-(y + 1.0 + 2.0), x); + //~^ suboptimal_flops // Cases where the lint shouldn't be applied let _ = x.powi(2); diff --git a/tests/ui/floating_point_powi.rs b/tests/ui/floating_point_powi.rs index f02e0e8ddb36..bb97a8eddf33 100644 --- a/tests/ui/floating_point_powi.rs +++ b/tests/ui/floating_point_powi.rs @@ -7,20 +7,34 @@ fn main() { let y = 4f32; let _ = x.powi(2) + y; + //~^ suboptimal_flops let _ = x.powi(2) - y; + //~^ suboptimal_flops let _ = x + y.powi(2); + //~^ suboptimal_flops let _ = x - y.powi(2); + //~^ suboptimal_flops let _ = x + (y as f32).powi(2); + //~^ suboptimal_flops let _ = (x.powi(2) + y).sqrt(); + //~^ suboptimal_flops let _ = (x + y.powi(2)).sqrt(); + //~^ suboptimal_flops let _ = (x - 1.0).powi(2) - y; + //~^ suboptimal_flops let _ = (x - 1.0).powi(2) - y + 3.0; + //~^ suboptimal_flops let _ = (x - 1.0).powi(2) - (y + 3.0); + //~^ suboptimal_flops let _ = x - (y + 1.0).powi(2); + //~^ suboptimal_flops let _ = x - (3.0 * y).powi(2); + //~^ suboptimal_flops let _ = x - (y + 1.0 + x).powi(2); + //~^ suboptimal_flops let _ = x - (y + 1.0 + 2.0).powi(2); + //~^ suboptimal_flops // Cases where the lint shouldn't be applied let _ = x.powi(2); diff --git a/tests/ui/floating_point_powi.stderr b/tests/ui/floating_point_powi.stderr index dfed20cb8c5a..211589382911 100644 --- a/tests/ui/floating_point_powi.stderr +++ b/tests/ui/floating_point_powi.stderr @@ -8,79 +8,79 @@ LL | let _ = x.powi(2) + y; = help: to override `-D warnings` add `#[allow(clippy::suboptimal_flops)]` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_powi.rs:10:13 + --> tests/ui/floating_point_powi.rs:11:13 | LL | let _ = x.powi(2) - y; | ^^^^^^^^^^^^^ help: consider using: `x.mul_add(x, -y)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_powi.rs:11:13 + --> tests/ui/floating_point_powi.rs:13:13 | LL | let _ = x + y.powi(2); | ^^^^^^^^^^^^^ help: consider using: `y.mul_add(y, x)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_powi.rs:12:13 + --> tests/ui/floating_point_powi.rs:15:13 | LL | let _ = x - y.powi(2); | ^^^^^^^^^^^^^ help: consider using: `y.mul_add(-y, x)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_powi.rs:13:13 + --> tests/ui/floating_point_powi.rs:17:13 | LL | let _ = x + (y as f32).powi(2); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(y as f32).mul_add(y as f32, x)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_powi.rs:14:13 + --> tests/ui/floating_point_powi.rs:19:13 | LL | let _ = (x.powi(2) + y).sqrt(); | ^^^^^^^^^^^^^^^ help: consider using: `x.mul_add(x, y)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_powi.rs:15:13 + --> tests/ui/floating_point_powi.rs:21:13 | LL | let _ = (x + y.powi(2)).sqrt(); | ^^^^^^^^^^^^^^^ help: consider using: `y.mul_add(y, x)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_powi.rs:17:13 + --> tests/ui/floating_point_powi.rs:24:13 | LL | let _ = (x - 1.0).powi(2) - y; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x - 1.0).mul_add(x - 1.0, -y)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_powi.rs:18:13 + --> tests/ui/floating_point_powi.rs:26:13 | LL | let _ = (x - 1.0).powi(2) - y + 3.0; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x - 1.0).mul_add(x - 1.0, -y)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_powi.rs:19:13 + --> tests/ui/floating_point_powi.rs:28:13 | LL | let _ = (x - 1.0).powi(2) - (y + 3.0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x - 1.0).mul_add(x - 1.0, -(y + 3.0))` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_powi.rs:20:13 + --> tests/ui/floating_point_powi.rs:30:13 | LL | let _ = x - (y + 1.0).powi(2); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(y + 1.0).mul_add(-(y + 1.0), x)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_powi.rs:21:13 + --> tests/ui/floating_point_powi.rs:32:13 | LL | let _ = x - (3.0 * y).powi(2); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(3.0 * y).mul_add(-(3.0 * y), x)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_powi.rs:22:13 + --> tests/ui/floating_point_powi.rs:34:13 | LL | let _ = x - (y + 1.0 + x).powi(2); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(y + 1.0 + x).mul_add(-(y + 1.0 + x), x)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_powi.rs:23:13 + --> tests/ui/floating_point_powi.rs:36:13 | LL | let _ = x - (y + 1.0 + 2.0).powi(2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(y + 1.0 + 2.0).mul_add(-(y + 1.0 + 2.0), x)` diff --git a/tests/ui/floating_point_rad.fixed b/tests/ui/floating_point_rad.fixed index 2f93d233cb40..61f3ccc8bd02 100644 --- a/tests/ui/floating_point_rad.fixed +++ b/tests/ui/floating_point_rad.fixed @@ -8,17 +8,25 @@ pub const fn const_context() { pub fn issue9391(degrees: i64) { let _ = (degrees as f64).to_radians(); + //~^ suboptimal_flops let _ = (degrees as f64).to_degrees(); + //~^ suboptimal_flops } fn main() { let x = 3f32; let _ = x.to_degrees(); + //~^ suboptimal_flops let _ = 90.0_f64.to_degrees(); + //~^ suboptimal_flops let _ = 90.5_f64.to_degrees(); + //~^ suboptimal_flops let _ = x.to_radians(); + //~^ suboptimal_flops let _ = 90.0_f64.to_radians(); + //~^ suboptimal_flops let _ = 90.5_f64.to_radians(); + //~^ suboptimal_flops // let _ = 90.5 * 80. * std::f32::consts::PI / 180f32; // Cases where the lint shouldn't be applied let _ = x * 90f32 / std::f32::consts::PI; diff --git a/tests/ui/floating_point_rad.rs b/tests/ui/floating_point_rad.rs index 9690effc4e10..f57359e15fe1 100644 --- a/tests/ui/floating_point_rad.rs +++ b/tests/ui/floating_point_rad.rs @@ -8,17 +8,25 @@ pub const fn const_context() { pub fn issue9391(degrees: i64) { let _ = degrees as f64 * std::f64::consts::PI / 180.0; + //~^ suboptimal_flops let _ = degrees as f64 * 180.0 / std::f64::consts::PI; + //~^ suboptimal_flops } fn main() { let x = 3f32; let _ = x * 180f32 / std::f32::consts::PI; + //~^ suboptimal_flops let _ = 90. * 180f64 / std::f64::consts::PI; + //~^ suboptimal_flops let _ = 90.5 * 180f64 / std::f64::consts::PI; + //~^ suboptimal_flops let _ = x * std::f32::consts::PI / 180f32; + //~^ suboptimal_flops let _ = 90. * std::f32::consts::PI / 180f32; + //~^ suboptimal_flops let _ = 90.5 * std::f32::consts::PI / 180f32; + //~^ suboptimal_flops // let _ = 90.5 * 80. * std::f32::consts::PI / 180f32; // Cases where the lint shouldn't be applied let _ = x * 90f32 / std::f32::consts::PI; diff --git a/tests/ui/floating_point_rad.stderr b/tests/ui/floating_point_rad.stderr index b834f5374e0b..b888edd59bfd 100644 --- a/tests/ui/floating_point_rad.stderr +++ b/tests/ui/floating_point_rad.stderr @@ -8,43 +8,43 @@ LL | let _ = degrees as f64 * std::f64::consts::PI / 180.0; = help: to override `-D warnings` add `#[allow(clippy::suboptimal_flops)]` error: conversion to degrees can be done more accurately - --> tests/ui/floating_point_rad.rs:11:13 + --> tests/ui/floating_point_rad.rs:12:13 | LL | let _ = degrees as f64 * 180.0 / std::f64::consts::PI; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(degrees as f64).to_degrees()` error: conversion to degrees can be done more accurately - --> tests/ui/floating_point_rad.rs:16:13 + --> tests/ui/floating_point_rad.rs:18:13 | LL | let _ = x * 180f32 / std::f32::consts::PI; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_degrees()` error: conversion to degrees can be done more accurately - --> tests/ui/floating_point_rad.rs:17:13 + --> tests/ui/floating_point_rad.rs:20:13 | LL | let _ = 90. * 180f64 / std::f64::consts::PI; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `90.0_f64.to_degrees()` error: conversion to degrees can be done more accurately - --> tests/ui/floating_point_rad.rs:18:13 + --> tests/ui/floating_point_rad.rs:22:13 | LL | let _ = 90.5 * 180f64 / std::f64::consts::PI; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `90.5_f64.to_degrees()` error: conversion to radians can be done more accurately - --> tests/ui/floating_point_rad.rs:19:13 + --> tests/ui/floating_point_rad.rs:24:13 | LL | let _ = x * std::f32::consts::PI / 180f32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_radians()` error: conversion to radians can be done more accurately - --> tests/ui/floating_point_rad.rs:20:13 + --> tests/ui/floating_point_rad.rs:26:13 | LL | let _ = 90. * std::f32::consts::PI / 180f32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `90.0_f64.to_radians()` error: conversion to radians can be done more accurately - --> tests/ui/floating_point_rad.rs:21:13 + --> tests/ui/floating_point_rad.rs:28:13 | LL | let _ = 90.5 * std::f32::consts::PI / 180f32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `90.5_f64.to_radians()` diff --git a/tests/ui/fn_to_numeric_cast.32bit.stderr b/tests/ui/fn_to_numeric_cast.32bit.stderr index 65991a3989ac..2affd0b7d6e9 100644 --- a/tests/ui/fn_to_numeric_cast.32bit.stderr +++ b/tests/ui/fn_to_numeric_cast.32bit.stderr @@ -1,5 +1,5 @@ error: casting function pointer `foo` to `i8`, which truncates the value - --> tests/ui/fn_to_numeric_cast.rs:10:13 + --> tests/ui/fn_to_numeric_cast.rs:12:13 | LL | let _ = foo as i8; | ^^^^^^^^^ help: try: `foo as usize` @@ -8,13 +8,13 @@ LL | let _ = foo as i8; = help: to override `-D warnings` add `#[allow(clippy::fn_to_numeric_cast_with_truncation)]` error: casting function pointer `foo` to `i16`, which truncates the value - --> tests/ui/fn_to_numeric_cast.rs:11:13 + --> tests/ui/fn_to_numeric_cast.rs:14:13 | LL | let _ = foo as i16; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `i32` - --> tests/ui/fn_to_numeric_cast.rs:12:13 + --> tests/ui/fn_to_numeric_cast.rs:16:13 | LL | let _ = foo as i32; | ^^^^^^^^^^ help: try: `foo as usize` @@ -23,121 +23,121 @@ LL | let _ = foo as i32; = help: to override `-D warnings` add `#[allow(clippy::fn_to_numeric_cast)]` error: casting function pointer `foo` to `i64` - --> tests/ui/fn_to_numeric_cast.rs:13:13 + --> tests/ui/fn_to_numeric_cast.rs:19:13 | LL | let _ = foo as i64; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `i128` - --> tests/ui/fn_to_numeric_cast.rs:14:13 + --> tests/ui/fn_to_numeric_cast.rs:21:13 | LL | let _ = foo as i128; | ^^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `isize` - --> tests/ui/fn_to_numeric_cast.rs:15:13 + --> tests/ui/fn_to_numeric_cast.rs:23:13 | LL | let _ = foo as isize; | ^^^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u8`, which truncates the value - --> tests/ui/fn_to_numeric_cast.rs:17:13 + --> tests/ui/fn_to_numeric_cast.rs:26:13 | LL | let _ = foo as u8; | ^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u16`, which truncates the value - --> tests/ui/fn_to_numeric_cast.rs:18:13 + --> tests/ui/fn_to_numeric_cast.rs:28:13 | LL | let _ = foo as u16; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u32` - --> tests/ui/fn_to_numeric_cast.rs:19:13 + --> tests/ui/fn_to_numeric_cast.rs:30:13 | LL | let _ = foo as u32; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u64` - --> tests/ui/fn_to_numeric_cast.rs:20:13 + --> tests/ui/fn_to_numeric_cast.rs:33:13 | LL | let _ = foo as u64; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u128` - --> tests/ui/fn_to_numeric_cast.rs:21:13 + --> tests/ui/fn_to_numeric_cast.rs:35:13 | LL | let _ = foo as u128; | ^^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `abc` to `i8`, which truncates the value - --> tests/ui/fn_to_numeric_cast.rs:34:13 + --> tests/ui/fn_to_numeric_cast.rs:49:13 | LL | let _ = abc as i8; | ^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i16`, which truncates the value - --> tests/ui/fn_to_numeric_cast.rs:35:13 + --> tests/ui/fn_to_numeric_cast.rs:51:13 | LL | let _ = abc as i16; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i32` - --> tests/ui/fn_to_numeric_cast.rs:36:13 + --> tests/ui/fn_to_numeric_cast.rs:53:13 | LL | let _ = abc as i32; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i64` - --> tests/ui/fn_to_numeric_cast.rs:37:13 + --> tests/ui/fn_to_numeric_cast.rs:56:13 | LL | let _ = abc as i64; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i128` - --> tests/ui/fn_to_numeric_cast.rs:38:13 + --> tests/ui/fn_to_numeric_cast.rs:58:13 | LL | let _ = abc as i128; | ^^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `isize` - --> tests/ui/fn_to_numeric_cast.rs:39:13 + --> tests/ui/fn_to_numeric_cast.rs:60:13 | LL | let _ = abc as isize; | ^^^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u8`, which truncates the value - --> tests/ui/fn_to_numeric_cast.rs:41:13 + --> tests/ui/fn_to_numeric_cast.rs:63:13 | LL | let _ = abc as u8; | ^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u16`, which truncates the value - --> tests/ui/fn_to_numeric_cast.rs:42:13 + --> tests/ui/fn_to_numeric_cast.rs:65:13 | LL | let _ = abc as u16; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u32` - --> tests/ui/fn_to_numeric_cast.rs:43:13 + --> tests/ui/fn_to_numeric_cast.rs:67:13 | LL | let _ = abc as u32; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u64` - --> tests/ui/fn_to_numeric_cast.rs:44:13 + --> tests/ui/fn_to_numeric_cast.rs:70:13 | LL | let _ = abc as u64; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u128` - --> tests/ui/fn_to_numeric_cast.rs:45:13 + --> tests/ui/fn_to_numeric_cast.rs:72:13 | LL | let _ = abc as u128; | ^^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `f` to `i32` - --> tests/ui/fn_to_numeric_cast.rs:52:5 + --> tests/ui/fn_to_numeric_cast.rs:80:5 | LL | f as i32 | ^^^^^^^^ help: try: `f as usize` diff --git a/tests/ui/fn_to_numeric_cast.64bit.stderr b/tests/ui/fn_to_numeric_cast.64bit.stderr index 58f55f19a745..48961d14f2bb 100644 --- a/tests/ui/fn_to_numeric_cast.64bit.stderr +++ b/tests/ui/fn_to_numeric_cast.64bit.stderr @@ -1,5 +1,5 @@ error: casting function pointer `foo` to `i8`, which truncates the value - --> tests/ui/fn_to_numeric_cast.rs:10:13 + --> tests/ui/fn_to_numeric_cast.rs:12:13 | LL | let _ = foo as i8; | ^^^^^^^^^ help: try: `foo as usize` @@ -8,19 +8,19 @@ LL | let _ = foo as i8; = help: to override `-D warnings` add `#[allow(clippy::fn_to_numeric_cast_with_truncation)]` error: casting function pointer `foo` to `i16`, which truncates the value - --> tests/ui/fn_to_numeric_cast.rs:11:13 + --> tests/ui/fn_to_numeric_cast.rs:14:13 | LL | let _ = foo as i16; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `i32`, which truncates the value - --> tests/ui/fn_to_numeric_cast.rs:12:13 + --> tests/ui/fn_to_numeric_cast.rs:16:13 | LL | let _ = foo as i32; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `i64` - --> tests/ui/fn_to_numeric_cast.rs:13:13 + --> tests/ui/fn_to_numeric_cast.rs:19:13 | LL | let _ = foo as i64; | ^^^^^^^^^^ help: try: `foo as usize` @@ -29,115 +29,115 @@ LL | let _ = foo as i64; = help: to override `-D warnings` add `#[allow(clippy::fn_to_numeric_cast)]` error: casting function pointer `foo` to `i128` - --> tests/ui/fn_to_numeric_cast.rs:14:13 + --> tests/ui/fn_to_numeric_cast.rs:21:13 | LL | let _ = foo as i128; | ^^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `isize` - --> tests/ui/fn_to_numeric_cast.rs:15:13 + --> tests/ui/fn_to_numeric_cast.rs:23:13 | LL | let _ = foo as isize; | ^^^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u8`, which truncates the value - --> tests/ui/fn_to_numeric_cast.rs:17:13 + --> tests/ui/fn_to_numeric_cast.rs:26:13 | LL | let _ = foo as u8; | ^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u16`, which truncates the value - --> tests/ui/fn_to_numeric_cast.rs:18:13 + --> tests/ui/fn_to_numeric_cast.rs:28:13 | LL | let _ = foo as u16; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u32`, which truncates the value - --> tests/ui/fn_to_numeric_cast.rs:19:13 + --> tests/ui/fn_to_numeric_cast.rs:30:13 | LL | let _ = foo as u32; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u64` - --> tests/ui/fn_to_numeric_cast.rs:20:13 + --> tests/ui/fn_to_numeric_cast.rs:33:13 | LL | let _ = foo as u64; | ^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `foo` to `u128` - --> tests/ui/fn_to_numeric_cast.rs:21:13 + --> tests/ui/fn_to_numeric_cast.rs:35:13 | LL | let _ = foo as u128; | ^^^^^^^^^^^ help: try: `foo as usize` error: casting function pointer `abc` to `i8`, which truncates the value - --> tests/ui/fn_to_numeric_cast.rs:34:13 + --> tests/ui/fn_to_numeric_cast.rs:49:13 | LL | let _ = abc as i8; | ^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i16`, which truncates the value - --> tests/ui/fn_to_numeric_cast.rs:35:13 + --> tests/ui/fn_to_numeric_cast.rs:51:13 | LL | let _ = abc as i16; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i32`, which truncates the value - --> tests/ui/fn_to_numeric_cast.rs:36:13 + --> tests/ui/fn_to_numeric_cast.rs:53:13 | LL | let _ = abc as i32; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i64` - --> tests/ui/fn_to_numeric_cast.rs:37:13 + --> tests/ui/fn_to_numeric_cast.rs:56:13 | LL | let _ = abc as i64; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `i128` - --> tests/ui/fn_to_numeric_cast.rs:38:13 + --> tests/ui/fn_to_numeric_cast.rs:58:13 | LL | let _ = abc as i128; | ^^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `isize` - --> tests/ui/fn_to_numeric_cast.rs:39:13 + --> tests/ui/fn_to_numeric_cast.rs:60:13 | LL | let _ = abc as isize; | ^^^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u8`, which truncates the value - --> tests/ui/fn_to_numeric_cast.rs:41:13 + --> tests/ui/fn_to_numeric_cast.rs:63:13 | LL | let _ = abc as u8; | ^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u16`, which truncates the value - --> tests/ui/fn_to_numeric_cast.rs:42:13 + --> tests/ui/fn_to_numeric_cast.rs:65:13 | LL | let _ = abc as u16; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u32`, which truncates the value - --> tests/ui/fn_to_numeric_cast.rs:43:13 + --> tests/ui/fn_to_numeric_cast.rs:67:13 | LL | let _ = abc as u32; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u64` - --> tests/ui/fn_to_numeric_cast.rs:44:13 + --> tests/ui/fn_to_numeric_cast.rs:70:13 | LL | let _ = abc as u64; | ^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `abc` to `u128` - --> tests/ui/fn_to_numeric_cast.rs:45:13 + --> tests/ui/fn_to_numeric_cast.rs:72:13 | LL | let _ = abc as u128; | ^^^^^^^^^^^ help: try: `abc as usize` error: casting function pointer `f` to `i32`, which truncates the value - --> tests/ui/fn_to_numeric_cast.rs:52:5 + --> tests/ui/fn_to_numeric_cast.rs:80:5 | LL | f as i32 | ^^^^^^^^ help: try: `f as usize` diff --git a/tests/ui/fn_to_numeric_cast.rs b/tests/ui/fn_to_numeric_cast.rs index 9501eb5da4b2..f53cbacdb377 100644 --- a/tests/ui/fn_to_numeric_cast.rs +++ b/tests/ui/fn_to_numeric_cast.rs @@ -1,4 +1,6 @@ -//@stderr-per-bitwidth +//@revisions: 32bit 64bit +//@[32bit]ignore-bitwidth: 64 +//@[64bit]ignore-bitwidth: 32 //@no-rustfix #![warn(clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation)] @@ -8,17 +10,30 @@ fn foo() -> String { fn test_function_to_numeric_cast() { let _ = foo as i8; + //~^ fn_to_numeric_cast_with_truncation let _ = foo as i16; + //~^ fn_to_numeric_cast_with_truncation let _ = foo as i32; + //~[64bit]^ fn_to_numeric_cast_with_truncation + //~[32bit]^^ fn_to_numeric_cast let _ = foo as i64; + //~^ fn_to_numeric_cast let _ = foo as i128; + //~^ fn_to_numeric_cast let _ = foo as isize; + //~^ fn_to_numeric_cast let _ = foo as u8; + //~^ fn_to_numeric_cast_with_truncation let _ = foo as u16; + //~^ fn_to_numeric_cast_with_truncation let _ = foo as u32; + //~[64bit]^ fn_to_numeric_cast_with_truncation + //~[32bit]^^ fn_to_numeric_cast let _ = foo as u64; + //~^ fn_to_numeric_cast let _ = foo as u128; + //~^ fn_to_numeric_cast // Casting to usize is OK and should not warn let _ = foo as usize; @@ -32,17 +47,30 @@ fn test_function_var_to_numeric_cast() { let abc: fn() -> String = foo; let _ = abc as i8; + //~^ fn_to_numeric_cast_with_truncation let _ = abc as i16; + //~^ fn_to_numeric_cast_with_truncation let _ = abc as i32; + //~[64bit]^ fn_to_numeric_cast_with_truncation + //~[32bit]^^ fn_to_numeric_cast let _ = abc as i64; + //~^ fn_to_numeric_cast let _ = abc as i128; + //~^ fn_to_numeric_cast let _ = abc as isize; + //~^ fn_to_numeric_cast let _ = abc as u8; + //~^ fn_to_numeric_cast_with_truncation let _ = abc as u16; + //~^ fn_to_numeric_cast_with_truncation let _ = abc as u32; + //~[64bit]^ fn_to_numeric_cast_with_truncation + //~[32bit]^^ fn_to_numeric_cast let _ = abc as u64; + //~^ fn_to_numeric_cast let _ = abc as u128; + //~^ fn_to_numeric_cast // Casting to usize is OK and should not warn let _ = abc as usize; @@ -50,6 +78,8 @@ fn test_function_var_to_numeric_cast() { fn fn_with_fn_args(f: fn(i32) -> i32) -> i32 { f as i32 + //~[64bit]^ fn_to_numeric_cast_with_truncation + //~[32bit]^^ fn_to_numeric_cast } fn main() {} diff --git a/tests/ui/fn_to_numeric_cast_any.rs b/tests/ui/fn_to_numeric_cast_any.rs index 95abc0ac68dd..42f2128cd378 100644 --- a/tests/ui/fn_to_numeric_cast_any.rs +++ b/tests/ui/fn_to_numeric_cast_any.rs @@ -21,58 +21,67 @@ impl Trait for Struct {} fn fn_pointer_to_integer() { let _ = foo as i8; - //~^ ERROR: casting function pointer `foo` to `i8` - //~| NOTE: `-D clippy::fn-to-numeric-cast-any` implied by `-D warnings` + //~^ fn_to_numeric_cast_any + let _ = foo as i16; - //~^ ERROR: casting function pointer `foo` to `i16` + //~^ fn_to_numeric_cast_any + let _ = foo as i32; - //~^ ERROR: casting function pointer `foo` to `i32` + //~^ fn_to_numeric_cast_any + let _ = foo as i64; - //~^ ERROR: casting function pointer `foo` to `i64` + //~^ fn_to_numeric_cast_any + let _ = foo as i128; - //~^ ERROR: casting function pointer `foo` to `i128` + //~^ fn_to_numeric_cast_any + let _ = foo as isize; - //~^ ERROR: casting function pointer `foo` to `isize` + //~^ fn_to_numeric_cast_any let _ = foo as u8; - //~^ ERROR: casting function pointer `foo` to `u8` + //~^ fn_to_numeric_cast_any + let _ = foo as u16; - //~^ ERROR: casting function pointer `foo` to `u16` + //~^ fn_to_numeric_cast_any + let _ = foo as u32; - //~^ ERROR: casting function pointer `foo` to `u32` + //~^ fn_to_numeric_cast_any + let _ = foo as u64; - //~^ ERROR: casting function pointer `foo` to `u64` + //~^ fn_to_numeric_cast_any + let _ = foo as u128; - //~^ ERROR: casting function pointer `foo` to `u128` + //~^ fn_to_numeric_cast_any + let _ = foo as usize; - //~^ ERROR: casting function pointer `foo` to `usize` + //~^ fn_to_numeric_cast_any } fn static_method_to_integer() { let _ = Struct::static_method as usize; - //~^ ERROR: casting function pointer `Struct::static_method` to `usize` + //~^ fn_to_numeric_cast_any } fn fn_with_fn_arg(f: fn(i32) -> u32) -> usize { f as usize - //~^ ERROR: casting function pointer `f` to `usize` + //~^ fn_to_numeric_cast_any } fn fn_with_generic_static_trait_method() -> usize { T::static_method as usize - //~^ ERROR: casting function pointer `T::static_method` to `usize` + //~^ fn_to_numeric_cast_any } fn closure_to_fn_to_integer() { let clos = |x| x * 2_u32; let _ = (clos as fn(u32) -> u32) as usize; - //~^ ERROR: casting function pointer `(clos as fn(u32) -> u32)` to `usize` + //~^ fn_to_numeric_cast_any } fn fn_to_raw_ptr() { let _ = foo as *const (); - //~^ ERROR: casting function pointer `foo` to `*const ()` + //~^ fn_to_numeric_cast_any } fn cast_fn_to_self() { diff --git a/tests/ui/fn_to_numeric_cast_any.stderr b/tests/ui/fn_to_numeric_cast_any.stderr index 0238e3a91369..58fac2d406a0 100644 --- a/tests/ui/fn_to_numeric_cast_any.stderr +++ b/tests/ui/fn_to_numeric_cast_any.stderr @@ -23,7 +23,7 @@ LL | let _ = foo() as i16; | ++ error: casting function pointer `foo` to `i32` - --> tests/ui/fn_to_numeric_cast_any.rs:28:13 + --> tests/ui/fn_to_numeric_cast_any.rs:29:13 | LL | let _ = foo as i32; | ^^^^^^^^^^ @@ -34,7 +34,7 @@ LL | let _ = foo() as i32; | ++ error: casting function pointer `foo` to `i64` - --> tests/ui/fn_to_numeric_cast_any.rs:30:13 + --> tests/ui/fn_to_numeric_cast_any.rs:32:13 | LL | let _ = foo as i64; | ^^^^^^^^^^ @@ -45,7 +45,7 @@ LL | let _ = foo() as i64; | ++ error: casting function pointer `foo` to `i128` - --> tests/ui/fn_to_numeric_cast_any.rs:32:13 + --> tests/ui/fn_to_numeric_cast_any.rs:35:13 | LL | let _ = foo as i128; | ^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | let _ = foo() as i128; | ++ error: casting function pointer `foo` to `isize` - --> tests/ui/fn_to_numeric_cast_any.rs:34:13 + --> tests/ui/fn_to_numeric_cast_any.rs:38:13 | LL | let _ = foo as isize; | ^^^^^^^^^^^^ @@ -67,7 +67,7 @@ LL | let _ = foo() as isize; | ++ error: casting function pointer `foo` to `u8` - --> tests/ui/fn_to_numeric_cast_any.rs:37:13 + --> tests/ui/fn_to_numeric_cast_any.rs:41:13 | LL | let _ = foo as u8; | ^^^^^^^^^ @@ -78,7 +78,7 @@ LL | let _ = foo() as u8; | ++ error: casting function pointer `foo` to `u16` - --> tests/ui/fn_to_numeric_cast_any.rs:39:13 + --> tests/ui/fn_to_numeric_cast_any.rs:44:13 | LL | let _ = foo as u16; | ^^^^^^^^^^ @@ -89,7 +89,7 @@ LL | let _ = foo() as u16; | ++ error: casting function pointer `foo` to `u32` - --> tests/ui/fn_to_numeric_cast_any.rs:41:13 + --> tests/ui/fn_to_numeric_cast_any.rs:47:13 | LL | let _ = foo as u32; | ^^^^^^^^^^ @@ -100,7 +100,7 @@ LL | let _ = foo() as u32; | ++ error: casting function pointer `foo` to `u64` - --> tests/ui/fn_to_numeric_cast_any.rs:43:13 + --> tests/ui/fn_to_numeric_cast_any.rs:50:13 | LL | let _ = foo as u64; | ^^^^^^^^^^ @@ -111,7 +111,7 @@ LL | let _ = foo() as u64; | ++ error: casting function pointer `foo` to `u128` - --> tests/ui/fn_to_numeric_cast_any.rs:45:13 + --> tests/ui/fn_to_numeric_cast_any.rs:53:13 | LL | let _ = foo as u128; | ^^^^^^^^^^^ @@ -122,7 +122,7 @@ LL | let _ = foo() as u128; | ++ error: casting function pointer `foo` to `usize` - --> tests/ui/fn_to_numeric_cast_any.rs:47:13 + --> tests/ui/fn_to_numeric_cast_any.rs:56:13 | LL | let _ = foo as usize; | ^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL | let _ = foo() as usize; | ++ error: casting function pointer `Struct::static_method` to `usize` - --> tests/ui/fn_to_numeric_cast_any.rs:52:13 + --> tests/ui/fn_to_numeric_cast_any.rs:61:13 | LL | let _ = Struct::static_method as usize; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -144,7 +144,7 @@ LL | let _ = Struct::static_method() as usize; | ++ error: casting function pointer `f` to `usize` - --> tests/ui/fn_to_numeric_cast_any.rs:57:5 + --> tests/ui/fn_to_numeric_cast_any.rs:66:5 | LL | f as usize | ^^^^^^^^^^ @@ -155,7 +155,7 @@ LL | f() as usize | ++ error: casting function pointer `T::static_method` to `usize` - --> tests/ui/fn_to_numeric_cast_any.rs:62:5 + --> tests/ui/fn_to_numeric_cast_any.rs:71:5 | LL | T::static_method as usize | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -166,7 +166,7 @@ LL | T::static_method() as usize | ++ error: casting function pointer `(clos as fn(u32) -> u32)` to `usize` - --> tests/ui/fn_to_numeric_cast_any.rs:69:13 + --> tests/ui/fn_to_numeric_cast_any.rs:78:13 | LL | let _ = (clos as fn(u32) -> u32) as usize; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -177,7 +177,7 @@ LL | let _ = (clos as fn(u32) -> u32)() as usize; | ++ error: casting function pointer `foo` to `*const ()` - --> tests/ui/fn_to_numeric_cast_any.rs:74:13 + --> tests/ui/fn_to_numeric_cast_any.rs:83:13 | LL | let _ = foo as *const (); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/for_kv_map.fixed b/tests/ui/for_kv_map.fixed index 1733b29128fe..2a68b7443fbf 100644 --- a/tests/ui/for_kv_map.fixed +++ b/tests/ui/for_kv_map.fixed @@ -7,14 +7,15 @@ use std::rc::Rc; fn main() { let m: HashMap = HashMap::new(); for v in m.values() { - //~^ ERROR: you seem to want to iterate on a map's values - //~| NOTE: `-D clippy::for-kv-map` implied by `-D warnings` + //~^ for_kv_map + let _v = v; } let m: Rc> = Rc::new(HashMap::new()); for v in (*m).values() { - //~^ ERROR: you seem to want to iterate on a map's values + //~^ for_kv_map + let _v = v; // Here the `*` is not actually necessary, but the test tests that we don't // suggest @@ -23,27 +24,31 @@ fn main() { let mut m: HashMap = HashMap::new(); for v in m.values_mut() { - //~^ ERROR: you seem to want to iterate on a map's values + //~^ for_kv_map + let _v = v; } let m: &mut HashMap = &mut HashMap::new(); for v in (*m).values_mut() { - //~^ ERROR: you seem to want to iterate on a map's values + //~^ for_kv_map + let _v = v; } let m: HashMap = HashMap::new(); let rm = &m; for k in rm.keys() { - //~^ ERROR: you seem to want to iterate on a map's keys + //~^ for_kv_map + let _k = k; } let m: HashMap = HashMap::new(); let rm = &m; 'label: for k in rm.keys() { - //~^ ERROR: you seem to want to iterate on a map's keys + //~^ for_kv_map + let _k = k; if *k == 0u64 { break 'label; diff --git a/tests/ui/for_kv_map.rs b/tests/ui/for_kv_map.rs index de465a7c8e6e..485a97815e3c 100644 --- a/tests/ui/for_kv_map.rs +++ b/tests/ui/for_kv_map.rs @@ -7,14 +7,15 @@ use std::rc::Rc; fn main() { let m: HashMap = HashMap::new(); for (_, v) in &m { - //~^ ERROR: you seem to want to iterate on a map's values - //~| NOTE: `-D clippy::for-kv-map` implied by `-D warnings` + //~^ for_kv_map + let _v = v; } let m: Rc> = Rc::new(HashMap::new()); for (_, v) in &*m { - //~^ ERROR: you seem to want to iterate on a map's values + //~^ for_kv_map + let _v = v; // Here the `*` is not actually necessary, but the test tests that we don't // suggest @@ -23,27 +24,31 @@ fn main() { let mut m: HashMap = HashMap::new(); for (_, v) in &mut m { - //~^ ERROR: you seem to want to iterate on a map's values + //~^ for_kv_map + let _v = v; } let m: &mut HashMap = &mut HashMap::new(); for (_, v) in &mut *m { - //~^ ERROR: you seem to want to iterate on a map's values + //~^ for_kv_map + let _v = v; } let m: HashMap = HashMap::new(); let rm = &m; for (k, _value) in rm { - //~^ ERROR: you seem to want to iterate on a map's keys + //~^ for_kv_map + let _k = k; } let m: HashMap = HashMap::new(); let rm = &m; 'label: for (k, _value) in rm { - //~^ ERROR: you seem to want to iterate on a map's keys + //~^ for_kv_map + let _k = k; if *k == 0u64 { break 'label; diff --git a/tests/ui/for_kv_map.stderr b/tests/ui/for_kv_map.stderr index 11b61c8cbc64..0bd474a10682 100644 --- a/tests/ui/for_kv_map.stderr +++ b/tests/ui/for_kv_map.stderr @@ -25,7 +25,7 @@ LL + for v in (*m).values() { | error: you seem to want to iterate on a map's values - --> tests/ui/for_kv_map.rs:25:19 + --> tests/ui/for_kv_map.rs:26:19 | LL | for (_, v) in &mut m { | ^^^^^^ @@ -37,7 +37,7 @@ LL + for v in m.values_mut() { | error: you seem to want to iterate on a map's values - --> tests/ui/for_kv_map.rs:31:19 + --> tests/ui/for_kv_map.rs:33:19 | LL | for (_, v) in &mut *m { | ^^^^^^^ @@ -49,7 +49,7 @@ LL + for v in (*m).values_mut() { | error: you seem to want to iterate on a map's keys - --> tests/ui/for_kv_map.rs:38:24 + --> tests/ui/for_kv_map.rs:41:24 | LL | for (k, _value) in rm { | ^^ @@ -61,7 +61,7 @@ LL + for k in rm.keys() { | error: you seem to want to iterate on a map's keys - --> tests/ui/for_kv_map.rs:45:32 + --> tests/ui/for_kv_map.rs:49:32 | LL | 'label: for (k, _value) in rm { | ^^ diff --git a/tests/ui/forget_non_drop.rs b/tests/ui/forget_non_drop.rs index 2459f51a38da..0235709b1f1c 100644 --- a/tests/ui/forget_non_drop.rs +++ b/tests/ui/forget_non_drop.rs @@ -11,7 +11,7 @@ fn main() { struct Foo; // Lint forget(Foo); - //~^ ERROR: call to `std::mem::forget` with a value that does not implement `Drop`. Fo + //~^ forget_non_drop struct Bar; impl Drop for Bar { @@ -23,7 +23,8 @@ fn main() { struct Baz(T); // Lint forget(Baz(Foo)); - //~^ ERROR: call to `std::mem::forget` with a value that does not implement `Drop`. Fo + //~^ forget_non_drop + // Don't lint forget(Baz(Bar)); } diff --git a/tests/ui/format.fixed b/tests/ui/format.fixed index 3dc8eb79ba28..16437c62094a 100644 --- a/tests/ui/format.fixed +++ b/tests/ui/format.fixed @@ -18,14 +18,19 @@ macro_rules! foo { fn main() { "foo".to_string(); + //~^ useless_format "{}".to_string(); + //~^ useless_format "{} abc {}".to_string(); + //~^ useless_format r##"foo {} " bar"##.to_string(); let _ = String::new(); + //~^ useless_format "foo".to_string(); + //~^ useless_format format!("{:?}", "foo"); // Don't warn about `Debug`. format!("{:8}", "foo"); format!("{:width$}", "foo", width = 8); @@ -34,6 +39,7 @@ fn main() { let arg = String::new(); arg.to_string(); + //~^ useless_format format!("{:?}", arg); // Don't warn about debug. format!("{:8}", arg); format!("{:width$}", arg, width = 8); @@ -64,28 +70,36 @@ fn main() { format!("{:.prec$}", "foo", prec = 10); 42.to_string(); + //~^ useless_format let x = std::path::PathBuf::from("/bar/foo/qux"); x.display().to_string(); + //~^ useless_format // False positive let a = "foo".to_string(); let _ = Some(a + "bar"); + //~^ useless_format // Wrap it with braces let v: Vec = vec!["foo".to_string(), "bar".to_string()]; let _s: String = (&*v.join("\n")).to_string(); + //~^ useless_format format!("prepend {:+}", "s"); // Issue #8290 let x = "foo"; let _ = x.to_string(); + //~^ useless_format let _ = format!("{x:?}"); // Don't lint on debug let _ = x.to_string(); + //~^ useless_format // Issue #9234 let abc = "abc"; let _ = abc.to_string(); + //~^ useless_format let xx = "xx"; let _ = xx.to_string(); + //~^ useless_format } diff --git a/tests/ui/format.rs b/tests/ui/format.rs index eaf33c2a6c92..06371378f27e 100644 --- a/tests/ui/format.rs +++ b/tests/ui/format.rs @@ -18,16 +18,22 @@ macro_rules! foo { fn main() { format!("foo"); + //~^ useless_format format!("{{}}"); + //~^ useless_format format!("{{}} abc {{}}"); + //~^ useless_format format!( + //~^ useless_format r##"foo {{}} " bar"## ); let _ = format!(""); + //~^ useless_format format!("{}", "foo"); + //~^ useless_format format!("{:?}", "foo"); // Don't warn about `Debug`. format!("{:8}", "foo"); format!("{:width$}", "foo", width = 8); @@ -36,6 +42,7 @@ fn main() { let arg = String::new(); format!("{}", arg); + //~^ useless_format format!("{:?}", arg); // Don't warn about debug. format!("{:8}", arg); format!("{:width$}", arg, width = 8); @@ -66,28 +73,36 @@ fn main() { format!("{:.prec$}", "foo", prec = 10); format!("{}", 42.to_string()); + //~^ useless_format let x = std::path::PathBuf::from("/bar/foo/qux"); format!("{}", x.display().to_string()); + //~^ useless_format // False positive let a = "foo".to_string(); let _ = Some(format!("{}", a + "bar")); + //~^ useless_format // Wrap it with braces let v: Vec = vec!["foo".to_string(), "bar".to_string()]; let _s: String = format!("{}", &*v.join("\n")); + //~^ useless_format format!("prepend {:+}", "s"); // Issue #8290 let x = "foo"; let _ = format!("{x}"); + //~^ useless_format let _ = format!("{x:?}"); // Don't lint on debug let _ = format!("{y}", y = x); + //~^ useless_format // Issue #9234 let abc = "abc"; let _ = format!("{abc}"); + //~^ useless_format let xx = "xx"; let _ = format!("{xx}"); + //~^ useless_format } diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr index 1368c8cd77e0..da990d32cb80 100644 --- a/tests/ui/format.stderr +++ b/tests/ui/format.stderr @@ -8,21 +8,22 @@ LL | format!("foo"); = help: to override `-D warnings` add `#[allow(clippy::useless_format)]` error: useless use of `format!` - --> tests/ui/format.rs:21:5 + --> tests/ui/format.rs:22:5 | LL | format!("{{}}"); | ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"{}".to_string()` error: useless use of `format!` - --> tests/ui/format.rs:22:5 + --> tests/ui/format.rs:24:5 | LL | format!("{{}} abc {{}}"); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"{} abc {}".to_string()` error: useless use of `format!` - --> tests/ui/format.rs:23:5 + --> tests/ui/format.rs:26:5 | LL | / format!( +LL | | LL | | r##"foo {{}} LL | | " bar"## LL | | ); @@ -35,67 +36,67 @@ LL ~ " bar"##.to_string(); | error: useless use of `format!` - --> tests/ui/format.rs:28:13 + --> tests/ui/format.rs:32:13 | LL | let _ = format!(""); | ^^^^^^^^^^^ help: consider using `String::new()`: `String::new()` error: useless use of `format!` - --> tests/ui/format.rs:30:5 + --> tests/ui/format.rs:35:5 | LL | format!("{}", "foo"); | ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()` error: useless use of `format!` - --> tests/ui/format.rs:38:5 + --> tests/ui/format.rs:44:5 | LL | format!("{}", arg); | ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()` error: useless use of `format!` - --> tests/ui/format.rs:68:5 + --> tests/ui/format.rs:75:5 | LL | format!("{}", 42.to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `42.to_string()` error: useless use of `format!` - --> tests/ui/format.rs:70:5 + --> tests/ui/format.rs:78:5 | LL | format!("{}", x.display().to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.display().to_string()` error: useless use of `format!` - --> tests/ui/format.rs:74:18 + --> tests/ui/format.rs:83:18 | LL | let _ = Some(format!("{}", a + "bar")); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `a + "bar"` error: useless use of `format!` - --> tests/ui/format.rs:78:22 + --> tests/ui/format.rs:88:22 | LL | let _s: String = format!("{}", &*v.join("\n")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `(&*v.join("\n")).to_string()` error: useless use of `format!` - --> tests/ui/format.rs:84:13 + --> tests/ui/format.rs:95:13 | LL | let _ = format!("{x}"); | ^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()` error: useless use of `format!` - --> tests/ui/format.rs:86:13 + --> tests/ui/format.rs:98:13 | LL | let _ = format!("{y}", y = x); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()` error: useless use of `format!` - --> tests/ui/format.rs:90:13 + --> tests/ui/format.rs:103:13 | LL | let _ = format!("{abc}"); | ^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `abc.to_string()` error: useless use of `format!` - --> tests/ui/format.rs:92:13 + --> tests/ui/format.rs:106:13 | LL | let _ = format!("{xx}"); | ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `xx.to_string()` diff --git a/tests/ui/format_args.fixed b/tests/ui/format_args.fixed index 20d1e3d90504..edfdaa23ca12 100644 --- a/tests/ui/format_args.fixed +++ b/tests/ui/format_args.fixed @@ -75,36 +75,58 @@ fn main() { let x_ref = &x; let _ = format!("error: something failed at {}", Location::caller()); + //~^ to_string_in_format_args let _ = write!( stdout(), "error: something failed at {}", - Location::caller() + Location::caller(), + //~^ to_string_in_format_args ); let _ = writeln!( stdout(), "error: something failed at {}", - Location::caller() + Location::caller(), + //~^ to_string_in_format_args ); print!("error: something failed at {}", Location::caller()); + //~^ to_string_in_format_args println!("error: something failed at {}", Location::caller()); + //~^ to_string_in_format_args eprint!("error: something failed at {}", Location::caller()); + //~^ to_string_in_format_args eprintln!("error: something failed at {}", Location::caller()); + //~^ to_string_in_format_args let _ = format_args!("error: something failed at {}", Location::caller()); + //~^ to_string_in_format_args assert!(true, "error: something failed at {}", Location::caller()); + //~^ to_string_in_format_args assert_eq!(0, 0, "error: something failed at {}", Location::caller()); + //~^ to_string_in_format_args assert_ne!(0, 0, "error: something failed at {}", Location::caller()); + //~^ to_string_in_format_args panic!("error: something failed at {}", Location::caller()); + //~^ to_string_in_format_args println!("{}", *X(1)); + //~^ to_string_in_format_args println!("{}", ***Y(&X(1))); + //~^ to_string_in_format_args println!("{}", Z(1)); + //~^ to_string_in_format_args println!("{}", **x); + //~^ to_string_in_format_args println!("{}", ***x_ref); + //~^ to_string_in_format_args // https://github.com/rust-lang/rust-clippy/issues/7903 println!("{foo}{bar}", foo = "foo", bar = "bar"); + //~^ to_string_in_format_args println!("{foo}{bar}", foo = "foo", bar = "bar"); + //~^ to_string_in_format_args println!("{foo}{bar}", bar = "bar", foo = "foo"); + //~^ to_string_in_format_args println!("{foo}{bar}", bar = "bar", foo = "foo"); + //~^ to_string_in_format_args println!("{}", my_other_macro!()); + //~^ to_string_in_format_args // negative tests println!("error: something failed at {}", Somewhere.to_string()); @@ -117,7 +139,9 @@ fn main() { // https://github.com/rust-lang/rust-clippy/issues/7903 println!("{foo}{foo:?}", foo = "foo".to_string()); print!("{}", (Location::caller())); + //~^ to_string_in_format_args print!("{}", ((Location::caller()))); + //~^ to_string_in_format_args } fn issue8643(vendor_id: usize, product_id: usize, name: &str) { @@ -146,6 +170,7 @@ mod issue_8855 { let b = A {}; let x = format!("{} {}", a, b); + //~^ to_string_in_format_args dbg!(x); let x = format!("{:>6} {:>6}", a, b.to_string()); @@ -160,6 +185,7 @@ mod issue_9256 { fn print_substring(original: &str) { assert!(original.len() > 10); println!("{}", &original[..10]); + //~^ to_string_in_format_args } fn main() { diff --git a/tests/ui/format_args.rs b/tests/ui/format_args.rs index 18ab223db78a..367560d577dd 100644 --- a/tests/ui/format_args.rs +++ b/tests/ui/format_args.rs @@ -75,36 +75,58 @@ fn main() { let x_ref = &x; let _ = format!("error: something failed at {}", Location::caller().to_string()); + //~^ to_string_in_format_args let _ = write!( stdout(), "error: something failed at {}", - Location::caller().to_string() + Location::caller().to_string(), + //~^ to_string_in_format_args ); let _ = writeln!( stdout(), "error: something failed at {}", - Location::caller().to_string() + Location::caller().to_string(), + //~^ to_string_in_format_args ); print!("error: something failed at {}", Location::caller().to_string()); + //~^ to_string_in_format_args println!("error: something failed at {}", Location::caller().to_string()); + //~^ to_string_in_format_args eprint!("error: something failed at {}", Location::caller().to_string()); + //~^ to_string_in_format_args eprintln!("error: something failed at {}", Location::caller().to_string()); + //~^ to_string_in_format_args let _ = format_args!("error: something failed at {}", Location::caller().to_string()); + //~^ to_string_in_format_args assert!(true, "error: something failed at {}", Location::caller().to_string()); + //~^ to_string_in_format_args assert_eq!(0, 0, "error: something failed at {}", Location::caller().to_string()); + //~^ to_string_in_format_args assert_ne!(0, 0, "error: something failed at {}", Location::caller().to_string()); + //~^ to_string_in_format_args panic!("error: something failed at {}", Location::caller().to_string()); + //~^ to_string_in_format_args println!("{}", X(1).to_string()); + //~^ to_string_in_format_args println!("{}", Y(&X(1)).to_string()); + //~^ to_string_in_format_args println!("{}", Z(1).to_string()); + //~^ to_string_in_format_args println!("{}", x.to_string()); + //~^ to_string_in_format_args println!("{}", x_ref.to_string()); + //~^ to_string_in_format_args // https://github.com/rust-lang/rust-clippy/issues/7903 println!("{foo}{bar}", foo = "foo".to_string(), bar = "bar"); + //~^ to_string_in_format_args println!("{foo}{bar}", foo = "foo", bar = "bar".to_string()); + //~^ to_string_in_format_args println!("{foo}{bar}", bar = "bar".to_string(), foo = "foo"); + //~^ to_string_in_format_args println!("{foo}{bar}", bar = "bar", foo = "foo".to_string()); + //~^ to_string_in_format_args println!("{}", my_other_macro!().to_string()); + //~^ to_string_in_format_args // negative tests println!("error: something failed at {}", Somewhere.to_string()); @@ -117,7 +139,9 @@ fn main() { // https://github.com/rust-lang/rust-clippy/issues/7903 println!("{foo}{foo:?}", foo = "foo".to_string()); print!("{}", (Location::caller().to_string())); + //~^ to_string_in_format_args print!("{}", ((Location::caller()).to_string())); + //~^ to_string_in_format_args } fn issue8643(vendor_id: usize, product_id: usize, name: &str) { @@ -146,6 +170,7 @@ mod issue_8855 { let b = A {}; let x = format!("{} {}", a, b.to_string()); + //~^ to_string_in_format_args dbg!(x); let x = format!("{:>6} {:>6}", a, b.to_string()); @@ -160,6 +185,7 @@ mod issue_9256 { fn print_substring(original: &str) { assert!(original.len() > 10); println!("{}", original[..10].to_string()); + //~^ to_string_in_format_args } fn main() { diff --git a/tests/ui/format_args.stderr b/tests/ui/format_args.stderr index 91a45e270081..589c341ce859 100644 --- a/tests/ui/format_args.stderr +++ b/tests/ui/format_args.stderr @@ -8,151 +8,151 @@ LL | let _ = format!("error: something failed at {}", Location::caller().to_ = help: to override `-D warnings` add `#[allow(clippy::to_string_in_format_args)]` error: `to_string` applied to a type that implements `Display` in `write!` args - --> tests/ui/format_args.rs:81:27 + --> tests/ui/format_args.rs:82:27 | -LL | Location::caller().to_string() +LL | Location::caller().to_string(), | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `writeln!` args - --> tests/ui/format_args.rs:86:27 + --> tests/ui/format_args.rs:88:27 | -LL | Location::caller().to_string() +LL | Location::caller().to_string(), | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `print!` args - --> tests/ui/format_args.rs:88:63 + --> tests/ui/format_args.rs:91:63 | LL | print!("error: something failed at {}", Location::caller().to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `println!` args - --> tests/ui/format_args.rs:89:65 + --> tests/ui/format_args.rs:93:65 | LL | println!("error: something failed at {}", Location::caller().to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `eprint!` args - --> tests/ui/format_args.rs:90:64 + --> tests/ui/format_args.rs:95:64 | LL | eprint!("error: something failed at {}", Location::caller().to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `eprintln!` args - --> tests/ui/format_args.rs:91:66 + --> tests/ui/format_args.rs:97:66 | LL | eprintln!("error: something failed at {}", Location::caller().to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `format_args!` args - --> tests/ui/format_args.rs:92:77 + --> tests/ui/format_args.rs:99:77 | LL | let _ = format_args!("error: something failed at {}", Location::caller().to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `assert!` args - --> tests/ui/format_args.rs:93:70 + --> tests/ui/format_args.rs:101:70 | LL | assert!(true, "error: something failed at {}", Location::caller().to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `assert_eq!` args - --> tests/ui/format_args.rs:94:73 + --> tests/ui/format_args.rs:103:73 | LL | assert_eq!(0, 0, "error: something failed at {}", Location::caller().to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `assert_ne!` args - --> tests/ui/format_args.rs:95:73 + --> tests/ui/format_args.rs:105:73 | LL | assert_ne!(0, 0, "error: something failed at {}", Location::caller().to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `panic!` args - --> tests/ui/format_args.rs:96:63 + --> tests/ui/format_args.rs:107:63 | LL | panic!("error: something failed at {}", Location::caller().to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `println!` args - --> tests/ui/format_args.rs:97:20 + --> tests/ui/format_args.rs:109:20 | LL | println!("{}", X(1).to_string()); | ^^^^^^^^^^^^^^^^ help: use this: `*X(1)` error: `to_string` applied to a type that implements `Display` in `println!` args - --> tests/ui/format_args.rs:98:20 + --> tests/ui/format_args.rs:111:20 | LL | println!("{}", Y(&X(1)).to_string()); | ^^^^^^^^^^^^^^^^^^^^ help: use this: `***Y(&X(1))` error: `to_string` applied to a type that implements `Display` in `println!` args - --> tests/ui/format_args.rs:99:24 + --> tests/ui/format_args.rs:113:24 | LL | println!("{}", Z(1).to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `println!` args - --> tests/ui/format_args.rs:100:20 + --> tests/ui/format_args.rs:115:20 | LL | println!("{}", x.to_string()); | ^^^^^^^^^^^^^ help: use this: `**x` error: `to_string` applied to a type that implements `Display` in `println!` args - --> tests/ui/format_args.rs:101:20 + --> tests/ui/format_args.rs:117:20 | LL | println!("{}", x_ref.to_string()); | ^^^^^^^^^^^^^^^^^ help: use this: `***x_ref` error: `to_string` applied to a type that implements `Display` in `println!` args - --> tests/ui/format_args.rs:103:39 + --> tests/ui/format_args.rs:120:39 | LL | println!("{foo}{bar}", foo = "foo".to_string(), bar = "bar"); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `println!` args - --> tests/ui/format_args.rs:104:52 + --> tests/ui/format_args.rs:122:52 | LL | println!("{foo}{bar}", foo = "foo", bar = "bar".to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `println!` args - --> tests/ui/format_args.rs:105:39 + --> tests/ui/format_args.rs:124:39 | LL | println!("{foo}{bar}", bar = "bar".to_string(), foo = "foo"); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `println!` args - --> tests/ui/format_args.rs:106:52 + --> tests/ui/format_args.rs:126:52 | LL | println!("{foo}{bar}", bar = "bar", foo = "foo".to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `println!` args - --> tests/ui/format_args.rs:107:37 + --> tests/ui/format_args.rs:128:37 | LL | println!("{}", my_other_macro!().to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `print!` args - --> tests/ui/format_args.rs:119:37 + --> tests/ui/format_args.rs:141:37 | LL | print!("{}", (Location::caller().to_string())); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `print!` args - --> tests/ui/format_args.rs:120:39 + --> tests/ui/format_args.rs:143:39 | LL | print!("{}", ((Location::caller()).to_string())); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `format!` args - --> tests/ui/format_args.rs:148:38 + --> tests/ui/format_args.rs:172:38 | LL | let x = format!("{} {}", a, b.to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `println!` args - --> tests/ui/format_args.rs:162:24 + --> tests/ui/format_args.rs:187:24 | LL | println!("{}", original[..10].to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use this: `&original[..10]` diff --git a/tests/ui/format_args_unfixable.rs b/tests/ui/format_args_unfixable.rs index 7590de3751a8..9e1d6a649c35 100644 --- a/tests/ui/format_args_unfixable.rs +++ b/tests/ui/format_args_unfixable.rs @@ -2,7 +2,7 @@ #![allow(unused)] #![allow(clippy::assertions_on_constants, clippy::eq_op, clippy::uninlined_format_args)] -use std::io::{Error, ErrorKind, Write, stdout}; +use std::io::{Error, Write, stdout}; use std::ops::Deref; use std::panic::Location; @@ -20,53 +20,68 @@ macro_rules! my_other_macro { } fn main() { - let error = Error::new(ErrorKind::Other, "bad thing"); + let error = Error::other("bad thing"); let x = 'x'; println!("error: {}", format!("something failed at {}", Location::caller())); - //~^ ERROR: `format!` in `println!` args + //~^ format_in_format_args + println!("{}: {}", error, format!("something failed at {}", Location::caller())); - //~^ ERROR: `format!` in `println!` args + //~^ format_in_format_args + println!("{:?}: {}", error, format!("something failed at {}", Location::caller())); - //~^ ERROR: `format!` in `println!` args + //~^ format_in_format_args + println!("{{}}: {}", format!("something failed at {}", Location::caller())); - //~^ ERROR: `format!` in `println!` args + //~^ format_in_format_args + println!(r#"error: "{}""#, format!("something failed at {}", Location::caller())); - //~^ ERROR: `format!` in `println!` args + //~^ format_in_format_args + println!("error: {}", format!(r#"something failed at "{}""#, Location::caller())); - //~^ ERROR: `format!` in `println!` args + //~^ format_in_format_args + println!("error: {}", format!("something failed at {} {0}", Location::caller())); - //~^ ERROR: `format!` in `println!` args + //~^ format_in_format_args + let _ = format!("error: {}", format!("something failed at {}", Location::caller())); - //~^ ERROR: `format!` in `format!` args + //~^ format_in_format_args + let _ = write!( - //~^ ERROR: `format!` in `write!` args + //~^ format_in_format_args stdout(), "error: {}", format!("something failed at {}", Location::caller()) ); let _ = writeln!( - //~^ ERROR: `format!` in `writeln!` args + //~^ format_in_format_args stdout(), "error: {}", format!("something failed at {}", Location::caller()) ); print!("error: {}", format!("something failed at {}", Location::caller())); - //~^ ERROR: `format!` in `print!` args + //~^ format_in_format_args + eprint!("error: {}", format!("something failed at {}", Location::caller())); - //~^ ERROR: `format!` in `eprint!` args + //~^ format_in_format_args + eprintln!("error: {}", format!("something failed at {}", Location::caller())); - //~^ ERROR: `format!` in `eprintln!` args + //~^ format_in_format_args + let _ = format_args!("error: {}", format!("something failed at {}", Location::caller())); - //~^ ERROR: `format!` in `format_args!` args + //~^ format_in_format_args + assert!(true, "error: {}", format!("something failed at {}", Location::caller())); - //~^ ERROR: `format!` in `assert!` args + //~^ format_in_format_args + assert_eq!(0, 0, "error: {}", format!("something failed at {}", Location::caller())); - //~^ ERROR: `format!` in `assert_eq!` args + //~^ format_in_format_args + assert_ne!(0, 0, "error: {}", format!("something failed at {}", Location::caller())); - //~^ ERROR: `format!` in `assert_ne!` args + //~^ format_in_format_args + panic!("error: {}", format!("something failed at {}", Location::caller())); - //~^ ERROR: `format!` in `panic!` args + //~^ format_in_format_args // negative tests println!("error: {}", format_args!("something failed at {}", Location::caller())); @@ -100,7 +115,7 @@ macro_rules! my_println2_args { } fn test2() { - let error = Error::new(ErrorKind::Other, "bad thing"); + let error = Error::other("bad thing"); // None of these should be linted without the config change my_println2!(true, "error: {}", format!("something failed at {}", Location::caller())); @@ -130,21 +145,27 @@ macro_rules! usr_println { } fn user_format() { - let error = Error::new(ErrorKind::Other, "bad thing"); + let error = Error::other("bad thing"); let x = 'x'; usr_println!(true, "error: {}", format!("boom at {}", Location::caller())); - //~^ ERROR: `format!` in `usr_println!` args + //~^ format_in_format_args + usr_println!(true, "{}: {}", error, format!("boom at {}", Location::caller())); - //~^ ERROR: `format!` in `usr_println!` args + //~^ format_in_format_args + usr_println!(true, "{:?}: {}", error, format!("boom at {}", Location::caller())); - //~^ ERROR: `format!` in `usr_println!` args + //~^ format_in_format_args + usr_println!(true, "{{}}: {}", format!("boom at {}", Location::caller())); - //~^ ERROR: `format!` in `usr_println!` args + //~^ format_in_format_args + usr_println!(true, r#"error: "{}""#, format!("boom at {}", Location::caller())); - //~^ ERROR: `format!` in `usr_println!` args + //~^ format_in_format_args + usr_println!(true, "error: {}", format!(r#"boom at "{}""#, Location::caller())); - //~^ ERROR: `format!` in `usr_println!` args + //~^ format_in_format_args + usr_println!(true, "error: {}", format!("boom at {} {0}", Location::caller())); - //~^ ERROR: `format!` in `usr_println!` args + //~^ format_in_format_args } diff --git a/tests/ui/format_args_unfixable.stderr b/tests/ui/format_args_unfixable.stderr index 1b4b683fd6c6..1271e80b60a7 100644 --- a/tests/ui/format_args_unfixable.stderr +++ b/tests/ui/format_args_unfixable.stderr @@ -10,7 +10,7 @@ LL | println!("error: {}", format!("something failed at {}", Location::calle = help: to override `-D warnings` add `#[allow(clippy::format_in_format_args)]` error: `format!` in `println!` args - --> tests/ui/format_args_unfixable.rs:28:5 + --> tests/ui/format_args_unfixable.rs:29:5 | LL | println!("{}: {}", error, format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | println!("{}: {}", error, format!("something failed at {}", Location::c = help: or consider changing `format!` to `format_args!` error: `format!` in `println!` args - --> tests/ui/format_args_unfixable.rs:30:5 + --> tests/ui/format_args_unfixable.rs:32:5 | LL | println!("{:?}: {}", error, format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | println!("{:?}: {}", error, format!("something failed at {}", Location: = help: or consider changing `format!` to `format_args!` error: `format!` in `println!` args - --> tests/ui/format_args_unfixable.rs:32:5 + --> tests/ui/format_args_unfixable.rs:35:5 | LL | println!("{{}}: {}", format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL | println!("{{}}: {}", format!("something failed at {}", Location::caller = help: or consider changing `format!` to `format_args!` error: `format!` in `println!` args - --> tests/ui/format_args_unfixable.rs:34:5 + --> tests/ui/format_args_unfixable.rs:38:5 | LL | println!(r#"error: "{}""#, format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -46,7 +46,7 @@ LL | println!(r#"error: "{}""#, format!("something failed at {}", Location:: = help: or consider changing `format!` to `format_args!` error: `format!` in `println!` args - --> tests/ui/format_args_unfixable.rs:36:5 + --> tests/ui/format_args_unfixable.rs:41:5 | LL | println!("error: {}", format!(r#"something failed at "{}""#, Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | println!("error: {}", format!(r#"something failed at "{}""#, Location:: = help: or consider changing `format!` to `format_args!` error: `format!` in `println!` args - --> tests/ui/format_args_unfixable.rs:38:5 + --> tests/ui/format_args_unfixable.rs:44:5 | LL | println!("error: {}", format!("something failed at {} {0}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | println!("error: {}", format!("something failed at {} {0}", Location::c = help: or consider changing `format!` to `format_args!` error: `format!` in `format!` args - --> tests/ui/format_args_unfixable.rs:40:13 + --> tests/ui/format_args_unfixable.rs:47:13 | LL | let _ = format!("error: {}", format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | let _ = format!("error: {}", format!("something failed at {}", Location = help: or consider changing `format!` to `format_args!` error: `format!` in `write!` args - --> tests/ui/format_args_unfixable.rs:42:13 + --> tests/ui/format_args_unfixable.rs:50:13 | LL | let _ = write!( | _____________^ @@ -88,7 +88,7 @@ LL | | ); = help: or consider changing `format!` to `format_args!` error: `format!` in `writeln!` args - --> tests/ui/format_args_unfixable.rs:48:13 + --> tests/ui/format_args_unfixable.rs:56:13 | LL | let _ = writeln!( | _____________^ @@ -103,7 +103,7 @@ LL | | ); = help: or consider changing `format!` to `format_args!` error: `format!` in `print!` args - --> tests/ui/format_args_unfixable.rs:54:5 + --> tests/ui/format_args_unfixable.rs:62:5 | LL | print!("error: {}", format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -112,7 +112,7 @@ LL | print!("error: {}", format!("something failed at {}", Location::caller( = help: or consider changing `format!` to `format_args!` error: `format!` in `eprint!` args - --> tests/ui/format_args_unfixable.rs:56:5 + --> tests/ui/format_args_unfixable.rs:65:5 | LL | eprint!("error: {}", format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL | eprint!("error: {}", format!("something failed at {}", Location::caller = help: or consider changing `format!` to `format_args!` error: `format!` in `eprintln!` args - --> tests/ui/format_args_unfixable.rs:58:5 + --> tests/ui/format_args_unfixable.rs:68:5 | LL | eprintln!("error: {}", format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -130,7 +130,7 @@ LL | eprintln!("error: {}", format!("something failed at {}", Location::call = help: or consider changing `format!` to `format_args!` error: `format!` in `format_args!` args - --> tests/ui/format_args_unfixable.rs:60:13 + --> tests/ui/format_args_unfixable.rs:71:13 | LL | let _ = format_args!("error: {}", format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -139,7 +139,7 @@ LL | let _ = format_args!("error: {}", format!("something failed at {}", Loc = help: or consider changing `format!` to `format_args!` error: `format!` in `assert!` args - --> tests/ui/format_args_unfixable.rs:62:5 + --> tests/ui/format_args_unfixable.rs:74:5 | LL | assert!(true, "error: {}", format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -148,7 +148,7 @@ LL | assert!(true, "error: {}", format!("something failed at {}", Location:: = help: or consider changing `format!` to `format_args!` error: `format!` in `assert_eq!` args - --> tests/ui/format_args_unfixable.rs:64:5 + --> tests/ui/format_args_unfixable.rs:77:5 | LL | assert_eq!(0, 0, "error: {}", format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL | assert_eq!(0, 0, "error: {}", format!("something failed at {}", Locatio = help: or consider changing `format!` to `format_args!` error: `format!` in `assert_ne!` args - --> tests/ui/format_args_unfixable.rs:66:5 + --> tests/ui/format_args_unfixable.rs:80:5 | LL | assert_ne!(0, 0, "error: {}", format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -166,7 +166,7 @@ LL | assert_ne!(0, 0, "error: {}", format!("something failed at {}", Locatio = help: or consider changing `format!` to `format_args!` error: `format!` in `panic!` args - --> tests/ui/format_args_unfixable.rs:68:5 + --> tests/ui/format_args_unfixable.rs:83:5 | LL | panic!("error: {}", format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -175,7 +175,7 @@ LL | panic!("error: {}", format!("something failed at {}", Location::caller( = help: or consider changing `format!` to `format_args!` error: `format!` in `usr_println!` args - --> tests/ui/format_args_unfixable.rs:136:5 + --> tests/ui/format_args_unfixable.rs:151:5 | LL | usr_println!(true, "error: {}", format!("boom at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -184,7 +184,7 @@ LL | usr_println!(true, "error: {}", format!("boom at {}", Location::caller( = help: or consider changing `format!` to `format_args!` error: `format!` in `usr_println!` args - --> tests/ui/format_args_unfixable.rs:138:5 + --> tests/ui/format_args_unfixable.rs:154:5 | LL | usr_println!(true, "{}: {}", error, format!("boom at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -193,7 +193,7 @@ LL | usr_println!(true, "{}: {}", error, format!("boom at {}", Location::cal = help: or consider changing `format!` to `format_args!` error: `format!` in `usr_println!` args - --> tests/ui/format_args_unfixable.rs:140:5 + --> tests/ui/format_args_unfixable.rs:157:5 | LL | usr_println!(true, "{:?}: {}", error, format!("boom at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -202,7 +202,7 @@ LL | usr_println!(true, "{:?}: {}", error, format!("boom at {}", Location::c = help: or consider changing `format!` to `format_args!` error: `format!` in `usr_println!` args - --> tests/ui/format_args_unfixable.rs:142:5 + --> tests/ui/format_args_unfixable.rs:160:5 | LL | usr_println!(true, "{{}}: {}", format!("boom at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -211,7 +211,7 @@ LL | usr_println!(true, "{{}}: {}", format!("boom at {}", Location::caller() = help: or consider changing `format!` to `format_args!` error: `format!` in `usr_println!` args - --> tests/ui/format_args_unfixable.rs:144:5 + --> tests/ui/format_args_unfixable.rs:163:5 | LL | usr_println!(true, r#"error: "{}""#, format!("boom at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -220,7 +220,7 @@ LL | usr_println!(true, r#"error: "{}""#, format!("boom at {}", Location::ca = help: or consider changing `format!` to `format_args!` error: `format!` in `usr_println!` args - --> tests/ui/format_args_unfixable.rs:146:5 + --> tests/ui/format_args_unfixable.rs:166:5 | LL | usr_println!(true, "error: {}", format!(r#"boom at "{}""#, Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -229,7 +229,7 @@ LL | usr_println!(true, "error: {}", format!(r#"boom at "{}""#, Location::ca = help: or consider changing `format!` to `format_args!` error: `format!` in `usr_println!` args - --> tests/ui/format_args_unfixable.rs:148:5 + --> tests/ui/format_args_unfixable.rs:169:5 | LL | usr_println!(true, "error: {}", format!("boom at {} {0}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/format_collect.rs b/tests/ui/format_collect.rs index 26ebdc6c0cb6..8f8633a52d86 100644 --- a/tests/ui/format_collect.rs +++ b/tests/ui/format_collect.rs @@ -3,13 +3,14 @@ fn hex_encode(bytes: &[u8]) -> String { bytes.iter().map(|b| format!("{b:02X}")).collect() - //~^ ERROR: use of `format!` to build up a string from an iterator + //~^ format_collect } #[rustfmt::skip] fn hex_encode_deep(bytes: &[u8]) -> String { bytes.iter().map(|b| {{{{{ format!("{b:02X}") }}}}}).collect() - //~^ ERROR: use of `format!` to build up a string from an iterator + //~^ format_collect + } macro_rules! fmt { @@ -24,7 +25,7 @@ fn from_macro(bytes: &[u8]) -> String { fn with_block() -> String { (1..10) - //~^ ERROR: use of `format!` to build up a string from an iterator + //~^ format_collect .map(|s| { let y = 1; format!("{s} {y}") diff --git a/tests/ui/format_collect.stderr b/tests/ui/format_collect.stderr index 863b457a7905..343e38a87b71 100644 --- a/tests/ui/format_collect.stderr +++ b/tests/ui/format_collect.stderr @@ -37,7 +37,7 @@ LL | bytes.iter().map(|b| {{{{{ format!("{b:02X}") }}}}}).collect() = note: this can be written more efficiently by appending to a `String` directly error: use of `format!` to build up a string from an iterator - --> tests/ui/format_collect.rs:26:5 + --> tests/ui/format_collect.rs:27:5 | LL | / (1..10) LL | | @@ -49,12 +49,12 @@ LL | | .collect() | |__________________^ | help: call `fold` instead - --> tests/ui/format_collect.rs:28:10 + --> tests/ui/format_collect.rs:29:10 | LL | .map(|s| { | ^^^ help: ... and use the `write!` macro here - --> tests/ui/format_collect.rs:30:13 + --> tests/ui/format_collect.rs:31:13 | LL | format!("{s} {y}") | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/format_push_string.rs b/tests/ui/format_push_string.rs index 735ae3393289..056ef59ff0e2 100644 --- a/tests/ui/format_push_string.rs +++ b/tests/ui/format_push_string.rs @@ -3,9 +3,10 @@ fn main() { let mut string = String::new(); string += &format!("{:?}", 1234); - //~^ ERROR: `format!(..)` appended to existing `String` + //~^ format_push_string + string.push_str(&format!("{:?}", 5678)); - //~^ ERROR: `format!(..)` appended to existing `String` + //~^ format_push_string } mod issue9493 { @@ -13,7 +14,8 @@ mod issue9493 { let mut hex = String::with_capacity(vector.len() * 2); for byte in vector { hex += &(if upper { - //~^ ERROR: `format!(..)` appended to existing `String` + //~^ format_push_string + format!("{byte:02X}") } else { format!("{byte:02x}") @@ -26,14 +28,15 @@ mod issue9493 { let mut s = String::new(); // if let s += &(if let Some(_a) = Some(1234) { - //~^ ERROR: `format!(..)` appended to existing `String` + //~^ format_push_string + format!("{}", 1234) } else { format!("{}", 1234) }); // match s += &(match Some(1234) { - //~^ ERROR: `format!(..)` appended to existing `String` + //~^ format_push_string Some(_) => format!("{}", 1234), None => format!("{}", 1234), }); diff --git a/tests/ui/format_push_string.stderr b/tests/ui/format_push_string.stderr index a9520600f52a..bba2a8947c43 100644 --- a/tests/ui/format_push_string.stderr +++ b/tests/ui/format_push_string.stderr @@ -9,7 +9,7 @@ LL | string += &format!("{:?}", 1234); = help: to override `-D warnings` add `#[allow(clippy::format_push_string)]` error: `format!(..)` appended to existing `String` - --> tests/ui/format_push_string.rs:7:5 + --> tests/ui/format_push_string.rs:8:5 | LL | string.push_str(&format!("{:?}", 5678)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,10 +17,11 @@ LL | string.push_str(&format!("{:?}", 5678)); = help: consider using `write!` to avoid the extra allocation error: `format!(..)` appended to existing `String` - --> tests/ui/format_push_string.rs:15:13 + --> tests/ui/format_push_string.rs:16:13 | LL | / hex += &(if upper { LL | | +LL | | LL | | format!("{byte:02X}") LL | | } else { LL | | format!("{byte:02x}") @@ -30,10 +31,11 @@ LL | | }); = help: consider using `write!` to avoid the extra allocation error: `format!(..)` appended to existing `String` - --> tests/ui/format_push_string.rs:28:9 + --> tests/ui/format_push_string.rs:30:9 | LL | / s += &(if let Some(_a) = Some(1234) { LL | | +LL | | LL | | format!("{}", 1234) LL | | } else { LL | | format!("{}", 1234) @@ -43,7 +45,7 @@ LL | | }); = help: consider using `write!` to avoid the extra allocation error: `format!(..)` appended to existing `String` - --> tests/ui/format_push_string.rs:35:9 + --> tests/ui/format_push_string.rs:38:9 | LL | / s += &(match Some(1234) { LL | | diff --git a/tests/ui/formatting.rs b/tests/ui/formatting.rs index 312fa2aa40ad..4e84dcf7d5b7 100644 --- a/tests/ui/formatting.rs +++ b/tests/ui/formatting.rs @@ -14,16 +14,19 @@ fn main() { // weird op_eq formatting: let mut a = 42; a =- 35; - //~^ ERROR: this looks like you are trying to use `.. -= ..`, but you really are doing - //~| NOTE: to remove this lint, use either `-=` or `= -` + //~^ suspicious_assignment_formatting + + a =* &191; - //~^ ERROR: this looks like you are trying to use `.. *= ..`, but you really are doing - //~| NOTE: to remove this lint, use either `*=` or `= *` + //~^ suspicious_assignment_formatting + + let mut b = true; b =! false; - //~^ ERROR: this looks like you are trying to use `.. != ..`, but you really are doing - //~| NOTE: to remove this lint, use either `!=` or `= !` + //~^ suspicious_assignment_formatting + + // those are ok: a = -35; @@ -33,14 +36,16 @@ fn main() { // possible missing comma in an array let _ = &[ -1, -2, -3 // <= no comma here - //~^ ERROR: possibly missing a comma here - //~| NOTE: to remove this lint, add a comma or write the expr in a single line + //~^ possible_missing_comma + + -4, -5, -6 ]; let _ = &[ -1, -2, -3 // <= no comma here - //~^ ERROR: possibly missing a comma here - //~| NOTE: to remove this lint, add a comma or write the expr in a single line + //~^ possible_missing_comma + + *4, -5, -6 ]; @@ -78,8 +83,9 @@ fn main() { // lint if it doesn't let _ = &[ -1 - //~^ ERROR: possibly missing a comma here - //~| NOTE: to remove this lint, add a comma or write the expr in a single line + //~^ possible_missing_comma + + -4, ]; } diff --git a/tests/ui/formatting.stderr b/tests/ui/formatting.stderr index e823e6512b8d..972bd3a6a2e6 100644 --- a/tests/ui/formatting.stderr +++ b/tests/ui/formatting.stderr @@ -9,7 +9,7 @@ LL | a =- 35; = help: to override `-D warnings` add `#[allow(clippy::suspicious_assignment_formatting)]` error: this looks like you are trying to use `.. *= ..`, but you really are doing `.. = (* ..)` - --> tests/ui/formatting.rs:19:6 + --> tests/ui/formatting.rs:20:6 | LL | a =* &191; | ^^^^ @@ -17,7 +17,7 @@ LL | a =* &191; = note: to remove this lint, use either `*=` or `= *` error: this looks like you are trying to use `.. != ..`, but you really are doing `.. = (! ..)` - --> tests/ui/formatting.rs:24:6 + --> tests/ui/formatting.rs:26:6 | LL | b =! false; | ^^^^ @@ -25,7 +25,7 @@ LL | b =! false; = note: to remove this lint, use either `!=` or `= !` error: possibly missing a comma here - --> tests/ui/formatting.rs:35:19 + --> tests/ui/formatting.rs:38:19 | LL | -1, -2, -3 // <= no comma here | ^ @@ -35,7 +35,7 @@ LL | -1, -2, -3 // <= no comma here = help: to override `-D warnings` add `#[allow(clippy::possible_missing_comma)]` error: possibly missing a comma here - --> tests/ui/formatting.rs:41:19 + --> tests/ui/formatting.rs:45:19 | LL | -1, -2, -3 // <= no comma here | ^ @@ -43,7 +43,7 @@ LL | -1, -2, -3 // <= no comma here = note: to remove this lint, add a comma or write the expr in a single line error: possibly missing a comma here - --> tests/ui/formatting.rs:80:11 + --> tests/ui/formatting.rs:85:11 | LL | -1 | ^ diff --git a/tests/ui/four_forward_slashes.fixed b/tests/ui/four_forward_slashes.fixed index 6d31c543d727..6f387b67ccbf 100644 --- a/tests/ui/four_forward_slashes.fixed +++ b/tests/ui/four_forward_slashes.fixed @@ -1,4 +1,3 @@ - //@aux-build:proc_macros.rs #![feature(custom_inner_attributes)] #![allow(unused)] @@ -10,14 +9,17 @@ extern crate proc_macros; /// whoops +//~^ four_forward_slashes fn a() {} /// whoops +//~^ four_forward_slashes #[allow(dead_code)] fn b() {} /// whoops /// two borked comments! +//~^^ four_forward_slashes #[track_caller] fn c() {} @@ -25,10 +27,12 @@ fn d() {} #[test] /// between attributes +//~^ four_forward_slashes #[allow(dead_code)] fn g() {} /// not very start of contents + //~^ four_forward_slashes fn h() {} fn i() { diff --git a/tests/ui/four_forward_slashes.rs b/tests/ui/four_forward_slashes.rs index 458b8de53e15..fae07e7d6094 100644 --- a/tests/ui/four_forward_slashes.rs +++ b/tests/ui/four_forward_slashes.rs @@ -1,4 +1,3 @@ - //@aux-build:proc_macros.rs #![feature(custom_inner_attributes)] #![allow(unused)] @@ -10,14 +9,17 @@ extern crate proc_macros; //// whoops +//~^ four_forward_slashes fn a() {} //// whoops +//~^ four_forward_slashes #[allow(dead_code)] fn b() {} //// whoops //// two borked comments! +//~^^ four_forward_slashes #[track_caller] fn c() {} @@ -25,10 +27,12 @@ fn d() {} #[test] //// between attributes +//~^ four_forward_slashes #[allow(dead_code)] fn g() {} //// not very start of contents + //~^ four_forward_slashes fn h() {} fn i() { diff --git a/tests/ui/four_forward_slashes.stderr b/tests/ui/four_forward_slashes.stderr index d5bf71fadc7d..95c860b29fba 100644 --- a/tests/ui/four_forward_slashes.stderr +++ b/tests/ui/four_forward_slashes.stderr @@ -1,7 +1,8 @@ error: this item has comments with 4 forward slashes (`////`). These look like doc comments, but they aren't - --> tests/ui/four_forward_slashes.rs:12:1 + --> tests/ui/four_forward_slashes.rs:11:1 | LL | / //// whoops +LL | | LL | | fn a() {} | |_^ | @@ -10,7 +11,7 @@ LL | | fn a() {} help: make this a doc comment by removing one `/` | LL - //// whoops -LL - fn a() {} +LL - LL + /// whoops | @@ -18,6 +19,7 @@ error: this item has comments with 4 forward slashes (`////`). These look like d --> tests/ui/four_forward_slashes.rs:15:1 | LL | / //// whoops +LL | | LL | | #[allow(dead_code)] LL | | fn b() {} | |_^ @@ -25,15 +27,16 @@ LL | | fn b() {} help: make this a doc comment by removing one `/` | LL - //// whoops -LL - #[allow(dead_code)] +LL - LL + /// whoops | error: this item has comments with 4 forward slashes (`////`). These look like doc comments, but they aren't - --> tests/ui/four_forward_slashes.rs:19:1 + --> tests/ui/four_forward_slashes.rs:20:1 | LL | / //// whoops LL | | //// two borked comments! +LL | | LL | | #[track_caller] LL | | fn c() {} | |_^ @@ -45,9 +48,10 @@ LL ~ /// two borked comments! | error: this item has comments with 4 forward slashes (`////`). These look like doc comments, but they aren't - --> tests/ui/four_forward_slashes.rs:27:1 + --> tests/ui/four_forward_slashes.rs:29:1 | LL | / //// between attributes +LL | | LL | | #[allow(dead_code)] LL | | fn g() {} | |_^ @@ -55,21 +59,22 @@ LL | | fn g() {} help: make this a doc comment by removing one `/` | LL - //// between attributes -LL - #[allow(dead_code)] +LL - LL + /// between attributes | error: this item has comments with 4 forward slashes (`////`). These look like doc comments, but they aren't - --> tests/ui/four_forward_slashes.rs:31:1 + --> tests/ui/four_forward_slashes.rs:34:1 | LL | / //// not very start of contents +LL | | LL | | fn h() {} | |_^ | help: make this a doc comment by removing one `/` | LL - //// not very start of contents -LL - fn h() {} +LL - LL + /// not very start of contents | diff --git a/tests/ui/four_forward_slashes_first_line.fixed b/tests/ui/four_forward_slashes_first_line.fixed index 5ef40015d88b..34604a6461b9 100644 --- a/tests/ui/four_forward_slashes_first_line.fixed +++ b/tests/ui/four_forward_slashes_first_line.fixed @@ -1,4 +1,5 @@ /// borked doc comment on the first line. doesn't combust! +//~^ four_forward_slashes fn a() {} // This test's entire purpose is to make sure we don't panic if the comment with four slashes diff --git a/tests/ui/four_forward_slashes_first_line.rs b/tests/ui/four_forward_slashes_first_line.rs index 9c835e745f65..150e9ba2711c 100644 --- a/tests/ui/four_forward_slashes_first_line.rs +++ b/tests/ui/four_forward_slashes_first_line.rs @@ -1,4 +1,5 @@ //// borked doc comment on the first line. doesn't combust! +//~^ four_forward_slashes fn a() {} // This test's entire purpose is to make sure we don't panic if the comment with four slashes diff --git a/tests/ui/four_forward_slashes_first_line.stderr b/tests/ui/four_forward_slashes_first_line.stderr index 83bfb60eb16f..6fcd3e2c1b73 100644 --- a/tests/ui/four_forward_slashes_first_line.stderr +++ b/tests/ui/four_forward_slashes_first_line.stderr @@ -2,6 +2,7 @@ error: this item has comments with 4 forward slashes (`////`). These look like d --> tests/ui/four_forward_slashes_first_line.rs:1:1 | LL | / //// borked doc comment on the first line. doesn't combust! +LL | | LL | | fn a() {} | |_^ | @@ -10,7 +11,7 @@ LL | | fn a() {} help: make this a doc comment by removing one `/` | LL - //// borked doc comment on the first line. doesn't combust! -LL - fn a() {} +LL - LL + /// borked doc comment on the first line. doesn't combust! | diff --git a/tests/ui/from_iter_instead_of_collect.fixed b/tests/ui/from_iter_instead_of_collect.fixed index 67da45a348f9..8618004efb89 100644 --- a/tests/ui/from_iter_instead_of_collect.fixed +++ b/tests/ui/from_iter_instead_of_collect.fixed @@ -15,46 +15,61 @@ impl FromIterator for Foo { impl<'a> FromIterator<&'a bool> for Foo { fn from_iter>(iter: T) -> Self { iter.into_iter().copied().collect::() + //~^ from_iter_instead_of_collect } } fn main() { let iter_expr = std::iter::repeat(5).take(5); let _ = iter_expr.collect::>(); + //~^ from_iter_instead_of_collect let _ = vec![5, 5, 5, 5].iter().enumerate().collect::>(); + //~^ from_iter_instead_of_collect Vec::from_iter(vec![42u32]); let a = vec![0, 1, 2]; assert_eq!(a, (0..3).collect::>()); + //~^ from_iter_instead_of_collect assert_eq!(a, (0..3).collect::>()); + //~^ from_iter_instead_of_collect let mut b = (0..3).collect::>(); + //~^ from_iter_instead_of_collect b.push_back(4); let mut b = (0..3).collect::>(); + //~^ from_iter_instead_of_collect b.push_back(4); { use std::collections; let mut b = (0..3).collect::>(); + //~^ from_iter_instead_of_collect b.push_back(4); } let values = [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]; let bm = values.iter().cloned().collect::>(); + //~^ from_iter_instead_of_collect let mut bar = bm.range(0..2).collect::>(); + //~^ from_iter_instead_of_collect bar.insert(&4, &'e'); let mut bts = (0..3).collect::>(); + //~^ from_iter_instead_of_collect bts.insert(2); { use std::collections; let _ = (0..3).collect::>(); + //~^ from_iter_instead_of_collect let _ = (0..3).collect::>(); + //~^ from_iter_instead_of_collect } for _i in [1, 2, 3].iter().collect::>() {} + //~^ from_iter_instead_of_collect for _i in [1, 2, 3].iter().collect::>() {} + //~^ from_iter_instead_of_collect } diff --git a/tests/ui/from_iter_instead_of_collect.rs b/tests/ui/from_iter_instead_of_collect.rs index 423a7454bed7..c46397e8ff56 100644 --- a/tests/ui/from_iter_instead_of_collect.rs +++ b/tests/ui/from_iter_instead_of_collect.rs @@ -15,46 +15,61 @@ impl FromIterator for Foo { impl<'a> FromIterator<&'a bool> for Foo { fn from_iter>(iter: T) -> Self { >::from_iter(iter.into_iter().copied()) + //~^ from_iter_instead_of_collect } } fn main() { let iter_expr = std::iter::repeat(5).take(5); let _ = Vec::from_iter(iter_expr); + //~^ from_iter_instead_of_collect let _ = HashMap::::from_iter(vec![5, 5, 5, 5].iter().enumerate()); + //~^ from_iter_instead_of_collect Vec::from_iter(vec![42u32]); let a = vec![0, 1, 2]; assert_eq!(a, Vec::from_iter(0..3)); + //~^ from_iter_instead_of_collect assert_eq!(a, Vec::::from_iter(0..3)); + //~^ from_iter_instead_of_collect let mut b = VecDeque::from_iter(0..3); + //~^ from_iter_instead_of_collect b.push_back(4); let mut b = VecDeque::::from_iter(0..3); + //~^ from_iter_instead_of_collect b.push_back(4); { use std::collections; let mut b = collections::VecDeque::::from_iter(0..3); + //~^ from_iter_instead_of_collect b.push_back(4); } let values = [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]; let bm = BTreeMap::from_iter(values.iter().cloned()); + //~^ from_iter_instead_of_collect let mut bar = BTreeMap::from_iter(bm.range(0..2)); + //~^ from_iter_instead_of_collect bar.insert(&4, &'e'); let mut bts = BTreeSet::from_iter(0..3); + //~^ from_iter_instead_of_collect bts.insert(2); { use std::collections; let _ = collections::BTreeSet::from_iter(0..3); + //~^ from_iter_instead_of_collect let _ = collections::BTreeSet::::from_iter(0..3); + //~^ from_iter_instead_of_collect } for _i in Vec::from_iter([1, 2, 3].iter()) {} + //~^ from_iter_instead_of_collect for _i in Vec::<&i32>::from_iter([1, 2, 3].iter()) {} + //~^ from_iter_instead_of_collect } diff --git a/tests/ui/from_iter_instead_of_collect.stderr b/tests/ui/from_iter_instead_of_collect.stderr index 0824a526b793..b46d97af152f 100644 --- a/tests/ui/from_iter_instead_of_collect.stderr +++ b/tests/ui/from_iter_instead_of_collect.stderr @@ -8,85 +8,85 @@ LL | >::from_iter(iter.into_iter().copied()) = help: to override `-D warnings` add `#[allow(clippy::from_iter_instead_of_collect)]` error: usage of `FromIterator::from_iter` - --> tests/ui/from_iter_instead_of_collect.rs:23:13 + --> tests/ui/from_iter_instead_of_collect.rs:24:13 | LL | let _ = Vec::from_iter(iter_expr); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `iter_expr.collect::>()` error: usage of `FromIterator::from_iter` - --> tests/ui/from_iter_instead_of_collect.rs:25:13 + --> tests/ui/from_iter_instead_of_collect.rs:27:13 | LL | let _ = HashMap::::from_iter(vec![5, 5, 5, 5].iter().enumerate()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `vec![5, 5, 5, 5].iter().enumerate().collect::>()` error: usage of `FromIterator::from_iter` - --> tests/ui/from_iter_instead_of_collect.rs:30:19 + --> tests/ui/from_iter_instead_of_collect.rs:33:19 | LL | assert_eq!(a, Vec::from_iter(0..3)); | ^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> tests/ui/from_iter_instead_of_collect.rs:31:19 + --> tests/ui/from_iter_instead_of_collect.rs:35:19 | LL | assert_eq!(a, Vec::::from_iter(0..3)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> tests/ui/from_iter_instead_of_collect.rs:33:17 + --> tests/ui/from_iter_instead_of_collect.rs:38:17 | LL | let mut b = VecDeque::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> tests/ui/from_iter_instead_of_collect.rs:36:17 + --> tests/ui/from_iter_instead_of_collect.rs:42:17 | LL | let mut b = VecDeque::::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> tests/ui/from_iter_instead_of_collect.rs:41:21 + --> tests/ui/from_iter_instead_of_collect.rs:48:21 | LL | let mut b = collections::VecDeque::::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> tests/ui/from_iter_instead_of_collect.rs:46:14 + --> tests/ui/from_iter_instead_of_collect.rs:54:14 | LL | let bm = BTreeMap::from_iter(values.iter().cloned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `values.iter().cloned().collect::>()` error: usage of `FromIterator::from_iter` - --> tests/ui/from_iter_instead_of_collect.rs:47:19 + --> tests/ui/from_iter_instead_of_collect.rs:56:19 | LL | let mut bar = BTreeMap::from_iter(bm.range(0..2)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `bm.range(0..2).collect::>()` error: usage of `FromIterator::from_iter` - --> tests/ui/from_iter_instead_of_collect.rs:50:19 + --> tests/ui/from_iter_instead_of_collect.rs:60:19 | LL | let mut bts = BTreeSet::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> tests/ui/from_iter_instead_of_collect.rs:54:17 + --> tests/ui/from_iter_instead_of_collect.rs:65:17 | LL | let _ = collections::BTreeSet::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> tests/ui/from_iter_instead_of_collect.rs:55:17 + --> tests/ui/from_iter_instead_of_collect.rs:67:17 | LL | let _ = collections::BTreeSet::::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::>()` error: usage of `FromIterator::from_iter` - --> tests/ui/from_iter_instead_of_collect.rs:58:15 + --> tests/ui/from_iter_instead_of_collect.rs:71:15 | LL | for _i in Vec::from_iter([1, 2, 3].iter()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `[1, 2, 3].iter().collect::>()` error: usage of `FromIterator::from_iter` - --> tests/ui/from_iter_instead_of_collect.rs:59:15 + --> tests/ui/from_iter_instead_of_collect.rs:73:15 | LL | for _i in Vec::<&i32>::from_iter([1, 2, 3].iter()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `[1, 2, 3].iter().collect::>()` diff --git a/tests/ui/from_over_into.fixed b/tests/ui/from_over_into.fixed index a33c1ea5738b..7d6780a0e02c 100644 --- a/tests/ui/from_over_into.fixed +++ b/tests/ui/from_over_into.fixed @@ -7,6 +7,7 @@ struct StringWrapper(String); impl From for StringWrapper { + //~^ from_over_into fn from(val: String) -> Self { StringWrapper(val) } @@ -15,6 +16,7 @@ impl From for StringWrapper { struct SelfType(String); impl From for SelfType { + //~^ from_over_into fn from(val: String) -> Self { SelfType(String::new()) } @@ -30,6 +32,7 @@ impl X { struct SelfKeywords; impl From for SelfKeywords { + //~^ from_over_into fn from(val: X) -> Self { let _ = X; let _ = X::FOO; @@ -42,6 +45,7 @@ impl From for SelfKeywords { struct ExplicitPaths(bool); impl core::convert::From for bool { + //~^ from_over_into fn from(mut val: crate::ExplicitPaths) -> Self { let in_closure = || val.0; @@ -62,6 +66,7 @@ impl From for A { struct PathInExpansion; impl From for String { + //~^ from_over_into fn from(val: PathInExpansion) -> Self { // non self/Self paths in expansions are fine panic!() @@ -84,6 +89,7 @@ fn msrv_1_41() { struct FromOverInto(Vec); impl From> for FromOverInto { + //~^ from_over_into fn from(val: Vec) -> Self { FromOverInto(val) } @@ -94,6 +100,7 @@ fn issue_12138() { struct Hello; impl From for () { + //~^ from_over_into fn from(val: Hello) {} } } diff --git a/tests/ui/from_over_into.rs b/tests/ui/from_over_into.rs index 6cd811ae401e..387ddde359c1 100644 --- a/tests/ui/from_over_into.rs +++ b/tests/ui/from_over_into.rs @@ -7,6 +7,7 @@ struct StringWrapper(String); impl Into for String { + //~^ from_over_into fn into(self) -> StringWrapper { StringWrapper(self) } @@ -15,6 +16,7 @@ impl Into for String { struct SelfType(String); impl Into for String { + //~^ from_over_into fn into(self) -> SelfType { SelfType(Self::new()) } @@ -30,6 +32,7 @@ impl X { struct SelfKeywords; impl Into for X { + //~^ from_over_into fn into(self) -> SelfKeywords { let _ = Self; let _ = Self::FOO; @@ -42,6 +45,7 @@ impl Into for X { struct ExplicitPaths(bool); impl core::convert::Into for crate::ExplicitPaths { + //~^ from_over_into fn into(mut self) -> bool { let in_closure = || self.0; @@ -62,6 +66,7 @@ impl From for A { struct PathInExpansion; impl Into for PathInExpansion { + //~^ from_over_into fn into(self) -> String { // non self/Self paths in expansions are fine panic!() @@ -84,6 +89,7 @@ fn msrv_1_41() { struct FromOverInto(Vec); impl Into> for Vec { + //~^ from_over_into fn into(self) -> FromOverInto { FromOverInto(self) } @@ -94,6 +100,7 @@ fn issue_12138() { struct Hello; impl Into<()> for Hello { + //~^ from_over_into fn into(self) {} } } diff --git a/tests/ui/from_over_into.stderr b/tests/ui/from_over_into.stderr index f913ae0bb506..a564bccbaf71 100644 --- a/tests/ui/from_over_into.stderr +++ b/tests/ui/from_over_into.stderr @@ -9,12 +9,13 @@ LL | impl Into for String { help: replace the `Into` implementation with `From` | LL ~ impl From for StringWrapper { +LL | LL ~ fn from(val: String) -> Self { LL ~ StringWrapper(val) | error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> tests/ui/from_over_into.rs:17:1 + --> tests/ui/from_over_into.rs:18:1 | LL | impl Into for String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,12 +23,13 @@ LL | impl Into for String { help: replace the `Into` implementation with `From` | LL ~ impl From for SelfType { +LL | LL ~ fn from(val: String) -> Self { LL ~ SelfType(String::new()) | error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> tests/ui/from_over_into.rs:32:1 + --> tests/ui/from_over_into.rs:34:1 | LL | impl Into for X { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -35,6 +37,7 @@ LL | impl Into for X { help: replace the `Into` implementation with `From` | LL ~ impl From for SelfKeywords { +LL | LL ~ fn from(val: X) -> Self { LL ~ let _ = X; LL ~ let _ = X::FOO; @@ -42,7 +45,7 @@ LL ~ let _: X = val; | error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> tests/ui/from_over_into.rs:44:1 + --> tests/ui/from_over_into.rs:47:1 | LL | impl core::convert::Into for crate::ExplicitPaths { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,6 +55,7 @@ LL | impl core::convert::Into for crate::ExplicitPaths { help: replace the `Into` implementation with `From` | LL ~ impl core::convert::From for bool { +LL | LL ~ fn from(mut val: crate::ExplicitPaths) -> Self { LL ~ let in_closure = || val.0; LL | @@ -60,7 +64,7 @@ LL ~ val.0 | error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> tests/ui/from_over_into.rs:64:1 + --> tests/ui/from_over_into.rs:68:1 | LL | impl Into for PathInExpansion { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -70,11 +74,12 @@ LL | impl Into for PathInExpansion { help: replace the `Into` implementation with `From` | LL ~ impl From for String { +LL | LL ~ fn from(val: PathInExpansion) -> Self { | error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> tests/ui/from_over_into.rs:86:5 + --> tests/ui/from_over_into.rs:91:5 | LL | impl Into> for Vec { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -82,12 +87,13 @@ LL | impl Into> for Vec { help: replace the `Into` implementation with `From>` | LL ~ impl From> for FromOverInto { +LL | LL ~ fn from(val: Vec) -> Self { LL ~ FromOverInto(val) | error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> tests/ui/from_over_into.rs:96:5 + --> tests/ui/from_over_into.rs:102:5 | LL | impl Into<()> for Hello { | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -97,6 +103,7 @@ LL | impl Into<()> for Hello { help: replace the `Into` implementation with `From` | LL ~ impl From for () { +LL | LL ~ fn from(val: Hello) {} | diff --git a/tests/ui/from_over_into_unfixable.rs b/tests/ui/from_over_into_unfixable.rs index 0c1f39f93fd3..de90c7c21a65 100644 --- a/tests/ui/from_over_into_unfixable.rs +++ b/tests/ui/from_over_into_unfixable.rs @@ -9,7 +9,8 @@ macro_rules! in_macro { } impl Into for String { - //~^ ERROR: an implementation of `From` is preferred since it gives you `Into<_>` for free + //~^ from_over_into + fn into(self) -> InMacro { InMacro(in_macro!()) } @@ -18,7 +19,8 @@ impl Into for String { struct WeirdUpperSelf; impl Into for &'static [u8] { - //~^ ERROR: an implementation of `From` is preferred since it gives you `Into<_>` for free + //~^ from_over_into + fn into(self) -> WeirdUpperSelf { let _ = Self::default(); WeirdUpperSelf @@ -28,7 +30,8 @@ impl Into for &'static [u8] { struct ContainsVal; impl Into for ContainsVal { - //~^ ERROR: an implementation of `From` is preferred since it gives you `Into<_>` for free + //~^ from_over_into + fn into(self) -> u8 { let val = 1; val + 1 @@ -40,7 +43,8 @@ pub struct Lval(T); pub struct Rval(T); impl Into> for Lval { - //~^ ERROR: an implementation of `From` is preferred since it gives you `Into<_>` for free + //~^ from_over_into + fn into(self) -> Rval { Rval(self) } diff --git a/tests/ui/from_over_into_unfixable.stderr b/tests/ui/from_over_into_unfixable.stderr index 1776b86e40dd..0e9264a153bb 100644 --- a/tests/ui/from_over_into_unfixable.stderr +++ b/tests/ui/from_over_into_unfixable.stderr @@ -9,7 +9,7 @@ LL | impl Into for String { = help: to override `-D warnings` add `#[allow(clippy::from_over_into)]` error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> tests/ui/from_over_into_unfixable.rs:20:1 + --> tests/ui/from_over_into_unfixable.rs:21:1 | LL | impl Into for &'static [u8] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | impl Into for &'static [u8] { = help: replace the `Into` implementation with `From<&'static [u8]>` error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> tests/ui/from_over_into_unfixable.rs:30:1 + --> tests/ui/from_over_into_unfixable.rs:32:1 | LL | impl Into for ContainsVal { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -27,7 +27,7 @@ LL | impl Into for ContainsVal { = help: replace the `Into` implementation with `From` error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> tests/ui/from_over_into_unfixable.rs:42:1 + --> tests/ui/from_over_into_unfixable.rs:45:1 | LL | impl Into> for Lval { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/from_raw_with_void_ptr.rs b/tests/ui/from_raw_with_void_ptr.rs index 81472070eb4c..390313884433 100644 --- a/tests/ui/from_raw_with_void_ptr.rs +++ b/tests/ui/from_raw_with_void_ptr.rs @@ -9,7 +9,7 @@ fn main() { // must lint let ptr = Box::into_raw(Box::new(42usize)) as *mut c_void; let _ = unsafe { Box::from_raw(ptr) }; - //~^ ERROR: creating a `Box` from a void raw pointer + //~^ from_raw_with_void_ptr // shouldn't be linted let _ = unsafe { Box::from_raw(ptr as *mut usize) }; @@ -21,20 +21,20 @@ fn main() { // must lint let ptr = Rc::into_raw(Rc::new(42usize)) as *mut c_void; let _ = unsafe { Rc::from_raw(ptr) }; - //~^ ERROR: creating a `Rc` from a void raw pointer + //~^ from_raw_with_void_ptr // must lint let ptr = Arc::into_raw(Arc::new(42usize)) as *mut c_void; let _ = unsafe { Arc::from_raw(ptr) }; - //~^ ERROR: creating a `Arc` from a void raw pointer + //~^ from_raw_with_void_ptr // must lint let ptr = std::rc::Weak::into_raw(Rc::downgrade(&Rc::new(42usize))) as *mut c_void; let _ = unsafe { std::rc::Weak::from_raw(ptr) }; - //~^ ERROR: creating a `Weak` from a void raw pointer + //~^ from_raw_with_void_ptr // must lint let ptr = std::sync::Weak::into_raw(Arc::downgrade(&Arc::new(42usize))) as *mut c_void; let _ = unsafe { std::sync::Weak::from_raw(ptr) }; - //~^ ERROR: creating a `Weak` from a void raw pointer + //~^ from_raw_with_void_ptr } diff --git a/tests/ui/from_str_radix_10.fixed b/tests/ui/from_str_radix_10.fixed index 6c582190b442..4b8fd778685e 100644 --- a/tests/ui/from_str_radix_10.fixed +++ b/tests/ui/from_str_radix_10.fixed @@ -26,26 +26,30 @@ impl std::ops::Add for Test { fn main() -> Result<(), Box> { // all of these should trigger the lint "30".parse::()?; - //~^ ERROR: this call to `from_str_radix` can be replaced with a call to `str::parse` - //~| NOTE: `-D clippy::from-str-radix-10` implied by `-D warnings` + //~^ from_str_radix_10 + "24".parse::()?; - //~^ ERROR: this call to `from_str_radix` can be replaced with a call to `str::parse` + //~^ from_str_radix_10 + "100".parse::()?; - //~^ ERROR: this call to `from_str_radix` can be replaced with a call to `str::parse` + //~^ from_str_radix_10 + "7".parse::()?; - //~^ ERROR: this call to `from_str_radix` can be replaced with a call to `str::parse` + //~^ from_str_radix_10 + ("10".to_owned() + "5").parse::()?; - //~^ ERROR: this call to `from_str_radix` can be replaced with a call to `str::parse` + //~^ from_str_radix_10 + (Test + Test).parse::()?; - //~^ ERROR: this call to `from_str_radix` can be replaced with a call to `str::parse` + //~^ from_str_radix_10 let string = "300"; string.parse::()?; - //~^ ERROR: this call to `from_str_radix` can be replaced with a call to `str::parse` + //~^ from_str_radix_10 let stringier = "400".to_string(); stringier.parse::()?; - //~^ ERROR: this call to `from_str_radix` can be replaced with a call to `str::parse` + //~^ from_str_radix_10 // none of these should trigger the lint u16::from_str_radix("20", 3)?; diff --git a/tests/ui/from_str_radix_10.rs b/tests/ui/from_str_radix_10.rs index 0df6a0a202ae..89002b11a995 100644 --- a/tests/ui/from_str_radix_10.rs +++ b/tests/ui/from_str_radix_10.rs @@ -26,26 +26,30 @@ impl std::ops::Add for Test { fn main() -> Result<(), Box> { // all of these should trigger the lint u32::from_str_radix("30", 10)?; - //~^ ERROR: this call to `from_str_radix` can be replaced with a call to `str::parse` - //~| NOTE: `-D clippy::from-str-radix-10` implied by `-D warnings` + //~^ from_str_radix_10 + i64::from_str_radix("24", 10)?; - //~^ ERROR: this call to `from_str_radix` can be replaced with a call to `str::parse` + //~^ from_str_radix_10 + isize::from_str_radix("100", 10)?; - //~^ ERROR: this call to `from_str_radix` can be replaced with a call to `str::parse` + //~^ from_str_radix_10 + u8::from_str_radix("7", 10)?; - //~^ ERROR: this call to `from_str_radix` can be replaced with a call to `str::parse` + //~^ from_str_radix_10 + u16::from_str_radix(&("10".to_owned() + "5"), 10)?; - //~^ ERROR: this call to `from_str_radix` can be replaced with a call to `str::parse` + //~^ from_str_radix_10 + i128::from_str_radix(Test + Test, 10)?; - //~^ ERROR: this call to `from_str_radix` can be replaced with a call to `str::parse` + //~^ from_str_radix_10 let string = "300"; i32::from_str_radix(string, 10)?; - //~^ ERROR: this call to `from_str_radix` can be replaced with a call to `str::parse` + //~^ from_str_radix_10 let stringier = "400".to_string(); i32::from_str_radix(&stringier, 10)?; - //~^ ERROR: this call to `from_str_radix` can be replaced with a call to `str::parse` + //~^ from_str_radix_10 // none of these should trigger the lint u16::from_str_radix("20", 3)?; diff --git a/tests/ui/from_str_radix_10.stderr b/tests/ui/from_str_radix_10.stderr index 4aa84eca2612..c693e8f50ff6 100644 --- a/tests/ui/from_str_radix_10.stderr +++ b/tests/ui/from_str_radix_10.stderr @@ -14,37 +14,37 @@ LL | i64::from_str_radix("24", 10)?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"24".parse::()` error: this call to `from_str_radix` can be replaced with a call to `str::parse` - --> tests/ui/from_str_radix_10.rs:33:5 + --> tests/ui/from_str_radix_10.rs:34:5 | LL | isize::from_str_radix("100", 10)?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"100".parse::()` error: this call to `from_str_radix` can be replaced with a call to `str::parse` - --> tests/ui/from_str_radix_10.rs:35:5 + --> tests/ui/from_str_radix_10.rs:37:5 | LL | u8::from_str_radix("7", 10)?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"7".parse::()` error: this call to `from_str_radix` can be replaced with a call to `str::parse` - --> tests/ui/from_str_radix_10.rs:37:5 + --> tests/ui/from_str_radix_10.rs:40:5 | LL | u16::from_str_radix(&("10".to_owned() + "5"), 10)?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `("10".to_owned() + "5").parse::()` error: this call to `from_str_radix` can be replaced with a call to `str::parse` - --> tests/ui/from_str_radix_10.rs:39:5 + --> tests/ui/from_str_radix_10.rs:43:5 | LL | i128::from_str_radix(Test + Test, 10)?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(Test + Test).parse::()` error: this call to `from_str_radix` can be replaced with a call to `str::parse` - --> tests/ui/from_str_radix_10.rs:43:5 + --> tests/ui/from_str_radix_10.rs:47:5 | LL | i32::from_str_radix(string, 10)?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `string.parse::()` error: this call to `from_str_radix` can be replaced with a call to `str::parse` - --> tests/ui/from_str_radix_10.rs:47:5 + --> tests/ui/from_str_radix_10.rs:51:5 | LL | i32::from_str_radix(&stringier, 10)?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `stringier.parse::()` diff --git a/tests/ui/functions.rs b/tests/ui/functions.rs index 0aef60959593..9c1ca8bf9300 100644 --- a/tests/ui/functions.rs +++ b/tests/ui/functions.rs @@ -6,12 +6,12 @@ fn good(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool) {} fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} -//~^ ERROR: this function has too many arguments (8/7) -//~| NOTE: `-D clippy::too-many-arguments` implied by `-D warnings` +//~^ too_many_arguments #[rustfmt::skip] fn bad_multiline( -//~^ ERROR: this function has too many arguments (8/7) +//~^ too_many_arguments + one: u32, two: u32, three: &str, @@ -46,7 +46,7 @@ extern "C" fn extern_fn( pub trait Foo { fn good(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool); fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()); - //~^ ERROR: this function has too many arguments (8/7) + //~^ too_many_arguments fn ptr(p: *const u8); } @@ -56,7 +56,7 @@ pub struct Bar; impl Bar { fn good_method(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool) {} fn bad_method(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} - //~^ ERROR: this function has too many arguments (8/7) + //~^ too_many_arguments } // ok, we don’t want to warn implementations @@ -66,12 +66,13 @@ impl Foo for Bar { fn ptr(p: *const u8) { println!("{}", unsafe { *p }); - //~^ ERROR: this public function might dereference a raw pointer but is not marked - //~| NOTE: `-D clippy::not-unsafe-ptr-arg-deref` implied by `-D warnings` + //~^ not_unsafe_ptr_arg_deref + println!("{:?}", unsafe { p.as_ref() }); - //~^ ERROR: this public function might dereference a raw pointer but is not marked + //~^ not_unsafe_ptr_arg_deref + unsafe { std::ptr::read(p) }; - //~^ ERROR: this public function might dereference a raw pointer but is not marked + //~^ not_unsafe_ptr_arg_deref } } @@ -83,22 +84,26 @@ fn private(p: *const u8) { pub fn public(p: *const u8) { println!("{}", unsafe { *p }); - //~^ ERROR: this public function might dereference a raw pointer but is not marked `un + //~^ not_unsafe_ptr_arg_deref + println!("{:?}", unsafe { p.as_ref() }); - //~^ ERROR: this public function might dereference a raw pointer but is not marked `un + //~^ not_unsafe_ptr_arg_deref + unsafe { std::ptr::read(p) }; - //~^ ERROR: this public function might dereference a raw pointer but is not marked `un + //~^ not_unsafe_ptr_arg_deref } type Alias = *const u8; pub fn type_alias(p: Alias) { println!("{}", unsafe { *p }); - //~^ ERROR: this public function might dereference a raw pointer but is not marked `un + //~^ not_unsafe_ptr_arg_deref + println!("{:?}", unsafe { p.as_ref() }); - //~^ ERROR: this public function might dereference a raw pointer but is not marked `un + //~^ not_unsafe_ptr_arg_deref + unsafe { std::ptr::read(p) }; - //~^ ERROR: this public function might dereference a raw pointer but is not marked `un + //~^ not_unsafe_ptr_arg_deref } impl Bar { @@ -108,11 +113,13 @@ impl Bar { pub fn public(self, p: *const u8) { println!("{}", unsafe { *p }); - //~^ ERROR: this public function might dereference a raw pointer but is not marked + //~^ not_unsafe_ptr_arg_deref + println!("{:?}", unsafe { p.as_ref() }); - //~^ ERROR: this public function might dereference a raw pointer but is not marked + //~^ not_unsafe_ptr_arg_deref + unsafe { std::ptr::read(p) }; - //~^ ERROR: this public function might dereference a raw pointer but is not marked + //~^ not_unsafe_ptr_arg_deref } pub fn public_ok(self, p: *const u8) { diff --git a/tests/ui/functions.stderr b/tests/ui/functions.stderr index 8fdceb8d8cd0..c8770023f77a 100644 --- a/tests/ui/functions.stderr +++ b/tests/ui/functions.stderr @@ -8,12 +8,12 @@ LL | fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f = help: to override `-D warnings` add `#[allow(clippy::too_many_arguments)]` error: this function has too many arguments (8/7) - --> tests/ui/functions.rs:13:1 + --> tests/ui/functions.rs:12:1 | LL | / fn bad_multiline( LL | | +LL | | LL | | one: u32, -LL | | two: u32, ... | LL | | eight: () LL | | ) { @@ -47,61 +47,61 @@ LL | println!("{:?}", unsafe { p.as_ref() }); | ^ error: this public function might dereference a raw pointer but is not marked `unsafe` - --> tests/ui/functions.rs:73:33 + --> tests/ui/functions.rs:74:33 | LL | unsafe { std::ptr::read(p) }; | ^ error: this public function might dereference a raw pointer but is not marked `unsafe` - --> tests/ui/functions.rs:85:30 + --> tests/ui/functions.rs:86:30 | LL | println!("{}", unsafe { *p }); | ^ error: this public function might dereference a raw pointer but is not marked `unsafe` - --> tests/ui/functions.rs:87:31 + --> tests/ui/functions.rs:89:31 | LL | println!("{:?}", unsafe { p.as_ref() }); | ^ error: this public function might dereference a raw pointer but is not marked `unsafe` - --> tests/ui/functions.rs:89:29 + --> tests/ui/functions.rs:92:29 | LL | unsafe { std::ptr::read(p) }; | ^ error: this public function might dereference a raw pointer but is not marked `unsafe` - --> tests/ui/functions.rs:96:30 + --> tests/ui/functions.rs:99:30 | LL | println!("{}", unsafe { *p }); | ^ error: this public function might dereference a raw pointer but is not marked `unsafe` - --> tests/ui/functions.rs:98:31 + --> tests/ui/functions.rs:102:31 | LL | println!("{:?}", unsafe { p.as_ref() }); | ^ error: this public function might dereference a raw pointer but is not marked `unsafe` - --> tests/ui/functions.rs:100:29 + --> tests/ui/functions.rs:105:29 | LL | unsafe { std::ptr::read(p) }; | ^ error: this public function might dereference a raw pointer but is not marked `unsafe` - --> tests/ui/functions.rs:110:34 + --> tests/ui/functions.rs:115:34 | LL | println!("{}", unsafe { *p }); | ^ error: this public function might dereference a raw pointer but is not marked `unsafe` - --> tests/ui/functions.rs:112:35 + --> tests/ui/functions.rs:118:35 | LL | println!("{:?}", unsafe { p.as_ref() }); | ^ error: this public function might dereference a raw pointer but is not marked `unsafe` - --> tests/ui/functions.rs:114:33 + --> tests/ui/functions.rs:121:33 | LL | unsafe { std::ptr::read(p) }; | ^ diff --git a/tests/ui/functions_maxlines.rs b/tests/ui/functions_maxlines.rs index a3496f56d4a6..e0990dadaaa9 100644 --- a/tests/ui/functions_maxlines.rs +++ b/tests/ui/functions_maxlines.rs @@ -56,8 +56,8 @@ fn good_lines() { } fn bad_lines() { - //~^ ERROR: this function has too many lines (102/100) - //~| NOTE: `-D clippy::too-many-lines` implied by `-D warnings` + //~^ too_many_lines + println!("Dont get confused by braces: {{}}"); println!("This is bad."); println!("This is bad."); diff --git a/tests/ui/future_not_send.rs b/tests/ui/future_not_send.rs index 626ee6de9e4f..662ecb9c955d 100644 --- a/tests/ui/future_not_send.rs +++ b/tests/ui/future_not_send.rs @@ -6,12 +6,14 @@ use std::rc::Rc; use std::sync::Arc; async fn private_future(rc: Rc<[u8]>, cell: &Cell) -> bool { - //~^ ERROR: future cannot be sent between threads safely + //~^ future_not_send + async { true }.await } pub async fn public_future(rc: Rc<[u8]>) { - //~^ ERROR: future cannot be sent between threads safely + //~^ future_not_send + async { true }.await; } @@ -20,12 +22,13 @@ pub async fn public_send(arc: Arc<[u8]>) -> bool { } async fn private_future2(rc: Rc<[u8]>, cell: &Cell) -> bool { - //~^ ERROR: future cannot be sent between threads safely + //~^ future_not_send + true } pub async fn public_future2(rc: Rc<[u8]>) {} -//~^ ERROR: future cannot be sent between threads safely +//~^ future_not_send pub async fn public_send2(arc: Arc<[u8]>) -> bool { false @@ -37,13 +40,15 @@ struct Dummy { impl Dummy { async fn private_future(&self) -> usize { - //~^ ERROR: future cannot be sent between threads safely + //~^ future_not_send + async { true }.await; self.rc.len() } pub async fn public_future(&self) { - //~^ ERROR: future cannot be sent between threads safely + //~^ future_not_send + self.private_future().await; } @@ -54,7 +59,7 @@ impl Dummy { } async fn generic_future(t: T) -> T -//~^ ERROR: future cannot be sent between threads safely +//~^ future_not_send where T: Send, { @@ -76,7 +81,8 @@ async fn maybe_send_generic_future2 Fut, Fut: Future>(f: F) { } async fn generic_future_always_unsend(_: Rc) { - //~^ ERROR: future cannot be sent between threads safely + //~^ future_not_send + async { true }.await; } diff --git a/tests/ui/future_not_send.stderr b/tests/ui/future_not_send.stderr index 3807c7470136..e366dc2d2195 100644 --- a/tests/ui/future_not_send.stderr +++ b/tests/ui/future_not_send.stderr @@ -5,11 +5,11 @@ LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `private_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> tests/ui/future_not_send.rs:10:20 + --> tests/ui/future_not_send.rs:11:20 | LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell) -> bool { | -- has type `std::rc::Rc<[u8]>` which is not `Send` -LL | +... LL | async { true }.await | ^^^^^ await occurs here, with `rc` maybe used later = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` @@ -23,84 +23,84 @@ LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell) -> bool { = help: to override `-D warnings` add `#[allow(clippy::future_not_send)]` error: future cannot be sent between threads safely - --> tests/ui/future_not_send.rs:13:1 + --> tests/ui/future_not_send.rs:14:1 | LL | pub async fn public_future(rc: Rc<[u8]>) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> tests/ui/future_not_send.rs:15:20 + --> tests/ui/future_not_send.rs:17:20 | LL | pub async fn public_future(rc: Rc<[u8]>) { | -- has type `std::rc::Rc<[u8]>` which is not `Send` -LL | +... LL | async { true }.await; | ^^^^^ await occurs here, with `rc` maybe used later = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` error: future cannot be sent between threads safely - --> tests/ui/future_not_send.rs:22:1 + --> tests/ui/future_not_send.rs:24:1 | LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `private_future2` is not `Send` | note: captured value is not `Send` - --> tests/ui/future_not_send.rs:22:26 + --> tests/ui/future_not_send.rs:24:26 | LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell) -> bool { | ^^ has type `std::rc::Rc<[u8]>` which is not `Send` = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` - --> tests/ui/future_not_send.rs:22:40 + --> tests/ui/future_not_send.rs:24:40 | LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell) -> bool { | ^^^^ has type `&std::cell::Cell` which is not `Send`, because `std::cell::Cell` is not `Sync` = note: `std::cell::Cell` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> tests/ui/future_not_send.rs:27:1 + --> tests/ui/future_not_send.rs:30:1 | LL | pub async fn public_future2(rc: Rc<[u8]>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future2` is not `Send` | note: captured value is not `Send` - --> tests/ui/future_not_send.rs:27:29 + --> tests/ui/future_not_send.rs:30:29 | LL | pub async fn public_future2(rc: Rc<[u8]>) {} | ^^ has type `std::rc::Rc<[u8]>` which is not `Send` = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` error: future cannot be sent between threads safely - --> tests/ui/future_not_send.rs:39:5 + --> tests/ui/future_not_send.rs:42:5 | LL | async fn private_future(&self) -> usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `private_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> tests/ui/future_not_send.rs:41:24 + --> tests/ui/future_not_send.rs:45:24 | LL | async fn private_future(&self) -> usize { | ----- has type `&Dummy` which is not `Send` -LL | +... LL | async { true }.await; | ^^^^^ await occurs here, with `&self` maybe used later = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> tests/ui/future_not_send.rs:45:5 + --> tests/ui/future_not_send.rs:49:5 | LL | pub async fn public_future(&self) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future` is not `Send` | note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` - --> tests/ui/future_not_send.rs:45:32 + --> tests/ui/future_not_send.rs:49:32 | LL | pub async fn public_future(&self) { | ^^^^^ has type `&Dummy` which is not `Send`, because `Dummy` is not `Sync` = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> tests/ui/future_not_send.rs:56:1 + --> tests/ui/future_not_send.rs:61:1 | LL | / async fn generic_future(t: T) -> T LL | | @@ -109,7 +109,7 @@ LL | | T: Send, | |____________^ future returned by `generic_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> tests/ui/future_not_send.rs:62:20 + --> tests/ui/future_not_send.rs:67:20 | LL | let rt = &t; | -- has type `&T` which is not `Send` @@ -118,17 +118,17 @@ LL | async { true }.await; = note: `T` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> tests/ui/future_not_send.rs:78:1 + --> tests/ui/future_not_send.rs:83:1 | LL | async fn generic_future_always_unsend(_: Rc) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `generic_future_always_unsend` is not `Send` | note: future is not `Send` as this value is used across an await - --> tests/ui/future_not_send.rs:80:20 + --> tests/ui/future_not_send.rs:86:20 | LL | async fn generic_future_always_unsend(_: Rc) { | - has type `std::rc::Rc` which is not `Send` -LL | +... LL | async { true }.await; | ^^^^^ await occurs here, with `_` maybe used later = note: `std::rc::Rc` doesn't implement `std::marker::Send` diff --git a/tests/ui/get_first.fixed b/tests/ui/get_first.fixed index 710ebab1ef2d..584080defa1e 100644 --- a/tests/ui/get_first.fixed +++ b/tests/ui/get_first.fixed @@ -15,25 +15,29 @@ impl Bar { fn main() { let x = vec![2, 3, 5]; let _ = x.first(); - //~^ ERROR: accessing first element with `x.get(0)` + //~^ get_first + let _ = x.get(1); let _ = x[0]; let y = [2, 3, 5]; let _ = y.first(); - //~^ ERROR: accessing first element with `y.get(0)` + //~^ get_first + let _ = y.get(1); let _ = y[0]; let z = &[2, 3, 5]; let _ = z.first(); - //~^ ERROR: accessing first element with `z.get(0)` + //~^ get_first + let _ = z.get(1); let _ = z[0]; let vecdeque: VecDeque<_> = x.iter().cloned().collect(); let _ = vecdeque.front(); - //~^ ERROR: accessing first element with `vecdeque.get(0)` + //~^ get_first + let _ = vecdeque.get(1); let hashmap: HashMap = HashMap::from_iter(vec![(0, 'a'), (1, 'b')]); @@ -46,5 +50,5 @@ fn main() { let non_primitives = [vec![1, 2], vec![3, 4]]; let _ = non_primitives.first(); - //~^ ERROR: accessing first element with `non_primitives.get(0)` + //~^ get_first } diff --git a/tests/ui/get_first.rs b/tests/ui/get_first.rs index ad2ba6ce2c3b..f01fbdf43c6d 100644 --- a/tests/ui/get_first.rs +++ b/tests/ui/get_first.rs @@ -15,25 +15,29 @@ impl Bar { fn main() { let x = vec![2, 3, 5]; let _ = x.get(0); - //~^ ERROR: accessing first element with `x.get(0)` + //~^ get_first + let _ = x.get(1); let _ = x[0]; let y = [2, 3, 5]; let _ = y.get(0); - //~^ ERROR: accessing first element with `y.get(0)` + //~^ get_first + let _ = y.get(1); let _ = y[0]; let z = &[2, 3, 5]; let _ = z.get(0); - //~^ ERROR: accessing first element with `z.get(0)` + //~^ get_first + let _ = z.get(1); let _ = z[0]; let vecdeque: VecDeque<_> = x.iter().cloned().collect(); let _ = vecdeque.get(0); - //~^ ERROR: accessing first element with `vecdeque.get(0)` + //~^ get_first + let _ = vecdeque.get(1); let hashmap: HashMap = HashMap::from_iter(vec![(0, 'a'), (1, 'b')]); @@ -46,5 +50,5 @@ fn main() { let non_primitives = [vec![1, 2], vec![3, 4]]; let _ = non_primitives.get(0); - //~^ ERROR: accessing first element with `non_primitives.get(0)` + //~^ get_first } diff --git a/tests/ui/get_first.stderr b/tests/ui/get_first.stderr index 155d341b5a77..4e19ebbc7589 100644 --- a/tests/ui/get_first.stderr +++ b/tests/ui/get_first.stderr @@ -8,25 +8,25 @@ LL | let _ = x.get(0); = help: to override `-D warnings` add `#[allow(clippy::get_first)]` error: accessing first element with `y.get(0)` - --> tests/ui/get_first.rs:23:13 + --> tests/ui/get_first.rs:24:13 | LL | let _ = y.get(0); | ^^^^^^^^ help: try: `y.first()` error: accessing first element with `z.get(0)` - --> tests/ui/get_first.rs:29:13 + --> tests/ui/get_first.rs:31:13 | LL | let _ = z.get(0); | ^^^^^^^^ help: try: `z.first()` error: accessing first element with `vecdeque.get(0)` - --> tests/ui/get_first.rs:35:13 + --> tests/ui/get_first.rs:38:13 | LL | let _ = vecdeque.get(0); | ^^^^^^^^^^^^^^^ help: try: `vecdeque.front()` error: accessing first element with `non_primitives.get(0)` - --> tests/ui/get_first.rs:48:13 + --> tests/ui/get_first.rs:52:13 | LL | let _ = non_primitives.get(0); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `non_primitives.first()` diff --git a/tests/ui/get_last_with_len.fixed b/tests/ui/get_last_with_len.fixed index 377906cb2448..15b6e1666af2 100644 --- a/tests/ui/get_last_with_len.fixed +++ b/tests/ui/get_last_with_len.fixed @@ -6,6 +6,7 @@ use std::collections::VecDeque; fn dont_use_last() { let x = vec![2, 3, 5]; let _ = x.last(); + //~^ get_last_with_len } fn indexing_two_from_end() { @@ -30,18 +31,23 @@ struct S { fn in_field(s: &S) { let _ = s.field.last(); + //~^ get_last_with_len } fn main() { let slice = &[1, 2, 3]; let _ = slice.last(); + //~^ get_last_with_len let array = [4, 5, 6]; let _ = array.last(); + //~^ get_last_with_len let deq = VecDeque::from([7, 8, 9]); let _ = deq.back(); + //~^ get_last_with_len let nested = [[1]]; let _ = nested[0].last(); + //~^ get_last_with_len } diff --git a/tests/ui/get_last_with_len.rs b/tests/ui/get_last_with_len.rs index 2735932043a3..5b132e001e7b 100644 --- a/tests/ui/get_last_with_len.rs +++ b/tests/ui/get_last_with_len.rs @@ -6,6 +6,7 @@ use std::collections::VecDeque; fn dont_use_last() { let x = vec![2, 3, 5]; let _ = x.get(x.len() - 1); + //~^ get_last_with_len } fn indexing_two_from_end() { @@ -30,18 +31,23 @@ struct S { fn in_field(s: &S) { let _ = s.field.get(s.field.len() - 1); + //~^ get_last_with_len } fn main() { let slice = &[1, 2, 3]; let _ = slice.get(slice.len() - 1); + //~^ get_last_with_len let array = [4, 5, 6]; let _ = array.get(array.len() - 1); + //~^ get_last_with_len let deq = VecDeque::from([7, 8, 9]); let _ = deq.get(deq.len() - 1); + //~^ get_last_with_len let nested = [[1]]; let _ = nested[0].get(nested[0].len() - 1); + //~^ get_last_with_len } diff --git a/tests/ui/get_last_with_len.stderr b/tests/ui/get_last_with_len.stderr index ba08f5db7cfa..83a03a438e44 100644 --- a/tests/ui/get_last_with_len.stderr +++ b/tests/ui/get_last_with_len.stderr @@ -8,31 +8,31 @@ LL | let _ = x.get(x.len() - 1); = help: to override `-D warnings` add `#[allow(clippy::get_last_with_len)]` error: accessing last element with `s.field.get(s.field.len() - 1)` - --> tests/ui/get_last_with_len.rs:32:13 + --> tests/ui/get_last_with_len.rs:33:13 | LL | let _ = s.field.get(s.field.len() - 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.field.last()` error: accessing last element with `slice.get(slice.len() - 1)` - --> tests/ui/get_last_with_len.rs:37:13 + --> tests/ui/get_last_with_len.rs:39:13 | LL | let _ = slice.get(slice.len() - 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `slice.last()` error: accessing last element with `array.get(array.len() - 1)` - --> tests/ui/get_last_with_len.rs:40:13 + --> tests/ui/get_last_with_len.rs:43:13 | LL | let _ = array.get(array.len() - 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `array.last()` error: accessing last element with `deq.get(deq.len() - 1)` - --> tests/ui/get_last_with_len.rs:43:13 + --> tests/ui/get_last_with_len.rs:47:13 | LL | let _ = deq.get(deq.len() - 1); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `deq.back()` error: accessing last element with `nested[0].get(nested[0].len() - 1)` - --> tests/ui/get_last_with_len.rs:46:13 + --> tests/ui/get_last_with_len.rs:51:13 | LL | let _ = nested[0].get(nested[0].len() - 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `nested[0].last()` diff --git a/tests/ui/get_unwrap.fixed b/tests/ui/get_unwrap.fixed index 2dd3c30a4e29..3115c1462f5a 100644 --- a/tests/ui/get_unwrap.fixed +++ b/tests/ui/get_unwrap.fixed @@ -35,23 +35,45 @@ fn main() { { // Test `get().unwrap()` let _ = &boxed_slice[1]; + //~^ get_unwrap + //~| unwrap_used let _ = &some_slice[0]; + //~^ get_unwrap + //~| unwrap_used let _ = &some_vec[0]; + //~^ get_unwrap + //~| unwrap_used let _ = &some_vecdeque[0]; + //~^ get_unwrap + //~| unwrap_used let _ = &some_hashmap[&1]; + //~^ get_unwrap + //~| unwrap_used let _ = &some_btreemap[&1]; + //~^ get_unwrap + //~| unwrap_used #[allow(clippy::unwrap_used)] let _ = false_positive.get(0).unwrap(); // Test with deref let _: u8 = boxed_slice[1]; + //~^ get_unwrap + //~| unwrap_used } { // Test `get_mut().unwrap()` boxed_slice[0] = 1; + //~^ get_unwrap + //~| unwrap_used some_slice[0] = 1; + //~^ get_unwrap + //~| unwrap_used some_vec[0] = 1; + //~^ get_unwrap + //~| unwrap_used some_vecdeque[0] = 1; + //~^ get_unwrap + //~| unwrap_used // Check false positives #[allow(clippy::unwrap_used)] { @@ -64,7 +86,11 @@ fn main() { { // Test `get().unwrap().foo()` and `get_mut().unwrap().bar()` let _ = some_vec[0..1].to_vec(); + //~^ get_unwrap + //~| unwrap_used let _ = some_vec[0..1].to_vec(); + //~^ get_unwrap + //~| unwrap_used } } mod issue9909 { @@ -76,12 +102,15 @@ mod issue9909 { // include a borrow in the suggestion, even if the argument is not just a numeric literal let _x: &i32 = &f[1 + 2]; + //~^ get_unwrap // don't include a borrow here let _x = f[1 + 2].to_string(); + //~^ get_unwrap // don't include a borrow here let _x = f[1 + 2].abs(); + //~^ get_unwrap } // original code: @@ -99,6 +128,7 @@ mod issue9909 { let (x, rest) = mat.split_at_mut(linidx(i, k) + 1); let a = x.last_mut().unwrap(); let b = &mut rest[linidx(j, k) - linidx(i, k) - 1]; + //~^ get_unwrap ::std::mem::swap(a, b); } } diff --git a/tests/ui/get_unwrap.rs b/tests/ui/get_unwrap.rs index 94226564cacb..963238a88983 100644 --- a/tests/ui/get_unwrap.rs +++ b/tests/ui/get_unwrap.rs @@ -35,23 +35,45 @@ fn main() { { // Test `get().unwrap()` let _ = boxed_slice.get(1).unwrap(); + //~^ get_unwrap + //~| unwrap_used let _ = some_slice.get(0).unwrap(); + //~^ get_unwrap + //~| unwrap_used let _ = some_vec.get(0).unwrap(); + //~^ get_unwrap + //~| unwrap_used let _ = some_vecdeque.get(0).unwrap(); + //~^ get_unwrap + //~| unwrap_used let _ = some_hashmap.get(&1).unwrap(); + //~^ get_unwrap + //~| unwrap_used let _ = some_btreemap.get(&1).unwrap(); + //~^ get_unwrap + //~| unwrap_used #[allow(clippy::unwrap_used)] let _ = false_positive.get(0).unwrap(); // Test with deref let _: u8 = *boxed_slice.get(1).unwrap(); + //~^ get_unwrap + //~| unwrap_used } { // Test `get_mut().unwrap()` *boxed_slice.get_mut(0).unwrap() = 1; + //~^ get_unwrap + //~| unwrap_used *some_slice.get_mut(0).unwrap() = 1; + //~^ get_unwrap + //~| unwrap_used *some_vec.get_mut(0).unwrap() = 1; + //~^ get_unwrap + //~| unwrap_used *some_vecdeque.get_mut(0).unwrap() = 1; + //~^ get_unwrap + //~| unwrap_used // Check false positives #[allow(clippy::unwrap_used)] { @@ -64,7 +86,11 @@ fn main() { { // Test `get().unwrap().foo()` and `get_mut().unwrap().bar()` let _ = some_vec.get(0..1).unwrap().to_vec(); + //~^ get_unwrap + //~| unwrap_used let _ = some_vec.get_mut(0..1).unwrap().to_vec(); + //~^ get_unwrap + //~| unwrap_used } } mod issue9909 { @@ -76,12 +102,15 @@ mod issue9909 { // include a borrow in the suggestion, even if the argument is not just a numeric literal let _x: &i32 = f.get(1 + 2).unwrap(); + //~^ get_unwrap // don't include a borrow here let _x = f.get(1 + 2).unwrap().to_string(); + //~^ get_unwrap // don't include a borrow here let _x = f.get(1 + 2).unwrap().abs(); + //~^ get_unwrap } // original code: @@ -99,6 +128,7 @@ mod issue9909 { let (x, rest) = mat.split_at_mut(linidx(i, k) + 1); let a = x.last_mut().unwrap(); let b = rest.get_mut(linidx(j, k) - linidx(i, k) - 1).unwrap(); + //~^ get_unwrap ::std::mem::swap(a, b); } } diff --git a/tests/ui/get_unwrap.stderr b/tests/ui/get_unwrap.stderr index fc6c0b9299c4..72a575654af9 100644 --- a/tests/ui/get_unwrap.stderr +++ b/tests/ui/get_unwrap.stderr @@ -27,7 +27,7 @@ LL | let _ = boxed_slice.get(1).unwrap(); = help: to override `-D warnings` add `#[allow(clippy::unwrap_used)]` error: called `.get().unwrap()` on a slice - --> tests/ui/get_unwrap.rs:38:17 + --> tests/ui/get_unwrap.rs:40:17 | LL | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -39,7 +39,7 @@ LL + let _ = &some_slice[0]; | error: used `unwrap()` on an `Option` value - --> tests/ui/get_unwrap.rs:38:17 + --> tests/ui/get_unwrap.rs:40:17 | LL | let _ = some_slice.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -48,7 +48,7 @@ LL | let _ = some_slice.get(0).unwrap(); = help: consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a Vec - --> tests/ui/get_unwrap.rs:39:17 + --> tests/ui/get_unwrap.rs:43:17 | LL | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL + let _ = &some_vec[0]; | error: used `unwrap()` on an `Option` value - --> tests/ui/get_unwrap.rs:39:17 + --> tests/ui/get_unwrap.rs:43:17 | LL | let _ = some_vec.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -69,7 +69,7 @@ LL | let _ = some_vec.get(0).unwrap(); = help: consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a VecDeque - --> tests/ui/get_unwrap.rs:40:17 + --> tests/ui/get_unwrap.rs:46:17 | LL | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -81,7 +81,7 @@ LL + let _ = &some_vecdeque[0]; | error: used `unwrap()` on an `Option` value - --> tests/ui/get_unwrap.rs:40:17 + --> tests/ui/get_unwrap.rs:46:17 | LL | let _ = some_vecdeque.get(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -90,7 +90,7 @@ LL | let _ = some_vecdeque.get(0).unwrap(); = help: consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a HashMap - --> tests/ui/get_unwrap.rs:41:17 + --> tests/ui/get_unwrap.rs:49:17 | LL | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -102,7 +102,7 @@ LL + let _ = &some_hashmap[&1]; | error: used `unwrap()` on an `Option` value - --> tests/ui/get_unwrap.rs:41:17 + --> tests/ui/get_unwrap.rs:49:17 | LL | let _ = some_hashmap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -111,7 +111,7 @@ LL | let _ = some_hashmap.get(&1).unwrap(); = help: consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a BTreeMap - --> tests/ui/get_unwrap.rs:42:17 + --> tests/ui/get_unwrap.rs:52:17 | LL | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -123,7 +123,7 @@ LL + let _ = &some_btreemap[&1]; | error: used `unwrap()` on an `Option` value - --> tests/ui/get_unwrap.rs:42:17 + --> tests/ui/get_unwrap.rs:52:17 | LL | let _ = some_btreemap.get(&1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -132,7 +132,7 @@ LL | let _ = some_btreemap.get(&1).unwrap(); = help: consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a slice - --> tests/ui/get_unwrap.rs:46:21 + --> tests/ui/get_unwrap.rs:58:21 | LL | let _: u8 = *boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -144,7 +144,7 @@ LL + let _: u8 = boxed_slice[1]; | error: used `unwrap()` on an `Option` value - --> tests/ui/get_unwrap.rs:46:22 + --> tests/ui/get_unwrap.rs:58:22 | LL | let _: u8 = *boxed_slice.get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -153,7 +153,7 @@ LL | let _: u8 = *boxed_slice.get(1).unwrap(); = help: consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a slice - --> tests/ui/get_unwrap.rs:51:9 + --> tests/ui/get_unwrap.rs:65:9 | LL | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,7 +165,7 @@ LL + boxed_slice[0] = 1; | error: used `unwrap()` on an `Option` value - --> tests/ui/get_unwrap.rs:51:10 + --> tests/ui/get_unwrap.rs:65:10 | LL | *boxed_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -174,7 +174,7 @@ LL | *boxed_slice.get_mut(0).unwrap() = 1; = help: consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a slice - --> tests/ui/get_unwrap.rs:52:9 + --> tests/ui/get_unwrap.rs:68:9 | LL | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -186,7 +186,7 @@ LL + some_slice[0] = 1; | error: used `unwrap()` on an `Option` value - --> tests/ui/get_unwrap.rs:52:10 + --> tests/ui/get_unwrap.rs:68:10 | LL | *some_slice.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -195,7 +195,7 @@ LL | *some_slice.get_mut(0).unwrap() = 1; = help: consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a Vec - --> tests/ui/get_unwrap.rs:53:9 + --> tests/ui/get_unwrap.rs:71:9 | LL | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -207,7 +207,7 @@ LL + some_vec[0] = 1; | error: used `unwrap()` on an `Option` value - --> tests/ui/get_unwrap.rs:53:10 + --> tests/ui/get_unwrap.rs:71:10 | LL | *some_vec.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -216,7 +216,7 @@ LL | *some_vec.get_mut(0).unwrap() = 1; = help: consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a VecDeque - --> tests/ui/get_unwrap.rs:54:9 + --> tests/ui/get_unwrap.rs:74:9 | LL | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -228,7 +228,7 @@ LL + some_vecdeque[0] = 1; | error: used `unwrap()` on an `Option` value - --> tests/ui/get_unwrap.rs:54:10 + --> tests/ui/get_unwrap.rs:74:10 | LL | *some_vecdeque.get_mut(0).unwrap() = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -237,7 +237,7 @@ LL | *some_vecdeque.get_mut(0).unwrap() = 1; = help: consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a Vec - --> tests/ui/get_unwrap.rs:66:17 + --> tests/ui/get_unwrap.rs:88:17 | LL | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -249,7 +249,7 @@ LL + let _ = some_vec[0..1].to_vec(); | error: used `unwrap()` on an `Option` value - --> tests/ui/get_unwrap.rs:66:17 + --> tests/ui/get_unwrap.rs:88:17 | LL | let _ = some_vec.get(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -258,7 +258,7 @@ LL | let _ = some_vec.get(0..1).unwrap().to_vec(); = help: consider using `expect()` to provide a better panic message error: called `.get_mut().unwrap()` on a Vec - --> tests/ui/get_unwrap.rs:67:17 + --> tests/ui/get_unwrap.rs:91:17 | LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -270,7 +270,7 @@ LL + let _ = some_vec[0..1].to_vec(); | error: used `unwrap()` on an `Option` value - --> tests/ui/get_unwrap.rs:67:17 + --> tests/ui/get_unwrap.rs:91:17 | LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -279,7 +279,7 @@ LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); = help: consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a slice - --> tests/ui/get_unwrap.rs:78:24 + --> tests/ui/get_unwrap.rs:104:24 | LL | let _x: &i32 = f.get(1 + 2).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^ @@ -291,7 +291,7 @@ LL + let _x: &i32 = &f[1 + 2]; | error: called `.get().unwrap()` on a slice - --> tests/ui/get_unwrap.rs:81:18 + --> tests/ui/get_unwrap.rs:108:18 | LL | let _x = f.get(1 + 2).unwrap().to_string(); | ^^^^^^^^^^^^^^^^^^^^^ @@ -303,7 +303,7 @@ LL + let _x = f[1 + 2].to_string(); | error: called `.get().unwrap()` on a slice - --> tests/ui/get_unwrap.rs:84:18 + --> tests/ui/get_unwrap.rs:112:18 | LL | let _x = f.get(1 + 2).unwrap().abs(); | ^^^^^^^^^^^^^^^^^^^^^ @@ -315,7 +315,7 @@ LL + let _x = f[1 + 2].abs(); | error: called `.get_mut().unwrap()` on a slice - --> tests/ui/get_unwrap.rs:101:33 + --> tests/ui/get_unwrap.rs:130:33 | LL | let b = rest.get_mut(linidx(j, k) - linidx(i, k) - 1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/identity_op.fixed b/tests/ui/identity_op.fixed index 2e8e2366de6f..a1b556029987 100644 --- a/tests/ui/identity_op.fixed +++ b/tests/ui/identity_op.fixed @@ -42,45 +42,58 @@ fn main() { let x = 0; x; - //~^ ERROR: this operation has no effect + //~^ identity_op + x; - //~^ ERROR: this operation has no effect + //~^ identity_op + x + 1; x; - //~^ ERROR: this operation has no effect + //~^ identity_op + 1 + x; x - ZERO; //no error, as we skip lookups (for now) x; - //~^ ERROR: this operation has no effect + //~^ identity_op + ((ZERO)) | x; //no error, as we skip lookups (for now) x; - //~^ ERROR: this operation has no effect + //~^ identity_op + x; - //~^ ERROR: this operation has no effect + //~^ identity_op + x / ONE; //no error, as we skip lookups (for now) x / 2; //no false positive x & NEG_ONE; //no error, as we skip lookups (for now) x; - //~^ ERROR: this operation has no effect + //~^ identity_op + let u: u8 = 0; u; - //~^ ERROR: this operation has no effect + //~^ identity_op + 1 << 0; // no error, this case is allowed, see issue 3430 42; - //~^ ERROR: this operation has no effect + //~^ identity_op + 1; - //~^ ERROR: this operation has no effect + //~^ identity_op + 42; - //~^ ERROR: this operation has no effect + //~^ identity_op + x; - //~^ ERROR: this operation has no effect + //~^ identity_op + x; - //~^ ERROR: this operation has no effect + //~^ identity_op + let mut a = A(String::new()); let b = a << 0; // no error: non-integer @@ -88,15 +101,20 @@ fn main() { 1 * Meter; // no error: non-integer 2; - //~^ ERROR: this operation has no effect + //~^ identity_op + -2; - //~^ ERROR: this operation has no effect + //~^ identity_op + 2 + x; - //~^ ERROR: this operation has no effect + //~^ identity_op + -2 + x; - //~^ ERROR: this operation has no effect + //~^ identity_op + x + 1; - //~^ ERROR: this operation has no effect + //~^ identity_op + (x + 1) % 3; // no error 4 % 3; // no error 4 % -3; // no error @@ -105,63 +123,85 @@ fn main() { let a = 0; let b = true; (if b { 1 } else { 2 }); - //~^ ERROR: this operation has no effect + //~^ identity_op + (if b { 1 } else { 2 }) + if b { 3 } else { 4 }; - //~^ ERROR: this operation has no effect + //~^ identity_op + (match a { 0 => 10, _ => 20 }); - //~^ ERROR: this operation has no effect + //~^ identity_op + (match a { 0 => 10, _ => 20 }) + match a { 0 => 30, _ => 40 }; - //~^ ERROR: this operation has no effect + //~^ identity_op + (if b { 1 } else { 2 }) + match a { 0 => 30, _ => 40 }; - //~^ ERROR: this operation has no effect + //~^ identity_op + (match a { 0 => 10, _ => 20 }) + if b { 3 } else { 4 }; - //~^ ERROR: this operation has no effect + //~^ identity_op + ((if b { 1 } else { 2 })); - //~^ ERROR: this operation has no effect + //~^ identity_op + ({ a }) + 3; - //~^ ERROR: this operation has no effect + //~^ identity_op + ({ a } * 2); - //~^ ERROR: this operation has no effect + //~^ identity_op + (loop { let mut c = 0; if c == 10 { break c; } c += 1; }) + { a * 2 }; - //~^ ERROR: this operation has no effect + //~^ identity_op + fn f(_: i32) { todo!(); } f(a + { 8 * 5 }); - //~^ ERROR: this operation has no effect + //~^ identity_op + f(if b { 1 } else { 2 } + 3); - //~^ ERROR: this operation has no effect + //~^ identity_op + const _: i32 = { 2 * 4 } + 3; - //~^ ERROR: this operation has no effect + //~^ identity_op + const _: i32 = { 1 + 2 * 3 } + 3; - //~^ ERROR: this operation has no effect + //~^ identity_op + a as usize; - //~^ ERROR: this operation has no effect + //~^ identity_op + let _ = a as usize; - //~^ ERROR: this operation has no effect + //~^ identity_op + ({ a } as usize); - //~^ ERROR: this operation has no effect + //~^ identity_op + 2 * { a }; - //~^ ERROR: this operation has no effect + //~^ identity_op + (({ a } + 4)); - //~^ ERROR: this operation has no effect + //~^ identity_op + 1; - //~^ ERROR: this operation has no effect + //~^ identity_op + // Issue #9904 let x = 0i32; let _: i32 = x; - //~^ ERROR: this operation has no effect + //~^ identity_op + } pub fn decide(a: bool, b: bool) -> u32 { (if a { 1 } else { 2 }) + if b { 3 } else { 5 } + //~^ identity_op } /// The following tests are from / for issue #12050 @@ -173,43 +213,51 @@ fn issue_12050() { { let x = &0i32; let _: i32 = *x; - //~^ ERROR: this operation has no effect + //~^ identity_op + let _: i32 = *x; - //~^ ERROR: this operation has no effect + //~^ identity_op } { let x = &&0i32; let _: i32 = **x; - //~^ ERROR: this operation has no effect + //~^ identity_op + let x = &&0i32; let _: i32 = **x; - //~^ ERROR: this operation has no effect + //~^ identity_op } { // this is just silly let x = &&&0i32; let _: i32 = ***x; - //~^ ERROR: this operation has no effect + //~^ identity_op + let _: i32 = ***x; - //~^ ERROR: this operation has no effect + //~^ identity_op + let x = 0i32; let _: i32 = *&x; - //~^ ERROR: this operation has no effect + //~^ identity_op + let _: i32 = **&&x; - //~^ ERROR: this operation has no effect + //~^ identity_op + let _: i32 = *&*&x; - //~^ ERROR: this operation has no effect + //~^ identity_op + let _: i32 = **&&*&x; - //~^ ERROR: this operation has no effect + //~^ identity_op } { // this is getting ridiculous, but we should still see the same // error message so let's just keep going let x = &0i32; let _: i32 = ***&&*&x; - //~^ ERROR: this operation has no effect + //~^ identity_op + let _: i32 = ***&&*&x; - //~^ ERROR: this operation has no effect + //~^ identity_op } } @@ -218,41 +266,49 @@ fn issue_13470() { let y = 1i32; // Removes the + 0i32 while keeping the parentheses around x + y so the cast operation works let _: u64 = (x + y) as u64; - //~^ ERROR: this operation has no effect + //~^ identity_op + // both of the next two lines should look the same after rustfix let _: u64 = 1u64 & (x + y) as u64; - //~^ ERROR: this operation has no effect + //~^ identity_op + // Same as above, but with extra redundant parenthesis let _: u64 = 1u64 & ((x + y)) as u64; - //~^ ERROR: this operation has no effect + //~^ identity_op + // Should maintain parenthesis even if the surrounding expr has the same precedence let _: u64 = 5u64 + ((x + y)) as u64; - //~^ ERROR: this operation has no effect + //~^ identity_op // If we don't maintain the parens here, the behavior changes let _ = -(x + y); - //~^ ERROR: this operation has no effect + //~^ identity_op + // Similarly, we need to maintain parens here let _ = -(x / y); - //~^ ERROR: this operation has no effect + //~^ identity_op + // Maintain parenthesis if the parent expr is of higher precedence let _ = 2i32 * (x + y); - //~^ ERROR: this operation has no effect + //~^ identity_op + // Maintain parenthesis if the parent expr is the same precedence // as not all operations are associative let _ = 2i32 - (x - y); - //~^ ERROR: this operation has no effect + //~^ identity_op + // But make sure that inner parens still exist let z = 1i32; let _ = 2 + (x + (y * z)); - //~^ ERROR: this operation has no effect + //~^ identity_op + // Maintain parenthesis if the parent expr is of lower precedence // This is for clarity, and clippy will not warn on these being unnecessary let _ = 2i32 + (x * y); - //~^ ERROR: this operation has no effect + //~^ identity_op let x = 1i16; let y = 1i16; let _: u64 = 1u64 + ((x as i32 + y as i32) as u64); - //~^ ERROR: this operation has no effect + //~^ identity_op } diff --git a/tests/ui/identity_op.rs b/tests/ui/identity_op.rs index 3e20fa6f2b89..f603e1078e4e 100644 --- a/tests/ui/identity_op.rs +++ b/tests/ui/identity_op.rs @@ -42,45 +42,58 @@ fn main() { let x = 0; x + 0; - //~^ ERROR: this operation has no effect + //~^ identity_op + x + (1 - 1); - //~^ ERROR: this operation has no effect + //~^ identity_op + x + 1; 0 + x; - //~^ ERROR: this operation has no effect + //~^ identity_op + 1 + x; x - ZERO; //no error, as we skip lookups (for now) x | (0); - //~^ ERROR: this operation has no effect + //~^ identity_op + ((ZERO)) | x; //no error, as we skip lookups (for now) x * 1; - //~^ ERROR: this operation has no effect + //~^ identity_op + 1 * x; - //~^ ERROR: this operation has no effect + //~^ identity_op + x / ONE; //no error, as we skip lookups (for now) x / 2; //no false positive x & NEG_ONE; //no error, as we skip lookups (for now) -1 & x; - //~^ ERROR: this operation has no effect + //~^ identity_op + let u: u8 = 0; u & 255; - //~^ ERROR: this operation has no effect + //~^ identity_op + 1 << 0; // no error, this case is allowed, see issue 3430 42 << 0; - //~^ ERROR: this operation has no effect + //~^ identity_op + 1 >> 0; - //~^ ERROR: this operation has no effect + //~^ identity_op + 42 >> 0; - //~^ ERROR: this operation has no effect + //~^ identity_op + &x >> 0; - //~^ ERROR: this operation has no effect + //~^ identity_op + x >> &0; - //~^ ERROR: this operation has no effect + //~^ identity_op + let mut a = A(String::new()); let b = a << 0; // no error: non-integer @@ -88,15 +101,20 @@ fn main() { 1 * Meter; // no error: non-integer 2 % 3; - //~^ ERROR: this operation has no effect + //~^ identity_op + -2 % 3; - //~^ ERROR: this operation has no effect + //~^ identity_op + 2 % -3 + x; - //~^ ERROR: this operation has no effect + //~^ identity_op + -2 % -3 + x; - //~^ ERROR: this operation has no effect + //~^ identity_op + x + 1 % 3; - //~^ ERROR: this operation has no effect + //~^ identity_op + (x + 1) % 3; // no error 4 % 3; // no error 4 % -3; // no error @@ -105,63 +123,85 @@ fn main() { let a = 0; let b = true; 0 + if b { 1 } else { 2 }; - //~^ ERROR: this operation has no effect + //~^ identity_op + 0 + if b { 1 } else { 2 } + if b { 3 } else { 4 }; - //~^ ERROR: this operation has no effect + //~^ identity_op + 0 + match a { 0 => 10, _ => 20 }; - //~^ ERROR: this operation has no effect + //~^ identity_op + 0 + match a { 0 => 10, _ => 20 } + match a { 0 => 30, _ => 40 }; - //~^ ERROR: this operation has no effect + //~^ identity_op + 0 + if b { 1 } else { 2 } + match a { 0 => 30, _ => 40 }; - //~^ ERROR: this operation has no effect + //~^ identity_op + 0 + match a { 0 => 10, _ => 20 } + if b { 3 } else { 4 }; - //~^ ERROR: this operation has no effect + //~^ identity_op + (if b { 1 } else { 2 }) + 0; - //~^ ERROR: this operation has no effect + //~^ identity_op + 0 + { a } + 3; - //~^ ERROR: this operation has no effect + //~^ identity_op + 0 + { a } * 2; - //~^ ERROR: this operation has no effect + //~^ identity_op + 0 + loop { let mut c = 0; if c == 10 { break c; } c += 1; } + { a * 2 }; - //~^ ERROR: this operation has no effect + //~^ identity_op + fn f(_: i32) { todo!(); } f(1 * a + { 8 * 5 }); - //~^ ERROR: this operation has no effect + //~^ identity_op + f(0 + if b { 1 } else { 2 } + 3); - //~^ ERROR: this operation has no effect + //~^ identity_op + const _: i32 = { 2 * 4 } + 0 + 3; - //~^ ERROR: this operation has no effect + //~^ identity_op + const _: i32 = 0 + { 1 + 2 * 3 } + 3; - //~^ ERROR: this operation has no effect + //~^ identity_op + 0 + a as usize; - //~^ ERROR: this operation has no effect + //~^ identity_op + let _ = 0 + a as usize; - //~^ ERROR: this operation has no effect + //~^ identity_op + 0 + { a } as usize; - //~^ ERROR: this operation has no effect + //~^ identity_op + 2 * (0 + { a }); - //~^ ERROR: this operation has no effect + //~^ identity_op + 1 * ({ a } + 4); - //~^ ERROR: this operation has no effect + //~^ identity_op + 1 * 1; - //~^ ERROR: this operation has no effect + //~^ identity_op + // Issue #9904 let x = 0i32; let _: i32 = &x + 0; - //~^ ERROR: this operation has no effect + //~^ identity_op + } pub fn decide(a: bool, b: bool) -> u32 { 0 + if a { 1 } else { 2 } + if b { 3 } else { 5 } + //~^ identity_op } /// The following tests are from / for issue #12050 @@ -173,43 +213,51 @@ fn issue_12050() { { let x = &0i32; let _: i32 = *x + 0; - //~^ ERROR: this operation has no effect + //~^ identity_op + let _: i32 = x + 0; - //~^ ERROR: this operation has no effect + //~^ identity_op } { let x = &&0i32; let _: i32 = **x + 0; - //~^ ERROR: this operation has no effect + //~^ identity_op + let x = &&0i32; let _: i32 = *x + 0; - //~^ ERROR: this operation has no effect + //~^ identity_op } { // this is just silly let x = &&&0i32; let _: i32 = ***x + 0; - //~^ ERROR: this operation has no effect + //~^ identity_op + let _: i32 = **x + 0; - //~^ ERROR: this operation has no effect + //~^ identity_op + let x = 0i32; let _: i32 = *&x + 0; - //~^ ERROR: this operation has no effect + //~^ identity_op + let _: i32 = **&&x + 0; - //~^ ERROR: this operation has no effect + //~^ identity_op + let _: i32 = *&*&x + 0; - //~^ ERROR: this operation has no effect + //~^ identity_op + let _: i32 = **&&*&x + 0; - //~^ ERROR: this operation has no effect + //~^ identity_op } { // this is getting ridiculous, but we should still see the same // error message so let's just keep going let x = &0i32; let _: i32 = **&&*&x + 0; - //~^ ERROR: this operation has no effect + //~^ identity_op + let _: i32 = **&&*&x + 0; - //~^ ERROR: this operation has no effect + //~^ identity_op } } @@ -218,41 +266,49 @@ fn issue_13470() { let y = 1i32; // Removes the + 0i32 while keeping the parentheses around x + y so the cast operation works let _: u64 = (x + y + 0i32) as u64; - //~^ ERROR: this operation has no effect + //~^ identity_op + // both of the next two lines should look the same after rustfix let _: u64 = 1u64 & (x + y + 0i32) as u64; - //~^ ERROR: this operation has no effect + //~^ identity_op + // Same as above, but with extra redundant parenthesis let _: u64 = 1u64 & ((x + y) + 0i32) as u64; - //~^ ERROR: this operation has no effect + //~^ identity_op + // Should maintain parenthesis even if the surrounding expr has the same precedence let _: u64 = 5u64 + ((x + y) + 0i32) as u64; - //~^ ERROR: this operation has no effect + //~^ identity_op // If we don't maintain the parens here, the behavior changes let _ = -(x + y + 0i32); - //~^ ERROR: this operation has no effect + //~^ identity_op + // Similarly, we need to maintain parens here let _ = -(x / y / 1i32); - //~^ ERROR: this operation has no effect + //~^ identity_op + // Maintain parenthesis if the parent expr is of higher precedence let _ = 2i32 * (x + y + 0i32); - //~^ ERROR: this operation has no effect + //~^ identity_op + // Maintain parenthesis if the parent expr is the same precedence // as not all operations are associative let _ = 2i32 - (x - y - 0i32); - //~^ ERROR: this operation has no effect + //~^ identity_op + // But make sure that inner parens still exist let z = 1i32; let _ = 2 + (x + (y * z) + 0); - //~^ ERROR: this operation has no effect + //~^ identity_op + // Maintain parenthesis if the parent expr is of lower precedence // This is for clarity, and clippy will not warn on these being unnecessary let _ = 2i32 + (x * y * 1i32); - //~^ ERROR: this operation has no effect + //~^ identity_op let x = 1i16; let y = 1i16; let _: u64 = 1u64 + ((x as i32 + y as i32) as u64 + 0u64); - //~^ ERROR: this operation has no effect + //~^ identity_op } diff --git a/tests/ui/identity_op.stderr b/tests/ui/identity_op.stderr index 99a58ef2c1b5..8f9c2b603c49 100644 --- a/tests/ui/identity_op.stderr +++ b/tests/ui/identity_op.stderr @@ -8,373 +8,373 @@ LL | x + 0; = help: to override `-D warnings` add `#[allow(clippy::identity_op)]` error: this operation has no effect - --> tests/ui/identity_op.rs:46:5 + --> tests/ui/identity_op.rs:47:5 | LL | x + (1 - 1); | ^^^^^^^^^^^ help: consider reducing it to: `x` error: this operation has no effect - --> tests/ui/identity_op.rs:49:5 + --> tests/ui/identity_op.rs:51:5 | LL | 0 + x; | ^^^^^ help: consider reducing it to: `x` error: this operation has no effect - --> tests/ui/identity_op.rs:53:5 + --> tests/ui/identity_op.rs:56:5 | LL | x | (0); | ^^^^^^^ help: consider reducing it to: `x` error: this operation has no effect - --> tests/ui/identity_op.rs:57:5 + --> tests/ui/identity_op.rs:61:5 | LL | x * 1; | ^^^^^ help: consider reducing it to: `x` error: this operation has no effect - --> tests/ui/identity_op.rs:59:5 + --> tests/ui/identity_op.rs:64:5 | LL | 1 * x; | ^^^^^ help: consider reducing it to: `x` error: this operation has no effect - --> tests/ui/identity_op.rs:66:5 + --> tests/ui/identity_op.rs:72:5 | LL | -1 & x; | ^^^^^^ help: consider reducing it to: `x` error: this operation has no effect - --> tests/ui/identity_op.rs:70:5 + --> tests/ui/identity_op.rs:77:5 | LL | u & 255; | ^^^^^^^ help: consider reducing it to: `u` error: this operation has no effect - --> tests/ui/identity_op.rs:74:5 + --> tests/ui/identity_op.rs:82:5 | LL | 42 << 0; | ^^^^^^^ help: consider reducing it to: `42` error: this operation has no effect - --> tests/ui/identity_op.rs:76:5 + --> tests/ui/identity_op.rs:85:5 | LL | 1 >> 0; | ^^^^^^ help: consider reducing it to: `1` error: this operation has no effect - --> tests/ui/identity_op.rs:78:5 + --> tests/ui/identity_op.rs:88:5 | LL | 42 >> 0; | ^^^^^^^ help: consider reducing it to: `42` error: this operation has no effect - --> tests/ui/identity_op.rs:80:5 + --> tests/ui/identity_op.rs:91:5 | LL | &x >> 0; | ^^^^^^^ help: consider reducing it to: `x` error: this operation has no effect - --> tests/ui/identity_op.rs:82:5 + --> tests/ui/identity_op.rs:94:5 | LL | x >> &0; | ^^^^^^^ help: consider reducing it to: `x` error: this operation has no effect - --> tests/ui/identity_op.rs:90:5 + --> tests/ui/identity_op.rs:103:5 | LL | 2 % 3; | ^^^^^ help: consider reducing it to: `2` error: this operation has no effect - --> tests/ui/identity_op.rs:92:5 + --> tests/ui/identity_op.rs:106:5 | LL | -2 % 3; | ^^^^^^ help: consider reducing it to: `-2` error: this operation has no effect - --> tests/ui/identity_op.rs:94:5 + --> tests/ui/identity_op.rs:109:5 | LL | 2 % -3 + x; | ^^^^^^ help: consider reducing it to: `2` error: this operation has no effect - --> tests/ui/identity_op.rs:96:5 + --> tests/ui/identity_op.rs:112:5 | LL | -2 % -3 + x; | ^^^^^^^ help: consider reducing it to: `-2` error: this operation has no effect - --> tests/ui/identity_op.rs:98:9 + --> tests/ui/identity_op.rs:115:9 | LL | x + 1 % 3; | ^^^^^ help: consider reducing it to: `1` error: this operation has no effect - --> tests/ui/identity_op.rs:107:5 + --> tests/ui/identity_op.rs:125:5 | LL | 0 + if b { 1 } else { 2 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if b { 1 } else { 2 })` error: this operation has no effect - --> tests/ui/identity_op.rs:109:5 + --> tests/ui/identity_op.rs:128:5 | LL | 0 + if b { 1 } else { 2 } + if b { 3 } else { 4 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if b { 1 } else { 2 })` error: this operation has no effect - --> tests/ui/identity_op.rs:111:5 + --> tests/ui/identity_op.rs:131:5 | LL | 0 + match a { 0 => 10, _ => 20 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(match a { 0 => 10, _ => 20 })` error: this operation has no effect - --> tests/ui/identity_op.rs:113:5 + --> tests/ui/identity_op.rs:134:5 | LL | 0 + match a { 0 => 10, _ => 20 } + match a { 0 => 30, _ => 40 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(match a { 0 => 10, _ => 20 })` error: this operation has no effect - --> tests/ui/identity_op.rs:115:5 + --> tests/ui/identity_op.rs:137:5 | LL | 0 + if b { 1 } else { 2 } + match a { 0 => 30, _ => 40 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if b { 1 } else { 2 })` error: this operation has no effect - --> tests/ui/identity_op.rs:117:5 + --> tests/ui/identity_op.rs:140:5 | LL | 0 + match a { 0 => 10, _ => 20 } + if b { 3 } else { 4 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(match a { 0 => 10, _ => 20 })` error: this operation has no effect - --> tests/ui/identity_op.rs:119:5 + --> tests/ui/identity_op.rs:143:5 | LL | (if b { 1 } else { 2 }) + 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `((if b { 1 } else { 2 }))` error: this operation has no effect - --> tests/ui/identity_op.rs:122:5 + --> tests/ui/identity_op.rs:147:5 | LL | 0 + { a } + 3; | ^^^^^^^^^ help: consider reducing it to: `({ a })` error: this operation has no effect - --> tests/ui/identity_op.rs:124:5 + --> tests/ui/identity_op.rs:150:5 | LL | 0 + { a } * 2; | ^^^^^^^^^^^^^ help: consider reducing it to: `({ a } * 2)` error: this operation has no effect - --> tests/ui/identity_op.rs:126:5 + --> tests/ui/identity_op.rs:153:5 | LL | 0 + loop { let mut c = 0; if c == 10 { break c; } c += 1; } + { a * 2 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(loop { let mut c = 0; if c == 10 { break c; } c += 1; })` error: this operation has no effect - --> tests/ui/identity_op.rs:133:7 + --> tests/ui/identity_op.rs:161:7 | LL | f(1 * a + { 8 * 5 }); | ^^^^^ help: consider reducing it to: `a` error: this operation has no effect - --> tests/ui/identity_op.rs:135:7 + --> tests/ui/identity_op.rs:164:7 | LL | f(0 + if b { 1 } else { 2 } + 3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `if b { 1 } else { 2 }` error: this operation has no effect - --> tests/ui/identity_op.rs:138:20 + --> tests/ui/identity_op.rs:168:20 | LL | const _: i32 = { 2 * 4 } + 0 + 3; | ^^^^^^^^^^^^^ help: consider reducing it to: `{ 2 * 4 }` error: this operation has no effect - --> tests/ui/identity_op.rs:140:20 + --> tests/ui/identity_op.rs:171:20 | LL | const _: i32 = 0 + { 1 + 2 * 3 } + 3; | ^^^^^^^^^^^^^^^^^ help: consider reducing it to: `{ 1 + 2 * 3 }` error: this operation has no effect - --> tests/ui/identity_op.rs:143:5 + --> tests/ui/identity_op.rs:175:5 | LL | 0 + a as usize; | ^^^^^^^^^^^^^^ help: consider reducing it to: `a as usize` error: this operation has no effect - --> tests/ui/identity_op.rs:145:13 + --> tests/ui/identity_op.rs:178:13 | LL | let _ = 0 + a as usize; | ^^^^^^^^^^^^^^ help: consider reducing it to: `a as usize` error: this operation has no effect - --> tests/ui/identity_op.rs:147:5 + --> tests/ui/identity_op.rs:181:5 | LL | 0 + { a } as usize; | ^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `({ a } as usize)` error: this operation has no effect - --> tests/ui/identity_op.rs:150:9 + --> tests/ui/identity_op.rs:185:9 | LL | 2 * (0 + { a }); | ^^^^^^^^^^^ help: consider reducing it to: `{ a }` error: this operation has no effect - --> tests/ui/identity_op.rs:152:5 + --> tests/ui/identity_op.rs:188:5 | LL | 1 * ({ a } + 4); | ^^^^^^^^^^^^^^^ help: consider reducing it to: `(({ a } + 4))` error: this operation has no effect - --> tests/ui/identity_op.rs:154:5 + --> tests/ui/identity_op.rs:191:5 | LL | 1 * 1; | ^^^^^ help: consider reducing it to: `1` error: this operation has no effect - --> tests/ui/identity_op.rs:159:18 + --> tests/ui/identity_op.rs:197:18 | LL | let _: i32 = &x + 0; | ^^^^^^ help: consider reducing it to: `x` error: this operation has no effect - --> tests/ui/identity_op.rs:164:5 + --> tests/ui/identity_op.rs:203:5 | LL | 0 + if a { 1 } else { 2 } + if b { 3 } else { 5 } | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if a { 1 } else { 2 })` error: this operation has no effect - --> tests/ui/identity_op.rs:175:22 + --> tests/ui/identity_op.rs:215:22 | LL | let _: i32 = *x + 0; | ^^^^^^ help: consider reducing it to: `*x` error: this operation has no effect - --> tests/ui/identity_op.rs:177:22 + --> tests/ui/identity_op.rs:218:22 | LL | let _: i32 = x + 0; | ^^^^^ help: consider reducing it to: `*x` error: this operation has no effect - --> tests/ui/identity_op.rs:182:22 + --> tests/ui/identity_op.rs:223:22 | LL | let _: i32 = **x + 0; | ^^^^^^^ help: consider reducing it to: `**x` error: this operation has no effect - --> tests/ui/identity_op.rs:185:22 + --> tests/ui/identity_op.rs:227:22 | LL | let _: i32 = *x + 0; | ^^^^^^ help: consider reducing it to: `**x` error: this operation has no effect - --> tests/ui/identity_op.rs:191:22 + --> tests/ui/identity_op.rs:233:22 | LL | let _: i32 = ***x + 0; | ^^^^^^^^ help: consider reducing it to: `***x` error: this operation has no effect - --> tests/ui/identity_op.rs:193:22 + --> tests/ui/identity_op.rs:236:22 | LL | let _: i32 = **x + 0; | ^^^^^^^ help: consider reducing it to: `***x` error: this operation has no effect - --> tests/ui/identity_op.rs:196:22 + --> tests/ui/identity_op.rs:240:22 | LL | let _: i32 = *&x + 0; | ^^^^^^^ help: consider reducing it to: `*&x` error: this operation has no effect - --> tests/ui/identity_op.rs:198:22 + --> tests/ui/identity_op.rs:243:22 | LL | let _: i32 = **&&x + 0; | ^^^^^^^^^ help: consider reducing it to: `**&&x` error: this operation has no effect - --> tests/ui/identity_op.rs:200:22 + --> tests/ui/identity_op.rs:246:22 | LL | let _: i32 = *&*&x + 0; | ^^^^^^^^^ help: consider reducing it to: `*&*&x` error: this operation has no effect - --> tests/ui/identity_op.rs:202:22 + --> tests/ui/identity_op.rs:249:22 | LL | let _: i32 = **&&*&x + 0; | ^^^^^^^^^^^ help: consider reducing it to: `**&&*&x` error: this operation has no effect - --> tests/ui/identity_op.rs:209:22 + --> tests/ui/identity_op.rs:256:22 | LL | let _: i32 = **&&*&x + 0; | ^^^^^^^^^^^ help: consider reducing it to: `***&&*&x` error: this operation has no effect - --> tests/ui/identity_op.rs:211:22 + --> tests/ui/identity_op.rs:259:22 | LL | let _: i32 = **&&*&x + 0; | ^^^^^^^^^^^ help: consider reducing it to: `***&&*&x` error: this operation has no effect - --> tests/ui/identity_op.rs:220:18 + --> tests/ui/identity_op.rs:268:18 | LL | let _: u64 = (x + y + 0i32) as u64; | ^^^^^^^^^^^^^^ help: consider reducing it to: `(x + y)` error: this operation has no effect - --> tests/ui/identity_op.rs:223:25 + --> tests/ui/identity_op.rs:272:25 | LL | let _: u64 = 1u64 & (x + y + 0i32) as u64; | ^^^^^^^^^^^^^^ help: consider reducing it to: `(x + y)` error: this operation has no effect - --> tests/ui/identity_op.rs:226:25 + --> tests/ui/identity_op.rs:276:25 | LL | let _: u64 = 1u64 & ((x + y) + 0i32) as u64; | ^^^^^^^^^^^^^^^^ help: consider reducing it to: `((x + y))` error: this operation has no effect - --> tests/ui/identity_op.rs:229:25 + --> tests/ui/identity_op.rs:280:25 | LL | let _: u64 = 5u64 + ((x + y) + 0i32) as u64; | ^^^^^^^^^^^^^^^^ help: consider reducing it to: `((x + y))` error: this operation has no effect - --> tests/ui/identity_op.rs:233:14 + --> tests/ui/identity_op.rs:284:14 | LL | let _ = -(x + y + 0i32); | ^^^^^^^^^^^^^^ help: consider reducing it to: `(x + y)` error: this operation has no effect - --> tests/ui/identity_op.rs:236:14 + --> tests/ui/identity_op.rs:288:14 | LL | let _ = -(x / y / 1i32); | ^^^^^^^^^^^^^^ help: consider reducing it to: `(x / y)` error: this operation has no effect - --> tests/ui/identity_op.rs:239:20 + --> tests/ui/identity_op.rs:292:20 | LL | let _ = 2i32 * (x + y + 0i32); | ^^^^^^^^^^^^^^ help: consider reducing it to: `(x + y)` error: this operation has no effect - --> tests/ui/identity_op.rs:243:20 + --> tests/ui/identity_op.rs:297:20 | LL | let _ = 2i32 - (x - y - 0i32); | ^^^^^^^^^^^^^^ help: consider reducing it to: `(x - y)` error: this operation has no effect - --> tests/ui/identity_op.rs:247:17 + --> tests/ui/identity_op.rs:302:17 | LL | let _ = 2 + (x + (y * z) + 0); | ^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(x + (y * z))` error: this operation has no effect - --> tests/ui/identity_op.rs:251:20 + --> tests/ui/identity_op.rs:307:20 | LL | let _ = 2i32 + (x * y * 1i32); | ^^^^^^^^^^^^^^ help: consider reducing it to: `(x * y)` error: this operation has no effect - --> tests/ui/identity_op.rs:256:25 + --> tests/ui/identity_op.rs:312:25 | LL | let _: u64 = 1u64 + ((x as i32 + y as i32) as u64 + 0u64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `((x as i32 + y as i32) as u64)` diff --git a/tests/ui/if_let_mutex.edition2021.stderr b/tests/ui/if_let_mutex.edition2021.stderr index 984d6adbb2a4..58afd03c8c24 100644 --- a/tests/ui/if_let_mutex.edition2021.stderr +++ b/tests/ui/if_let_mutex.edition2021.stderr @@ -1,5 +1,5 @@ error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock - --> tests/ui/if_let_mutex.rs:16:5 + --> tests/ui/if_let_mutex.rs:17:5 | LL | if let Err(locked) = m.lock() { | ^ - this Mutex will remain locked for the entire `if let`-block... @@ -19,7 +19,7 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::if_let_mutex)]` error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock - --> tests/ui/if_let_mutex.rs:29:5 + --> tests/ui/if_let_mutex.rs:30:5 | LL | if let Some(locked) = m.lock().unwrap().deref() { | ^ - this Mutex will remain locked for the entire `if let`-block... @@ -37,7 +37,7 @@ LL | | }; = help: move the lock call outside of the `if let ...` expression error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock - --> tests/ui/if_let_mutex.rs:51:5 + --> tests/ui/if_let_mutex.rs:52:5 | LL | if let Ok(i) = mutex.lock() { | ^ ----- this Mutex will remain locked for the entire `if let`-block... @@ -54,7 +54,7 @@ LL | | }; = help: move the lock call outside of the `if let ...` expression error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock - --> tests/ui/if_let_mutex.rs:60:5 + --> tests/ui/if_let_mutex.rs:61:5 | LL | if let Ok(_) = m1.lock() { | ^ -- this Mutex will remain locked for the entire `if let`-block... diff --git a/tests/ui/if_let_mutex.rs b/tests/ui/if_let_mutex.rs index 80eee2939890..72058ea33ee7 100644 --- a/tests/ui/if_let_mutex.rs +++ b/tests/ui/if_let_mutex.rs @@ -3,6 +3,7 @@ //@revisions: edition2021 edition2024 //@[edition2021] edition:2021 //@[edition2024] edition:2024 +//@[edition2024] check-pass #![warn(clippy::if_let_mutex)] #![allow(clippy::redundant_pattern_matching)] @@ -62,6 +63,7 @@ fn multiple_mutexes(m1: &Mutex<()>, m2: &Mutex<()>) { } else { m1.lock(); } + //~[edition2021]^^^^^ if_let_mutex } fn main() {} diff --git a/tests/ui/if_not_else.fixed b/tests/ui/if_not_else.fixed index 11d1e13179c4..d26a15156cd8 100644 --- a/tests/ui/if_not_else.fixed +++ b/tests/ui/if_not_else.fixed @@ -12,13 +12,15 @@ fn main() { if bla() { println!("Bunny"); } else { - //~^ ERROR: unnecessary boolean `not` operation + //~^ if_not_else + println!("Bugs"); } if 4 == 5 { println!("Bunny"); } else { - //~^ ERROR: unnecessary `!=` operation + //~^ if_not_else + println!("Bugs"); } if !foo() { @@ -32,6 +34,7 @@ fn main() { if (foo() && bla()) { println!("both true"); } else { + //~^ if_not_else #[cfg(not(debug_assertions))] println!("not debug"); #[cfg(debug_assertions)] @@ -50,6 +53,7 @@ fn with_comments() { if foo() { println!("foo"); /* foo */ } else { + //~^ if_not_else /* foo is false */ println!("foo is false"); } @@ -57,6 +61,7 @@ fn with_comments() { if bla() { println!("bla"); // bla } else { + //~^ if_not_else // bla is false println!("bla"); } @@ -67,6 +72,7 @@ fn with_annotations() { if foo() { println!("foo"); /* foo */ } else { + //~^ if_not_else /* foo is false */ println!("foo is false"); } diff --git a/tests/ui/if_not_else.rs b/tests/ui/if_not_else.rs index fcc67e163e8a..6171cf116495 100644 --- a/tests/ui/if_not_else.rs +++ b/tests/ui/if_not_else.rs @@ -10,13 +10,15 @@ fn bla() -> bool { fn main() { if !bla() { - //~^ ERROR: unnecessary boolean `not` operation + //~^ if_not_else + println!("Bugs"); } else { println!("Bunny"); } if 4 != 5 { - //~^ ERROR: unnecessary `!=` operation + //~^ if_not_else + println!("Bugs"); } else { println!("Bunny"); @@ -30,6 +32,7 @@ fn main() { } if !(foo() && bla()) { + //~^ if_not_else #[cfg(not(debug_assertions))] println!("not debug"); #[cfg(debug_assertions)] @@ -48,6 +51,7 @@ fn main() { fn with_comments() { if !foo() { + //~^ if_not_else /* foo is false */ println!("foo is false"); } else { @@ -55,6 +59,7 @@ fn with_comments() { } if !bla() { + //~^ if_not_else // bla is false println!("bla"); } else { @@ -65,6 +70,7 @@ fn with_comments() { fn with_annotations() { #[cfg(debug_assertions)] if !foo() { + //~^ if_not_else /* foo is false */ println!("foo is false"); } else { diff --git a/tests/ui/if_not_else.stderr b/tests/ui/if_not_else.stderr index b01cb5af11f7..f44dd0aabc86 100644 --- a/tests/ui/if_not_else.stderr +++ b/tests/ui/if_not_else.stderr @@ -3,6 +3,7 @@ error: unnecessary boolean `not` operation | LL | / if !bla() { LL | | +LL | | LL | | println!("Bugs"); LL | | } else { LL | | println!("Bunny"); @@ -17,15 +18,17 @@ LL ~ if bla() { LL + println!("Bunny"); LL + } else { LL + +LL + LL + println!("Bugs"); LL + } | error: unnecessary `!=` operation - --> tests/ui/if_not_else.rs:18:5 + --> tests/ui/if_not_else.rs:19:5 | LL | / if 4 != 5 { LL | | +LL | | LL | | println!("Bugs"); LL | | } else { LL | | println!("Bunny"); @@ -38,17 +41,18 @@ LL ~ if 4 == 5 { LL + println!("Bunny"); LL + } else { LL + +LL + LL + println!("Bugs"); LL + } | error: unnecessary boolean `not` operation - --> tests/ui/if_not_else.rs:32:5 + --> tests/ui/if_not_else.rs:34:5 | LL | / if !(foo() && bla()) { +LL | | LL | | #[cfg(not(debug_assertions))] LL | | println!("not debug"); -LL | | #[cfg(debug_assertions)] ... | LL | | println!("both true"); LL | | } @@ -59,6 +63,7 @@ help: try LL ~ if (foo() && bla()) { LL + println!("both true"); LL + } else { +LL + LL + #[cfg(not(debug_assertions))] LL + println!("not debug"); LL + #[cfg(debug_assertions)] @@ -74,9 +79,10 @@ LL + } | error: unnecessary boolean `not` operation - --> tests/ui/if_not_else.rs:50:5 + --> tests/ui/if_not_else.rs:53:5 | LL | / if !foo() { +LL | | LL | | /* foo is false */ LL | | println!("foo is false"); LL | | } else { @@ -89,15 +95,17 @@ help: try LL ~ if foo() { LL + println!("foo"); /* foo */ LL + } else { +LL + LL + /* foo is false */ LL + println!("foo is false"); LL + } | error: unnecessary boolean `not` operation - --> tests/ui/if_not_else.rs:57:5 + --> tests/ui/if_not_else.rs:61:5 | LL | / if !bla() { +LL | | LL | | // bla is false LL | | println!("bla"); LL | | } else { @@ -110,15 +118,17 @@ help: try LL ~ if bla() { LL + println!("bla"); // bla LL + } else { +LL + LL + // bla is false LL + println!("bla"); LL + } | error: unnecessary boolean `not` operation - --> tests/ui/if_not_else.rs:67:5 + --> tests/ui/if_not_else.rs:72:5 | LL | / if !foo() { +LL | | LL | | /* foo is false */ LL | | println!("foo is false"); LL | | } else { @@ -131,6 +141,7 @@ help: try LL ~ if foo() { LL + println!("foo"); /* foo */ LL + } else { +LL + LL + /* foo is false */ LL + println!("foo is false"); LL + } diff --git a/tests/ui/if_not_else_bittest.rs b/tests/ui/if_not_else_bittest.rs index 586ce6ce1bcc..205823c5a8ab 100644 --- a/tests/ui/if_not_else_bittest.rs +++ b/tests/ui/if_not_else_bittest.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![deny(clippy::if_not_else)] fn show_permissions(flags: u32) { diff --git a/tests/ui/if_same_then_else.rs b/tests/ui/if_same_then_else.rs index d53e1383d845..6d2e63e7299a 100644 --- a/tests/ui/if_same_then_else.rs +++ b/tests/ui/if_same_then_else.rs @@ -37,7 +37,7 @@ fn if_same_then_else() { 0..=10; foo(); } - //~^^^^^^^^^^^^^^^^^ ERROR: this `if` has identical blocks + //~^^^^^^^^^^^^^^^^^ if_same_then_else if true { Foo { bar: 42 }; @@ -65,10 +65,10 @@ fn if_same_then_else() { } let _ = if true { 0.0 } else { 0.0 }; - //~^ ERROR: this `if` has identical blocks + //~^ if_same_then_else let _ = if true { -0.0 } else { -0.0 }; - //~^ ERROR: this `if` has identical blocks + //~^ if_same_then_else let _ = if true { 0.0 } else { -0.0 }; @@ -80,7 +80,7 @@ fn if_same_then_else() { } let _ = if true { 42 } else { 42 }; - //~^ ERROR: this `if` has identical blocks + //~^ if_same_then_else if true { let bar = if true { 42 } else { 43 }; @@ -97,7 +97,7 @@ fn if_same_then_else() { } bar + 1; } - //~^^^^^^^^^^^^^^^ ERROR: this `if` has identical blocks + //~^^^^^^^^^^^^^^^ if_same_then_else if true { let _ = match 42 { @@ -240,6 +240,7 @@ mod issue_11213 { } else { 0_u8.is_power_of_two() } + //~^^^^^ if_same_then_else } } diff --git a/tests/ui/if_same_then_else2.rs b/tests/ui/if_same_then_else2.rs index e23c77b08274..5b74aecdacbe 100644 --- a/tests/ui/if_same_then_else2.rs +++ b/tests/ui/if_same_then_else2.rs @@ -31,21 +31,21 @@ fn if_same_then_else2() -> Result<&'static str, ()> { } } } - //~^^^^^^^^^^^^^^^^^^^ ERROR: this `if` has identical blocks + //~^^^^^^^^^^^^^^^^^^^ if_same_then_else if true { if let Some(a) = Some(42) {} } else { if let Some(a) = Some(42) {} } - //~^^^^^ ERROR: this `if` has identical blocks + //~^^^^^ if_same_then_else if true { if let (1, .., 3) = (1, 2, 3) {} } else { if let (1, .., 3) = (1, 2, 3) {} } - //~^^^^^ ERROR: this `if` has identical blocks + //~^^^^^ if_same_then_else if true { if let (1, .., 3) = (1, 2, 3) {} @@ -91,14 +91,14 @@ fn if_same_then_else2() -> Result<&'static str, ()> { // Same NaNs let _ = if true { f32::NAN } else { f32::NAN }; - //~^ ERROR: this `if` has identical blocks + //~^ if_same_then_else if true { Ok("foo")?; } else { Ok("foo")?; } - //~^^^^^ ERROR: this `if` has identical blocks + //~^^^^^ if_same_then_else if true { let foo = ""; @@ -124,7 +124,7 @@ fn if_same_then_else2() -> Result<&'static str, ()> { let foo = ""; return Ok(&foo[0..]); } - //~^^^^^^^ ERROR: this `if` has identical blocks + //~^^^^^^^ if_same_then_else // False positive `if_same_then_else`: `let (x, y)` vs. `let (y, x)`; see issue #3559. if true { diff --git a/tests/ui/if_then_some_else_none.fixed b/tests/ui/if_then_some_else_none.fixed index 1f47dddcbc40..f774608712d1 100644 --- a/tests/ui/if_then_some_else_none.fixed +++ b/tests/ui/if_then_some_else_none.fixed @@ -11,12 +11,12 @@ fn main() { // Should issue an error. Binary expression `o < 32` should be parenthesized. let x = Some(5); let _ = x.and_then(|o| (o < 32).then_some(o)); - //~^ ERROR: this could be simplified with `bool::then_some` + //~^ if_then_some_else_none // Should issue an error. Unary expression `!x` should be parenthesized. let x = true; let _ = (!x).then_some(0); - //~^ ERROR: this could be simplified with `bool::then_some` + //~^ if_then_some_else_none // Should not issue an error since the `else` block has a statement besides `None`. let _ = if foo() { @@ -115,6 +115,7 @@ fn issue11394(b: bool, v: Result<(), ()>) -> Result<(), ()> { fn issue13407(s: &str) -> Option { (s == "1").then(|| true) + //~^ if_then_some_else_none } const fn issue12103(x: u32) -> Option { diff --git a/tests/ui/if_then_some_else_none.rs b/tests/ui/if_then_some_else_none.rs index 499f008fb876..8b8ff0a6ea00 100644 --- a/tests/ui/if_then_some_else_none.rs +++ b/tests/ui/if_then_some_else_none.rs @@ -4,7 +4,8 @@ fn main() { // Should issue an error. let _ = if foo() { - //~^ ERROR: this could be simplified with `bool::then` + //~^ if_then_some_else_none + println!("true!"); Some("foo") } else { @@ -13,7 +14,8 @@ fn main() { // Should issue an error when macros are used. let _ = if matches!(true, true) { - //~^ ERROR: this could be simplified with `bool::then` + //~^ if_then_some_else_none + println!("true!"); Some(matches!(true, false)) } else { @@ -23,12 +25,12 @@ fn main() { // Should issue an error. Binary expression `o < 32` should be parenthesized. let x = Some(5); let _ = x.and_then(|o| if o < 32 { Some(o) } else { None }); - //~^ ERROR: this could be simplified with `bool::then_some` + //~^ if_then_some_else_none // Should issue an error. Unary expression `!x` should be parenthesized. let x = true; let _ = if !x { Some(0) } else { None }; - //~^ ERROR: this could be simplified with `bool::then_some` + //~^ if_then_some_else_none // Should not issue an error since the `else` block has a statement besides `None`. let _ = if foo() { @@ -84,7 +86,8 @@ fn _msrv_1_49() { #[clippy::msrv = "1.50"] fn _msrv_1_50() { let _ = if foo() { - //~^ ERROR: this could be simplified with `bool::then` + //~^ if_then_some_else_none + println!("true!"); Some(150) } else { @@ -133,6 +136,7 @@ fn issue11394(b: bool, v: Result<(), ()>) -> Result<(), ()> { fn issue13407(s: &str) -> Option { if s == "1" { Some(true) } else { None } + //~^ if_then_some_else_none } const fn issue12103(x: u32) -> Option { diff --git a/tests/ui/if_then_some_else_none.stderr b/tests/ui/if_then_some_else_none.stderr index e7bc66b3ee88..71285574ef24 100644 --- a/tests/ui/if_then_some_else_none.stderr +++ b/tests/ui/if_then_some_else_none.stderr @@ -4,9 +4,9 @@ error: this could be simplified with `bool::then` LL | let _ = if foo() { | _____________^ LL | | +LL | | LL | | println!("true!"); -LL | | Some("foo") -LL | | } else { +... | LL | | None LL | | }; | |_____^ help: try: `foo().then(|| { println!("true!"); "foo" })` @@ -15,45 +15,45 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::if_then_some_else_none)]` error: this could be simplified with `bool::then` - --> tests/ui/if_then_some_else_none.rs:15:13 + --> tests/ui/if_then_some_else_none.rs:16:13 | LL | let _ = if matches!(true, true) { | _____________^ LL | | +LL | | LL | | println!("true!"); -LL | | Some(matches!(true, false)) -LL | | } else { +... | LL | | None LL | | }; | |_____^ help: try: `matches!(true, true).then(|| { println!("true!"); matches!(true, false) })` error: this could be simplified with `bool::then_some` - --> tests/ui/if_then_some_else_none.rs:25:28 + --> tests/ui/if_then_some_else_none.rs:27:28 | LL | let _ = x.and_then(|o| if o < 32 { Some(o) } else { None }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(o < 32).then_some(o)` error: this could be simplified with `bool::then_some` - --> tests/ui/if_then_some_else_none.rs:30:13 + --> tests/ui/if_then_some_else_none.rs:32:13 | LL | let _ = if !x { Some(0) } else { None }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(!x).then_some(0)` error: this could be simplified with `bool::then` - --> tests/ui/if_then_some_else_none.rs:86:13 + --> tests/ui/if_then_some_else_none.rs:88:13 | LL | let _ = if foo() { | _____________^ LL | | +LL | | LL | | println!("true!"); -LL | | Some(150) -LL | | } else { +... | LL | | None LL | | }; | |_____^ help: try: `foo().then(|| { println!("true!"); 150 })` error: this could be simplified with `bool::then` - --> tests/ui/if_then_some_else_none.rs:135:5 + --> tests/ui/if_then_some_else_none.rs:138:5 | LL | if s == "1" { Some(true) } else { None } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(s == "1").then(|| true)` diff --git a/tests/ui/ifs_same_cond.rs b/tests/ui/ifs_same_cond.rs index ad77346b75f2..6ecb7cb1eba9 100644 --- a/tests/ui/ifs_same_cond.rs +++ b/tests/ui/ifs_same_cond.rs @@ -12,18 +12,18 @@ fn ifs_same_cond() { if b { } else if b { - //~^ ERROR: this `if` has the same condition as a previous `if` + //~^ ifs_same_cond } if a == 1 { } else if a == 1 { - //~^ ERROR: this `if` has the same condition as a previous `if` + //~^ ifs_same_cond } if 2 * a == 1 { } else if 2 * a == 2 { } else if 2 * a == 1 { - //~^ ERROR: this `if` has the same condition as a previous `if` + //~^ ifs_same_cond } else if a == 1 { } @@ -56,7 +56,8 @@ fn issue10272() { let a = String::from("ha"); if a.contains("ah") { } else if a.contains("ah") { - //~^ ERROR: this `if` has the same condition as a previous `if` + //~^ ifs_same_cond + // Trigger this lint } else if a.contains("ha") { } else if a == "wow" { diff --git a/tests/ui/impl.rs b/tests/ui/impl.rs index 7f452cb46e06..1b9e4a5cdee1 100644 --- a/tests/ui/impl.rs +++ b/tests/ui/impl.rs @@ -8,7 +8,8 @@ impl MyStruct { } impl MyStruct { - //~^ ERROR: multiple implementations of this structure + //~^ multiple_inherent_impl + fn second() {} } @@ -23,7 +24,8 @@ mod submod { } impl super::MyStruct { - //~^ ERROR: multiple implementations of this structure + //~^ multiple_inherent_impl + fn third() {} } } @@ -44,7 +46,8 @@ impl WithArgs { fn f2() {} } impl WithArgs { - //~^ ERROR: multiple implementations of this structure + //~^ multiple_inherent_impl + fn f3() {} } @@ -66,6 +69,6 @@ impl OneAllowedImpl {} #[allow(clippy::multiple_inherent_impl)] impl OneAllowedImpl {} impl OneAllowedImpl {} // Lint, only one of the three blocks is allowed. -//~^ ERROR: multiple implementations of this structure +//~^ multiple_inherent_impl fn main() {} diff --git a/tests/ui/impl.stderr b/tests/ui/impl.stderr index bb906957a0d3..355927b78253 100644 --- a/tests/ui/impl.stderr +++ b/tests/ui/impl.stderr @@ -3,6 +3,7 @@ error: multiple implementations of this structure | LL | / impl MyStruct { LL | | +LL | | LL | | fn second() {} LL | | } | |_^ @@ -18,10 +19,11 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::multiple_inherent_impl)]` error: multiple implementations of this structure - --> tests/ui/impl.rs:25:5 + --> tests/ui/impl.rs:26:5 | LL | / impl super::MyStruct { LL | | +LL | | LL | | fn third() {} LL | | } | |_____^ @@ -35,16 +37,17 @@ LL | | } | |_^ error: multiple implementations of this structure - --> tests/ui/impl.rs:46:1 + --> tests/ui/impl.rs:48:1 | LL | / impl WithArgs { LL | | +LL | | LL | | fn f3() {} LL | | } | |_^ | note: first implementation here - --> tests/ui/impl.rs:43:1 + --> tests/ui/impl.rs:45:1 | LL | / impl WithArgs { LL | | fn f2() {} @@ -52,13 +55,13 @@ LL | | } | |_^ error: multiple implementations of this structure - --> tests/ui/impl.rs:68:1 + --> tests/ui/impl.rs:71:1 | LL | impl OneAllowedImpl {} // Lint, only one of the three blocks is allowed. | ^^^^^^^^^^^^^^^^^^^^^^ | note: first implementation here - --> tests/ui/impl.rs:65:1 + --> tests/ui/impl.rs:68:1 | LL | impl OneAllowedImpl {} | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/impl_trait_in_params.rs b/tests/ui/impl_trait_in_params.rs index a6251a370d1d..2039f6339a87 100644 --- a/tests/ui/impl_trait_in_params.rs +++ b/tests/ui/impl_trait_in_params.rs @@ -7,9 +7,10 @@ pub trait AnotherTrait {} // Should warn pub fn a(_: impl Trait) {} -//~^ ERROR: `impl Trait` used as a function parameter +//~^ impl_trait_in_params + pub fn c(_: C, _: impl Trait) {} -//~^ ERROR: `impl Trait` used as a function parameter +//~^ impl_trait_in_params // Shouldn't warn @@ -33,10 +34,12 @@ trait Private { struct S; impl S { - pub fn h(_: impl Trait) {} //~ ERROR: `impl Trait` used as a function parameter + pub fn h(_: impl Trait) {} + //~^ impl_trait_in_params fn i(_: impl Trait) {} pub fn j(_: J) {} - pub fn k>(_: K, _: impl AnotherTrait) {} //~ ERROR: `impl Trait` used as a function parameter + pub fn k>(_: K, _: impl AnotherTrait) {} + //~^ impl_trait_in_params } // Trying with traits diff --git a/tests/ui/impl_trait_in_params.stderr b/tests/ui/impl_trait_in_params.stderr index 0ec0a34ea8db..c904d5843c93 100644 --- a/tests/ui/impl_trait_in_params.stderr +++ b/tests/ui/impl_trait_in_params.stderr @@ -12,7 +12,7 @@ LL | pub fn a<{ /* Generic name */ }: Trait>(_: impl Trait) {} | +++++++++++++++++++++++++++++++ error: `impl Trait` used as a function parameter - --> tests/ui/impl_trait_in_params.rs:11:29 + --> tests/ui/impl_trait_in_params.rs:12:29 | LL | pub fn c(_: C, _: impl Trait) {} | ^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | pub fn c(_: C, _: impl Trait) {} | +++++++++++++++++++++++++++++++ error: `impl Trait` used as a function parameter - --> tests/ui/impl_trait_in_params.rs:36:17 + --> tests/ui/impl_trait_in_params.rs:37:17 | LL | pub fn h(_: impl Trait) {} | ^^^^^^^^^^ @@ -34,7 +34,7 @@ LL | pub fn h<{ /* Generic name */ }: Trait>(_: impl Trait) {} | +++++++++++++++++++++++++++++++ error: `impl Trait` used as a function parameter - --> tests/ui/impl_trait_in_params.rs:39:45 + --> tests/ui/impl_trait_in_params.rs:41:45 | LL | pub fn k>(_: K, _: impl AnotherTrait) {} | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/implicit_clone.fixed b/tests/ui/implicit_clone.fixed index 98556b4dd303..d60d1cb0ec04 100644 --- a/tests/ui/implicit_clone.fixed +++ b/tests/ui/implicit_clone.fixed @@ -63,12 +63,15 @@ fn main() { let vec = vec![5]; let _ = return_owned_from_slice(&vec); let _ = vec.clone(); + //~^ implicit_clone let _ = vec.clone(); + //~^ implicit_clone let vec_ref = &vec; let _ = return_owned_from_slice(vec_ref); let _ = vec_ref.to_owned(); let _ = vec_ref.clone(); + //~^ implicit_clone // we expect no lint for this let _ = weird::to_vec(&vec); @@ -81,10 +84,12 @@ fn main() { let str = "hello world".to_string(); let _ = str.clone(); + //~^ implicit_clone // testing w/ an arbitrary type let kitten = Kitten {}; let _ = kitten.clone(); + //~^ implicit_clone let _ = own_same_from_ref(&kitten); // this shouldn't lint let _ = kitten.to_vec(); @@ -95,11 +100,15 @@ fn main() { let pathbuf = PathBuf::new(); let _ = pathbuf.clone(); + //~^ implicit_clone let _ = pathbuf.clone(); + //~^ implicit_clone let os_string = OsString::from("foo"); let _ = os_string.clone(); + //~^ implicit_clone let _ = os_string.clone(); + //~^ implicit_clone // we expect no lints for this let os_str = OsStr::new("foo"); @@ -111,9 +120,11 @@ fn main() { let pathbuf_ref = &pathbuf_ref; let _ = pathbuf_ref.to_owned(); // Don't lint. Returns `&PathBuf` let _ = (*pathbuf_ref).clone(); + //~^ implicit_clone let pathbuf_ref = &pathbuf_ref; let _ = pathbuf_ref.to_owned(); // Don't lint. Returns `&&PathBuf` let _ = (**pathbuf_ref).clone(); + //~^ implicit_clone struct NoClone; impl ToOwned for NoClone { diff --git a/tests/ui/implicit_clone.rs b/tests/ui/implicit_clone.rs index a064bd23a338..b96828f28c82 100644 --- a/tests/ui/implicit_clone.rs +++ b/tests/ui/implicit_clone.rs @@ -63,12 +63,15 @@ fn main() { let vec = vec![5]; let _ = return_owned_from_slice(&vec); let _ = vec.to_owned(); + //~^ implicit_clone let _ = vec.to_vec(); + //~^ implicit_clone let vec_ref = &vec; let _ = return_owned_from_slice(vec_ref); let _ = vec_ref.to_owned(); let _ = vec_ref.to_vec(); + //~^ implicit_clone // we expect no lint for this let _ = weird::to_vec(&vec); @@ -81,10 +84,12 @@ fn main() { let str = "hello world".to_string(); let _ = str.to_owned(); + //~^ implicit_clone // testing w/ an arbitrary type let kitten = Kitten {}; let _ = kitten.to_owned(); + //~^ implicit_clone let _ = own_same_from_ref(&kitten); // this shouldn't lint let _ = kitten.to_vec(); @@ -95,11 +100,15 @@ fn main() { let pathbuf = PathBuf::new(); let _ = pathbuf.to_owned(); + //~^ implicit_clone let _ = pathbuf.to_path_buf(); + //~^ implicit_clone let os_string = OsString::from("foo"); let _ = os_string.to_owned(); + //~^ implicit_clone let _ = os_string.to_os_string(); + //~^ implicit_clone // we expect no lints for this let os_str = OsStr::new("foo"); @@ -111,9 +120,11 @@ fn main() { let pathbuf_ref = &pathbuf_ref; let _ = pathbuf_ref.to_owned(); // Don't lint. Returns `&PathBuf` let _ = pathbuf_ref.to_path_buf(); + //~^ implicit_clone let pathbuf_ref = &pathbuf_ref; let _ = pathbuf_ref.to_owned(); // Don't lint. Returns `&&PathBuf` let _ = pathbuf_ref.to_path_buf(); + //~^ implicit_clone struct NoClone; impl ToOwned for NoClone { diff --git a/tests/ui/implicit_clone.stderr b/tests/ui/implicit_clone.stderr index 31c212eba2c8..1eb6ff1fe429 100644 --- a/tests/ui/implicit_clone.stderr +++ b/tests/ui/implicit_clone.stderr @@ -8,61 +8,61 @@ LL | let _ = vec.to_owned(); = help: to override `-D warnings` add `#[allow(clippy::implicit_clone)]` error: implicitly cloning a `Vec` by calling `to_vec` on its dereferenced type - --> tests/ui/implicit_clone.rs:66:13 + --> tests/ui/implicit_clone.rs:67:13 | LL | let _ = vec.to_vec(); | ^^^^^^^^^^^^ help: consider using: `vec.clone()` error: implicitly cloning a `Vec` by calling `to_vec` on its dereferenced type - --> tests/ui/implicit_clone.rs:71:13 + --> tests/ui/implicit_clone.rs:73:13 | LL | let _ = vec_ref.to_vec(); | ^^^^^^^^^^^^^^^^ help: consider using: `vec_ref.clone()` error: implicitly cloning a `String` by calling `to_owned` on its dereferenced type - --> tests/ui/implicit_clone.rs:83:13 + --> tests/ui/implicit_clone.rs:86:13 | LL | let _ = str.to_owned(); | ^^^^^^^^^^^^^^ help: consider using: `str.clone()` error: implicitly cloning a `Kitten` by calling `to_owned` on its dereferenced type - --> tests/ui/implicit_clone.rs:87:13 + --> tests/ui/implicit_clone.rs:91:13 | LL | let _ = kitten.to_owned(); | ^^^^^^^^^^^^^^^^^ help: consider using: `kitten.clone()` error: implicitly cloning a `PathBuf` by calling `to_owned` on its dereferenced type - --> tests/ui/implicit_clone.rs:97:13 + --> tests/ui/implicit_clone.rs:102:13 | LL | let _ = pathbuf.to_owned(); | ^^^^^^^^^^^^^^^^^^ help: consider using: `pathbuf.clone()` error: implicitly cloning a `PathBuf` by calling `to_path_buf` on its dereferenced type - --> tests/ui/implicit_clone.rs:98:13 + --> tests/ui/implicit_clone.rs:104:13 | LL | let _ = pathbuf.to_path_buf(); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `pathbuf.clone()` error: implicitly cloning a `OsString` by calling `to_owned` on its dereferenced type - --> tests/ui/implicit_clone.rs:101:13 + --> tests/ui/implicit_clone.rs:108:13 | LL | let _ = os_string.to_owned(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `os_string.clone()` error: implicitly cloning a `OsString` by calling `to_os_string` on its dereferenced type - --> tests/ui/implicit_clone.rs:102:13 + --> tests/ui/implicit_clone.rs:110:13 | LL | let _ = os_string.to_os_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `os_string.clone()` error: implicitly cloning a `PathBuf` by calling `to_path_buf` on its dereferenced type - --> tests/ui/implicit_clone.rs:113:13 + --> tests/ui/implicit_clone.rs:122:13 | LL | let _ = pathbuf_ref.to_path_buf(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(*pathbuf_ref).clone()` error: implicitly cloning a `PathBuf` by calling `to_path_buf` on its dereferenced type - --> tests/ui/implicit_clone.rs:116:13 + --> tests/ui/implicit_clone.rs:126:13 | LL | let _ = pathbuf_ref.to_path_buf(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(**pathbuf_ref).clone()` diff --git a/tests/ui/implicit_hasher.fixed b/tests/ui/implicit_hasher.fixed index 971746ae95d7..bea5b9afc43a 100644 --- a/tests/ui/implicit_hasher.fixed +++ b/tests/ui/implicit_hasher.fixed @@ -13,6 +13,7 @@ pub trait Foo: Sized { } impl Foo for HashMap { + //~^ implicit_hasher fn make() -> (Self, Self) { // OK, don't suggest to modify these let _: HashMap = HashMap::new(); @@ -22,11 +23,13 @@ impl Foo for HashMap } } impl Foo for (HashMap,) { + //~^ implicit_hasher fn make() -> (Self, Self) { ((HashMap::default(),), (HashMap::with_capacity_and_hasher(10, Default::default()),)) } } impl Foo for HashMap { + //~^ implicit_hasher fn make() -> (Self, Self) { (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) } @@ -44,11 +47,13 @@ impl Foo for HashMap { } impl Foo for HashSet { + //~^ implicit_hasher fn make() -> (Self, Self) { (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) } } impl Foo for HashSet { + //~^ implicit_hasher fn make() -> (Self, Self) { (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) } @@ -66,14 +71,17 @@ impl Foo for HashSet { } pub fn map(map: &mut HashMap) {} +//~^ implicit_hasher pub fn set(set: &mut HashSet) {} +//~^ implicit_hasher #[inline_macros] pub mod gen_ { use super::*; inline! { impl Foo for HashMap { + //~^ implicit_hasher fn make() -> (Self, Self) { (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) } @@ -98,5 +106,6 @@ external! { // #7712 pub async fn election_vote(_data: HashMap) {} +//~^ implicit_hasher fn main() {} diff --git a/tests/ui/implicit_hasher.rs b/tests/ui/implicit_hasher.rs index b34aa1f81374..afdf4da61650 100644 --- a/tests/ui/implicit_hasher.rs +++ b/tests/ui/implicit_hasher.rs @@ -13,6 +13,7 @@ pub trait Foo: Sized { } impl Foo for HashMap { + //~^ implicit_hasher fn make() -> (Self, Self) { // OK, don't suggest to modify these let _: HashMap = HashMap::new(); @@ -22,11 +23,13 @@ impl Foo for HashMap { } } impl Foo for (HashMap,) { + //~^ implicit_hasher fn make() -> (Self, Self) { ((HashMap::new(),), (HashMap::with_capacity(10),)) } } impl Foo for HashMap { + //~^ implicit_hasher fn make() -> (Self, Self) { (HashMap::new(), HashMap::with_capacity(10)) } @@ -44,11 +47,13 @@ impl Foo for HashMap { } impl Foo for HashSet { + //~^ implicit_hasher fn make() -> (Self, Self) { (HashSet::new(), HashSet::with_capacity(10)) } } impl Foo for HashSet { + //~^ implicit_hasher fn make() -> (Self, Self) { (HashSet::new(), HashSet::with_capacity(10)) } @@ -66,14 +71,17 @@ impl Foo for HashSet { } pub fn map(map: &mut HashMap) {} +//~^ implicit_hasher pub fn set(set: &mut HashSet) {} +//~^ implicit_hasher #[inline_macros] pub mod gen_ { use super::*; inline! { impl Foo for HashMap { + //~^ implicit_hasher fn make() -> (Self, Self) { (HashMap::new(), HashMap::with_capacity(10)) } @@ -98,5 +106,6 @@ external! { // #7712 pub async fn election_vote(_data: HashMap) {} +//~^ implicit_hasher fn main() {} diff --git a/tests/ui/implicit_hasher.stderr b/tests/ui/implicit_hasher.stderr index 01d08a1bd9b2..6735998ed654 100644 --- a/tests/ui/implicit_hasher.stderr +++ b/tests/ui/implicit_hasher.stderr @@ -12,14 +12,14 @@ LL | #![deny(clippy::implicit_hasher)] help: add a type parameter for `BuildHasher` | LL ~ impl Foo for HashMap { -LL | fn make() -> (Self, Self) { +LL | ... LL | LL ~ (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) | error: impl for `HashMap` should be generalized over different hashers - --> tests/ui/implicit_hasher.rs:24:36 + --> tests/ui/implicit_hasher.rs:25:36 | LL | impl Foo for (HashMap,) { | ^^^^^^^^^^^^^ @@ -27,12 +27,13 @@ LL | impl Foo for (HashMap,) { help: add a type parameter for `BuildHasher` | LL ~ impl Foo for (HashMap,) { +LL | LL | fn make() -> (Self, Self) { LL ~ ((HashMap::default(),), (HashMap::with_capacity_and_hasher(10, Default::default()),)) | error: impl for `HashMap` should be generalized over different hashers - --> tests/ui/implicit_hasher.rs:29:19 + --> tests/ui/implicit_hasher.rs:31:19 | LL | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -40,12 +41,13 @@ LL | impl Foo for HashMap { help: add a type parameter for `BuildHasher` | LL ~ impl Foo for HashMap { +LL | LL | fn make() -> (Self, Self) { LL ~ (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) | error: impl for `HashSet` should be generalized over different hashers - --> tests/ui/implicit_hasher.rs:46:32 + --> tests/ui/implicit_hasher.rs:49:32 | LL | impl Foo for HashSet { | ^^^^^^^^^^ @@ -53,12 +55,13 @@ LL | impl Foo for HashSet { help: add a type parameter for `BuildHasher` | LL ~ impl Foo for HashSet { +LL | LL | fn make() -> (Self, Self) { LL ~ (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) | error: impl for `HashSet` should be generalized over different hashers - --> tests/ui/implicit_hasher.rs:51:19 + --> tests/ui/implicit_hasher.rs:55:19 | LL | impl Foo for HashSet { | ^^^^^^^^^^^^^^^ @@ -66,12 +69,13 @@ LL | impl Foo for HashSet { help: add a type parameter for `BuildHasher` | LL ~ impl Foo for HashSet { +LL | LL | fn make() -> (Self, Self) { LL ~ (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default())) | error: parameter of type `HashMap` should be generalized over different hashers - --> tests/ui/implicit_hasher.rs:68:22 + --> tests/ui/implicit_hasher.rs:73:22 | LL | pub fn map(map: &mut HashMap) {} | ^^^^^^^^^^^^^^^^^ @@ -82,7 +86,7 @@ LL | pub fn map(map: &mut HashMap) {} | +++++++++++++++++++++++++++++ +++ error: parameter of type `HashSet` should be generalized over different hashers - --> tests/ui/implicit_hasher.rs:70:22 + --> tests/ui/implicit_hasher.rs:76:22 | LL | pub fn set(set: &mut HashSet) {} | ^^^^^^^^^^^^ @@ -93,7 +97,7 @@ LL | pub fn set(set: &mut HashSet) {} | +++++++++++++++++++++++++++++ +++ error: impl for `HashMap` should be generalized over different hashers - --> tests/ui/implicit_hasher.rs:76:43 + --> tests/ui/implicit_hasher.rs:83:43 | LL | impl Foo for HashMap { | ^^^^^^^^^^^^^ @@ -102,12 +106,13 @@ LL | impl Foo for HashMap { help: add a type parameter for `BuildHasher` | LL ~ impl Foo for HashMap { +LL | LL | fn make() -> (Self, Self) { LL ~ (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default())) | error: parameter of type `HashMap` should be generalized over different hashers - --> tests/ui/implicit_hasher.rs:100:35 + --> tests/ui/implicit_hasher.rs:108:35 | LL | pub async fn election_vote(_data: HashMap) {} | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/implicit_return.fixed b/tests/ui/implicit_return.fixed index 56fe29b4e677..1cb639b60a9a 100644 --- a/tests/ui/implicit_return.fixed +++ b/tests/ui/implicit_return.fixed @@ -13,17 +13,22 @@ fn test_end_of_fn() -> bool { } return true + //~^ implicit_return } fn test_if_block() -> bool { if true { return true } else { return false } + //~^ implicit_return + //~| implicit_return } #[rustfmt::skip] fn test_match(x: bool) -> bool { match x { true => return false, + //~^ implicit_return false => { return true }, + //~^ implicit_return } } @@ -37,6 +42,7 @@ fn test_match_with_unreachable(x: bool) -> bool { fn test_loop() -> bool { loop { return true; + //~^ implicit_return } } @@ -44,6 +50,7 @@ fn test_loop_with_block() -> bool { loop { { return true; + //~^ implicit_return } } } @@ -52,6 +59,7 @@ fn test_loop_with_nests() -> bool { loop { if true { return true; + //~^ implicit_return } else { let _ = true; } @@ -70,7 +78,9 @@ fn test_loop_with_if_let() -> bool { fn test_closure() { #[rustfmt::skip] let _ = || { return true }; + //~^ implicit_return let _ = || return true; + //~^ implicit_return } fn test_panic() -> bool { @@ -79,6 +89,7 @@ fn test_panic() -> bool { fn test_return_macro() -> String { return format!("test {}", "test") + //~^ implicit_return } fn macro_branch_test() -> bool { @@ -88,17 +99,20 @@ fn macro_branch_test() -> bool { }; } return m!(true, false) + //~^ implicit_return } fn loop_test() -> bool { 'outer: loop { if true { return true; + //~^ implicit_return } let _ = loop { if false { return false; + //~^ implicit_return } if true { break true; @@ -117,6 +131,7 @@ fn loop_macro_test() -> bool { m!(true); } } +//~^^^^ implicit_return fn divergent_test() -> bool { fn diverge() -> ! { @@ -128,6 +143,7 @@ fn divergent_test() -> bool { // issue #6940 async fn foo() -> bool { return true + //~^ implicit_return } fn main() {} diff --git a/tests/ui/implicit_return.rs b/tests/ui/implicit_return.rs index f066ce20cfd1..99d75e4987e4 100644 --- a/tests/ui/implicit_return.rs +++ b/tests/ui/implicit_return.rs @@ -13,17 +13,22 @@ fn test_end_of_fn() -> bool { } true + //~^ implicit_return } fn test_if_block() -> bool { if true { true } else { false } + //~^ implicit_return + //~| implicit_return } #[rustfmt::skip] fn test_match(x: bool) -> bool { match x { true => false, + //~^ implicit_return false => { true }, + //~^ implicit_return } } @@ -37,6 +42,7 @@ fn test_match_with_unreachable(x: bool) -> bool { fn test_loop() -> bool { loop { break true; + //~^ implicit_return } } @@ -44,6 +50,7 @@ fn test_loop_with_block() -> bool { loop { { break true; + //~^ implicit_return } } } @@ -52,6 +59,7 @@ fn test_loop_with_nests() -> bool { loop { if true { break true; + //~^ implicit_return } else { let _ = true; } @@ -70,7 +78,9 @@ fn test_loop_with_if_let() -> bool { fn test_closure() { #[rustfmt::skip] let _ = || { true }; + //~^ implicit_return let _ = || true; + //~^ implicit_return } fn test_panic() -> bool { @@ -79,6 +89,7 @@ fn test_panic() -> bool { fn test_return_macro() -> String { format!("test {}", "test") + //~^ implicit_return } fn macro_branch_test() -> bool { @@ -88,17 +99,20 @@ fn macro_branch_test() -> bool { }; } m!(true, false) + //~^ implicit_return } fn loop_test() -> bool { 'outer: loop { if true { break true; + //~^ implicit_return } let _ = loop { if false { break 'outer false; + //~^ implicit_return } if true { break true; @@ -117,6 +131,7 @@ fn loop_macro_test() -> bool { m!(true); } } +//~^^^^ implicit_return fn divergent_test() -> bool { fn diverge() -> ! { @@ -128,6 +143,7 @@ fn divergent_test() -> bool { // issue #6940 async fn foo() -> bool { true + //~^ implicit_return } fn main() {} diff --git a/tests/ui/implicit_return.stderr b/tests/ui/implicit_return.stderr index 936a779fa747..02044df47ac3 100644 --- a/tests/ui/implicit_return.stderr +++ b/tests/ui/implicit_return.stderr @@ -12,7 +12,7 @@ LL | return true | ++++++ error: missing `return` statement - --> tests/ui/implicit_return.rs:19:15 + --> tests/ui/implicit_return.rs:20:15 | LL | if true { true } else { false } | ^^^^ @@ -23,7 +23,7 @@ LL | if true { return true } else { false } | ++++++ error: missing `return` statement - --> tests/ui/implicit_return.rs:19:29 + --> tests/ui/implicit_return.rs:20:29 | LL | if true { true } else { false } | ^^^^^ @@ -34,7 +34,7 @@ LL | if true { true } else { return false } | ++++++ error: missing `return` statement - --> tests/ui/implicit_return.rs:25:17 + --> tests/ui/implicit_return.rs:28:17 | LL | true => false, | ^^^^^ @@ -45,7 +45,7 @@ LL | true => return false, | ++++++ error: missing `return` statement - --> tests/ui/implicit_return.rs:26:20 + --> tests/ui/implicit_return.rs:30:20 | LL | false => { true }, | ^^^^ @@ -56,7 +56,7 @@ LL | false => { return true }, | ++++++ error: missing `return` statement - --> tests/ui/implicit_return.rs:39:9 + --> tests/ui/implicit_return.rs:44:9 | LL | break true; | ^^^^^^^^^^ @@ -68,7 +68,7 @@ LL + return true; | error: missing `return` statement - --> tests/ui/implicit_return.rs:46:13 + --> tests/ui/implicit_return.rs:52:13 | LL | break true; | ^^^^^^^^^^ @@ -80,7 +80,7 @@ LL + return true; | error: missing `return` statement - --> tests/ui/implicit_return.rs:54:13 + --> tests/ui/implicit_return.rs:61:13 | LL | break true; | ^^^^^^^^^^ @@ -92,7 +92,7 @@ LL + return true; | error: missing `return` statement - --> tests/ui/implicit_return.rs:72:18 + --> tests/ui/implicit_return.rs:80:18 | LL | let _ = || { true }; | ^^^^ @@ -103,7 +103,7 @@ LL | let _ = || { return true }; | ++++++ error: missing `return` statement - --> tests/ui/implicit_return.rs:73:16 + --> tests/ui/implicit_return.rs:82:16 | LL | let _ = || true; | ^^^^ @@ -114,7 +114,7 @@ LL | let _ = || return true; | ++++++ error: missing `return` statement - --> tests/ui/implicit_return.rs:81:5 + --> tests/ui/implicit_return.rs:91:5 | LL | format!("test {}", "test") | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -125,7 +125,7 @@ LL | return format!("test {}", "test") | ++++++ error: missing `return` statement - --> tests/ui/implicit_return.rs:90:5 + --> tests/ui/implicit_return.rs:101:5 | LL | m!(true, false) | ^^^^^^^^^^^^^^^ @@ -136,7 +136,7 @@ LL | return m!(true, false) | ++++++ error: missing `return` statement - --> tests/ui/implicit_return.rs:96:13 + --> tests/ui/implicit_return.rs:108:13 | LL | break true; | ^^^^^^^^^^ @@ -148,7 +148,7 @@ LL + return true; | error: missing `return` statement - --> tests/ui/implicit_return.rs:101:17 + --> tests/ui/implicit_return.rs:114:17 | LL | break 'outer false; | ^^^^^^^^^^^^^^^^^^ @@ -160,7 +160,7 @@ LL + return false; | error: missing `return` statement - --> tests/ui/implicit_return.rs:116:5 + --> tests/ui/implicit_return.rs:130:5 | LL | / loop { LL | | m!(true); @@ -173,7 +173,7 @@ LL | return loop { | ++++++ error: missing `return` statement - --> tests/ui/implicit_return.rs:130:5 + --> tests/ui/implicit_return.rs:145:5 | LL | true | ^^^^ diff --git a/tests/ui/implicit_saturating_add.rs b/tests/ui/implicit_saturating_add.rs index 94513f34c262..d9d035bdcd31 100644 --- a/tests/ui/implicit_saturating_add.rs +++ b/tests/ui/implicit_saturating_add.rs @@ -19,10 +19,12 @@ fn main() { } if u_8 != u8::MAX { + //~^ implicit_saturating_add u_8 += 1; } if u_8 < u8::MAX { + //~^ implicit_saturating_add u_8 += 1; } @@ -31,86 +33,107 @@ fn main() { } if u_16 != u16::MAX { + //~^ implicit_saturating_add u_16 += 1; } if u_16 < u16::MAX { + //~^ implicit_saturating_add u_16 += 1; } if u16::MAX > u_16 { + //~^ implicit_saturating_add u_16 += 1; } if u_32 != u32::MAX { + //~^ implicit_saturating_add u_32 += 1; } if u_32 < u32::MAX { + //~^ implicit_saturating_add u_32 += 1; } if u32::MAX > u_32 { + //~^ implicit_saturating_add u_32 += 1; } if u_64 != u64::MAX { + //~^ implicit_saturating_add u_64 += 1; } if u_64 < u64::MAX { + //~^ implicit_saturating_add u_64 += 1; } if u64::MAX > u_64 { + //~^ implicit_saturating_add u_64 += 1; } if i_8 != i8::MAX { + //~^ implicit_saturating_add i_8 += 1; } if i_8 < i8::MAX { + //~^ implicit_saturating_add i_8 += 1; } if i8::MAX > i_8 { + //~^ implicit_saturating_add i_8 += 1; } if i_16 != i16::MAX { + //~^ implicit_saturating_add i_16 += 1; } if i_16 < i16::MAX { + //~^ implicit_saturating_add i_16 += 1; } if i16::MAX > i_16 { + //~^ implicit_saturating_add i_16 += 1; } if i_32 != i32::MAX { + //~^ implicit_saturating_add i_32 += 1; } if i_32 < i32::MAX { + //~^ implicit_saturating_add i_32 += 1; } if i32::MAX > i_32 { + //~^ implicit_saturating_add i_32 += 1; } if i_64 != i64::MAX { + //~^ implicit_saturating_add i_64 += 1; } if i_64 < i64::MAX { + //~^ implicit_saturating_add i_64 += 1; } if i64::MAX > i_64 { + //~^ implicit_saturating_add i_64 += 1; } @@ -147,6 +170,7 @@ fn main() { if u_32 < 42 { println!("brace yourself!"); } else if u_32 < u32::MAX { + //~^ implicit_saturating_add u_32 += 1; } } diff --git a/tests/ui/implicit_saturating_add.stderr b/tests/ui/implicit_saturating_add.stderr index 4fb9282bc91d..8ae7dc4b884b 100644 --- a/tests/ui/implicit_saturating_add.stderr +++ b/tests/ui/implicit_saturating_add.stderr @@ -2,6 +2,7 @@ error: manual saturating add detected --> tests/ui/implicit_saturating_add.rs:21:5 | LL | / if u_8 != u8::MAX { +LL | | LL | | u_8 += 1; LL | | } | |_____^ help: use instead: `u_8 = u_8.saturating_add(1);` @@ -10,33 +11,28 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::implicit_saturating_add)]` error: manual saturating add detected - --> tests/ui/implicit_saturating_add.rs:25:5 + --> tests/ui/implicit_saturating_add.rs:26:5 | LL | / if u_8 < u8::MAX { +LL | | LL | | u_8 += 1; LL | | } | |_____^ help: use instead: `u_8 = u_8.saturating_add(1);` error: manual saturating add detected - --> tests/ui/implicit_saturating_add.rs:33:5 + --> tests/ui/implicit_saturating_add.rs:35:5 | LL | / if u_16 != u16::MAX { +LL | | LL | | u_16 += 1; LL | | } | |_____^ help: use instead: `u_16 = u_16.saturating_add(1);` error: manual saturating add detected - --> tests/ui/implicit_saturating_add.rs:37:5 + --> tests/ui/implicit_saturating_add.rs:40:5 | LL | / if u_16 < u16::MAX { -LL | | u_16 += 1; -LL | | } - | |_____^ help: use instead: `u_16 = u_16.saturating_add(1);` - -error: manual saturating add detected - --> tests/ui/implicit_saturating_add.rs:41:5 - | -LL | / if u16::MAX > u_16 { +LL | | LL | | u_16 += 1; LL | | } | |_____^ help: use instead: `u_16 = u_16.saturating_add(1);` @@ -44,152 +40,180 @@ LL | | } error: manual saturating add detected --> tests/ui/implicit_saturating_add.rs:45:5 | +LL | / if u16::MAX > u_16 { +LL | | +LL | | u_16 += 1; +LL | | } + | |_____^ help: use instead: `u_16 = u_16.saturating_add(1);` + +error: manual saturating add detected + --> tests/ui/implicit_saturating_add.rs:50:5 + | LL | / if u_32 != u32::MAX { +LL | | LL | | u_32 += 1; LL | | } | |_____^ help: use instead: `u_32 = u_32.saturating_add(1);` error: manual saturating add detected - --> tests/ui/implicit_saturating_add.rs:49:5 + --> tests/ui/implicit_saturating_add.rs:55:5 | LL | / if u_32 < u32::MAX { +LL | | LL | | u_32 += 1; LL | | } | |_____^ help: use instead: `u_32 = u_32.saturating_add(1);` error: manual saturating add detected - --> tests/ui/implicit_saturating_add.rs:53:5 + --> tests/ui/implicit_saturating_add.rs:60:5 | LL | / if u32::MAX > u_32 { +LL | | LL | | u_32 += 1; LL | | } | |_____^ help: use instead: `u_32 = u_32.saturating_add(1);` -error: manual saturating add detected - --> tests/ui/implicit_saturating_add.rs:57:5 - | -LL | / if u_64 != u64::MAX { -LL | | u_64 += 1; -LL | | } - | |_____^ help: use instead: `u_64 = u_64.saturating_add(1);` - -error: manual saturating add detected - --> tests/ui/implicit_saturating_add.rs:61:5 - | -LL | / if u_64 < u64::MAX { -LL | | u_64 += 1; -LL | | } - | |_____^ help: use instead: `u_64 = u_64.saturating_add(1);` - error: manual saturating add detected --> tests/ui/implicit_saturating_add.rs:65:5 | -LL | / if u64::MAX > u_64 { +LL | / if u_64 != u64::MAX { +LL | | LL | | u_64 += 1; LL | | } | |_____^ help: use instead: `u_64 = u_64.saturating_add(1);` error: manual saturating add detected - --> tests/ui/implicit_saturating_add.rs:69:5 + --> tests/ui/implicit_saturating_add.rs:70:5 + | +LL | / if u_64 < u64::MAX { +LL | | +LL | | u_64 += 1; +LL | | } + | |_____^ help: use instead: `u_64 = u_64.saturating_add(1);` + +error: manual saturating add detected + --> tests/ui/implicit_saturating_add.rs:75:5 + | +LL | / if u64::MAX > u_64 { +LL | | +LL | | u_64 += 1; +LL | | } + | |_____^ help: use instead: `u_64 = u_64.saturating_add(1);` + +error: manual saturating add detected + --> tests/ui/implicit_saturating_add.rs:80:5 | LL | / if i_8 != i8::MAX { +LL | | LL | | i_8 += 1; LL | | } | |_____^ help: use instead: `i_8 = i_8.saturating_add(1);` -error: manual saturating add detected - --> tests/ui/implicit_saturating_add.rs:73:5 - | -LL | / if i_8 < i8::MAX { -LL | | i_8 += 1; -LL | | } - | |_____^ help: use instead: `i_8 = i_8.saturating_add(1);` - -error: manual saturating add detected - --> tests/ui/implicit_saturating_add.rs:77:5 - | -LL | / if i8::MAX > i_8 { -LL | | i_8 += 1; -LL | | } - | |_____^ help: use instead: `i_8 = i_8.saturating_add(1);` - -error: manual saturating add detected - --> tests/ui/implicit_saturating_add.rs:81:5 - | -LL | / if i_16 != i16::MAX { -LL | | i_16 += 1; -LL | | } - | |_____^ help: use instead: `i_16 = i_16.saturating_add(1);` - error: manual saturating add detected --> tests/ui/implicit_saturating_add.rs:85:5 | +LL | / if i_8 < i8::MAX { +LL | | +LL | | i_8 += 1; +LL | | } + | |_____^ help: use instead: `i_8 = i_8.saturating_add(1);` + +error: manual saturating add detected + --> tests/ui/implicit_saturating_add.rs:90:5 + | +LL | / if i8::MAX > i_8 { +LL | | +LL | | i_8 += 1; +LL | | } + | |_____^ help: use instead: `i_8 = i_8.saturating_add(1);` + +error: manual saturating add detected + --> tests/ui/implicit_saturating_add.rs:95:5 + | +LL | / if i_16 != i16::MAX { +LL | | +LL | | i_16 += 1; +LL | | } + | |_____^ help: use instead: `i_16 = i_16.saturating_add(1);` + +error: manual saturating add detected + --> tests/ui/implicit_saturating_add.rs:100:5 + | LL | / if i_16 < i16::MAX { +LL | | LL | | i_16 += 1; LL | | } | |_____^ help: use instead: `i_16 = i_16.saturating_add(1);` -error: manual saturating add detected - --> tests/ui/implicit_saturating_add.rs:89:5 - | -LL | / if i16::MAX > i_16 { -LL | | i_16 += 1; -LL | | } - | |_____^ help: use instead: `i_16 = i_16.saturating_add(1);` - -error: manual saturating add detected - --> tests/ui/implicit_saturating_add.rs:93:5 - | -LL | / if i_32 != i32::MAX { -LL | | i_32 += 1; -LL | | } - | |_____^ help: use instead: `i_32 = i_32.saturating_add(1);` - -error: manual saturating add detected - --> tests/ui/implicit_saturating_add.rs:97:5 - | -LL | / if i_32 < i32::MAX { -LL | | i_32 += 1; -LL | | } - | |_____^ help: use instead: `i_32 = i_32.saturating_add(1);` - -error: manual saturating add detected - --> tests/ui/implicit_saturating_add.rs:101:5 - | -LL | / if i32::MAX > i_32 { -LL | | i_32 += 1; -LL | | } - | |_____^ help: use instead: `i_32 = i_32.saturating_add(1);` - error: manual saturating add detected --> tests/ui/implicit_saturating_add.rs:105:5 | +LL | / if i16::MAX > i_16 { +LL | | +LL | | i_16 += 1; +LL | | } + | |_____^ help: use instead: `i_16 = i_16.saturating_add(1);` + +error: manual saturating add detected + --> tests/ui/implicit_saturating_add.rs:110:5 + | +LL | / if i_32 != i32::MAX { +LL | | +LL | | i_32 += 1; +LL | | } + | |_____^ help: use instead: `i_32 = i_32.saturating_add(1);` + +error: manual saturating add detected + --> tests/ui/implicit_saturating_add.rs:115:5 + | +LL | / if i_32 < i32::MAX { +LL | | +LL | | i_32 += 1; +LL | | } + | |_____^ help: use instead: `i_32 = i_32.saturating_add(1);` + +error: manual saturating add detected + --> tests/ui/implicit_saturating_add.rs:120:5 + | +LL | / if i32::MAX > i_32 { +LL | | +LL | | i_32 += 1; +LL | | } + | |_____^ help: use instead: `i_32 = i_32.saturating_add(1);` + +error: manual saturating add detected + --> tests/ui/implicit_saturating_add.rs:125:5 + | LL | / if i_64 != i64::MAX { +LL | | LL | | i_64 += 1; LL | | } | |_____^ help: use instead: `i_64 = i_64.saturating_add(1);` error: manual saturating add detected - --> tests/ui/implicit_saturating_add.rs:109:5 + --> tests/ui/implicit_saturating_add.rs:130:5 | LL | / if i_64 < i64::MAX { +LL | | LL | | i_64 += 1; LL | | } | |_____^ help: use instead: `i_64 = i_64.saturating_add(1);` error: manual saturating add detected - --> tests/ui/implicit_saturating_add.rs:113:5 + --> tests/ui/implicit_saturating_add.rs:135:5 | LL | / if i64::MAX > i_64 { +LL | | LL | | i_64 += 1; LL | | } | |_____^ help: use instead: `i_64 = i_64.saturating_add(1);` error: manual saturating add detected - --> tests/ui/implicit_saturating_add.rs:149:12 + --> tests/ui/implicit_saturating_add.rs:172:12 | LL | } else if u_32 < u32::MAX { | ____________^ +LL | | LL | | u_32 += 1; LL | | } | |_____^ help: use instead: `{u_32 = u_32.saturating_add(1); }` diff --git a/tests/ui/implicit_saturating_sub.rs b/tests/ui/implicit_saturating_sub.rs index e371e37fb2f6..140cf0338602 100644 --- a/tests/ui/implicit_saturating_sub.rs +++ b/tests/ui/implicit_saturating_sub.rs @@ -25,6 +25,7 @@ fn main() { // Lint if u_8 > 0 { + //~^ implicit_saturating_sub u_8 = u_8 - 1; } @@ -32,6 +33,7 @@ fn main() { 10 => { // Lint if u_8 > 0 { + //~^ implicit_saturating_sub u_8 -= 1; } }, @@ -46,6 +48,7 @@ fn main() { // Lint if u_16 > 0 { + //~^ implicit_saturating_sub u_16 -= 1; } @@ -56,6 +59,7 @@ fn main() { // Lint if u_32 != 0 { + //~^ implicit_saturating_sub u_32 -= 1; } @@ -77,16 +81,19 @@ fn main() { // Lint if u_64 > 0 { + //~^ implicit_saturating_sub u_64 -= 1; } // Lint if 0 < u_64 { + //~^ implicit_saturating_sub u_64 -= 1; } // Lint if 0 != u_64 { + //~^ implicit_saturating_sub u_64 -= 1; } @@ -108,6 +115,7 @@ fn main() { // Lint if u_usize > 0 { + //~^ implicit_saturating_sub u_usize -= 1; } @@ -120,21 +128,25 @@ fn main() { // Lint if i_8 > i8::MIN { + //~^ implicit_saturating_sub i_8 -= 1; } // Lint if i_8 > i8::MIN { + //~^ implicit_saturating_sub i_8 -= 1; } // Lint if i_8 != i8::MIN { + //~^ implicit_saturating_sub i_8 -= 1; } // Lint if i_8 != i8::MIN { + //~^ implicit_saturating_sub i_8 -= 1; } @@ -145,21 +157,25 @@ fn main() { // Lint if i_16 > i16::MIN { + //~^ implicit_saturating_sub i_16 -= 1; } // Lint if i_16 > i16::MIN { + //~^ implicit_saturating_sub i_16 -= 1; } // Lint if i_16 != i16::MIN { + //~^ implicit_saturating_sub i_16 -= 1; } // Lint if i_16 != i16::MIN { + //~^ implicit_saturating_sub i_16 -= 1; } @@ -170,21 +186,25 @@ fn main() { // Lint if i_32 > i32::MIN { + //~^ implicit_saturating_sub i_32 -= 1; } // Lint if i_32 > i32::MIN { + //~^ implicit_saturating_sub i_32 -= 1; } // Lint if i_32 != i32::MIN { + //~^ implicit_saturating_sub i_32 -= 1; } // Lint if i_32 != i32::MIN { + //~^ implicit_saturating_sub i_32 -= 1; } @@ -195,16 +215,19 @@ fn main() { // Lint if i64::MIN < i_64 { + //~^ implicit_saturating_sub i_64 -= 1; } // Lint if i64::MIN != i_64 { + //~^ implicit_saturating_sub i_64 -= 1; } // Lint if i64::MIN < i_64 { + //~^ implicit_saturating_sub i_64 -= 1; } @@ -273,6 +296,7 @@ fn regression_13524(a: usize, b: usize, c: bool) -> usize { if c { 123 } else if a >= b { + //~^ implicit_saturating_sub 0 } else { b - a diff --git a/tests/ui/implicit_saturating_sub.stderr b/tests/ui/implicit_saturating_sub.stderr index 613198512280..f9c94d3ad841 100644 --- a/tests/ui/implicit_saturating_sub.stderr +++ b/tests/ui/implicit_saturating_sub.stderr @@ -2,6 +2,7 @@ error: implicitly performing saturating subtraction --> tests/ui/implicit_saturating_sub.rs:27:5 | LL | / if u_8 > 0 { +LL | | LL | | u_8 = u_8 - 1; LL | | } | |_____^ help: try: `u_8 = u_8.saturating_sub(1);` @@ -10,41 +11,37 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::implicit_saturating_sub)]` error: implicitly performing saturating subtraction - --> tests/ui/implicit_saturating_sub.rs:34:13 + --> tests/ui/implicit_saturating_sub.rs:35:13 | LL | / if u_8 > 0 { +LL | | LL | | u_8 -= 1; LL | | } | |_____________^ help: try: `u_8 = u_8.saturating_sub(1);` error: implicitly performing saturating subtraction - --> tests/ui/implicit_saturating_sub.rs:48:5 + --> tests/ui/implicit_saturating_sub.rs:50:5 | LL | / if u_16 > 0 { +LL | | LL | | u_16 -= 1; LL | | } | |_____^ help: try: `u_16 = u_16.saturating_sub(1);` error: implicitly performing saturating subtraction - --> tests/ui/implicit_saturating_sub.rs:58:5 + --> tests/ui/implicit_saturating_sub.rs:61:5 | LL | / if u_32 != 0 { +LL | | LL | | u_32 -= 1; LL | | } | |_____^ help: try: `u_32 = u_32.saturating_sub(1);` error: implicitly performing saturating subtraction - --> tests/ui/implicit_saturating_sub.rs:79:5 + --> tests/ui/implicit_saturating_sub.rs:83:5 | LL | / if u_64 > 0 { -LL | | u_64 -= 1; -LL | | } - | |_____^ help: try: `u_64 = u_64.saturating_sub(1);` - -error: implicitly performing saturating subtraction - --> tests/ui/implicit_saturating_sub.rs:84:5 - | -LL | / if 0 < u_64 { +LL | | LL | | u_64 -= 1; LL | | } | |_____^ help: try: `u_64 = u_64.saturating_sub(1);` @@ -52,144 +49,171 @@ LL | | } error: implicitly performing saturating subtraction --> tests/ui/implicit_saturating_sub.rs:89:5 | -LL | / if 0 != u_64 { +LL | / if 0 < u_64 { +LL | | LL | | u_64 -= 1; LL | | } | |_____^ help: try: `u_64 = u_64.saturating_sub(1);` error: implicitly performing saturating subtraction - --> tests/ui/implicit_saturating_sub.rs:110:5 + --> tests/ui/implicit_saturating_sub.rs:95:5 + | +LL | / if 0 != u_64 { +LL | | +LL | | u_64 -= 1; +LL | | } + | |_____^ help: try: `u_64 = u_64.saturating_sub(1);` + +error: implicitly performing saturating subtraction + --> tests/ui/implicit_saturating_sub.rs:117:5 | LL | / if u_usize > 0 { +LL | | LL | | u_usize -= 1; LL | | } | |_____^ help: try: `u_usize = u_usize.saturating_sub(1);` error: implicitly performing saturating subtraction - --> tests/ui/implicit_saturating_sub.rs:122:5 + --> tests/ui/implicit_saturating_sub.rs:130:5 | LL | / if i_8 > i8::MIN { +LL | | LL | | i_8 -= 1; LL | | } | |_____^ help: try: `i_8 = i_8.saturating_sub(1);` error: implicitly performing saturating subtraction - --> tests/ui/implicit_saturating_sub.rs:127:5 + --> tests/ui/implicit_saturating_sub.rs:136:5 | LL | / if i_8 > i8::MIN { +LL | | LL | | i_8 -= 1; LL | | } | |_____^ help: try: `i_8 = i_8.saturating_sub(1);` error: implicitly performing saturating subtraction - --> tests/ui/implicit_saturating_sub.rs:132:5 + --> tests/ui/implicit_saturating_sub.rs:142:5 | LL | / if i_8 != i8::MIN { +LL | | LL | | i_8 -= 1; LL | | } | |_____^ help: try: `i_8 = i_8.saturating_sub(1);` error: implicitly performing saturating subtraction - --> tests/ui/implicit_saturating_sub.rs:137:5 + --> tests/ui/implicit_saturating_sub.rs:148:5 | LL | / if i_8 != i8::MIN { +LL | | LL | | i_8 -= 1; LL | | } | |_____^ help: try: `i_8 = i_8.saturating_sub(1);` error: implicitly performing saturating subtraction - --> tests/ui/implicit_saturating_sub.rs:147:5 + --> tests/ui/implicit_saturating_sub.rs:159:5 | LL | / if i_16 > i16::MIN { +LL | | LL | | i_16 -= 1; LL | | } | |_____^ help: try: `i_16 = i_16.saturating_sub(1);` error: implicitly performing saturating subtraction - --> tests/ui/implicit_saturating_sub.rs:152:5 + --> tests/ui/implicit_saturating_sub.rs:165:5 | LL | / if i_16 > i16::MIN { +LL | | LL | | i_16 -= 1; LL | | } | |_____^ help: try: `i_16 = i_16.saturating_sub(1);` error: implicitly performing saturating subtraction - --> tests/ui/implicit_saturating_sub.rs:157:5 + --> tests/ui/implicit_saturating_sub.rs:171:5 | LL | / if i_16 != i16::MIN { +LL | | LL | | i_16 -= 1; LL | | } | |_____^ help: try: `i_16 = i_16.saturating_sub(1);` -error: implicitly performing saturating subtraction - --> tests/ui/implicit_saturating_sub.rs:162:5 - | -LL | / if i_16 != i16::MIN { -LL | | i_16 -= 1; -LL | | } - | |_____^ help: try: `i_16 = i_16.saturating_sub(1);` - -error: implicitly performing saturating subtraction - --> tests/ui/implicit_saturating_sub.rs:172:5 - | -LL | / if i_32 > i32::MIN { -LL | | i_32 -= 1; -LL | | } - | |_____^ help: try: `i_32 = i_32.saturating_sub(1);` - error: implicitly performing saturating subtraction --> tests/ui/implicit_saturating_sub.rs:177:5 | +LL | / if i_16 != i16::MIN { +LL | | +LL | | i_16 -= 1; +LL | | } + | |_____^ help: try: `i_16 = i_16.saturating_sub(1);` + +error: implicitly performing saturating subtraction + --> tests/ui/implicit_saturating_sub.rs:188:5 + | LL | / if i_32 > i32::MIN { +LL | | LL | | i_32 -= 1; LL | | } | |_____^ help: try: `i_32 = i_32.saturating_sub(1);` error: implicitly performing saturating subtraction - --> tests/ui/implicit_saturating_sub.rs:182:5 + --> tests/ui/implicit_saturating_sub.rs:194:5 + | +LL | / if i_32 > i32::MIN { +LL | | +LL | | i_32 -= 1; +LL | | } + | |_____^ help: try: `i_32 = i_32.saturating_sub(1);` + +error: implicitly performing saturating subtraction + --> tests/ui/implicit_saturating_sub.rs:200:5 | LL | / if i_32 != i32::MIN { +LL | | LL | | i_32 -= 1; LL | | } | |_____^ help: try: `i_32 = i_32.saturating_sub(1);` error: implicitly performing saturating subtraction - --> tests/ui/implicit_saturating_sub.rs:187:5 + --> tests/ui/implicit_saturating_sub.rs:206:5 | LL | / if i_32 != i32::MIN { +LL | | LL | | i_32 -= 1; LL | | } | |_____^ help: try: `i_32 = i_32.saturating_sub(1);` error: implicitly performing saturating subtraction - --> tests/ui/implicit_saturating_sub.rs:197:5 + --> tests/ui/implicit_saturating_sub.rs:217:5 | LL | / if i64::MIN < i_64 { +LL | | LL | | i_64 -= 1; LL | | } | |_____^ help: try: `i_64 = i_64.saturating_sub(1);` error: implicitly performing saturating subtraction - --> tests/ui/implicit_saturating_sub.rs:202:5 + --> tests/ui/implicit_saturating_sub.rs:223:5 | LL | / if i64::MIN != i_64 { +LL | | LL | | i_64 -= 1; LL | | } | |_____^ help: try: `i_64 = i_64.saturating_sub(1);` error: implicitly performing saturating subtraction - --> tests/ui/implicit_saturating_sub.rs:207:5 + --> tests/ui/implicit_saturating_sub.rs:229:5 | LL | / if i64::MIN < i_64 { +LL | | LL | | i_64 -= 1; LL | | } | |_____^ help: try: `i_64 = i_64.saturating_sub(1);` error: manual arithmetic check found - --> tests/ui/implicit_saturating_sub.rs:275:12 + --> tests/ui/implicit_saturating_sub.rs:298:12 | LL | } else if a >= b { | ____________^ +LL | | LL | | 0 LL | | } else { LL | | b - a diff --git a/tests/ui/implied_bounds_in_impls.fixed b/tests/ui/implied_bounds_in_impls.fixed index 6fd4cbd80fe4..bac7af59491f 100644 --- a/tests/ui/implied_bounds_in_impls.fixed +++ b/tests/ui/implied_bounds_in_impls.fixed @@ -11,6 +11,7 @@ fn normal_deref(x: T) -> impl Deref { // Deref implied by DerefMut fn deref_derefmut(x: T) -> impl DerefMut { + //~^ implied_bounds_in_impls Box::new(x) } @@ -28,14 +29,19 @@ impl GenericSubtrait<(), i32, V> for () {} impl GenericSubtrait<(), i64, V> for () {} fn generics_implied() -> impl GenericSubtrait +//~^ implied_bounds_in_impls where (): GenericSubtrait, { } fn generics_implied_multi() -> impl GenericSubtrait<(), i32, V> {} +//~^ implied_bounds_in_impls +//~| implied_bounds_in_impls fn generics_implied_multi2() -> impl GenericSubtrait<(), T, V> +//~^ implied_bounds_in_impls +//~| implied_bounds_in_impls where (): GenericSubtrait<(), T, V> + GenericTrait, { @@ -46,21 +52,25 @@ fn generics_different() -> impl GenericTrait + GenericSubtrait<(), i64, ()> // i32 == i32, GenericSubtrait<_, i32, _> does imply GenericTrait, lint fn generics_same() -> impl GenericSubtrait<(), i32, ()> {} +//~^ implied_bounds_in_impls trait SomeTrait { // Check that it works in trait declarations. fn f() -> impl DerefMut; + //~^ implied_bounds_in_impls } struct SomeStruct; impl SomeStruct { // Check that it works in inherent impl blocks. fn f() -> impl DerefMut { + //~^ implied_bounds_in_impls Box::new(123) } } impl SomeTrait for SomeStruct { // Check that it works in trait impls. fn f() -> impl DerefMut { + //~^ implied_bounds_in_impls Box::new(42) } } @@ -72,7 +82,9 @@ mod issue11422 { // `PartialOrd` has a default generic parameter and does not need to be explicitly specified. // This needs special handling. fn default_generic_param1() -> impl PartialOrd + Debug {} + //~^ implied_bounds_in_impls fn default_generic_param2() -> impl PartialOrd + Debug {} + //~^ implied_bounds_in_impls // Referring to `Self` in the supertrait clause needs special handling. trait Trait1 {} @@ -86,11 +98,13 @@ mod issue11422 { mod issue11435 { // Associated type needs to be included on DoubleEndedIterator in the suggestion fn my_iter() -> impl DoubleEndedIterator { + //~^ implied_bounds_in_impls 0..5 } // Removing the `Clone` bound should include the `+` behind it in its remove suggestion fn f() -> impl Copy { + //~^ implied_bounds_in_impls 1 } @@ -105,6 +119,7 @@ mod issue11435 { // When the other trait has generics, it shouldn't add another pair of `<>` fn f2() -> impl Trait2 {} + //~^ implied_bounds_in_impls trait Trait3 { type X; @@ -120,6 +135,7 @@ mod issue11435 { // Associated type `X` is specified, but `Y` is not, so only that associated type should be moved // over fn f3() -> impl Trait4 {} + //~^ implied_bounds_in_impls } fn issue11880() { @@ -147,14 +163,19 @@ fn issue11880() { // X::T is never constrained in the first place, so it can be omitted // and left unconstrained fn f3() -> impl Y {} + //~^ implied_bounds_in_impls fn f4() -> impl Y {} + //~^ implied_bounds_in_impls fn f5() -> impl Y {} + //~^ implied_bounds_in_impls } fn apit(_: impl DerefMut) {} +//~^ implied_bounds_in_impls trait Rpitit { fn f() -> impl DerefMut; + //~^ implied_bounds_in_impls } trait Atpit { @@ -163,12 +184,14 @@ trait Atpit { } impl Atpit for () { type Assoc = impl DerefMut; + //~^ implied_bounds_in_impls fn define() -> Self::Assoc { &mut [] as &mut [()] } } type Tait = impl DerefMut; +//~^ implied_bounds_in_impls fn define() -> Tait { &mut [] as &mut [()] } diff --git a/tests/ui/implied_bounds_in_impls.rs b/tests/ui/implied_bounds_in_impls.rs index 52076c9f998e..2014cd46ada7 100644 --- a/tests/ui/implied_bounds_in_impls.rs +++ b/tests/ui/implied_bounds_in_impls.rs @@ -11,6 +11,7 @@ fn normal_deref(x: T) -> impl Deref { // Deref implied by DerefMut fn deref_derefmut(x: T) -> impl Deref + DerefMut { + //~^ implied_bounds_in_impls Box::new(x) } @@ -28,14 +29,19 @@ impl GenericSubtrait<(), i32, V> for () {} impl GenericSubtrait<(), i64, V> for () {} fn generics_implied() -> impl GenericTrait + GenericSubtrait +//~^ implied_bounds_in_impls where (): GenericSubtrait, { } fn generics_implied_multi() -> impl GenericTrait + GenericTrait2 + GenericSubtrait<(), i32, V> {} +//~^ implied_bounds_in_impls +//~| implied_bounds_in_impls fn generics_implied_multi2() -> impl GenericTrait + GenericTrait2 + GenericSubtrait<(), T, V> +//~^ implied_bounds_in_impls +//~| implied_bounds_in_impls where (): GenericSubtrait<(), T, V> + GenericTrait, { @@ -46,21 +52,25 @@ fn generics_different() -> impl GenericTrait + GenericSubtrait<(), i64, ()> // i32 == i32, GenericSubtrait<_, i32, _> does imply GenericTrait, lint fn generics_same() -> impl GenericTrait + GenericSubtrait<(), i32, ()> {} +//~^ implied_bounds_in_impls trait SomeTrait { // Check that it works in trait declarations. fn f() -> impl Deref + DerefMut; + //~^ implied_bounds_in_impls } struct SomeStruct; impl SomeStruct { // Check that it works in inherent impl blocks. fn f() -> impl Deref + DerefMut { + //~^ implied_bounds_in_impls Box::new(123) } } impl SomeTrait for SomeStruct { // Check that it works in trait impls. fn f() -> impl Deref + DerefMut { + //~^ implied_bounds_in_impls Box::new(42) } } @@ -72,7 +82,9 @@ mod issue11422 { // `PartialOrd` has a default generic parameter and does not need to be explicitly specified. // This needs special handling. fn default_generic_param1() -> impl PartialEq + PartialOrd + Debug {} + //~^ implied_bounds_in_impls fn default_generic_param2() -> impl PartialOrd + PartialEq + Debug {} + //~^ implied_bounds_in_impls // Referring to `Self` in the supertrait clause needs special handling. trait Trait1 {} @@ -86,11 +98,13 @@ mod issue11422 { mod issue11435 { // Associated type needs to be included on DoubleEndedIterator in the suggestion fn my_iter() -> impl Iterator + DoubleEndedIterator { + //~^ implied_bounds_in_impls 0..5 } // Removing the `Clone` bound should include the `+` behind it in its remove suggestion fn f() -> impl Copy + Clone { + //~^ implied_bounds_in_impls 1 } @@ -105,6 +119,7 @@ mod issue11435 { // When the other trait has generics, it shouldn't add another pair of `<>` fn f2() -> impl Trait1 + Trait2 {} + //~^ implied_bounds_in_impls trait Trait3 { type X; @@ -120,6 +135,7 @@ mod issue11435 { // Associated type `X` is specified, but `Y` is not, so only that associated type should be moved // over fn f3() -> impl Trait3 + Trait4 {} + //~^ implied_bounds_in_impls } fn issue11880() { @@ -147,14 +163,19 @@ fn issue11880() { // X::T is never constrained in the first place, so it can be omitted // and left unconstrained fn f3() -> impl X + Y {} + //~^ implied_bounds_in_impls fn f4() -> impl X + Y {} + //~^ implied_bounds_in_impls fn f5() -> impl X + Y {} + //~^ implied_bounds_in_impls } fn apit(_: impl Deref + DerefMut) {} +//~^ implied_bounds_in_impls trait Rpitit { fn f() -> impl Deref + DerefMut; + //~^ implied_bounds_in_impls } trait Atpit { @@ -163,12 +184,14 @@ trait Atpit { } impl Atpit for () { type Assoc = impl Deref + DerefMut; + //~^ implied_bounds_in_impls fn define() -> Self::Assoc { &mut [] as &mut [()] } } type Tait = impl Deref + DerefMut; +//~^ implied_bounds_in_impls fn define() -> Tait { &mut [] as &mut [()] } diff --git a/tests/ui/implied_bounds_in_impls.stderr b/tests/ui/implied_bounds_in_impls.stderr index 805532a56802..e2888d86f315 100644 --- a/tests/ui/implied_bounds_in_impls.stderr +++ b/tests/ui/implied_bounds_in_impls.stderr @@ -13,7 +13,7 @@ LL + fn deref_derefmut(x: T) -> impl DerefMut { | error: this bound is already specified as the supertrait of `GenericSubtrait` - --> tests/ui/implied_bounds_in_impls.rs:30:37 + --> tests/ui/implied_bounds_in_impls.rs:31:37 | LL | fn generics_implied() -> impl GenericTrait + GenericSubtrait | ^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + fn generics_implied() -> impl GenericSubtrait | error: this bound is already specified as the supertrait of `GenericSubtrait<(), i32, V>` - --> tests/ui/implied_bounds_in_impls.rs:36:40 + --> tests/ui/implied_bounds_in_impls.rs:38:40 | LL | fn generics_implied_multi() -> impl GenericTrait + GenericTrait2 + GenericSubtrait<(), i32, V> {} | ^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + fn generics_implied_multi() -> impl GenericTrait2 + GenericSubtrait<( | error: this bound is already specified as the supertrait of `GenericSubtrait<(), i32, V>` - --> tests/ui/implied_bounds_in_impls.rs:36:60 + --> tests/ui/implied_bounds_in_impls.rs:38:60 | LL | fn generics_implied_multi() -> impl GenericTrait + GenericTrait2 + GenericSubtrait<(), i32, V> {} | ^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + fn generics_implied_multi() -> impl GenericTrait + GenericSubtrait< | error: this bound is already specified as the supertrait of `GenericSubtrait<(), T, V>` - --> tests/ui/implied_bounds_in_impls.rs:38:44 + --> tests/ui/implied_bounds_in_impls.rs:42:44 | LL | fn generics_implied_multi2() -> impl GenericTrait + GenericTrait2 + GenericSubtrait<(), T, V> | ^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + fn generics_implied_multi2() -> impl GenericTrait2 + GenericSubtra | error: this bound is already specified as the supertrait of `GenericSubtrait<(), T, V>` - --> tests/ui/implied_bounds_in_impls.rs:38:62 + --> tests/ui/implied_bounds_in_impls.rs:42:62 | LL | fn generics_implied_multi2() -> impl GenericTrait + GenericTrait2 + GenericSubtrait<(), T, V> | ^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + fn generics_implied_multi2() -> impl GenericTrait + GenericSubtrai | error: this bound is already specified as the supertrait of `GenericSubtrait<(), i32, ()>` - --> tests/ui/implied_bounds_in_impls.rs:48:28 + --> tests/ui/implied_bounds_in_impls.rs:54:28 | LL | fn generics_same() -> impl GenericTrait + GenericSubtrait<(), i32, ()> {} | ^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + fn generics_same() -> impl GenericSubtrait<(), i32, ()> {} | error: this bound is already specified as the supertrait of `DerefMut` - --> tests/ui/implied_bounds_in_impls.rs:52:20 + --> tests/ui/implied_bounds_in_impls.rs:59:20 | LL | fn f() -> impl Deref + DerefMut; | ^^^^^ @@ -97,7 +97,7 @@ LL + fn f() -> impl DerefMut; | error: this bound is already specified as the supertrait of `DerefMut` - --> tests/ui/implied_bounds_in_impls.rs:57:20 + --> tests/ui/implied_bounds_in_impls.rs:65:20 | LL | fn f() -> impl Deref + DerefMut { | ^^^^^ @@ -109,7 +109,7 @@ LL + fn f() -> impl DerefMut { | error: this bound is already specified as the supertrait of `DerefMut` - --> tests/ui/implied_bounds_in_impls.rs:63:20 + --> tests/ui/implied_bounds_in_impls.rs:72:20 | LL | fn f() -> impl Deref + DerefMut { | ^^^^^ @@ -121,7 +121,7 @@ LL + fn f() -> impl DerefMut { | error: this bound is already specified as the supertrait of `PartialOrd` - --> tests/ui/implied_bounds_in_impls.rs:74:41 + --> tests/ui/implied_bounds_in_impls.rs:84:41 | LL | fn default_generic_param1() -> impl PartialEq + PartialOrd + Debug {} | ^^^^^^^^^ @@ -133,7 +133,7 @@ LL + fn default_generic_param1() -> impl PartialOrd + Debug {} | error: this bound is already specified as the supertrait of `PartialOrd` - --> tests/ui/implied_bounds_in_impls.rs:75:54 + --> tests/ui/implied_bounds_in_impls.rs:86:54 | LL | fn default_generic_param2() -> impl PartialOrd + PartialEq + Debug {} | ^^^^^^^^^ @@ -145,7 +145,7 @@ LL + fn default_generic_param2() -> impl PartialOrd + Debug {} | error: this bound is already specified as the supertrait of `DoubleEndedIterator` - --> tests/ui/implied_bounds_in_impls.rs:88:26 + --> tests/ui/implied_bounds_in_impls.rs:100:26 | LL | fn my_iter() -> impl Iterator + DoubleEndedIterator { | ^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL + fn my_iter() -> impl DoubleEndedIterator { | error: this bound is already specified as the supertrait of `Copy` - --> tests/ui/implied_bounds_in_impls.rs:93:27 + --> tests/ui/implied_bounds_in_impls.rs:106:27 | LL | fn f() -> impl Copy + Clone { | ^^^^^ @@ -169,7 +169,7 @@ LL + fn f() -> impl Copy { | error: this bound is already specified as the supertrait of `Trait2` - --> tests/ui/implied_bounds_in_impls.rs:107:21 + --> tests/ui/implied_bounds_in_impls.rs:121:21 | LL | fn f2() -> impl Trait1 + Trait2 {} | ^^^^^^^^^^^^^^^^^^^^ @@ -181,7 +181,7 @@ LL + fn f2() -> impl Trait2 {} | error: this bound is already specified as the supertrait of `Trait4` - --> tests/ui/implied_bounds_in_impls.rs:122:21 + --> tests/ui/implied_bounds_in_impls.rs:137:21 | LL | fn f3() -> impl Trait3 + Trait4 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -193,7 +193,7 @@ LL + fn f3() -> impl Trait4 {} | error: this bound is already specified as the supertrait of `Y` - --> tests/ui/implied_bounds_in_impls.rs:149:21 + --> tests/ui/implied_bounds_in_impls.rs:165:21 | LL | fn f3() -> impl X + Y {} | ^ @@ -205,7 +205,7 @@ LL + fn f3() -> impl Y {} | error: this bound is already specified as the supertrait of `Y` - --> tests/ui/implied_bounds_in_impls.rs:150:21 + --> tests/ui/implied_bounds_in_impls.rs:167:21 | LL | fn f4() -> impl X + Y {} | ^ @@ -217,7 +217,7 @@ LL + fn f4() -> impl Y {} | error: this bound is already specified as the supertrait of `Y` - --> tests/ui/implied_bounds_in_impls.rs:151:21 + --> tests/ui/implied_bounds_in_impls.rs:169:21 | LL | fn f5() -> impl X + Y {} | ^^^^^^^^^^^^^ @@ -229,7 +229,7 @@ LL + fn f5() -> impl Y {} | error: this bound is already specified as the supertrait of `DerefMut` - --> tests/ui/implied_bounds_in_impls.rs:154:17 + --> tests/ui/implied_bounds_in_impls.rs:173:17 | LL | fn apit(_: impl Deref + DerefMut) {} | ^^^^^ @@ -241,7 +241,7 @@ LL + fn apit(_: impl DerefMut) {} | error: this bound is already specified as the supertrait of `DerefMut` - --> tests/ui/implied_bounds_in_impls.rs:157:20 + --> tests/ui/implied_bounds_in_impls.rs:177:20 | LL | fn f() -> impl Deref + DerefMut; | ^^^^^ @@ -253,7 +253,7 @@ LL + fn f() -> impl DerefMut; | error: this bound is already specified as the supertrait of `DerefMut` - --> tests/ui/implied_bounds_in_impls.rs:165:23 + --> tests/ui/implied_bounds_in_impls.rs:186:23 | LL | type Assoc = impl Deref + DerefMut; | ^^^^^ @@ -265,7 +265,7 @@ LL + type Assoc = impl DerefMut; | error: this bound is already specified as the supertrait of `DerefMut` - --> tests/ui/implied_bounds_in_impls.rs:171:18 + --> tests/ui/implied_bounds_in_impls.rs:193:18 | LL | type Tait = impl Deref + DerefMut; | ^^^^^ diff --git a/tests/ui/incompatible_msrv.rs b/tests/ui/incompatible_msrv.rs index c23df223d508..b4fea4cae5ed 100644 --- a/tests/ui/incompatible_msrv.rs +++ b/tests/ui/incompatible_msrv.rs @@ -11,14 +11,15 @@ use std::time::Duration; fn foo() { let mut map: HashMap<&str, u32> = HashMap::new(); assert_eq!(map.entry("poneyland").key(), &"poneyland"); - //~^ ERROR: is `1.3.0` but this item is stable since `1.10.0` + //~^ incompatible_msrv + if let Entry::Vacant(v) = map.entry("poneyland") { v.into_key(); - //~^ ERROR: is `1.3.0` but this item is stable since `1.12.0` + //~^ incompatible_msrv } // Should warn for `sleep` but not for `Duration` (which was added in `1.3.0`). sleep(Duration::new(1, 0)); - //~^ ERROR: is `1.3.0` but this item is stable since `1.4.0` + //~^ incompatible_msrv } #[test] diff --git a/tests/ui/incompatible_msrv.stderr b/tests/ui/incompatible_msrv.stderr index 34f01c3e14a1..56c9eae5aafa 100644 --- a/tests/ui/incompatible_msrv.stderr +++ b/tests/ui/incompatible_msrv.stderr @@ -8,13 +8,13 @@ LL | assert_eq!(map.entry("poneyland").key(), &"poneyland"); = help: to override `-D warnings` add `#[allow(clippy::incompatible_msrv)]` error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.12.0` - --> tests/ui/incompatible_msrv.rs:16:11 + --> tests/ui/incompatible_msrv.rs:17:11 | LL | v.into_key(); | ^^^^^^^^^^ error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.4.0` - --> tests/ui/incompatible_msrv.rs:20:5 + --> tests/ui/incompatible_msrv.rs:21:5 | LL | sleep(Duration::new(1, 0)); | ^^^^^ diff --git a/tests/ui/inconsistent_digit_grouping.fixed b/tests/ui/inconsistent_digit_grouping.fixed index 3f1dfbbae97b..23d2d7cc0aa4 100644 --- a/tests/ui/inconsistent_digit_grouping.fixed +++ b/tests/ui/inconsistent_digit_grouping.fixed @@ -23,15 +23,25 @@ fn main() { 1.123_456_7_f32, ); let bad = (123_456, 12_345_678, 1_234_567, 1_234.567_8_f32, 1.234_567_8_f32); + //~^ inconsistent_digit_grouping + //~| inconsistent_digit_grouping + //~| inconsistent_digit_grouping + //~| inconsistent_digit_grouping + //~| inconsistent_digit_grouping // Test padding let _ = 0x0010_0000; + //~^ unreadable_literal let _ = 0x0100_0000; + //~^ unreadable_literal let _ = 0x1000_0000; + //~^ unreadable_literal let _ = 0x0001_0000_0000_u64; + //~^ unreadable_literal // Test suggestion when fraction has no digits let _: f32 = 123_456.; + //~^ inconsistent_digit_grouping // Test UUID formatted literal let _: u128 = 0x12345678_1234_1234_1234_123456789012; diff --git a/tests/ui/inconsistent_digit_grouping.rs b/tests/ui/inconsistent_digit_grouping.rs index ac47ae175948..a172c5450ef8 100644 --- a/tests/ui/inconsistent_digit_grouping.rs +++ b/tests/ui/inconsistent_digit_grouping.rs @@ -23,15 +23,25 @@ fn main() { 1.123_456_7_f32, ); let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); + //~^ inconsistent_digit_grouping + //~| inconsistent_digit_grouping + //~| inconsistent_digit_grouping + //~| inconsistent_digit_grouping + //~| inconsistent_digit_grouping // Test padding let _ = 0x100000; + //~^ unreadable_literal let _ = 0x1000000; + //~^ unreadable_literal let _ = 0x10000000; + //~^ unreadable_literal let _ = 0x100000000_u64; + //~^ unreadable_literal // Test suggestion when fraction has no digits let _: f32 = 1_23_456.; + //~^ inconsistent_digit_grouping // Test UUID formatted literal let _: u128 = 0x12345678_1234_1234_1234_123456789012; diff --git a/tests/ui/inconsistent_digit_grouping.stderr b/tests/ui/inconsistent_digit_grouping.stderr index 173b824935c8..be54de5e7c16 100644 --- a/tests/ui/inconsistent_digit_grouping.stderr +++ b/tests/ui/inconsistent_digit_grouping.stderr @@ -32,7 +32,7 @@ LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f | ^^^^^^^^^^^^^^ help: consider: `1.234_567_8_f32` error: long literal lacking separators - --> tests/ui/inconsistent_digit_grouping.rs:28:13 + --> tests/ui/inconsistent_digit_grouping.rs:33:13 | LL | let _ = 0x100000; | ^^^^^^^^ help: consider: `0x0010_0000` @@ -44,25 +44,25 @@ LL | #[deny(clippy::unreadable_literal)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: long literal lacking separators - --> tests/ui/inconsistent_digit_grouping.rs:29:13 + --> tests/ui/inconsistent_digit_grouping.rs:35:13 | LL | let _ = 0x1000000; | ^^^^^^^^^ help: consider: `0x0100_0000` error: long literal lacking separators - --> tests/ui/inconsistent_digit_grouping.rs:30:13 + --> tests/ui/inconsistent_digit_grouping.rs:37:13 | LL | let _ = 0x10000000; | ^^^^^^^^^^ help: consider: `0x1000_0000` error: long literal lacking separators - --> tests/ui/inconsistent_digit_grouping.rs:31:13 + --> tests/ui/inconsistent_digit_grouping.rs:39:13 | LL | let _ = 0x100000000_u64; | ^^^^^^^^^^^^^^^ help: consider: `0x0001_0000_0000_u64` error: digits grouped inconsistently by underscores - --> tests/ui/inconsistent_digit_grouping.rs:34:18 + --> tests/ui/inconsistent_digit_grouping.rs:43:18 | LL | let _: f32 = 1_23_456.; | ^^^^^^^^^ help: consider: `123_456.` diff --git a/tests/ui/inconsistent_struct_constructor.fixed b/tests/ui/inconsistent_struct_constructor.fixed index 67bd3e4d2797..66232c0b9d8e 100644 --- a/tests/ui/inconsistent_struct_constructor.fixed +++ b/tests/ui/inconsistent_struct_constructor.fixed @@ -34,6 +34,7 @@ mod without_base { // Should lint. Foo { x, y, z }; + //~^ inconsistent_struct_constructor // Should NOT lint. // issue #7069. @@ -65,6 +66,7 @@ mod with_base { z, ..Default::default() }; + //~^^^^ inconsistent_struct_constructor // Should NOT lint because the order is consistent with the definition. Foo { diff --git a/tests/ui/inconsistent_struct_constructor.rs b/tests/ui/inconsistent_struct_constructor.rs index d49f236b9b07..8dd228e72ed7 100644 --- a/tests/ui/inconsistent_struct_constructor.rs +++ b/tests/ui/inconsistent_struct_constructor.rs @@ -34,6 +34,7 @@ mod without_base { // Should lint. Foo { y, x, z }; + //~^ inconsistent_struct_constructor // Should NOT lint. // issue #7069. @@ -65,6 +66,7 @@ mod with_base { x, ..Default::default() }; + //~^^^^ inconsistent_struct_constructor // Should NOT lint because the order is consistent with the definition. Foo { diff --git a/tests/ui/inconsistent_struct_constructor.stderr b/tests/ui/inconsistent_struct_constructor.stderr index c145eb2a239e..2f48a011d26f 100644 --- a/tests/ui/inconsistent_struct_constructor.stderr +++ b/tests/ui/inconsistent_struct_constructor.stderr @@ -8,7 +8,7 @@ LL | Foo { y, x, z }; = help: to override `-D warnings` add `#[allow(clippy::inconsistent_struct_constructor)]` error: struct constructor field order is inconsistent with struct definition field order - --> tests/ui/inconsistent_struct_constructor.rs:64:13 + --> tests/ui/inconsistent_struct_constructor.rs:65:13 | LL | / z, LL | | x, diff --git a/tests/ui/index_refutable_slice/if_let_slice_binding.fixed b/tests/ui/index_refutable_slice/if_let_slice_binding.fixed index ea8e56e18b08..e19aa4acb4c1 100644 --- a/tests/ui/index_refutable_slice/if_let_slice_binding.fixed +++ b/tests/ui/index_refutable_slice/if_let_slice_binding.fixed @@ -12,21 +12,24 @@ fn lintable_examples() { // Try with reference let slice: Option<&[u32]> = Some(&[1, 2, 3]); if let Some([slice_0, ..]) = slice { - //~^ ERROR: this binding can be a slice pattern to avoid indexing + //~^ index_refutable_slice + println!("{}", slice_0); } // Try with copy let slice: Option<[u32; 3]> = Some([1, 2, 3]); if let Some([slice_0, ..]) = slice { - //~^ ERROR: this binding can be a slice pattern to avoid indexing + //~^ index_refutable_slice + println!("{}", slice_0); } // Try with long slice and small indices let slice: Option<[u32; 9]> = Some([1, 2, 3, 4, 5, 6, 7, 8, 9]); if let Some([slice_0, _, slice_2, ..]) = slice { - //~^ ERROR: this binding can be a slice pattern to avoid indexing + //~^ index_refutable_slice + println!("{}", slice_2); println!("{}", slice_0); } @@ -34,7 +37,8 @@ fn lintable_examples() { // Multiple bindings let slice_wrapped: SomeEnum<[u32; 3]> = SomeEnum::One([5, 6, 7]); if let SomeEnum::One([slice_0, ..]) | SomeEnum::Three([slice_0, ..]) = slice_wrapped { - //~^ ERROR: this binding can be a slice pattern to avoid indexing + //~^ index_refutable_slice + println!("{}", slice_0); } @@ -42,8 +46,9 @@ fn lintable_examples() { let a_wrapped: SomeEnum<[u32; 3]> = SomeEnum::One([9, 5, 1]); let b_wrapped: Option<[u32; 2]> = Some([4, 6]); if let (SomeEnum::Three([_, _, a_2, ..]), Some([_, b_1, ..])) = (a_wrapped, b_wrapped) { - //~^ ERROR: this binding can be a slice pattern to avoid indexing - //~| ERROR: this binding can be a slice pattern to avoid indexing + //~^ index_refutable_slice + //~| index_refutable_slice + println!("{} -> {}", a_2, b_1); } @@ -51,7 +56,8 @@ fn lintable_examples() { // borrowed and `String` doesn't implement copy let slice: Option<[String; 2]> = Some([String::from("1"), String::from("2")]); if let Some([_, ref slice_1, ..]) = slice { - //~^ ERROR: this binding can be a slice pattern to avoid indexing + //~^ index_refutable_slice + println!("{:?}", slice_1); } println!("{:?}", slice); @@ -60,7 +66,8 @@ fn lintable_examples() { // a reference let slice: Option<[String; 2]> = Some([String::from("1"), String::from("2")]); if let Some([slice_0, ..]) = &slice { - //~^ ERROR: this binding can be a slice pattern to avoid indexing + //~^ index_refutable_slice + println!("{:?}", slice_0); } println!("{:?}", slice); @@ -130,7 +137,8 @@ fn check_slice_in_struct() { // Test 1: Field access if let Some([slice_0, ..]) = wrap.inner { - //~^ ERROR: this binding can be a slice pattern to avoid indexing + //~^ index_refutable_slice + if wrap.is_awesome { println!("This is awesome! {}", slice_0); } @@ -138,7 +146,8 @@ fn check_slice_in_struct() { // Test 2: function access if let Some([slice_0, ..]) = wrap.inner { - //~^ ERROR: this binding can be a slice pattern to avoid indexing + //~^ index_refutable_slice + if wrap.is_super_awesome() { println!("This is super awesome! {}", slice_0); } diff --git a/tests/ui/index_refutable_slice/if_let_slice_binding.rs b/tests/ui/index_refutable_slice/if_let_slice_binding.rs index 1c1d1c4cbe46..290393568554 100644 --- a/tests/ui/index_refutable_slice/if_let_slice_binding.rs +++ b/tests/ui/index_refutable_slice/if_let_slice_binding.rs @@ -12,21 +12,24 @@ fn lintable_examples() { // Try with reference let slice: Option<&[u32]> = Some(&[1, 2, 3]); if let Some(slice) = slice { - //~^ ERROR: this binding can be a slice pattern to avoid indexing + //~^ index_refutable_slice + println!("{}", slice[0]); } // Try with copy let slice: Option<[u32; 3]> = Some([1, 2, 3]); if let Some(slice) = slice { - //~^ ERROR: this binding can be a slice pattern to avoid indexing + //~^ index_refutable_slice + println!("{}", slice[0]); } // Try with long slice and small indices let slice: Option<[u32; 9]> = Some([1, 2, 3, 4, 5, 6, 7, 8, 9]); if let Some(slice) = slice { - //~^ ERROR: this binding can be a slice pattern to avoid indexing + //~^ index_refutable_slice + println!("{}", slice[2]); println!("{}", slice[0]); } @@ -34,7 +37,8 @@ fn lintable_examples() { // Multiple bindings let slice_wrapped: SomeEnum<[u32; 3]> = SomeEnum::One([5, 6, 7]); if let SomeEnum::One(slice) | SomeEnum::Three(slice) = slice_wrapped { - //~^ ERROR: this binding can be a slice pattern to avoid indexing + //~^ index_refutable_slice + println!("{}", slice[0]); } @@ -42,8 +46,9 @@ fn lintable_examples() { let a_wrapped: SomeEnum<[u32; 3]> = SomeEnum::One([9, 5, 1]); let b_wrapped: Option<[u32; 2]> = Some([4, 6]); if let (SomeEnum::Three(a), Some(b)) = (a_wrapped, b_wrapped) { - //~^ ERROR: this binding can be a slice pattern to avoid indexing - //~| ERROR: this binding can be a slice pattern to avoid indexing + //~^ index_refutable_slice + //~| index_refutable_slice + println!("{} -> {}", a[2], b[1]); } @@ -51,7 +56,8 @@ fn lintable_examples() { // borrowed and `String` doesn't implement copy let slice: Option<[String; 2]> = Some([String::from("1"), String::from("2")]); if let Some(ref slice) = slice { - //~^ ERROR: this binding can be a slice pattern to avoid indexing + //~^ index_refutable_slice + println!("{:?}", slice[1]); } println!("{:?}", slice); @@ -60,7 +66,8 @@ fn lintable_examples() { // a reference let slice: Option<[String; 2]> = Some([String::from("1"), String::from("2")]); if let Some(slice) = &slice { - //~^ ERROR: this binding can be a slice pattern to avoid indexing + //~^ index_refutable_slice + println!("{:?}", slice[0]); } println!("{:?}", slice); @@ -130,7 +137,8 @@ fn check_slice_in_struct() { // Test 1: Field access if let Some(slice) = wrap.inner { - //~^ ERROR: this binding can be a slice pattern to avoid indexing + //~^ index_refutable_slice + if wrap.is_awesome { println!("This is awesome! {}", slice[0]); } @@ -138,7 +146,8 @@ fn check_slice_in_struct() { // Test 2: function access if let Some(slice) = wrap.inner { - //~^ ERROR: this binding can be a slice pattern to avoid indexing + //~^ index_refutable_slice + if wrap.is_super_awesome() { println!("This is super awesome! {}", slice[0]); } diff --git a/tests/ui/index_refutable_slice/if_let_slice_binding.stderr b/tests/ui/index_refutable_slice/if_let_slice_binding.stderr index 14ee2e54cab1..04bc9838d0c2 100644 --- a/tests/ui/index_refutable_slice/if_let_slice_binding.stderr +++ b/tests/ui/index_refutable_slice/if_let_slice_binding.stderr @@ -13,11 +13,12 @@ help: replace the binding and indexed access with a slice pattern | LL ~ if let Some([slice_0, ..]) = slice { LL | +LL | LL ~ println!("{}", slice_0); | error: this binding can be a slice pattern to avoid indexing - --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:21:17 + --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:22:17 | LL | if let Some(slice) = slice { | ^^^^^ @@ -26,11 +27,12 @@ help: replace the binding and indexed access with a slice pattern | LL ~ if let Some([slice_0, ..]) = slice { LL | +LL | LL ~ println!("{}", slice_0); | error: this binding can be a slice pattern to avoid indexing - --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:28:17 + --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:30:17 | LL | if let Some(slice) = slice { | ^^^^^ @@ -39,12 +41,13 @@ help: replace the binding and indexed access with a slice pattern | LL ~ if let Some([slice_0, _, slice_2, ..]) = slice { LL | +LL | LL ~ println!("{}", slice_2); LL ~ println!("{}", slice_0); | error: this binding can be a slice pattern to avoid indexing - --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:36:26 + --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:39:26 | LL | if let SomeEnum::One(slice) | SomeEnum::Three(slice) = slice_wrapped { | ^^^^^ @@ -53,11 +56,12 @@ help: replace the binding and indexed access with a slice pattern | LL ~ if let SomeEnum::One([slice_0, ..]) | SomeEnum::Three([slice_0, ..]) = slice_wrapped { LL | +LL | LL ~ println!("{}", slice_0); | error: this binding can be a slice pattern to avoid indexing - --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:44:29 + --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:48:29 | LL | if let (SomeEnum::Three(a), Some(b)) = (a_wrapped, b_wrapped) { | ^ @@ -67,11 +71,12 @@ help: replace the binding and indexed access with a slice pattern LL ~ if let (SomeEnum::Three([_, _, a_2, ..]), Some(b)) = (a_wrapped, b_wrapped) { LL | LL | +LL | LL ~ println!("{} -> {}", a_2, b[1]); | error: this binding can be a slice pattern to avoid indexing - --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:44:38 + --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:48:38 | LL | if let (SomeEnum::Three(a), Some(b)) = (a_wrapped, b_wrapped) { | ^ @@ -81,11 +86,12 @@ help: replace the binding and indexed access with a slice pattern LL ~ if let (SomeEnum::Three(a), Some([_, b_1, ..])) = (a_wrapped, b_wrapped) { LL | LL | +LL | LL ~ println!("{} -> {}", a[2], b_1); | error: this binding can be a slice pattern to avoid indexing - --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:53:21 + --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:58:21 | LL | if let Some(ref slice) = slice { | ^^^^^ @@ -94,11 +100,12 @@ help: replace the binding and indexed access with a slice pattern | LL ~ if let Some([_, ref slice_1, ..]) = slice { LL | +LL | LL ~ println!("{:?}", slice_1); | error: this binding can be a slice pattern to avoid indexing - --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:62:17 + --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:68:17 | LL | if let Some(slice) = &slice { | ^^^^^ @@ -107,11 +114,12 @@ help: replace the binding and indexed access with a slice pattern | LL ~ if let Some([slice_0, ..]) = &slice { LL | +LL | LL ~ println!("{:?}", slice_0); | error: this binding can be a slice pattern to avoid indexing - --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:132:17 + --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:139:17 | LL | if let Some(slice) = wrap.inner { | ^^^^^ @@ -120,12 +128,13 @@ help: replace the binding and indexed access with a slice pattern | LL ~ if let Some([slice_0, ..]) = wrap.inner { LL | +LL | LL | if wrap.is_awesome { LL ~ println!("This is awesome! {}", slice_0); | error: this binding can be a slice pattern to avoid indexing - --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:140:17 + --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:148:17 | LL | if let Some(slice) = wrap.inner { | ^^^^^ @@ -134,6 +143,7 @@ help: replace the binding and indexed access with a slice pattern | LL ~ if let Some([slice_0, ..]) = wrap.inner { LL | +LL | LL | if wrap.is_super_awesome() { LL ~ println!("This is super awesome! {}", slice_0); | diff --git a/tests/ui/indexing_slicing_index.rs b/tests/ui/indexing_slicing_index.rs index 2af5fcc82a9b..cfa1c2f7c75f 100644 --- a/tests/ui/indexing_slicing_index.rs +++ b/tests/ui/indexing_slicing_index.rs @@ -49,8 +49,10 @@ fn main() { //~^ ERROR: indexing may panic // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays. x[4]; + //~^ out_of_bounds_indexing // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays. x[1 << 3]; + //~^ out_of_bounds_indexing // Ok, should not produce stderr. x[0]; @@ -66,12 +68,14 @@ fn main() { // This should be linted, since `suppress-restriction-lint-in-const` default is false. const { &ARR[idx4()] }; //~^ ERROR: indexing may panic + //~| ERROR: evaluation of `main let y = &x; // Ok, referencing shouldn't affect this lint. See the issue 6021 y[0]; // Ok, rustc will handle references too. y[4]; + //~^ out_of_bounds_indexing let v = vec![0; 5]; v[0]; @@ -87,6 +91,7 @@ fn main() { const M: usize = 3; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays. x[N]; + //~^ out_of_bounds_indexing // Ok, should not produce stderr. x[M]; v[N]; @@ -96,4 +101,5 @@ fn main() { let slice = &x; let _ = x[4]; + //~^ out_of_bounds_indexing } diff --git a/tests/ui/indexing_slicing_index.stderr b/tests/ui/indexing_slicing_index.stderr index 71677584d25b..50ee9b9edc75 100644 --- a/tests/ui/indexing_slicing_index.stderr +++ b/tests/ui/indexing_slicing_index.stderr @@ -10,13 +10,13 @@ LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-re = help: to override `-D warnings` add `#[allow(clippy::indexing_slicing)]` error[E0080]: evaluation of `main::{constant#3}` failed - --> tests/ui/indexing_slicing_index.rs:67:14 + --> tests/ui/indexing_slicing_index.rs:69:14 | LL | const { &ARR[idx4()] }; | ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4 note: erroneous constant encountered - --> tests/ui/indexing_slicing_index.rs:67:5 + --> tests/ui/indexing_slicing_index.rs:69:5 | LL | const { &ARR[idx4()] }; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -39,13 +39,13 @@ LL | x[4]; = help: to override `-D warnings` add `#[allow(clippy::out_of_bounds_indexing)]` error: index is out of bounds - --> tests/ui/indexing_slicing_index.rs:53:5 + --> tests/ui/indexing_slicing_index.rs:54:5 | LL | x[1 << 3]; | ^^^^^^^^^ error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:64:14 + --> tests/ui/indexing_slicing_index.rs:66:14 | LL | const { &ARR[idx()] }; | ^^^^^^^^^^ @@ -54,7 +54,7 @@ LL | const { &ARR[idx()] }; = note: the suggestion might not be applicable in constant blocks error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:67:14 + --> tests/ui/indexing_slicing_index.rs:69:14 | LL | const { &ARR[idx4()] }; | ^^^^^^^^^^^ @@ -63,13 +63,13 @@ LL | const { &ARR[idx4()] }; = note: the suggestion might not be applicable in constant blocks error: index is out of bounds - --> tests/ui/indexing_slicing_index.rs:74:5 + --> tests/ui/indexing_slicing_index.rs:77:5 | LL | y[4]; | ^^^^ error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:77:5 + --> tests/ui/indexing_slicing_index.rs:81:5 | LL | v[0]; | ^^^^ @@ -77,7 +77,7 @@ LL | v[0]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:79:5 + --> tests/ui/indexing_slicing_index.rs:83:5 | LL | v[10]; | ^^^^^ @@ -85,7 +85,7 @@ LL | v[10]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:81:5 + --> tests/ui/indexing_slicing_index.rs:85:5 | LL | v[1 << 3]; | ^^^^^^^^^ @@ -93,13 +93,13 @@ LL | v[1 << 3]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: index is out of bounds - --> tests/ui/indexing_slicing_index.rs:89:5 + --> tests/ui/indexing_slicing_index.rs:93:5 | LL | x[N]; | ^^^^ error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:92:5 + --> tests/ui/indexing_slicing_index.rs:97:5 | LL | v[N]; | ^^^^ @@ -107,7 +107,7 @@ LL | v[N]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:94:5 + --> tests/ui/indexing_slicing_index.rs:99:5 | LL | v[M]; | ^^^^ @@ -115,7 +115,7 @@ LL | v[M]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: index is out of bounds - --> tests/ui/indexing_slicing_index.rs:98:13 + --> tests/ui/indexing_slicing_index.rs:103:13 | LL | let _ = x[4]; | ^^^^ diff --git a/tests/ui/indexing_slicing_slice.rs b/tests/ui/indexing_slicing_slice.rs index f37bcc4aa0ca..cad77f56d03a 100644 --- a/tests/ui/indexing_slicing_slice.rs +++ b/tests/ui/indexing_slicing_slice.rs @@ -113,22 +113,21 @@ fn main() { let index_from: usize = 2; let index_to: usize = 3; &x[index..]; - //~^ ERROR: slicing may panic + //~^ indexing_slicing &x[..index]; - //~^ ERROR: slicing may panic + //~^ indexing_slicing &x[index_from..index_to]; - //~^ ERROR: slicing may panic + //~^ indexing_slicing &x[index_from..][..index_to]; - //~^ ERROR: slicing may panic - //~| ERROR: slicing may panic + //~^ indexing_slicing + //~| indexing_slicing &x[5..][..10]; - //~^ ERROR: slicing may panic - //~| ERROR: range is out of bounds - //~| NOTE: `-D clippy::out-of-bounds-indexing` implied by `-D warnings` + //~^ indexing_slicing + //~| out_of_bounds_indexing &x[0..][..3]; - //~^ ERROR: slicing may panic + //~^ indexing_slicing &x[1..][..5]; - //~^ ERROR: slicing may panic + //~^ indexing_slicing &x[0..].get(..3); // Ok, should not produce stderr. &x[0..3]; // Ok, should not produce stderr. @@ -136,22 +135,22 @@ fn main() { let y = &x; &y[1..2]; &y[0..=4]; - //~^ ERROR: range is out of bounds + //~^ out_of_bounds_indexing &y[..=4]; - //~^ ERROR: range is out of bounds + //~^ out_of_bounds_indexing &y[..]; // Ok, should not produce stderr. let v = vec![0; 5]; &v[10..100]; - //~^ ERROR: slicing may panic + //~^ indexing_slicing &x[10..][..100]; - //~^ ERROR: slicing may panic - //~| ERROR: range is out of bounds + //~^ indexing_slicing + //~| out_of_bounds_indexing &v[10..]; - //~^ ERROR: slicing may panic + //~^ indexing_slicing &v[..100]; - //~^ ERROR: slicing may panic + //~^ indexing_slicing &v[..]; // Ok, should not produce stderr. @@ -169,12 +168,15 @@ fn main() { // Lint on this, because `get` does exist with same signature map_with_get[true]; + //~^ indexing_slicing let s = S::(1); s[0]; + //~^ indexing_slicing let y = Y::(1); y[0]; + //~^ indexing_slicing let z = Z::(1); z[0]; diff --git a/tests/ui/indexing_slicing_slice.stderr b/tests/ui/indexing_slicing_slice.stderr index 1e72506746ec..e3ef89823e3d 100644 --- a/tests/ui/indexing_slicing_slice.stderr +++ b/tests/ui/indexing_slicing_slice.stderr @@ -58,7 +58,7 @@ LL | &x[5..][..10]; = help: to override `-D warnings` add `#[allow(clippy::out_of_bounds_indexing)]` error: slicing may panic - --> tests/ui/indexing_slicing_slice.rs:128:6 + --> tests/ui/indexing_slicing_slice.rs:127:6 | LL | &x[0..][..3]; | ^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | &x[0..][..3]; = help: consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic - --> tests/ui/indexing_slicing_slice.rs:130:6 + --> tests/ui/indexing_slicing_slice.rs:129:6 | LL | &x[1..][..5]; | ^^^^^^^^^^^ @@ -74,19 +74,19 @@ LL | &x[1..][..5]; = help: consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> tests/ui/indexing_slicing_slice.rs:138:12 + --> tests/ui/indexing_slicing_slice.rs:137:12 | LL | &y[0..=4]; | ^ error: range is out of bounds - --> tests/ui/indexing_slicing_slice.rs:140:11 + --> tests/ui/indexing_slicing_slice.rs:139:11 | LL | &y[..=4]; | ^ error: slicing may panic - --> tests/ui/indexing_slicing_slice.rs:146:6 + --> tests/ui/indexing_slicing_slice.rs:145:6 | LL | &v[10..100]; | ^^^^^^^^^^ @@ -94,7 +94,7 @@ LL | &v[10..100]; = help: consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic - --> tests/ui/indexing_slicing_slice.rs:148:6 + --> tests/ui/indexing_slicing_slice.rs:147:6 | LL | &x[10..][..100]; | ^^^^^^^^^^^^^^ @@ -102,13 +102,13 @@ LL | &x[10..][..100]; = help: consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> tests/ui/indexing_slicing_slice.rs:148:8 + --> tests/ui/indexing_slicing_slice.rs:147:8 | LL | &x[10..][..100]; | ^^ error: slicing may panic - --> tests/ui/indexing_slicing_slice.rs:151:6 + --> tests/ui/indexing_slicing_slice.rs:150:6 | LL | &v[10..]; | ^^^^^^^ @@ -116,7 +116,7 @@ LL | &v[10..]; = help: consider using `.get(n..)` or .get_mut(n..)` instead error: slicing may panic - --> tests/ui/indexing_slicing_slice.rs:153:6 + --> tests/ui/indexing_slicing_slice.rs:152:6 | LL | &v[..100]; | ^^^^^^^^ @@ -124,7 +124,7 @@ LL | &v[..100]; = help: consider using `.get(..n)`or `.get_mut(..n)` instead error: indexing may panic - --> tests/ui/indexing_slicing_slice.rs:171:5 + --> tests/ui/indexing_slicing_slice.rs:170:5 | LL | map_with_get[true]; | ^^^^^^^^^^^^^^^^^^ @@ -140,7 +140,7 @@ LL | s[0]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> tests/ui/indexing_slicing_slice.rs:177:5 + --> tests/ui/indexing_slicing_slice.rs:178:5 | LL | y[0]; | ^^^^ diff --git a/tests/ui/ineffective_open_options.fixed b/tests/ui/ineffective_open_options.fixed index 88489dc46bbb..03b73f99961a 100644 --- a/tests/ui/ineffective_open_options.fixed +++ b/tests/ui/ineffective_open_options.fixed @@ -5,7 +5,8 @@ use std::fs::OpenOptions; fn main() { let file = OpenOptions::new() .create(true) - //~ ERROR: unnecessary use of `.write(true)` + + //~^ ineffective_open_options .append(true) .open("dump.json") .unwrap(); @@ -13,7 +14,8 @@ fn main() { let file = OpenOptions::new() .create(true) .append(true) - //~ ERROR: unnecessary use of `.write(true)` + + //~^ ineffective_open_options .open("dump.json") .unwrap(); diff --git a/tests/ui/ineffective_open_options.rs b/tests/ui/ineffective_open_options.rs index db8bca3e2acd..e333a71490fb 100644 --- a/tests/ui/ineffective_open_options.rs +++ b/tests/ui/ineffective_open_options.rs @@ -5,7 +5,8 @@ use std::fs::OpenOptions; fn main() { let file = OpenOptions::new() .create(true) - .write(true) //~ ERROR: unnecessary use of `.write(true)` + .write(true) + //~^ ineffective_open_options .append(true) .open("dump.json") .unwrap(); @@ -13,7 +14,8 @@ fn main() { let file = OpenOptions::new() .create(true) .append(true) - .write(true) //~ ERROR: unnecessary use of `.write(true)` + .write(true) + //~^ ineffective_open_options .open("dump.json") .unwrap(); diff --git a/tests/ui/ineffective_open_options.stderr b/tests/ui/ineffective_open_options.stderr index 0d6933bb449e..42bb0438dcee 100644 --- a/tests/ui/ineffective_open_options.stderr +++ b/tests/ui/ineffective_open_options.stderr @@ -8,7 +8,7 @@ LL | .write(true) = help: to override `-D warnings` add `#[allow(clippy::ineffective_open_options)]` error: unnecessary use of `.write(true)` because there is `.append(true)` - --> tests/ui/ineffective_open_options.rs:16:9 + --> tests/ui/ineffective_open_options.rs:17:9 | LL | .write(true) | ^^^^^^^^^^^^ help: remove `.write(true)` diff --git a/tests/ui/inefficient_to_string.fixed b/tests/ui/inefficient_to_string.fixed index 1e19323113c5..a0d34e58a925 100644 --- a/tests/ui/inefficient_to_string.fixed +++ b/tests/ui/inefficient_to_string.fixed @@ -8,7 +8,9 @@ fn main() { let rrrstr: &&&str = &rrstr; let _: String = rstr.to_string(); let _: String = (*rrstr).to_string(); + //~^ inefficient_to_string let _: String = (**rrrstr).to_string(); + //~^ inefficient_to_string let string: String = String::from("hello"); let rstring: &String = &string; @@ -17,7 +19,9 @@ fn main() { let _: String = string.to_string(); let _: String = rstring.to_string(); let _: String = (*rrstring).to_string(); + //~^ inefficient_to_string let _: String = (**rrrstring).to_string(); + //~^ inefficient_to_string let cow: Cow<'_, str> = Cow::Borrowed("hello"); let rcow: &Cow<'_, str> = &cow; @@ -26,5 +30,7 @@ fn main() { let _: String = cow.to_string(); let _: String = rcow.to_string(); let _: String = (*rrcow).to_string(); + //~^ inefficient_to_string let _: String = (**rrrcow).to_string(); + //~^ inefficient_to_string } diff --git a/tests/ui/inefficient_to_string.rs b/tests/ui/inefficient_to_string.rs index f027bae6fe34..cbe90d4a125b 100644 --- a/tests/ui/inefficient_to_string.rs +++ b/tests/ui/inefficient_to_string.rs @@ -8,7 +8,9 @@ fn main() { let rrrstr: &&&str = &rrstr; let _: String = rstr.to_string(); let _: String = rrstr.to_string(); + //~^ inefficient_to_string let _: String = rrrstr.to_string(); + //~^ inefficient_to_string let string: String = String::from("hello"); let rstring: &String = &string; @@ -17,7 +19,9 @@ fn main() { let _: String = string.to_string(); let _: String = rstring.to_string(); let _: String = rrstring.to_string(); + //~^ inefficient_to_string let _: String = rrrstring.to_string(); + //~^ inefficient_to_string let cow: Cow<'_, str> = Cow::Borrowed("hello"); let rcow: &Cow<'_, str> = &cow; @@ -26,5 +30,7 @@ fn main() { let _: String = cow.to_string(); let _: String = rcow.to_string(); let _: String = rrcow.to_string(); + //~^ inefficient_to_string let _: String = rrrcow.to_string(); + //~^ inefficient_to_string } diff --git a/tests/ui/inefficient_to_string.stderr b/tests/ui/inefficient_to_string.stderr index e71e667cf0cf..8593c0addc5f 100644 --- a/tests/ui/inefficient_to_string.stderr +++ b/tests/ui/inefficient_to_string.stderr @@ -12,7 +12,7 @@ LL | #![deny(clippy::inefficient_to_string)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: calling `to_string` on `&&&str` - --> tests/ui/inefficient_to_string.rs:11:21 + --> tests/ui/inefficient_to_string.rs:12:21 | LL | let _: String = rrrstr.to_string(); | ^^^^^^^^^^^^^^^^^^ help: try dereferencing the receiver: `(**rrrstr).to_string()` @@ -20,7 +20,7 @@ LL | let _: String = rrrstr.to_string(); = help: `&&str` implements `ToString` through a slower blanket impl, but `str` has a fast specialization of `ToString` error: calling `to_string` on `&&std::string::String` - --> tests/ui/inefficient_to_string.rs:19:21 + --> tests/ui/inefficient_to_string.rs:21:21 | LL | let _: String = rrstring.to_string(); | ^^^^^^^^^^^^^^^^^^^^ help: try dereferencing the receiver: `(*rrstring).to_string()` @@ -28,7 +28,7 @@ LL | let _: String = rrstring.to_string(); = help: `&std::string::String` implements `ToString` through a slower blanket impl, but `std::string::String` has a fast specialization of `ToString` error: calling `to_string` on `&&&std::string::String` - --> tests/ui/inefficient_to_string.rs:20:21 + --> tests/ui/inefficient_to_string.rs:23:21 | LL | let _: String = rrrstring.to_string(); | ^^^^^^^^^^^^^^^^^^^^^ help: try dereferencing the receiver: `(**rrrstring).to_string()` @@ -36,7 +36,7 @@ LL | let _: String = rrrstring.to_string(); = help: `&&std::string::String` implements `ToString` through a slower blanket impl, but `std::string::String` has a fast specialization of `ToString` error: calling `to_string` on `&&std::borrow::Cow<'_, str>` - --> tests/ui/inefficient_to_string.rs:28:21 + --> tests/ui/inefficient_to_string.rs:32:21 | LL | let _: String = rrcow.to_string(); | ^^^^^^^^^^^^^^^^^ help: try dereferencing the receiver: `(*rrcow).to_string()` @@ -44,7 +44,7 @@ LL | let _: String = rrcow.to_string(); = help: `&std::borrow::Cow<'_, str>` implements `ToString` through a slower blanket impl, but `std::borrow::Cow<'_, str>` has a fast specialization of `ToString` error: calling `to_string` on `&&&std::borrow::Cow<'_, str>` - --> tests/ui/inefficient_to_string.rs:29:21 + --> tests/ui/inefficient_to_string.rs:34:21 | LL | let _: String = rrrcow.to_string(); | ^^^^^^^^^^^^^^^^^^ help: try dereferencing the receiver: `(**rrrcow).to_string()` diff --git a/tests/ui/infallible_destructuring_match.rs b/tests/ui/infallible_destructuring_match.rs index 7cc7cb9d6878..5db30ebca88f 100644 --- a/tests/ui/infallible_destructuring_match.rs +++ b/tests/ui/infallible_destructuring_match.rs @@ -26,6 +26,7 @@ fn infallible_destructuring_match_enum() { // This should lint! let data = match wrapper { + //~^ infallible_destructuring_match SingleVariantEnum::Variant(i) => i, }; @@ -58,6 +59,7 @@ fn infallible_destructuring_match_struct() { // This should lint! let data = match wrapper { + //~^ infallible_destructuring_match TupleStruct(i) => i, }; @@ -82,6 +84,7 @@ fn infallible_destructuring_match_struct_with_noncopy() { // This should lint! (keeping `ref` in the suggestion) let data = match wrapper { + //~^ infallible_destructuring_match TupleStructWithNonCopy(ref n) => n, }; @@ -101,6 +104,7 @@ fn never_enum() { // This should lint! let data = match wrapper { + //~^ infallible_destructuring_match Ok(i) => i, }; diff --git a/tests/ui/infallible_destructuring_match.stderr b/tests/ui/infallible_destructuring_match.stderr index b709fd8630e9..1e784bc598bf 100644 --- a/tests/ui/infallible_destructuring_match.stderr +++ b/tests/ui/infallible_destructuring_match.stderr @@ -2,6 +2,7 @@ error: you seem to be trying to use `match` to destructure a single infallible p --> tests/ui/infallible_destructuring_match.rs:28:5 | LL | / let data = match wrapper { +LL | | LL | | SingleVariantEnum::Variant(i) => i, LL | | }; | |______^ help: try: `let SingleVariantEnum::Variant(data) = wrapper;` @@ -10,25 +11,28 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::infallible_destructuring_match)]` error: you seem to be trying to use `match` to destructure a single infallible pattern. Consider using `let` - --> tests/ui/infallible_destructuring_match.rs:60:5 + --> tests/ui/infallible_destructuring_match.rs:61:5 | LL | / let data = match wrapper { +LL | | LL | | TupleStruct(i) => i, LL | | }; | |______^ help: try: `let TupleStruct(data) = wrapper;` error: you seem to be trying to use `match` to destructure a single infallible pattern. Consider using `let` - --> tests/ui/infallible_destructuring_match.rs:84:5 + --> tests/ui/infallible_destructuring_match.rs:86:5 | LL | / let data = match wrapper { +LL | | LL | | TupleStructWithNonCopy(ref n) => n, LL | | }; | |______^ help: try: `let TupleStructWithNonCopy(ref data) = wrapper;` error: you seem to be trying to use `match` to destructure a single infallible pattern. Consider using `let` - --> tests/ui/infallible_destructuring_match.rs:103:5 + --> tests/ui/infallible_destructuring_match.rs:106:5 | LL | / let data = match wrapper { +LL | | LL | | Ok(i) => i, LL | | }; | |______^ help: try: `let Ok(data) = wrapper;` diff --git a/tests/ui/infinite_iter.rs b/tests/ui/infinite_iter.rs index 178e300ff5bf..002a791a6579 100644 --- a/tests/ui/infinite_iter.rs +++ b/tests/ui/infinite_iter.rs @@ -9,13 +9,16 @@ fn square_is_lower_64(x: &u32) -> bool { #[deny(clippy::infinite_iter)] fn infinite_iters() { repeat(0_u8).collect::>(); - //~^ ERROR: infinite iteration detected + //~^ infinite_iter + // infinite iter (0..8_u32).take_while(square_is_lower_64).cycle().count(); - //~^ ERROR: infinite iteration detected + //~^ infinite_iter + // infinite iter (0..8_u64).chain(0..).max(); - //~^ ERROR: infinite iteration detected + //~^ infinite_iter + // infinite iter (0_usize..) .chain([0usize, 1, 2].iter().cloned()) @@ -23,7 +26,7 @@ fn infinite_iters() { .min(); // infinite iter (0..8_u32) - //~^ ERROR: infinite iteration detected + //~^ infinite_iter .rev() .cycle() .map(|x| x + 1_u32) @@ -32,10 +35,12 @@ fn infinite_iters() { (0..3_u32).flat_map(|x| x..).sum::(); // infinite iter (0_usize..).flat_map(|x| 0..x).product::(); - //~^ ERROR: infinite iteration detected + //~^ infinite_iter + // infinite iter (0_u64..).filter(|x| x % 2 == 0).last(); - //~^ ERROR: infinite iteration detected + //~^ infinite_iter + // not an infinite, because ranges are double-ended (0..42_u64).by_ref().last(); // iterator is not exhausted @@ -46,13 +51,15 @@ fn infinite_iters() { fn potential_infinite_iters() { // maybe infinite iter (0..).zip((0..).take_while(square_is_lower_64)).count(); - //~^ ERROR: possible infinite iteration detected + //~^ maybe_infinite_iter + // maybe infinite iter repeat(42).take_while(|x| *x == 42).chain(0..42).max(); - //~^ ERROR: possible infinite iteration detected + //~^ maybe_infinite_iter + // maybe infinite iter (1..) - //~^ ERROR: possible infinite iteration detected + //~^ maybe_infinite_iter .scan(0, |state, x| { *state += x; Some(*state) @@ -60,16 +67,19 @@ fn potential_infinite_iters() { .min(); // maybe infinite iter (0..).find(|x| *x == 24); - //~^ ERROR: possible infinite iteration detected + //~^ maybe_infinite_iter + // maybe infinite iter (0..).position(|x| x == 24); - //~^ ERROR: possible infinite iteration detected + //~^ maybe_infinite_iter + // maybe infinite iter (0..).any(|x| x == 24); - //~^ ERROR: possible infinite iteration detected + //~^ maybe_infinite_iter + // maybe infinite iter (0..).all(|x| x == 24); - //~^ ERROR: possible infinite iteration detected + //~^ maybe_infinite_iter // not infinite (0..).zip(0..42).take_while(|&(x, _)| x != 42).count(); @@ -95,8 +105,7 @@ mod finite_collect { fn check_collect() { // Infinite iter let _: HashSet = (0..).collect(); - //~^ ERROR: infinite iteration detected - //~| NOTE: `#[deny(clippy::infinite_iter)]` on by default + //~^ infinite_iter // Some data structures don't collect infinitely, such as `ArrayVec` let _: C = (0..).collect(); diff --git a/tests/ui/infinite_iter.stderr b/tests/ui/infinite_iter.stderr index e33d83b75edb..47133a2ea62e 100644 --- a/tests/ui/infinite_iter.stderr +++ b/tests/ui/infinite_iter.stderr @@ -11,19 +11,19 @@ LL | #[deny(clippy::infinite_iter)] | ^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> tests/ui/infinite_iter.rs:14:5 + --> tests/ui/infinite_iter.rs:15:5 | LL | (0..8_u32).take_while(square_is_lower_64).cycle().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> tests/ui/infinite_iter.rs:17:5 + --> tests/ui/infinite_iter.rs:19:5 | LL | (0..8_u64).chain(0..).max(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> tests/ui/infinite_iter.rs:25:5 + --> tests/ui/infinite_iter.rs:28:5 | LL | / (0..8_u32) LL | | @@ -34,37 +34,37 @@ LL | | .for_each(|x| println!("{}", x)); | |________________________________________^ error: infinite iteration detected - --> tests/ui/infinite_iter.rs:34:5 + --> tests/ui/infinite_iter.rs:37:5 | LL | (0_usize..).flat_map(|x| 0..x).product::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> tests/ui/infinite_iter.rs:37:5 + --> tests/ui/infinite_iter.rs:41:5 | LL | (0_u64..).filter(|x| x % 2 == 0).last(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> tests/ui/infinite_iter.rs:48:5 + --> tests/ui/infinite_iter.rs:53:5 | LL | (0..).zip((0..).take_while(square_is_lower_64)).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> tests/ui/infinite_iter.rs:45:8 + --> tests/ui/infinite_iter.rs:50:8 | LL | #[deny(clippy::maybe_infinite_iter)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> tests/ui/infinite_iter.rs:51:5 + --> tests/ui/infinite_iter.rs:57:5 | LL | repeat(42).take_while(|x| *x == 42).chain(0..42).max(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> tests/ui/infinite_iter.rs:54:5 + --> tests/ui/infinite_iter.rs:61:5 | LL | / (1..) LL | | @@ -76,31 +76,31 @@ LL | | .min(); | |______________^ error: possible infinite iteration detected - --> tests/ui/infinite_iter.rs:62:5 + --> tests/ui/infinite_iter.rs:69:5 | LL | (0..).find(|x| *x == 24); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> tests/ui/infinite_iter.rs:65:5 + --> tests/ui/infinite_iter.rs:73:5 | LL | (0..).position(|x| x == 24); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> tests/ui/infinite_iter.rs:68:5 + --> tests/ui/infinite_iter.rs:77:5 | LL | (0..).any(|x| x == 24); | ^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> tests/ui/infinite_iter.rs:71:5 + --> tests/ui/infinite_iter.rs:81:5 | LL | (0..).all(|x| x == 24); | ^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> tests/ui/infinite_iter.rs:97:31 + --> tests/ui/infinite_iter.rs:107:31 | LL | let _: HashSet = (0..).collect(); | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/infinite_loop.rs b/tests/ui/infinite_loop.rs index 765c67011474..4a0968918bfb 100644 --- a/tests/ui/infinite_loop.rs +++ b/tests/ui/infinite_loop.rs @@ -20,15 +20,15 @@ fn immutable_condition() { // Should warn when all vars mentioned are immutable let y = 0; while y < 10 { - //~^ ERROR: variables in the condition are not mutated in the loop body - //~| NOTE: this may lead to an infinite or to a never running loop + //~^ while_immutable_condition + println!("KO - y is immutable"); } let x = 0; while y < 10 && x < 3 { - //~^ ERROR: variables in the condition are not mutated in the loop body - //~| NOTE: this may lead to an infinite or to a never running loop + //~^ while_immutable_condition + let mut k = 1; k += 2; println!("KO - x and y immutable"); @@ -36,8 +36,8 @@ fn immutable_condition() { let cond = false; while !cond { - //~^ ERROR: variables in the condition are not mutated in the loop body - //~| NOTE: this may lead to an infinite or to a never running loop + //~^ while_immutable_condition + println!("KO - cond immutable"); } @@ -82,21 +82,21 @@ fn unused_var() { let (mut i, mut j) = (0, 0); while i < 3 { - //~^ ERROR: variables in the condition are not mutated in the loop body - //~| NOTE: this may lead to an infinite or to a never running loop + //~^ while_immutable_condition + j = 3; println!("KO - i not mentioned"); } while i < 3 && j > 0 { - //~^ ERROR: variables in the condition are not mutated in the loop body - //~| NOTE: this may lead to an infinite or to a never running loop + //~^ while_immutable_condition + println!("KO - i and j not mentioned"); } while i < 3 { - //~^ ERROR: variables in the condition are not mutated in the loop body - //~| NOTE: this may lead to an infinite or to a never running loop + //~^ while_immutable_condition + let mut i = 5; fn_mutref(&mut i); println!("KO - shadowed"); @@ -112,15 +112,15 @@ fn used_immutable() { let mut i = 0; while i < 3 { - //~^ ERROR: variables in the condition are not mutated in the loop body - //~| NOTE: this may lead to an infinite or to a never running loop + //~^ while_immutable_condition + fn_constref(&i); println!("KO - const reference"); } while i < 3 { - //~^ ERROR: variables in the condition are not mutated in the loop body - //~| NOTE: this may lead to an infinite or to a never running loop + //~^ while_immutable_condition + fn_val(i); println!("KO - passed by value"); } @@ -187,8 +187,8 @@ impl Counter { fn print_n(&self, n: usize) { while self.count < n { - //~^ ERROR: variables in the condition are not mutated in the loop body - //~| NOTE: this may lead to an infinite or to a never running loop + //~^ while_immutable_condition + println!("KO - {} is not mutated", self.count); } } @@ -197,8 +197,8 @@ impl Counter { fn while_loop_with_break_and_return() { let y = 0; while y < 10 { - //~^ ERROR: variables in the condition are not mutated in the loop body - //~| NOTE: this may lead to an infinite or to a never running loop + //~^ while_immutable_condition + if y == 0 { break; } @@ -206,8 +206,8 @@ fn while_loop_with_break_and_return() { } while y < 10 { - //~^ ERROR: variables in the condition are not mutated in the loop body - //~| NOTE: this may lead to an infinite or to a never running loop + //~^ while_immutable_condition + if y == 0 { return; } diff --git a/tests/ui/infinite_loops.rs b/tests/ui/infinite_loops.rs index d7be6f9ce7e9..eaa8d0088068 100644 --- a/tests/ui/infinite_loops.rs +++ b/tests/ui/infinite_loops.rs @@ -11,18 +11,18 @@ fn do_something() {} fn no_break() { loop { - //~^ ERROR: infinite loop detected + //~^ infinite_loop do_something(); } } fn all_inf() { loop { - //~^ ERROR: infinite loop detected + //~^ infinite_loop loop { - //~^ ERROR: infinite loop detected + //~^ infinite_loop loop { - //~^ ERROR: infinite loop detected + //~^ infinite_loop do_something(); } } @@ -36,7 +36,7 @@ fn no_break_return_some_ty() -> Option { return None; } loop { - //~^ ERROR: infinite loop detected + //~^ infinite_loop do_something(); } } @@ -49,6 +49,7 @@ fn no_break_never_ret() -> ! { fn no_break_never_ret_noise() { loop { + //~^ infinite_loop fn inner_fn() -> ! { std::process::exit(0); } @@ -92,7 +93,7 @@ fn has_indirect_break_2(stop_num: i32) { fn break_inner_but_not_outer_1(cond: bool) { loop { - //~^ ERROR: infinite loop detected + //~^ infinite_loop loop { if cond { break; @@ -103,7 +104,7 @@ fn break_inner_but_not_outer_1(cond: bool) { fn break_inner_but_not_outer_2(cond: bool) { loop { - //~^ ERROR: infinite loop detected + //~^ infinite_loop 'inner: loop { loop { if cond { @@ -117,7 +118,7 @@ fn break_inner_but_not_outer_2(cond: bool) { fn break_outer_but_not_inner() { loop { loop { - //~^ ERROR: infinite loop detected + //~^ infinite_loop do_something(); } break; @@ -140,7 +141,7 @@ fn break_wrong_loop(cond: bool) { // 'inner has statement to break 'outer loop, but it was broken out of early by a labeled child loop 'outer: loop { loop { - //~^ ERROR: infinite loop detected + //~^ infinite_loop 'inner: loop { loop { loop { @@ -180,7 +181,7 @@ enum Foo { fn match_like() { let opt: Option = Some(1); loop { - //~^ ERROR: infinite loop detected + //~^ infinite_loop match opt { Some(v) => { println!("{v}"); @@ -221,12 +222,12 @@ fn match_like() { } loop { - //~^ ERROR: infinite loop detected + //~^ infinite_loop let _x = matches!(result, Ok(v) if v != 0).then_some(0); } loop { - //~^ ERROR: infinite loop detected + //~^ infinite_loop // This `return` does not return the function, so it doesn't count let _x = matches!(result, Ok(v) if v != 0).then(|| { if true { @@ -331,7 +332,7 @@ fn exit_directly(cond: bool) { trait MyTrait { fn problematic_trait_method() { loop { - //~^ ERROR: infinite loop detected + //~^ infinite_loop do_something(); } } @@ -341,7 +342,7 @@ trait MyTrait { impl MyTrait for String { fn could_be_problematic() { loop { - //~^ ERROR: infinite loop detected + //~^ infinite_loop do_something(); } } @@ -350,7 +351,7 @@ impl MyTrait for String { fn inf_loop_in_closure() { let _loop_forever = || { loop { - //~^ ERROR: infinite loop detected + //~^ infinite_loop do_something(); } }; @@ -364,6 +365,7 @@ fn inf_loop_in_closure() { fn inf_loop_in_res() -> Result<(), i32> { Ok(loop { + //~^ infinite_loop do_something() }) } @@ -406,15 +408,16 @@ fn continue_outer() { // This should lint as we continue the loop itself 'infinite: loop { - //~^ ERROR: infinite loop detected + //~^ infinite_loop loop { continue 'infinite; } } // This should lint as we continue an inner loop loop { - //~^ ERROR: infinite loop detected + //~^ infinite_loop 'inner: loop { + //~^ infinite_loop loop { continue 'inner; } @@ -423,7 +426,7 @@ fn continue_outer() { // This should lint as we continue the loop itself loop { - //~^ ERROR: infinite loop detected + //~^ infinite_loop continue; } } diff --git a/tests/ui/infinite_loops.stderr b/tests/ui/infinite_loops.stderr index 3b5705d5f21d..4d02636ef4ae 100644 --- a/tests/ui/infinite_loops.stderr +++ b/tests/ui/infinite_loops.stderr @@ -74,9 +74,11 @@ error: infinite loop detected --> tests/ui/infinite_loops.rs:51:5 | LL | / loop { +LL | | LL | | fn inner_fn() -> ! { LL | | std::process::exit(0); -... | +LL | | } +LL | | do_something(); LL | | } | |_____^ | @@ -86,7 +88,7 @@ LL | fn no_break_never_ret_noise() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:94:5 + --> tests/ui/infinite_loops.rs:95:5 | LL | / loop { LL | | @@ -102,7 +104,7 @@ LL | fn break_inner_but_not_outer_1(cond: bool) -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:105:5 + --> tests/ui/infinite_loops.rs:106:5 | LL | / loop { LL | | @@ -118,7 +120,7 @@ LL | fn break_inner_but_not_outer_2(cond: bool) -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:119:9 + --> tests/ui/infinite_loops.rs:120:9 | LL | / loop { LL | | @@ -132,7 +134,7 @@ LL | fn break_outer_but_not_inner() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:142:9 + --> tests/ui/infinite_loops.rs:143:9 | LL | / loop { LL | | @@ -148,7 +150,7 @@ LL | fn break_wrong_loop(cond: bool) -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:182:5 + --> tests/ui/infinite_loops.rs:183:5 | LL | / loop { LL | | @@ -164,7 +166,7 @@ LL | fn match_like() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:223:5 + --> tests/ui/infinite_loops.rs:224:5 | LL | / loop { LL | | @@ -178,7 +180,7 @@ LL | fn match_like() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:228:5 + --> tests/ui/infinite_loops.rs:229:5 | LL | / loop { LL | | @@ -195,7 +197,7 @@ LL | fn match_like() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:333:9 + --> tests/ui/infinite_loops.rs:334:9 | LL | / loop { LL | | @@ -209,7 +211,7 @@ LL | fn problematic_trait_method() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:343:9 + --> tests/ui/infinite_loops.rs:344:9 | LL | / loop { LL | | @@ -223,7 +225,7 @@ LL | fn could_be_problematic() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:352:9 + --> tests/ui/infinite_loops.rs:353:9 | LL | / loop { LL | | @@ -237,10 +239,11 @@ LL | let _loop_forever = || -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:366:8 + --> tests/ui/infinite_loops.rs:367:8 | LL | Ok(loop { | ________^ +LL | | LL | | do_something() LL | | }) | |_____^ @@ -248,7 +251,7 @@ LL | | }) = help: if this is not intended, try adding a `break` or `return` condition in the loop error: infinite loop detected - --> tests/ui/infinite_loops.rs:408:5 + --> tests/ui/infinite_loops.rs:410:5 | LL | / 'infinite: loop { LL | | @@ -264,12 +267,11 @@ LL | fn continue_outer() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:415:5 + --> tests/ui/infinite_loops.rs:417:5 | LL | / loop { LL | | LL | | 'inner: loop { -LL | | loop { ... | LL | | } | |_____^ @@ -280,9 +282,10 @@ LL | fn continue_outer() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:417:9 + --> tests/ui/infinite_loops.rs:419:9 | LL | / 'inner: loop { +LL | | LL | | loop { LL | | continue 'inner; LL | | } @@ -295,7 +298,7 @@ LL | fn continue_outer() -> ! { | ++++ error: infinite loop detected - --> tests/ui/infinite_loops.rs:425:5 + --> tests/ui/infinite_loops.rs:428:5 | LL | / loop { LL | | diff --git a/tests/ui/inherent_to_string.rs b/tests/ui/inherent_to_string.rs index 7b938cdd758c..30977f2d93ac 100644 --- a/tests/ui/inherent_to_string.rs +++ b/tests/ui/inherent_to_string.rs @@ -20,7 +20,8 @@ struct J; impl A { // Should be detected; emit warning fn to_string(&self) -> String { - //~^ ERROR: implementation of inherent method `to_string(&self) -> String` for type `A + //~^ inherent_to_string + "A.to_string()".to_string() } @@ -45,7 +46,8 @@ impl B { impl C { // Should be detected and emit error as C also implements Display fn to_string(&self) -> String { - //~^ ERROR: type `C` implements inherent method `to_string(&self) -> String` which sha + //~^ inherent_to_string_shadow_display + "C.to_string()".to_string() } } diff --git a/tests/ui/inherent_to_string.stderr b/tests/ui/inherent_to_string.stderr index eb22525a2491..f1d415a45755 100644 --- a/tests/ui/inherent_to_string.stderr +++ b/tests/ui/inherent_to_string.stderr @@ -3,6 +3,7 @@ error: implementation of inherent method `to_string(&self) -> String` for type ` | LL | / fn to_string(&self) -> String { LL | | +LL | | LL | | "A.to_string()".to_string() LL | | } | |_____^ @@ -12,10 +13,11 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::inherent_to_string)]` error: type `C` implements inherent method `to_string(&self) -> String` which shadows the implementation of `Display` - --> tests/ui/inherent_to_string.rs:47:5 + --> tests/ui/inherent_to_string.rs:48:5 | LL | / fn to_string(&self) -> String { LL | | +LL | | LL | | "C.to_string()".to_string() LL | | } | |_____^ diff --git a/tests/ui/init_numbered_fields.fixed b/tests/ui/init_numbered_fields.fixed index dca4e8da4d2f..b4c5fa83ce95 100644 --- a/tests/ui/init_numbered_fields.fixed +++ b/tests/ui/init_numbered_fields.fixed @@ -39,6 +39,7 @@ fn main() { struct TupleStructVec(Vec); let _ = TupleStructVec(vec![0, 1, 2, 3]); + //~^ init_numbered_fields { struct S(i32, i32); diff --git a/tests/ui/init_numbered_fields.rs b/tests/ui/init_numbered_fields.rs index 8cb34705b4f6..ae5dfe889575 100644 --- a/tests/ui/init_numbered_fields.rs +++ b/tests/ui/init_numbered_fields.rs @@ -15,6 +15,7 @@ fn main() { // This should lint let _ = TupleStruct { + //~^ init_numbered_fields 0: 1u32, 1: 42, 2: 23u8, @@ -22,6 +23,7 @@ fn main() { // This should also lint and order the fields correctly let _ = TupleStruct { + //~^ init_numbered_fields 0: 1u32, 2: 2u8, 1: 3u32, @@ -47,6 +49,7 @@ fn main() { struct TupleStructVec(Vec); let _ = TupleStructVec { 0: vec![0, 1, 2, 3] }; + //~^ init_numbered_fields { struct S(i32, i32); diff --git a/tests/ui/init_numbered_fields.stderr b/tests/ui/init_numbered_fields.stderr index f176e0c2ff30..89828b7e2fce 100644 --- a/tests/ui/init_numbered_fields.stderr +++ b/tests/ui/init_numbered_fields.stderr @@ -3,6 +3,7 @@ error: used a field initializer for a tuple struct | LL | let _ = TupleStruct { | _____________^ +LL | | LL | | 0: 1u32, LL | | 1: 42, LL | | 2: 23u8, @@ -13,10 +14,11 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::init_numbered_fields)]` error: used a field initializer for a tuple struct - --> tests/ui/init_numbered_fields.rs:24:13 + --> tests/ui/init_numbered_fields.rs:25:13 | LL | let _ = TupleStruct { | _____________^ +LL | | LL | | 0: 1u32, LL | | 2: 2u8, LL | | 1: 3u32, @@ -24,7 +26,7 @@ LL | | }; | |_____^ help: use tuple initialization: `TupleStruct(1u32, 3u32, 2u8)` error: used a field initializer for a tuple struct - --> tests/ui/init_numbered_fields.rs:49:13 + --> tests/ui/init_numbered_fields.rs:51:13 | LL | let _ = TupleStructVec { 0: vec![0, 1, 2, 3] }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use tuple initialization: `TupleStructVec(vec![0, 1, 2, 3])` diff --git a/tests/ui/inline_fn_without_body.fixed b/tests/ui/inline_fn_without_body.fixed index acd808ed49bb..3567209b41f7 100644 --- a/tests/ui/inline_fn_without_body.fixed +++ b/tests/ui/inline_fn_without_body.fixed @@ -2,10 +2,13 @@ #![allow(clippy::inline_always)] trait Foo { + //~^ inline_fn_without_body fn default_inline(); + //~^ inline_fn_without_body fn always_inline(); + //~^ inline_fn_without_body fn never_inline(); #[inline] diff --git a/tests/ui/inline_fn_without_body.rs b/tests/ui/inline_fn_without_body.rs index af81feaa374a..9ca90e637f15 100644 --- a/tests/ui/inline_fn_without_body.rs +++ b/tests/ui/inline_fn_without_body.rs @@ -3,12 +3,15 @@ trait Foo { #[inline] + //~^ inline_fn_without_body fn default_inline(); #[inline(always)] + //~^ inline_fn_without_body fn always_inline(); #[inline(never)] + //~^ inline_fn_without_body fn never_inline(); #[inline] diff --git a/tests/ui/inline_fn_without_body.stderr b/tests/ui/inline_fn_without_body.stderr index 89db710fabe7..61bc5505ea30 100644 --- a/tests/ui/inline_fn_without_body.stderr +++ b/tests/ui/inline_fn_without_body.stderr @@ -3,26 +3,26 @@ error: use of `#[inline]` on trait method `default_inline` which has no body | LL | #[inline] | _____-^^^^^^^^ -LL | | fn default_inline(); +LL | | | |____- help: remove | = note: `-D clippy::inline-fn-without-body` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::inline_fn_without_body)]` error: use of `#[inline]` on trait method `always_inline` which has no body - --> tests/ui/inline_fn_without_body.rs:8:5 + --> tests/ui/inline_fn_without_body.rs:9:5 | LL | #[inline(always)] | _____-^^^^^^^^^^^^^^^^ -LL | | fn always_inline(); +LL | | | |____- help: remove error: use of `#[inline]` on trait method `never_inline` which has no body - --> tests/ui/inline_fn_without_body.rs:11:5 + --> tests/ui/inline_fn_without_body.rs:13:5 | LL | #[inline(never)] | _____-^^^^^^^^^^^^^^^ -LL | | fn never_inline(); +LL | | | |____- help: remove error: aborting due to 3 previous errors diff --git a/tests/ui/inspect_for_each.rs b/tests/ui/inspect_for_each.rs index 974690eaa8e4..8bfd9cec66dc 100644 --- a/tests/ui/inspect_for_each.rs +++ b/tests/ui/inspect_for_each.rs @@ -5,7 +5,8 @@ fn main() { let mut b: Vec = Vec::new(); a.into_iter().inspect(|x| assert!(*x > 0)).for_each(|x| { - //~^ ERROR: called `inspect(..).for_each(..)` on an `Iterator` + //~^ inspect_for_each + let y = do_some(x); let z = do_more(y); b.push(z); diff --git a/tests/ui/inspect_for_each.stderr b/tests/ui/inspect_for_each.stderr index 3c2dee15ebd5..6a715c9c4efc 100644 --- a/tests/ui/inspect_for_each.stderr +++ b/tests/ui/inspect_for_each.stderr @@ -4,6 +4,7 @@ error: called `inspect(..).for_each(..)` on an `Iterator` LL | a.into_iter().inspect(|x| assert!(*x > 0)).for_each(|x| { | ___________________^ LL | | +LL | | LL | | let y = do_some(x); LL | | let z = do_more(y); LL | | b.push(z); diff --git a/tests/ui/int_plus_one.fixed b/tests/ui/int_plus_one.fixed index 77d9cd3f773a..a1aba6bf7f64 100644 --- a/tests/ui/int_plus_one.fixed +++ b/tests/ui/int_plus_one.fixed @@ -5,10 +5,14 @@ fn main() { let y = 0i32; let _ = x > y; + //~^ int_plus_one let _ = y < x; + //~^ int_plus_one let _ = x > y; + //~^ int_plus_one let _ = y < x; + //~^ int_plus_one let _ = x > y; // should be ok let _ = y < x; // should be ok diff --git a/tests/ui/int_plus_one.rs b/tests/ui/int_plus_one.rs index 57c87819dbfe..f804fc9047de 100644 --- a/tests/ui/int_plus_one.rs +++ b/tests/ui/int_plus_one.rs @@ -5,10 +5,14 @@ fn main() { let y = 0i32; let _ = x >= y + 1; + //~^ int_plus_one let _ = y + 1 <= x; + //~^ int_plus_one let _ = x - 1 >= y; + //~^ int_plus_one let _ = y <= x - 1; + //~^ int_plus_one let _ = x > y; // should be ok let _ = y < x; // should be ok diff --git a/tests/ui/int_plus_one.stderr b/tests/ui/int_plus_one.stderr index cedac14f350d..052706028141 100644 --- a/tests/ui/int_plus_one.stderr +++ b/tests/ui/int_plus_one.stderr @@ -8,19 +8,19 @@ LL | let _ = x >= y + 1; = help: to override `-D warnings` add `#[allow(clippy::int_plus_one)]` error: unnecessary `>= y + 1` or `x - 1 >=` - --> tests/ui/int_plus_one.rs:8:13 + --> tests/ui/int_plus_one.rs:9:13 | LL | let _ = y + 1 <= x; | ^^^^^^^^^^ help: change it to: `y < x` error: unnecessary `>= y + 1` or `x - 1 >=` - --> tests/ui/int_plus_one.rs:10:13 + --> tests/ui/int_plus_one.rs:12:13 | LL | let _ = x - 1 >= y; | ^^^^^^^^^^ help: change it to: `x > y` error: unnecessary `>= y + 1` or `x - 1 >=` - --> tests/ui/int_plus_one.rs:11:13 + --> tests/ui/int_plus_one.rs:14:13 | LL | let _ = y <= x - 1; | ^^^^^^^^^^ help: change it to: `y < x` diff --git a/tests/ui/integer_division.rs b/tests/ui/integer_division.rs index 137548fecf4a..632fedc9e8fe 100644 --- a/tests/ui/integer_division.rs +++ b/tests/ui/integer_division.rs @@ -3,10 +3,13 @@ fn main() { let two = 2; let n = 1 / 2; - //~^ ERROR: integer division + //~^ integer_division + let o = 1 / two; - //~^ ERROR: integer division + //~^ integer_division + let p = two / 4; - //~^ ERROR: integer division + //~^ integer_division + let x = 1. / 2.0; } diff --git a/tests/ui/integer_division.stderr b/tests/ui/integer_division.stderr index 5f0d905a48b6..0fe2021a1a9c 100644 --- a/tests/ui/integer_division.stderr +++ b/tests/ui/integer_division.stderr @@ -9,7 +9,7 @@ LL | let n = 1 / 2; = help: to override `-D warnings` add `#[allow(clippy::integer_division)]` error: integer division - --> tests/ui/integer_division.rs:7:13 + --> tests/ui/integer_division.rs:8:13 | LL | let o = 1 / two; | ^^^^^^^ @@ -17,7 +17,7 @@ LL | let o = 1 / two; = help: division of integers may cause loss of precision. consider using floats error: integer division - --> tests/ui/integer_division.rs:9:13 + --> tests/ui/integer_division.rs:11:13 | LL | let p = two / 4; | ^^^^^^^ diff --git a/tests/ui/integer_division_remainder_used.rs b/tests/ui/integer_division_remainder_used.rs index 5d1b02095d18..4d3a7c5eaa15 100644 --- a/tests/ui/integer_division_remainder_used.rs +++ b/tests/ui/integer_division_remainder_used.rs @@ -8,6 +8,7 @@ impl std::ops::Div for CustomOps { fn div(self, rhs: Self) -> Self::Output { Self(self.0 / rhs.0) + //~^ integer_division_remainder_used } } impl std::ops::Rem for CustomOps { @@ -15,6 +16,7 @@ impl std::ops::Rem for CustomOps { fn rem(self, rhs: Self) -> Self::Output { Self(self.0 % rhs.0) + //~^ integer_division_remainder_used } } @@ -23,12 +25,19 @@ fn main() { let a = 10; let b = 5; let c = a / b; + //~^ integer_division_remainder_used let d = a % b; + //~^ integer_division_remainder_used let e = &a / b; + //~^ integer_division_remainder_used let f = a % &b; + //~^ integer_division_remainder_used let g = &a / &b; + //~^ integer_division_remainder_used let h = &10 % b; + //~^ integer_division_remainder_used let i = a / &4; + //~^ integer_division_remainder_used // should not trigger on custom Div and Rem let w = CustomOps(3); diff --git a/tests/ui/integer_division_remainder_used.stderr b/tests/ui/integer_division_remainder_used.stderr index 8adfda28893d..ea9f0e716c7d 100644 --- a/tests/ui/integer_division_remainder_used.stderr +++ b/tests/ui/integer_division_remainder_used.stderr @@ -8,49 +8,49 @@ LL | Self(self.0 / rhs.0) = help: to override `-D warnings` add `#[allow(clippy::integer_division_remainder_used)]` error: use of % has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:17:14 + --> tests/ui/integer_division_remainder_used.rs:18:14 | LL | Self(self.0 % rhs.0) | ^^^^^^^^^^^^^^ error: use of / has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:25:13 + --> tests/ui/integer_division_remainder_used.rs:27:13 | LL | let c = a / b; | ^^^^^ error: use of % has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:26:13 + --> tests/ui/integer_division_remainder_used.rs:29:13 | LL | let d = a % b; | ^^^^^ error: use of / has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:27:13 + --> tests/ui/integer_division_remainder_used.rs:31:13 | LL | let e = &a / b; | ^^^^^^ error: use of % has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:28:13 + --> tests/ui/integer_division_remainder_used.rs:33:13 | LL | let f = a % &b; | ^^^^^^ error: use of / has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:29:13 + --> tests/ui/integer_division_remainder_used.rs:35:13 | LL | let g = &a / &b; | ^^^^^^^ error: use of % has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:30:13 + --> tests/ui/integer_division_remainder_used.rs:37:13 | LL | let h = &10 % b; | ^^^^^^^ error: use of / has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:31:13 + --> tests/ui/integer_division_remainder_used.rs:39:13 | LL | let i = a / &4; | ^^^^^^ diff --git a/tests/ui/into_iter_on_ref.fixed b/tests/ui/into_iter_on_ref.fixed index 72b39c982bf7..7626569fd422 100644 --- a/tests/ui/into_iter_on_ref.fixed +++ b/tests/ui/into_iter_on_ref.fixed @@ -10,34 +10,60 @@ fn main() { for _ in &vec![X, X] {} let _ = vec![1, 2, 3].into_iter(); - let _ = (&vec![1, 2, 3]).iter(); //~ ERROR: equivalent to `.iter() - let _ = std::rc::Rc::from(&[X][..]).iter(); //~ ERROR: equivalent to `.iter() - let _ = std::sync::Arc::from(&[X][..]).iter(); //~ ERROR: equivalent to `.iter() + let _ = (&vec![1, 2, 3]).iter(); + //~^ into_iter_on_ref + let _ = std::rc::Rc::from(&[X][..]).iter(); + //~^ into_iter_on_ref + let _ = std::sync::Arc::from(&[X][..]).iter(); + //~^ into_iter_on_ref - let _ = (&&&&&&&[1, 2, 3]).iter(); //~ ERROR: equivalent to `.iter() - let _ = (&&&&mut &&&[1, 2, 3]).iter(); //~ ERROR: equivalent to `.iter() - let _ = (&mut &mut &mut [1, 2, 3]).iter_mut(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&&&&&&&[1, 2, 3]).iter(); + //~^ into_iter_on_ref + let _ = (&&&&mut &&&[1, 2, 3]).iter(); + //~^ into_iter_on_ref + let _ = (&mut &mut &mut [1, 2, 3]).iter_mut(); + //~^ into_iter_on_ref - let _ = (&Some(4)).iter(); //~ ERROR: equivalent to `.iter() - let _ = (&mut Some(5)).iter_mut(); //~ ERROR: equivalent to `.iter_mut() - let _ = (&Ok::<_, i32>(6)).iter(); //~ ERROR: equivalent to `.iter() - let _ = (&mut Err::(7)).iter_mut(); //~ ERROR: equivalent to `.iter_mut() - let _ = (&Vec::::new()).iter(); //~ ERROR: equivalent to `.iter() - let _ = (&mut Vec::::new()).iter_mut(); //~ ERROR: equivalent to `.iter_mut() - let _ = (&BTreeMap::::new()).iter(); //~ ERROR: equivalent to `.iter() - let _ = (&mut BTreeMap::::new()).iter_mut(); //~ ERROR: equivalent to `.iter_mut() - let _ = (&VecDeque::::new()).iter(); //~ ERROR: equivalent to `.iter() - let _ = (&mut VecDeque::::new()).iter_mut(); //~ ERROR: equivalent to `.iter_mut() - let _ = (&LinkedList::::new()).iter(); //~ ERROR: equivalent to `.iter() - let _ = (&mut LinkedList::::new()).iter_mut(); //~ ERROR: equivalent to `.iter_mut() - let _ = (&HashMap::::new()).iter(); //~ ERROR: equivalent to `.iter() - let _ = (&mut HashMap::::new()).iter_mut(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&Some(4)).iter(); + //~^ into_iter_on_ref + let _ = (&mut Some(5)).iter_mut(); + //~^ into_iter_on_ref + let _ = (&Ok::<_, i32>(6)).iter(); + //~^ into_iter_on_ref + let _ = (&mut Err::(7)).iter_mut(); + //~^ into_iter_on_ref + let _ = (&Vec::::new()).iter(); + //~^ into_iter_on_ref + let _ = (&mut Vec::::new()).iter_mut(); + //~^ into_iter_on_ref + let _ = (&BTreeMap::::new()).iter(); + //~^ into_iter_on_ref + let _ = (&mut BTreeMap::::new()).iter_mut(); + //~^ into_iter_on_ref + let _ = (&VecDeque::::new()).iter(); + //~^ into_iter_on_ref + let _ = (&mut VecDeque::::new()).iter_mut(); + //~^ into_iter_on_ref + let _ = (&LinkedList::::new()).iter(); + //~^ into_iter_on_ref + let _ = (&mut LinkedList::::new()).iter_mut(); + //~^ into_iter_on_ref + let _ = (&HashMap::::new()).iter(); + //~^ into_iter_on_ref + let _ = (&mut HashMap::::new()).iter_mut(); + //~^ into_iter_on_ref - let _ = (&BTreeSet::::new()).iter(); //~ ERROR: equivalent to `.iter() - let _ = (&BinaryHeap::::new()).iter(); //~ ERROR: equivalent to `.iter() - let _ = (&HashSet::::new()).iter(); //~ ERROR: equivalent to `.iter() - let _ = std::path::Path::new("12/34").iter(); //~ ERROR: equivalent to `.iter() - let _ = std::path::PathBuf::from("12/34").iter(); //~ ERROR: equivalent to `.iter() + let _ = (&BTreeSet::::new()).iter(); + //~^ into_iter_on_ref + let _ = (&BinaryHeap::::new()).iter(); + //~^ into_iter_on_ref + let _ = (&HashSet::::new()).iter(); + //~^ into_iter_on_ref + let _ = std::path::Path::new("12/34").iter(); + //~^ into_iter_on_ref + let _ = std::path::PathBuf::from("12/34").iter(); + //~^ into_iter_on_ref - let _ = (&[1, 2, 3]).iter().next(); //~ ERROR: equivalent to `.iter() + let _ = (&[1, 2, 3]).iter().next(); + //~^ into_iter_on_ref } diff --git a/tests/ui/into_iter_on_ref.rs b/tests/ui/into_iter_on_ref.rs index 5ba224720d34..286a62c69ce5 100644 --- a/tests/ui/into_iter_on_ref.rs +++ b/tests/ui/into_iter_on_ref.rs @@ -10,34 +10,60 @@ fn main() { for _ in &vec![X, X] {} let _ = vec![1, 2, 3].into_iter(); - let _ = (&vec![1, 2, 3]).into_iter(); //~ ERROR: equivalent to `.iter() - let _ = std::rc::Rc::from(&[X][..]).into_iter(); //~ ERROR: equivalent to `.iter() - let _ = std::sync::Arc::from(&[X][..]).into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&vec![1, 2, 3]).into_iter(); + //~^ into_iter_on_ref + let _ = std::rc::Rc::from(&[X][..]).into_iter(); + //~^ into_iter_on_ref + let _ = std::sync::Arc::from(&[X][..]).into_iter(); + //~^ into_iter_on_ref - let _ = (&&&&&&&[1, 2, 3]).into_iter(); //~ ERROR: equivalent to `.iter() - let _ = (&&&&mut &&&[1, 2, 3]).into_iter(); //~ ERROR: equivalent to `.iter() - let _ = (&mut &mut &mut [1, 2, 3]).into_iter(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&&&&&&&[1, 2, 3]).into_iter(); + //~^ into_iter_on_ref + let _ = (&&&&mut &&&[1, 2, 3]).into_iter(); + //~^ into_iter_on_ref + let _ = (&mut &mut &mut [1, 2, 3]).into_iter(); + //~^ into_iter_on_ref - let _ = (&Some(4)).into_iter(); //~ ERROR: equivalent to `.iter() - let _ = (&mut Some(5)).into_iter(); //~ ERROR: equivalent to `.iter_mut() - let _ = (&Ok::<_, i32>(6)).into_iter(); //~ ERROR: equivalent to `.iter() - let _ = (&mut Err::(7)).into_iter(); //~ ERROR: equivalent to `.iter_mut() - let _ = (&Vec::::new()).into_iter(); //~ ERROR: equivalent to `.iter() - let _ = (&mut Vec::::new()).into_iter(); //~ ERROR: equivalent to `.iter_mut() - let _ = (&BTreeMap::::new()).into_iter(); //~ ERROR: equivalent to `.iter() - let _ = (&mut BTreeMap::::new()).into_iter(); //~ ERROR: equivalent to `.iter_mut() - let _ = (&VecDeque::::new()).into_iter(); //~ ERROR: equivalent to `.iter() - let _ = (&mut VecDeque::::new()).into_iter(); //~ ERROR: equivalent to `.iter_mut() - let _ = (&LinkedList::::new()).into_iter(); //~ ERROR: equivalent to `.iter() - let _ = (&mut LinkedList::::new()).into_iter(); //~ ERROR: equivalent to `.iter_mut() - let _ = (&HashMap::::new()).into_iter(); //~ ERROR: equivalent to `.iter() - let _ = (&mut HashMap::::new()).into_iter(); //~ ERROR: equivalent to `.iter_mut() + let _ = (&Some(4)).into_iter(); + //~^ into_iter_on_ref + let _ = (&mut Some(5)).into_iter(); + //~^ into_iter_on_ref + let _ = (&Ok::<_, i32>(6)).into_iter(); + //~^ into_iter_on_ref + let _ = (&mut Err::(7)).into_iter(); + //~^ into_iter_on_ref + let _ = (&Vec::::new()).into_iter(); + //~^ into_iter_on_ref + let _ = (&mut Vec::::new()).into_iter(); + //~^ into_iter_on_ref + let _ = (&BTreeMap::::new()).into_iter(); + //~^ into_iter_on_ref + let _ = (&mut BTreeMap::::new()).into_iter(); + //~^ into_iter_on_ref + let _ = (&VecDeque::::new()).into_iter(); + //~^ into_iter_on_ref + let _ = (&mut VecDeque::::new()).into_iter(); + //~^ into_iter_on_ref + let _ = (&LinkedList::::new()).into_iter(); + //~^ into_iter_on_ref + let _ = (&mut LinkedList::::new()).into_iter(); + //~^ into_iter_on_ref + let _ = (&HashMap::::new()).into_iter(); + //~^ into_iter_on_ref + let _ = (&mut HashMap::::new()).into_iter(); + //~^ into_iter_on_ref - let _ = (&BTreeSet::::new()).into_iter(); //~ ERROR: equivalent to `.iter() - let _ = (&BinaryHeap::::new()).into_iter(); //~ ERROR: equivalent to `.iter() - let _ = (&HashSet::::new()).into_iter(); //~ ERROR: equivalent to `.iter() - let _ = std::path::Path::new("12/34").into_iter(); //~ ERROR: equivalent to `.iter() - let _ = std::path::PathBuf::from("12/34").into_iter(); //~ ERROR: equivalent to `.iter() + let _ = (&BTreeSet::::new()).into_iter(); + //~^ into_iter_on_ref + let _ = (&BinaryHeap::::new()).into_iter(); + //~^ into_iter_on_ref + let _ = (&HashSet::::new()).into_iter(); + //~^ into_iter_on_ref + let _ = std::path::Path::new("12/34").into_iter(); + //~^ into_iter_on_ref + let _ = std::path::PathBuf::from("12/34").into_iter(); + //~^ into_iter_on_ref - let _ = (&[1, 2, 3]).into_iter().next(); //~ ERROR: equivalent to `.iter() + let _ = (&[1, 2, 3]).into_iter().next(); + //~^ into_iter_on_ref } diff --git a/tests/ui/into_iter_on_ref.stderr b/tests/ui/into_iter_on_ref.stderr index 64d814074da4..57ff097a6ca2 100644 --- a/tests/ui/into_iter_on_ref.stderr +++ b/tests/ui/into_iter_on_ref.stderr @@ -8,151 +8,151 @@ LL | let _ = (&vec![1, 2, 3]).into_iter(); = help: to override `-D warnings` add `#[allow(clippy::into_iter_on_ref)]` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `slice` - --> tests/ui/into_iter_on_ref.rs:14:41 + --> tests/ui/into_iter_on_ref.rs:15:41 | LL | let _ = std::rc::Rc::from(&[X][..]).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `slice` - --> tests/ui/into_iter_on_ref.rs:15:44 + --> tests/ui/into_iter_on_ref.rs:17:44 | LL | let _ = std::sync::Arc::from(&[X][..]).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `array` - --> tests/ui/into_iter_on_ref.rs:17:32 + --> tests/ui/into_iter_on_ref.rs:20:32 | LL | let _ = (&&&&&&&[1, 2, 3]).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `array` - --> tests/ui/into_iter_on_ref.rs:18:36 + --> tests/ui/into_iter_on_ref.rs:22:36 | LL | let _ = (&&&&mut &&&[1, 2, 3]).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `array` - --> tests/ui/into_iter_on_ref.rs:19:40 + --> tests/ui/into_iter_on_ref.rs:24:40 | LL | let _ = (&mut &mut &mut [1, 2, 3]).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Option` - --> tests/ui/into_iter_on_ref.rs:21:24 + --> tests/ui/into_iter_on_ref.rs:27:24 | LL | let _ = (&Some(4)).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `Option` - --> tests/ui/into_iter_on_ref.rs:22:28 + --> tests/ui/into_iter_on_ref.rs:29:28 | LL | let _ = (&mut Some(5)).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Result` - --> tests/ui/into_iter_on_ref.rs:23:32 + --> tests/ui/into_iter_on_ref.rs:31:32 | LL | let _ = (&Ok::<_, i32>(6)).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `Result` - --> tests/ui/into_iter_on_ref.rs:24:37 + --> tests/ui/into_iter_on_ref.rs:33:37 | LL | let _ = (&mut Err::(7)).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Vec` - --> tests/ui/into_iter_on_ref.rs:25:34 + --> tests/ui/into_iter_on_ref.rs:35:34 | LL | let _ = (&Vec::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `Vec` - --> tests/ui/into_iter_on_ref.rs:26:38 + --> tests/ui/into_iter_on_ref.rs:37:38 | LL | let _ = (&mut Vec::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `BTreeMap` - --> tests/ui/into_iter_on_ref.rs:27:44 + --> tests/ui/into_iter_on_ref.rs:39:44 | LL | let _ = (&BTreeMap::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `BTreeMap` - --> tests/ui/into_iter_on_ref.rs:28:48 + --> tests/ui/into_iter_on_ref.rs:41:48 | LL | let _ = (&mut BTreeMap::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `VecDeque` - --> tests/ui/into_iter_on_ref.rs:29:39 + --> tests/ui/into_iter_on_ref.rs:43:39 | LL | let _ = (&VecDeque::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `VecDeque` - --> tests/ui/into_iter_on_ref.rs:30:43 + --> tests/ui/into_iter_on_ref.rs:45:43 | LL | let _ = (&mut VecDeque::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `LinkedList` - --> tests/ui/into_iter_on_ref.rs:31:41 + --> tests/ui/into_iter_on_ref.rs:47:41 | LL | let _ = (&LinkedList::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `LinkedList` - --> tests/ui/into_iter_on_ref.rs:32:45 + --> tests/ui/into_iter_on_ref.rs:49:45 | LL | let _ = (&mut LinkedList::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `HashMap` - --> tests/ui/into_iter_on_ref.rs:33:43 + --> tests/ui/into_iter_on_ref.rs:51:43 | LL | let _ = (&HashMap::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `HashMap` - --> tests/ui/into_iter_on_ref.rs:34:47 + --> tests/ui/into_iter_on_ref.rs:53:47 | LL | let _ = (&mut HashMap::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `BTreeSet` - --> tests/ui/into_iter_on_ref.rs:36:39 + --> tests/ui/into_iter_on_ref.rs:56:39 | LL | let _ = (&BTreeSet::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `BinaryHeap` - --> tests/ui/into_iter_on_ref.rs:37:41 + --> tests/ui/into_iter_on_ref.rs:58:41 | LL | let _ = (&BinaryHeap::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `HashSet` - --> tests/ui/into_iter_on_ref.rs:38:38 + --> tests/ui/into_iter_on_ref.rs:60:38 | LL | let _ = (&HashSet::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Path` - --> tests/ui/into_iter_on_ref.rs:39:43 + --> tests/ui/into_iter_on_ref.rs:62:43 | LL | let _ = std::path::Path::new("12/34").into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `PathBuf` - --> tests/ui/into_iter_on_ref.rs:40:47 + --> tests/ui/into_iter_on_ref.rs:64:47 | LL | let _ = std::path::PathBuf::from("12/34").into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `array` - --> tests/ui/into_iter_on_ref.rs:42:26 + --> tests/ui/into_iter_on_ref.rs:67:26 | LL | let _ = (&[1, 2, 3]).into_iter().next(); | ^^^^^^^^^ help: call directly: `iter` diff --git a/tests/ui/into_iter_without_iter.rs b/tests/ui/into_iter_without_iter.rs index 109259d6975c..45e34b3930ad 100644 --- a/tests/ui/into_iter_without_iter.rs +++ b/tests/ui/into_iter_without_iter.rs @@ -7,7 +7,7 @@ use std::iter::IntoIterator; pub struct S1; impl<'a> IntoIterator for &'a S1 { - //~^ ERROR: `IntoIterator` implemented for a reference type without an `iter` method + //~^ into_iter_without_iter type IntoIter = std::slice::Iter<'a, u8>; type Item = &'a u8; fn into_iter(self) -> Self::IntoIter { @@ -15,7 +15,7 @@ impl<'a> IntoIterator for &'a S1 { } } impl<'a> IntoIterator for &'a mut S1 { - //~^ ERROR: `IntoIterator` implemented for a reference type without an `iter_mut` method + //~^ into_iter_without_iter type IntoIter = std::slice::IterMut<'a, u8>; type Item = &'a mut u8; fn into_iter(self) -> Self::IntoIter { @@ -25,7 +25,7 @@ impl<'a> IntoIterator for &'a mut S1 { pub struct S2(T); impl<'a, T> IntoIterator for &'a S2 { - //~^ ERROR: `IntoIterator` implemented for a reference type without an `iter` method + //~^ into_iter_without_iter type IntoIter = std::slice::Iter<'a, T>; type Item = &'a T; fn into_iter(self) -> Self::IntoIter { @@ -33,7 +33,7 @@ impl<'a, T> IntoIterator for &'a S2 { } } impl<'a, T> IntoIterator for &'a mut S2 { - //~^ ERROR: `IntoIterator` implemented for a reference type without an `iter_mut` method + //~^ into_iter_without_iter type IntoIter = std::slice::IterMut<'a, T>; type Item = &'a mut T; fn into_iter(self) -> Self::IntoIter { @@ -84,7 +84,7 @@ impl<'a, T> IntoIterator for &S4<'a, T> { } impl<'a, T> IntoIterator for &mut S4<'a, T> { - //~^ ERROR: `IntoIterator` implemented for a reference type without an `iter_mut` method + //~^ into_iter_without_iter type IntoIter = std::slice::IterMut<'a, T>; type Item = &'a mut T; fn into_iter(self) -> Self::IntoIter { @@ -118,6 +118,7 @@ pub struct Issue12037; macro_rules! generate_impl { () => { impl<'a> IntoIterator for &'a Issue12037 { + //~^ into_iter_without_iter type IntoIter = std::slice::Iter<'a, u8>; type Item = &'a u8; fn into_iter(self) -> Self::IntoIter { diff --git a/tests/ui/into_iter_without_iter.stderr b/tests/ui/into_iter_without_iter.stderr index cde1b60c2abc..a033ff645f49 100644 --- a/tests/ui/into_iter_without_iter.stderr +++ b/tests/ui/into_iter_without_iter.stderr @@ -109,9 +109,9 @@ error: `IntoIterator` implemented for a reference type without an `iter` method --> tests/ui/into_iter_without_iter.rs:120:9 | LL | / impl<'a> IntoIterator for &'a Issue12037 { +LL | | LL | | type IntoIter = std::slice::Iter<'a, u8>; LL | | type Item = &'a u8; -LL | | fn into_iter(self) -> Self::IntoIter { ... | LL | | } | |_________^ diff --git a/tests/ui/invalid_null_ptr_usage.fixed b/tests/ui/invalid_null_ptr_usage.fixed index ba225102c984..ce78e89ee829 100644 --- a/tests/ui/invalid_null_ptr_usage.fixed +++ b/tests/ui/invalid_null_ptr_usage.fixed @@ -1,44 +1,66 @@ fn main() { unsafe { let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::NonNull::dangling().as_ptr(), 0); + //~^ invalid_null_ptr_usage let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::NonNull::dangling().as_ptr(), 0); + //~^ invalid_null_ptr_usage let _slice: &[usize] = std::slice::from_raw_parts_mut(std::ptr::NonNull::dangling().as_ptr(), 0); + //~^ invalid_null_ptr_usage std::ptr::copy::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::NonNull::dangling().as_ptr(), 0); + //~^ invalid_null_ptr_usage std::ptr::copy::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::NonNull::dangling().as_ptr(), 0); + //~^ invalid_null_ptr_usage std::ptr::copy_nonoverlapping::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::NonNull::dangling().as_ptr(), 0); + //~^ invalid_null_ptr_usage std::ptr::copy_nonoverlapping::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::NonNull::dangling().as_ptr(), 0); + //~^ invalid_null_ptr_usage struct A; // zero sized struct assert_eq!(std::mem::size_of::(), 0); let _a: A = std::ptr::read(std::ptr::NonNull::dangling().as_ptr()); + //~^ invalid_null_ptr_usage let _a: A = std::ptr::read(std::ptr::NonNull::dangling().as_ptr()); + //~^ invalid_null_ptr_usage let _a: A = std::ptr::read_unaligned(std::ptr::NonNull::dangling().as_ptr()); + //~^ invalid_null_ptr_usage let _a: A = std::ptr::read_unaligned(std::ptr::NonNull::dangling().as_ptr()); + //~^ invalid_null_ptr_usage let _a: A = std::ptr::read_volatile(std::ptr::NonNull::dangling().as_ptr()); + //~^ invalid_null_ptr_usage let _a: A = std::ptr::read_volatile(std::ptr::NonNull::dangling().as_ptr()); + //~^ invalid_null_ptr_usage let _a: A = std::ptr::replace(std::ptr::NonNull::dangling().as_ptr(), A); + //~^ invalid_null_ptr_usage let _slice: *const [usize] = std::ptr::slice_from_raw_parts(std::ptr::null_mut(), 0); // shouldn't lint let _slice: *const [usize] = std::ptr::slice_from_raw_parts_mut(std::ptr::null_mut(), 0); std::ptr::swap::(std::ptr::NonNull::dangling().as_ptr(), &mut A); + //~^ invalid_null_ptr_usage std::ptr::swap::(&mut A, std::ptr::NonNull::dangling().as_ptr()); + //~^ invalid_null_ptr_usage std::ptr::swap_nonoverlapping::(std::ptr::NonNull::dangling().as_ptr(), &mut A, 0); + //~^ invalid_null_ptr_usage std::ptr::swap_nonoverlapping::(&mut A, std::ptr::NonNull::dangling().as_ptr(), 0); + //~^ invalid_null_ptr_usage std::ptr::write(std::ptr::NonNull::dangling().as_ptr(), A); + //~^ invalid_null_ptr_usage std::ptr::write_unaligned(std::ptr::NonNull::dangling().as_ptr(), A); + //~^ invalid_null_ptr_usage std::ptr::write_volatile(std::ptr::NonNull::dangling().as_ptr(), A); + //~^ invalid_null_ptr_usage std::ptr::write_bytes::(std::ptr::NonNull::dangling().as_ptr(), 42, 0); + //~^ invalid_null_ptr_usage } } diff --git a/tests/ui/invalid_null_ptr_usage.rs b/tests/ui/invalid_null_ptr_usage.rs index 480b6642a3e3..361865fbd960 100644 --- a/tests/ui/invalid_null_ptr_usage.rs +++ b/tests/ui/invalid_null_ptr_usage.rs @@ -1,44 +1,66 @@ fn main() { unsafe { let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null(), 0); + //~^ invalid_null_ptr_usage let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null_mut(), 0); + //~^ invalid_null_ptr_usage let _slice: &[usize] = std::slice::from_raw_parts_mut(std::ptr::null_mut(), 0); + //~^ invalid_null_ptr_usage std::ptr::copy::(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0); + //~^ invalid_null_ptr_usage std::ptr::copy::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0); + //~^ invalid_null_ptr_usage std::ptr::copy_nonoverlapping::(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0); + //~^ invalid_null_ptr_usage std::ptr::copy_nonoverlapping::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0); + //~^ invalid_null_ptr_usage struct A; // zero sized struct assert_eq!(std::mem::size_of::(), 0); let _a: A = std::ptr::read(std::ptr::null()); + //~^ invalid_null_ptr_usage let _a: A = std::ptr::read(std::ptr::null_mut()); + //~^ invalid_null_ptr_usage let _a: A = std::ptr::read_unaligned(std::ptr::null()); + //~^ invalid_null_ptr_usage let _a: A = std::ptr::read_unaligned(std::ptr::null_mut()); + //~^ invalid_null_ptr_usage let _a: A = std::ptr::read_volatile(std::ptr::null()); + //~^ invalid_null_ptr_usage let _a: A = std::ptr::read_volatile(std::ptr::null_mut()); + //~^ invalid_null_ptr_usage let _a: A = std::ptr::replace(std::ptr::null_mut(), A); + //~^ invalid_null_ptr_usage let _slice: *const [usize] = std::ptr::slice_from_raw_parts(std::ptr::null_mut(), 0); // shouldn't lint let _slice: *const [usize] = std::ptr::slice_from_raw_parts_mut(std::ptr::null_mut(), 0); std::ptr::swap::(std::ptr::null_mut(), &mut A); + //~^ invalid_null_ptr_usage std::ptr::swap::(&mut A, std::ptr::null_mut()); + //~^ invalid_null_ptr_usage std::ptr::swap_nonoverlapping::(std::ptr::null_mut(), &mut A, 0); + //~^ invalid_null_ptr_usage std::ptr::swap_nonoverlapping::(&mut A, std::ptr::null_mut(), 0); + //~^ invalid_null_ptr_usage std::ptr::write(std::ptr::null_mut(), A); + //~^ invalid_null_ptr_usage std::ptr::write_unaligned(std::ptr::null_mut(), A); + //~^ invalid_null_ptr_usage std::ptr::write_volatile(std::ptr::null_mut(), A); + //~^ invalid_null_ptr_usage std::ptr::write_bytes::(std::ptr::null_mut(), 42, 0); + //~^ invalid_null_ptr_usage } } diff --git a/tests/ui/invalid_null_ptr_usage.stderr b/tests/ui/invalid_null_ptr_usage.stderr index 613a2cc36885..3f9d15b90401 100644 --- a/tests/ui/invalid_null_ptr_usage.stderr +++ b/tests/ui/invalid_null_ptr_usage.stderr @@ -7,127 +7,127 @@ LL | let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null(), = note: `#[deny(clippy::invalid_null_ptr_usage)]` on by default error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:4:59 + --> tests/ui/invalid_null_ptr_usage.rs:5:59 | LL | let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null_mut(), 0); | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:6:63 + --> tests/ui/invalid_null_ptr_usage.rs:8:63 | LL | let _slice: &[usize] = std::slice::from_raw_parts_mut(std::ptr::null_mut(), 0); | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:8:33 + --> tests/ui/invalid_null_ptr_usage.rs:11:33 | LL | std::ptr::copy::(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0); | ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:9:73 + --> tests/ui/invalid_null_ptr_usage.rs:13:73 | LL | std::ptr::copy::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0); | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:11:48 + --> tests/ui/invalid_null_ptr_usage.rs:16:48 | LL | std::ptr::copy_nonoverlapping::(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0); | ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:12:88 + --> tests/ui/invalid_null_ptr_usage.rs:18:88 | LL | std::ptr::copy_nonoverlapping::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0); | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:17:36 + --> tests/ui/invalid_null_ptr_usage.rs:24:36 | LL | let _a: A = std::ptr::read(std::ptr::null()); | ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:18:36 + --> tests/ui/invalid_null_ptr_usage.rs:26:36 | LL | let _a: A = std::ptr::read(std::ptr::null_mut()); | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:20:46 + --> tests/ui/invalid_null_ptr_usage.rs:29:46 | LL | let _a: A = std::ptr::read_unaligned(std::ptr::null()); | ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:21:46 + --> tests/ui/invalid_null_ptr_usage.rs:31:46 | LL | let _a: A = std::ptr::read_unaligned(std::ptr::null_mut()); | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:23:45 + --> tests/ui/invalid_null_ptr_usage.rs:34:45 | LL | let _a: A = std::ptr::read_volatile(std::ptr::null()); | ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:24:45 + --> tests/ui/invalid_null_ptr_usage.rs:36:45 | LL | let _a: A = std::ptr::read_volatile(std::ptr::null_mut()); | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:26:39 + --> tests/ui/invalid_null_ptr_usage.rs:39:39 | LL | let _a: A = std::ptr::replace(std::ptr::null_mut(), A); | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:30:29 + --> tests/ui/invalid_null_ptr_usage.rs:44:29 | LL | std::ptr::swap::(std::ptr::null_mut(), &mut A); | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:31:37 + --> tests/ui/invalid_null_ptr_usage.rs:46:37 | LL | std::ptr::swap::(&mut A, std::ptr::null_mut()); | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:33:44 + --> tests/ui/invalid_null_ptr_usage.rs:49:44 | LL | std::ptr::swap_nonoverlapping::(std::ptr::null_mut(), &mut A, 0); | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:34:52 + --> tests/ui/invalid_null_ptr_usage.rs:51:52 | LL | std::ptr::swap_nonoverlapping::(&mut A, std::ptr::null_mut(), 0); | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:36:25 + --> tests/ui/invalid_null_ptr_usage.rs:54:25 | LL | std::ptr::write(std::ptr::null_mut(), A); | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:38:35 + --> tests/ui/invalid_null_ptr_usage.rs:57:35 | LL | std::ptr::write_unaligned(std::ptr::null_mut(), A); | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:40:34 + --> tests/ui/invalid_null_ptr_usage.rs:60:34 | LL | std::ptr::write_volatile(std::ptr::null_mut(), A); | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:42:40 + --> tests/ui/invalid_null_ptr_usage.rs:63:40 | LL | std::ptr::write_bytes::(std::ptr::null_mut(), 42, 0); | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` diff --git a/tests/ui/invalid_null_ptr_usage_no_std.fixed b/tests/ui/invalid_null_ptr_usage_no_std.fixed index 2bbfe7274242..df7ab166187d 100644 --- a/tests/ui/invalid_null_ptr_usage_no_std.fixed +++ b/tests/ui/invalid_null_ptr_usage_no_std.fixed @@ -14,44 +14,66 @@ fn panic(info: &PanicInfo) -> ! { fn main() { unsafe { let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0); + //~^ invalid_null_ptr_usage let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0); + //~^ invalid_null_ptr_usage let _slice: &[usize] = core::slice::from_raw_parts_mut(core::ptr::NonNull::dangling().as_ptr(), 0); + //~^ invalid_null_ptr_usage core::ptr::copy::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::NonNull::dangling().as_ptr(), 0); + //~^ invalid_null_ptr_usage core::ptr::copy::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::NonNull::dangling().as_ptr(), 0); + //~^ invalid_null_ptr_usage core::ptr::copy_nonoverlapping::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::NonNull::dangling().as_ptr(), 0); + //~^ invalid_null_ptr_usage core::ptr::copy_nonoverlapping::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::NonNull::dangling().as_ptr(), 0); + //~^ invalid_null_ptr_usage struct A; // zero sized struct assert_eq!(core::mem::size_of::(), 0); let _a: A = core::ptr::read(core::ptr::NonNull::dangling().as_ptr()); + //~^ invalid_null_ptr_usage let _a: A = core::ptr::read(core::ptr::NonNull::dangling().as_ptr()); + //~^ invalid_null_ptr_usage let _a: A = core::ptr::read_unaligned(core::ptr::NonNull::dangling().as_ptr()); + //~^ invalid_null_ptr_usage let _a: A = core::ptr::read_unaligned(core::ptr::NonNull::dangling().as_ptr()); + //~^ invalid_null_ptr_usage let _a: A = core::ptr::read_volatile(core::ptr::NonNull::dangling().as_ptr()); + //~^ invalid_null_ptr_usage let _a: A = core::ptr::read_volatile(core::ptr::NonNull::dangling().as_ptr()); + //~^ invalid_null_ptr_usage let _a: A = core::ptr::replace(core::ptr::NonNull::dangling().as_ptr(), A); + //~^ invalid_null_ptr_usage let _slice: *const [usize] = core::ptr::slice_from_raw_parts(core::ptr::null_mut(), 0); // shouldn't lint let _slice: *const [usize] = core::ptr::slice_from_raw_parts_mut(core::ptr::null_mut(), 0); core::ptr::swap::(core::ptr::NonNull::dangling().as_ptr(), &mut A); + //~^ invalid_null_ptr_usage core::ptr::swap::(&mut A, core::ptr::NonNull::dangling().as_ptr()); + //~^ invalid_null_ptr_usage core::ptr::swap_nonoverlapping::(core::ptr::NonNull::dangling().as_ptr(), &mut A, 0); + //~^ invalid_null_ptr_usage core::ptr::swap_nonoverlapping::(&mut A, core::ptr::NonNull::dangling().as_ptr(), 0); + //~^ invalid_null_ptr_usage core::ptr::write(core::ptr::NonNull::dangling().as_ptr(), A); + //~^ invalid_null_ptr_usage core::ptr::write_unaligned(core::ptr::NonNull::dangling().as_ptr(), A); + //~^ invalid_null_ptr_usage core::ptr::write_volatile(core::ptr::NonNull::dangling().as_ptr(), A); + //~^ invalid_null_ptr_usage core::ptr::write_bytes::(core::ptr::NonNull::dangling().as_ptr(), 42, 0); + //~^ invalid_null_ptr_usage } } diff --git a/tests/ui/invalid_null_ptr_usage_no_std.rs b/tests/ui/invalid_null_ptr_usage_no_std.rs index cbce44f7c0d9..38ddfff05535 100644 --- a/tests/ui/invalid_null_ptr_usage_no_std.rs +++ b/tests/ui/invalid_null_ptr_usage_no_std.rs @@ -14,44 +14,66 @@ fn panic(info: &PanicInfo) -> ! { fn main() { unsafe { let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::null(), 0); + //~^ invalid_null_ptr_usage let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::null_mut(), 0); + //~^ invalid_null_ptr_usage let _slice: &[usize] = core::slice::from_raw_parts_mut(core::ptr::null_mut(), 0); + //~^ invalid_null_ptr_usage core::ptr::copy::(core::ptr::null(), core::ptr::NonNull::dangling().as_ptr(), 0); + //~^ invalid_null_ptr_usage core::ptr::copy::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::null_mut(), 0); + //~^ invalid_null_ptr_usage core::ptr::copy_nonoverlapping::(core::ptr::null(), core::ptr::NonNull::dangling().as_ptr(), 0); + //~^ invalid_null_ptr_usage core::ptr::copy_nonoverlapping::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::null_mut(), 0); + //~^ invalid_null_ptr_usage struct A; // zero sized struct assert_eq!(core::mem::size_of::(), 0); let _a: A = core::ptr::read(core::ptr::null()); + //~^ invalid_null_ptr_usage let _a: A = core::ptr::read(core::ptr::null_mut()); + //~^ invalid_null_ptr_usage let _a: A = core::ptr::read_unaligned(core::ptr::null()); + //~^ invalid_null_ptr_usage let _a: A = core::ptr::read_unaligned(core::ptr::null_mut()); + //~^ invalid_null_ptr_usage let _a: A = core::ptr::read_volatile(core::ptr::null()); + //~^ invalid_null_ptr_usage let _a: A = core::ptr::read_volatile(core::ptr::null_mut()); + //~^ invalid_null_ptr_usage let _a: A = core::ptr::replace(core::ptr::null_mut(), A); + //~^ invalid_null_ptr_usage let _slice: *const [usize] = core::ptr::slice_from_raw_parts(core::ptr::null_mut(), 0); // shouldn't lint let _slice: *const [usize] = core::ptr::slice_from_raw_parts_mut(core::ptr::null_mut(), 0); core::ptr::swap::(core::ptr::null_mut(), &mut A); + //~^ invalid_null_ptr_usage core::ptr::swap::(&mut A, core::ptr::null_mut()); + //~^ invalid_null_ptr_usage core::ptr::swap_nonoverlapping::(core::ptr::null_mut(), &mut A, 0); + //~^ invalid_null_ptr_usage core::ptr::swap_nonoverlapping::(&mut A, core::ptr::null_mut(), 0); + //~^ invalid_null_ptr_usage core::ptr::write(core::ptr::null_mut(), A); + //~^ invalid_null_ptr_usage core::ptr::write_unaligned(core::ptr::null_mut(), A); + //~^ invalid_null_ptr_usage core::ptr::write_volatile(core::ptr::null_mut(), A); + //~^ invalid_null_ptr_usage core::ptr::write_bytes::(core::ptr::null_mut(), 42, 0); + //~^ invalid_null_ptr_usage } } diff --git a/tests/ui/invalid_null_ptr_usage_no_std.stderr b/tests/ui/invalid_null_ptr_usage_no_std.stderr index df0d40e9e072..b5dd21ce6248 100644 --- a/tests/ui/invalid_null_ptr_usage_no_std.stderr +++ b/tests/ui/invalid_null_ptr_usage_no_std.stderr @@ -7,127 +7,127 @@ LL | let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::null( = note: `#[deny(clippy::invalid_null_ptr_usage)]` on by default error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:17:60 + --> tests/ui/invalid_null_ptr_usage_no_std.rs:18:60 | LL | let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::null_mut(), 0); | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:19:64 + --> tests/ui/invalid_null_ptr_usage_no_std.rs:21:64 | LL | let _slice: &[usize] = core::slice::from_raw_parts_mut(core::ptr::null_mut(), 0); | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:21:34 + --> tests/ui/invalid_null_ptr_usage_no_std.rs:24:34 | LL | core::ptr::copy::(core::ptr::null(), core::ptr::NonNull::dangling().as_ptr(), 0); | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:22:75 + --> tests/ui/invalid_null_ptr_usage_no_std.rs:26:75 | LL | core::ptr::copy::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::null_mut(), 0); | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:24:49 + --> tests/ui/invalid_null_ptr_usage_no_std.rs:29:49 | LL | core::ptr::copy_nonoverlapping::(core::ptr::null(), core::ptr::NonNull::dangling().as_ptr(), 0); | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:25:90 + --> tests/ui/invalid_null_ptr_usage_no_std.rs:31:90 | LL | core::ptr::copy_nonoverlapping::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::null_mut(), 0); | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:30:37 + --> tests/ui/invalid_null_ptr_usage_no_std.rs:37:37 | LL | let _a: A = core::ptr::read(core::ptr::null()); | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:31:37 + --> tests/ui/invalid_null_ptr_usage_no_std.rs:39:37 | LL | let _a: A = core::ptr::read(core::ptr::null_mut()); | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:33:47 + --> tests/ui/invalid_null_ptr_usage_no_std.rs:42:47 | LL | let _a: A = core::ptr::read_unaligned(core::ptr::null()); | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:34:47 + --> tests/ui/invalid_null_ptr_usage_no_std.rs:44:47 | LL | let _a: A = core::ptr::read_unaligned(core::ptr::null_mut()); | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:36:46 + --> tests/ui/invalid_null_ptr_usage_no_std.rs:47:46 | LL | let _a: A = core::ptr::read_volatile(core::ptr::null()); | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:37:46 + --> tests/ui/invalid_null_ptr_usage_no_std.rs:49:46 | LL | let _a: A = core::ptr::read_volatile(core::ptr::null_mut()); | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:39:40 + --> tests/ui/invalid_null_ptr_usage_no_std.rs:52:40 | LL | let _a: A = core::ptr::replace(core::ptr::null_mut(), A); | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:43:30 + --> tests/ui/invalid_null_ptr_usage_no_std.rs:57:30 | LL | core::ptr::swap::(core::ptr::null_mut(), &mut A); | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:44:38 + --> tests/ui/invalid_null_ptr_usage_no_std.rs:59:38 | LL | core::ptr::swap::(&mut A, core::ptr::null_mut()); | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:46:45 + --> tests/ui/invalid_null_ptr_usage_no_std.rs:62:45 | LL | core::ptr::swap_nonoverlapping::(core::ptr::null_mut(), &mut A, 0); | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:47:53 + --> tests/ui/invalid_null_ptr_usage_no_std.rs:64:53 | LL | core::ptr::swap_nonoverlapping::(&mut A, core::ptr::null_mut(), 0); | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:49:26 + --> tests/ui/invalid_null_ptr_usage_no_std.rs:67:26 | LL | core::ptr::write(core::ptr::null_mut(), A); | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:51:36 + --> tests/ui/invalid_null_ptr_usage_no_std.rs:70:36 | LL | core::ptr::write_unaligned(core::ptr::null_mut(), A); | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:53:35 + --> tests/ui/invalid_null_ptr_usage_no_std.rs:73:35 | LL | core::ptr::write_volatile(core::ptr::null_mut(), A); | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:55:41 + --> tests/ui/invalid_null_ptr_usage_no_std.rs:76:41 | LL | core::ptr::write_bytes::(core::ptr::null_mut(), 42, 0); | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` diff --git a/tests/ui/invalid_upcast_comparisons.rs b/tests/ui/invalid_upcast_comparisons.rs index a9db15f20973..4f3194869f43 100644 --- a/tests/ui/invalid_upcast_comparisons.rs +++ b/tests/ui/invalid_upcast_comparisons.rs @@ -19,61 +19,81 @@ fn main() { // always false, since no u8 can be > 300 (u8 as u32) > 300; - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is - //~| NOTE: `-D clippy::invalid-upcast-comparisons` implied by `-D warnings` + //~^ invalid_upcast_comparisons + (u8 as i32) > 300; - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons + (u8 as u32) == 300; - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons + (u8 as i32) == 300; - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons + 300 < (u8 as u32); - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons + 300 < (u8 as i32); - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons + 300 == (u8 as u32); - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons + 300 == (u8 as i32); - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons + // inverted of the above (u8 as u32) <= 300; - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons + (u8 as i32) <= 300; - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons + (u8 as u32) != 300; - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons + (u8 as i32) != 300; - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons + 300 >= (u8 as u32); - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons + 300 >= (u8 as i32); - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons + 300 != (u8 as u32); - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons + 300 != (u8 as i32); - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons // always false, since u8 -> i32 doesn't wrap (u8 as i32) < 0; - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons + -5 != (u8 as i32); - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons + // inverted of the above (u8 as i32) >= 0; - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons + -5 == (u8 as i32); - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons // always false, since no u8 can be 1337 1337 == (u8 as i32); - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons + 1337 == (u8 as u32); - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons + // inverted of the above 1337 != (u8 as i32); - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons + 1337 != (u8 as u32); - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons // Those are Ok: (u8 as u32) > 20; @@ -88,9 +108,11 @@ fn main() { (u8 as i8) == -1; (u8 as i8) != -1; (u8 as i32) > -1; - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons + (u8 as i32) < -1; - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons + (u32 as i32) < -5; (u32 as i32) < 10; @@ -107,7 +129,7 @@ fn main() { -5 > (u32 as i32); -5 >= (u8 as i32); - //~^ ERROR: because of the numeric bounds on `u8` prior to casting, this expression is + //~^ invalid_upcast_comparisons -5 == (u32 as i32); } diff --git a/tests/ui/invalid_upcast_comparisons.stderr b/tests/ui/invalid_upcast_comparisons.stderr index b1fbe2951577..ef36f18eabc9 100644 --- a/tests/ui/invalid_upcast_comparisons.stderr +++ b/tests/ui/invalid_upcast_comparisons.stderr @@ -14,151 +14,151 @@ LL | (u8 as i32) > 300; | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> tests/ui/invalid_upcast_comparisons.rs:26:5 + --> tests/ui/invalid_upcast_comparisons.rs:27:5 | LL | (u8 as u32) == 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> tests/ui/invalid_upcast_comparisons.rs:28:5 + --> tests/ui/invalid_upcast_comparisons.rs:30:5 | LL | (u8 as i32) == 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> tests/ui/invalid_upcast_comparisons.rs:30:5 + --> tests/ui/invalid_upcast_comparisons.rs:33:5 | LL | 300 < (u8 as u32); | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> tests/ui/invalid_upcast_comparisons.rs:32:5 + --> tests/ui/invalid_upcast_comparisons.rs:36:5 | LL | 300 < (u8 as i32); | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> tests/ui/invalid_upcast_comparisons.rs:34:5 + --> tests/ui/invalid_upcast_comparisons.rs:39:5 | LL | 300 == (u8 as u32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> tests/ui/invalid_upcast_comparisons.rs:36:5 + --> tests/ui/invalid_upcast_comparisons.rs:42:5 | LL | 300 == (u8 as i32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> tests/ui/invalid_upcast_comparisons.rs:39:5 + --> tests/ui/invalid_upcast_comparisons.rs:46:5 | LL | (u8 as u32) <= 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> tests/ui/invalid_upcast_comparisons.rs:41:5 + --> tests/ui/invalid_upcast_comparisons.rs:49:5 | LL | (u8 as i32) <= 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> tests/ui/invalid_upcast_comparisons.rs:43:5 + --> tests/ui/invalid_upcast_comparisons.rs:52:5 | LL | (u8 as u32) != 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> tests/ui/invalid_upcast_comparisons.rs:45:5 + --> tests/ui/invalid_upcast_comparisons.rs:55:5 | LL | (u8 as i32) != 300; | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> tests/ui/invalid_upcast_comparisons.rs:47:5 + --> tests/ui/invalid_upcast_comparisons.rs:58:5 | LL | 300 >= (u8 as u32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> tests/ui/invalid_upcast_comparisons.rs:49:5 + --> tests/ui/invalid_upcast_comparisons.rs:61:5 | LL | 300 >= (u8 as i32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> tests/ui/invalid_upcast_comparisons.rs:51:5 + --> tests/ui/invalid_upcast_comparisons.rs:64:5 | LL | 300 != (u8 as u32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> tests/ui/invalid_upcast_comparisons.rs:53:5 + --> tests/ui/invalid_upcast_comparisons.rs:67:5 | LL | 300 != (u8 as i32); | ^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> tests/ui/invalid_upcast_comparisons.rs:57:5 + --> tests/ui/invalid_upcast_comparisons.rs:71:5 | LL | (u8 as i32) < 0; | ^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> tests/ui/invalid_upcast_comparisons.rs:59:5 + --> tests/ui/invalid_upcast_comparisons.rs:74:5 | LL | -5 != (u8 as i32); | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> tests/ui/invalid_upcast_comparisons.rs:62:5 + --> tests/ui/invalid_upcast_comparisons.rs:78:5 | LL | (u8 as i32) >= 0; | ^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> tests/ui/invalid_upcast_comparisons.rs:64:5 + --> tests/ui/invalid_upcast_comparisons.rs:81:5 | LL | -5 == (u8 as i32); | ^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> tests/ui/invalid_upcast_comparisons.rs:68:5 + --> tests/ui/invalid_upcast_comparisons.rs:85:5 | LL | 1337 == (u8 as i32); | ^^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> tests/ui/invalid_upcast_comparisons.rs:70:5 + --> tests/ui/invalid_upcast_comparisons.rs:88:5 | LL | 1337 == (u8 as u32); | ^^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> tests/ui/invalid_upcast_comparisons.rs:73:5 + --> tests/ui/invalid_upcast_comparisons.rs:92:5 | LL | 1337 != (u8 as i32); | ^^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> tests/ui/invalid_upcast_comparisons.rs:75:5 + --> tests/ui/invalid_upcast_comparisons.rs:95:5 | LL | 1337 != (u8 as u32); | ^^^^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always true - --> tests/ui/invalid_upcast_comparisons.rs:90:5 + --> tests/ui/invalid_upcast_comparisons.rs:110:5 | LL | (u8 as i32) > -1; | ^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> tests/ui/invalid_upcast_comparisons.rs:92:5 + --> tests/ui/invalid_upcast_comparisons.rs:113:5 | LL | (u8 as i32) < -1; | ^^^^^^^^^^^^^^^^ error: because of the numeric bounds on `u8` prior to casting, this expression is always false - --> tests/ui/invalid_upcast_comparisons.rs:109:5 + --> tests/ui/invalid_upcast_comparisons.rs:131:5 | LL | -5 >= (u8 as i32); | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/io_other_error.fixed b/tests/ui/io_other_error.fixed new file mode 100644 index 000000000000..0054c56fb628 --- /dev/null +++ b/tests/ui/io_other_error.fixed @@ -0,0 +1,55 @@ +#![warn(clippy::io_other_error)] +use std::fmt; + +#[derive(Debug)] +struct E; + +impl std::error::Error for E {} +impl fmt::Display for E { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("E") + } +} + +macro_rules! o { + {} => { std::io::ErrorKind::Other }; +} + +macro_rules! e { + { $kind:expr } => { std::io::Error::new($kind, E) }; +} + +fn main() { + let _err = std::io::Error::other(E); + //~^ ERROR: this can be `std::io::Error::other(_)` + let other = std::io::ErrorKind::Other; + let _err = std::io::Error::other(E); + //~^ ERROR: this can be `std::io::Error::other(_)` + + // not other + let _err = std::io::Error::new(std::io::ErrorKind::TimedOut, E); + + // from expansion + let _err = e!(other); + let _err = std::io::Error::new(o!(), E); + let _err = e!(o!()); + + paths::short(); + under_msrv(); +} + +mod paths { + use std::io::{self, Error, ErrorKind}; + + pub fn short() { + let _err = Error::other(super::E); + //~^ ERROR: this can be `std::io::Error::other(_)` + let _err = io::Error::other(super::E); + //~^ ERROR: this can be `std::io::Error::other(_)` + } +} + +#[clippy::msrv = "1.73"] +fn under_msrv() { + let _err = std::io::Error::new(std::io::ErrorKind::Other, E); +} diff --git a/tests/ui/io_other_error.rs b/tests/ui/io_other_error.rs new file mode 100644 index 000000000000..8529fb9a77f9 --- /dev/null +++ b/tests/ui/io_other_error.rs @@ -0,0 +1,55 @@ +#![warn(clippy::io_other_error)] +use std::fmt; + +#[derive(Debug)] +struct E; + +impl std::error::Error for E {} +impl fmt::Display for E { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("E") + } +} + +macro_rules! o { + {} => { std::io::ErrorKind::Other }; +} + +macro_rules! e { + { $kind:expr } => { std::io::Error::new($kind, E) }; +} + +fn main() { + let _err = std::io::Error::new(std::io::ErrorKind::Other, E); + //~^ ERROR: this can be `std::io::Error::other(_)` + let other = std::io::ErrorKind::Other; + let _err = std::io::Error::new(other, E); + //~^ ERROR: this can be `std::io::Error::other(_)` + + // not other + let _err = std::io::Error::new(std::io::ErrorKind::TimedOut, E); + + // from expansion + let _err = e!(other); + let _err = std::io::Error::new(o!(), E); + let _err = e!(o!()); + + paths::short(); + under_msrv(); +} + +mod paths { + use std::io::{self, Error, ErrorKind}; + + pub fn short() { + let _err = Error::new(ErrorKind::Other, super::E); + //~^ ERROR: this can be `std::io::Error::other(_)` + let _err = io::Error::new(io::ErrorKind::Other, super::E); + //~^ ERROR: this can be `std::io::Error::other(_)` + } +} + +#[clippy::msrv = "1.73"] +fn under_msrv() { + let _err = std::io::Error::new(std::io::ErrorKind::Other, E); +} diff --git a/tests/ui/io_other_error.stderr b/tests/ui/io_other_error.stderr new file mode 100644 index 000000000000..e79e05ecd406 --- /dev/null +++ b/tests/ui/io_other_error.stderr @@ -0,0 +1,52 @@ +error: this can be `std::io::Error::other(_)` + --> tests/ui/io_other_error.rs:23:16 + | +LL | let _err = std::io::Error::new(std::io::ErrorKind::Other, E); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::io-other-error` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::io_other_error)]` +help: use `std::io::Error::other` + | +LL - let _err = std::io::Error::new(std::io::ErrorKind::Other, E); +LL + let _err = std::io::Error::other(E); + | + +error: this can be `std::io::Error::other(_)` + --> tests/ui/io_other_error.rs:26:16 + | +LL | let _err = std::io::Error::new(other, E); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `std::io::Error::other` + | +LL - let _err = std::io::Error::new(other, E); +LL + let _err = std::io::Error::other(E); + | + +error: this can be `std::io::Error::other(_)` + --> tests/ui/io_other_error.rs:45:20 + | +LL | let _err = Error::new(ErrorKind::Other, super::E); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `std::io::Error::other` + | +LL - let _err = Error::new(ErrorKind::Other, super::E); +LL + let _err = Error::other(super::E); + | + +error: this can be `std::io::Error::other(_)` + --> tests/ui/io_other_error.rs:47:20 + | +LL | let _err = io::Error::new(io::ErrorKind::Other, super::E); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `std::io::Error::other` + | +LL - let _err = io::Error::new(io::ErrorKind::Other, super::E); +LL + let _err = io::Error::other(super::E); + | + +error: aborting due to 4 previous errors + diff --git a/tests/ui/is_digit_ascii_radix.fixed b/tests/ui/is_digit_ascii_radix.fixed index 62953ff74cfc..b0509ed2a751 100644 --- a/tests/ui/is_digit_ascii_radix.fixed +++ b/tests/ui/is_digit_ascii_radix.fixed @@ -7,8 +7,11 @@ fn main() { // Should trigger the lint. let _ = c.is_ascii_digit(); + //~^ is_digit_ascii_radix let _ = c.is_ascii_hexdigit(); + //~^ is_digit_ascii_radix let _ = c.is_ascii_hexdigit(); + //~^ is_digit_ascii_radix // Should not trigger the lint. let _ = c.is_digit(11); diff --git a/tests/ui/is_digit_ascii_radix.rs b/tests/ui/is_digit_ascii_radix.rs index 229f530f611d..68d4b56063b5 100644 --- a/tests/ui/is_digit_ascii_radix.rs +++ b/tests/ui/is_digit_ascii_radix.rs @@ -7,8 +7,11 @@ fn main() { // Should trigger the lint. let _ = c.is_digit(10); + //~^ is_digit_ascii_radix let _ = c.is_digit(16); + //~^ is_digit_ascii_radix let _ = c.is_digit(0x10); + //~^ is_digit_ascii_radix // Should not trigger the lint. let _ = c.is_digit(11); diff --git a/tests/ui/is_digit_ascii_radix.stderr b/tests/ui/is_digit_ascii_radix.stderr index f26183ddab84..b6e53eb5829f 100644 --- a/tests/ui/is_digit_ascii_radix.stderr +++ b/tests/ui/is_digit_ascii_radix.stderr @@ -8,13 +8,13 @@ LL | let _ = c.is_digit(10); = help: to override `-D warnings` add `#[allow(clippy::is_digit_ascii_radix)]` error: use of `char::is_digit` with literal radix of 16 - --> tests/ui/is_digit_ascii_radix.rs:10:13 + --> tests/ui/is_digit_ascii_radix.rs:11:13 | LL | let _ = c.is_digit(16); | ^^^^^^^^^^^^^^ help: try: `c.is_ascii_hexdigit()` error: use of `char::is_digit` with literal radix of 16 - --> tests/ui/is_digit_ascii_radix.rs:11:13 + --> tests/ui/is_digit_ascii_radix.rs:13:13 | LL | let _ = c.is_digit(0x10); | ^^^^^^^^^^^^^^^^ help: try: `c.is_ascii_hexdigit()` diff --git a/tests/ui/issue-111399.rs b/tests/ui/issue-111399.rs index b65e6c7261a5..2a6436b4b4eb 100644 --- a/tests/ui/issue-111399.rs +++ b/tests/ui/issue-111399.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![feature(inherent_associated_types)] #![allow(incomplete_features)] diff --git a/tests/ui/issue-7447.rs b/tests/ui/issue-7447.rs index 7e7ef209d485..452011de1195 100644 --- a/tests/ui/issue-7447.rs +++ b/tests/ui/issue-7447.rs @@ -24,8 +24,8 @@ pub struct ByteView<'a> { fn main() { byte_view(panic!()); - //~^ ERROR: sub-expression diverges - //~| NOTE: `-D clippy::diverging-sub-expression` implied by `-D warnings` + //~^ diverging_sub_expression + group_entries(panic!()); - //~^ ERROR: sub-expression diverges + //~^ diverging_sub_expression } diff --git a/tests/ui/issue_2356.fixed b/tests/ui/issue_2356.fixed index 892aa4e34216..46ba653eba2c 100644 --- a/tests/ui/issue_2356.fixed +++ b/tests/ui/issue_2356.fixed @@ -15,6 +15,7 @@ impl Foo { fn foo2>(mut it: I) { for e in it { + //~^ while_let_on_iterator println!("{:?}", e); } } diff --git a/tests/ui/issue_2356.rs b/tests/ui/issue_2356.rs index da0eead15b39..defe2584a93e 100644 --- a/tests/ui/issue_2356.rs +++ b/tests/ui/issue_2356.rs @@ -15,6 +15,7 @@ impl Foo { fn foo2>(mut it: I) { while let Some(e) = it.next() { + //~^ while_let_on_iterator println!("{:?}", e); } } diff --git a/tests/ui/issue_4266.rs b/tests/ui/issue_4266.rs index 23453207b4e5..664f0b84a207 100644 --- a/tests/ui/issue_4266.rs +++ b/tests/ui/issue_4266.rs @@ -2,13 +2,14 @@ #![allow(clippy::uninlined_format_args)] async fn sink1<'a>(_: &'a str) {} // lint -//~^ ERROR: the following explicit lifetimes could be elided: 'a -//~| NOTE: `-D clippy::needless-lifetimes` implied by `-D warnings` +//~^ needless_lifetimes + async fn sink1_elided(_: &str) {} // ok // lint async fn one_to_one<'a>(s: &'a str) -> &'a str { - //~^ ERROR: the following explicit lifetimes could be elided: 'a + //~^ needless_lifetimes + s } @@ -29,7 +30,8 @@ struct Foo; impl Foo { // ok pub async fn new(&mut self) -> Self { - //~^ ERROR: methods called `new` usually take no `self` + //~^ wrong_self_convention + Foo {} } } diff --git a/tests/ui/issue_4266.stderr b/tests/ui/issue_4266.stderr index 63c568a153b2..0e181025430f 100644 --- a/tests/ui/issue_4266.stderr +++ b/tests/ui/issue_4266.stderr @@ -14,7 +14,7 @@ LL | async fn one_to_one<'a>(s: &'a str) -> &'a str { | ^^ ^^ ^^ error: methods called `new` usually take no `self` - --> tests/ui/issue_4266.rs:31:22 + --> tests/ui/issue_4266.rs:32:22 | LL | pub async fn new(&mut self) -> Self { | ^^^^^^^^^ diff --git a/tests/ui/items_after_statement.rs b/tests/ui/items_after_statement.rs index 943e7c116760..b97c831f37ec 100644 --- a/tests/ui/items_after_statement.rs +++ b/tests/ui/items_after_statement.rs @@ -11,8 +11,8 @@ fn ok() { fn last() { foo(); fn foo() { - //~^ ERROR: adding items after statements is confusing, since items exist from the sta - //~| NOTE: `-D clippy::items-after-statements` implied by `-D warnings` + //~^ items_after_statements + println!("foo"); } } @@ -20,7 +20,8 @@ fn last() { fn main() { foo(); fn foo() { - //~^ ERROR: adding items after statements is confusing, since items exist from the sta + //~^ items_after_statements + println!("foo"); } foo(); @@ -34,6 +35,7 @@ fn mac() { () => {{ a = 6; fn say_something() { + //~^ items_after_statements println!("something"); } }}; diff --git a/tests/ui/items_after_statement.stderr b/tests/ui/items_after_statement.stderr index 0f1989d4c9fc..7a5ae2c8d47d 100644 --- a/tests/ui/items_after_statement.stderr +++ b/tests/ui/items_after_statement.stderr @@ -16,14 +16,16 @@ error: adding items after statements is confusing, since items exist from the st | LL | / fn foo() { LL | | +LL | | LL | | println!("foo"); LL | | } | |_____^ error: adding items after statements is confusing, since items exist from the start of the scope - --> tests/ui/items_after_statement.rs:36:13 + --> tests/ui/items_after_statement.rs:37:13 | LL | / fn say_something() { +LL | | LL | | println!("something"); LL | | } | |_____________^ diff --git a/tests/ui/items_after_test_module/after_proc_macros.rs b/tests/ui/items_after_test_module/after_proc_macros.rs index d9c0aef88c8c..54a04988cda0 100644 --- a/tests/ui/items_after_test_module/after_proc_macros.rs +++ b/tests/ui/items_after_test_module/after_proc_macros.rs @@ -1,3 +1,4 @@ +//@ check-pass //@aux-build:../auxiliary/proc_macros.rs extern crate proc_macros; diff --git a/tests/ui/items_after_test_module/imported_module.rs b/tests/ui/items_after_test_module/imported_module.rs index 6a757aef48e7..d756be5b433e 100644 --- a/tests/ui/items_after_test_module/imported_module.rs +++ b/tests/ui/items_after_test_module/imported_module.rs @@ -1,3 +1,4 @@ +//@ check-pass //@compile-flags: --test #![allow(unused)] #![warn(clippy::items_after_test_module)] diff --git a/tests/ui/items_after_test_module/in_submodule.rs b/tests/ui/items_after_test_module/in_submodule.rs index 7132e71764eb..6ca100c07f96 100644 --- a/tests/ui/items_after_test_module/in_submodule.rs +++ b/tests/ui/items_after_test_module/in_submodule.rs @@ -1,3 +1,4 @@ +//@error-in-other-file: #[path = "auxiliary/submodule.rs"] mod submodule; diff --git a/tests/ui/items_after_test_module/multiple_modules.rs b/tests/ui/items_after_test_module/multiple_modules.rs index 8ab9e8200f18..8618710654a5 100644 --- a/tests/ui/items_after_test_module/multiple_modules.rs +++ b/tests/ui/items_after_test_module/multiple_modules.rs @@ -1,3 +1,5 @@ +//@ check-pass + #[cfg(test)] mod tests { #[test] diff --git a/tests/ui/items_after_test_module/root_module.fixed b/tests/ui/items_after_test_module/root_module.fixed index d444100a76b9..f036b368a667 100644 --- a/tests/ui/items_after_test_module/root_module.fixed +++ b/tests/ui/items_after_test_module/root_module.fixed @@ -17,6 +17,7 @@ macro_rules! should_lint { #[allow(clippy::allow_attributes)] #[cfg(test)] mod tests { + //~^ items_after_test_module #[test] fn hi() {} } diff --git a/tests/ui/items_after_test_module/root_module.rs b/tests/ui/items_after_test_module/root_module.rs index 57da01639cca..de0cbb120330 100644 --- a/tests/ui/items_after_test_module/root_module.rs +++ b/tests/ui/items_after_test_module/root_module.rs @@ -10,6 +10,7 @@ fn should_not_lint() {} #[allow(clippy::allow_attributes)] #[cfg(test)] mod tests { + //~^ items_after_test_module #[test] fn hi() {} } diff --git a/tests/ui/iter_cloned_collect.fixed b/tests/ui/iter_cloned_collect.fixed index 1d623642a713..e9fb44e89598 100644 --- a/tests/ui/iter_cloned_collect.fixed +++ b/tests/ui/iter_cloned_collect.fixed @@ -6,11 +6,13 @@ use std::collections::{HashSet, VecDeque}; fn main() { let v = [1, 2, 3, 4, 5]; let v2: Vec = v.to_vec(); + //~^ iter_cloned_collect let v3: HashSet = v.iter().cloned().collect(); let v4: VecDeque = v.iter().cloned().collect(); // Handle macro expansion in suggestion let _: Vec = vec![1, 2, 3].to_vec(); + //~^ iter_cloned_collect // Issue #3704 unsafe { @@ -21,7 +23,9 @@ fn main() { // Issue #6808 let arr: [u8; 64] = [0; 64]; let _: Vec<_> = arr.to_vec(); + //~^ iter_cloned_collect // Issue #6703 let _: Vec = v.to_vec(); + //~^ iter_cloned_collect } diff --git a/tests/ui/iter_cloned_collect.rs b/tests/ui/iter_cloned_collect.rs index 091bd9eaf081..c9b8abcc9a0d 100644 --- a/tests/ui/iter_cloned_collect.rs +++ b/tests/ui/iter_cloned_collect.rs @@ -6,16 +6,19 @@ use std::collections::{HashSet, VecDeque}; fn main() { let v = [1, 2, 3, 4, 5]; let v2: Vec = v.iter().cloned().collect(); + //~^ iter_cloned_collect let v3: HashSet = v.iter().cloned().collect(); let v4: VecDeque = v.iter().cloned().collect(); // Handle macro expansion in suggestion let _: Vec = vec![1, 2, 3].iter().cloned().collect(); + //~^ iter_cloned_collect // Issue #3704 unsafe { let _: Vec = std::ffi::CStr::from_ptr(std::ptr::null()) .to_bytes() + //~^ iter_cloned_collect .iter() .cloned() .collect(); @@ -24,7 +27,9 @@ fn main() { // Issue #6808 let arr: [u8; 64] = [0; 64]; let _: Vec<_> = arr.iter().cloned().collect(); + //~^ iter_cloned_collect // Issue #6703 let _: Vec = v.iter().copied().collect(); + //~^ iter_cloned_collect } diff --git a/tests/ui/iter_cloned_collect.stderr b/tests/ui/iter_cloned_collect.stderr index e8d82ec2c1b3..119698cb4634 100644 --- a/tests/ui/iter_cloned_collect.stderr +++ b/tests/ui/iter_cloned_collect.stderr @@ -8,29 +8,30 @@ LL | let v2: Vec = v.iter().cloned().collect(); = help: to override `-D warnings` add `#[allow(clippy::iter_cloned_collect)]` error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> tests/ui/iter_cloned_collect.rs:13:38 + --> tests/ui/iter_cloned_collect.rs:14:38 | LL | let _: Vec = vec![1, 2, 3].iter().cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()` error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> tests/ui/iter_cloned_collect.rs:18:24 + --> tests/ui/iter_cloned_collect.rs:20:24 | LL | .to_bytes() | ________________________^ +LL | | LL | | .iter() LL | | .cloned() LL | | .collect(); | |______________________^ help: try: `.to_vec()` error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> tests/ui/iter_cloned_collect.rs:26:24 + --> tests/ui/iter_cloned_collect.rs:29:24 | LL | let _: Vec<_> = arr.iter().cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()` error: called `iter().copied().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable - --> tests/ui/iter_cloned_collect.rs:29:26 + --> tests/ui/iter_cloned_collect.rs:33:26 | LL | let _: Vec = v.iter().copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()` diff --git a/tests/ui/iter_count.fixed b/tests/ui/iter_count.fixed index 75c007bb0c99..2e187e5bfa75 100644 --- a/tests/ui/iter_count.fixed +++ b/tests/ui/iter_count.fixed @@ -52,32 +52,57 @@ fn main() { binary_heap.push(1); &vec[..].len(); + //~^ iter_count vec.len(); + //~^ iter_count boxed_slice.len(); + //~^ iter_count vec_deque.len(); + //~^ iter_count hash_set.len(); + //~^ iter_count hash_map.len(); + //~^ iter_count b_tree_map.len(); + //~^ iter_count b_tree_set.len(); + //~^ iter_count linked_list.len(); + //~^ iter_count binary_heap.len(); + //~^ iter_count vec.len(); + //~^ iter_count &vec[..].len(); + //~^ iter_count vec_deque.len(); + //~^ iter_count hash_map.len(); + //~^ iter_count b_tree_map.len(); + //~^ iter_count linked_list.len(); + //~^ iter_count &vec[..].len(); + //~^ iter_count vec.len(); + //~^ iter_count vec_deque.len(); + //~^ iter_count hash_set.len(); + //~^ iter_count hash_map.len(); + //~^ iter_count b_tree_map.len(); + //~^ iter_count b_tree_set.len(); + //~^ iter_count linked_list.len(); + //~^ iter_count binary_heap.len(); + //~^ iter_count // Make sure we don't lint for non-relevant types. let false_positive = HasIter; diff --git a/tests/ui/iter_count.rs b/tests/ui/iter_count.rs index cd8207b2c5dc..e941892136ec 100644 --- a/tests/ui/iter_count.rs +++ b/tests/ui/iter_count.rs @@ -52,32 +52,57 @@ fn main() { binary_heap.push(1); &vec[..].iter().count(); + //~^ iter_count vec.iter().count(); + //~^ iter_count boxed_slice.iter().count(); + //~^ iter_count vec_deque.iter().count(); + //~^ iter_count hash_set.iter().count(); + //~^ iter_count hash_map.iter().count(); + //~^ iter_count b_tree_map.iter().count(); + //~^ iter_count b_tree_set.iter().count(); + //~^ iter_count linked_list.iter().count(); + //~^ iter_count binary_heap.iter().count(); + //~^ iter_count vec.iter_mut().count(); + //~^ iter_count &vec[..].iter_mut().count(); + //~^ iter_count vec_deque.iter_mut().count(); + //~^ iter_count hash_map.iter_mut().count(); + //~^ iter_count b_tree_map.iter_mut().count(); + //~^ iter_count linked_list.iter_mut().count(); + //~^ iter_count &vec[..].into_iter().count(); + //~^ iter_count vec.into_iter().count(); + //~^ iter_count vec_deque.into_iter().count(); + //~^ iter_count hash_set.into_iter().count(); + //~^ iter_count hash_map.into_iter().count(); + //~^ iter_count b_tree_map.into_iter().count(); + //~^ iter_count b_tree_set.into_iter().count(); + //~^ iter_count linked_list.into_iter().count(); + //~^ iter_count binary_heap.into_iter().count(); + //~^ iter_count // Make sure we don't lint for non-relevant types. let false_positive = HasIter; diff --git a/tests/ui/iter_count.stderr b/tests/ui/iter_count.stderr index b703310731f3..a5ccefd9048d 100644 --- a/tests/ui/iter_count.stderr +++ b/tests/ui/iter_count.stderr @@ -8,145 +8,145 @@ LL | &vec[..].iter().count(); = help: to override `-D warnings` add `#[allow(clippy::iter_count)]` error: called `.iter().count()` on a `Vec` - --> tests/ui/iter_count.rs:55:5 + --> tests/ui/iter_count.rs:56:5 | LL | vec.iter().count(); | ^^^^^^^^^^^^^^^^^^ help: try: `vec.len()` error: called `.iter().count()` on a `slice` - --> tests/ui/iter_count.rs:56:5 + --> tests/ui/iter_count.rs:58:5 | LL | boxed_slice.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice.len()` error: called `.iter().count()` on a `VecDeque` - --> tests/ui/iter_count.rs:57:5 + --> tests/ui/iter_count.rs:60:5 | LL | vec_deque.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec_deque.len()` error: called `.iter().count()` on a `HashSet` - --> tests/ui/iter_count.rs:58:5 + --> tests/ui/iter_count.rs:62:5 | LL | hash_set.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_set.len()` error: called `.iter().count()` on a `HashMap` - --> tests/ui/iter_count.rs:59:5 + --> tests/ui/iter_count.rs:64:5 | LL | hash_map.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.len()` error: called `.iter().count()` on a `BTreeMap` - --> tests/ui/iter_count.rs:60:5 + --> tests/ui/iter_count.rs:66:5 | LL | b_tree_map.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_map.len()` error: called `.iter().count()` on a `BTreeSet` - --> tests/ui/iter_count.rs:61:5 + --> tests/ui/iter_count.rs:68:5 | LL | b_tree_set.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_set.len()` error: called `.iter().count()` on a `LinkedList` - --> tests/ui/iter_count.rs:62:5 + --> tests/ui/iter_count.rs:70:5 | LL | linked_list.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `linked_list.len()` error: called `.iter().count()` on a `BinaryHeap` - --> tests/ui/iter_count.rs:63:5 + --> tests/ui/iter_count.rs:72:5 | LL | binary_heap.iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `binary_heap.len()` error: called `.iter_mut().count()` on a `Vec` - --> tests/ui/iter_count.rs:65:5 + --> tests/ui/iter_count.rs:75:5 | LL | vec.iter_mut().count(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.len()` error: called `.iter_mut().count()` on a `slice` - --> tests/ui/iter_count.rs:66:6 + --> tests/ui/iter_count.rs:77:6 | LL | &vec[..].iter_mut().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()` error: called `.iter_mut().count()` on a `VecDeque` - --> tests/ui/iter_count.rs:67:5 + --> tests/ui/iter_count.rs:79:5 | LL | vec_deque.iter_mut().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec_deque.len()` error: called `.iter_mut().count()` on a `HashMap` - --> tests/ui/iter_count.rs:68:5 + --> tests/ui/iter_count.rs:81:5 | LL | hash_map.iter_mut().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.len()` error: called `.iter_mut().count()` on a `BTreeMap` - --> tests/ui/iter_count.rs:69:5 + --> tests/ui/iter_count.rs:83:5 | LL | b_tree_map.iter_mut().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_map.len()` error: called `.iter_mut().count()` on a `LinkedList` - --> tests/ui/iter_count.rs:70:5 + --> tests/ui/iter_count.rs:85:5 | LL | linked_list.iter_mut().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `linked_list.len()` error: called `.into_iter().count()` on a `slice` - --> tests/ui/iter_count.rs:72:6 + --> tests/ui/iter_count.rs:88:6 | LL | &vec[..].into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()` error: called `.into_iter().count()` on a `Vec` - --> tests/ui/iter_count.rs:73:5 + --> tests/ui/iter_count.rs:90:5 | LL | vec.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.len()` error: called `.into_iter().count()` on a `VecDeque` - --> tests/ui/iter_count.rs:74:5 + --> tests/ui/iter_count.rs:92:5 | LL | vec_deque.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec_deque.len()` error: called `.into_iter().count()` on a `HashSet` - --> tests/ui/iter_count.rs:75:5 + --> tests/ui/iter_count.rs:94:5 | LL | hash_set.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_set.len()` error: called `.into_iter().count()` on a `HashMap` - --> tests/ui/iter_count.rs:76:5 + --> tests/ui/iter_count.rs:96:5 | LL | hash_map.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.len()` error: called `.into_iter().count()` on a `BTreeMap` - --> tests/ui/iter_count.rs:77:5 + --> tests/ui/iter_count.rs:98:5 | LL | b_tree_map.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_map.len()` error: called `.into_iter().count()` on a `BTreeSet` - --> tests/ui/iter_count.rs:78:5 + --> tests/ui/iter_count.rs:100:5 | LL | b_tree_set.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_set.len()` error: called `.into_iter().count()` on a `LinkedList` - --> tests/ui/iter_count.rs:79:5 + --> tests/ui/iter_count.rs:102:5 | LL | linked_list.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `linked_list.len()` error: called `.into_iter().count()` on a `BinaryHeap` - --> tests/ui/iter_count.rs:80:5 + --> tests/ui/iter_count.rs:104:5 | LL | binary_heap.into_iter().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `binary_heap.len()` diff --git a/tests/ui/iter_filter_is_ok.fixed b/tests/ui/iter_filter_is_ok.fixed index 80db8b29c18e..3223e19d23a7 100644 --- a/tests/ui/iter_filter_is_ok.fixed +++ b/tests/ui/iter_filter_is_ok.fixed @@ -9,51 +9,54 @@ fn main() { { let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten(); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok + let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten(); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok + #[rustfmt::skip] let _ = vec![Ok(1), Err(2)].into_iter().flatten(); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok } { let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten(); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten(); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok #[rustfmt::skip] let _ = vec![Ok(1), Err(2)].into_iter().flatten(); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok } { let _ = vec![Ok(1), Err(2), Ok(3)] .into_iter() .flatten(); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok let _ = vec![Ok(1), Err(2), Ok(3)] .into_iter() .flatten(); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok + #[rustfmt::skip] let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten(); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok } { let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten(); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten(); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok #[rustfmt::skip] let _ = vec![Ok(1), Err(2)].into_iter().flatten(); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok } } diff --git a/tests/ui/iter_filter_is_ok.rs b/tests/ui/iter_filter_is_ok.rs index 89b083b84f32..973653819850 100644 --- a/tests/ui/iter_filter_is_ok.rs +++ b/tests/ui/iter_filter_is_ok.rs @@ -9,51 +9,54 @@ fn main() { { let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(Result::is_ok); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok + let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|a| a.is_ok()); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok + #[rustfmt::skip] let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| { o.is_ok() }); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok } { let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|&a| a.is_ok()); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|&a| a.is_ok()); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok #[rustfmt::skip] let _ = vec![Ok(1), Err(2)].into_iter().filter(|&o| { o.is_ok() }); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok } { let _ = vec![Ok(1), Err(2), Ok(3)] .into_iter() .filter(std::result::Result::is_ok); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok let _ = vec![Ok(1), Err(2), Ok(3)] .into_iter() .filter(|a| std::result::Result::is_ok(a)); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok + #[rustfmt::skip] let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|a| { std::result::Result::is_ok(a) }); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok } { let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|ref a| a.is_ok()); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|ref a| a.is_ok()); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok #[rustfmt::skip] let _ = vec![Ok(1), Err(2)].into_iter().filter(|ref o| { o.is_ok() }); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_ok } } diff --git a/tests/ui/iter_filter_is_ok.stderr b/tests/ui/iter_filter_is_ok.stderr index 0aff60224e0e..b7fd0d25cc23 100644 --- a/tests/ui/iter_filter_is_ok.stderr +++ b/tests/ui/iter_filter_is_ok.stderr @@ -8,59 +8,53 @@ LL | let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(Result::is_ok = help: to override `-D warnings` add `#[allow(clippy::iter_filter_is_ok)]` error: `filter` for `is_ok` on iterator over `Result`s - --> tests/ui/iter_filter_is_ok.rs:13:56 + --> tests/ui/iter_filter_is_ok.rs:14:56 | LL | let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|a| a.is_ok()); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `is_ok` on iterator over `Result`s - --> tests/ui/iter_filter_is_ok.rs:16:49 + --> tests/ui/iter_filter_is_ok.rs:18:49 | LL | let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| { o.is_ok() }); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `is_ok` on iterator over `Result`s - --> tests/ui/iter_filter_is_ok.rs:21:56 + --> tests/ui/iter_filter_is_ok.rs:23:56 | LL | let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|&a| a.is_ok()); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `is_ok` on iterator over `Result`s - --> tests/ui/iter_filter_is_ok.rs:24:56 + --> tests/ui/iter_filter_is_ok.rs:26:56 | LL | let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|&a| a.is_ok()); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `is_ok` on iterator over `Result`s - --> tests/ui/iter_filter_is_ok.rs:28:49 + --> tests/ui/iter_filter_is_ok.rs:30:49 | LL | let _ = vec![Ok(1), Err(2)].into_iter().filter(|&o| { o.is_ok() }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `is_ok` on iterator over `Result`s - --> tests/ui/iter_filter_is_ok.rs:35:14 + --> tests/ui/iter_filter_is_ok.rs:37:14 | LL | .filter(std::result::Result::is_ok); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `is_ok` on iterator over `Result`s - --> tests/ui/iter_filter_is_ok.rs:40:14 + --> tests/ui/iter_filter_is_ok.rs:42:14 | LL | .filter(|a| std::result::Result::is_ok(a)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `is_ok` on iterator over `Result`s - --> tests/ui/iter_filter_is_ok.rs:43:56 + --> tests/ui/iter_filter_is_ok.rs:46:56 | LL | let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|a| { std::result::Result::is_ok(a) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` -error: `filter` for `is_ok` on iterator over `Result`s - --> tests/ui/iter_filter_is_ok.rs:48:56 - | -LL | let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|ref a| a.is_ok()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` - error: `filter` for `is_ok` on iterator over `Result`s --> tests/ui/iter_filter_is_ok.rs:51:56 | @@ -68,7 +62,13 @@ LL | let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|ref a| a.is_ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `is_ok` on iterator over `Result`s - --> tests/ui/iter_filter_is_ok.rs:55:49 + --> tests/ui/iter_filter_is_ok.rs:54:56 + | +LL | let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|ref a| a.is_ok()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` + +error: `filter` for `is_ok` on iterator over `Result`s + --> tests/ui/iter_filter_is_ok.rs:58:49 | LL | let _ = vec![Ok(1), Err(2)].into_iter().filter(|ref o| { o.is_ok() }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` diff --git a/tests/ui/iter_filter_is_some.fixed b/tests/ui/iter_filter_is_some.fixed index 8a818c0c6728..99e764e957fb 100644 --- a/tests/ui/iter_filter_is_some.fixed +++ b/tests/ui/iter_filter_is_some.fixed @@ -13,45 +13,48 @@ use std::collections::HashMap; fn main() { { let _ = vec![Some(1), None, Some(3)].into_iter().flatten(); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_some + let _ = vec![Some(1), None, Some(3)].into_iter().flatten(); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_some + #[rustfmt::skip] let _ = vec![Some(1), None, Some(3)].into_iter().flatten(); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_some } { let _ = vec![Some(1), None, Some(3)] .into_iter() .flatten(); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_some let _ = vec![Some(1), None, Some(3)] .into_iter() .flatten(); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_some + #[rustfmt::skip] let _ = vec![Some(1), None, Some(3)].into_iter().flatten(); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_some } { let _ = vec![Some(1), None, Some(3)].into_iter().flatten(); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_some #[rustfmt::skip] let _ = vec![Some(1), None, Some(3)].into_iter().flatten(); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_some } { let _ = vec![Some(1), None, Some(3)].into_iter().flatten(); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_some #[rustfmt::skip] let _ = vec![Some(1), None, Some(3)].into_iter().flatten(); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_some } } diff --git a/tests/ui/iter_filter_is_some.rs b/tests/ui/iter_filter_is_some.rs index 9eda93a25921..ecb7a04ab4df 100644 --- a/tests/ui/iter_filter_is_some.rs +++ b/tests/ui/iter_filter_is_some.rs @@ -13,45 +13,48 @@ use std::collections::HashMap; fn main() { { let _ = vec![Some(1), None, Some(3)].into_iter().filter(Option::is_some); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_some + let _ = vec![Some(1), None, Some(3)].into_iter().filter(|a| a.is_some()); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_some + #[rustfmt::skip] let _ = vec![Some(1), None, Some(3)].into_iter().filter(|o| { o.is_some() }); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_some } { let _ = vec![Some(1), None, Some(3)] .into_iter() .filter(std::option::Option::is_some); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_some let _ = vec![Some(1), None, Some(3)] .into_iter() .filter(|a| std::option::Option::is_some(a)); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_some + #[rustfmt::skip] let _ = vec![Some(1), None, Some(3)].into_iter().filter(|a| { std::option::Option::is_some(a) }); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_some } { let _ = vec![Some(1), None, Some(3)].into_iter().filter(|&a| a.is_some()); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_some #[rustfmt::skip] let _ = vec![Some(1), None, Some(3)].into_iter().filter(|&o| { o.is_some() }); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_some } { let _ = vec![Some(1), None, Some(3)].into_iter().filter(|ref a| a.is_some()); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_some #[rustfmt::skip] let _ = vec![Some(1), None, Some(3)].into_iter().filter(|ref o| { o.is_some() }); - //~^ HELP: consider using `flatten` instead + //~^ iter_filter_is_some } } diff --git a/tests/ui/iter_filter_is_some.stderr b/tests/ui/iter_filter_is_some.stderr index 54aff892b1f0..cd01a3e05cd0 100644 --- a/tests/ui/iter_filter_is_some.stderr +++ b/tests/ui/iter_filter_is_some.stderr @@ -8,55 +8,55 @@ LL | let _ = vec![Some(1), None, Some(3)].into_iter().filter(Option::is_ = help: to override `-D warnings` add `#[allow(clippy::iter_filter_is_some)]` error: `filter` for `is_some` on iterator over `Option` - --> tests/ui/iter_filter_is_some.rs:17:58 + --> tests/ui/iter_filter_is_some.rs:18:58 | LL | let _ = vec![Some(1), None, Some(3)].into_iter().filter(|a| a.is_some()); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `is_some` on iterator over `Option` - --> tests/ui/iter_filter_is_some.rs:20:58 + --> tests/ui/iter_filter_is_some.rs:22:58 | LL | let _ = vec![Some(1), None, Some(3)].into_iter().filter(|o| { o.is_some() }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `is_some` on iterator over `Option` - --> tests/ui/iter_filter_is_some.rs:27:14 + --> tests/ui/iter_filter_is_some.rs:29:14 | LL | .filter(std::option::Option::is_some); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `is_some` on iterator over `Option` - --> tests/ui/iter_filter_is_some.rs:32:14 + --> tests/ui/iter_filter_is_some.rs:34:14 | LL | .filter(|a| std::option::Option::is_some(a)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `is_some` on iterator over `Option` - --> tests/ui/iter_filter_is_some.rs:35:58 + --> tests/ui/iter_filter_is_some.rs:38:58 | LL | let _ = vec![Some(1), None, Some(3)].into_iter().filter(|a| { std::option::Option::is_some(a) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `is_some` on iterator over `Option` - --> tests/ui/iter_filter_is_some.rs:40:58 + --> tests/ui/iter_filter_is_some.rs:43:58 | LL | let _ = vec![Some(1), None, Some(3)].into_iter().filter(|&a| a.is_some()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `is_some` on iterator over `Option` - --> tests/ui/iter_filter_is_some.rs:44:58 + --> tests/ui/iter_filter_is_some.rs:47:58 | LL | let _ = vec![Some(1), None, Some(3)].into_iter().filter(|&o| { o.is_some() }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `is_some` on iterator over `Option` - --> tests/ui/iter_filter_is_some.rs:49:58 + --> tests/ui/iter_filter_is_some.rs:52:58 | LL | let _ = vec![Some(1), None, Some(3)].into_iter().filter(|ref a| a.is_some()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `is_some` on iterator over `Option` - --> tests/ui/iter_filter_is_some.rs:53:58 + --> tests/ui/iter_filter_is_some.rs:56:58 | LL | let _ = vec![Some(1), None, Some(3)].into_iter().filter(|ref o| { o.is_some() }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` diff --git a/tests/ui/iter_kv_map.fixed b/tests/ui/iter_kv_map.fixed index 2cbf972fca5f..7fcab6592e26 100644 --- a/tests/ui/iter_kv_map.fixed +++ b/tests/ui/iter_kv_map.fixed @@ -12,17 +12,26 @@ fn main() { let map: HashMap = HashMap::new(); let _ = map.keys().collect::>(); + //~^ iter_kv_map let _ = map.values().collect::>(); + //~^ iter_kv_map let _ = map.values().map(|v| v + 2).collect::>(); + //~^ iter_kv_map let _ = map.clone().into_keys().collect::>(); + //~^ iter_kv_map let _ = map.clone().into_keys().map(|key| key + 2).collect::>(); + //~^ iter_kv_map let _ = map.clone().into_values().collect::>(); + //~^ iter_kv_map let _ = map.clone().into_values().map(|val| val + 2).collect::>(); + //~^ iter_kv_map let _ = map.clone().values().collect::>(); + //~^ iter_kv_map let _ = map.keys().filter(|x| *x % 2 == 0).count(); + //~^ iter_kv_map // Don't lint let _ = map.iter().filter(|(_, val)| *val % 2 == 0).map(|(key, _)| key).count(); @@ -33,13 +42,17 @@ fn main() { // Lint let _ = map.keys().map(|key| key * 9).count(); + //~^ iter_kv_map let _ = map.values().map(|value| value * 17).count(); + //~^ iter_kv_map // Preserve the ref in the fix. let _ = map.clone().into_values().map(|ref val| ref_acceptor(val)).count(); + //~^ iter_kv_map // Preserve the mut in the fix. let _ = map + //~^ iter_kv_map .clone().into_values().map(|mut val| { val += 2; val @@ -48,21 +61,31 @@ fn main() { // Don't let a mut interfere. let _ = map.clone().into_values().count(); + //~^ iter_kv_map let map: BTreeMap = BTreeMap::new(); let _ = map.keys().collect::>(); + //~^ iter_kv_map let _ = map.values().collect::>(); + //~^ iter_kv_map let _ = map.values().map(|v| v + 2).collect::>(); + //~^ iter_kv_map let _ = map.clone().into_keys().collect::>(); + //~^ iter_kv_map let _ = map.clone().into_keys().map(|key| key + 2).collect::>(); + //~^ iter_kv_map let _ = map.clone().into_values().collect::>(); + //~^ iter_kv_map let _ = map.clone().into_values().map(|val| val + 2).collect::>(); + //~^ iter_kv_map let _ = map.clone().values().collect::>(); + //~^ iter_kv_map let _ = map.keys().filter(|x| *x % 2 == 0).count(); + //~^ iter_kv_map // Don't lint let _ = map.iter().filter(|(_, val)| *val % 2 == 0).map(|(key, _)| key).count(); @@ -73,13 +96,17 @@ fn main() { // Lint let _ = map.keys().map(|key| key * 9).count(); + //~^ iter_kv_map let _ = map.values().map(|value| value * 17).count(); + //~^ iter_kv_map // Preserve the ref in the fix. let _ = map.clone().into_values().map(|ref val| ref_acceptor(val)).count(); + //~^ iter_kv_map // Preserve the mut in the fix. let _ = map + //~^ iter_kv_map .clone().into_values().map(|mut val| { val += 2; val @@ -88,6 +115,7 @@ fn main() { // Don't let a mut interfere. let _ = map.clone().into_values().count(); + //~^ iter_kv_map } #[clippy::msrv = "1.53"] @@ -103,11 +131,13 @@ fn msrv_1_53() { // Lint let _ = map.keys().collect::>(); - //~^ ERROR: iterating on a map's keys + //~^ iter_kv_map + let _ = map.values().collect::>(); - //~^ ERROR: iterating on a map's values + //~^ iter_kv_map + let _ = map.values().map(|v| v + 2).collect::>(); - //~^ ERROR: iterating on a map's values + //~^ iter_kv_map } #[clippy::msrv = "1.54"] @@ -116,19 +146,23 @@ fn msrv_1_54() { let map: HashMap = HashMap::new(); let _ = map.clone().into_keys().collect::>(); - //~^ ERROR: iterating on a map's keys + //~^ iter_kv_map + let _ = map.clone().into_keys().map(|key| key + 2).collect::>(); - //~^ ERROR: iterating on a map's keys + //~^ iter_kv_map let _ = map.clone().into_values().collect::>(); - //~^ ERROR: iterating on a map's values + //~^ iter_kv_map + let _ = map.clone().into_values().map(|val| val + 2).collect::>(); - //~^ ERROR: iterating on a map's values + //~^ iter_kv_map let _ = map.keys().collect::>(); - //~^ ERROR: iterating on a map's keys + //~^ iter_kv_map + let _ = map.values().collect::>(); - //~^ ERROR: iterating on a map's values + //~^ iter_kv_map + let _ = map.values().map(|v| v + 2).collect::>(); - //~^ ERROR: iterating on a map's values + //~^ iter_kv_map } diff --git a/tests/ui/iter_kv_map.rs b/tests/ui/iter_kv_map.rs index 6a9a4267a765..b590aef7b803 100644 --- a/tests/ui/iter_kv_map.rs +++ b/tests/ui/iter_kv_map.rs @@ -12,17 +12,26 @@ fn main() { let map: HashMap = HashMap::new(); let _ = map.iter().map(|(key, _)| key).collect::>(); + //~^ iter_kv_map let _ = map.iter().map(|(_, value)| value).collect::>(); + //~^ iter_kv_map let _ = map.iter().map(|(_, v)| v + 2).collect::>(); + //~^ iter_kv_map let _ = map.clone().into_iter().map(|(key, _)| key).collect::>(); + //~^ iter_kv_map let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::>(); + //~^ iter_kv_map let _ = map.clone().into_iter().map(|(_, val)| val).collect::>(); + //~^ iter_kv_map let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::>(); + //~^ iter_kv_map let _ = map.clone().iter().map(|(_, val)| val).collect::>(); + //~^ iter_kv_map let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count(); + //~^ iter_kv_map // Don't lint let _ = map.iter().filter(|(_, val)| *val % 2 == 0).map(|(key, _)| key).count(); @@ -33,13 +42,17 @@ fn main() { // Lint let _ = map.iter().map(|(key, _value)| key * 9).count(); + //~^ iter_kv_map let _ = map.iter().map(|(_key, value)| value * 17).count(); + //~^ iter_kv_map // Preserve the ref in the fix. let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count(); + //~^ iter_kv_map // Preserve the mut in the fix. let _ = map + //~^ iter_kv_map .clone() .into_iter() .map(|(_, mut val)| { @@ -50,21 +63,31 @@ fn main() { // Don't let a mut interfere. let _ = map.clone().into_iter().map(|(_, mut val)| val).count(); + //~^ iter_kv_map let map: BTreeMap = BTreeMap::new(); let _ = map.iter().map(|(key, _)| key).collect::>(); + //~^ iter_kv_map let _ = map.iter().map(|(_, value)| value).collect::>(); + //~^ iter_kv_map let _ = map.iter().map(|(_, v)| v + 2).collect::>(); + //~^ iter_kv_map let _ = map.clone().into_iter().map(|(key, _)| key).collect::>(); + //~^ iter_kv_map let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::>(); + //~^ iter_kv_map let _ = map.clone().into_iter().map(|(_, val)| val).collect::>(); + //~^ iter_kv_map let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::>(); + //~^ iter_kv_map let _ = map.clone().iter().map(|(_, val)| val).collect::>(); + //~^ iter_kv_map let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count(); + //~^ iter_kv_map // Don't lint let _ = map.iter().filter(|(_, val)| *val % 2 == 0).map(|(key, _)| key).count(); @@ -75,13 +98,17 @@ fn main() { // Lint let _ = map.iter().map(|(key, _value)| key * 9).count(); + //~^ iter_kv_map let _ = map.iter().map(|(_key, value)| value * 17).count(); + //~^ iter_kv_map // Preserve the ref in the fix. let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count(); + //~^ iter_kv_map // Preserve the mut in the fix. let _ = map + //~^ iter_kv_map .clone() .into_iter() .map(|(_, mut val)| { @@ -92,6 +119,7 @@ fn main() { // Don't let a mut interfere. let _ = map.clone().into_iter().map(|(_, mut val)| val).count(); + //~^ iter_kv_map } #[clippy::msrv = "1.53"] @@ -107,11 +135,13 @@ fn msrv_1_53() { // Lint let _ = map.iter().map(|(key, _)| key).collect::>(); - //~^ ERROR: iterating on a map's keys + //~^ iter_kv_map + let _ = map.iter().map(|(_, value)| value).collect::>(); - //~^ ERROR: iterating on a map's values + //~^ iter_kv_map + let _ = map.iter().map(|(_, v)| v + 2).collect::>(); - //~^ ERROR: iterating on a map's values + //~^ iter_kv_map } #[clippy::msrv = "1.54"] @@ -120,19 +150,23 @@ fn msrv_1_54() { let map: HashMap = HashMap::new(); let _ = map.clone().into_iter().map(|(key, _)| key).collect::>(); - //~^ ERROR: iterating on a map's keys + //~^ iter_kv_map + let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::>(); - //~^ ERROR: iterating on a map's keys + //~^ iter_kv_map let _ = map.clone().into_iter().map(|(_, val)| val).collect::>(); - //~^ ERROR: iterating on a map's values + //~^ iter_kv_map + let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::>(); - //~^ ERROR: iterating on a map's values + //~^ iter_kv_map let _ = map.iter().map(|(key, _)| key).collect::>(); - //~^ ERROR: iterating on a map's keys + //~^ iter_kv_map + let _ = map.iter().map(|(_, value)| value).collect::>(); - //~^ ERROR: iterating on a map's values + //~^ iter_kv_map + let _ = map.iter().map(|(_, v)| v + 2).collect::>(); - //~^ ERROR: iterating on a map's values + //~^ iter_kv_map } diff --git a/tests/ui/iter_kv_map.stderr b/tests/ui/iter_kv_map.stderr index ad23dba55cb6..00d566ed14a2 100644 --- a/tests/ui/iter_kv_map.stderr +++ b/tests/ui/iter_kv_map.stderr @@ -8,80 +8,80 @@ LL | let _ = map.iter().map(|(key, _)| key).collect::>(); = help: to override `-D warnings` add `#[allow(clippy::iter_kv_map)]` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:15:13 + --> tests/ui/iter_kv_map.rs:16:13 | LL | let _ = map.iter().map(|(_, value)| value).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:16:13 + --> tests/ui/iter_kv_map.rs:18:13 | LL | let _ = map.iter().map(|(_, v)| v + 2).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:18:13 + --> tests/ui/iter_kv_map.rs:21:13 | LL | let _ = map.clone().into_iter().map(|(key, _)| key).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:19:13 + --> tests/ui/iter_kv_map.rs:23:13 | LL | let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:21:13 + --> tests/ui/iter_kv_map.rs:26:13 | LL | let _ = map.clone().into_iter().map(|(_, val)| val).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:22:13 + --> tests/ui/iter_kv_map.rs:28:13 | LL | let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:24:13 + --> tests/ui/iter_kv_map.rs:31:13 | LL | let _ = map.clone().iter().map(|(_, val)| val).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:25:13 + --> tests/ui/iter_kv_map.rs:33:13 | LL | let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:35:13 + --> tests/ui/iter_kv_map.rs:44:13 | LL | let _ = map.iter().map(|(key, _value)| key * 9).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:36:13 + --> tests/ui/iter_kv_map.rs:46:13 | LL | let _ = map.iter().map(|(_key, value)| value * 17).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:39:13 + --> tests/ui/iter_kv_map.rs:50:13 | LL | let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|ref val| ref_acceptor(val))` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:42:13 + --> tests/ui/iter_kv_map.rs:54:13 | LL | let _ = map | _____________^ +LL | | LL | | .clone() LL | | .into_iter() -LL | | .map(|(_, mut val)| { -LL | | val += 2; +... | LL | | val LL | | }) | |__________^ @@ -89,6 +89,7 @@ LL | | }) help: try | LL ~ let _ = map +LL + LL + .clone().into_values().map(|mut val| { LL + val += 2; LL + val @@ -96,92 +97,92 @@ LL + }) | error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:52:13 + --> tests/ui/iter_kv_map.rs:65:13 | LL | let _ = map.clone().into_iter().map(|(_, mut val)| val).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:56:13 + --> tests/ui/iter_kv_map.rs:70:13 | LL | let _ = map.iter().map(|(key, _)| key).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:57:13 + --> tests/ui/iter_kv_map.rs:72:13 | LL | let _ = map.iter().map(|(_, value)| value).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:58:13 + --> tests/ui/iter_kv_map.rs:74:13 | LL | let _ = map.iter().map(|(_, v)| v + 2).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)` -error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:60:13 - | -LL | let _ = map.clone().into_iter().map(|(key, _)| key).collect::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()` - -error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:61:13 - | -LL | let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)` - -error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:63:13 - | -LL | let _ = map.clone().into_iter().map(|(_, val)| val).collect::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()` - -error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:64:13 - | -LL | let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)` - -error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:66:13 - | -LL | let _ = map.clone().iter().map(|(_, val)| val).collect::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()` - -error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:67:13 - | -LL | let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` - error: iterating on a map's keys --> tests/ui/iter_kv_map.rs:77:13 | +LL | let _ = map.clone().into_iter().map(|(key, _)| key).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()` + +error: iterating on a map's keys + --> tests/ui/iter_kv_map.rs:79:13 + | +LL | let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)` + +error: iterating on a map's values + --> tests/ui/iter_kv_map.rs:82:13 + | +LL | let _ = map.clone().into_iter().map(|(_, val)| val).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()` + +error: iterating on a map's values + --> tests/ui/iter_kv_map.rs:84:13 + | +LL | let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)` + +error: iterating on a map's values + --> tests/ui/iter_kv_map.rs:87:13 + | +LL | let _ = map.clone().iter().map(|(_, val)| val).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()` + +error: iterating on a map's keys + --> tests/ui/iter_kv_map.rs:89:13 + | +LL | let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` + +error: iterating on a map's keys + --> tests/ui/iter_kv_map.rs:100:13 + | LL | let _ = map.iter().map(|(key, _value)| key * 9).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:78:13 + --> tests/ui/iter_kv_map.rs:102:13 | LL | let _ = map.iter().map(|(_key, value)| value * 17).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:81:13 + --> tests/ui/iter_kv_map.rs:106:13 | LL | let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|ref val| ref_acceptor(val))` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:84:13 + --> tests/ui/iter_kv_map.rs:110:13 | LL | let _ = map | _____________^ +LL | | LL | | .clone() LL | | .into_iter() -LL | | .map(|(_, mut val)| { -LL | | val += 2; +... | LL | | val LL | | }) | |__________^ @@ -189,6 +190,7 @@ LL | | }) help: try | LL ~ let _ = map +LL + LL + .clone().into_values().map(|mut val| { LL + val += 2; LL + val @@ -196,67 +198,67 @@ LL + }) | error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:94:13 + --> tests/ui/iter_kv_map.rs:121:13 | LL | let _ = map.clone().into_iter().map(|(_, mut val)| val).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:109:13 + --> tests/ui/iter_kv_map.rs:137:13 | LL | let _ = map.iter().map(|(key, _)| key).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:111:13 + --> tests/ui/iter_kv_map.rs:140:13 | LL | let _ = map.iter().map(|(_, value)| value).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:113:13 + --> tests/ui/iter_kv_map.rs:143:13 | LL | let _ = map.iter().map(|(_, v)| v + 2).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:122:13 + --> tests/ui/iter_kv_map.rs:152:13 | LL | let _ = map.clone().into_iter().map(|(key, _)| key).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:124:13 + --> tests/ui/iter_kv_map.rs:155:13 | LL | let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:127:13 + --> tests/ui/iter_kv_map.rs:158:13 | LL | let _ = map.clone().into_iter().map(|(_, val)| val).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:129:13 + --> tests/ui/iter_kv_map.rs:161:13 | LL | let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:132:13 + --> tests/ui/iter_kv_map.rs:164:13 | LL | let _ = map.iter().map(|(key, _)| key).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:134:13 + --> tests/ui/iter_kv_map.rs:167:13 | LL | let _ = map.iter().map(|(_, value)| value).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:136:13 + --> tests/ui/iter_kv_map.rs:170:13 | LL | let _ = map.iter().map(|(_, v)| v + 2).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)` diff --git a/tests/ui/iter_next_loop.rs b/tests/ui/iter_next_loop.rs index d425f4da0e81..32711c7ef623 100644 --- a/tests/ui/iter_next_loop.rs +++ b/tests/ui/iter_next_loop.rs @@ -4,6 +4,7 @@ fn main() { let x = [1, 2, 3, 4]; for _ in x.iter().next() {} + //~^ iter_next_loop struct Unrelated(&'static [u8]); impl Unrelated { diff --git a/tests/ui/iter_next_slice.fixed b/tests/ui/iter_next_slice.fixed index 83be12c4e254..2e7b4e632840 100644 --- a/tests/ui/iter_next_slice.fixed +++ b/tests/ui/iter_next_slice.fixed @@ -7,15 +7,19 @@ fn main() { let v = vec![1, 2, 3]; let _ = s.first(); + //~^ iter_next_slice // Should be replaced by s.first() let _ = s.get(2); + //~^ iter_next_slice // Should be replaced by s.get(2) let _ = v.get(5); + //~^ iter_next_slice // Should be replaced by v.get(5) let _ = v.first(); + //~^ iter_next_slice // Should be replaced by v.first() let o = Some(5); diff --git a/tests/ui/iter_next_slice.rs b/tests/ui/iter_next_slice.rs index 1b257514d23e..b2e047f5d817 100644 --- a/tests/ui/iter_next_slice.rs +++ b/tests/ui/iter_next_slice.rs @@ -7,15 +7,19 @@ fn main() { let v = vec![1, 2, 3]; let _ = s.iter().next(); + //~^ iter_next_slice // Should be replaced by s.first() let _ = s[2..].iter().next(); + //~^ iter_next_slice // Should be replaced by s.get(2) let _ = v[5..].iter().next(); + //~^ iter_next_slice // Should be replaced by v.get(5) let _ = v.iter().next(); + //~^ iter_next_slice // Should be replaced by v.first() let o = Some(5); diff --git a/tests/ui/iter_next_slice.stderr b/tests/ui/iter_next_slice.stderr index 55cce2b9103d..0a22ab7f6a15 100644 --- a/tests/ui/iter_next_slice.stderr +++ b/tests/ui/iter_next_slice.stderr @@ -8,19 +8,19 @@ LL | let _ = s.iter().next(); = help: to override `-D warnings` add `#[allow(clippy::iter_next_slice)]` error: using `.iter().next()` on a Slice without end index - --> tests/ui/iter_next_slice.rs:12:13 + --> tests/ui/iter_next_slice.rs:13:13 | LL | let _ = s[2..].iter().next(); | ^^^^^^^^^^^^^^^^^^^^ help: try calling: `s.get(2)` error: using `.iter().next()` on a Slice without end index - --> tests/ui/iter_next_slice.rs:15:13 + --> tests/ui/iter_next_slice.rs:17:13 | LL | let _ = v[5..].iter().next(); | ^^^^^^^^^^^^^^^^^^^^ help: try calling: `v.get(5)` error: using `.iter().next()` on an array - --> tests/ui/iter_next_slice.rs:18:13 + --> tests/ui/iter_next_slice.rs:21:13 | LL | let _ = v.iter().next(); | ^^^^^^^^^^^^^^^ help: try calling: `v.first()` diff --git a/tests/ui/iter_not_returning_iterator.rs b/tests/ui/iter_not_returning_iterator.rs index e694bc7ac62f..5c8c8eb4a43d 100644 --- a/tests/ui/iter_not_returning_iterator.rs +++ b/tests/ui/iter_not_returning_iterator.rs @@ -28,13 +28,14 @@ struct Counter2 { impl Data2 { fn iter(&self) -> Counter2 { - //~^ ERROR: this method is named `iter` but its return type does not implement `Iterat - //~| NOTE: `-D clippy::iter-not-returning-iterator` implied by `-D warnings` + //~^ iter_not_returning_iterator + todo!() } fn iter_mut(&self) -> Counter2 { - //~^ ERROR: this method is named `iter_mut` but its return type does not implement `It + //~^ iter_not_returning_iterator + todo!() } } @@ -51,7 +52,7 @@ impl Iterator for Counter { trait Iter { type I; fn iter(&self) -> Self::I; - //~^ ERROR: this method is named `iter` but its return type does not implement `Iterat + //~^ iter_not_returning_iterator } impl Iter for () { diff --git a/tests/ui/iter_not_returning_iterator.stderr b/tests/ui/iter_not_returning_iterator.stderr index c3ee8bae772d..74ee8325d53e 100644 --- a/tests/ui/iter_not_returning_iterator.stderr +++ b/tests/ui/iter_not_returning_iterator.stderr @@ -14,7 +14,7 @@ LL | fn iter_mut(&self) -> Counter2 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this method is named `iter` but its return type does not implement `Iterator` - --> tests/ui/iter_not_returning_iterator.rs:53:5 + --> tests/ui/iter_not_returning_iterator.rs:54:5 | LL | fn iter(&self) -> Self::I; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/iter_nth.fixed b/tests/ui/iter_nth.fixed index aff3731a8837..5650903a5dcb 100644 --- a/tests/ui/iter_nth.fixed +++ b/tests/ui/iter_nth.fixed @@ -32,24 +32,32 @@ fn iter_nth() { { // Make sure we lint `.iter()` for relevant types. let bad_vec = some_vec.get(3); + //~^ iter_nth let bad_slice = &some_vec[..].get(3); + //~^ iter_nth let bad_boxed_slice = boxed_slice.get(3); + //~^ iter_nth let bad_vec_deque = some_vec_deque.get(3); + //~^ iter_nth } { // Make sure we lint `.iter_mut()` for relevant types. let bad_vec = some_vec.get_mut(3); + //~^ iter_nth } { let bad_slice = &some_vec[..].get_mut(3); + //~^ iter_nth } { let bad_vec_deque = some_vec_deque.get_mut(3); + //~^ iter_nth } let vec_ref = &Vec::::new(); vec_ref.get(3); + //~^ iter_nth // Make sure we don't lint for non-relevant types. let false_positive = HasIter; diff --git a/tests/ui/iter_nth.rs b/tests/ui/iter_nth.rs index 89d68044ddda..cfd0629420e1 100644 --- a/tests/ui/iter_nth.rs +++ b/tests/ui/iter_nth.rs @@ -32,24 +32,32 @@ fn iter_nth() { { // Make sure we lint `.iter()` for relevant types. let bad_vec = some_vec.iter().nth(3); + //~^ iter_nth let bad_slice = &some_vec[..].iter().nth(3); + //~^ iter_nth let bad_boxed_slice = boxed_slice.iter().nth(3); + //~^ iter_nth let bad_vec_deque = some_vec_deque.iter().nth(3); + //~^ iter_nth } { // Make sure we lint `.iter_mut()` for relevant types. let bad_vec = some_vec.iter_mut().nth(3); + //~^ iter_nth } { let bad_slice = &some_vec[..].iter_mut().nth(3); + //~^ iter_nth } { let bad_vec_deque = some_vec_deque.iter_mut().nth(3); + //~^ iter_nth } let vec_ref = &Vec::::new(); vec_ref.iter().nth(3); + //~^ iter_nth // Make sure we don't lint for non-relevant types. let false_positive = HasIter; diff --git a/tests/ui/iter_nth.stderr b/tests/ui/iter_nth.stderr index 1167a604ecdc..76ddfd9684e2 100644 --- a/tests/ui/iter_nth.stderr +++ b/tests/ui/iter_nth.stderr @@ -13,7 +13,7 @@ LL + let bad_vec = some_vec.get(3); | error: called `.iter().nth()` on a slice - --> tests/ui/iter_nth.rs:35:26 + --> tests/ui/iter_nth.rs:36:26 | LL | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + let bad_slice = &some_vec[..].get(3); | error: called `.iter().nth()` on a slice - --> tests/ui/iter_nth.rs:36:31 + --> tests/ui/iter_nth.rs:38:31 | LL | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + let bad_boxed_slice = boxed_slice.get(3); | error: called `.iter().nth()` on a `VecDeque` - --> tests/ui/iter_nth.rs:37:29 + --> tests/ui/iter_nth.rs:40:29 | LL | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + let bad_vec_deque = some_vec_deque.get(3); | error: called `.iter_mut().nth()` on a `Vec` - --> tests/ui/iter_nth.rs:42:23 + --> tests/ui/iter_nth.rs:46:23 | LL | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + let bad_vec = some_vec.get_mut(3); | error: called `.iter_mut().nth()` on a slice - --> tests/ui/iter_nth.rs:45:26 + --> tests/ui/iter_nth.rs:50:26 | LL | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + let bad_slice = &some_vec[..].get_mut(3); | error: called `.iter_mut().nth()` on a `VecDeque` - --> tests/ui/iter_nth.rs:48:29 + --> tests/ui/iter_nth.rs:54:29 | LL | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + let bad_vec_deque = some_vec_deque.get_mut(3); | error: called `.iter().nth()` on a `Vec` - --> tests/ui/iter_nth.rs:52:5 + --> tests/ui/iter_nth.rs:59:5 | LL | vec_ref.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/iter_nth_zero.fixed b/tests/ui/iter_nth_zero.fixed index a3cdb2e59bff..07153db90c19 100644 --- a/tests/ui/iter_nth_zero.fixed +++ b/tests/ui/iter_nth_zero.fixed @@ -16,16 +16,19 @@ fn main() { let mut s = HashSet::new(); s.insert(1); let _x = s.iter().next(); + //~^ iter_nth_zero let mut s2 = HashSet::new(); s2.insert(2); let mut iter = s2.iter(); let _y = iter.next(); + //~^ iter_nth_zero let mut s3 = HashSet::new(); s3.insert(3); let mut iter2 = s3.iter(); let _unwrapped = iter2.next().unwrap(); + //~^ iter_nth_zero } struct Issue9820; diff --git a/tests/ui/iter_nth_zero.rs b/tests/ui/iter_nth_zero.rs index 64229b5128a3..45d008cd7040 100644 --- a/tests/ui/iter_nth_zero.rs +++ b/tests/ui/iter_nth_zero.rs @@ -16,16 +16,19 @@ fn main() { let mut s = HashSet::new(); s.insert(1); let _x = s.iter().nth(0); + //~^ iter_nth_zero let mut s2 = HashSet::new(); s2.insert(2); let mut iter = s2.iter(); let _y = iter.nth(0); + //~^ iter_nth_zero let mut s3 = HashSet::new(); s3.insert(3); let mut iter2 = s3.iter(); let _unwrapped = iter2.nth(0).unwrap(); + //~^ iter_nth_zero } struct Issue9820; diff --git a/tests/ui/iter_nth_zero.stderr b/tests/ui/iter_nth_zero.stderr index b5e5cf45c26b..edd44838b7ec 100644 --- a/tests/ui/iter_nth_zero.stderr +++ b/tests/ui/iter_nth_zero.stderr @@ -8,13 +8,13 @@ LL | let _x = s.iter().nth(0); = help: to override `-D warnings` add `#[allow(clippy::iter_nth_zero)]` error: called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent - --> tests/ui/iter_nth_zero.rs:23:14 + --> tests/ui/iter_nth_zero.rs:24:14 | LL | let _y = iter.nth(0); | ^^^^^^^^^^^ help: try calling `.next()` instead of `.nth(0)`: `iter.next()` error: called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent - --> tests/ui/iter_nth_zero.rs:28:22 + --> tests/ui/iter_nth_zero.rs:30:22 | LL | let _unwrapped = iter2.nth(0).unwrap(); | ^^^^^^^^^^^^ help: try calling `.next()` instead of `.nth(0)`: `iter2.next()` diff --git a/tests/ui/iter_on_empty_collections.fixed b/tests/ui/iter_on_empty_collections.fixed index 0f28b48d9ab8..0c2100034e18 100644 --- a/tests/ui/iter_on_empty_collections.fixed +++ b/tests/ui/iter_on_empty_collections.fixed @@ -3,11 +3,17 @@ fn array() { assert_eq!(std::iter::empty().next(), Option::::None); + //~^ iter_on_empty_collections assert_eq!(std::iter::empty().next(), Option::<&mut i32>::None); + //~^ iter_on_empty_collections assert_eq!(std::iter::empty().next(), Option::<&i32>::None); + //~^ iter_on_empty_collections assert_eq!(std::iter::empty().next(), Option::::None); + //~^ iter_on_empty_collections assert_eq!(std::iter::empty().next(), Option::<&mut i32>::None); + //~^ iter_on_empty_collections assert_eq!(std::iter::empty().next(), Option::<&i32>::None); + //~^ iter_on_empty_collections // Don't trigger on non-iter methods let _: Option = None.clone(); @@ -26,6 +32,7 @@ fn array() { // Don't trigger when the empty collection iter is relied upon for its concrete type // But do trigger if it is just an iterator, despite being an argument to a method for i in smth.as_ref().map_or([].iter(), |s| s.iter()).chain(std::iter::empty()) { + //~^ iter_on_empty_collections println!("{i}"); } diff --git a/tests/ui/iter_on_empty_collections.rs b/tests/ui/iter_on_empty_collections.rs index 702da514df7d..0fb7a32d3691 100644 --- a/tests/ui/iter_on_empty_collections.rs +++ b/tests/ui/iter_on_empty_collections.rs @@ -3,11 +3,17 @@ fn array() { assert_eq!([].into_iter().next(), Option::::None); + //~^ iter_on_empty_collections assert_eq!([].iter_mut().next(), Option::<&mut i32>::None); + //~^ iter_on_empty_collections assert_eq!([].iter().next(), Option::<&i32>::None); + //~^ iter_on_empty_collections assert_eq!(None.into_iter().next(), Option::::None); + //~^ iter_on_empty_collections assert_eq!(None.iter_mut().next(), Option::<&mut i32>::None); + //~^ iter_on_empty_collections assert_eq!(None.iter().next(), Option::<&i32>::None); + //~^ iter_on_empty_collections // Don't trigger on non-iter methods let _: Option = None.clone(); @@ -26,6 +32,7 @@ fn array() { // Don't trigger when the empty collection iter is relied upon for its concrete type // But do trigger if it is just an iterator, despite being an argument to a method for i in smth.as_ref().map_or([].iter(), |s| s.iter()).chain([].iter()) { + //~^ iter_on_empty_collections println!("{i}"); } diff --git a/tests/ui/iter_on_empty_collections.stderr b/tests/ui/iter_on_empty_collections.stderr index da9caa6925bd..2803999cc735 100644 --- a/tests/ui/iter_on_empty_collections.stderr +++ b/tests/ui/iter_on_empty_collections.stderr @@ -8,37 +8,37 @@ LL | assert_eq!([].into_iter().next(), Option::::None); = help: to override `-D warnings` add `#[allow(clippy::iter_on_empty_collections)]` error: `iter_mut` call on an empty collection - --> tests/ui/iter_on_empty_collections.rs:6:16 + --> tests/ui/iter_on_empty_collections.rs:7:16 | LL | assert_eq!([].iter_mut().next(), Option::<&mut i32>::None); | ^^^^^^^^^^^^^ help: try: `std::iter::empty()` error: `iter` call on an empty collection - --> tests/ui/iter_on_empty_collections.rs:7:16 + --> tests/ui/iter_on_empty_collections.rs:9:16 | LL | assert_eq!([].iter().next(), Option::<&i32>::None); | ^^^^^^^^^ help: try: `std::iter::empty()` error: `into_iter` call on an empty collection - --> tests/ui/iter_on_empty_collections.rs:8:16 + --> tests/ui/iter_on_empty_collections.rs:11:16 | LL | assert_eq!(None.into_iter().next(), Option::::None); | ^^^^^^^^^^^^^^^^ help: try: `std::iter::empty()` error: `iter_mut` call on an empty collection - --> tests/ui/iter_on_empty_collections.rs:9:16 + --> tests/ui/iter_on_empty_collections.rs:13:16 | LL | assert_eq!(None.iter_mut().next(), Option::<&mut i32>::None); | ^^^^^^^^^^^^^^^ help: try: `std::iter::empty()` error: `iter` call on an empty collection - --> tests/ui/iter_on_empty_collections.rs:10:16 + --> tests/ui/iter_on_empty_collections.rs:15:16 | LL | assert_eq!(None.iter().next(), Option::<&i32>::None); | ^^^^^^^^^^^ help: try: `std::iter::empty()` error: `iter` call on an empty collection - --> tests/ui/iter_on_empty_collections.rs:28:66 + --> tests/ui/iter_on_empty_collections.rs:34:66 | LL | for i in smth.as_ref().map_or([].iter(), |s| s.iter()).chain([].iter()) { | ^^^^^^^^^ help: try: `std::iter::empty()` diff --git a/tests/ui/iter_on_single_items.fixed b/tests/ui/iter_on_single_items.fixed index 117ec8429c37..b43fad6449c1 100644 --- a/tests/ui/iter_on_single_items.fixed +++ b/tests/ui/iter_on_single_items.fixed @@ -3,11 +3,17 @@ fn array() { assert_eq!(std::iter::once(123).next(), Some(123)); + //~^ iter_on_single_items assert_eq!(std::iter::once(&mut 123).next(), Some(&mut 123)); + //~^ iter_on_single_items assert_eq!(std::iter::once(&123).next(), Some(&123)); + //~^ iter_on_single_items assert_eq!(std::iter::once(123).next(), Some(123)); + //~^ iter_on_single_items assert_eq!(std::iter::once(&mut 123).next(), Some(&mut 123)); + //~^ iter_on_single_items assert_eq!(std::iter::once(&123).next(), Some(&123)); + //~^ iter_on_single_items // Don't trigger on non-iter methods let _: Option = Some("test".to_string()).clone(); diff --git a/tests/ui/iter_on_single_items.rs b/tests/ui/iter_on_single_items.rs index d059370d996c..625c96d3ef1f 100644 --- a/tests/ui/iter_on_single_items.rs +++ b/tests/ui/iter_on_single_items.rs @@ -3,11 +3,17 @@ fn array() { assert_eq!([123].into_iter().next(), Some(123)); + //~^ iter_on_single_items assert_eq!([123].iter_mut().next(), Some(&mut 123)); + //~^ iter_on_single_items assert_eq!([123].iter().next(), Some(&123)); + //~^ iter_on_single_items assert_eq!(Some(123).into_iter().next(), Some(123)); + //~^ iter_on_single_items assert_eq!(Some(123).iter_mut().next(), Some(&mut 123)); + //~^ iter_on_single_items assert_eq!(Some(123).iter().next(), Some(&123)); + //~^ iter_on_single_items // Don't trigger on non-iter methods let _: Option = Some("test".to_string()).clone(); diff --git a/tests/ui/iter_on_single_items.stderr b/tests/ui/iter_on_single_items.stderr index 0252c859581b..536e9eb36d88 100644 --- a/tests/ui/iter_on_single_items.stderr +++ b/tests/ui/iter_on_single_items.stderr @@ -8,31 +8,31 @@ LL | assert_eq!([123].into_iter().next(), Some(123)); = help: to override `-D warnings` add `#[allow(clippy::iter_on_single_items)]` error: `iter_mut` call on a collection with only one item - --> tests/ui/iter_on_single_items.rs:6:16 + --> tests/ui/iter_on_single_items.rs:7:16 | LL | assert_eq!([123].iter_mut().next(), Some(&mut 123)); | ^^^^^^^^^^^^^^^^ help: try: `std::iter::once(&mut 123)` error: `iter` call on a collection with only one item - --> tests/ui/iter_on_single_items.rs:7:16 + --> tests/ui/iter_on_single_items.rs:9:16 | LL | assert_eq!([123].iter().next(), Some(&123)); | ^^^^^^^^^^^^ help: try: `std::iter::once(&123)` error: `into_iter` call on a collection with only one item - --> tests/ui/iter_on_single_items.rs:8:16 + --> tests/ui/iter_on_single_items.rs:11:16 | LL | assert_eq!(Some(123).into_iter().next(), Some(123)); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `std::iter::once(123)` error: `iter_mut` call on a collection with only one item - --> tests/ui/iter_on_single_items.rs:9:16 + --> tests/ui/iter_on_single_items.rs:13:16 | LL | assert_eq!(Some(123).iter_mut().next(), Some(&mut 123)); | ^^^^^^^^^^^^^^^^^^^^ help: try: `std::iter::once(&mut 123)` error: `iter` call on a collection with only one item - --> tests/ui/iter_on_single_items.rs:10:16 + --> tests/ui/iter_on_single_items.rs:15:16 | LL | assert_eq!(Some(123).iter().next(), Some(&123)); | ^^^^^^^^^^^^^^^^ help: try: `std::iter::once(&123)` diff --git a/tests/ui/iter_out_of_bounds.rs b/tests/ui/iter_out_of_bounds.rs index 3cfe6e82fc1e..b34e4ad78240 100644 --- a/tests/ui/iter_out_of_bounds.rs +++ b/tests/ui/iter_out_of_bounds.rs @@ -10,57 +10,60 @@ fn opaque_empty_iter() -> impl Iterator { fn main() { #[allow(clippy::never_loop)] for _ in [1, 2, 3].iter().skip(4) { - //~^ ERROR: this `.skip()` call skips more items than the iterator will produce + //~^ iter_out_of_bounds + unreachable!(); } for (i, _) in [1, 2, 3].iter().take(4).enumerate() { - //~^ ERROR: this `.take()` call takes more items than the iterator will produce + //~^ iter_out_of_bounds + assert!(i <= 2); } #[allow(clippy::needless_borrow)] for _ in (&&&&&&[1, 2, 3]).iter().take(4) {} - //~^ ERROR: this `.take()` call takes more items than the iterator will produce + //~^ iter_out_of_bounds for _ in [1, 2, 3].iter().skip(4) {} - //~^ ERROR: this `.skip()` call skips more items than the iterator will produce + //~^ iter_out_of_bounds for _ in [1; 3].iter().skip(4) {} - //~^ ERROR: this `.skip()` call skips more items than the iterator will produce + //~^ iter_out_of_bounds // Should not lint for _ in opaque_empty_iter().skip(1) {} for _ in vec![1, 2, 3].iter().skip(4) {} - //~^ ERROR: this `.skip()` call skips more items than the iterator will produce + //~^ iter_out_of_bounds for _ in vec![1; 3].iter().skip(4) {} - //~^ ERROR: this `.skip()` call skips more items than the iterator will produce + //~^ iter_out_of_bounds let x = [1, 2, 3]; for _ in x.iter().skip(4) {} - //~^ ERROR: this `.skip()` call skips more items than the iterator will produce + //~^ iter_out_of_bounds let n = 4; for _ in x.iter().skip(n) {} - //~^ ERROR: this `.skip()` call skips more items than the iterator will produce + //~^ iter_out_of_bounds let empty = std::iter::empty::; for _ in empty().skip(1) {} - //~^ ERROR: this `.skip()` call skips more items than the iterator will produce + //~^ iter_out_of_bounds for _ in empty().take(1) {} - //~^ ERROR: this `.take()` call takes more items than the iterator will produce + //~^ iter_out_of_bounds for _ in std::iter::once(1).skip(2) {} - //~^ ERROR: this `.skip()` call skips more items than the iterator will produce + //~^ iter_out_of_bounds for _ in std::iter::once(1).take(2) {} - //~^ ERROR: this `.take()` call takes more items than the iterator will produce + //~^ iter_out_of_bounds for x in [].iter().take(1) { - //~^ ERROR: this `.take()` call takes more items than the iterator will produce + //~^ iter_out_of_bounds + let _: &i32 = x; } diff --git a/tests/ui/iter_out_of_bounds.stderr b/tests/ui/iter_out_of_bounds.stderr index 96df04251fc9..19ac60b9d0ac 100644 --- a/tests/ui/iter_out_of_bounds.stderr +++ b/tests/ui/iter_out_of_bounds.stderr @@ -12,7 +12,7 @@ LL | #![deny(clippy::iter_out_of_bounds)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this `.take()` call takes more items than the iterator will produce - --> tests/ui/iter_out_of_bounds.rs:16:19 + --> tests/ui/iter_out_of_bounds.rs:17:19 | LL | for (i, _) in [1, 2, 3].iter().take(4).enumerate() { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -20,7 +20,7 @@ LL | for (i, _) in [1, 2, 3].iter().take(4).enumerate() { = note: this operation is useless and the returned iterator will simply yield the same items error: this `.take()` call takes more items than the iterator will produce - --> tests/ui/iter_out_of_bounds.rs:22:14 + --> tests/ui/iter_out_of_bounds.rs:24:14 | LL | for _ in (&&&&&&[1, 2, 3]).iter().take(4) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | for _ in (&&&&&&[1, 2, 3]).iter().take(4) {} = note: this operation is useless and the returned iterator will simply yield the same items error: this `.skip()` call skips more items than the iterator will produce - --> tests/ui/iter_out_of_bounds.rs:25:14 + --> tests/ui/iter_out_of_bounds.rs:27:14 | LL | for _ in [1, 2, 3].iter().skip(4) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +36,7 @@ LL | for _ in [1, 2, 3].iter().skip(4) {} = note: this operation is useless and will create an empty iterator error: this `.skip()` call skips more items than the iterator will produce - --> tests/ui/iter_out_of_bounds.rs:28:14 + --> tests/ui/iter_out_of_bounds.rs:30:14 | LL | for _ in [1; 3].iter().skip(4) {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | for _ in [1; 3].iter().skip(4) {} = note: this operation is useless and will create an empty iterator error: this `.skip()` call skips more items than the iterator will produce - --> tests/ui/iter_out_of_bounds.rs:34:14 + --> tests/ui/iter_out_of_bounds.rs:36:14 | LL | for _ in vec![1, 2, 3].iter().skip(4) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,7 +52,7 @@ LL | for _ in vec![1, 2, 3].iter().skip(4) {} = note: this operation is useless and will create an empty iterator error: this `.skip()` call skips more items than the iterator will produce - --> tests/ui/iter_out_of_bounds.rs:37:14 + --> tests/ui/iter_out_of_bounds.rs:39:14 | LL | for _ in vec![1; 3].iter().skip(4) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL | for _ in vec![1; 3].iter().skip(4) {} = note: this operation is useless and will create an empty iterator error: this `.skip()` call skips more items than the iterator will produce - --> tests/ui/iter_out_of_bounds.rs:41:14 + --> tests/ui/iter_out_of_bounds.rs:43:14 | LL | for _ in x.iter().skip(4) {} | ^^^^^^^^^^^^^^^^ @@ -68,7 +68,7 @@ LL | for _ in x.iter().skip(4) {} = note: this operation is useless and will create an empty iterator error: this `.skip()` call skips more items than the iterator will produce - --> tests/ui/iter_out_of_bounds.rs:45:14 + --> tests/ui/iter_out_of_bounds.rs:47:14 | LL | for _ in x.iter().skip(n) {} | ^^^^^^^^^^^^^^^^ @@ -76,7 +76,7 @@ LL | for _ in x.iter().skip(n) {} = note: this operation is useless and will create an empty iterator error: this `.skip()` call skips more items than the iterator will produce - --> tests/ui/iter_out_of_bounds.rs:50:14 + --> tests/ui/iter_out_of_bounds.rs:52:14 | LL | for _ in empty().skip(1) {} | ^^^^^^^^^^^^^^^ @@ -84,7 +84,7 @@ LL | for _ in empty().skip(1) {} = note: this operation is useless and will create an empty iterator error: this `.take()` call takes more items than the iterator will produce - --> tests/ui/iter_out_of_bounds.rs:53:14 + --> tests/ui/iter_out_of_bounds.rs:55:14 | LL | for _ in empty().take(1) {} | ^^^^^^^^^^^^^^^ @@ -92,7 +92,7 @@ LL | for _ in empty().take(1) {} = note: this operation is useless and the returned iterator will simply yield the same items error: this `.skip()` call skips more items than the iterator will produce - --> tests/ui/iter_out_of_bounds.rs:56:14 + --> tests/ui/iter_out_of_bounds.rs:58:14 | LL | for _ in std::iter::once(1).skip(2) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -100,7 +100,7 @@ LL | for _ in std::iter::once(1).skip(2) {} = note: this operation is useless and will create an empty iterator error: this `.take()` call takes more items than the iterator will produce - --> tests/ui/iter_out_of_bounds.rs:59:14 + --> tests/ui/iter_out_of_bounds.rs:61:14 | LL | for _ in std::iter::once(1).take(2) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -108,7 +108,7 @@ LL | for _ in std::iter::once(1).take(2) {} = note: this operation is useless and the returned iterator will simply yield the same items error: this `.take()` call takes more items than the iterator will produce - --> tests/ui/iter_out_of_bounds.rs:62:14 + --> tests/ui/iter_out_of_bounds.rs:64:14 | LL | for x in [].iter().take(1) { | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/iter_over_hash_type.rs b/tests/ui/iter_over_hash_type.rs index 65bae1df4218..914cc9df0de9 100644 --- a/tests/ui/iter_over_hash_type.rs +++ b/tests/ui/iter_over_hash_type.rs @@ -16,46 +16,59 @@ fn main() { // test hashset for x in &hash_set { + //~^ iter_over_hash_type let _ = x; } for x in hash_set.iter() { + //~^ iter_over_hash_type let _ = x; } for x in hash_set.clone() { + //~^ iter_over_hash_type let _ = x; } for x in hash_set.drain() { + //~^ iter_over_hash_type let _ = x; } // test hashmap for (x, y) in &hash_map { + //~^ iter_over_hash_type let _ = (x, y); } for x in hash_map.keys() { + //~^ iter_over_hash_type let _ = x; } for x in hash_map.values() { + //~^ iter_over_hash_type let _ = x; } for x in hash_map.values_mut() { + //~^ iter_over_hash_type *x += 1; } for x in hash_map.iter() { + //~^ iter_over_hash_type let _ = x; } for x in hash_map.clone() { + //~^ iter_over_hash_type let _ = x; } for x in hash_map.drain() { + //~^ iter_over_hash_type let _ = x; } // test type-aliased hashers for x in fx_hash_set { + //~^ iter_over_hash_type let _ = x; } for x in fx_hash_map { + //~^ iter_over_hash_type let _ = x; } diff --git a/tests/ui/iter_over_hash_type.stderr b/tests/ui/iter_over_hash_type.stderr index 6afe69ee20e1..1bc6f4588d44 100644 --- a/tests/ui/iter_over_hash_type.stderr +++ b/tests/ui/iter_over_hash_type.stderr @@ -2,6 +2,7 @@ error: iteration over unordered hash-based type --> tests/ui/iter_over_hash_type.rs:18:5 | LL | / for x in &hash_set { +LL | | LL | | let _ = x; LL | | } | |_____^ @@ -10,97 +11,109 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::iter_over_hash_type)]` error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:21:5 + --> tests/ui/iter_over_hash_type.rs:22:5 | LL | / for x in hash_set.iter() { +LL | | LL | | let _ = x; LL | | } | |_____^ error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:24:5 + --> tests/ui/iter_over_hash_type.rs:26:5 | LL | / for x in hash_set.clone() { +LL | | LL | | let _ = x; LL | | } | |_____^ error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:27:5 + --> tests/ui/iter_over_hash_type.rs:30:5 | LL | / for x in hash_set.drain() { +LL | | LL | | let _ = x; LL | | } | |_____^ error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:32:5 + --> tests/ui/iter_over_hash_type.rs:36:5 | LL | / for (x, y) in &hash_map { +LL | | LL | | let _ = (x, y); LL | | } | |_____^ error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:35:5 + --> tests/ui/iter_over_hash_type.rs:40:5 | LL | / for x in hash_map.keys() { +LL | | LL | | let _ = x; LL | | } | |_____^ -error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:38:5 - | -LL | / for x in hash_map.values() { -LL | | let _ = x; -LL | | } - | |_____^ - -error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:41:5 - | -LL | / for x in hash_map.values_mut() { -LL | | *x += 1; -LL | | } - | |_____^ - error: iteration over unordered hash-based type --> tests/ui/iter_over_hash_type.rs:44:5 | -LL | / for x in hash_map.iter() { +LL | / for x in hash_map.values() { +LL | | LL | | let _ = x; LL | | } | |_____^ error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:47:5 + --> tests/ui/iter_over_hash_type.rs:48:5 + | +LL | / for x in hash_map.values_mut() { +LL | | +LL | | *x += 1; +LL | | } + | |_____^ + +error: iteration over unordered hash-based type + --> tests/ui/iter_over_hash_type.rs:52:5 + | +LL | / for x in hash_map.iter() { +LL | | +LL | | let _ = x; +LL | | } + | |_____^ + +error: iteration over unordered hash-based type + --> tests/ui/iter_over_hash_type.rs:56:5 | LL | / for x in hash_map.clone() { +LL | | LL | | let _ = x; LL | | } | |_____^ error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:50:5 + --> tests/ui/iter_over_hash_type.rs:60:5 | LL | / for x in hash_map.drain() { +LL | | LL | | let _ = x; LL | | } | |_____^ error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:55:5 + --> tests/ui/iter_over_hash_type.rs:66:5 | LL | / for x in fx_hash_set { +LL | | LL | | let _ = x; LL | | } | |_____^ error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:58:5 + --> tests/ui/iter_over_hash_type.rs:70:5 | LL | / for x in fx_hash_map { +LL | | LL | | let _ = x; LL | | } | |_____^ diff --git a/tests/ui/iter_overeager_cloned.fixed b/tests/ui/iter_overeager_cloned.fixed index d7d3d299349e..999912690290 100644 --- a/tests/ui/iter_overeager_cloned.fixed +++ b/tests/ui/iter_overeager_cloned.fixed @@ -10,36 +10,49 @@ fn main() { let vec = vec!["1".to_string(), "2".to_string(), "3".to_string()]; let _: Option = vec.iter().last().cloned(); + //~^ iter_overeager_cloned let _: Option = vec.iter().chain(vec.iter()).next().cloned(); + //~^ iter_overeager_cloned let _: usize = vec.iter().filter(|x| x == &"2").count(); + //~^ redundant_clone let _: Vec<_> = vec.iter().take(2).cloned().collect(); + //~^ iter_overeager_cloned let _: Vec<_> = vec.iter().skip(2).cloned().collect(); + //~^ iter_overeager_cloned let _ = vec.iter().filter(|x| x == &"2").nth(2).cloned(); + //~^ iter_overeager_cloned let _ = [Some(Some("str".to_string())), Some(Some("str".to_string()))] + //~^ iter_overeager_cloned .iter() .flatten().cloned(); let _ = vec.iter().filter(|&x| x.starts_with('2')).cloned(); + //~^ iter_overeager_cloned let _ = vec.iter().find(|&x| x == "2").cloned(); + //~^ iter_overeager_cloned { let f = |x: &String| x.starts_with('2'); let _ = vec.iter().filter(|&x| f(x)).cloned(); + //~^ iter_overeager_cloned let _ = vec.iter().find(|&x| f(x)).cloned(); + //~^ iter_overeager_cloned } { let vec: Vec<(String, String)> = vec![]; let f = move |x: &(String, String)| x.0.starts_with('2'); let _ = vec.iter().filter(|&x| f(x)).cloned(); + //~^ iter_overeager_cloned let _ = vec.iter().find(|&x| f(x)).cloned(); + //~^ iter_overeager_cloned } fn test_move<'a>( @@ -47,6 +60,7 @@ fn main() { target: String, ) -> impl Iterator + 'a { iter.filter(move |&(&a, b)| a == 1 && b == &target).cloned() + //~^ iter_overeager_cloned } { @@ -58,19 +72,24 @@ fn main() { fn bar<'a>(iter: impl Iterator> + 'a, target: String) -> impl Iterator> + 'a { iter.filter(move |&S { a, b }| **a == 1 && b == &target).cloned() + //~^ iter_overeager_cloned } } let _ = vec.iter().map(|x| x.len()); + //~^ redundant_clone // This would fail if changed. let _ = vec.iter().cloned().map(|x| x + "2"); let _ = vec.iter().for_each(|x| assert!(!x.is_empty())); + //~^ redundant_clone let _ = vec.iter().all(|x| x.len() == 1); + //~^ redundant_clone let _ = vec.iter().any(|x| x.len() == 1); + //~^ redundant_clone // Should probably stay as it is. let _ = [0, 1, 2, 3, 4].iter().cloned().take(10); diff --git a/tests/ui/iter_overeager_cloned.rs b/tests/ui/iter_overeager_cloned.rs index 45e1349febd0..6a860dad5afd 100644 --- a/tests/ui/iter_overeager_cloned.rs +++ b/tests/ui/iter_overeager_cloned.rs @@ -10,37 +10,50 @@ fn main() { let vec = vec!["1".to_string(), "2".to_string(), "3".to_string()]; let _: Option = vec.iter().cloned().last(); + //~^ iter_overeager_cloned let _: Option = vec.iter().chain(vec.iter()).cloned().next(); + //~^ iter_overeager_cloned let _: usize = vec.iter().filter(|x| x == &"2").cloned().count(); + //~^ redundant_clone let _: Vec<_> = vec.iter().cloned().take(2).collect(); + //~^ iter_overeager_cloned let _: Vec<_> = vec.iter().cloned().skip(2).collect(); + //~^ iter_overeager_cloned let _ = vec.iter().filter(|x| x == &"2").cloned().nth(2); + //~^ iter_overeager_cloned let _ = [Some(Some("str".to_string())), Some(Some("str".to_string()))] + //~^ iter_overeager_cloned .iter() .cloned() .flatten(); let _ = vec.iter().cloned().filter(|x| x.starts_with('2')); + //~^ iter_overeager_cloned let _ = vec.iter().cloned().find(|x| x == "2"); + //~^ iter_overeager_cloned { let f = |x: &String| x.starts_with('2'); let _ = vec.iter().cloned().filter(f); + //~^ iter_overeager_cloned let _ = vec.iter().cloned().find(f); + //~^ iter_overeager_cloned } { let vec: Vec<(String, String)> = vec![]; let f = move |x: &(String, String)| x.0.starts_with('2'); let _ = vec.iter().cloned().filter(f); + //~^ iter_overeager_cloned let _ = vec.iter().cloned().find(f); + //~^ iter_overeager_cloned } fn test_move<'a>( @@ -48,6 +61,7 @@ fn main() { target: String, ) -> impl Iterator + 'a { iter.cloned().filter(move |(&a, b)| a == 1 && b == &target) + //~^ iter_overeager_cloned } { @@ -59,19 +73,24 @@ fn main() { fn bar<'a>(iter: impl Iterator> + 'a, target: String) -> impl Iterator> + 'a { iter.cloned().filter(move |S { a, b }| **a == 1 && b == &target) + //~^ iter_overeager_cloned } } let _ = vec.iter().cloned().map(|x| x.len()); + //~^ redundant_clone // This would fail if changed. let _ = vec.iter().cloned().map(|x| x + "2"); let _ = vec.iter().cloned().for_each(|x| assert!(!x.is_empty())); + //~^ redundant_clone let _ = vec.iter().cloned().all(|x| x.len() == 1); + //~^ redundant_clone let _ = vec.iter().cloned().any(|x| x.len() == 1); + //~^ redundant_clone // Should probably stay as it is. let _ = [0, 1, 2, 3, 4].iter().cloned().take(10); diff --git a/tests/ui/iter_overeager_cloned.stderr b/tests/ui/iter_overeager_cloned.stderr index e6680266f107..f3239b59582e 100644 --- a/tests/ui/iter_overeager_cloned.stderr +++ b/tests/ui/iter_overeager_cloned.stderr @@ -10,7 +10,7 @@ LL | let _: Option = vec.iter().cloned().last(); = help: to override `-D warnings` add `#[allow(clippy::iter_overeager_cloned)]` error: unnecessarily eager cloning of iterator items - --> tests/ui/iter_overeager_cloned.rs:14:29 + --> tests/ui/iter_overeager_cloned.rs:15:29 | LL | let _: Option = vec.iter().chain(vec.iter()).cloned().next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------- @@ -18,7 +18,7 @@ LL | let _: Option = vec.iter().chain(vec.iter()).cloned().next(); | help: try: `.next().cloned()` error: unneeded cloning of iterator items - --> tests/ui/iter_overeager_cloned.rs:16:20 + --> tests/ui/iter_overeager_cloned.rs:18:20 | LL | let _: usize = vec.iter().filter(|x| x == &"2").cloned().count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------- @@ -29,7 +29,7 @@ LL | let _: usize = vec.iter().filter(|x| x == &"2").cloned().count(); = help: to override `-D warnings` add `#[allow(clippy::redundant_clone)]` error: unnecessarily eager cloning of iterator items - --> tests/ui/iter_overeager_cloned.rs:18:21 + --> tests/ui/iter_overeager_cloned.rs:21:21 | LL | let _: Vec<_> = vec.iter().cloned().take(2).collect(); | ^^^^^^^^^^----------------- @@ -37,7 +37,7 @@ LL | let _: Vec<_> = vec.iter().cloned().take(2).collect(); | help: try: `.take(2).cloned()` error: unnecessarily eager cloning of iterator items - --> tests/ui/iter_overeager_cloned.rs:20:21 + --> tests/ui/iter_overeager_cloned.rs:24:21 | LL | let _: Vec<_> = vec.iter().cloned().skip(2).collect(); | ^^^^^^^^^^----------------- @@ -45,7 +45,7 @@ LL | let _: Vec<_> = vec.iter().cloned().skip(2).collect(); | help: try: `.skip(2).cloned()` error: unnecessarily eager cloning of iterator items - --> tests/ui/iter_overeager_cloned.rs:22:13 + --> tests/ui/iter_overeager_cloned.rs:27:13 | LL | let _ = vec.iter().filter(|x| x == &"2").cloned().nth(2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------- @@ -53,10 +53,11 @@ LL | let _ = vec.iter().filter(|x| x == &"2").cloned().nth(2); | help: try: `.nth(2).cloned()` error: unnecessarily eager cloning of iterator items - --> tests/ui/iter_overeager_cloned.rs:24:13 + --> tests/ui/iter_overeager_cloned.rs:30:13 | LL | let _ = [Some(Some("str".to_string())), Some(Some("str".to_string()))] | _____________^ +LL | | LL | | .iter() LL | | .cloned() LL | | .flatten(); @@ -69,7 +70,7 @@ LL ~ .flatten().cloned(); | error: unnecessarily eager cloning of iterator items - --> tests/ui/iter_overeager_cloned.rs:29:13 + --> tests/ui/iter_overeager_cloned.rs:36:13 | LL | let _ = vec.iter().cloned().filter(|x| x.starts_with('2')); | ^^^^^^^^^^---------------------------------------- @@ -77,7 +78,7 @@ LL | let _ = vec.iter().cloned().filter(|x| x.starts_with('2')); | help: try: `.filter(|&x| x.starts_with('2')).cloned()` error: unnecessarily eager cloning of iterator items - --> tests/ui/iter_overeager_cloned.rs:31:13 + --> tests/ui/iter_overeager_cloned.rs:39:13 | LL | let _ = vec.iter().cloned().find(|x| x == "2"); | ^^^^^^^^^^---------------------------- @@ -85,7 +86,7 @@ LL | let _ = vec.iter().cloned().find(|x| x == "2"); | help: try: `.find(|&x| x == "2").cloned()` error: unnecessarily eager cloning of iterator items - --> tests/ui/iter_overeager_cloned.rs:35:17 + --> tests/ui/iter_overeager_cloned.rs:44:17 | LL | let _ = vec.iter().cloned().filter(f); | ^^^^^^^^^^------------------- @@ -93,7 +94,7 @@ LL | let _ = vec.iter().cloned().filter(f); | help: try: `.filter(|&x| f(x)).cloned()` error: unnecessarily eager cloning of iterator items - --> tests/ui/iter_overeager_cloned.rs:36:17 + --> tests/ui/iter_overeager_cloned.rs:46:17 | LL | let _ = vec.iter().cloned().find(f); | ^^^^^^^^^^----------------- @@ -101,7 +102,7 @@ LL | let _ = vec.iter().cloned().find(f); | help: try: `.find(|&x| f(x)).cloned()` error: unnecessarily eager cloning of iterator items - --> tests/ui/iter_overeager_cloned.rs:42:17 + --> tests/ui/iter_overeager_cloned.rs:53:17 | LL | let _ = vec.iter().cloned().filter(f); | ^^^^^^^^^^------------------- @@ -109,7 +110,7 @@ LL | let _ = vec.iter().cloned().filter(f); | help: try: `.filter(|&x| f(x)).cloned()` error: unnecessarily eager cloning of iterator items - --> tests/ui/iter_overeager_cloned.rs:43:17 + --> tests/ui/iter_overeager_cloned.rs:55:17 | LL | let _ = vec.iter().cloned().find(f); | ^^^^^^^^^^----------------- @@ -117,7 +118,7 @@ LL | let _ = vec.iter().cloned().find(f); | help: try: `.find(|&x| f(x)).cloned()` error: unnecessarily eager cloning of iterator items - --> tests/ui/iter_overeager_cloned.rs:50:9 + --> tests/ui/iter_overeager_cloned.rs:63:9 | LL | iter.cloned().filter(move |(&a, b)| a == 1 && b == &target) | ^^^^------------------------------------------------------- @@ -125,7 +126,7 @@ LL | iter.cloned().filter(move |(&a, b)| a == 1 && b == &target) | help: try: `.filter(move |&(&a, b)| a == 1 && b == &target).cloned()` error: unnecessarily eager cloning of iterator items - --> tests/ui/iter_overeager_cloned.rs:61:13 + --> tests/ui/iter_overeager_cloned.rs:75:13 | LL | iter.cloned().filter(move |S { a, b }| **a == 1 && b == &target) | ^^^^------------------------------------------------------------ @@ -133,7 +134,7 @@ LL | iter.cloned().filter(move |S { a, b }| **a == 1 && b == &target | help: try: `.filter(move |&S { a, b }| **a == 1 && b == &target).cloned()` error: unneeded cloning of iterator items - --> tests/ui/iter_overeager_cloned.rs:65:13 + --> tests/ui/iter_overeager_cloned.rs:80:13 | LL | let _ = vec.iter().cloned().map(|x| x.len()); | ^^^^^^^^^^-------------------------- @@ -141,7 +142,7 @@ LL | let _ = vec.iter().cloned().map(|x| x.len()); | help: try: `.map(|x| x.len())` error: unneeded cloning of iterator items - --> tests/ui/iter_overeager_cloned.rs:70:13 + --> tests/ui/iter_overeager_cloned.rs:86:13 | LL | let _ = vec.iter().cloned().for_each(|x| assert!(!x.is_empty())); | ^^^^^^^^^^---------------------------------------------- @@ -149,7 +150,7 @@ LL | let _ = vec.iter().cloned().for_each(|x| assert!(!x.is_empty())); | help: try: `.for_each(|x| assert!(!x.is_empty()))` error: unneeded cloning of iterator items - --> tests/ui/iter_overeager_cloned.rs:72:13 + --> tests/ui/iter_overeager_cloned.rs:89:13 | LL | let _ = vec.iter().cloned().all(|x| x.len() == 1); | ^^^^^^^^^^------------------------------- @@ -157,7 +158,7 @@ LL | let _ = vec.iter().cloned().all(|x| x.len() == 1); | help: try: `.all(|x| x.len() == 1)` error: unneeded cloning of iterator items - --> tests/ui/iter_overeager_cloned.rs:74:13 + --> tests/ui/iter_overeager_cloned.rs:92:13 | LL | let _ = vec.iter().cloned().any(|x| x.len() == 1); | ^^^^^^^^^^------------------------------- diff --git a/tests/ui/iter_skip_next.fixed b/tests/ui/iter_skip_next.fixed index 3e41b3632490..1d6a07f2d828 100644 --- a/tests/ui/iter_skip_next.fixed +++ b/tests/ui/iter_skip_next.fixed @@ -15,9 +15,13 @@ use option_helpers::IteratorFalsePositives; fn main() { let some_vec = vec![0, 1, 2, 3]; let _ = some_vec.iter().nth(42); + //~^ iter_skip_next let _ = some_vec.iter().cycle().nth(42); + //~^ iter_skip_next let _ = (1..10).nth(10); + //~^ iter_skip_next let _ = &some_vec[..].iter().nth(3); + //~^ iter_skip_next let foo = IteratorFalsePositives { foo: 0 }; let _ = foo.skip(42).next(); let _ = foo.filter().skip(42).next(); @@ -26,13 +30,16 @@ fn main() { let test_string = "1|1 2"; let mut sp = test_string.split('|').map(|s| s.trim()); let _: Vec<&str> = sp.nth(1).unwrap().split(' ').collect(); + //~^ iter_skip_next if let Some(mut s) = Some(test_string.split('|').map(|s| s.trim())) { let _: Vec<&str> = s.nth(1).unwrap().split(' ').collect(); + //~^ iter_skip_next }; fn check(mut s: T) where T: Iterator, { let _: Vec<&str> = s.nth(1).unwrap().split(' ').collect(); + //~^ iter_skip_next } } diff --git a/tests/ui/iter_skip_next.rs b/tests/ui/iter_skip_next.rs index 6d96441ca96f..7570e17a0925 100644 --- a/tests/ui/iter_skip_next.rs +++ b/tests/ui/iter_skip_next.rs @@ -15,9 +15,13 @@ use option_helpers::IteratorFalsePositives; fn main() { let some_vec = vec![0, 1, 2, 3]; let _ = some_vec.iter().skip(42).next(); + //~^ iter_skip_next let _ = some_vec.iter().cycle().skip(42).next(); + //~^ iter_skip_next let _ = (1..10).skip(10).next(); + //~^ iter_skip_next let _ = &some_vec[..].iter().skip(3).next(); + //~^ iter_skip_next let foo = IteratorFalsePositives { foo: 0 }; let _ = foo.skip(42).next(); let _ = foo.filter().skip(42).next(); @@ -26,13 +30,16 @@ fn main() { let test_string = "1|1 2"; let mut sp = test_string.split('|').map(|s| s.trim()); let _: Vec<&str> = sp.skip(1).next().unwrap().split(' ').collect(); + //~^ iter_skip_next if let Some(mut s) = Some(test_string.split('|').map(|s| s.trim())) { let _: Vec<&str> = s.skip(1).next().unwrap().split(' ').collect(); + //~^ iter_skip_next }; fn check(mut s: T) where T: Iterator, { let _: Vec<&str> = s.skip(1).next().unwrap().split(' ').collect(); + //~^ iter_skip_next } } diff --git a/tests/ui/iter_skip_next.stderr b/tests/ui/iter_skip_next.stderr index 0fa04465ff15..9f6d708c2f41 100644 --- a/tests/ui/iter_skip_next.stderr +++ b/tests/ui/iter_skip_next.stderr @@ -8,37 +8,37 @@ LL | let _ = some_vec.iter().skip(42).next(); = help: to override `-D warnings` add `#[allow(clippy::iter_skip_next)]` error: called `skip(..).next()` on an iterator - --> tests/ui/iter_skip_next.rs:18:36 + --> tests/ui/iter_skip_next.rs:19:36 | LL | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(42)` error: called `skip(..).next()` on an iterator - --> tests/ui/iter_skip_next.rs:19:20 + --> tests/ui/iter_skip_next.rs:21:20 | LL | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(10)` error: called `skip(..).next()` on an iterator - --> tests/ui/iter_skip_next.rs:20:33 + --> tests/ui/iter_skip_next.rs:23:33 | LL | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(3)` error: called `skip(..).next()` on an iterator - --> tests/ui/iter_skip_next.rs:28:26 + --> tests/ui/iter_skip_next.rs:32:26 | LL | let _: Vec<&str> = sp.skip(1).next().unwrap().split(' ').collect(); | ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(1)` error: called `skip(..).next()` on an iterator - --> tests/ui/iter_skip_next.rs:30:29 + --> tests/ui/iter_skip_next.rs:35:29 | LL | let _: Vec<&str> = s.skip(1).next().unwrap().split(' ').collect(); | ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(1)` error: called `skip(..).next()` on an iterator - --> tests/ui/iter_skip_next.rs:36:29 + --> tests/ui/iter_skip_next.rs:42:29 | LL | let _: Vec<&str> = s.skip(1).next().unwrap().split(' ').collect(); | ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(1)` diff --git a/tests/ui/iter_skip_next_unfixable.rs b/tests/ui/iter_skip_next_unfixable.rs index 6c98bdc8c880..3f855b54d12a 100644 --- a/tests/ui/iter_skip_next_unfixable.rs +++ b/tests/ui/iter_skip_next_unfixable.rs @@ -7,16 +7,17 @@ fn main() { let test_string = "1|1 2"; let sp = test_string.split('|').map(|s| s.trim()); let _: Vec<&str> = sp.skip(1).next().unwrap().split(' ').collect(); - //~^ ERROR: called `skip(..).next()` on an iterator + //~^ iter_skip_next + if let Some(s) = Some(test_string.split('|').map(|s| s.trim())) { let _: Vec<&str> = s.skip(1).next().unwrap().split(' ').collect(); - //~^ ERROR: called `skip(..).next()` on an iterator + //~^ iter_skip_next }; fn check(s: T) where T: Iterator, { let _: Vec<&str> = s.skip(1).next().unwrap().split(' ').collect(); - //~^ ERROR: called `skip(..).next()` on an iterator + //~^ iter_skip_next } } diff --git a/tests/ui/iter_skip_next_unfixable.stderr b/tests/ui/iter_skip_next_unfixable.stderr index 9bfffb07ca62..44c5c1f85442 100644 --- a/tests/ui/iter_skip_next_unfixable.stderr +++ b/tests/ui/iter_skip_next_unfixable.stderr @@ -13,25 +13,25 @@ LL | let sp = test_string.split('|').map(|s| s.trim()); = help: to override `-D warnings` add `#[allow(clippy::iter_skip_next)]` error: called `skip(..).next()` on an iterator - --> tests/ui/iter_skip_next_unfixable.rs:12:29 + --> tests/ui/iter_skip_next_unfixable.rs:13:29 | LL | let _: Vec<&str> = s.skip(1).next().unwrap().split(' ').collect(); | ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(1)` | help: for this change `s` has to be mutable - --> tests/ui/iter_skip_next_unfixable.rs:11:17 + --> tests/ui/iter_skip_next_unfixable.rs:12:17 | LL | if let Some(s) = Some(test_string.split('|').map(|s| s.trim())) { | ^ error: called `skip(..).next()` on an iterator - --> tests/ui/iter_skip_next_unfixable.rs:19:29 + --> tests/ui/iter_skip_next_unfixable.rs:20:29 | LL | let _: Vec<&str> = s.skip(1).next().unwrap().split(' ').collect(); | ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(1)` | help: for this change `s` has to be mutable - --> tests/ui/iter_skip_next_unfixable.rs:15:17 + --> tests/ui/iter_skip_next_unfixable.rs:16:17 | LL | fn check(s: T) | ^ diff --git a/tests/ui/iter_skip_zero.fixed b/tests/ui/iter_skip_zero.fixed index 447d07100e95..498af9bb4ff6 100644 --- a/tests/ui/iter_skip_zero.fixed +++ b/tests/ui/iter_skip_zero.fixed @@ -9,9 +9,14 @@ use std::iter::once; fn main() { let _ = [1, 2, 3].iter().skip(1); + //~^ iter_skip_zero let _ = vec![1, 2, 3].iter().skip(1); + //~^ iter_skip_zero let _ = once([1, 2, 3]).skip(1); + //~^ iter_skip_zero let _ = vec![1, 2, 3].iter().chain([1, 2, 3].iter().skip(1)).skip(1); + //~^ iter_skip_zero + //~| iter_skip_zero // Don't lint let _ = [1, 2, 3].iter().skip(1); let _ = vec![1, 2, 3].iter().skip(1); diff --git a/tests/ui/iter_skip_zero.rs b/tests/ui/iter_skip_zero.rs index ba63c3981808..f168e9109953 100644 --- a/tests/ui/iter_skip_zero.rs +++ b/tests/ui/iter_skip_zero.rs @@ -9,9 +9,14 @@ use std::iter::once; fn main() { let _ = [1, 2, 3].iter().skip(0); + //~^ iter_skip_zero let _ = vec![1, 2, 3].iter().skip(0); + //~^ iter_skip_zero let _ = once([1, 2, 3]).skip(0); + //~^ iter_skip_zero let _ = vec![1, 2, 3].iter().chain([1, 2, 3].iter().skip(0)).skip(0); + //~^ iter_skip_zero + //~| iter_skip_zero // Don't lint let _ = [1, 2, 3].iter().skip(1); let _ = vec![1, 2, 3].iter().skip(1); diff --git a/tests/ui/iter_skip_zero.stderr b/tests/ui/iter_skip_zero.stderr index ef46db843377..235074374aa1 100644 --- a/tests/ui/iter_skip_zero.stderr +++ b/tests/ui/iter_skip_zero.stderr @@ -9,7 +9,7 @@ LL | let _ = [1, 2, 3].iter().skip(0); = help: to override `-D warnings` add `#[allow(clippy::iter_skip_zero)]` error: usage of `.skip(0)` - --> tests/ui/iter_skip_zero.rs:12:39 + --> tests/ui/iter_skip_zero.rs:13:39 | LL | let _ = vec![1, 2, 3].iter().skip(0); | ^ help: if you meant to skip the first element, use: `1` @@ -17,7 +17,7 @@ LL | let _ = vec![1, 2, 3].iter().skip(0); = note: this call to `skip` does nothing and is useless; remove it error: usage of `.skip(0)` - --> tests/ui/iter_skip_zero.rs:13:34 + --> tests/ui/iter_skip_zero.rs:15:34 | LL | let _ = once([1, 2, 3]).skip(0); | ^ help: if you meant to skip the first element, use: `1` @@ -25,7 +25,7 @@ LL | let _ = once([1, 2, 3]).skip(0); = note: this call to `skip` does nothing and is useless; remove it error: usage of `.skip(0)` - --> tests/ui/iter_skip_zero.rs:14:71 + --> tests/ui/iter_skip_zero.rs:17:71 | LL | let _ = vec![1, 2, 3].iter().chain([1, 2, 3].iter().skip(0)).skip(0); | ^ help: if you meant to skip the first element, use: `1` @@ -33,7 +33,7 @@ LL | let _ = vec![1, 2, 3].iter().chain([1, 2, 3].iter().skip(0)).skip(0); = note: this call to `skip` does nothing and is useless; remove it error: usage of `.skip(0)` - --> tests/ui/iter_skip_zero.rs:14:62 + --> tests/ui/iter_skip_zero.rs:17:62 | LL | let _ = vec![1, 2, 3].iter().chain([1, 2, 3].iter().skip(0)).skip(0); | ^ help: if you meant to skip the first element, use: `1` diff --git a/tests/ui/iter_with_drain.fixed b/tests/ui/iter_with_drain.fixed index a03efceed4ca..b0661ffb981b 100644 --- a/tests/ui/iter_with_drain.fixed +++ b/tests/ui/iter_with_drain.fixed @@ -8,20 +8,26 @@ use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque}; fn full() { let mut a = vec!["aaa".to_string(), "bbb".to_string()]; let mut a: BinaryHeap<_> = a.into_iter().collect(); + //~^ iter_with_drain let mut a: HashSet<_> = a.drain().collect(); let mut a: VecDeque<_> = a.drain().collect(); let mut a: Vec<_> = a.into_iter().collect(); + //~^ iter_with_drain let mut a: HashMap<_, _> = a.into_iter().map(|x| (x.clone(), x)).collect(); + //~^ iter_with_drain let _: Vec<(String, String)> = a.drain().collect(); } fn closed() { let mut a = vec!["aaa".to_string(), "bbb".to_string()]; let mut a: BinaryHeap<_> = a.into_iter().collect(); + //~^ iter_with_drain let mut a: HashSet<_> = a.drain().collect(); let mut a: VecDeque<_> = a.drain().collect(); let mut a: Vec<_> = a.into_iter().collect(); + //~^ iter_with_drain let mut a: HashMap<_, _> = a.into_iter().map(|x| (x.clone(), x)).collect(); + //~^ iter_with_drain let _: Vec<(String, String)> = a.drain().collect(); } diff --git a/tests/ui/iter_with_drain.rs b/tests/ui/iter_with_drain.rs index a8cd47f83d04..746b0f9a5eda 100644 --- a/tests/ui/iter_with_drain.rs +++ b/tests/ui/iter_with_drain.rs @@ -8,20 +8,26 @@ use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque}; fn full() { let mut a = vec!["aaa".to_string(), "bbb".to_string()]; let mut a: BinaryHeap<_> = a.drain(..).collect(); + //~^ iter_with_drain let mut a: HashSet<_> = a.drain().collect(); let mut a: VecDeque<_> = a.drain().collect(); let mut a: Vec<_> = a.drain(..).collect(); + //~^ iter_with_drain let mut a: HashMap<_, _> = a.drain(..).map(|x| (x.clone(), x)).collect(); + //~^ iter_with_drain let _: Vec<(String, String)> = a.drain().collect(); } fn closed() { let mut a = vec!["aaa".to_string(), "bbb".to_string()]; let mut a: BinaryHeap<_> = a.drain(0..).collect(); + //~^ iter_with_drain let mut a: HashSet<_> = a.drain().collect(); let mut a: VecDeque<_> = a.drain().collect(); let mut a: Vec<_> = a.drain(..a.len()).collect(); + //~^ iter_with_drain let mut a: HashMap<_, _> = a.drain(0..a.len()).map(|x| (x.clone(), x)).collect(); + //~^ iter_with_drain let _: Vec<(String, String)> = a.drain().collect(); } diff --git a/tests/ui/iter_with_drain.stderr b/tests/ui/iter_with_drain.stderr index 265e18c263be..370658961b9b 100644 --- a/tests/ui/iter_with_drain.stderr +++ b/tests/ui/iter_with_drain.stderr @@ -8,31 +8,31 @@ LL | let mut a: BinaryHeap<_> = a.drain(..).collect(); = help: to override `-D warnings` add `#[allow(clippy::iter_with_drain)]` error: `drain(..)` used on a `VecDeque` - --> tests/ui/iter_with_drain.rs:13:27 + --> tests/ui/iter_with_drain.rs:14:27 | LL | let mut a: Vec<_> = a.drain(..).collect(); | ^^^^^^^^^ help: try: `into_iter()` error: `drain(..)` used on a `Vec` - --> tests/ui/iter_with_drain.rs:14:34 + --> tests/ui/iter_with_drain.rs:16:34 | LL | let mut a: HashMap<_, _> = a.drain(..).map(|x| (x.clone(), x)).collect(); | ^^^^^^^^^ help: try: `into_iter()` error: `drain(..)` used on a `Vec` - --> tests/ui/iter_with_drain.rs:20:34 + --> tests/ui/iter_with_drain.rs:23:34 | LL | let mut a: BinaryHeap<_> = a.drain(0..).collect(); | ^^^^^^^^^^ help: try: `into_iter()` error: `drain(..)` used on a `VecDeque` - --> tests/ui/iter_with_drain.rs:23:27 + --> tests/ui/iter_with_drain.rs:27:27 | LL | let mut a: Vec<_> = a.drain(..a.len()).collect(); | ^^^^^^^^^^^^^^^^ help: try: `into_iter()` error: `drain(..)` used on a `Vec` - --> tests/ui/iter_with_drain.rs:24:34 + --> tests/ui/iter_with_drain.rs:29:34 | LL | let mut a: HashMap<_, _> = a.drain(0..a.len()).map(|x| (x.clone(), x)).collect(); | ^^^^^^^^^^^^^^^^^ help: try: `into_iter()` diff --git a/tests/ui/iter_without_into_iter.rs b/tests/ui/iter_without_into_iter.rs index d5b28e45453b..dc3149be2cb4 100644 --- a/tests/ui/iter_without_into_iter.rs +++ b/tests/ui/iter_without_into_iter.rs @@ -7,11 +7,11 @@ extern crate proc_macros; pub struct S1; impl S1 { pub fn iter(&self) -> std::slice::Iter<'_, u8> { - //~^ ERROR: `iter` method without an `IntoIterator` impl + //~^ iter_without_into_iter [].iter() } pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> { - //~^ ERROR: `iter_mut` method without an `IntoIterator` impl + //~^ iter_without_into_iter [].iter_mut() } } @@ -27,11 +27,11 @@ impl S2 { pub struct S3<'a>(&'a mut [u8]); impl<'a> S3<'a> { pub fn iter(&self) -> std::slice::Iter<'_, u8> { - //~^ ERROR: `iter` method without an `IntoIterator` impl + //~^ iter_without_into_iter self.0.iter() } pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> { - //~^ ERROR: `iter_mut` method without an `IntoIterator` impl + //~^ iter_without_into_iter self.0.iter_mut() } } @@ -68,6 +68,7 @@ impl S7 { pub struct S8(T); impl S8 { pub fn iter(&self) -> std::slice::Iter<'static, T> { + //~^ iter_without_into_iter todo!() } } @@ -76,11 +77,11 @@ impl S8 { pub struct S9(T); impl S9 { pub fn iter(&self) -> std::slice::Iter<'_, T> { - //~^ ERROR: `iter` method without an `IntoIterator` impl + //~^ iter_without_into_iter todo!() } pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> { - //~^ ERROR: `iter_mut` method without an `IntoIterator` impl + //~^ iter_without_into_iter todo!() } } @@ -129,6 +130,7 @@ macro_rules! generate_impl { () => { impl Issue12037 { fn iter(&self) -> std::slice::Iter<'_, u8> { + //~^ iter_without_into_iter todo!() } } diff --git a/tests/ui/iter_without_into_iter.stderr b/tests/ui/iter_without_into_iter.stderr index d748c85003bb..8f86bee09670 100644 --- a/tests/ui/iter_without_into_iter.stderr +++ b/tests/ui/iter_without_into_iter.stderr @@ -88,6 +88,7 @@ error: `iter` method without an `IntoIterator` impl for `&S8` --> tests/ui/iter_without_into_iter.rs:70:5 | LL | / pub fn iter(&self) -> std::slice::Iter<'static, T> { +LL | | LL | | todo!() LL | | } | |_____^ @@ -105,7 +106,7 @@ LL + } | error: `iter` method without an `IntoIterator` impl for `&S9` - --> tests/ui/iter_without_into_iter.rs:78:5 + --> tests/ui/iter_without_into_iter.rs:79:5 | LL | / pub fn iter(&self) -> std::slice::Iter<'_, T> { LL | | @@ -126,7 +127,7 @@ LL + } | error: `iter_mut` method without an `IntoIterator` impl for `&mut S9` - --> tests/ui/iter_without_into_iter.rs:82:5 + --> tests/ui/iter_without_into_iter.rs:83:5 | LL | / pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> { LL | | @@ -147,9 +148,10 @@ LL + } | error: `iter` method without an `IntoIterator` impl for `&Issue12037` - --> tests/ui/iter_without_into_iter.rs:131:13 + --> tests/ui/iter_without_into_iter.rs:132:13 | LL | / fn iter(&self) -> std::slice::Iter<'_, u8> { +LL | | LL | | todo!() LL | | } | |_____________^ diff --git a/tests/ui/iterator_step_by_zero.rs b/tests/ui/iterator_step_by_zero.rs index 0b51842df2e3..a729101bd403 100644 --- a/tests/ui/iterator_step_by_zero.rs +++ b/tests/ui/iterator_step_by_zero.rs @@ -2,12 +2,13 @@ #[warn(clippy::iterator_step_by_zero)] fn main() { let _ = vec!["A", "B", "B"].iter().step_by(0); - //~^ ERROR: `Iterator::step_by(0)` will panic at runtime - //~| NOTE: `-D clippy::iterator-step-by-zero` implied by `-D warnings` + //~^ iterator_step_by_zero + let _ = "XXX".chars().step_by(0); - //~^ ERROR: `Iterator::step_by(0)` will panic at runtime + //~^ iterator_step_by_zero + let _ = (0..1).step_by(0); - //~^ ERROR: `Iterator::step_by(0)` will panic at runtime + //~^ iterator_step_by_zero // No error, not an iterator. let y = NotIterator; @@ -17,18 +18,19 @@ fn main() { let _ = (0..1).step_by(1); let _ = (1..).step_by(0); - //~^ ERROR: `Iterator::step_by(0)` will panic at runtime + //~^ iterator_step_by_zero + let _ = (1..=2).step_by(0); - //~^ ERROR: `Iterator::step_by(0)` will panic at runtime + //~^ iterator_step_by_zero let x = 0..1; let _ = x.step_by(0); - //~^ ERROR: `Iterator::step_by(0)` will panic at runtime + //~^ iterator_step_by_zero // check const eval let v1 = vec![1, 2, 3]; let _ = v1.iter().step_by(2 / 3); - //~^ ERROR: `Iterator::step_by(0)` will panic at runtime + //~^ iterator_step_by_zero } struct NotIterator; diff --git a/tests/ui/iterator_step_by_zero.stderr b/tests/ui/iterator_step_by_zero.stderr index 4156642d6dbb..0ff916b6dd5e 100644 --- a/tests/ui/iterator_step_by_zero.stderr +++ b/tests/ui/iterator_step_by_zero.stderr @@ -14,31 +14,31 @@ LL | let _ = "XXX".chars().step_by(0); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: `Iterator::step_by(0)` will panic at runtime - --> tests/ui/iterator_step_by_zero.rs:9:13 + --> tests/ui/iterator_step_by_zero.rs:10:13 | LL | let _ = (0..1).step_by(0); | ^^^^^^^^^^^^^^^^^ error: `Iterator::step_by(0)` will panic at runtime - --> tests/ui/iterator_step_by_zero.rs:19:13 + --> tests/ui/iterator_step_by_zero.rs:20:13 | LL | let _ = (1..).step_by(0); | ^^^^^^^^^^^^^^^^ error: `Iterator::step_by(0)` will panic at runtime - --> tests/ui/iterator_step_by_zero.rs:21:13 + --> tests/ui/iterator_step_by_zero.rs:23:13 | LL | let _ = (1..=2).step_by(0); | ^^^^^^^^^^^^^^^^^^ error: `Iterator::step_by(0)` will panic at runtime - --> tests/ui/iterator_step_by_zero.rs:25:13 + --> tests/ui/iterator_step_by_zero.rs:27:13 | LL | let _ = x.step_by(0); | ^^^^^^^^^^^^ error: `Iterator::step_by(0)` will panic at runtime - --> tests/ui/iterator_step_by_zero.rs:30:13 + --> tests/ui/iterator_step_by_zero.rs:32:13 | LL | let _ = v1.iter().step_by(2 / 3); | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/join_absolute_paths.rs b/tests/ui/join_absolute_paths.rs index efa77a0492e6..144c9147c2a1 100644 --- a/tests/ui/join_absolute_paths.rs +++ b/tests/ui/join_absolute_paths.rs @@ -8,19 +8,19 @@ use std::path::{Path, PathBuf}; fn main() { let path = Path::new("/bin"); path.join("/sh"); - //~^ ERROR: argument to `Path::join` starts with a path separator + //~^ join_absolute_paths let path = Path::new("C:\\Users"); path.join("\\user"); - //~^ ERROR: argument to `Path::join` starts with a path separator + //~^ join_absolute_paths let path = PathBuf::from("/bin"); path.join("/sh"); - //~^ ERROR: argument to `Path::join` starts with a path separator + //~^ join_absolute_paths let path = PathBuf::from("/bin"); path.join(r#"/sh"#); - //~^ ERROR: argument to `Path::join` starts with a path separator + //~^ join_absolute_paths let path: &[&str] = &["/bin"]; path.join("/sh"); diff --git a/tests/ui/large_const_arrays.fixed b/tests/ui/large_const_arrays.fixed index e5b28cb6a9dd..7c3868fc8ffd 100644 --- a/tests/ui/large_const_arrays.fixed +++ b/tests/ui/large_const_arrays.fixed @@ -8,9 +8,13 @@ pub struct S { // Should lint pub(crate) static FOO_PUB_CRATE: [u32; 1_000_000] = [0u32; 1_000_000]; +//~^ large_const_arrays pub static FOO_PUB: [u32; 1_000_000] = [0u32; 1_000_000]; +//~^ large_const_arrays static FOO_COMPUTED: [u32; 1_000 * 100] = [0u32; 1_000 * 100]; +//~^ large_const_arrays static FOO: [u32; 1_000_000] = [0u32; 1_000_000]; +//~^ large_const_arrays // Good pub(crate) const G_FOO_PUB_CRATE: [u32; 250] = [0u32; 250]; @@ -21,11 +25,17 @@ const G_FOO: [u32; 250] = [0u32; 250]; fn main() { // Should lint pub static BAR_PUB: [u32; 1_000_000] = [0u32; 1_000_000]; + //~^ large_const_arrays static BAR: [u32; 1_000_000] = [0u32; 1_000_000]; + //~^ large_const_arrays pub static BAR_STRUCT_PUB: [S; 5_000] = [S { data: [0; 32] }; 5_000]; + //~^ large_const_arrays static BAR_STRUCT: [S; 5_000] = [S { data: [0; 32] }; 5_000]; + //~^ large_const_arrays pub static BAR_S_PUB: [Option<&str>; 200_000] = [Some("str"); 200_000]; + //~^ large_const_arrays static BAR_S: [Option<&str>; 200_000] = [Some("str"); 200_000]; + //~^ large_const_arrays // Good pub const G_BAR_PUB: [u32; 250] = [0u32; 250]; diff --git a/tests/ui/large_const_arrays.rs b/tests/ui/large_const_arrays.rs index b9593225da2f..3e811520f063 100644 --- a/tests/ui/large_const_arrays.rs +++ b/tests/ui/large_const_arrays.rs @@ -8,9 +8,13 @@ pub struct S { // Should lint pub(crate) const FOO_PUB_CRATE: [u32; 1_000_000] = [0u32; 1_000_000]; +//~^ large_const_arrays pub const FOO_PUB: [u32; 1_000_000] = [0u32; 1_000_000]; +//~^ large_const_arrays const FOO_COMPUTED: [u32; 1_000 * 100] = [0u32; 1_000 * 100]; +//~^ large_const_arrays const FOO: [u32; 1_000_000] = [0u32; 1_000_000]; +//~^ large_const_arrays // Good pub(crate) const G_FOO_PUB_CRATE: [u32; 250] = [0u32; 250]; @@ -21,11 +25,17 @@ const G_FOO: [u32; 250] = [0u32; 250]; fn main() { // Should lint pub const BAR_PUB: [u32; 1_000_000] = [0u32; 1_000_000]; + //~^ large_const_arrays const BAR: [u32; 1_000_000] = [0u32; 1_000_000]; + //~^ large_const_arrays pub const BAR_STRUCT_PUB: [S; 5_000] = [S { data: [0; 32] }; 5_000]; + //~^ large_const_arrays const BAR_STRUCT: [S; 5_000] = [S { data: [0; 32] }; 5_000]; + //~^ large_const_arrays pub const BAR_S_PUB: [Option<&str>; 200_000] = [Some("str"); 200_000]; + //~^ large_const_arrays const BAR_S: [Option<&str>; 200_000] = [Some("str"); 200_000]; + //~^ large_const_arrays // Good pub const G_BAR_PUB: [u32; 250] = [0u32; 250]; diff --git a/tests/ui/large_const_arrays.stderr b/tests/ui/large_const_arrays.stderr index 271122053908..56cddeaf628d 100644 --- a/tests/ui/large_const_arrays.stderr +++ b/tests/ui/large_const_arrays.stderr @@ -10,7 +10,7 @@ LL | pub(crate) const FOO_PUB_CRATE: [u32; 1_000_000] = [0u32; 1_000_000]; = help: to override `-D warnings` add `#[allow(clippy::large_const_arrays)]` error: large array defined as const - --> tests/ui/large_const_arrays.rs:11:1 + --> tests/ui/large_const_arrays.rs:12:1 | LL | pub const FOO_PUB: [u32; 1_000_000] = [0u32; 1_000_000]; | ^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,7 +18,7 @@ LL | pub const FOO_PUB: [u32; 1_000_000] = [0u32; 1_000_000]; | help: make this a static item: `static` error: large array defined as const - --> tests/ui/large_const_arrays.rs:12:1 + --> tests/ui/large_const_arrays.rs:14:1 | LL | const FOO_COMPUTED: [u32; 1_000 * 100] = [0u32; 1_000 * 100]; | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | const FOO_COMPUTED: [u32; 1_000 * 100] = [0u32; 1_000 * 100]; | help: make this a static item: `static` error: large array defined as const - --> tests/ui/large_const_arrays.rs:13:1 + --> tests/ui/large_const_arrays.rs:16:1 | LL | const FOO: [u32; 1_000_000] = [0u32; 1_000_000]; | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,7 +34,7 @@ LL | const FOO: [u32; 1_000_000] = [0u32; 1_000_000]; | help: make this a static item: `static` error: large array defined as const - --> tests/ui/large_const_arrays.rs:23:5 + --> tests/ui/large_const_arrays.rs:27:5 | LL | pub const BAR_PUB: [u32; 1_000_000] = [0u32; 1_000_000]; | ^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -42,7 +42,7 @@ LL | pub const BAR_PUB: [u32; 1_000_000] = [0u32; 1_000_000]; | help: make this a static item: `static` error: large array defined as const - --> tests/ui/large_const_arrays.rs:24:5 + --> tests/ui/large_const_arrays.rs:29:5 | LL | const BAR: [u32; 1_000_000] = [0u32; 1_000_000]; | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -50,7 +50,7 @@ LL | const BAR: [u32; 1_000_000] = [0u32; 1_000_000]; | help: make this a static item: `static` error: large array defined as const - --> tests/ui/large_const_arrays.rs:25:5 + --> tests/ui/large_const_arrays.rs:31:5 | LL | pub const BAR_STRUCT_PUB: [S; 5_000] = [S { data: [0; 32] }; 5_000]; | ^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -58,7 +58,7 @@ LL | pub const BAR_STRUCT_PUB: [S; 5_000] = [S { data: [0; 32] }; 5_000]; | help: make this a static item: `static` error: large array defined as const - --> tests/ui/large_const_arrays.rs:26:5 + --> tests/ui/large_const_arrays.rs:33:5 | LL | const BAR_STRUCT: [S; 5_000] = [S { data: [0; 32] }; 5_000]; | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | const BAR_STRUCT: [S; 5_000] = [S { data: [0; 32] }; 5_000]; | help: make this a static item: `static` error: large array defined as const - --> tests/ui/large_const_arrays.rs:27:5 + --> tests/ui/large_const_arrays.rs:35:5 | LL | pub const BAR_S_PUB: [Option<&str>; 200_000] = [Some("str"); 200_000]; | ^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -74,7 +74,7 @@ LL | pub const BAR_S_PUB: [Option<&str>; 200_000] = [Some("str"); 200_000]; | help: make this a static item: `static` error: large array defined as const - --> tests/ui/large_const_arrays.rs:28:5 + --> tests/ui/large_const_arrays.rs:37:5 | LL | const BAR_S: [Option<&str>; 200_000] = [Some("str"); 200_000]; | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/large_digit_groups.fixed b/tests/ui/large_digit_groups.fixed index cdb001e47e2b..0ad2ebf522b8 100644 --- a/tests/ui/large_digit_groups.fixed +++ b/tests/ui/large_digit_groups.fixed @@ -20,10 +20,15 @@ fn main() { let _bad = ( 0b1_10110_i64, 0xdead_beef_usize, + //~^ unusual_byte_groupings 123_456_f32, + //~^ large_digit_groups 123_456.12_f32, + //~^ large_digit_groups 123_456.123_45_f64, + //~^ large_digit_groups 123_456.123_456_f64, + //~^ large_digit_groups ); // Ignore literals in macros let _ = mac!(); diff --git a/tests/ui/large_digit_groups.rs b/tests/ui/large_digit_groups.rs index 3c30c8670284..1cf489fd69b2 100644 --- a/tests/ui/large_digit_groups.rs +++ b/tests/ui/large_digit_groups.rs @@ -20,10 +20,15 @@ fn main() { let _bad = ( 0b1_10110_i64, 0xd_e_adbee_f_usize, + //~^ unusual_byte_groupings 1_23456_f32, + //~^ large_digit_groups 1_23456.12_f32, + //~^ large_digit_groups 1_23456.12345_f64, + //~^ large_digit_groups 1_23456.12345_6_f64, + //~^ large_digit_groups ); // Ignore literals in macros let _ = mac!(); diff --git a/tests/ui/large_digit_groups.stderr b/tests/ui/large_digit_groups.stderr index da34a91bc3bc..281a6267c8d6 100644 --- a/tests/ui/large_digit_groups.stderr +++ b/tests/ui/large_digit_groups.stderr @@ -8,7 +8,7 @@ LL | 0xd_e_adbee_f_usize, = help: to override `-D warnings` add `#[allow(clippy::unusual_byte_groupings)]` error: digit groups should be smaller - --> tests/ui/large_digit_groups.rs:23:9 + --> tests/ui/large_digit_groups.rs:24:9 | LL | 1_23456_f32, | ^^^^^^^^^^^ help: consider: `123_456_f32` @@ -17,19 +17,19 @@ LL | 1_23456_f32, = help: to override `-D warnings` add `#[allow(clippy::large_digit_groups)]` error: digit groups should be smaller - --> tests/ui/large_digit_groups.rs:24:9 + --> tests/ui/large_digit_groups.rs:26:9 | LL | 1_23456.12_f32, | ^^^^^^^^^^^^^^ help: consider: `123_456.12_f32` error: digit groups should be smaller - --> tests/ui/large_digit_groups.rs:25:9 + --> tests/ui/large_digit_groups.rs:28:9 | LL | 1_23456.12345_f64, | ^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_45_f64` error: digit groups should be smaller - --> tests/ui/large_digit_groups.rs:26:9 + --> tests/ui/large_digit_groups.rs:30:9 | LL | 1_23456.12345_6_f64, | ^^^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_456_f64` diff --git a/tests/ui/large_enum_variant.32bit.stderr b/tests/ui/large_enum_variant.32bit.stderr index ff4f1a7f312c..80ca5daa1d57 100644 --- a/tests/ui/large_enum_variant.32bit.stderr +++ b/tests/ui/large_enum_variant.32bit.stderr @@ -1,7 +1,8 @@ error: large size difference between variants - --> tests/ui/large_enum_variant.rs:11:1 + --> tests/ui/large_enum_variant.rs:13:1 | LL | / enum LargeEnum { +LL | | LL | | A(i32), | | ------ the second-largest variant contains at least 4 bytes LL | | B([i32; 8000]), @@ -13,13 +14,15 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::large_enum_variant)]` help: consider boxing the large fields to reduce the total size of the enum | -LL | B(Box<[i32; 8000]>), - | ~~~~~~~~~~~~~~~~ +LL - B([i32; 8000]), +LL + B(Box<[i32; 8000]>), + | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:35:1 + --> tests/ui/large_enum_variant.rs:38:1 | LL | / enum LargeEnum2 { +LL | | LL | | VariantOk(i32, u32), | | ------------------- the second-largest variant contains at least 8 bytes LL | | ContainingLargeEnum(LargeEnum), @@ -29,13 +32,15 @@ LL | | } | help: consider boxing the large fields to reduce the total size of the enum | -LL | ContainingLargeEnum(Box), - | ~~~~~~~~~~~~~~ +LL - ContainingLargeEnum(LargeEnum), +LL + ContainingLargeEnum(Box), + | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:40:1 + --> tests/ui/large_enum_variant.rs:44:1 | LL | / enum LargeEnum3 { +LL | | LL | | ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]), | | --------------------------------------------------------- the largest variant contains at least 70004 bytes LL | | VoidVariant, @@ -46,13 +51,15 @@ LL | | } | help: consider boxing the large fields to reduce the total size of the enum | -LL | ContainingMoreThanOneField(i32, Box<[i32; 8000]>, Box<[i32; 9500]>), - | ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~ +LL - ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]), +LL + ContainingMoreThanOneField(i32, Box<[i32; 8000]>, Box<[i32; 9500]>), + | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:46:1 + --> tests/ui/large_enum_variant.rs:51:1 | LL | / enum LargeEnum4 { +LL | | LL | | VariantOk(i32, u32), | | ------------------- the second-largest variant contains at least 8 bytes LL | | StructLikeLarge { x: [i32; 8000], y: i32 }, @@ -62,13 +69,15 @@ LL | | } | help: consider boxing the large fields to reduce the total size of the enum | -LL | StructLikeLarge { x: Box<[i32; 8000]>, y: i32 }, - | ~~~~~~~~~~~~~~~~ +LL - StructLikeLarge { x: [i32; 8000], y: i32 }, +LL + StructLikeLarge { x: Box<[i32; 8000]>, y: i32 }, + | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:51:1 + --> tests/ui/large_enum_variant.rs:57:1 | LL | / enum LargeEnum5 { +LL | | LL | | VariantOk(i32, u32), | | ------------------- the second-largest variant contains at least 8 bytes LL | | StructLikeLarge2 { x: [i32; 8000] }, @@ -78,13 +87,15 @@ LL | | } | help: consider boxing the large fields to reduce the total size of the enum | -LL | StructLikeLarge2 { x: Box<[i32; 8000]> }, - | ~~~~~~~~~~~~~~~~ +LL - StructLikeLarge2 { x: [i32; 8000] }, +LL + StructLikeLarge2 { x: Box<[i32; 8000]> }, + | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:67:1 + --> tests/ui/large_enum_variant.rs:74:1 | LL | / enum LargeEnum7 { +LL | | LL | | A, LL | | B([u8; 1255]), | | ------------- the largest variant contains at least 1255 bytes @@ -95,13 +106,15 @@ LL | | } | help: consider boxing the large fields to reduce the total size of the enum | -LL | B(Box<[u8; 1255]>), - | ~~~~~~~~~~~~~~~ +LL - B([u8; 1255]), +LL + B(Box<[u8; 1255]>), + | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:73:1 + --> tests/ui/large_enum_variant.rs:81:1 | LL | / enum LargeEnum8 { +LL | | LL | | VariantOk(i32, u32), | | ------------------- the second-largest variant contains at least 8 bytes LL | | ContainingMoreThanOneField([i32; 8000], [i32; 2], [i32; 9500], [i32; 30]), @@ -111,13 +124,15 @@ LL | | } | help: consider boxing the large fields to reduce the total size of the enum | -LL | ContainingMoreThanOneField(Box<[i32; 8000]>, [i32; 2], Box<[i32; 9500]>, [i32; 30]), - | ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~ +LL - ContainingMoreThanOneField([i32; 8000], [i32; 2], [i32; 9500], [i32; 30]), +LL + ContainingMoreThanOneField(Box<[i32; 8000]>, [i32; 2], Box<[i32; 9500]>, [i32; 30]), + | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:78:1 + --> tests/ui/large_enum_variant.rs:87:1 | LL | / enum LargeEnum9 { +LL | | LL | | A(Struct<()>), | | ------------- the second-largest variant contains at least 4 bytes LL | | B(Struct2), @@ -127,13 +142,15 @@ LL | | } | help: consider boxing the large fields to reduce the total size of the enum | -LL | B(Box), - | ~~~~~~~~~~~~ +LL - B(Struct2), +LL + B(Box), + | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:83:1 + --> tests/ui/large_enum_variant.rs:93:1 | LL | / enum LargeEnumOk2 { +LL | | LL | | A(T), | | ---- the second-largest variant contains at least 0 bytes LL | | B(Struct2), @@ -143,13 +160,15 @@ LL | | } | help: consider boxing the large fields to reduce the total size of the enum | -LL | B(Box), - | ~~~~~~~~~~~~ +LL - B(Struct2), +LL + B(Box), + | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:88:1 + --> tests/ui/large_enum_variant.rs:99:1 | LL | / enum LargeEnumOk3 { +LL | | LL | | A(Struct), | | ------------ the second-largest variant contains at least 4 bytes LL | | B(Struct2), @@ -159,13 +178,15 @@ LL | | } | help: consider boxing the large fields to reduce the total size of the enum | -LL | B(Box), - | ~~~~~~~~~~~~ +LL - B(Struct2), +LL + B(Box), + | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:103:1 + --> tests/ui/large_enum_variant.rs:115:1 | LL | / enum CopyableLargeEnum { +LL | | LL | | A(bool), | | ------- the second-largest variant contains at least 1 bytes LL | | B([u64; 8000]), @@ -174,34 +195,12 @@ LL | | } | |_^ the entire enum is at least 64004 bytes | note: boxing a variant would require the type no longer be `Copy` - --> tests/ui/large_enum_variant.rs:103:6 + --> tests/ui/large_enum_variant.rs:115:6 | LL | enum CopyableLargeEnum { | ^^^^^^^^^^^^^^^^^ help: consider boxing the large fields to reduce the total size of the enum - --> tests/ui/large_enum_variant.rs:105:5 - | -LL | B([u64; 8000]), - | ^^^^^^^^^^^^^^ - -error: large size difference between variants - --> tests/ui/large_enum_variant.rs:108:1 - | -LL | / enum ManuallyCopyLargeEnum { -LL | | A(bool), - | | ------- the second-largest variant contains at least 1 bytes -LL | | B([u64; 8000]), - | | -------------- the largest variant contains at least 64000 bytes -LL | | } - | |_^ the entire enum is at least 64004 bytes - | -note: boxing a variant would require the type no longer be `Copy` - --> tests/ui/large_enum_variant.rs:108:6 - | -LL | enum ManuallyCopyLargeEnum { - | ^^^^^^^^^^^^^^^^^^^^^ -help: consider boxing the large fields to reduce the total size of the enum - --> tests/ui/large_enum_variant.rs:110:5 + --> tests/ui/large_enum_variant.rs:118:5 | LL | B([u64; 8000]), | ^^^^^^^^^^^^^^ @@ -209,7 +208,31 @@ LL | B([u64; 8000]), error: large size difference between variants --> tests/ui/large_enum_variant.rs:121:1 | +LL | / enum ManuallyCopyLargeEnum { +LL | | +LL | | A(bool), + | | ------- the second-largest variant contains at least 1 bytes +LL | | B([u64; 8000]), + | | -------------- the largest variant contains at least 64000 bytes +LL | | } + | |_^ the entire enum is at least 64004 bytes + | +note: boxing a variant would require the type no longer be `Copy` + --> tests/ui/large_enum_variant.rs:121:6 + | +LL | enum ManuallyCopyLargeEnum { + | ^^^^^^^^^^^^^^^^^^^^^ +help: consider boxing the large fields to reduce the total size of the enum + --> tests/ui/large_enum_variant.rs:124:5 + | +LL | B([u64; 8000]), + | ^^^^^^^^^^^^^^ + +error: large size difference between variants + --> tests/ui/large_enum_variant.rs:135:1 + | LL | / enum SomeGenericPossiblyCopyEnum { +LL | | LL | | A(bool, std::marker::PhantomData), | | ------------------------------------ the second-largest variant contains at least 1 bytes LL | | B([u64; 4000]), @@ -218,20 +241,21 @@ LL | | } | |_^ the entire enum is at least 32004 bytes | note: boxing a variant would require the type no longer be `Copy` - --> tests/ui/large_enum_variant.rs:121:6 + --> tests/ui/large_enum_variant.rs:135:6 | LL | enum SomeGenericPossiblyCopyEnum { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider boxing the large fields to reduce the total size of the enum - --> tests/ui/large_enum_variant.rs:123:5 + --> tests/ui/large_enum_variant.rs:138:5 | LL | B([u64; 4000]), | ^^^^^^^^^^^^^^ error: large size difference between variants - --> tests/ui/large_enum_variant.rs:134:1 + --> tests/ui/large_enum_variant.rs:149:1 | LL | / enum LargeEnumWithGenerics { +LL | | LL | | Small, | | ----- the second-largest variant carries no data at all LL | | Large((T, [u8; 512])), @@ -241,13 +265,15 @@ LL | | } | help: consider boxing the large fields to reduce the total size of the enum | -LL | Large(Box<(T, [u8; 512])>), - | ~~~~~~~~~~~~~~~~~~~ +LL - Large((T, [u8; 512])), +LL + Large(Box<(T, [u8; 512])>), + | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:143:1 + --> tests/ui/large_enum_variant.rs:159:1 | LL | / enum WithGenerics { +LL | | LL | | Large([Foo; 64]), | | --------------------- the largest variant contains at least 512 bytes LL | | Small(u8), @@ -257,13 +283,15 @@ LL | | } | help: consider boxing the large fields to reduce the total size of the enum | -LL | Large(Box<[Foo; 64]>), - | ~~~~~~~~~~~~~~~~~~~ +LL - Large([Foo; 64]), +LL + Large(Box<[Foo; 64]>), + | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:153:1 + --> tests/ui/large_enum_variant.rs:170:1 | LL | / enum LargeEnumOfConst { +LL | | LL | | Ok, | | -- the second-largest variant carries no data at all LL | | Error(PossiblyLargeEnumWithConst<256>), @@ -273,8 +301,45 @@ LL | | } | help: consider boxing the large fields to reduce the total size of the enum | -LL | Error(Box>), - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL - Error(PossiblyLargeEnumWithConst<256>), +LL + Error(Box>), + | -error: aborting due to 16 previous errors +error: large size difference between variants + --> tests/ui/large_enum_variant.rs:176:1 + | +LL | / enum WithRecursion { +LL | | +LL | | Large([u64; 64]), + | | ---------------- the largest variant contains at least 512 bytes +LL | | Recursive(Box), + | | ----------------------------- the second-largest variant contains at least 4 bytes +LL | | } + | |_^ the entire enum is at least 516 bytes + | +help: consider boxing the large fields to reduce the total size of the enum + | +LL - Large([u64; 64]), +LL + Large(Box<[u64; 64]>), + | + +error: large size difference between variants + --> tests/ui/large_enum_variant.rs:187:1 + | +LL | / enum LargeEnumWithGenericsAndRecursive { +LL | | +LL | | Ok(), + | | ---- the second-largest variant carries no data at all +LL | | Error(WithRecursionAndGenerics), + | | ------------------------------------ the largest variant contains at least 516 bytes +LL | | } + | |_^ the entire enum is at least 516 bytes + | +help: consider boxing the large fields to reduce the total size of the enum + | +LL - Error(WithRecursionAndGenerics), +LL + Error(Box>), + | + +error: aborting due to 18 previous errors diff --git a/tests/ui/large_enum_variant.64bit.stderr b/tests/ui/large_enum_variant.64bit.stderr index 60653b4abfb5..559bdf2a2f50 100644 --- a/tests/ui/large_enum_variant.64bit.stderr +++ b/tests/ui/large_enum_variant.64bit.stderr @@ -1,7 +1,8 @@ error: large size difference between variants - --> tests/ui/large_enum_variant.rs:11:1 + --> tests/ui/large_enum_variant.rs:13:1 | LL | / enum LargeEnum { +LL | | LL | | A(i32), | | ------ the second-largest variant contains at least 4 bytes LL | | B([i32; 8000]), @@ -18,9 +19,10 @@ LL + B(Box<[i32; 8000]>), | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:35:1 + --> tests/ui/large_enum_variant.rs:38:1 | LL | / enum LargeEnum2 { +LL | | LL | | VariantOk(i32, u32), | | ------------------- the second-largest variant contains at least 8 bytes LL | | ContainingLargeEnum(LargeEnum), @@ -35,9 +37,10 @@ LL + ContainingLargeEnum(Box), | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:40:1 + --> tests/ui/large_enum_variant.rs:44:1 | LL | / enum LargeEnum3 { +LL | | LL | | ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]), | | --------------------------------------------------------- the largest variant contains at least 70004 bytes LL | | VoidVariant, @@ -53,9 +56,10 @@ LL + ContainingMoreThanOneField(i32, Box<[i32; 8000]>, Box<[i32; 9500]>), | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:46:1 + --> tests/ui/large_enum_variant.rs:51:1 | LL | / enum LargeEnum4 { +LL | | LL | | VariantOk(i32, u32), | | ------------------- the second-largest variant contains at least 8 bytes LL | | StructLikeLarge { x: [i32; 8000], y: i32 }, @@ -70,9 +74,10 @@ LL + StructLikeLarge { x: Box<[i32; 8000]>, y: i32 }, | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:51:1 + --> tests/ui/large_enum_variant.rs:57:1 | LL | / enum LargeEnum5 { +LL | | LL | | VariantOk(i32, u32), | | ------------------- the second-largest variant contains at least 8 bytes LL | | StructLikeLarge2 { x: [i32; 8000] }, @@ -87,9 +92,10 @@ LL + StructLikeLarge2 { x: Box<[i32; 8000]> }, | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:67:1 + --> tests/ui/large_enum_variant.rs:74:1 | LL | / enum LargeEnum7 { +LL | | LL | | A, LL | | B([u8; 1255]), | | ------------- the largest variant contains at least 1255 bytes @@ -105,9 +111,10 @@ LL + B(Box<[u8; 1255]>), | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:73:1 + --> tests/ui/large_enum_variant.rs:81:1 | LL | / enum LargeEnum8 { +LL | | LL | | VariantOk(i32, u32), | | ------------------- the second-largest variant contains at least 8 bytes LL | | ContainingMoreThanOneField([i32; 8000], [i32; 2], [i32; 9500], [i32; 30]), @@ -122,9 +129,10 @@ LL + ContainingMoreThanOneField(Box<[i32; 8000]>, [i32; 2], Box<[i32; 9500]> | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:78:1 + --> tests/ui/large_enum_variant.rs:87:1 | LL | / enum LargeEnum9 { +LL | | LL | | A(Struct<()>), | | ------------- the second-largest variant contains at least 4 bytes LL | | B(Struct2), @@ -139,9 +147,10 @@ LL + B(Box), | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:83:1 + --> tests/ui/large_enum_variant.rs:93:1 | LL | / enum LargeEnumOk2 { +LL | | LL | | A(T), | | ---- the second-largest variant contains at least 0 bytes LL | | B(Struct2), @@ -156,9 +165,10 @@ LL + B(Box), | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:88:1 + --> tests/ui/large_enum_variant.rs:99:1 | LL | / enum LargeEnumOk3 { +LL | | LL | | A(Struct), | | ------------ the second-largest variant contains at least 4 bytes LL | | B(Struct2), @@ -173,9 +183,10 @@ LL + B(Box), | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:103:1 + --> tests/ui/large_enum_variant.rs:115:1 | LL | / enum CopyableLargeEnum { +LL | | LL | | A(bool), | | ------- the second-largest variant contains at least 1 bytes LL | | B([u64; 8000]), @@ -184,34 +195,12 @@ LL | | } | |_^ the entire enum is at least 64008 bytes | note: boxing a variant would require the type no longer be `Copy` - --> tests/ui/large_enum_variant.rs:103:6 + --> tests/ui/large_enum_variant.rs:115:6 | LL | enum CopyableLargeEnum { | ^^^^^^^^^^^^^^^^^ help: consider boxing the large fields to reduce the total size of the enum - --> tests/ui/large_enum_variant.rs:105:5 - | -LL | B([u64; 8000]), - | ^^^^^^^^^^^^^^ - -error: large size difference between variants - --> tests/ui/large_enum_variant.rs:108:1 - | -LL | / enum ManuallyCopyLargeEnum { -LL | | A(bool), - | | ------- the second-largest variant contains at least 1 bytes -LL | | B([u64; 8000]), - | | -------------- the largest variant contains at least 64000 bytes -LL | | } - | |_^ the entire enum is at least 64008 bytes - | -note: boxing a variant would require the type no longer be `Copy` - --> tests/ui/large_enum_variant.rs:108:6 - | -LL | enum ManuallyCopyLargeEnum { - | ^^^^^^^^^^^^^^^^^^^^^ -help: consider boxing the large fields to reduce the total size of the enum - --> tests/ui/large_enum_variant.rs:110:5 + --> tests/ui/large_enum_variant.rs:118:5 | LL | B([u64; 8000]), | ^^^^^^^^^^^^^^ @@ -219,7 +208,31 @@ LL | B([u64; 8000]), error: large size difference between variants --> tests/ui/large_enum_variant.rs:121:1 | +LL | / enum ManuallyCopyLargeEnum { +LL | | +LL | | A(bool), + | | ------- the second-largest variant contains at least 1 bytes +LL | | B([u64; 8000]), + | | -------------- the largest variant contains at least 64000 bytes +LL | | } + | |_^ the entire enum is at least 64008 bytes + | +note: boxing a variant would require the type no longer be `Copy` + --> tests/ui/large_enum_variant.rs:121:6 + | +LL | enum ManuallyCopyLargeEnum { + | ^^^^^^^^^^^^^^^^^^^^^ +help: consider boxing the large fields to reduce the total size of the enum + --> tests/ui/large_enum_variant.rs:124:5 + | +LL | B([u64; 8000]), + | ^^^^^^^^^^^^^^ + +error: large size difference between variants + --> tests/ui/large_enum_variant.rs:135:1 + | LL | / enum SomeGenericPossiblyCopyEnum { +LL | | LL | | A(bool, std::marker::PhantomData), | | ------------------------------------ the second-largest variant contains at least 1 bytes LL | | B([u64; 4000]), @@ -228,20 +241,21 @@ LL | | } | |_^ the entire enum is at least 32008 bytes | note: boxing a variant would require the type no longer be `Copy` - --> tests/ui/large_enum_variant.rs:121:6 + --> tests/ui/large_enum_variant.rs:135:6 | LL | enum SomeGenericPossiblyCopyEnum { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider boxing the large fields to reduce the total size of the enum - --> tests/ui/large_enum_variant.rs:123:5 + --> tests/ui/large_enum_variant.rs:138:5 | LL | B([u64; 4000]), | ^^^^^^^^^^^^^^ error: large size difference between variants - --> tests/ui/large_enum_variant.rs:134:1 + --> tests/ui/large_enum_variant.rs:149:1 | LL | / enum LargeEnumWithGenerics { +LL | | LL | | Small, | | ----- the second-largest variant carries no data at all LL | | Large((T, [u8; 512])), @@ -256,9 +270,10 @@ LL + Large(Box<(T, [u8; 512])>), | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:143:1 + --> tests/ui/large_enum_variant.rs:159:1 | LL | / enum WithGenerics { +LL | | LL | | Large([Foo; 64]), | | --------------------- the largest variant contains at least 512 bytes LL | | Small(u8), @@ -273,9 +288,10 @@ LL + Large(Box<[Foo; 64]>), | error: large size difference between variants - --> tests/ui/large_enum_variant.rs:153:1 + --> tests/ui/large_enum_variant.rs:170:1 | LL | / enum LargeEnumOfConst { +LL | | LL | | Ok, | | -- the second-largest variant carries no data at all LL | | Error(PossiblyLargeEnumWithConst<256>), @@ -289,5 +305,77 @@ LL - Error(PossiblyLargeEnumWithConst<256>), LL + Error(Box>), | -error: aborting due to 16 previous errors +error: large size difference between variants + --> tests/ui/large_enum_variant.rs:176:1 + | +LL | / enum WithRecursion { +LL | | +LL | | Large([u64; 64]), + | | ---------------- the largest variant contains at least 512 bytes +LL | | Recursive(Box), + | | ----------------------------- the second-largest variant contains at least 8 bytes +LL | | } + | |_^ the entire enum is at least 520 bytes + | +help: consider boxing the large fields to reduce the total size of the enum + | +LL - Large([u64; 64]), +LL + Large(Box<[u64; 64]>), + | + +error: large size difference between variants + --> tests/ui/large_enum_variant.rs:187:1 + | +LL | / enum LargeEnumWithGenericsAndRecursive { +LL | | +LL | | Ok(), + | | ---- the second-largest variant carries no data at all +LL | | Error(WithRecursionAndGenerics), + | | ------------------------------------ the largest variant contains at least 520 bytes +LL | | } + | |_^ the entire enum is at least 520 bytes + | +help: consider boxing the large fields to reduce the total size of the enum + | +LL - Error(WithRecursionAndGenerics), +LL + Error(Box>), + | + +error: large size difference between variants + --> tests/ui/large_enum_variant.rs:223:5 + | +LL | / enum NoWarnings { +LL | | +LL | | BigBoi(PublishWithBytes), + | | ------------------------ the largest variant contains at least 296 bytes +LL | | _SmallBoi(u8), + | | ------------- the second-largest variant contains at least 1 bytes +LL | | } + | |_____^ the entire enum is at least 296 bytes + | +help: consider boxing the large fields to reduce the total size of the enum + | +LL - BigBoi(PublishWithBytes), +LL + BigBoi(Box), + | + +error: large size difference between variants + --> tests/ui/large_enum_variant.rs:229:5 + | +LL | / enum MakesClippyAngry { +LL | | +LL | | BigBoi(PublishWithVec), + | | ---------------------- the largest variant contains at least 224 bytes +LL | | _SmallBoi(u8), + | | ------------- the second-largest variant contains at least 1 bytes +LL | | } + | |_____^ the entire enum is at least 224 bytes + | +help: consider boxing the large fields to reduce the total size of the enum + | +LL - BigBoi(PublishWithVec), +LL + BigBoi(Box), + | + +error: aborting due to 20 previous errors diff --git a/tests/ui/large_enum_variant.rs b/tests/ui/large_enum_variant.rs index 3625c011dbfa..9cf6318ca342 100644 --- a/tests/ui/large_enum_variant.rs +++ b/tests/ui/large_enum_variant.rs @@ -1,6 +1,8 @@ -//@stderr-per-bitwidth +//@revisions: 32bit 64bit //@aux-build:proc_macros.rs //@no-rustfix +//@[32bit]ignore-bitwidth: 64 +//@[64bit]ignore-bitwidth: 32 #![allow(dead_code)] #![allow(unused_variables)] #![warn(clippy::large_enum_variant)] @@ -9,6 +11,7 @@ extern crate proc_macros; use proc_macros::external; enum LargeEnum { + //~^ large_enum_variant A(i32), B([i32; 8000]), } @@ -33,22 +36,26 @@ enum LargeEnumGeneric { } enum LargeEnum2 { + //~^ large_enum_variant VariantOk(i32, u32), ContainingLargeEnum(LargeEnum), } enum LargeEnum3 { + //~^ large_enum_variant ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]), VoidVariant, StructLikeLittle { x: i32, y: i32 }, } enum LargeEnum4 { + //~^ large_enum_variant VariantOk(i32, u32), StructLikeLarge { x: [i32; 8000], y: i32 }, } enum LargeEnum5 { + //~^ large_enum_variant VariantOk(i32, u32), StructLikeLarge2 { x: [i32; 8000] }, } @@ -65,27 +72,32 @@ enum LargeEnum6 { } enum LargeEnum7 { + //~^ large_enum_variant A, B([u8; 1255]), C([u8; 200]), } enum LargeEnum8 { + //~^ large_enum_variant VariantOk(i32, u32), ContainingMoreThanOneField([i32; 8000], [i32; 2], [i32; 9500], [i32; 30]), } enum LargeEnum9 { + //~^ large_enum_variant A(Struct<()>), B(Struct2), } enum LargeEnumOk2 { + //~^ large_enum_variant A(T), B(Struct2), } enum LargeEnumOk3 { + //~^ large_enum_variant A(Struct), B(Struct2), } @@ -101,11 +113,13 @@ struct Struct2 { #[derive(Copy, Clone)] enum CopyableLargeEnum { + //~^ large_enum_variant A(bool), B([u64; 8000]), } enum ManuallyCopyLargeEnum { + //~^ large_enum_variant A(bool), B([u64; 8000]), } @@ -119,6 +133,7 @@ impl Clone for ManuallyCopyLargeEnum { impl Copy for ManuallyCopyLargeEnum {} enum SomeGenericPossiblyCopyEnum { + //~^ large_enum_variant A(bool, std::marker::PhantomData), B([u64; 4000]), } @@ -132,6 +147,7 @@ impl Clone for SomeGenericPossiblyCopyEnum { impl Copy for SomeGenericPossiblyCopyEnum {} enum LargeEnumWithGenerics { + //~^ large_enum_variant Small, Large((T, [u8; 512])), } @@ -141,6 +157,7 @@ struct Foo { } enum WithGenerics { + //~^ large_enum_variant Large([Foo; 64]), Small(u8), } @@ -151,10 +168,28 @@ enum PossiblyLargeEnumWithConst { } enum LargeEnumOfConst { + //~^ large_enum_variant Ok, Error(PossiblyLargeEnumWithConst<256>), } +enum WithRecursion { + //~^ large_enum_variant + Large([u64; 64]), + Recursive(Box), +} + +enum WithRecursionAndGenerics { + Large([T; 64]), + Recursive(Box>), +} + +enum LargeEnumWithGenericsAndRecursive { + //~^ large_enum_variant + Ok(), + Error(WithRecursionAndGenerics), +} + fn main() { external!( enum LargeEnumInMacro { @@ -163,3 +198,67 @@ fn main() { } ); } + +mod issue11915 { + use std::sync::atomic::AtomicPtr; + + pub struct Bytes { + ptr: *const u8, + len: usize, + // inlined "trait object" + data: AtomicPtr<()>, + vtable: &'static Vtable, + } + pub(crate) struct Vtable { + /// fn(data, ptr, len) + pub clone: unsafe fn(&AtomicPtr<()>, *const u8, usize) -> Bytes, + /// fn(data, ptr, len) + /// + /// takes `Bytes` to value + pub to_vec: unsafe fn(&AtomicPtr<()>, *const u8, usize) -> Vec, + /// fn(data, ptr, len) + pub drop: unsafe fn(&mut AtomicPtr<()>, *const u8, usize), + } + + enum NoWarnings { + //~[64bit]^ large_enum_variant + BigBoi(PublishWithBytes), + _SmallBoi(u8), + } + + enum MakesClippyAngry { + //~[64bit]^ large_enum_variant + BigBoi(PublishWithVec), + _SmallBoi(u8), + } + + struct PublishWithBytes { + _dup: bool, + _retain: bool, + _topic: Bytes, + __topic: Bytes, + ___topic: Bytes, + ____topic: Bytes, + _pkid: u16, + _payload: Bytes, + __payload: Bytes, + ___payload: Bytes, + ____payload: Bytes, + _____payload: Bytes, + } + + struct PublishWithVec { + _dup: bool, + _retain: bool, + _topic: Vec, + __topic: Vec, + ___topic: Vec, + ____topic: Vec, + _pkid: u16, + _payload: Vec, + __payload: Vec, + ___payload: Vec, + ____payload: Vec, + _____payload: Vec, + } +} diff --git a/tests/ui/large_futures.fixed b/tests/ui/large_futures.fixed index 1e87859f4526..c2159c58de1e 100644 --- a/tests/ui/large_futures.fixed +++ b/tests/ui/large_futures.fixed @@ -8,21 +8,21 @@ async fn big_fut(_arg: [u8; 1024 * 16]) {} async fn wait() { let f = async { Box::pin(big_fut([0u8; 1024 * 16])).await; - //~^ ERROR: large future with a size of 16385 bytes - //~| NOTE: `-D clippy::large-futures` implied by `-D warnings` + //~^ large_futures }; Box::pin(f).await - //~^ ERROR: large future with a size of 16386 bytes + //~^ large_futures } async fn calls_fut(fut: impl std::future::Future) { loop { Box::pin(wait()).await; - //~^ ERROR: large future with a size of 16387 bytes + //~^ large_futures + if true { return fut.await; } else { Box::pin(wait()).await; - //~^ ERROR: large future with a size of 16387 bytes + //~^ large_futures } } } @@ -30,9 +30,10 @@ async fn calls_fut(fut: impl std::future::Future) { pub async fn test() { let fut = big_fut([0u8; 1024 * 16]); Box::pin(foo()).await; - //~^ ERROR: large future with a size of 65540 bytes + //~^ large_futures + Box::pin(calls_fut(fut)).await; - //~^ ERROR: large future with a size of 49159 bytes + //~^ large_futures } pub fn foo() -> impl std::future::Future { @@ -45,7 +46,8 @@ pub fn foo() -> impl std::future::Future { pub async fn lines() { Box::pin(async { - //~^ ERROR: large future with a size of 65540 bytes + //~^ large_futures + let x = [0i32; 1024 * 16]; async {}.await; println!("{:?}", x); @@ -57,6 +59,7 @@ pub async fn macro_expn() { macro_rules! macro_ { () => { Box::pin(async { + //~^ large_futures let x = [0i32; 1024 * 16]; async {}.await; println!("macro: {:?}", x); diff --git a/tests/ui/large_futures.rs b/tests/ui/large_futures.rs index 3f4ea2ebf8bb..567f6344afea 100644 --- a/tests/ui/large_futures.rs +++ b/tests/ui/large_futures.rs @@ -8,21 +8,21 @@ async fn big_fut(_arg: [u8; 1024 * 16]) {} async fn wait() { let f = async { big_fut([0u8; 1024 * 16]).await; - //~^ ERROR: large future with a size of 16385 bytes - //~| NOTE: `-D clippy::large-futures` implied by `-D warnings` + //~^ large_futures }; f.await - //~^ ERROR: large future with a size of 16386 bytes + //~^ large_futures } async fn calls_fut(fut: impl std::future::Future) { loop { wait().await; - //~^ ERROR: large future with a size of 16387 bytes + //~^ large_futures + if true { return fut.await; } else { wait().await; - //~^ ERROR: large future with a size of 16387 bytes + //~^ large_futures } } } @@ -30,9 +30,10 @@ async fn calls_fut(fut: impl std::future::Future) { pub async fn test() { let fut = big_fut([0u8; 1024 * 16]); foo().await; - //~^ ERROR: large future with a size of 65540 bytes + //~^ large_futures + calls_fut(fut).await; - //~^ ERROR: large future with a size of 49159 bytes + //~^ large_futures } pub fn foo() -> impl std::future::Future { @@ -45,7 +46,8 @@ pub fn foo() -> impl std::future::Future { pub async fn lines() { async { - //~^ ERROR: large future with a size of 65540 bytes + //~^ large_futures + let x = [0i32; 1024 * 16]; async {}.await; println!("{:?}", x); @@ -57,6 +59,7 @@ pub async fn macro_expn() { macro_rules! macro_ { () => { async { + //~^ large_futures let x = [0i32; 1024 * 16]; async {}.await; println!("macro: {:?}", x); diff --git a/tests/ui/large_futures.stderr b/tests/ui/large_futures.stderr index 00082e579c59..fd6ba4e3563d 100644 --- a/tests/ui/large_futures.stderr +++ b/tests/ui/large_futures.stderr @@ -8,13 +8,13 @@ LL | big_fut([0u8; 1024 * 16]).await; = help: to override `-D warnings` add `#[allow(clippy::large_futures)]` error: large future with a size of 16386 bytes - --> tests/ui/large_futures.rs:14:5 + --> tests/ui/large_futures.rs:13:5 | LL | f.await | ^ help: consider `Box::pin` on it: `Box::pin(f)` error: large future with a size of 16387 bytes - --> tests/ui/large_futures.rs:19:9 + --> tests/ui/large_futures.rs:18:9 | LL | wait().await; | ^^^^^^ help: consider `Box::pin` on it: `Box::pin(wait())` @@ -32,16 +32,17 @@ LL | foo().await; | ^^^^^ help: consider `Box::pin` on it: `Box::pin(foo())` error: large future with a size of 49159 bytes - --> tests/ui/large_futures.rs:34:5 + --> tests/ui/large_futures.rs:35:5 | LL | calls_fut(fut).await; | ^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(calls_fut(fut))` error: large future with a size of 65540 bytes - --> tests/ui/large_futures.rs:47:5 + --> tests/ui/large_futures.rs:48:5 | LL | / async { LL | | +LL | | LL | | let x = [0i32; 1024 * 16]; LL | | async {}.await; LL | | println!("{:?}", x); @@ -52,6 +53,7 @@ help: consider `Box::pin` on it | LL ~ Box::pin(async { LL + +LL + LL + let x = [0i32; 1024 * 16]; LL + async {}.await; LL + println!("{:?}", x); @@ -59,9 +61,10 @@ LL + }) | error: large future with a size of 65540 bytes - --> tests/ui/large_futures.rs:59:13 + --> tests/ui/large_futures.rs:61:13 | LL | / async { +LL | | LL | | let x = [0i32; 1024 * 16]; LL | | async {}.await; LL | | println!("macro: {:?}", x); @@ -75,6 +78,7 @@ LL | macro_!().await help: consider `Box::pin` on it | LL ~ Box::pin(async { +LL + LL + let x = [0i32; 1024 * 16]; LL + async {}.await; LL + println!("macro: {:?}", x); diff --git a/tests/ui/large_stack_frames.rs b/tests/ui/large_stack_frames.rs index e6c030b8a9e8..3ed124f69ef3 100644 --- a/tests/ui/large_stack_frames.rs +++ b/tests/ui/large_stack_frames.rs @@ -25,7 +25,8 @@ impl Default for ArrayDefault { } fn many_small_arrays() { - //~^ ERROR: this function may allocate + //~^ large_stack_frames + let x = [0u8; 500_000]; let x2 = [0u8; 500_000]; let x3 = [0u8; 500_000]; @@ -35,18 +36,21 @@ fn many_small_arrays() { } fn large_return_value() -> ArrayDefault<1_000_000> { - //~^ ERROR: this function may allocate 1000000 bytes on the stack + //~^ large_stack_frames + Default::default() } fn large_fn_arg(x: ArrayDefault<1_000_000>) { - //~^ ERROR: this function may allocate + //~^ large_stack_frames + black_box(&x); } fn has_large_closure() { let f = || black_box(&[0u8; 1_000_000]); - //~^ ERROR: this function may allocate + //~^ large_stack_frames + f(); } diff --git a/tests/ui/large_stack_frames.stderr b/tests/ui/large_stack_frames.stderr index f2e0a127f5f5..0ff49e9f5b37 100644 --- a/tests/ui/large_stack_frames.stderr +++ b/tests/ui/large_stack_frames.stderr @@ -13,7 +13,7 @@ LL | let x5 = [0u8; 500_000]; = help: to override `-D warnings` add `#[allow(clippy::large_stack_frames)]` error: this function may allocate 1000000 bytes on the stack - --> tests/ui/large_stack_frames.rs:37:4 + --> tests/ui/large_stack_frames.rs:38:4 | LL | fn large_return_value() -> ArrayDefault<1_000_000> { | ^^^^^^^^^^^^^^^^^^ ----------------------- this is the largest part, at 1000000 bytes for type `ArrayDefault<1000000>` @@ -21,7 +21,7 @@ LL | fn large_return_value() -> ArrayDefault<1_000_000> { = note: 1000000 bytes is larger than Clippy's configured `stack-size-threshold` of 512000 error: this function may allocate 100$PTR bytes on the stack - --> tests/ui/large_stack_frames.rs:42:4 + --> tests/ui/large_stack_frames.rs:44:4 | LL | fn large_fn_arg(x: ArrayDefault<1_000_000>) { | ^^^^^^^^^^^^ - `x` is the largest part, at 1000000 bytes for type `ArrayDefault<1000000>` @@ -29,7 +29,7 @@ LL | fn large_fn_arg(x: ArrayDefault<1_000_000>) { = note: 100$PTR bytes is larger than Clippy's configured `stack-size-threshold` of 512000 error: this function may allocate 100$PTR bytes on the stack - --> tests/ui/large_stack_frames.rs:48:13 + --> tests/ui/large_stack_frames.rs:51:13 | LL | let f = || black_box(&[0u8; 1_000_000]); | ^^^^^^^^^^^^^^----------------^ diff --git a/tests/ui/large_types_passed_by_value.rs b/tests/ui/large_types_passed_by_value.rs index 78994a2988a2..562a46306e06 100644 --- a/tests/ui/large_types_passed_by_value.rs +++ b/tests/ui/large_types_passed_by_value.rs @@ -18,19 +18,25 @@ fn not_copy(a: Large) {} fn by_ref(a: &Large, b: &LargeAndCopy) {} fn mutable(mut a: LargeAndCopy) {} fn bad(a: LargeAndCopy) {} +//~^ large_types_passed_by_value pub fn bad_but_pub(a: LargeAndCopy) {} impl LargeAndCopy { fn self_is_ok(self) {} fn other_is_not_ok(self, other: LargeAndCopy) {} + //~^ large_types_passed_by_value fn unless_other_can_change(self, mut other: LargeAndCopy) {} pub fn or_were_in_public(self, other: LargeAndCopy) {} } trait LargeTypeDevourer { fn devoure_array(&self, array: [u8; 6666]); + //~^ large_types_passed_by_value fn devoure_tuple(&self, tup: (LargeAndCopy, LargeAndCopy)); + //~^ large_types_passed_by_value fn devoure_array_and_tuple_wow(&self, array: [u8; 6666], tup: (LargeAndCopy, LargeAndCopy)); + //~^ large_types_passed_by_value + //~| large_types_passed_by_value } pub trait PubLargeTypeDevourer { @@ -56,10 +62,12 @@ fn foo_always(x: LargeAndCopy) { } #[inline(never)] fn foo_never(x: LargeAndCopy) { + //~^ large_types_passed_by_value todo!(); } #[inline] fn foo(x: LargeAndCopy) { + //~^ large_types_passed_by_value todo!(); } diff --git a/tests/ui/large_types_passed_by_value.stderr b/tests/ui/large_types_passed_by_value.stderr index 5b42ab9e02ac..0ad68bc326e0 100644 --- a/tests/ui/large_types_passed_by_value.stderr +++ b/tests/ui/large_types_passed_by_value.stderr @@ -8,43 +8,43 @@ LL | fn bad(a: LargeAndCopy) {} = help: to override `-D warnings` add `#[allow(clippy::large_types_passed_by_value)]` error: this argument (N byte) is passed by value, but might be more efficient if passed by reference (limit: N byte) - --> tests/ui/large_types_passed_by_value.rs:25:37 + --> tests/ui/large_types_passed_by_value.rs:26:37 | LL | fn other_is_not_ok(self, other: LargeAndCopy) {} | ^^^^^^^^^^^^ help: consider passing by reference instead: `&LargeAndCopy` error: this argument (N byte) is passed by value, but might be more efficient if passed by reference (limit: N byte) - --> tests/ui/large_types_passed_by_value.rs:31:36 + --> tests/ui/large_types_passed_by_value.rs:33:36 | LL | fn devoure_array(&self, array: [u8; 6666]); | ^^^^^^^^^^ help: consider passing by reference instead: `&[u8; 6666]` error: this argument (N byte) is passed by value, but might be more efficient if passed by reference (limit: N byte) - --> tests/ui/large_types_passed_by_value.rs:32:34 + --> tests/ui/large_types_passed_by_value.rs:35:34 | LL | fn devoure_tuple(&self, tup: (LargeAndCopy, LargeAndCopy)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider passing by reference instead: `&(LargeAndCopy, LargeAndCopy)` error: this argument (N byte) is passed by value, but might be more efficient if passed by reference (limit: N byte) - --> tests/ui/large_types_passed_by_value.rs:33:50 + --> tests/ui/large_types_passed_by_value.rs:37:50 | LL | fn devoure_array_and_tuple_wow(&self, array: [u8; 6666], tup: (LargeAndCopy, LargeAndCopy)); | ^^^^^^^^^^ help: consider passing by reference instead: `&[u8; 6666]` error: this argument (N byte) is passed by value, but might be more efficient if passed by reference (limit: N byte) - --> tests/ui/large_types_passed_by_value.rs:33:67 + --> tests/ui/large_types_passed_by_value.rs:37:67 | LL | fn devoure_array_and_tuple_wow(&self, array: [u8; 6666], tup: (LargeAndCopy, LargeAndCopy)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider passing by reference instead: `&(LargeAndCopy, LargeAndCopy)` error: this argument (N byte) is passed by value, but might be more efficient if passed by reference (limit: N byte) - --> tests/ui/large_types_passed_by_value.rs:58:17 + --> tests/ui/large_types_passed_by_value.rs:64:17 | LL | fn foo_never(x: LargeAndCopy) { | ^^^^^^^^^^^^ help: consider passing by reference instead: `&LargeAndCopy` error: this argument (N byte) is passed by value, but might be more efficient if passed by reference (limit: N byte) - --> tests/ui/large_types_passed_by_value.rs:62:11 + --> tests/ui/large_types_passed_by_value.rs:69:11 | LL | fn foo(x: LargeAndCopy) { | ^^^^^^^^^^^^ help: consider passing by reference instead: `&LargeAndCopy` diff --git a/tests/ui/legacy_numeric_constants.fixed b/tests/ui/legacy_numeric_constants.fixed index 3a2294ef4c59..30bb549a9d65 100644 --- a/tests/ui/legacy_numeric_constants.fixed +++ b/tests/ui/legacy_numeric_constants.fixed @@ -1,4 +1,5 @@ //@aux-build:proc_macros.rs +//@require-annotations-for-level: WARN #![allow(clippy::no_effect, deprecated, unused)] #![allow(clippy::legacy_numeric_constants)] // For imports. diff --git a/tests/ui/legacy_numeric_constants.rs b/tests/ui/legacy_numeric_constants.rs index 6cb3e694ea14..d3878199055f 100644 --- a/tests/ui/legacy_numeric_constants.rs +++ b/tests/ui/legacy_numeric_constants.rs @@ -1,4 +1,5 @@ //@aux-build:proc_macros.rs +//@require-annotations-for-level: WARN #![allow(clippy::no_effect, deprecated, unused)] #![allow(clippy::legacy_numeric_constants)] // For imports. diff --git a/tests/ui/legacy_numeric_constants.stderr b/tests/ui/legacy_numeric_constants.stderr index 91dfe79d55ba..4d69b8165a34 100644 --- a/tests/ui/legacy_numeric_constants.stderr +++ b/tests/ui/legacy_numeric_constants.stderr @@ -1,5 +1,5 @@ error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:31:5 + --> tests/ui/legacy_numeric_constants.rs:32:5 | LL | std::f32::EPSILON; | ^^^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL + f32::EPSILON; | error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:34:5 + --> tests/ui/legacy_numeric_constants.rs:35:5 | LL | std::u8::MIN; | ^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + u8::MIN; | error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:37:5 + --> tests/ui/legacy_numeric_constants.rs:38:5 | LL | std::usize::MIN; | ^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + usize::MIN; | error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:40:5 + --> tests/ui/legacy_numeric_constants.rs:41:5 | LL | std::u32::MAX; | ^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + u32::MAX; | error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:43:5 + --> tests/ui/legacy_numeric_constants.rs:44:5 | LL | core::u32::MAX; | ^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + u32::MAX; | error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:46:5 + --> tests/ui/legacy_numeric_constants.rs:47:5 | LL | MAX; | ^^^ @@ -72,7 +72,7 @@ LL | u32::MAX; | +++++ error: usage of a legacy numeric method - --> tests/ui/legacy_numeric_constants.rs:49:10 + --> tests/ui/legacy_numeric_constants.rs:50:10 | LL | i32::max_value(); | ^^^^^^^^^^^ @@ -84,7 +84,7 @@ LL + i32::MAX; | error: usage of a legacy numeric method - --> tests/ui/legacy_numeric_constants.rs:52:9 + --> tests/ui/legacy_numeric_constants.rs:53:9 | LL | u8::max_value(); | ^^^^^^^^^^^ @@ -96,7 +96,7 @@ LL + u8::MAX; | error: usage of a legacy numeric method - --> tests/ui/legacy_numeric_constants.rs:55:9 + --> tests/ui/legacy_numeric_constants.rs:56:9 | LL | u8::min_value(); | ^^^^^^^^^^^ @@ -108,7 +108,7 @@ LL + u8::MIN; | error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:58:5 + --> tests/ui/legacy_numeric_constants.rs:59:5 | LL | ::std::u8::MIN; | ^^^^^^^^^^^^^^ @@ -120,7 +120,7 @@ LL + u8::MIN; | error: usage of a legacy numeric method - --> tests/ui/legacy_numeric_constants.rs:61:27 + --> tests/ui/legacy_numeric_constants.rs:62:27 | LL | ::std::primitive::u8::min_value(); | ^^^^^^^^^^^ @@ -132,7 +132,7 @@ LL + ::std::primitive::u8::MIN; | error: usage of a legacy numeric method - --> tests/ui/legacy_numeric_constants.rs:64:26 + --> tests/ui/legacy_numeric_constants.rs:65:26 | LL | std::primitive::i32::max_value(); | ^^^^^^^^^^^ @@ -144,7 +144,7 @@ LL + std::primitive::i32::MAX; | error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:67:5 + --> tests/ui/legacy_numeric_constants.rs:68:5 | LL | self::a::u128::MAX; | ^^^^^^^^^^^^^^^^^^ @@ -156,7 +156,7 @@ LL + u128::MAX; | error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:17:25 + --> tests/ui/legacy_numeric_constants.rs:18:25 | LL | let x = std::u64::MAX; | ^^^^^^^^^^^^^ @@ -172,7 +172,7 @@ LL + let x = u64::MAX; | error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:81:14 + --> tests/ui/legacy_numeric_constants.rs:82:14 | LL | [(0, "", std::i128::MAX)]; | ^^^^^^^^^^^^^^ @@ -184,7 +184,7 @@ LL + [(0, "", i128::MAX)]; | error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:115:5 + --> tests/ui/legacy_numeric_constants.rs:116:5 | LL | std::u32::MAX; | ^^^^^^^^^^^^^ diff --git a/tests/ui/legacy_numeric_constants_unfixable.rs b/tests/ui/legacy_numeric_constants_unfixable.rs index 86738ede210c..9bf0f7f355ae 100644 --- a/tests/ui/legacy_numeric_constants_unfixable.rs +++ b/tests/ui/legacy_numeric_constants_unfixable.rs @@ -1,4 +1,5 @@ //@no-rustfix +//@require-annotations-for-level: WARN //@aux-build:proc_macros.rs #![allow(clippy::no_effect, deprecated, unused)] #![warn(clippy::legacy_numeric_constants)] diff --git a/tests/ui/legacy_numeric_constants_unfixable.stderr b/tests/ui/legacy_numeric_constants_unfixable.stderr index 2edcf7188362..96e6c9ef9759 100644 --- a/tests/ui/legacy_numeric_constants_unfixable.stderr +++ b/tests/ui/legacy_numeric_constants_unfixable.stderr @@ -1,5 +1,5 @@ error: importing legacy numeric constants - --> tests/ui/legacy_numeric_constants_unfixable.rs:9:5 + --> tests/ui/legacy_numeric_constants_unfixable.rs:10:5 | LL | use std::u128 as _; | ^^^^^^^^^ @@ -9,7 +9,7 @@ LL | use std::u128 as _; = help: to override `-D warnings` add `#[allow(clippy::legacy_numeric_constants)]` error: importing legacy numeric constants - --> tests/ui/legacy_numeric_constants_unfixable.rs:13:24 + --> tests/ui/legacy_numeric_constants_unfixable.rs:14:24 | LL | pub use std::{mem, u128}; | ^^^^ @@ -18,7 +18,7 @@ LL | pub use std::{mem, u128}; = note: then `u128::` will resolve to the respective associated constant error: importing a legacy numeric constant - --> tests/ui/legacy_numeric_constants_unfixable.rs:29:9 + --> tests/ui/legacy_numeric_constants_unfixable.rs:30:9 | LL | use std::u32::MAX; | ^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | use std::u32::MAX; = help: remove this import and use the associated constant `u32::MAX` from the primitive type instead error: importing a legacy numeric constant - --> tests/ui/legacy_numeric_constants_unfixable.rs:32:9 + --> tests/ui/legacy_numeric_constants_unfixable.rs:33:9 | LL | use std::u8::MIN; | ^^^^^^^^^^^^ @@ -34,7 +34,7 @@ LL | use std::u8::MIN; = help: remove this import and use the associated constant `u8::MIN` from the primitive type instead error: importing legacy numeric constants - --> tests/ui/legacy_numeric_constants_unfixable.rs:36:9 + --> tests/ui/legacy_numeric_constants_unfixable.rs:37:9 | LL | use std::u32; | ^^^^^^^^ @@ -43,7 +43,7 @@ LL | use std::u32; = note: then `u32::` will resolve to the respective associated constant error: importing a legacy numeric constant - --> tests/ui/legacy_numeric_constants_unfixable.rs:40:9 + --> tests/ui/legacy_numeric_constants_unfixable.rs:41:9 | LL | use std::f32::MIN_POSITIVE; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -51,7 +51,7 @@ LL | use std::f32::MIN_POSITIVE; = help: remove this import and use the associated constant `f32::MIN_POSITIVE` from the primitive type instead error: importing legacy numeric constants - --> tests/ui/legacy_numeric_constants_unfixable.rs:44:9 + --> tests/ui/legacy_numeric_constants_unfixable.rs:45:9 | LL | use std::i16::*; | ^^^^^^^^ @@ -59,7 +59,7 @@ LL | use std::i16::*; = help: remove this import and use associated constants `i16::` from the primitive type instead error: importing legacy numeric constants - --> tests/ui/legacy_numeric_constants_unfixable.rs:21:17 + --> tests/ui/legacy_numeric_constants_unfixable.rs:22:17 | LL | use std::u32; | ^^^^^^^^ @@ -72,7 +72,7 @@ LL | b!(); = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) error: importing a legacy numeric constant - --> tests/ui/legacy_numeric_constants_unfixable.rs:76:9 + --> tests/ui/legacy_numeric_constants_unfixable.rs:77:9 | LL | use std::u32::MAX; | ^^^^^^^^^^^^^ diff --git a/tests/ui/len_without_is_empty.rs b/tests/ui/len_without_is_empty.rs index d623601110e2..011833072d76 100644 --- a/tests/ui/len_without_is_empty.rs +++ b/tests/ui/len_without_is_empty.rs @@ -5,8 +5,8 @@ pub struct PubOne; impl PubOne { pub fn len(&self) -> isize { - //~^ ERROR: struct `PubOne` has a public `len` method, but no `is_empty` method - //~| NOTE: `-D clippy::len-without-is-empty` implied by `-D warnings` + //~^ len_without_is_empty + 1 } } @@ -55,7 +55,8 @@ impl PubAllowedStruct { } pub trait PubTraitsToo { - //~^ ERROR: trait `PubTraitsToo` has a `len` method but no (possibly inherited) `is_empty` + //~^ len_without_is_empty + fn len(&self) -> isize; } @@ -69,7 +70,8 @@ pub struct HasIsEmpty; impl HasIsEmpty { pub fn len(&self) -> isize { - //~^ ERROR: struct `HasIsEmpty` has a public `len` method, but a private `is_empty` me + //~^ len_without_is_empty + 1 } @@ -82,7 +84,8 @@ pub struct HasWrongIsEmpty; impl HasWrongIsEmpty { pub fn len(&self) -> isize { - //~^ ERROR: struct `HasWrongIsEmpty` has a public `len` method, but the `is_empty` met + //~^ len_without_is_empty + 1 } @@ -95,7 +98,8 @@ pub struct MismatchedSelf; impl MismatchedSelf { pub fn len(self) -> isize { - //~^ ERROR: struct `MismatchedSelf` has a public `len` method, but the `is_empty` meth + //~^ len_without_is_empty + 1 } @@ -175,7 +179,8 @@ pub trait InheritingEmpty: Empty { pub trait Foo: Sized {} pub trait DependsOnFoo: Foo { - //~^ ERROR: trait `DependsOnFoo` has a `len` method but no (possibly inherited) `is_empty` + //~^ len_without_is_empty + fn len(&mut self) -> usize; } @@ -221,7 +226,8 @@ impl OptionalLen2 { pub struct OptionalLen3; impl OptionalLen3 { pub fn len(&self) -> usize { - //~^ ERROR: struct `OptionalLen3` has a public `len` method, but the `is_empty` method + //~^ len_without_is_empty + 0 } @@ -234,8 +240,9 @@ impl OptionalLen3 { pub struct ResultLen; impl ResultLen { pub fn len(&self) -> Result { - //~^ ERROR: struct `ResultLen` has a public `len` method, but the `is_empty` method ha - //~| ERROR: this returns a `Result<_, ()>` + //~^ len_without_is_empty + //~| result_unit_err + Ok(0) } @@ -248,12 +255,14 @@ impl ResultLen { pub struct ResultLen2; impl ResultLen2 { pub fn len(&self) -> Result { - //~^ ERROR: this returns a `Result<_, ()>` + //~^ result_unit_err + Ok(0) } pub fn is_empty(&self) -> Result { - //~^ ERROR: this returns a `Result<_, ()>` + //~^ result_unit_err + Ok(true) } } @@ -261,7 +270,8 @@ impl ResultLen2 { pub struct ResultLen3; impl ResultLen3 { pub fn len(&self) -> Result { - //~^ ERROR: this returns a `Result<_, ()>` + //~^ result_unit_err + Ok(0) } @@ -303,7 +313,8 @@ impl AsyncLenWithoutIsEmpty { } pub async fn len(&self) -> usize { - //~^ ERROR: struct `AsyncLenWithoutIsEmpty` has a public `len` method, but no `is_empt + //~^ len_without_is_empty + usize::from(!self.async_task().await) } } @@ -316,7 +327,8 @@ impl AsyncOptionLenWithoutIsEmpty { } pub async fn len(&self) -> Option { - //~^ ERROR: struct `AsyncOptionLenWithoutIsEmpty` has a public `len` method, but no `i + //~^ len_without_is_empty + None } } @@ -338,7 +350,8 @@ impl AsyncResultLenWithoutIsEmpty { } pub async fn len(&self) -> Result { - //~^ ERROR: struct `AsyncResultLenWithoutIsEmpty` has a public `len` method, but no `i + //~^ len_without_is_empty + Err(()) } } @@ -454,7 +467,8 @@ pub struct Aliased2; pub type Alias2 = Aliased2; impl Alias2 { pub fn len(&self) -> usize { - //~^ ERROR: type `Alias2` has a public `len` method, but no `is_empty` method + //~^ len_without_is_empty + todo!() } } diff --git a/tests/ui/len_without_is_empty.stderr b/tests/ui/len_without_is_empty.stderr index 11d0d855fc0b..748a55712f88 100644 --- a/tests/ui/len_without_is_empty.stderr +++ b/tests/ui/len_without_is_empty.stderr @@ -12,85 +12,87 @@ error: trait `PubTraitsToo` has a `len` method but no (possibly inherited) `is_e | LL | / pub trait PubTraitsToo { LL | | +LL | | LL | | fn len(&self) -> isize; LL | | } | |_^ error: struct `HasIsEmpty` has a public `len` method, but a private `is_empty` method - --> tests/ui/len_without_is_empty.rs:71:5 + --> tests/ui/len_without_is_empty.rs:72:5 | LL | pub fn len(&self) -> isize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `is_empty` defined here - --> tests/ui/len_without_is_empty.rs:76:5 + --> tests/ui/len_without_is_empty.rs:78:5 | LL | fn is_empty(&self) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: struct `HasWrongIsEmpty` has a public `len` method, but the `is_empty` method has an unexpected signature - --> tests/ui/len_without_is_empty.rs:84:5 + --> tests/ui/len_without_is_empty.rs:86:5 | LL | pub fn len(&self) -> isize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `is_empty` defined here - --> tests/ui/len_without_is_empty.rs:89:5 + --> tests/ui/len_without_is_empty.rs:92:5 | LL | pub fn is_empty(&self, x: u32) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: expected signature: `(&self) -> bool` error: struct `MismatchedSelf` has a public `len` method, but the `is_empty` method has an unexpected signature - --> tests/ui/len_without_is_empty.rs:97:5 + --> tests/ui/len_without_is_empty.rs:100:5 | LL | pub fn len(self) -> isize { | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `is_empty` defined here - --> tests/ui/len_without_is_empty.rs:102:5 + --> tests/ui/len_without_is_empty.rs:106:5 | LL | pub fn is_empty(&self) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: expected signature: `(self) -> bool` error: trait `DependsOnFoo` has a `len` method but no (possibly inherited) `is_empty` method - --> tests/ui/len_without_is_empty.rs:177:1 + --> tests/ui/len_without_is_empty.rs:181:1 | LL | / pub trait DependsOnFoo: Foo { LL | | +LL | | LL | | fn len(&mut self) -> usize; LL | | } | |_^ error: struct `OptionalLen3` has a public `len` method, but the `is_empty` method has an unexpected signature - --> tests/ui/len_without_is_empty.rs:223:5 + --> tests/ui/len_without_is_empty.rs:228:5 | LL | pub fn len(&self) -> usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `is_empty` defined here - --> tests/ui/len_without_is_empty.rs:229:5 + --> tests/ui/len_without_is_empty.rs:235:5 | LL | pub fn is_empty(&self) -> Option { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: expected signature: `(&self) -> bool` error: struct `ResultLen` has a public `len` method, but the `is_empty` method has an unexpected signature - --> tests/ui/len_without_is_empty.rs:236:5 + --> tests/ui/len_without_is_empty.rs:242:5 | LL | pub fn len(&self) -> Result { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `is_empty` defined here - --> tests/ui/len_without_is_empty.rs:243:5 + --> tests/ui/len_without_is_empty.rs:250:5 | LL | pub fn is_empty(&self) -> Option { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: expected signature: `(&self) -> bool` or `(&self) -> Result error: this returns a `Result<_, ()>` - --> tests/ui/len_without_is_empty.rs:236:5 + --> tests/ui/len_without_is_empty.rs:242:5 | LL | pub fn len(&self) -> Result { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -100,7 +102,7 @@ LL | pub fn len(&self) -> Result { = help: to override `-D warnings` add `#[allow(clippy::result_unit_err)]` error: this returns a `Result<_, ()>` - --> tests/ui/len_without_is_empty.rs:250:5 + --> tests/ui/len_without_is_empty.rs:257:5 | LL | pub fn len(&self) -> Result { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -108,7 +110,7 @@ LL | pub fn len(&self) -> Result { = help: use a custom `Error` type instead error: this returns a `Result<_, ()>` - --> tests/ui/len_without_is_empty.rs:255:5 + --> tests/ui/len_without_is_empty.rs:263:5 | LL | pub fn is_empty(&self) -> Result { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -116,7 +118,7 @@ LL | pub fn is_empty(&self) -> Result { = help: use a custom `Error` type instead error: this returns a `Result<_, ()>` - --> tests/ui/len_without_is_empty.rs:263:5 + --> tests/ui/len_without_is_empty.rs:272:5 | LL | pub fn len(&self) -> Result { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -124,25 +126,25 @@ LL | pub fn len(&self) -> Result { = help: use a custom `Error` type instead error: struct `AsyncLenWithoutIsEmpty` has a public `len` method, but no `is_empty` method - --> tests/ui/len_without_is_empty.rs:305:5 + --> tests/ui/len_without_is_empty.rs:315:5 | LL | pub async fn len(&self) -> usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: struct `AsyncOptionLenWithoutIsEmpty` has a public `len` method, but no `is_empty` method - --> tests/ui/len_without_is_empty.rs:318:5 + --> tests/ui/len_without_is_empty.rs:329:5 | LL | pub async fn len(&self) -> Option { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: struct `AsyncResultLenWithoutIsEmpty` has a public `len` method, but no `is_empty` method - --> tests/ui/len_without_is_empty.rs:340:5 + --> tests/ui/len_without_is_empty.rs:352:5 | LL | pub async fn len(&self) -> Result { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `Alias2` has a public `len` method, but no `is_empty` method - --> tests/ui/len_without_is_empty.rs:456:5 + --> tests/ui/len_without_is_empty.rs:469:5 | LL | pub fn len(&self) -> usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/len_zero.fixed b/tests/ui/len_zero.fixed index c9c476ba4214..b8573ef13b0e 100644 --- a/tests/ui/len_zero.fixed +++ b/tests/ui/len_zero.fixed @@ -86,10 +86,12 @@ impl Deref for DerefToString { fn main() { let x = [1, 2]; if x.is_empty() { + //~^ len_zero println!("This should not happen!"); } if "".is_empty() {} + //~^ len_zero let s = "Hello, world!"; let s1 = &s; @@ -99,16 +101,24 @@ fn main() { let s5 = &s4; let s6 = &s5; println!("{}", s1.is_empty()); + //~^ comparison_to_empty println!("{}", s2.is_empty()); + //~^ comparison_to_empty println!("{}", s3.is_empty()); + //~^ comparison_to_empty println!("{}", s4.is_empty()); + //~^ comparison_to_empty println!("{}", s5.is_empty()); + //~^ comparison_to_empty println!("{}", (s6).is_empty()); + //~^ comparison_to_empty let d2s = DerefToDerefToString {}; println!("{}", (**d2s).is_empty()); + //~^ comparison_to_empty println!("{}", std::borrow::Cow::Borrowed("").is_empty()); + //~^ comparison_to_empty let y = One; if y.len() == 0 { @@ -124,18 +134,23 @@ fn main() { let has_is_empty = HasIsEmpty; if has_is_empty.is_empty() { + //~^ len_zero println!("Or this!"); } if !has_is_empty.is_empty() { + //~^ len_zero println!("Or this!"); } if !has_is_empty.is_empty() { + //~^ len_zero println!("Or this!"); } if has_is_empty.is_empty() { + //~^ len_zero println!("Or this!"); } if !has_is_empty.is_empty() { + //~^ len_zero println!("Or this!"); } if has_is_empty.len() > 1 { @@ -147,18 +162,23 @@ fn main() { println!("This can happen."); } if has_is_empty.is_empty() { + //~^ len_zero println!("Or this!"); } if !has_is_empty.is_empty() { + //~^ len_zero println!("Or this!"); } if !has_is_empty.is_empty() { + //~^ len_zero println!("Or this!"); } if !has_is_empty.is_empty() { + //~^ len_zero println!("Or this!"); } if has_is_empty.is_empty() { + //~^ len_zero println!("Or this!"); } if 1 < has_is_empty.len() { @@ -173,6 +193,7 @@ fn main() { let with_is_empty: &dyn WithIsEmpty = &Wither; if with_is_empty.is_empty() { + //~^ len_zero println!("Or this!"); } assert!(!with_is_empty.is_empty()); @@ -185,11 +206,14 @@ fn main() { // issue #10529 (!has_is_empty.is_empty()).then(|| println!("This can happen.")); + //~^ len_zero (has_is_empty.is_empty()).then(|| println!("Or this!")); + //~^ len_zero } fn test_slice(b: &[u8]) { if !b.is_empty() {} + //~^ len_zero } // issue #11992 @@ -224,9 +248,12 @@ fn binop_with_macros() { if has_is_empty.len() == compare_to!(1) {} if has_is_empty.is_empty() {} + //~^ len_zero if has_is_empty.is_empty() {} + //~^ len_zero (!has_is_empty.is_empty()).then(|| println!("This can happen.")); + //~^ len_zero } fn no_infinite_recursion() -> bool { diff --git a/tests/ui/len_zero.rs b/tests/ui/len_zero.rs index 610a5448d10e..ef3c49c1ab30 100644 --- a/tests/ui/len_zero.rs +++ b/tests/ui/len_zero.rs @@ -86,10 +86,12 @@ impl Deref for DerefToString { fn main() { let x = [1, 2]; if x.len() == 0 { + //~^ len_zero println!("This should not happen!"); } if "".len() == 0 {} + //~^ len_zero let s = "Hello, world!"; let s1 = &s; @@ -99,16 +101,24 @@ fn main() { let s5 = &s4; let s6 = &s5; println!("{}", *s1 == ""); + //~^ comparison_to_empty println!("{}", **s2 == ""); + //~^ comparison_to_empty println!("{}", ***s3 == ""); + //~^ comparison_to_empty println!("{}", ****s4 == ""); + //~^ comparison_to_empty println!("{}", *****s5 == ""); + //~^ comparison_to_empty println!("{}", ******(s6) == ""); + //~^ comparison_to_empty let d2s = DerefToDerefToString {}; println!("{}", &**d2s == ""); + //~^ comparison_to_empty println!("{}", std::borrow::Cow::Borrowed("") == ""); + //~^ comparison_to_empty let y = One; if y.len() == 0 { @@ -124,18 +134,23 @@ fn main() { let has_is_empty = HasIsEmpty; if has_is_empty.len() == 0 { + //~^ len_zero println!("Or this!"); } if has_is_empty.len() != 0 { + //~^ len_zero println!("Or this!"); } if has_is_empty.len() > 0 { + //~^ len_zero println!("Or this!"); } if has_is_empty.len() < 1 { + //~^ len_zero println!("Or this!"); } if has_is_empty.len() >= 1 { + //~^ len_zero println!("Or this!"); } if has_is_empty.len() > 1 { @@ -147,18 +162,23 @@ fn main() { println!("This can happen."); } if 0 == has_is_empty.len() { + //~^ len_zero println!("Or this!"); } if 0 != has_is_empty.len() { + //~^ len_zero println!("Or this!"); } if 0 < has_is_empty.len() { + //~^ len_zero println!("Or this!"); } if 1 <= has_is_empty.len() { + //~^ len_zero println!("Or this!"); } if 1 > has_is_empty.len() { + //~^ len_zero println!("Or this!"); } if 1 < has_is_empty.len() { @@ -173,6 +193,7 @@ fn main() { let with_is_empty: &dyn WithIsEmpty = &Wither; if with_is_empty.len() == 0 { + //~^ len_zero println!("Or this!"); } assert!(!with_is_empty.is_empty()); @@ -185,11 +206,14 @@ fn main() { // issue #10529 (has_is_empty.len() > 0).then(|| println!("This can happen.")); + //~^ len_zero (has_is_empty.len() == 0).then(|| println!("Or this!")); + //~^ len_zero } fn test_slice(b: &[u8]) { if b.len() != 0 {} + //~^ len_zero } // issue #11992 @@ -224,9 +248,12 @@ fn binop_with_macros() { if has_is_empty.len() == compare_to!(1) {} if has_is_empty.len() == compare_to!(0) {} + //~^ len_zero if has_is_empty.len() == zero!() {} + //~^ len_zero (compare_to!(0) < has_is_empty.len()).then(|| println!("This can happen.")); + //~^ len_zero } fn no_infinite_recursion() -> bool { diff --git a/tests/ui/len_zero.stderr b/tests/ui/len_zero.stderr index 8d6b57e4b6d4..25052f39ad33 100644 --- a/tests/ui/len_zero.stderr +++ b/tests/ui/len_zero.stderr @@ -8,13 +8,13 @@ LL | if x.len() == 0 { = help: to override `-D warnings` add `#[allow(clippy::len_zero)]` error: length comparison to zero - --> tests/ui/len_zero.rs:92:8 + --> tests/ui/len_zero.rs:93:8 | LL | if "".len() == 0 {} | ^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `"".is_empty()` error: comparison to empty slice - --> tests/ui/len_zero.rs:101:20 + --> tests/ui/len_zero.rs:103:20 | LL | println!("{}", *s1 == ""); | ^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s1.is_empty()` @@ -23,145 +23,145 @@ LL | println!("{}", *s1 == ""); = help: to override `-D warnings` add `#[allow(clippy::comparison_to_empty)]` error: comparison to empty slice - --> tests/ui/len_zero.rs:102:20 + --> tests/ui/len_zero.rs:105:20 | LL | println!("{}", **s2 == ""); | ^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s2.is_empty()` error: comparison to empty slice - --> tests/ui/len_zero.rs:103:20 + --> tests/ui/len_zero.rs:107:20 | LL | println!("{}", ***s3 == ""); | ^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s3.is_empty()` error: comparison to empty slice - --> tests/ui/len_zero.rs:104:20 + --> tests/ui/len_zero.rs:109:20 | LL | println!("{}", ****s4 == ""); | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s4.is_empty()` error: comparison to empty slice - --> tests/ui/len_zero.rs:105:20 + --> tests/ui/len_zero.rs:111:20 | LL | println!("{}", *****s5 == ""); | ^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s5.is_empty()` error: comparison to empty slice - --> tests/ui/len_zero.rs:106:20 + --> tests/ui/len_zero.rs:113:20 | LL | println!("{}", ******(s6) == ""); | ^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `(s6).is_empty()` error: comparison to empty slice - --> tests/ui/len_zero.rs:109:20 + --> tests/ui/len_zero.rs:117:20 | LL | println!("{}", &**d2s == ""); | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `(**d2s).is_empty()` error: comparison to empty slice - --> tests/ui/len_zero.rs:111:20 + --> tests/ui/len_zero.rs:120:20 | LL | println!("{}", std::borrow::Cow::Borrowed("") == ""); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `std::borrow::Cow::Borrowed("").is_empty()` error: length comparison to zero - --> tests/ui/len_zero.rs:126:8 + --> tests/ui/len_zero.rs:136:8 | LL | if has_is_empty.len() == 0 { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero - --> tests/ui/len_zero.rs:129:8 + --> tests/ui/len_zero.rs:140:8 | LL | if has_is_empty.len() != 0 { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero - --> tests/ui/len_zero.rs:132:8 + --> tests/ui/len_zero.rs:144:8 | LL | if has_is_empty.len() > 0 { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one - --> tests/ui/len_zero.rs:135:8 + --> tests/ui/len_zero.rs:148:8 | LL | if has_is_empty.len() < 1 { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to one - --> tests/ui/len_zero.rs:138:8 + --> tests/ui/len_zero.rs:152:8 | LL | if has_is_empty.len() >= 1 { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero - --> tests/ui/len_zero.rs:149:8 + --> tests/ui/len_zero.rs:164:8 | LL | if 0 == has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero - --> tests/ui/len_zero.rs:152:8 + --> tests/ui/len_zero.rs:168:8 | LL | if 0 != has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero - --> tests/ui/len_zero.rs:155:8 + --> tests/ui/len_zero.rs:172:8 | LL | if 0 < has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one - --> tests/ui/len_zero.rs:158:8 + --> tests/ui/len_zero.rs:176:8 | LL | if 1 <= has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one - --> tests/ui/len_zero.rs:161:8 + --> tests/ui/len_zero.rs:180:8 | LL | if 1 > has_is_empty.len() { | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero - --> tests/ui/len_zero.rs:175:8 + --> tests/ui/len_zero.rs:195:8 | LL | if with_is_empty.len() == 0 { | ^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `with_is_empty.is_empty()` error: length comparison to zero - --> tests/ui/len_zero.rs:187:6 + --> tests/ui/len_zero.rs:208:6 | LL | (has_is_empty.len() > 0).then(|| println!("This can happen.")); | ^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero - --> tests/ui/len_zero.rs:188:6 + --> tests/ui/len_zero.rs:210:6 | LL | (has_is_empty.len() == 0).then(|| println!("Or this!")); | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero - --> tests/ui/len_zero.rs:192:8 + --> tests/ui/len_zero.rs:215:8 | LL | if b.len() != 0 {} | ^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!b.is_empty()` error: length comparison to zero - --> tests/ui/len_zero.rs:226:8 + --> tests/ui/len_zero.rs:250:8 | LL | if has_is_empty.len() == compare_to!(0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero - --> tests/ui/len_zero.rs:227:8 + --> tests/ui/len_zero.rs:252:8 | LL | if has_is_empty.len() == zero!() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` error: length comparison to zero - --> tests/ui/len_zero.rs:229:6 + --> tests/ui/len_zero.rs:255:6 | LL | (compare_to!(0) < has_is_empty.len()).then(|| println!("This can happen.")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` diff --git a/tests/ui/len_zero_ranges.fixed b/tests/ui/len_zero_ranges.fixed index 1fdeb2c7a37b..d5b514d98113 100644 --- a/tests/ui/len_zero_ranges.fixed +++ b/tests/ui/len_zero_ranges.fixed @@ -5,10 +5,12 @@ mod issue_3807 { fn suggestion_is_fine_range() { let _ = (0..42).is_empty(); + //~^ len_zero } fn suggestion_is_fine_range_inclusive() { let _ = (0_u8..=42).is_empty(); + //~^ len_zero } } diff --git a/tests/ui/len_zero_ranges.rs b/tests/ui/len_zero_ranges.rs index a5c9a969aaa6..98c97ca02457 100644 --- a/tests/ui/len_zero_ranges.rs +++ b/tests/ui/len_zero_ranges.rs @@ -5,10 +5,12 @@ mod issue_3807 { fn suggestion_is_fine_range() { let _ = (0..42).len() == 0; + //~^ len_zero } fn suggestion_is_fine_range_inclusive() { let _ = (0_u8..=42).len() == 0; + //~^ len_zero } } diff --git a/tests/ui/len_zero_ranges.stderr b/tests/ui/len_zero_ranges.stderr index 0b2991e15ea3..10845bcade47 100644 --- a/tests/ui/len_zero_ranges.stderr +++ b/tests/ui/len_zero_ranges.stderr @@ -8,7 +8,7 @@ LL | let _ = (0..42).len() == 0; = help: to override `-D warnings` add `#[allow(clippy::len_zero)]` error: length comparison to zero - --> tests/ui/len_zero_ranges.rs:11:17 + --> tests/ui/len_zero_ranges.rs:12:17 | LL | let _ = (0_u8..=42).len() == 0; | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `(0_u8..=42).is_empty()` diff --git a/tests/ui/let_and_return.edition2021.fixed b/tests/ui/let_and_return.edition2021.fixed new file mode 100644 index 000000000000..70d503018e0f --- /dev/null +++ b/tests/ui/let_and_return.edition2021.fixed @@ -0,0 +1,264 @@ +//@revisions: edition2021 edition2024 +//@[edition2021] edition:2021 +//@[edition2024] edition:2024 + +#![allow(unused)] +#![warn(clippy::let_and_return)] + +use std::cell::RefCell; + +fn test() -> i32 { + let _y = 0; // no warning + + 5 + //~^ let_and_return +} + +fn test_inner() -> i32 { + if true { + + 5 + //~^ let_and_return + } else { + 0 + } +} + +fn test_nowarn_1() -> i32 { + let mut x = 5; + x += 1; + x +} + +fn test_nowarn_2() -> i32 { + let x = 5; + x + 1 +} + +fn test_nowarn_3() -> (i32, i32) { + // this should technically warn, but we do not compare complex patterns + let (x, y) = (5, 9); + (x, y) +} + +fn test_nowarn_4() -> i32 { + // this should technically warn, but not b/c of clippy::let_and_return, but b/c of useless type + let x: i32 = 5; + x +} + +fn test_nowarn_5(x: i16) -> u16 { + #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] + let x = x as u16; + x +} + +// False positive example +trait Decode { + fn decode(d: D) -> Result + where + Self: Sized; +} + +macro_rules! tuple_encode { + ($($x:ident),*) => ( + impl<$($x: Decode),*> Decode for ($($x),*) { + #[inline] + #[allow(non_snake_case)] + fn decode(mut d: D) -> Result { + // Shouldn't trigger lint + Ok(($({let $x = Decode::decode(&mut d)?; $x }),*)) + } + } + ); +} + +fn issue_3792() -> String { + use std::io::{self, BufRead, Stdin}; + + let stdin = io::stdin(); + // `Stdin::lock` returns `StdinLock<'static>` so `line` doesn't borrow from `stdin` + // https://github.com/rust-lang/rust/pull/93965 + + stdin.lock().lines().next().unwrap().unwrap() + //~^ let_and_return +} + +tuple_encode!(T0, T1, T2, T3, T4, T5, T6, T7); + +mod no_lint_if_stmt_borrows { + use std::cell::RefCell; + use std::rc::{Rc, Weak}; + struct Bar; + + impl Bar { + fn new() -> Self { + Bar {} + } + fn baz(&self) -> u32 { + 0 + } + } + + fn issue_3324(value: Weak>) -> u32 { + let value = value.upgrade().unwrap(); + let ret = value.borrow().baz(); + ret + //~[edition2024]^ let_and_return + } + + fn borrows_in_closure(value: Weak>) -> u32 { + fn f(mut x: impl FnMut() -> u32) -> impl FnMut() -> u32 { + x + } + + let value = value.upgrade().unwrap(); + let ret = f(|| value.borrow().baz())(); + ret + //~[edition2024]^ let_and_return + } + + mod free_function { + struct Inner; + + struct Foo<'a> { + inner: &'a Inner, + } + + impl Drop for Foo<'_> { + fn drop(&mut self) {} + } + + impl<'a> Foo<'a> { + fn new(inner: &'a Inner) -> Self { + Self { inner } + } + + fn value(&self) -> i32 { + 42 + } + } + + fn some_foo(inner: &Inner) -> Foo<'_> { + Foo { inner } + } + + fn test() -> i32 { + let x = Inner {}; + let value = some_foo(&x).value(); + value + //~[edition2024]^ let_and_return + } + + fn test2() -> i32 { + let x = Inner {}; + let value = Foo::new(&x).value(); + value + //~[edition2024]^ let_and_return + } + } +} + +mod issue_5729 { + use std::sync::Arc; + + trait Foo {} + + trait FooStorage { + fn foo_cloned(&self) -> Arc; + } + + struct FooStorageImpl { + foo: Arc, + } + + impl FooStorage for FooStorageImpl { + fn foo_cloned(&self) -> Arc { + + (Arc::clone(&self.foo)) as _ + //~^ let_and_return + } + } +} + +mod issue_11335 { + pub enum E { + A(T), + B(T), + } + + impl E { + pub fn inner(&self) -> &T { + + + (match self { + E::A(x) => x, + E::B(x) => x, + }) as _ + //~^ let_and_return + } + } +} + +// https://github.com/rust-lang/rust-clippy/issues/11167 +macro_rules! fn_in_macro { + ($b:block) => { + fn f() -> usize $b + } +} +fn_in_macro!({ + return 1; +}); + +fn issue9150() -> usize { + let x = 1; + #[cfg(any())] + panic!("can't see me"); + x +} + +fn issue12801() { + fn left_is_if() -> String { + + (if true { "a".to_string() } else { "b".to_string() } + "c") + //~^ let_and_return + } + + fn no_par_needed() -> String { + + "c".to_string() + if true { "a" } else { "b" } + //~^ let_and_return + } + + fn conjunctive_blocks() -> String { + + ({ "a".to_string() } + "b" + { "c" } + "d") + //~^ let_and_return + } + + #[allow(clippy::overly_complex_bool_expr)] + fn other_ops() { + let _ = || { + + (if true { 2 } else { 3 } << 4) + //~^ let_and_return + }; + let _ = || { + + ({ true } || { false } && { 2 <= 3 }) + //~^ let_and_return + }; + } +} + +fn issue14164() -> Result { + let v = std::cell::RefCell::new(Some(vec![1])); + let r = match &*v.borrow() { + Some(v) => Ok(Ok(v[0])), + None => Ok(Ok(0)), + }?; + r + //~[edition2024]^ let_and_return +} + +fn main() {} diff --git a/tests/ui/let_and_return.edition2021.stderr b/tests/ui/let_and_return.edition2021.stderr new file mode 100644 index 000000000000..f9536d1b5477 --- /dev/null +++ b/tests/ui/let_and_return.edition2021.stderr @@ -0,0 +1,152 @@ +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:13:5 + | +LL | let x = 5; + | ---------- unnecessary `let` binding +LL | x + | ^ + | + = note: `-D clippy::let-and-return` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::let_and_return)]` +help: return the expression directly + | +LL ~ +LL ~ 5 + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:20:9 + | +LL | let x = 5; + | ---------- unnecessary `let` binding +LL | x + | ^ + | +help: return the expression directly + | +LL ~ +LL ~ 5 + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:83:5 + | +LL | let line = stdin.lock().lines().next().unwrap().unwrap(); + | --------------------------------------------------------- unnecessary `let` binding +LL | line + | ^^^^ + | +help: return the expression directly + | +LL ~ +LL ~ stdin.lock().lines().next().unwrap().unwrap() + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:178:13 + | +LL | let clone = Arc::clone(&self.foo); + | ---------------------------------- unnecessary `let` binding +LL | clone + | ^^^^^ + | +help: return the expression directly + | +LL ~ +LL ~ (Arc::clone(&self.foo)) as _ + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:197:13 + | +LL | / let result = match self { +LL | | E::A(x) => x, +LL | | E::B(x) => x, +LL | | }; + | |______________- unnecessary `let` binding +LL | +LL | result + | ^^^^^^ + | +help: return the expression directly + | +LL ~ +LL | +LL ~ (match self { +LL + E::A(x) => x, +LL + E::B(x) => x, +LL + }) as _ + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:223:9 + | +LL | let s = if true { "a".to_string() } else { "b".to_string() } + "c"; + | ------------------------------------------------------------------- unnecessary `let` binding +LL | s + | ^ + | +help: return the expression directly + | +LL ~ +LL ~ (if true { "a".to_string() } else { "b".to_string() } + "c") + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:229:9 + | +LL | let s = "c".to_string() + if true { "a" } else { "b" }; + | ------------------------------------------------------- unnecessary `let` binding +LL | s + | ^ + | +help: return the expression directly + | +LL ~ +LL ~ "c".to_string() + if true { "a" } else { "b" } + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:235:9 + | +LL | let s = { "a".to_string() } + "b" + { "c" } + "d"; + | -------------------------------------------------- unnecessary `let` binding +LL | s + | ^ + | +help: return the expression directly + | +LL ~ +LL ~ ({ "a".to_string() } + "b" + { "c" } + "d") + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:243:13 + | +LL | let s = if true { 2 } else { 3 } << 4; + | -------------------------------------- unnecessary `let` binding +LL | s + | ^ + | +help: return the expression directly + | +LL ~ +LL ~ (if true { 2 } else { 3 } << 4) + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:248:13 + | +LL | let s = { true } || { false } && { 2 <= 3 }; + | -------------------------------------------- unnecessary `let` binding +LL | s + | ^ + | +help: return the expression directly + | +LL ~ +LL ~ ({ true } || { false } && { 2 <= 3 }) + | + +error: aborting due to 10 previous errors + diff --git a/tests/ui/let_and_return.edition2024.fixed b/tests/ui/let_and_return.edition2024.fixed new file mode 100644 index 000000000000..9990c3b71205 --- /dev/null +++ b/tests/ui/let_and_return.edition2024.fixed @@ -0,0 +1,264 @@ +//@revisions: edition2021 edition2024 +//@[edition2021] edition:2021 +//@[edition2024] edition:2024 + +#![allow(unused)] +#![warn(clippy::let_and_return)] + +use std::cell::RefCell; + +fn test() -> i32 { + let _y = 0; // no warning + + 5 + //~^ let_and_return +} + +fn test_inner() -> i32 { + if true { + + 5 + //~^ let_and_return + } else { + 0 + } +} + +fn test_nowarn_1() -> i32 { + let mut x = 5; + x += 1; + x +} + +fn test_nowarn_2() -> i32 { + let x = 5; + x + 1 +} + +fn test_nowarn_3() -> (i32, i32) { + // this should technically warn, but we do not compare complex patterns + let (x, y) = (5, 9); + (x, y) +} + +fn test_nowarn_4() -> i32 { + // this should technically warn, but not b/c of clippy::let_and_return, but b/c of useless type + let x: i32 = 5; + x +} + +fn test_nowarn_5(x: i16) -> u16 { + #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] + let x = x as u16; + x +} + +// False positive example +trait Decode { + fn decode(d: D) -> Result + where + Self: Sized; +} + +macro_rules! tuple_encode { + ($($x:ident),*) => ( + impl<$($x: Decode),*> Decode for ($($x),*) { + #[inline] + #[allow(non_snake_case)] + fn decode(mut d: D) -> Result { + // Shouldn't trigger lint + Ok(($({let $x = Decode::decode(&mut d)?; $x }),*)) + } + } + ); +} + +fn issue_3792() -> String { + use std::io::{self, BufRead, Stdin}; + + let stdin = io::stdin(); + // `Stdin::lock` returns `StdinLock<'static>` so `line` doesn't borrow from `stdin` + // https://github.com/rust-lang/rust/pull/93965 + + stdin.lock().lines().next().unwrap().unwrap() + //~^ let_and_return +} + +tuple_encode!(T0, T1, T2, T3, T4, T5, T6, T7); + +mod no_lint_if_stmt_borrows { + use std::cell::RefCell; + use std::rc::{Rc, Weak}; + struct Bar; + + impl Bar { + fn new() -> Self { + Bar {} + } + fn baz(&self) -> u32 { + 0 + } + } + + fn issue_3324(value: Weak>) -> u32 { + let value = value.upgrade().unwrap(); + + value.borrow().baz() + //~[edition2024]^ let_and_return + } + + fn borrows_in_closure(value: Weak>) -> u32 { + fn f(mut x: impl FnMut() -> u32) -> impl FnMut() -> u32 { + x + } + + let value = value.upgrade().unwrap(); + + f(|| value.borrow().baz())() + //~[edition2024]^ let_and_return + } + + mod free_function { + struct Inner; + + struct Foo<'a> { + inner: &'a Inner, + } + + impl Drop for Foo<'_> { + fn drop(&mut self) {} + } + + impl<'a> Foo<'a> { + fn new(inner: &'a Inner) -> Self { + Self { inner } + } + + fn value(&self) -> i32 { + 42 + } + } + + fn some_foo(inner: &Inner) -> Foo<'_> { + Foo { inner } + } + + fn test() -> i32 { + let x = Inner {}; + + some_foo(&x).value() + //~[edition2024]^ let_and_return + } + + fn test2() -> i32 { + let x = Inner {}; + + Foo::new(&x).value() + //~[edition2024]^ let_and_return + } + } +} + +mod issue_5729 { + use std::sync::Arc; + + trait Foo {} + + trait FooStorage { + fn foo_cloned(&self) -> Arc; + } + + struct FooStorageImpl { + foo: Arc, + } + + impl FooStorage for FooStorageImpl { + fn foo_cloned(&self) -> Arc { + + (Arc::clone(&self.foo)) as _ + //~^ let_and_return + } + } +} + +mod issue_11335 { + pub enum E { + A(T), + B(T), + } + + impl E { + pub fn inner(&self) -> &T { + + + (match self { + E::A(x) => x, + E::B(x) => x, + }) as _ + //~^ let_and_return + } + } +} + +// https://github.com/rust-lang/rust-clippy/issues/11167 +macro_rules! fn_in_macro { + ($b:block) => { + fn f() -> usize $b + } +} +fn_in_macro!({ + return 1; +}); + +fn issue9150() -> usize { + let x = 1; + #[cfg(any())] + panic!("can't see me"); + x +} + +fn issue12801() { + fn left_is_if() -> String { + + (if true { "a".to_string() } else { "b".to_string() } + "c") + //~^ let_and_return + } + + fn no_par_needed() -> String { + + "c".to_string() + if true { "a" } else { "b" } + //~^ let_and_return + } + + fn conjunctive_blocks() -> String { + + ({ "a".to_string() } + "b" + { "c" } + "d") + //~^ let_and_return + } + + #[allow(clippy::overly_complex_bool_expr)] + fn other_ops() { + let _ = || { + + (if true { 2 } else { 3 } << 4) + //~^ let_and_return + }; + let _ = || { + + ({ true } || { false } && { 2 <= 3 }) + //~^ let_and_return + }; + } +} + +fn issue14164() -> Result { + let v = std::cell::RefCell::new(Some(vec![1])); + + match &*v.borrow() { + Some(v) => Ok(Ok(v[0])), + None => Ok(Ok(0)), + }? + //~[edition2024]^ let_and_return +} + +fn main() {} diff --git a/tests/ui/let_and_return.edition2024.stderr b/tests/ui/let_and_return.edition2024.stderr new file mode 100644 index 000000000000..ca378fa43232 --- /dev/null +++ b/tests/ui/let_and_return.edition2024.stderr @@ -0,0 +1,228 @@ +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:13:5 + | +LL | let x = 5; + | ---------- unnecessary `let` binding +LL | x + | ^ + | + = note: `-D clippy::let-and-return` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::let_and_return)]` +help: return the expression directly + | +LL ~ +LL ~ 5 + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:20:9 + | +LL | let x = 5; + | ---------- unnecessary `let` binding +LL | x + | ^ + | +help: return the expression directly + | +LL ~ +LL ~ 5 + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:83:5 + | +LL | let line = stdin.lock().lines().next().unwrap().unwrap(); + | --------------------------------------------------------- unnecessary `let` binding +LL | line + | ^^^^ + | +help: return the expression directly + | +LL ~ +LL ~ stdin.lock().lines().next().unwrap().unwrap() + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:106:9 + | +LL | let ret = value.borrow().baz(); + | ------------------------------- unnecessary `let` binding +LL | ret + | ^^^ + | +help: return the expression directly + | +LL ~ +LL ~ value.borrow().baz() + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:117:9 + | +LL | let ret = f(|| value.borrow().baz())(); + | --------------------------------------- unnecessary `let` binding +LL | ret + | ^^^ + | +help: return the expression directly + | +LL ~ +LL ~ f(|| value.borrow().baz())() + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:149:13 + | +LL | let value = some_foo(&x).value(); + | --------------------------------- unnecessary `let` binding +LL | value + | ^^^^^ + | +help: return the expression directly + | +LL ~ +LL ~ some_foo(&x).value() + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:156:13 + | +LL | let value = Foo::new(&x).value(); + | --------------------------------- unnecessary `let` binding +LL | value + | ^^^^^ + | +help: return the expression directly + | +LL ~ +LL ~ Foo::new(&x).value() + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:178:13 + | +LL | let clone = Arc::clone(&self.foo); + | ---------------------------------- unnecessary `let` binding +LL | clone + | ^^^^^ + | +help: return the expression directly + | +LL ~ +LL ~ (Arc::clone(&self.foo)) as _ + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:197:13 + | +LL | / let result = match self { +LL | | E::A(x) => x, +LL | | E::B(x) => x, +LL | | }; + | |______________- unnecessary `let` binding +LL | +LL | result + | ^^^^^^ + | +help: return the expression directly + | +LL ~ +LL | +LL ~ (match self { +LL + E::A(x) => x, +LL + E::B(x) => x, +LL + }) as _ + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:223:9 + | +LL | let s = if true { "a".to_string() } else { "b".to_string() } + "c"; + | ------------------------------------------------------------------- unnecessary `let` binding +LL | s + | ^ + | +help: return the expression directly + | +LL ~ +LL ~ (if true { "a".to_string() } else { "b".to_string() } + "c") + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:229:9 + | +LL | let s = "c".to_string() + if true { "a" } else { "b" }; + | ------------------------------------------------------- unnecessary `let` binding +LL | s + | ^ + | +help: return the expression directly + | +LL ~ +LL ~ "c".to_string() + if true { "a" } else { "b" } + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:235:9 + | +LL | let s = { "a".to_string() } + "b" + { "c" } + "d"; + | -------------------------------------------------- unnecessary `let` binding +LL | s + | ^ + | +help: return the expression directly + | +LL ~ +LL ~ ({ "a".to_string() } + "b" + { "c" } + "d") + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:243:13 + | +LL | let s = if true { 2 } else { 3 } << 4; + | -------------------------------------- unnecessary `let` binding +LL | s + | ^ + | +help: return the expression directly + | +LL ~ +LL ~ (if true { 2 } else { 3 } << 4) + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:248:13 + | +LL | let s = { true } || { false } && { 2 <= 3 }; + | -------------------------------------------- unnecessary `let` binding +LL | s + | ^ + | +help: return the expression directly + | +LL ~ +LL ~ ({ true } || { false } && { 2 <= 3 }) + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:260:5 + | +LL | / let r = match &*v.borrow() { +LL | | Some(v) => Ok(Ok(v[0])), +LL | | None => Ok(Ok(0)), +LL | | }?; + | |_______- unnecessary `let` binding +LL | r + | ^ + | +help: return the expression directly + | +LL ~ +LL ~ match &*v.borrow() { +LL + Some(v) => Ok(Ok(v[0])), +LL + None => Ok(Ok(0)), +LL + }? + | + +error: aborting due to 15 previous errors + diff --git a/tests/ui/let_and_return.fixed b/tests/ui/let_and_return.fixed index b68b41cdca23..e22e66eb522e 100644 --- a/tests/ui/let_and_return.fixed +++ b/tests/ui/let_and_return.fixed @@ -244,4 +244,14 @@ fn issue12801() { } } +// Do not lint +fn issue14164() -> Result { + let v = std::cell::RefCell::new(Some(vec![1])); + let r = match &*v.borrow() { + Some(v) => Ok(Ok(v[0])), + None => Ok(Ok(0)), + }?; + r +} + fn main() {} diff --git a/tests/ui/let_and_return.rs b/tests/ui/let_and_return.rs index 6b9035f94288..48c20cdd60db 100644 --- a/tests/ui/let_and_return.rs +++ b/tests/ui/let_and_return.rs @@ -1,3 +1,7 @@ +//@revisions: edition2021 edition2024 +//@[edition2021] edition:2021 +//@[edition2024] edition:2024 + #![allow(unused)] #![warn(clippy::let_and_return)] @@ -7,15 +11,14 @@ fn test() -> i32 { let _y = 0; // no warning let x = 5; x - //~^ ERROR: returning the result of a `let` binding from a block - //~| NOTE: `-D clippy::let-and-return` implied by `-D warnings` + //~^ let_and_return } fn test_inner() -> i32 { if true { let x = 5; x - //~^ ERROR: returning the result of a `let` binding from a block + //~^ let_and_return } else { 0 } @@ -78,7 +81,7 @@ fn issue_3792() -> String { // https://github.com/rust-lang/rust/pull/93965 let line = stdin.lock().lines().next().unwrap().unwrap(); line - //~^ ERROR: returning the result of a `let` binding from a block + //~^ let_and_return } tuple_encode!(T0, T1, T2, T3, T4, T5, T6, T7); @@ -101,6 +104,7 @@ mod no_lint_if_stmt_borrows { let value = value.upgrade().unwrap(); let ret = value.borrow().baz(); ret + //~[edition2024]^ let_and_return } fn borrows_in_closure(value: Weak>) -> u32 { @@ -111,6 +115,7 @@ mod no_lint_if_stmt_borrows { let value = value.upgrade().unwrap(); let ret = f(|| value.borrow().baz())(); ret + //~[edition2024]^ let_and_return } mod free_function { @@ -142,12 +147,14 @@ mod no_lint_if_stmt_borrows { let x = Inner {}; let value = some_foo(&x).value(); value + //~[edition2024]^ let_and_return } fn test2() -> i32 { let x = Inner {}; let value = Foo::new(&x).value(); value + //~[edition2024]^ let_and_return } } } @@ -169,7 +176,7 @@ mod issue_5729 { fn foo_cloned(&self) -> Arc { let clone = Arc::clone(&self.foo); clone - //~^ ERROR: returning the result of a `let` binding from a block + //~^ let_and_return } } } @@ -188,7 +195,7 @@ mod issue_11335 { }; result - //~^ ERROR: returning the result of a `let` binding from a block + //~^ let_and_return } } } @@ -214,19 +221,19 @@ fn issue12801() { fn left_is_if() -> String { let s = if true { "a".to_string() } else { "b".to_string() } + "c"; s - //~^ ERROR: returning the result of a `let` binding from a block + //~^ let_and_return } fn no_par_needed() -> String { let s = "c".to_string() + if true { "a" } else { "b" }; s - //~^ ERROR: returning the result of a `let` binding from a block + //~^ let_and_return } fn conjunctive_blocks() -> String { let s = { "a".to_string() } + "b" + { "c" } + "d"; s - //~^ ERROR: returning the result of a `let` binding from a block + //~^ let_and_return } #[allow(clippy::overly_complex_bool_expr)] @@ -234,14 +241,24 @@ fn issue12801() { let _ = || { let s = if true { 2 } else { 3 } << 4; s - //~^ ERROR: returning the result of a `let` binding from a block + //~^ let_and_return }; let _ = || { let s = { true } || { false } && { 2 <= 3 }; s - //~^ ERROR: returning the result of a `let` binding from a block + //~^ let_and_return }; } } +fn issue14164() -> Result { + let v = std::cell::RefCell::new(Some(vec![1])); + let r = match &*v.borrow() { + Some(v) => Ok(Ok(v[0])), + None => Ok(Ok(0)), + }?; + r + //~[edition2024]^ let_and_return +} + fn main() {} diff --git a/tests/ui/let_if_seq.rs b/tests/ui/let_if_seq.rs index a29d35880b8d..2db206212aa5 100644 --- a/tests/ui/let_if_seq.rs +++ b/tests/ui/let_if_seq.rs @@ -75,15 +75,15 @@ fn main() { issue985_alt(); let mut foo = 0; - //~^ ERROR: `if _ { .. } else { .. }` is an expression - //~| NOTE: you might not need `mut` at all + //~^ useless_let_if_seq + if f() { foo = 42; } let mut bar = 0; - //~^ ERROR: `if _ { .. } else { .. }` is an expression - //~| NOTE: you might not need `mut` at all + //~^ useless_let_if_seq + if f() { f(); bar = 42; @@ -92,7 +92,8 @@ fn main() { } let quz; - //~^ ERROR: `if _ { .. } else { .. }` is an expression + //~^ useless_let_if_seq + if f() { quz = 42; } else { @@ -122,8 +123,8 @@ fn main() { // baz needs to be mut let mut baz = 0; - //~^ ERROR: `if _ { .. } else { .. }` is an expression - //~| NOTE: you might not need `mut` at all + //~^ useless_let_if_seq + if f() { baz = 42; } diff --git a/tests/ui/let_if_seq.stderr b/tests/ui/let_if_seq.stderr index 41930108fb1a..f59d42bf4c8d 100644 --- a/tests/ui/let_if_seq.stderr +++ b/tests/ui/let_if_seq.stderr @@ -32,15 +32,15 @@ error: `if _ { .. } else { .. }` is an expression | LL | / let quz; LL | | +LL | | LL | | if f() { -LL | | quz = 42; -LL | | } else { +... | LL | | quz = 0; LL | | } | |_____^ help: it is more idiomatic to write: `let quz = if f() { 42 } else { 0 };` error: `if _ { .. } else { .. }` is an expression - --> tests/ui/let_if_seq.rs:124:5 + --> tests/ui/let_if_seq.rs:125:5 | LL | / let mut baz = 0; LL | | diff --git a/tests/ui/let_underscore_future.rs b/tests/ui/let_underscore_future.rs index c2185e9785d8..6347c792280e 100644 --- a/tests/ui/let_underscore_future.rs +++ b/tests/ui/let_underscore_future.rs @@ -12,12 +12,13 @@ fn do_something_to_future(future: &mut impl Future) {} fn main() { let _ = some_async_fn(); - //~^ ERROR: non-binding `let` on a future + //~^ let_underscore_future + let _ = custom(); - //~^ ERROR: non-binding `let` on a future + //~^ let_underscore_future let mut future = some_async_fn(); do_something_to_future(&mut future); let _ = future; - //~^ ERROR: non-binding `let` on a future + //~^ let_underscore_future } diff --git a/tests/ui/let_underscore_future.stderr b/tests/ui/let_underscore_future.stderr index 66aeb5035394..baa489551d4a 100644 --- a/tests/ui/let_underscore_future.stderr +++ b/tests/ui/let_underscore_future.stderr @@ -9,7 +9,7 @@ LL | let _ = some_async_fn(); = help: to override `-D warnings` add `#[allow(clippy::let_underscore_future)]` error: non-binding `let` on a future - --> tests/ui/let_underscore_future.rs:16:5 + --> tests/ui/let_underscore_future.rs:17:5 | LL | let _ = custom(); | ^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | let _ = custom(); = help: consider awaiting the future or dropping explicitly with `std::mem::drop` error: non-binding `let` on a future - --> tests/ui/let_underscore_future.rs:21:5 + --> tests/ui/let_underscore_future.rs:22:5 | LL | let _ = future; | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/let_underscore_must_use.rs b/tests/ui/let_underscore_must_use.rs index 3290d087724e..5cf31ec63c66 100644 --- a/tests/ui/let_underscore_must_use.rs +++ b/tests/ui/let_underscore_must_use.rs @@ -65,42 +65,47 @@ impl Trait for S { fn main() { let _ = f(); - //~^ ERROR: non-binding `let` on a result of a `#[must_use]` function + //~^ let_underscore_must_use + let _ = g(); - //~^ ERROR: non-binding `let` on an expression with `#[must_use]` type + //~^ let_underscore_must_use + let _ = h(); let _ = l(0_u32); - //~^ ERROR: non-binding `let` on a result of a `#[must_use]` function + //~^ let_underscore_must_use let s = S {}; let _ = s.f(); - //~^ ERROR: non-binding `let` on a result of a `#[must_use]` function + //~^ let_underscore_must_use + let _ = s.g(); - //~^ ERROR: non-binding `let` on an expression with `#[must_use]` type + //~^ let_underscore_must_use + let _ = s.k(); let _ = S::h(); - //~^ ERROR: non-binding `let` on a result of a `#[must_use]` function + //~^ let_underscore_must_use + let _ = S::p(); - //~^ ERROR: non-binding `let` on an expression with `#[must_use]` type + //~^ let_underscore_must_use let _ = S::a(); - //~^ ERROR: non-binding `let` on a result of a `#[must_use]` function + //~^ let_underscore_must_use let _ = if true { Ok(()) } else { Err(()) }; - //~^ ERROR: non-binding `let` on an expression with `#[must_use]` type + //~^ let_underscore_must_use let a = Result::<(), ()>::Ok(()); let _ = a.is_ok(); - //~^ ERROR: non-binding `let` on a result of a `#[must_use]` function + //~^ let_underscore_must_use let _ = a.map(|_| ()); - //~^ ERROR: non-binding `let` on an expression with `#[must_use]` type + //~^ let_underscore_must_use let _ = a; - //~^ ERROR: non-binding `let` on an expression with `#[must_use]` type + //~^ let_underscore_must_use #[allow(clippy::let_underscore_must_use)] let _ = a; diff --git a/tests/ui/let_underscore_must_use.stderr b/tests/ui/let_underscore_must_use.stderr index e8785b92b815..130ea11646fd 100644 --- a/tests/ui/let_underscore_must_use.stderr +++ b/tests/ui/let_underscore_must_use.stderr @@ -9,7 +9,7 @@ LL | let _ = f(); = help: to override `-D warnings` add `#[allow(clippy::let_underscore_must_use)]` error: non-binding `let` on an expression with `#[must_use]` type - --> tests/ui/let_underscore_must_use.rs:69:5 + --> tests/ui/let_underscore_must_use.rs:70:5 | LL | let _ = g(); | ^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | let _ = g(); = help: consider explicitly using expression value error: non-binding `let` on a result of a `#[must_use]` function - --> tests/ui/let_underscore_must_use.rs:72:5 + --> tests/ui/let_underscore_must_use.rs:74:5 | LL | let _ = l(0_u32); | ^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | let _ = l(0_u32); = help: consider explicitly using function result error: non-binding `let` on a result of a `#[must_use]` function - --> tests/ui/let_underscore_must_use.rs:77:5 + --> tests/ui/let_underscore_must_use.rs:79:5 | LL | let _ = s.f(); | ^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | let _ = s.f(); = help: consider explicitly using function result error: non-binding `let` on an expression with `#[must_use]` type - --> tests/ui/let_underscore_must_use.rs:79:5 + --> tests/ui/let_underscore_must_use.rs:82:5 | LL | let _ = s.g(); | ^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | let _ = s.g(); = help: consider explicitly using expression value error: non-binding `let` on a result of a `#[must_use]` function - --> tests/ui/let_underscore_must_use.rs:83:5 + --> tests/ui/let_underscore_must_use.rs:87:5 | LL | let _ = S::h(); | ^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | let _ = S::h(); = help: consider explicitly using function result error: non-binding `let` on an expression with `#[must_use]` type - --> tests/ui/let_underscore_must_use.rs:85:5 + --> tests/ui/let_underscore_must_use.rs:90:5 | LL | let _ = S::p(); | ^^^^^^^^^^^^^^^ @@ -57,7 +57,7 @@ LL | let _ = S::p(); = help: consider explicitly using expression value error: non-binding `let` on a result of a `#[must_use]` function - --> tests/ui/let_underscore_must_use.rs:88:5 + --> tests/ui/let_underscore_must_use.rs:93:5 | LL | let _ = S::a(); | ^^^^^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | let _ = S::a(); = help: consider explicitly using function result error: non-binding `let` on an expression with `#[must_use]` type - --> tests/ui/let_underscore_must_use.rs:91:5 + --> tests/ui/let_underscore_must_use.rs:96:5 | LL | let _ = if true { Ok(()) } else { Err(()) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | let _ = if true { Ok(()) } else { Err(()) }; = help: consider explicitly using expression value error: non-binding `let` on a result of a `#[must_use]` function - --> tests/ui/let_underscore_must_use.rs:96:5 + --> tests/ui/let_underscore_must_use.rs:101:5 | LL | let _ = a.is_ok(); | ^^^^^^^^^^^^^^^^^^ @@ -81,7 +81,7 @@ LL | let _ = a.is_ok(); = help: consider explicitly using function result error: non-binding `let` on an expression with `#[must_use]` type - --> tests/ui/let_underscore_must_use.rs:99:5 + --> tests/ui/let_underscore_must_use.rs:104:5 | LL | let _ = a.map(|_| ()); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -89,7 +89,7 @@ LL | let _ = a.map(|_| ()); = help: consider explicitly using expression value error: non-binding `let` on an expression with `#[must_use]` type - --> tests/ui/let_underscore_must_use.rs:102:5 + --> tests/ui/let_underscore_must_use.rs:107:5 | LL | let _ = a; | ^^^^^^^^^^ diff --git a/tests/ui/let_underscore_untyped.rs b/tests/ui/let_underscore_untyped.rs index 6275b6f970a1..26ba8682dc2d 100644 --- a/tests/ui/let_underscore_untyped.rs +++ b/tests/ui/let_underscore_untyped.rs @@ -49,11 +49,16 @@ with_span!( fn main() { let _ = a(); + //~^ let_underscore_untyped let _ = b(1); + //~^ let_underscore_untyped let _ = c(); let _ = d(&1); + //~^ let_underscore_untyped let _ = e(); + //~^ let_underscore_untyped let _ = f(); + //~^ let_underscore_untyped let _ = g(); let closure = || {}; diff --git a/tests/ui/let_underscore_untyped.stderr b/tests/ui/let_underscore_untyped.stderr index 1dd51e1e59b1..86cdd5c662cc 100644 --- a/tests/ui/let_underscore_untyped.stderr +++ b/tests/ui/let_underscore_untyped.stderr @@ -13,49 +13,49 @@ LL | let _ = a(); = help: to override `-D warnings` add `#[allow(clippy::let_underscore_untyped)]` error: non-binding `let` without a type annotation - --> tests/ui/let_underscore_untyped.rs:52:5 + --> tests/ui/let_underscore_untyped.rs:53:5 | LL | let _ = b(1); | ^^^^^^^^^^^^^ | help: consider adding a type annotation - --> tests/ui/let_underscore_untyped.rs:52:10 + --> tests/ui/let_underscore_untyped.rs:53:10 | LL | let _ = b(1); | ^ error: non-binding `let` without a type annotation - --> tests/ui/let_underscore_untyped.rs:54:5 + --> tests/ui/let_underscore_untyped.rs:56:5 | LL | let _ = d(&1); | ^^^^^^^^^^^^^^ | help: consider adding a type annotation - --> tests/ui/let_underscore_untyped.rs:54:10 + --> tests/ui/let_underscore_untyped.rs:56:10 | LL | let _ = d(&1); | ^ error: non-binding `let` without a type annotation - --> tests/ui/let_underscore_untyped.rs:55:5 + --> tests/ui/let_underscore_untyped.rs:58:5 | LL | let _ = e(); | ^^^^^^^^^^^^ | help: consider adding a type annotation - --> tests/ui/let_underscore_untyped.rs:55:10 + --> tests/ui/let_underscore_untyped.rs:58:10 | LL | let _ = e(); | ^ error: non-binding `let` without a type annotation - --> tests/ui/let_underscore_untyped.rs:56:5 + --> tests/ui/let_underscore_untyped.rs:60:5 | LL | let _ = f(); | ^^^^^^^^^^^^ | help: consider adding a type annotation - --> tests/ui/let_underscore_untyped.rs:56:10 + --> tests/ui/let_underscore_untyped.rs:60:10 | LL | let _ = f(); | ^ diff --git a/tests/ui/let_unit.fixed b/tests/ui/let_unit.fixed index 3456e274f6a4..5e7a2ad37a84 100644 --- a/tests/ui/let_unit.fixed +++ b/tests/ui/let_unit.fixed @@ -9,6 +9,7 @@ macro_rules! let_and_return { fn main() { println!("x"); + //~^ let_unit_value let _y = 1; // this is fine let _z = ((), 1); // this as well if true { @@ -57,6 +58,7 @@ fn multiline_sugg() { let v: Vec = vec![2]; v + //~^ let_unit_value .into_iter() .map(|i| i * 2) .filter(|i| i % 2 == 0) @@ -106,6 +108,7 @@ fn _returns_generic() { let x: () = if true { f() } else { f2(0) }; match Some(0) { + //~^ let_unit_value None => f2(1), Some(0) => f(), Some(1) => f2(3), @@ -187,6 +190,7 @@ pub fn issue12594() { fn actual_test() { // create first a unit value'd value returns_unit(); + //~^ let_unit_value returns_result(()).unwrap(); returns_result(()).unwrap(); // make sure we replace only the first variable diff --git a/tests/ui/let_unit.rs b/tests/ui/let_unit.rs index e2dafbcb7714..7b06f6940121 100644 --- a/tests/ui/let_unit.rs +++ b/tests/ui/let_unit.rs @@ -9,6 +9,7 @@ macro_rules! let_and_return { fn main() { let _x = println!("x"); + //~^ let_unit_value let _y = 1; // this is fine let _z = ((), 1); // this as well if true { @@ -57,6 +58,7 @@ fn multiline_sugg() { let v: Vec = vec![2]; let _ = v + //~^ let_unit_value .into_iter() .map(|i| i * 2) .filter(|i| i % 2 == 0) @@ -106,6 +108,7 @@ fn _returns_generic() { let x: () = if true { f() } else { f2(0) }; let x = match Some(0) { + //~^ let_unit_value None => f2(1), Some(0) => f(), Some(1) => f2(3), @@ -187,6 +190,7 @@ pub fn issue12594() { fn actual_test() { // create first a unit value'd value let res = returns_unit(); + //~^ let_unit_value returns_result(res).unwrap(); returns_result(res).unwrap(); // make sure we replace only the first variable diff --git a/tests/ui/let_unit.stderr b/tests/ui/let_unit.stderr index a2f368f22e5b..d7d01d304cad 100644 --- a/tests/ui/let_unit.stderr +++ b/tests/ui/let_unit.stderr @@ -8,13 +8,13 @@ LL | let _x = println!("x"); = help: to override `-D warnings` add `#[allow(clippy::let_unit_value)]` error: this let-binding has unit value - --> tests/ui/let_unit.rs:59:5 + --> tests/ui/let_unit.rs:60:5 | LL | / let _ = v +LL | | LL | | .into_iter() LL | | .map(|i| i * 2) -LL | | .filter(|i| i % 2 == 0) -LL | | .map(|_| ()) +... | LL | | .next() LL | | .unwrap(); | |__________________^ @@ -22,6 +22,7 @@ LL | | .unwrap(); help: omit the `let` binding | LL ~ v +LL + LL + .into_iter() LL + .map(|i| i * 2) LL + .filter(|i| i % 2 == 0) @@ -31,9 +32,10 @@ LL + .unwrap(); | error: this let-binding has unit value - --> tests/ui/let_unit.rs:108:5 + --> tests/ui/let_unit.rs:110:5 | LL | / let x = match Some(0) { +LL | | LL | | None => f2(1), LL | | Some(0) => f(), LL | | Some(1) => f2(3), @@ -44,6 +46,7 @@ LL | | }; help: omit the `let` binding | LL ~ match Some(0) { +LL + LL + None => f2(1), LL + Some(0) => f(), LL + Some(1) => f2(3), @@ -52,7 +55,7 @@ LL + }; | error: this let-binding has unit value - --> tests/ui/let_unit.rs:189:9 + --> tests/ui/let_unit.rs:192:9 | LL | let res = returns_unit(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,6 +63,7 @@ LL | let res = returns_unit(); help: omit the `let` binding and replace variable usages with `()` | LL ~ returns_unit(); +LL | LL ~ returns_result(()).unwrap(); LL ~ returns_result(()).unwrap(); | diff --git a/tests/ui/let_with_type_underscore.rs b/tests/ui/let_with_type_underscore.rs index ae1a480bcfc5..a7c2f598b56d 100644 --- a/tests/ui/let_with_type_underscore.rs +++ b/tests/ui/let_with_type_underscore.rs @@ -13,9 +13,13 @@ fn func() -> &'static str { fn main() { // Will lint let x: _ = 1; + //~^ let_with_type_underscore let _: _ = 2; + //~^ let_with_type_underscore let x: _ = func(); + //~^ let_with_type_underscore let x: _; + //~^ let_with_type_underscore x = (); let x = 1; // Will not lint, Rust infers this to an integer before Clippy @@ -23,6 +27,7 @@ fn main() { let x: Vec<_> = Vec::::new(); let x: [_; 1] = [1]; let x : _ = 1; + //~^ let_with_type_underscore // Do not lint from procedural macros proc_macros::with_span! { diff --git a/tests/ui/let_with_type_underscore.stderr b/tests/ui/let_with_type_underscore.stderr index 29ec25a5b2ac..2284d1fe2e48 100644 --- a/tests/ui/let_with_type_underscore.stderr +++ b/tests/ui/let_with_type_underscore.stderr @@ -13,49 +13,49 @@ LL | let x: _ = 1; = help: to override `-D warnings` add `#[allow(clippy::let_with_type_underscore)]` error: variable declared with type underscore - --> tests/ui/let_with_type_underscore.rs:16:5 + --> tests/ui/let_with_type_underscore.rs:17:5 | LL | let _: _ = 2; | ^^^^^^^^^^^^^ | help: remove the explicit type `_` declaration - --> tests/ui/let_with_type_underscore.rs:16:10 + --> tests/ui/let_with_type_underscore.rs:17:10 | LL | let _: _ = 2; | ^^^ error: variable declared with type underscore - --> tests/ui/let_with_type_underscore.rs:17:5 + --> tests/ui/let_with_type_underscore.rs:19:5 | LL | let x: _ = func(); | ^^^^^^^^^^^^^^^^^^ | help: remove the explicit type `_` declaration - --> tests/ui/let_with_type_underscore.rs:17:10 + --> tests/ui/let_with_type_underscore.rs:19:10 | LL | let x: _ = func(); | ^^^ error: variable declared with type underscore - --> tests/ui/let_with_type_underscore.rs:18:5 + --> tests/ui/let_with_type_underscore.rs:21:5 | LL | let x: _; | ^^^^^^^^^ | help: remove the explicit type `_` declaration - --> tests/ui/let_with_type_underscore.rs:18:10 + --> tests/ui/let_with_type_underscore.rs:21:10 | LL | let x: _; | ^^^ error: variable declared with type underscore - --> tests/ui/let_with_type_underscore.rs:25:5 + --> tests/ui/let_with_type_underscore.rs:29:5 | LL | let x : _ = 1; | ^^^^^^^^^^^^^^ | help: remove the explicit type `_` declaration - --> tests/ui/let_with_type_underscore.rs:25:10 + --> tests/ui/let_with_type_underscore.rs:29:10 | LL | let x : _ = 1; | ^^^^ diff --git a/tests/ui/lines_filter_map_ok.fixed b/tests/ui/lines_filter_map_ok.fixed index 621115cc1325..977e31c744a2 100644 --- a/tests/ui/lines_filter_map_ok.fixed +++ b/tests/ui/lines_filter_map_ok.fixed @@ -7,20 +7,26 @@ fn main() -> io::Result<()> { let f = std::fs::File::open("/")?; // Lint BufReader::new(f).lines().map_while(Result::ok).for_each(|_| ()); + //~^ lines_filter_map_ok // Lint let f = std::fs::File::open("/")?; BufReader::new(f).lines().map_while(Result::ok).for_each(|_| ()); + //~^ lines_filter_map_ok // Lint let f = std::fs::File::open("/")?; BufReader::new(f).lines().map_while(Result::ok).for_each(|_| ()); + //~^ lines_filter_map_ok let s = "foo\nbar\nbaz\n"; // Lint io::stdin().lines().map_while(Result::ok).for_each(|_| ()); + //~^ lines_filter_map_ok // Lint io::stdin().lines().map_while(Result::ok).for_each(|_| ()); + //~^ lines_filter_map_ok // Lint io::stdin().lines().map_while(Result::ok).for_each(|_| ()); + //~^ lines_filter_map_ok // Do not lint (not a `Lines` iterator) io::stdin() .lines() @@ -31,3 +37,10 @@ fn main() -> io::Result<()> { io::stdin().lines().filter_map(|x| x.err()).for_each(|_| ()); Ok(()) } + +#[clippy::msrv = "1.56"] +fn msrv_check() { + let _lines = BufReader::new(std::fs::File::open("some-path").unwrap()) + .lines() + .filter_map(Result::ok); +} diff --git a/tests/ui/lines_filter_map_ok.rs b/tests/ui/lines_filter_map_ok.rs index a86efbd66862..2196075bc445 100644 --- a/tests/ui/lines_filter_map_ok.rs +++ b/tests/ui/lines_filter_map_ok.rs @@ -7,20 +7,26 @@ fn main() -> io::Result<()> { let f = std::fs::File::open("/")?; // Lint BufReader::new(f).lines().filter_map(Result::ok).for_each(|_| ()); + //~^ lines_filter_map_ok // Lint let f = std::fs::File::open("/")?; BufReader::new(f).lines().flat_map(Result::ok).for_each(|_| ()); + //~^ lines_filter_map_ok // Lint let f = std::fs::File::open("/")?; BufReader::new(f).lines().flatten().for_each(|_| ()); + //~^ lines_filter_map_ok let s = "foo\nbar\nbaz\n"; // Lint io::stdin().lines().filter_map(Result::ok).for_each(|_| ()); + //~^ lines_filter_map_ok // Lint io::stdin().lines().filter_map(|x| x.ok()).for_each(|_| ()); + //~^ lines_filter_map_ok // Lint io::stdin().lines().flatten().for_each(|_| ()); + //~^ lines_filter_map_ok // Do not lint (not a `Lines` iterator) io::stdin() .lines() @@ -31,3 +37,10 @@ fn main() -> io::Result<()> { io::stdin().lines().filter_map(|x| x.err()).for_each(|_| ()); Ok(()) } + +#[clippy::msrv = "1.56"] +fn msrv_check() { + let _lines = BufReader::new(std::fs::File::open("some-path").unwrap()) + .lines() + .filter_map(Result::ok); +} diff --git a/tests/ui/lines_filter_map_ok.stderr b/tests/ui/lines_filter_map_ok.stderr index 558c0532be95..f9038eec9fb2 100644 --- a/tests/ui/lines_filter_map_ok.stderr +++ b/tests/ui/lines_filter_map_ok.stderr @@ -13,61 +13,61 @@ LL | BufReader::new(f).lines().filter_map(Result::ok).for_each(|_| ()); = help: to override `-D warnings` add `#[allow(clippy::lines_filter_map_ok)]` error: `flat_map()` will run forever if the iterator repeatedly produces an `Err` - --> tests/ui/lines_filter_map_ok.rs:12:31 + --> tests/ui/lines_filter_map_ok.rs:13:31 | LL | BufReader::new(f).lines().flat_map(Result::ok).for_each(|_| ()); | ^^^^^^^^^^^^^^^^^^^^ help: replace with: `map_while(Result::ok)` | note: this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error - --> tests/ui/lines_filter_map_ok.rs:12:5 + --> tests/ui/lines_filter_map_ok.rs:13:5 | LL | BufReader::new(f).lines().flat_map(Result::ok).for_each(|_| ()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: `flatten()` will run forever if the iterator repeatedly produces an `Err` - --> tests/ui/lines_filter_map_ok.rs:15:31 + --> tests/ui/lines_filter_map_ok.rs:17:31 | LL | BufReader::new(f).lines().flatten().for_each(|_| ()); | ^^^^^^^^^ help: replace with: `map_while(Result::ok)` | note: this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error - --> tests/ui/lines_filter_map_ok.rs:15:5 + --> tests/ui/lines_filter_map_ok.rs:17:5 | LL | BufReader::new(f).lines().flatten().for_each(|_| ()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: `filter_map()` will run forever if the iterator repeatedly produces an `Err` - --> tests/ui/lines_filter_map_ok.rs:19:25 + --> tests/ui/lines_filter_map_ok.rs:22:25 | LL | io::stdin().lines().filter_map(Result::ok).for_each(|_| ()); | ^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `map_while(Result::ok)` | note: this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error - --> tests/ui/lines_filter_map_ok.rs:19:5 + --> tests/ui/lines_filter_map_ok.rs:22:5 | LL | io::stdin().lines().filter_map(Result::ok).for_each(|_| ()); | ^^^^^^^^^^^^^^^^^^^ error: `filter_map()` will run forever if the iterator repeatedly produces an `Err` - --> tests/ui/lines_filter_map_ok.rs:21:25 + --> tests/ui/lines_filter_map_ok.rs:25:25 | LL | io::stdin().lines().filter_map(|x| x.ok()).for_each(|_| ()); | ^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `map_while(Result::ok)` | note: this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error - --> tests/ui/lines_filter_map_ok.rs:21:5 + --> tests/ui/lines_filter_map_ok.rs:25:5 | LL | io::stdin().lines().filter_map(|x| x.ok()).for_each(|_| ()); | ^^^^^^^^^^^^^^^^^^^ error: `flatten()` will run forever if the iterator repeatedly produces an `Err` - --> tests/ui/lines_filter_map_ok.rs:23:25 + --> tests/ui/lines_filter_map_ok.rs:28:25 | LL | io::stdin().lines().flatten().for_each(|_| ()); | ^^^^^^^^^ help: replace with: `map_while(Result::ok)` | note: this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error - --> tests/ui/lines_filter_map_ok.rs:23:5 + --> tests/ui/lines_filter_map_ok.rs:28:5 | LL | io::stdin().lines().flatten().for_each(|_| ()); | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/linkedlist.rs b/tests/ui/linkedlist.rs index e1e6cff98097..64a9ba0029da 100644 --- a/tests/ui/linkedlist.rs +++ b/tests/ui/linkedlist.rs @@ -6,17 +6,20 @@ extern crate alloc; use alloc::collections::linked_list::LinkedList; const C: LinkedList = LinkedList::new(); -//~^ ERROR: you seem to be using a `LinkedList`! Perhaps you meant some other data structu +//~^ linkedlist + static S: LinkedList = LinkedList::new(); -//~^ ERROR: you seem to be using a `LinkedList`! Perhaps you meant some other data structu +//~^ linkedlist trait Foo { type Baz = LinkedList; - //~^ ERROR: you seem to be using a `LinkedList`! Perhaps you meant some other data str + //~^ linkedlist + fn foo(_: LinkedList); - //~^ ERROR: you seem to be using a `LinkedList`! Perhaps you meant some other data str + //~^ linkedlist + const BAR: Option>; - //~^ ERROR: you seem to be using a `LinkedList`! Perhaps you meant some other data str + //~^ linkedlist } // Ok, we don’t want to warn for implementations; see issue #605. @@ -27,20 +30,22 @@ impl Foo for LinkedList { pub struct Bar { priv_linked_list_field: LinkedList, - //~^ ERROR: you seem to be using a `LinkedList`! Perhaps you meant some other data str + //~^ linkedlist pub pub_linked_list_field: LinkedList, } impl Bar { fn foo(_: LinkedList) {} - //~^ ERROR: you seem to be using a `LinkedList`! Perhaps you meant some other data str + //~^ linkedlist } // All of these test should be trigger the lint because they are not // part of the public api fn test(my_favorite_linked_list: LinkedList) {} -//~^ ERROR: you seem to be using a `LinkedList`! Perhaps you meant some other data structu +//~^ linkedlist + fn test_ret() -> Option> { - //~^ ERROR: you seem to be using a `LinkedList`! Perhaps you meant some other data structu + //~^ linkedlist + None } fn test_local_not_linted() { diff --git a/tests/ui/linkedlist.stderr b/tests/ui/linkedlist.stderr index d19176c7b0d2..419fbcc7e188 100644 --- a/tests/ui/linkedlist.stderr +++ b/tests/ui/linkedlist.stderr @@ -9,7 +9,7 @@ LL | const C: LinkedList = LinkedList::new(); = help: to override `-D warnings` add `#[allow(clippy::linkedlist)]` error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure? - --> tests/ui/linkedlist.rs:10:11 + --> tests/ui/linkedlist.rs:11:11 | LL | static S: LinkedList = LinkedList::new(); | ^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | static S: LinkedList = LinkedList::new(); = help: a `VecDeque` might work error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure? - --> tests/ui/linkedlist.rs:14:16 + --> tests/ui/linkedlist.rs:15:16 | LL | type Baz = LinkedList; | ^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | type Baz = LinkedList; = help: a `VecDeque` might work error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure? - --> tests/ui/linkedlist.rs:16:15 + --> tests/ui/linkedlist.rs:18:15 | LL | fn foo(_: LinkedList); | ^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | fn foo(_: LinkedList); = help: a `VecDeque` might work error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure? - --> tests/ui/linkedlist.rs:18:23 + --> tests/ui/linkedlist.rs:21:23 | LL | const BAR: Option>; | ^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | const BAR: Option>; = help: a `VecDeque` might work error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure? - --> tests/ui/linkedlist.rs:29:29 + --> tests/ui/linkedlist.rs:32:29 | LL | priv_linked_list_field: LinkedList, | ^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | priv_linked_list_field: LinkedList, = help: a `VecDeque` might work error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure? - --> tests/ui/linkedlist.rs:34:15 + --> tests/ui/linkedlist.rs:37:15 | LL | fn foo(_: LinkedList) {} | ^^^^^^^^^^^^^^ @@ -57,7 +57,7 @@ LL | fn foo(_: LinkedList) {} = help: a `VecDeque` might work error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure? - --> tests/ui/linkedlist.rs:40:34 + --> tests/ui/linkedlist.rs:43:34 | LL | fn test(my_favorite_linked_list: LinkedList) {} | ^^^^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | fn test(my_favorite_linked_list: LinkedList) {} = help: a `VecDeque` might work error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure? - --> tests/ui/linkedlist.rs:42:25 + --> tests/ui/linkedlist.rs:46:25 | LL | fn test_ret() -> Option> { | ^^^^^^^^^^^^^^ diff --git a/tests/ui/literal_string_with_formatting_arg.rs b/tests/ui/literal_string_with_formatting_arg.rs index f257c66f59d3..d54cceae53eb 100644 --- a/tests/ui/literal_string_with_formatting_arg.rs +++ b/tests/ui/literal_string_with_formatting_arg.rs @@ -1,6 +1,31 @@ #![warn(clippy::literal_string_with_formatting_args)] #![allow(clippy::unnecessary_literal_unwrap)] +// Regression test for . +// It's not supposed to emit the lint in this case (in `assert!` expansion). +fn compiler_macro() { + fn parse(_: &str) -> Result<(), i32> { + unimplemented!() + } + + assert!( + parse( + #[allow(clippy::literal_string_with_formatting_args)] + "foo {:}" + ) + .is_err() + ); + let value = 0; + assert!(format!("{value}").is_ascii()); +} + +// Regression test for . +fn regression_14007() { + let s = "{и}"; + let ш = 12; + let s = "{ш}"; //~ literal_string_with_formatting_args +} + fn main() { let x: Option = None; let y = "hello"; @@ -13,8 +38,10 @@ fn main() { x.expect(r"{y:?} {y:?} "); //~ literal_string_with_formatting_args x.expect(r"{y:?} y:?}"); //~ literal_string_with_formatting_args x.expect(r##" {y:?} {y:?} "##); //~ literal_string_with_formatting_args + assert!("{y}".is_ascii()); //~ literal_string_with_formatting_args // Ensure that it doesn't try to go in the middle of a unicode character. - x.expect("———{:?}"); //~ literal_string_with_formatting_args + x.expect("———{:?}"); + //~^ literal_string_with_formatting_args // Should not lint! format!("{y:?}"); @@ -25,6 +52,8 @@ fn main() { x.expect("{{y:?}"); x.expect(" {0}"); // If it only contains an integer, we ignore it. x.expect(r##" {x:?} "##); // `x` doesn't exist so we shoud not lint + // + //~^^ literal_string_with_formatting_args x.expect("{y:...}"); let _ = "fn main {\n\ }"; diff --git a/tests/ui/literal_string_with_formatting_arg.stderr b/tests/ui/literal_string_with_formatting_arg.stderr index 32a84f600da7..55425d01c587 100644 --- a/tests/ui/literal_string_with_formatting_arg.stderr +++ b/tests/ui/literal_string_with_formatting_arg.stderr @@ -1,71 +1,83 @@ error: this looks like a formatting argument but it is not part of a formatting macro - --> tests/ui/literal_string_with_formatting_arg.rs:7:15 + --> tests/ui/literal_string_with_formatting_arg.rs:26:14 | -LL | x.expect("{y} {}"); - | ^^^ +LL | let s = "{ш}"; + | ^^^ | = note: `-D clippy::literal-string-with-formatting-args` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::literal_string_with_formatting_args)]` error: this looks like a formatting argument but it is not part of a formatting macro - --> tests/ui/literal_string_with_formatting_arg.rs:8:16 + --> tests/ui/literal_string_with_formatting_arg.rs:32:15 + | +LL | x.expect("{y} {}"); + | ^^^ + +error: this looks like a formatting argument but it is not part of a formatting macro + --> tests/ui/literal_string_with_formatting_arg.rs:33:16 | LL | x.expect(" {y} bla"); | ^^^ error: this looks like a formatting argument but it is not part of a formatting macro - --> tests/ui/literal_string_with_formatting_arg.rs:9:15 + --> tests/ui/literal_string_with_formatting_arg.rs:34:15 | LL | x.expect("{:?}"); | ^^^^ error: this looks like a formatting argument but it is not part of a formatting macro - --> tests/ui/literal_string_with_formatting_arg.rs:10:15 + --> tests/ui/literal_string_with_formatting_arg.rs:35:15 | LL | x.expect("{y:?}"); | ^^^^^ error: these look like formatting arguments but are not part of a formatting macro - --> tests/ui/literal_string_with_formatting_arg.rs:11:16 + --> tests/ui/literal_string_with_formatting_arg.rs:36:16 | LL | x.expect(" {y:?} {y:?} "); | ^^^^^ ^^^^^ error: this looks like a formatting argument but it is not part of a formatting macro - --> tests/ui/literal_string_with_formatting_arg.rs:12:23 + --> tests/ui/literal_string_with_formatting_arg.rs:37:23 | LL | x.expect(" {y:..} {y:?} "); | ^^^^^ error: these look like formatting arguments but are not part of a formatting macro - --> tests/ui/literal_string_with_formatting_arg.rs:13:16 + --> tests/ui/literal_string_with_formatting_arg.rs:38:16 | LL | x.expect(r"{y:?} {y:?} "); | ^^^^^ ^^^^^ error: this looks like a formatting argument but it is not part of a formatting macro - --> tests/ui/literal_string_with_formatting_arg.rs:14:16 + --> tests/ui/literal_string_with_formatting_arg.rs:39:16 | LL | x.expect(r"{y:?} y:?}"); | ^^^^^ error: these look like formatting arguments but are not part of a formatting macro - --> tests/ui/literal_string_with_formatting_arg.rs:15:19 + --> tests/ui/literal_string_with_formatting_arg.rs:40:19 | LL | x.expect(r##" {y:?} {y:?} "##); | ^^^^^ ^^^^^ error: this looks like a formatting argument but it is not part of a formatting macro - --> tests/ui/literal_string_with_formatting_arg.rs:17:18 + --> tests/ui/literal_string_with_formatting_arg.rs:41:14 + | +LL | assert!("{y}".is_ascii()); + | ^^^ + +error: this looks like a formatting argument but it is not part of a formatting macro + --> tests/ui/literal_string_with_formatting_arg.rs:43:18 | LL | x.expect("———{:?}"); | ^^^^ error: this looks like a formatting argument but it is not part of a formatting macro - --> tests/ui/literal_string_with_formatting_arg.rs:27:19 + --> tests/ui/literal_string_with_formatting_arg.rs:54:19 | LL | x.expect(r##" {x:?} "##); // `x` doesn't exist so we shoud not lint | ^^^^^ -error: aborting due to 11 previous errors +error: aborting due to 13 previous errors diff --git a/tests/ui/literals.rs b/tests/ui/literals.rs index c275b04d886b..d21d49310a07 100644 --- a/tests/ui/literals.rs +++ b/tests/ui/literals.rs @@ -11,32 +11,35 @@ fn main() { let ok1 = 0xABCD; let ok3 = 0xab_cd; let ok4 = 0xab_cd_i32; - //~^ ERROR: integer type suffix should not be separated by an underscore - //~| NOTE: `-D clippy::separated-literal-suffix` implied by `-D warnings` + //~^ separated_literal_suffix + let ok5 = 0xAB_CD_u32; - //~^ ERROR: integer type suffix should not be separated by an underscore + //~^ separated_literal_suffix + let ok5 = 0xAB_CD_isize; - //~^ ERROR: integer type suffix should not be separated by an underscore + //~^ separated_literal_suffix + let fail1 = 0xabCD; - //~^ ERROR: inconsistent casing in hexadecimal literal - //~| NOTE: `-D clippy::mixed-case-hex-literals` implied by `-D warnings` + //~^ mixed_case_hex_literals + let fail2 = 0xabCD_u32; - //~^ ERROR: integer type suffix should not be separated by an underscore - //~| ERROR: inconsistent casing in hexadecimal literal + //~^ separated_literal_suffix + //~| mixed_case_hex_literals + let fail2 = 0xabCD_isize; - //~^ ERROR: integer type suffix should not be separated by an underscore - //~| ERROR: inconsistent casing in hexadecimal literal + //~^ separated_literal_suffix + //~| mixed_case_hex_literals + let fail_multi_zero = 000_123usize; - //~^ ERROR: integer type suffix should be separated by an underscore - //~| NOTE: `-D clippy::unseparated-literal-suffix` implied by `-D warnings` - //~| ERROR: this is a decimal constant - //~| NOTE: `-D clippy::zero-prefixed-literal` implied by `-D warnings` + //~^ unseparated_literal_suffix + //~| zero_prefixed_literal let ok9 = 0; let ok10 = 0_i64; - //~^ ERROR: integer type suffix should not be separated by an underscore + //~^ separated_literal_suffix + let fail8 = 0123; - //~^ ERROR: this is a decimal constant + //~^ zero_prefixed_literal let ok11 = 0o123; let ok12 = 0b10_1010; @@ -46,20 +49,22 @@ fn main() { let ok15 = 0xab_cabc_abca_bcab_cabc; let ok16 = 0xFE_BAFE_ABAB_ABCD; let ok17 = 0x123_4567_8901_usize; - //~^ ERROR: integer type suffix should not be separated by an underscore + //~^ separated_literal_suffix + let ok18 = 0xF; let fail19 = 12_3456_21; - //~^ ERROR: digits grouped inconsistently by underscores - //~| NOTE: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings` + //~^ inconsistent_digit_grouping + let fail22 = 3__4___23; - //~^ ERROR: digits grouped inconsistently by underscores + //~^ inconsistent_digit_grouping + let fail23 = 3__16___23; - //~^ ERROR: digits grouped inconsistently by underscores + //~^ inconsistent_digit_grouping let fail24 = 0xAB_ABC_AB; - //~^ ERROR: digits of hex, binary or octal literal not in groups of equal size - //~| NOTE: `-D clippy::unusual-byte-groupings` implied by `-D warnings` + //~^ unusual_byte_groupings + let fail25 = 0b01_100_101; let ok26 = 0x6_A0_BF; let ok27 = 0b1_0010_0101; @@ -68,9 +73,11 @@ fn main() { fn issue9651() { // lint but octal form is not possible here let _ = 08; - //~^ ERROR: this is a decimal constant + //~^ zero_prefixed_literal + let _ = 09; - //~^ ERROR: this is a decimal constant + //~^ zero_prefixed_literal + let _ = 089; - //~^ ERROR: this is a decimal constant + //~^ zero_prefixed_literal } diff --git a/tests/ui/literals.stderr b/tests/ui/literals.stderr index 576b38a47d2d..d65cd3c89ebb 100644 --- a/tests/ui/literals.stderr +++ b/tests/ui/literals.stderr @@ -14,13 +14,13 @@ LL | let ok5 = 0xAB_CD_u32; | ^^^^^^^^^^^ help: remove the underscore: `0xAB_CDu32` error: integer type suffix should not be separated by an underscore - --> tests/ui/literals.rs:18:15 + --> tests/ui/literals.rs:19:15 | LL | let ok5 = 0xAB_CD_isize; | ^^^^^^^^^^^^^ help: remove the underscore: `0xAB_CDisize` error: inconsistent casing in hexadecimal literal - --> tests/ui/literals.rs:20:17 + --> tests/ui/literals.rs:22:17 | LL | let fail1 = 0xabCD; | ^^^^^^ @@ -29,31 +29,31 @@ LL | let fail1 = 0xabCD; = help: to override `-D warnings` add `#[allow(clippy::mixed_case_hex_literals)]` error: integer type suffix should not be separated by an underscore - --> tests/ui/literals.rs:23:17 + --> tests/ui/literals.rs:25:17 | LL | let fail2 = 0xabCD_u32; | ^^^^^^^^^^ help: remove the underscore: `0xabCDu32` error: inconsistent casing in hexadecimal literal - --> tests/ui/literals.rs:23:17 + --> tests/ui/literals.rs:25:17 | LL | let fail2 = 0xabCD_u32; | ^^^^^^^^^^ error: integer type suffix should not be separated by an underscore - --> tests/ui/literals.rs:26:17 + --> tests/ui/literals.rs:29:17 | LL | let fail2 = 0xabCD_isize; | ^^^^^^^^^^^^ help: remove the underscore: `0xabCDisize` error: inconsistent casing in hexadecimal literal - --> tests/ui/literals.rs:26:17 + --> tests/ui/literals.rs:29:17 | LL | let fail2 = 0xabCD_isize; | ^^^^^^^^^^^^ error: integer type suffix should be separated by an underscore - --> tests/ui/literals.rs:29:27 + --> tests/ui/literals.rs:33:27 | LL | let fail_multi_zero = 000_123usize; | ^^^^^^^^^^^^ help: add an underscore: `000_123_usize` @@ -62,7 +62,7 @@ LL | let fail_multi_zero = 000_123usize; = help: to override `-D warnings` add `#[allow(clippy::unseparated_literal_suffix)]` error: this is a decimal constant - --> tests/ui/literals.rs:29:27 + --> tests/ui/literals.rs:33:27 | LL | let fail_multi_zero = 000_123usize; | ^^^^^^^^^^^^ @@ -81,13 +81,13 @@ LL + let fail_multi_zero = 0o123usize; | error: integer type suffix should not be separated by an underscore - --> tests/ui/literals.rs:36:16 + --> tests/ui/literals.rs:38:16 | LL | let ok10 = 0_i64; | ^^^^^ help: remove the underscore: `0i64` error: this is a decimal constant - --> tests/ui/literals.rs:38:17 + --> tests/ui/literals.rs:41:17 | LL | let fail8 = 0123; | ^^^^ @@ -103,13 +103,13 @@ LL | let fail8 = 0o123; | + error: integer type suffix should not be separated by an underscore - --> tests/ui/literals.rs:48:16 + --> tests/ui/literals.rs:51:16 | LL | let ok17 = 0x123_4567_8901_usize; | ^^^^^^^^^^^^^^^^^^^^^ help: remove the underscore: `0x123_4567_8901usize` error: digits grouped inconsistently by underscores - --> tests/ui/literals.rs:52:18 + --> tests/ui/literals.rs:56:18 | LL | let fail19 = 12_3456_21; | ^^^^^^^^^^ help: consider: `12_345_621` @@ -118,19 +118,19 @@ LL | let fail19 = 12_3456_21; = help: to override `-D warnings` add `#[allow(clippy::inconsistent_digit_grouping)]` error: digits grouped inconsistently by underscores - --> tests/ui/literals.rs:55:18 + --> tests/ui/literals.rs:59:18 | LL | let fail22 = 3__4___23; | ^^^^^^^^^ help: consider: `3_423` error: digits grouped inconsistently by underscores - --> tests/ui/literals.rs:57:18 + --> tests/ui/literals.rs:62:18 | LL | let fail23 = 3__16___23; | ^^^^^^^^^^ help: consider: `31_623` error: digits of hex, binary or octal literal not in groups of equal size - --> tests/ui/literals.rs:60:18 + --> tests/ui/literals.rs:65:18 | LL | let fail24 = 0xAB_ABC_AB; | ^^^^^^^^^^^ help: consider: `0x0ABA_BCAB` @@ -139,7 +139,7 @@ LL | let fail24 = 0xAB_ABC_AB; = help: to override `-D warnings` add `#[allow(clippy::unusual_byte_groupings)]` error: this is a decimal constant - --> tests/ui/literals.rs:70:13 + --> tests/ui/literals.rs:75:13 | LL | let _ = 08; | ^^ @@ -151,7 +151,7 @@ LL + let _ = 8; | error: this is a decimal constant - --> tests/ui/literals.rs:72:13 + --> tests/ui/literals.rs:78:13 | LL | let _ = 09; | ^^ @@ -163,7 +163,7 @@ LL + let _ = 9; | error: this is a decimal constant - --> tests/ui/literals.rs:74:13 + --> tests/ui/literals.rs:81:13 | LL | let _ = 089; | ^^^ diff --git a/tests/ui/lossy_float_literal.fixed b/tests/ui/lossy_float_literal.fixed index cc8c0b4a0d17..925a1465cc30 100644 --- a/tests/ui/lossy_float_literal.fixed +++ b/tests/ui/lossy_float_literal.fixed @@ -12,17 +12,28 @@ fn main() { let _: f16 = -4_097.0; let _: f32 = 16_777_216.0; + //~^ lossy_float_literal let _: f32 = 16_777_220.0; + //~^ lossy_float_literal let _: f32 = 16_777_220.0; + //~^ lossy_float_literal let _: f32 = 16_777_220.0; + //~^ lossy_float_literal let _ = 16_777_220_f32; + //~^ lossy_float_literal let _: f32 = -16_777_220.0; + //~^ lossy_float_literal let _: f64 = 9_007_199_254_740_992.0; + //~^ lossy_float_literal let _: f64 = 9_007_199_254_740_992.0; + //~^ lossy_float_literal let _: f64 = 9_007_199_254_740_992.0; + //~^ lossy_float_literal let _ = 9_007_199_254_740_992_f64; + //~^ lossy_float_literal let _: f64 = -9_007_199_254_740_992.0; + //~^ lossy_float_literal let _: f128 = 10_384_593_717_069_655_257_060_992_658_440_193.0; let _: f128 = 10_384_593_717_069_655_257_060_992_658_440_193.; diff --git a/tests/ui/lossy_float_literal.rs b/tests/ui/lossy_float_literal.rs index c84eef396d58..7341388d4816 100644 --- a/tests/ui/lossy_float_literal.rs +++ b/tests/ui/lossy_float_literal.rs @@ -12,17 +12,28 @@ fn main() { let _: f16 = -4_097.0; let _: f32 = 16_777_217.0; + //~^ lossy_float_literal let _: f32 = 16_777_219.0; + //~^ lossy_float_literal let _: f32 = 16_777_219.; + //~^ lossy_float_literal let _: f32 = 16_777_219.000; + //~^ lossy_float_literal let _ = 16_777_219f32; + //~^ lossy_float_literal let _: f32 = -16_777_219.0; + //~^ lossy_float_literal let _: f64 = 9_007_199_254_740_993.0; + //~^ lossy_float_literal let _: f64 = 9_007_199_254_740_993.; + //~^ lossy_float_literal let _: f64 = 9_007_199_254_740_993.00; + //~^ lossy_float_literal let _ = 9_007_199_254_740_993f64; + //~^ lossy_float_literal let _: f64 = -9_007_199_254_740_993.0; + //~^ lossy_float_literal let _: f128 = 10_384_593_717_069_655_257_060_992_658_440_193.0; let _: f128 = 10_384_593_717_069_655_257_060_992_658_440_193.; diff --git a/tests/ui/lossy_float_literal.stderr b/tests/ui/lossy_float_literal.stderr index 118351a62d00..33b650b19c8a 100644 --- a/tests/ui/lossy_float_literal.stderr +++ b/tests/ui/lossy_float_literal.stderr @@ -13,7 +13,7 @@ LL + let _: f32 = 16_777_216.0; | error: literal cannot be represented as the underlying type without loss of precision - --> tests/ui/lossy_float_literal.rs:15:18 + --> tests/ui/lossy_float_literal.rs:16:18 | LL | let _: f32 = 16_777_219.0; | ^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + let _: f32 = 16_777_220.0; | error: literal cannot be represented as the underlying type without loss of precision - --> tests/ui/lossy_float_literal.rs:16:18 + --> tests/ui/lossy_float_literal.rs:18:18 | LL | let _: f32 = 16_777_219.; | ^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + let _: f32 = 16_777_220.0; | error: literal cannot be represented as the underlying type without loss of precision - --> tests/ui/lossy_float_literal.rs:17:18 + --> tests/ui/lossy_float_literal.rs:20:18 | LL | let _: f32 = 16_777_219.000; | ^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + let _: f32 = 16_777_220.0; | error: literal cannot be represented as the underlying type without loss of precision - --> tests/ui/lossy_float_literal.rs:18:13 + --> tests/ui/lossy_float_literal.rs:22:13 | LL | let _ = 16_777_219f32; | ^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + let _ = 16_777_220_f32; | error: literal cannot be represented as the underlying type without loss of precision - --> tests/ui/lossy_float_literal.rs:19:19 + --> tests/ui/lossy_float_literal.rs:24:19 | LL | let _: f32 = -16_777_219.0; | ^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + let _: f32 = -16_777_220.0; | error: literal cannot be represented as the underlying type without loss of precision - --> tests/ui/lossy_float_literal.rs:21:18 + --> tests/ui/lossy_float_literal.rs:27:18 | LL | let _: f64 = 9_007_199_254_740_993.0; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + let _: f64 = 9_007_199_254_740_992.0; | error: literal cannot be represented as the underlying type without loss of precision - --> tests/ui/lossy_float_literal.rs:22:18 + --> tests/ui/lossy_float_literal.rs:29:18 | LL | let _: f64 = 9_007_199_254_740_993.; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL + let _: f64 = 9_007_199_254_740_992.0; | error: literal cannot be represented as the underlying type without loss of precision - --> tests/ui/lossy_float_literal.rs:23:18 + --> tests/ui/lossy_float_literal.rs:31:18 | LL | let _: f64 = 9_007_199_254_740_993.00; | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL + let _: f64 = 9_007_199_254_740_992.0; | error: literal cannot be represented as the underlying type without loss of precision - --> tests/ui/lossy_float_literal.rs:24:13 + --> tests/ui/lossy_float_literal.rs:33:13 | LL | let _ = 9_007_199_254_740_993f64; | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL + let _ = 9_007_199_254_740_992_f64; | error: literal cannot be represented as the underlying type without loss of precision - --> tests/ui/lossy_float_literal.rs:25:19 + --> tests/ui/lossy_float_literal.rs:35:19 | LL | let _: f64 = -9_007_199_254_740_993.0; | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/macro_use_imports.fixed b/tests/ui/macro_use_imports.fixed index 28844fab7479..d12222fce3eb 100644 --- a/tests/ui/macro_use_imports.fixed +++ b/tests/ui/macro_use_imports.fixed @@ -16,12 +16,16 @@ extern crate proc_macro_derive as mini_mac; mod a { use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro}; + //~^ macro_use_imports use mac; use mini_mac::ClippyMiniMacroTest; + //~^ macro_use_imports use mini_mac; use mac::{inner::mut_mut, inner::try_err}; + //~^ macro_use_imports use mac::inner; use mac::inner::nested::string_add; + //~^ macro_use_imports use mac::inner::nested; #[derive(ClippyMiniMacroTest)] diff --git a/tests/ui/macro_use_imports.rs b/tests/ui/macro_use_imports.rs index 5381f2959898..3baa9f8b5e59 100644 --- a/tests/ui/macro_use_imports.rs +++ b/tests/ui/macro_use_imports.rs @@ -16,12 +16,16 @@ extern crate proc_macro_derive as mini_mac; mod a { #[macro_use] + //~^ macro_use_imports use mac; #[macro_use] + //~^ macro_use_imports use mini_mac; #[macro_use] + //~^ macro_use_imports use mac::inner; #[macro_use] + //~^ macro_use_imports use mac::inner::nested; #[derive(ClippyMiniMacroTest)] diff --git a/tests/ui/macro_use_imports.stderr b/tests/ui/macro_use_imports.stderr index ea0670d36667..cdef5bc79e0c 100644 --- a/tests/ui/macro_use_imports.stderr +++ b/tests/ui/macro_use_imports.stderr @@ -8,19 +8,19 @@ LL | #[macro_use] = help: to override `-D warnings` add `#[allow(clippy::macro_use_imports)]` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> tests/ui/macro_use_imports.rs:22:5 + --> tests/ui/macro_use_imports.rs:24:5 | LL | #[macro_use] | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::mut_mut, inner::try_err};` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> tests/ui/macro_use_imports.rs:24:5 + --> tests/ui/macro_use_imports.rs:27:5 | LL | #[macro_use] | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> tests/ui/macro_use_imports.rs:20:5 + --> tests/ui/macro_use_imports.rs:21:5 | LL | #[macro_use] | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;` diff --git a/tests/ui/macro_use_imports_expect.rs b/tests/ui/macro_use_imports_expect.rs index 60cce1d24a28..115b30d3877f 100644 --- a/tests/ui/macro_use_imports_expect.rs +++ b/tests/ui/macro_use_imports_expect.rs @@ -1,3 +1,4 @@ +//@ check-pass //@aux-build:macro_rules.rs //@aux-build:macro_use_helper.rs //@aux-build:proc_macro_derive.rs diff --git a/tests/ui/manual_arithmetic_check-2.rs b/tests/ui/manual_arithmetic_check-2.rs index e97e3bdfef76..749d15f1cbd8 100644 --- a/tests/ui/manual_arithmetic_check-2.rs +++ b/tests/ui/manual_arithmetic_check-2.rs @@ -7,18 +7,22 @@ fn main() { let b = 13u32; let result = if a > b { b - a } else { 0 }; - //~^ ERROR: inverted arithmetic check before subtraction + //~^ inverted_saturating_sub + let result = if b < a { b - a } else { 0 }; - //~^ ERROR: inverted arithmetic check before subtraction + //~^ inverted_saturating_sub let result = if a > b { 0 } else { a - b }; - //~^ ERROR: inverted arithmetic check before subtraction + //~^ inverted_saturating_sub + let result = if a >= b { 0 } else { a - b }; - //~^ ERROR: inverted arithmetic check before subtraction + //~^ inverted_saturating_sub + let result = if b < a { 0 } else { a - b }; - //~^ ERROR: inverted arithmetic check before subtraction + //~^ inverted_saturating_sub + let result = if b <= a { 0 } else { a - b }; - //~^ ERROR: inverted arithmetic check before subtraction + //~^ inverted_saturating_sub let af = 12f32; let bf = 13f32; diff --git a/tests/ui/manual_arithmetic_check-2.stderr b/tests/ui/manual_arithmetic_check-2.stderr index 4121aa7464f0..8841210befda 100644 --- a/tests/ui/manual_arithmetic_check-2.stderr +++ b/tests/ui/manual_arithmetic_check-2.stderr @@ -12,61 +12,61 @@ LL | let result = if a > b { b - a } else { 0 }; = note: `#[deny(clippy::inverted_saturating_sub)]` on by default error: inverted arithmetic check before subtraction - --> tests/ui/manual_arithmetic_check-2.rs:11:23 + --> tests/ui/manual_arithmetic_check-2.rs:12:23 | LL | let result = if b < a { b - a } else { 0 }; | ^ ----- help: try replacing it with: `a - b` | note: this subtraction underflows when `b < a` - --> tests/ui/manual_arithmetic_check-2.rs:11:29 + --> tests/ui/manual_arithmetic_check-2.rs:12:29 | LL | let result = if b < a { b - a } else { 0 }; | ^^^^^ error: inverted arithmetic check before subtraction - --> tests/ui/manual_arithmetic_check-2.rs:14:23 + --> tests/ui/manual_arithmetic_check-2.rs:15:23 | LL | let result = if a > b { 0 } else { a - b }; | ^ ----- help: try replacing it with: `b - a` | note: this subtraction underflows when `a < b` - --> tests/ui/manual_arithmetic_check-2.rs:14:40 + --> tests/ui/manual_arithmetic_check-2.rs:15:40 | LL | let result = if a > b { 0 } else { a - b }; | ^^^^^ error: inverted arithmetic check before subtraction - --> tests/ui/manual_arithmetic_check-2.rs:16:23 + --> tests/ui/manual_arithmetic_check-2.rs:18:23 | LL | let result = if a >= b { 0 } else { a - b }; | ^^ ----- help: try replacing it with: `b - a` | note: this subtraction underflows when `a < b` - --> tests/ui/manual_arithmetic_check-2.rs:16:41 + --> tests/ui/manual_arithmetic_check-2.rs:18:41 | LL | let result = if a >= b { 0 } else { a - b }; | ^^^^^ error: inverted arithmetic check before subtraction - --> tests/ui/manual_arithmetic_check-2.rs:18:23 + --> tests/ui/manual_arithmetic_check-2.rs:21:23 | LL | let result = if b < a { 0 } else { a - b }; | ^ ----- help: try replacing it with: `b - a` | note: this subtraction underflows when `a < b` - --> tests/ui/manual_arithmetic_check-2.rs:18:40 + --> tests/ui/manual_arithmetic_check-2.rs:21:40 | LL | let result = if b < a { 0 } else { a - b }; | ^^^^^ error: inverted arithmetic check before subtraction - --> tests/ui/manual_arithmetic_check-2.rs:20:23 + --> tests/ui/manual_arithmetic_check-2.rs:24:23 | LL | let result = if b <= a { 0 } else { a - b }; | ^^ ----- help: try replacing it with: `b - a` | note: this subtraction underflows when `a < b` - --> tests/ui/manual_arithmetic_check-2.rs:20:41 + --> tests/ui/manual_arithmetic_check-2.rs:24:41 | LL | let result = if b <= a { 0 } else { a - b }; | ^^^^^ diff --git a/tests/ui/manual_arithmetic_check.fixed b/tests/ui/manual_arithmetic_check.fixed index 29ecbb9ad2ad..99ed1faf90a6 100644 --- a/tests/ui/manual_arithmetic_check.fixed +++ b/tests/ui/manual_arithmetic_check.fixed @@ -7,14 +7,16 @@ fn main() { let c = 8u32; let result = a.saturating_sub(b); - //~^ ERROR: manual arithmetic check found - let result = a.saturating_sub(b); - //~^ ERROR: manual arithmetic check found + //~^ implicit_saturating_sub let result = a.saturating_sub(b); - //~^ ERROR: manual arithmetic check found + //~^ implicit_saturating_sub + let result = a.saturating_sub(b); - //~^ ERROR: manual arithmetic check found + //~^ implicit_saturating_sub + + let result = a.saturating_sub(b); + //~^ implicit_saturating_sub // Should not warn! let result = if a > b { a - b } else { a - c }; diff --git a/tests/ui/manual_arithmetic_check.rs b/tests/ui/manual_arithmetic_check.rs index 69554c6b61ca..cf202fa35a6a 100644 --- a/tests/ui/manual_arithmetic_check.rs +++ b/tests/ui/manual_arithmetic_check.rs @@ -7,14 +7,16 @@ fn main() { let c = 8u32; let result = if a > b { a - b } else { 0 }; - //~^ ERROR: manual arithmetic check found + //~^ implicit_saturating_sub + let result = if b < a { a - b } else { 0 }; - //~^ ERROR: manual arithmetic check found + //~^ implicit_saturating_sub let result = if a < b { 0 } else { a - b }; - //~^ ERROR: manual arithmetic check found + //~^ implicit_saturating_sub + let result = if b > a { 0 } else { a - b }; - //~^ ERROR: manual arithmetic check found + //~^ implicit_saturating_sub // Should not warn! let result = if a > b { a - b } else { a - c }; diff --git a/tests/ui/manual_arithmetic_check.stderr b/tests/ui/manual_arithmetic_check.stderr index b0cf73cd9151..b1598a5d06dc 100644 --- a/tests/ui/manual_arithmetic_check.stderr +++ b/tests/ui/manual_arithmetic_check.stderr @@ -8,19 +8,19 @@ LL | let result = if a > b { a - b } else { 0 }; = help: to override `-D warnings` add `#[allow(clippy::implicit_saturating_sub)]` error: manual arithmetic check found - --> tests/ui/manual_arithmetic_check.rs:11:18 + --> tests/ui/manual_arithmetic_check.rs:12:18 | LL | let result = if b < a { a - b } else { 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b)` error: manual arithmetic check found - --> tests/ui/manual_arithmetic_check.rs:14:18 + --> tests/ui/manual_arithmetic_check.rs:15:18 | LL | let result = if a < b { 0 } else { a - b }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b)` error: manual arithmetic check found - --> tests/ui/manual_arithmetic_check.rs:16:18 + --> tests/ui/manual_arithmetic_check.rs:18:18 | LL | let result = if b > a { 0 } else { a - b }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b)` diff --git a/tests/ui/manual_assert.edition2018.stderr b/tests/ui/manual_assert.edition2018.stderr index dfccf7e99396..8cedf2c68636 100644 --- a/tests/ui/manual_assert.edition2018.stderr +++ b/tests/ui/manual_assert.edition2018.stderr @@ -2,76 +2,155 @@ error: only a `panic!` in `if`-then statement --> tests/ui/manual_assert.rs:32:5 | LL | / if !a.is_empty() { +LL | | LL | | panic!("qaqaq{:?}", a); LL | | } - | |_____^ help: try instead: `assert!(a.is_empty(), "qaqaq{:?}", a);` + | |_____^ | = note: `-D clippy::manual-assert` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::manual_assert)]` +help: try instead + | +LL - if !a.is_empty() { +LL - +LL - panic!("qaqaq{:?}", a); +LL - } +LL + assert!(a.is_empty(), "qaqaq{:?}", a); + | error: only a `panic!` in `if`-then statement - --> tests/ui/manual_assert.rs:35:5 + --> tests/ui/manual_assert.rs:36:5 | LL | / if !a.is_empty() { +LL | | LL | | panic!("qwqwq"); LL | | } - | |_____^ help: try instead: `assert!(a.is_empty(), "qwqwq");` + | |_____^ + | +help: try instead + | +LL - if !a.is_empty() { +LL - +LL - panic!("qwqwq"); +LL - } +LL + assert!(a.is_empty(), "qwqwq"); + | error: only a `panic!` in `if`-then statement - --> tests/ui/manual_assert.rs:52:5 + --> tests/ui/manual_assert.rs:54:5 | LL | / if b.is_empty() { +LL | | LL | | panic!("panic1"); LL | | } - | |_____^ help: try instead: `assert!(!b.is_empty(), "panic1");` - -error: only a `panic!` in `if`-then statement - --> tests/ui/manual_assert.rs:55:5 + | |_____^ + | +help: try instead + | +LL - if b.is_empty() { +LL - +LL - panic!("panic1"); +LL - } +LL + assert!(!b.is_empty(), "panic1"); | -LL | / if b.is_empty() && a.is_empty() { -LL | | panic!("panic2"); -LL | | } - | |_____^ help: try instead: `assert!(!(b.is_empty() && a.is_empty()), "panic2");` error: only a `panic!` in `if`-then statement --> tests/ui/manual_assert.rs:58:5 | +LL | / if b.is_empty() && a.is_empty() { +LL | | +LL | | panic!("panic2"); +LL | | } + | |_____^ + | +help: try instead + | +LL - if b.is_empty() && a.is_empty() { +LL - +LL - panic!("panic2"); +LL - } +LL + assert!(!(b.is_empty() && a.is_empty()), "panic2"); + | + +error: only a `panic!` in `if`-then statement + --> tests/ui/manual_assert.rs:62:5 + | LL | / if a.is_empty() && !b.is_empty() { +LL | | LL | | panic!("panic3"); LL | | } - | |_____^ help: try instead: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");` + | |_____^ + | +help: try instead + | +LL - if a.is_empty() && !b.is_empty() { +LL - +LL - panic!("panic3"); +LL - } +LL + assert!(!(a.is_empty() && !b.is_empty()), "panic3"); + | error: only a `panic!` in `if`-then statement - --> tests/ui/manual_assert.rs:61:5 + --> tests/ui/manual_assert.rs:66:5 | LL | / if b.is_empty() || a.is_empty() { +LL | | LL | | panic!("panic4"); LL | | } - | |_____^ help: try instead: `assert!(!(b.is_empty() || a.is_empty()), "panic4");` + | |_____^ + | +help: try instead + | +LL - if b.is_empty() || a.is_empty() { +LL - +LL - panic!("panic4"); +LL - } +LL + assert!(!(b.is_empty() || a.is_empty()), "panic4"); + | error: only a `panic!` in `if`-then statement - --> tests/ui/manual_assert.rs:64:5 + --> tests/ui/manual_assert.rs:70:5 | LL | / if a.is_empty() || !b.is_empty() { +LL | | LL | | panic!("panic5"); LL | | } - | |_____^ help: try instead: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");` + | |_____^ + | +help: try instead + | +LL - if a.is_empty() || !b.is_empty() { +LL - +LL - panic!("panic5"); +LL - } +LL + assert!(!(a.is_empty() || !b.is_empty()), "panic5"); + | error: only a `panic!` in `if`-then statement - --> tests/ui/manual_assert.rs:67:5 + --> tests/ui/manual_assert.rs:74:5 | LL | / if a.is_empty() { +LL | | LL | | panic!("with expansion {}", one!()) LL | | } - | |_____^ help: try instead: `assert!(!a.is_empty(), "with expansion {}", one!());` + | |_____^ + | +help: try instead + | +LL - if a.is_empty() { +LL - +LL - panic!("with expansion {}", one!()) +LL - } +LL + assert!(!a.is_empty(), "with expansion {}", one!()); + | error: only a `panic!` in `if`-then statement - --> tests/ui/manual_assert.rs:79:5 + --> tests/ui/manual_assert.rs:87:5 | LL | / if a > 2 { +LL | | LL | | // comment LL | | /* this is a -LL | | multiline ... | LL | | panic!("panic with comment") // comment after `panic!` LL | | } @@ -80,6 +159,7 @@ LL | | } help: try instead | LL - if a > 2 { +LL - LL - // comment LL - /* this is a LL - multiline @@ -91,13 +171,23 @@ LL + assert!(!(a > 2), "panic with comment"); | error: only a `panic!` in `if`-then statement - --> tests/ui/manual_assert.rs:93:25 + --> tests/ui/manual_assert.rs:102:25 | LL | const BAR: () = if N == 0 { | _________________________^ +LL | | LL | | panic!() LL | | }; - | |_________^ help: try instead: `assert!(!(N == 0), )` + | |_________^ + | +help: try instead + | +LL - const BAR: () = if N == 0 { +LL - +LL - panic!() +LL - }; +LL + const BAR: () = assert!(!(N == 0), ); + | error: aborting due to 10 previous errors diff --git a/tests/ui/manual_assert.edition2021.stderr b/tests/ui/manual_assert.edition2021.stderr index dfccf7e99396..8cedf2c68636 100644 --- a/tests/ui/manual_assert.edition2021.stderr +++ b/tests/ui/manual_assert.edition2021.stderr @@ -2,76 +2,155 @@ error: only a `panic!` in `if`-then statement --> tests/ui/manual_assert.rs:32:5 | LL | / if !a.is_empty() { +LL | | LL | | panic!("qaqaq{:?}", a); LL | | } - | |_____^ help: try instead: `assert!(a.is_empty(), "qaqaq{:?}", a);` + | |_____^ | = note: `-D clippy::manual-assert` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::manual_assert)]` +help: try instead + | +LL - if !a.is_empty() { +LL - +LL - panic!("qaqaq{:?}", a); +LL - } +LL + assert!(a.is_empty(), "qaqaq{:?}", a); + | error: only a `panic!` in `if`-then statement - --> tests/ui/manual_assert.rs:35:5 + --> tests/ui/manual_assert.rs:36:5 | LL | / if !a.is_empty() { +LL | | LL | | panic!("qwqwq"); LL | | } - | |_____^ help: try instead: `assert!(a.is_empty(), "qwqwq");` + | |_____^ + | +help: try instead + | +LL - if !a.is_empty() { +LL - +LL - panic!("qwqwq"); +LL - } +LL + assert!(a.is_empty(), "qwqwq"); + | error: only a `panic!` in `if`-then statement - --> tests/ui/manual_assert.rs:52:5 + --> tests/ui/manual_assert.rs:54:5 | LL | / if b.is_empty() { +LL | | LL | | panic!("panic1"); LL | | } - | |_____^ help: try instead: `assert!(!b.is_empty(), "panic1");` - -error: only a `panic!` in `if`-then statement - --> tests/ui/manual_assert.rs:55:5 + | |_____^ + | +help: try instead + | +LL - if b.is_empty() { +LL - +LL - panic!("panic1"); +LL - } +LL + assert!(!b.is_empty(), "panic1"); | -LL | / if b.is_empty() && a.is_empty() { -LL | | panic!("panic2"); -LL | | } - | |_____^ help: try instead: `assert!(!(b.is_empty() && a.is_empty()), "panic2");` error: only a `panic!` in `if`-then statement --> tests/ui/manual_assert.rs:58:5 | +LL | / if b.is_empty() && a.is_empty() { +LL | | +LL | | panic!("panic2"); +LL | | } + | |_____^ + | +help: try instead + | +LL - if b.is_empty() && a.is_empty() { +LL - +LL - panic!("panic2"); +LL - } +LL + assert!(!(b.is_empty() && a.is_empty()), "panic2"); + | + +error: only a `panic!` in `if`-then statement + --> tests/ui/manual_assert.rs:62:5 + | LL | / if a.is_empty() && !b.is_empty() { +LL | | LL | | panic!("panic3"); LL | | } - | |_____^ help: try instead: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");` + | |_____^ + | +help: try instead + | +LL - if a.is_empty() && !b.is_empty() { +LL - +LL - panic!("panic3"); +LL - } +LL + assert!(!(a.is_empty() && !b.is_empty()), "panic3"); + | error: only a `panic!` in `if`-then statement - --> tests/ui/manual_assert.rs:61:5 + --> tests/ui/manual_assert.rs:66:5 | LL | / if b.is_empty() || a.is_empty() { +LL | | LL | | panic!("panic4"); LL | | } - | |_____^ help: try instead: `assert!(!(b.is_empty() || a.is_empty()), "panic4");` + | |_____^ + | +help: try instead + | +LL - if b.is_empty() || a.is_empty() { +LL - +LL - panic!("panic4"); +LL - } +LL + assert!(!(b.is_empty() || a.is_empty()), "panic4"); + | error: only a `panic!` in `if`-then statement - --> tests/ui/manual_assert.rs:64:5 + --> tests/ui/manual_assert.rs:70:5 | LL | / if a.is_empty() || !b.is_empty() { +LL | | LL | | panic!("panic5"); LL | | } - | |_____^ help: try instead: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");` + | |_____^ + | +help: try instead + | +LL - if a.is_empty() || !b.is_empty() { +LL - +LL - panic!("panic5"); +LL - } +LL + assert!(!(a.is_empty() || !b.is_empty()), "panic5"); + | error: only a `panic!` in `if`-then statement - --> tests/ui/manual_assert.rs:67:5 + --> tests/ui/manual_assert.rs:74:5 | LL | / if a.is_empty() { +LL | | LL | | panic!("with expansion {}", one!()) LL | | } - | |_____^ help: try instead: `assert!(!a.is_empty(), "with expansion {}", one!());` + | |_____^ + | +help: try instead + | +LL - if a.is_empty() { +LL - +LL - panic!("with expansion {}", one!()) +LL - } +LL + assert!(!a.is_empty(), "with expansion {}", one!()); + | error: only a `panic!` in `if`-then statement - --> tests/ui/manual_assert.rs:79:5 + --> tests/ui/manual_assert.rs:87:5 | LL | / if a > 2 { +LL | | LL | | // comment LL | | /* this is a -LL | | multiline ... | LL | | panic!("panic with comment") // comment after `panic!` LL | | } @@ -80,6 +159,7 @@ LL | | } help: try instead | LL - if a > 2 { +LL - LL - // comment LL - /* this is a LL - multiline @@ -91,13 +171,23 @@ LL + assert!(!(a > 2), "panic with comment"); | error: only a `panic!` in `if`-then statement - --> tests/ui/manual_assert.rs:93:25 + --> tests/ui/manual_assert.rs:102:25 | LL | const BAR: () = if N == 0 { | _________________________^ +LL | | LL | | panic!() LL | | }; - | |_________^ help: try instead: `assert!(!(N == 0), )` + | |_________^ + | +help: try instead + | +LL - const BAR: () = if N == 0 { +LL - +LL - panic!() +LL - }; +LL + const BAR: () = assert!(!(N == 0), ); + | error: aborting due to 10 previous errors diff --git a/tests/ui/manual_assert.rs b/tests/ui/manual_assert.rs index 6337920a3eea..46a42c3d00af 100644 --- a/tests/ui/manual_assert.rs +++ b/tests/ui/manual_assert.rs @@ -30,9 +30,11 @@ fn main() { panic!("qaqaq{:?}", a); } if !a.is_empty() { + //~^ manual_assert panic!("qaqaq{:?}", a); } if !a.is_empty() { + //~^ manual_assert panic!("qwqwq"); } if a.len() == 3 { @@ -50,21 +52,27 @@ fn main() { } let b = vec![1, 2, 3]; if b.is_empty() { + //~^ manual_assert panic!("panic1"); } if b.is_empty() && a.is_empty() { + //~^ manual_assert panic!("panic2"); } if a.is_empty() && !b.is_empty() { + //~^ manual_assert panic!("panic3"); } if b.is_empty() || a.is_empty() { + //~^ manual_assert panic!("panic4"); } if a.is_empty() || !b.is_empty() { + //~^ manual_assert panic!("panic5"); } if a.is_empty() { + //~^ manual_assert panic!("with expansion {}", one!()) } if a.is_empty() { @@ -77,6 +85,7 @@ fn main() { fn issue7730(a: u8) { // Suggestion should preserve comment if a > 2 { + //~^ manual_assert // comment /* this is a multiline @@ -91,6 +100,7 @@ fn issue12505() { impl Foo { const BAR: () = if N == 0 { + //~^ manual_assert panic!() }; } diff --git a/tests/ui/manual_async_fn.fixed b/tests/ui/manual_async_fn.fixed index dc1cb8e11fca..ad0266d39e98 100644 --- a/tests/ui/manual_async_fn.fixed +++ b/tests/ui/manual_async_fn.fixed @@ -113,4 +113,30 @@ pub(crate) async fn issue_10450_2() -> i32 { 42 } pub(self) async fn issue_10450_3() -> i32 { 42 } +macro_rules! issue_12407 { + ( + $( + $(#[$m:meta])* + $v:vis $(override($($overrides:tt),* $(,)?))? fn $name:ident $([$($params:tt)*])? ( + $($arg_name:ident: $arg_typ:ty),* $(,)? + ) $(-> $ret_ty:ty)? = $e:expr; + )* + ) => { + $( + $(#[$m])* + $v $($($overrides)*)? fn $name$(<$($params)*>)?( + $($arg_name: $arg_typ),* + ) $(-> $ret_ty)? { + $e + } + )* + }; +} + +issue_12407! { + fn _hello() -> impl Future = async {}; + fn non_async() = println!("hello"); + fn foo() = non_async(); +} + fn main() {} diff --git a/tests/ui/manual_async_fn.rs b/tests/ui/manual_async_fn.rs index 9ca7654a3688..fe367b4bc7b9 100644 --- a/tests/ui/manual_async_fn.rs +++ b/tests/ui/manual_async_fn.rs @@ -4,34 +4,41 @@ use std::future::Future; fn fut() -> impl Future { + //~^ manual_async_fn async { 42 } } #[rustfmt::skip] fn fut2() ->impl Future { +//~^ manual_async_fn async { 42 } } #[rustfmt::skip] fn fut3()-> impl Future { +//~^ manual_async_fn async { 42 } } fn empty_fut() -> impl Future { + //~^ manual_async_fn async {} } #[rustfmt::skip] fn empty_fut2() ->impl Future { +//~^ manual_async_fn async {} } #[rustfmt::skip] fn empty_fut3()-> impl Future { +//~^ manual_async_fn async {} } fn core_fut() -> impl core::future::Future { + //~^ manual_async_fn async move { 42 } } @@ -54,6 +61,7 @@ async fn already_async() -> impl Future { struct S; impl S { fn inh_fut() -> impl Future { + //~^ manual_async_fn async { // NOTE: this code is here just to check that the indentation is correct in the suggested fix let a = 42; @@ -89,6 +97,7 @@ impl S { // Tests related to lifetime capture fn elided(_: &i32) -> impl Future + '_ { + //~^ manual_async_fn async { 42 } } @@ -99,6 +108,7 @@ fn elided_not_bound(_: &i32) -> impl Future { #[allow(clippy::needless_lifetimes)] fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future + 'a + 'b { + //~^ manual_async_fn async { 42 } } @@ -128,15 +138,44 @@ mod issue_5765 { } pub fn issue_10450() -> impl Future { + //~^ manual_async_fn async { 42 } } pub(crate) fn issue_10450_2() -> impl Future { + //~^ manual_async_fn async { 42 } } pub(self) fn issue_10450_3() -> impl Future { + //~^ manual_async_fn async { 42 } } +macro_rules! issue_12407 { + ( + $( + $(#[$m:meta])* + $v:vis $(override($($overrides:tt),* $(,)?))? fn $name:ident $([$($params:tt)*])? ( + $($arg_name:ident: $arg_typ:ty),* $(,)? + ) $(-> $ret_ty:ty)? = $e:expr; + )* + ) => { + $( + $(#[$m])* + $v $($($overrides)*)? fn $name$(<$($params)*>)?( + $($arg_name: $arg_typ),* + ) $(-> $ret_ty)? { + $e + } + )* + }; +} + +issue_12407! { + fn _hello() -> impl Future = async {}; + fn non_async() = println!("hello"); + fn foo() = non_async(); +} + fn main() {} diff --git a/tests/ui/manual_async_fn.stderr b/tests/ui/manual_async_fn.stderr index a7cfc30fb69c..54a9b1d40a11 100644 --- a/tests/ui/manual_async_fn.stderr +++ b/tests/ui/manual_async_fn.stderr @@ -13,7 +13,7 @@ LL + async fn fut() -> i32 { 42 } | error: this function can be simplified using the `async fn` syntax - --> tests/ui/manual_async_fn.rs:11:1 + --> tests/ui/manual_async_fn.rs:12:1 | LL | fn fut2() ->impl Future { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + async fn fut2() -> i32 { 42 } | error: this function can be simplified using the `async fn` syntax - --> tests/ui/manual_async_fn.rs:16:1 + --> tests/ui/manual_async_fn.rs:18:1 | LL | fn fut3()-> impl Future { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + async fn fut3() -> i32 { 42 } | error: this function can be simplified using the `async fn` syntax - --> tests/ui/manual_async_fn.rs:20:1 + --> tests/ui/manual_async_fn.rs:23:1 | LL | fn empty_fut() -> impl Future { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + async fn empty_fut() {} | error: this function can be simplified using the `async fn` syntax - --> tests/ui/manual_async_fn.rs:25:1 + --> tests/ui/manual_async_fn.rs:29:1 | LL | fn empty_fut2() ->impl Future { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + async fn empty_fut2() {} | error: this function can be simplified using the `async fn` syntax - --> tests/ui/manual_async_fn.rs:30:1 + --> tests/ui/manual_async_fn.rs:35:1 | LL | fn empty_fut3()-> impl Future { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + async fn empty_fut3() {} | error: this function can be simplified using the `async fn` syntax - --> tests/ui/manual_async_fn.rs:34:1 + --> tests/ui/manual_async_fn.rs:40:1 | LL | fn core_fut() -> impl core::future::Future { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + async fn core_fut() -> i32 { 42 } | error: this function can be simplified using the `async fn` syntax - --> tests/ui/manual_async_fn.rs:56:5 + --> tests/ui/manual_async_fn.rs:63:5 | LL | fn inh_fut() -> impl Future { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -108,7 +108,7 @@ LL + } | error: this function can be simplified using the `async fn` syntax - --> tests/ui/manual_async_fn.rs:91:1 + --> tests/ui/manual_async_fn.rs:99:1 | LL | fn elided(_: &i32) -> impl Future + '_ { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -120,7 +120,7 @@ LL + async fn elided(_: &i32) -> i32 { 42 } | error: this function can be simplified using the `async fn` syntax - --> tests/ui/manual_async_fn.rs:101:1 + --> tests/ui/manual_async_fn.rs:110:1 | LL | fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future + 'a + 'b { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -132,7 +132,7 @@ LL + async fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> i32 { 42 } | error: this function can be simplified using the `async fn` syntax - --> tests/ui/manual_async_fn.rs:130:1 + --> tests/ui/manual_async_fn.rs:140:1 | LL | pub fn issue_10450() -> impl Future { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -144,7 +144,7 @@ LL + pub async fn issue_10450() -> i32 { 42 } | error: this function can be simplified using the `async fn` syntax - --> tests/ui/manual_async_fn.rs:134:1 + --> tests/ui/manual_async_fn.rs:145:1 | LL | pub(crate) fn issue_10450_2() -> impl Future { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -156,7 +156,7 @@ LL + pub(crate) async fn issue_10450_2() -> i32 { 42 } | error: this function can be simplified using the `async fn` syntax - --> tests/ui/manual_async_fn.rs:138:1 + --> tests/ui/manual_async_fn.rs:150:1 | LL | pub(self) fn issue_10450_3() -> impl Future { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/manual_bits.fixed b/tests/ui/manual_bits.fixed index 8e5cb7d38b9b..db2ad2ace625 100644 --- a/tests/ui/manual_bits.fixed +++ b/tests/ui/manual_bits.fixed @@ -12,32 +12,56 @@ use std::mem::{size_of, size_of_val}; fn main() { i8::BITS as usize; + //~^ manual_bits i16::BITS as usize; + //~^ manual_bits i32::BITS as usize; + //~^ manual_bits i64::BITS as usize; + //~^ manual_bits i128::BITS as usize; + //~^ manual_bits isize::BITS as usize; + //~^ manual_bits u8::BITS as usize; + //~^ manual_bits u16::BITS as usize; + //~^ manual_bits u32::BITS as usize; + //~^ manual_bits u64::BITS as usize; + //~^ manual_bits u128::BITS as usize; + //~^ manual_bits usize::BITS as usize; + //~^ manual_bits i8::BITS as usize; + //~^ manual_bits i16::BITS as usize; + //~^ manual_bits i32::BITS as usize; + //~^ manual_bits i64::BITS as usize; + //~^ manual_bits i128::BITS as usize; + //~^ manual_bits isize::BITS as usize; + //~^ manual_bits u8::BITS as usize; + //~^ manual_bits u16::BITS as usize; + //~^ manual_bits u32::BITS as usize; + //~^ manual_bits u64::BITS as usize; + //~^ manual_bits u128::BITS as usize; + //~^ manual_bits usize::BITS as usize; + //~^ manual_bits size_of::() * 4; 4 * size_of::(); @@ -48,13 +72,18 @@ fn main() { type Word = u32; Word::BITS as usize; + //~^ manual_bits type Bool = bool; size_of::() * 8; let _: u32 = u128::BITS as u32; + //~^ manual_bits let _: u32 = u128::BITS.try_into().unwrap(); + //~^ manual_bits let _ = (u128::BITS as usize).pow(5); + //~^ manual_bits let _ = &(u128::BITS as usize); + //~^ manual_bits } fn should_not_lint() { diff --git a/tests/ui/manual_bits.rs b/tests/ui/manual_bits.rs index 5e492ed15d21..6d1f0de1c19d 100644 --- a/tests/ui/manual_bits.rs +++ b/tests/ui/manual_bits.rs @@ -12,32 +12,56 @@ use std::mem::{size_of, size_of_val}; fn main() { size_of::() * 8; + //~^ manual_bits size_of::() * 8; + //~^ manual_bits size_of::() * 8; + //~^ manual_bits size_of::() * 8; + //~^ manual_bits size_of::() * 8; + //~^ manual_bits size_of::() * 8; + //~^ manual_bits size_of::() * 8; + //~^ manual_bits size_of::() * 8; + //~^ manual_bits size_of::() * 8; + //~^ manual_bits size_of::() * 8; + //~^ manual_bits size_of::() * 8; + //~^ manual_bits size_of::() * 8; + //~^ manual_bits 8 * size_of::(); + //~^ manual_bits 8 * size_of::(); + //~^ manual_bits 8 * size_of::(); + //~^ manual_bits 8 * size_of::(); + //~^ manual_bits 8 * size_of::(); + //~^ manual_bits 8 * size_of::(); + //~^ manual_bits 8 * size_of::(); + //~^ manual_bits 8 * size_of::(); + //~^ manual_bits 8 * size_of::(); + //~^ manual_bits 8 * size_of::(); + //~^ manual_bits 8 * size_of::(); + //~^ manual_bits 8 * size_of::(); + //~^ manual_bits size_of::() * 4; 4 * size_of::(); @@ -48,13 +72,18 @@ fn main() { type Word = u32; size_of::() * 8; + //~^ manual_bits type Bool = bool; size_of::() * 8; let _: u32 = (size_of::() * 8) as u32; + //~^ manual_bits let _: u32 = (size_of::() * 8).try_into().unwrap(); + //~^ manual_bits let _ = (size_of::() * 8).pow(5); + //~^ manual_bits let _ = &(size_of::() * 8); + //~^ manual_bits } fn should_not_lint() { diff --git a/tests/ui/manual_bits.stderr b/tests/ui/manual_bits.stderr index 4383aa49df9b..a50975ed474e 100644 --- a/tests/ui/manual_bits.stderr +++ b/tests/ui/manual_bits.stderr @@ -8,169 +8,169 @@ LL | size_of::() * 8; = help: to override `-D warnings` add `#[allow(clippy::manual_bits)]` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:15:5 + --> tests/ui/manual_bits.rs:16:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i16::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:16:5 + --> tests/ui/manual_bits.rs:18:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i32::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:17:5 + --> tests/ui/manual_bits.rs:20:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i64::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:18:5 + --> tests/ui/manual_bits.rs:22:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `i128::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:19:5 + --> tests/ui/manual_bits.rs:24:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `isize::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:21:5 + --> tests/ui/manual_bits.rs:27:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^ help: consider using: `u8::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:22:5 + --> tests/ui/manual_bits.rs:29:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u16::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:23:5 + --> tests/ui/manual_bits.rs:31:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u32::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:24:5 + --> tests/ui/manual_bits.rs:33:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u64::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:25:5 + --> tests/ui/manual_bits.rs:35:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `u128::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:26:5 + --> tests/ui/manual_bits.rs:37:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `usize::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:28:5 + --> tests/ui/manual_bits.rs:40:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `i8::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:29:5 + --> tests/ui/manual_bits.rs:42:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i16::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:30:5 + --> tests/ui/manual_bits.rs:44:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i32::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:31:5 + --> tests/ui/manual_bits.rs:46:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i64::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:32:5 + --> tests/ui/manual_bits.rs:48:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `i128::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:33:5 + --> tests/ui/manual_bits.rs:50:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `isize::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:35:5 + --> tests/ui/manual_bits.rs:53:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `u8::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:36:5 + --> tests/ui/manual_bits.rs:55:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u16::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:37:5 + --> tests/ui/manual_bits.rs:57:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u32::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:38:5 + --> tests/ui/manual_bits.rs:59:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u64::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:39:5 + --> tests/ui/manual_bits.rs:61:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `u128::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:40:5 + --> tests/ui/manual_bits.rs:63:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `usize::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:50:5 + --> tests/ui/manual_bits.rs:74:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `Word::BITS as usize` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:54:18 + --> tests/ui/manual_bits.rs:79:18 | LL | let _: u32 = (size_of::() * 8) as u32; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `u128::BITS` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:55:18 + --> tests/ui/manual_bits.rs:81:18 | LL | let _: u32 = (size_of::() * 8).try_into().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `u128::BITS` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:56:13 + --> tests/ui/manual_bits.rs:83:13 | LL | let _ = (size_of::() * 8).pow(5); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(u128::BITS as usize)` error: usage of `mem::size_of::()` to obtain the size of `T` in bits - --> tests/ui/manual_bits.rs:57:14 + --> tests/ui/manual_bits.rs:85:14 | LL | let _ = &(size_of::() * 8); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(u128::BITS as usize)` diff --git a/tests/ui/manual_c_str_literals.edition2021.fixed b/tests/ui/manual_c_str_literals.edition2021.fixed index 391c63bb4b89..3ffaef0386ce 100644 --- a/tests/ui/manual_c_str_literals.edition2021.fixed +++ b/tests/ui/manual_c_str_literals.edition2021.fixed @@ -1,6 +1,7 @@ //@revisions: edition2018 edition2021 //@[edition2018] edition:2018 //@[edition2021] edition:2021 +//@[edition2018] check-pass #![warn(clippy::manual_c_str_literals)] #![allow(clippy::no_effect)] @@ -32,29 +33,42 @@ fn pre_stabilization() { #[clippy::msrv = "1.77.0"] fn post_stabilization() { c"foo"; + //~[edition2021]^ manual_c_str_literals } fn main() { c"foo"; + //~[edition2021]^ manual_c_str_literals c"foo"; + //~[edition2021]^ manual_c_str_literals c"foo"; + //~[edition2021]^ manual_c_str_literals c"foo\\0sdsd"; + //~[edition2021]^ manual_c_str_literals CStr::from_bytes_with_nul(br"foo\\0sdsd\0").unwrap(); CStr::from_bytes_with_nul(br"foo\x00").unwrap(); CStr::from_bytes_with_nul(br##"foo#a\0"##).unwrap(); unsafe { c"foo" }; + //~[edition2021]^ manual_c_str_literals unsafe { c"foo" }; + //~[edition2021]^ manual_c_str_literals let _: *const _ = c"foo".as_ptr(); + //~[edition2021]^ manual_c_str_literals let _: *const _ = c"foo".as_ptr(); + //~[edition2021]^ manual_c_str_literals let _: *const _ = "foo".as_ptr(); // not a C-string let _: *const _ = "".as_ptr(); let _: *const _ = c"foo".as_ptr().cast::(); + //~[edition2021]^ manual_c_str_literals let _ = "电脑".as_ptr(); let _ = "电脑\\".as_ptr(); let _ = c"电脑\\".as_ptr(); + //~[edition2021]^ manual_c_str_literals let _ = c"电脑".as_ptr(); + //~[edition2021]^ manual_c_str_literals let _ = c"电脑".as_ptr(); + //~[edition2021]^ manual_c_str_literals // Macro cases, don't lint: cstr!("foo"); diff --git a/tests/ui/manual_c_str_literals.edition2021.stderr b/tests/ui/manual_c_str_literals.edition2021.stderr index beab29ccdda0..2119bbc5b425 100644 --- a/tests/ui/manual_c_str_literals.edition2021.stderr +++ b/tests/ui/manual_c_str_literals.edition2021.stderr @@ -1,5 +1,5 @@ error: calling `CStr::new` with a byte string literal - --> tests/ui/manual_c_str_literals.rs:34:5 + --> tests/ui/manual_c_str_literals.rs:35:5 | LL | CStr::from_bytes_with_nul(b"foo\0"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a `c""` literal: `c"foo"` @@ -8,73 +8,73 @@ LL | CStr::from_bytes_with_nul(b"foo\0"); = help: to override `-D warnings` add `#[allow(clippy::manual_c_str_literals)]` error: calling `CStr::new` with a byte string literal - --> tests/ui/manual_c_str_literals.rs:38:5 + --> tests/ui/manual_c_str_literals.rs:40:5 | LL | CStr::from_bytes_with_nul(b"foo\0"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a `c""` literal: `c"foo"` error: calling `CStr::new` with a byte string literal - --> tests/ui/manual_c_str_literals.rs:39:5 + --> tests/ui/manual_c_str_literals.rs:42:5 | LL | CStr::from_bytes_with_nul(b"foo\x00"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a `c""` literal: `c"foo"` error: calling `CStr::new` with a byte string literal - --> tests/ui/manual_c_str_literals.rs:40:5 + --> tests/ui/manual_c_str_literals.rs:44:5 | LL | CStr::from_bytes_with_nul(b"foo\0").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a `c""` literal: `c"foo"` error: calling `CStr::new` with a byte string literal - --> tests/ui/manual_c_str_literals.rs:41:5 + --> tests/ui/manual_c_str_literals.rs:46:5 | LL | CStr::from_bytes_with_nul(b"foo\\0sdsd\0").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a `c""` literal: `c"foo\\0sdsd"` error: calling `CStr::from_ptr` with a byte string literal - --> tests/ui/manual_c_str_literals.rs:46:14 + --> tests/ui/manual_c_str_literals.rs:52:14 | LL | unsafe { CStr::from_ptr(b"foo\0".as_ptr().cast()) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a `c""` literal: `c"foo"` error: calling `CStr::from_ptr` with a byte string literal - --> tests/ui/manual_c_str_literals.rs:47:14 + --> tests/ui/manual_c_str_literals.rs:54:14 | LL | unsafe { CStr::from_ptr(b"foo\0".as_ptr() as *const _) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a `c""` literal: `c"foo"` error: manually constructing a nul-terminated string - --> tests/ui/manual_c_str_literals.rs:48:23 + --> tests/ui/manual_c_str_literals.rs:56:23 | LL | let _: *const _ = b"foo\0".as_ptr(); | ^^^^^^^^ help: use a `c""` literal: `c"foo"` error: manually constructing a nul-terminated string - --> tests/ui/manual_c_str_literals.rs:49:23 + --> tests/ui/manual_c_str_literals.rs:58:23 | LL | let _: *const _ = "foo\0".as_ptr(); | ^^^^^^^ help: use a `c""` literal: `c"foo"` error: manually constructing a nul-terminated string - --> tests/ui/manual_c_str_literals.rs:52:23 + --> tests/ui/manual_c_str_literals.rs:62:23 | LL | let _: *const _ = b"foo\0".as_ptr().cast::(); | ^^^^^^^^ help: use a `c""` literal: `c"foo"` error: manually constructing a nul-terminated string - --> tests/ui/manual_c_str_literals.rs:55:13 + --> tests/ui/manual_c_str_literals.rs:66:13 | LL | let _ = "电脑\\\0".as_ptr(); | ^^^^^^^^^^ help: use a `c""` literal: `c"电脑\\"` error: manually constructing a nul-terminated string - --> tests/ui/manual_c_str_literals.rs:56:13 + --> tests/ui/manual_c_str_literals.rs:68:13 | LL | let _ = "电脑\0".as_ptr(); | ^^^^^^^^ help: use a `c""` literal: `c"电脑"` error: manually constructing a nul-terminated string - --> tests/ui/manual_c_str_literals.rs:57:13 + --> tests/ui/manual_c_str_literals.rs:70:13 | LL | let _ = "电脑\x00".as_ptr(); | ^^^^^^^^^^ help: use a `c""` literal: `c"电脑"` diff --git a/tests/ui/manual_c_str_literals.rs b/tests/ui/manual_c_str_literals.rs index 39b622580774..ec3b8e587724 100644 --- a/tests/ui/manual_c_str_literals.rs +++ b/tests/ui/manual_c_str_literals.rs @@ -1,6 +1,7 @@ //@revisions: edition2018 edition2021 //@[edition2018] edition:2018 //@[edition2021] edition:2021 +//@[edition2018] check-pass #![warn(clippy::manual_c_str_literals)] #![allow(clippy::no_effect)] @@ -32,29 +33,42 @@ fn pre_stabilization() { #[clippy::msrv = "1.77.0"] fn post_stabilization() { CStr::from_bytes_with_nul(b"foo\0"); + //~[edition2021]^ manual_c_str_literals } fn main() { CStr::from_bytes_with_nul(b"foo\0"); + //~[edition2021]^ manual_c_str_literals CStr::from_bytes_with_nul(b"foo\x00"); + //~[edition2021]^ manual_c_str_literals CStr::from_bytes_with_nul(b"foo\0").unwrap(); + //~[edition2021]^ manual_c_str_literals CStr::from_bytes_with_nul(b"foo\\0sdsd\0").unwrap(); + //~[edition2021]^ manual_c_str_literals CStr::from_bytes_with_nul(br"foo\\0sdsd\0").unwrap(); CStr::from_bytes_with_nul(br"foo\x00").unwrap(); CStr::from_bytes_with_nul(br##"foo#a\0"##).unwrap(); unsafe { CStr::from_ptr(b"foo\0".as_ptr().cast()) }; + //~[edition2021]^ manual_c_str_literals unsafe { CStr::from_ptr(b"foo\0".as_ptr() as *const _) }; + //~[edition2021]^ manual_c_str_literals let _: *const _ = b"foo\0".as_ptr(); + //~[edition2021]^ manual_c_str_literals let _: *const _ = "foo\0".as_ptr(); + //~[edition2021]^ manual_c_str_literals let _: *const _ = "foo".as_ptr(); // not a C-string let _: *const _ = "".as_ptr(); let _: *const _ = b"foo\0".as_ptr().cast::(); + //~[edition2021]^ manual_c_str_literals let _ = "电脑".as_ptr(); let _ = "电脑\\".as_ptr(); let _ = "电脑\\\0".as_ptr(); + //~[edition2021]^ manual_c_str_literals let _ = "电脑\0".as_ptr(); + //~[edition2021]^ manual_c_str_literals let _ = "电脑\x00".as_ptr(); + //~[edition2021]^ manual_c_str_literals // Macro cases, don't lint: cstr!("foo"); diff --git a/tests/ui/manual_clamp.fixed b/tests/ui/manual_clamp.fixed index 8d57cbbf51bf..2450a4f4c611 100644 --- a/tests/ui/manual_clamp.fixed +++ b/tests/ui/manual_clamp.fixed @@ -150,12 +150,10 @@ fn const_main() { let x3 = input.clamp(CONST_MIN, CONST_MAX); let x4 = input.clamp(CONST_MIN, CONST_MAX); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp let x5 = input.clamp(CONST_MIN, CONST_MAX); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp let x6 = input.clamp(CONST_MIN, CONST_MAX); @@ -187,54 +185,53 @@ fn const_main() { let input: i32 = cmp_min_max(1); // These can only be detected if exactly one of the arguments to the inner function is const. let x16 = input.clamp(CONST_MIN, CONST_MAX); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + let x17 = input.clamp(CONST_MIN, CONST_MAX); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + let x18 = input.clamp(CONST_MIN, CONST_MAX); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + let x19 = input.clamp(CONST_MIN, CONST_MAX); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + let x20 = input.clamp(CONST_MIN, CONST_MAX); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + let x21 = input.clamp(CONST_MIN, CONST_MAX); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + let x22 = input.clamp(CONST_MIN, CONST_MAX); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + let x23 = input.clamp(CONST_MIN, CONST_MAX); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + let input: f64 = cmp_min_max(1) as f64; let x24 = input.clamp(CONST_F64_MIN, CONST_F64_MAX); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min, min.is_nan(), or max.is_nan() + //~^ manual_clamp + let x25 = input.clamp(CONST_F64_MIN, CONST_F64_MAX); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min, min.is_nan(), or max.is_nan() + //~^ manual_clamp + let x26 = input.clamp(CONST_F64_MIN, CONST_F64_MAX); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min, min.is_nan(), or max.is_nan() + //~^ manual_clamp + let x27 = input.clamp(CONST_F64_MIN, CONST_F64_MAX); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min, min.is_nan(), or max.is_nan() + //~^ manual_clamp + let x28 = input.clamp(CONST_F64_MIN, CONST_F64_MAX); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min, min.is_nan(), or max.is_nan() + //~^ manual_clamp + let x29 = input.clamp(CONST_F64_MIN, CONST_F64_MAX); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min, min.is_nan(), or max.is_nan() + //~^ manual_clamp + let x30 = input.clamp(CONST_F64_MIN, CONST_F64_MAX); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min, min.is_nan(), or max.is_nan() + //~^ manual_clamp + let x31 = input.clamp(CONST_F64_MIN, CONST_F64_MAX); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min, min.is_nan(), or max.is_nan() + //~^ manual_clamp } let mut x32 = input; x32 = x32.clamp(CONST_MIN, CONST_MAX); diff --git a/tests/ui/manual_clamp.rs b/tests/ui/manual_clamp.rs index 4d2a0c47bbd7..ee341d50768f 100644 --- a/tests/ui/manual_clamp.rs +++ b/tests/ui/manual_clamp.rs @@ -142,8 +142,8 @@ fn const_main() { let input = 0; // Min and max are const, so this should trigger the lint. let x0 = if CONST_MAX < input { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + CONST_MAX } else if CONST_MIN > input { CONST_MIN @@ -152,8 +152,8 @@ fn const_main() { }; let x1 = if input > CONST_MAX { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + CONST_MAX } else if input < CONST_MIN { CONST_MIN @@ -162,8 +162,8 @@ fn const_main() { }; let x2 = if input < CONST_MIN { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + CONST_MIN } else if input > CONST_MAX { CONST_MAX @@ -172,8 +172,8 @@ fn const_main() { }; let x3 = if CONST_MIN > input { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + CONST_MIN } else if CONST_MAX < input { CONST_MAX @@ -182,32 +182,27 @@ fn const_main() { }; let x4 = input.max(CONST_MIN).min(CONST_MAX); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp let x5 = input.min(CONST_MAX).max(CONST_MIN); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp let x6 = match input { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp x if x > CONST_MAX => CONST_MAX, x if x < CONST_MIN => CONST_MIN, x => x, }; let x7 = match input { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp x if x < CONST_MIN => CONST_MIN, x if x > CONST_MAX => CONST_MAX, x => x, }; let x8 = match input { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp x if CONST_MAX < x => CONST_MAX, x if CONST_MIN > x => CONST_MIN, x => x, @@ -215,8 +210,8 @@ fn const_main() { let mut x9 = input; if x9 < CONST_MIN { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + x9 = CONST_MIN; } if x9 > CONST_MAX { @@ -224,8 +219,7 @@ fn const_main() { } let x10 = match input { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp x if CONST_MIN > x => CONST_MIN, x if CONST_MAX < x => CONST_MAX, x => x, @@ -234,8 +228,8 @@ fn const_main() { let mut x11 = input; let _ = 1; if x11 > CONST_MAX { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + x11 = CONST_MAX; } if x11 < CONST_MIN { @@ -244,8 +238,8 @@ fn const_main() { let mut x12 = input; if CONST_MIN > x12 { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + x12 = CONST_MIN; } if CONST_MAX < x12 { @@ -254,8 +248,8 @@ fn const_main() { let mut x13 = input; if CONST_MAX < x13 { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + x13 = CONST_MAX; } if CONST_MIN > x13 { @@ -263,8 +257,8 @@ fn const_main() { } let x14 = if input > CONST_MAX { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + CONST_MAX } else if input < CONST_MIN { CONST_MIN @@ -274,8 +268,8 @@ fn const_main() { { let input = 0.0f64; let x15 = if input > CONST_F64_MAX { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + CONST_F64_MAX } else if input < CONST_F64_MIN { CONST_F64_MIN @@ -287,59 +281,58 @@ fn const_main() { let input: i32 = cmp_min_max(1); // These can only be detected if exactly one of the arguments to the inner function is const. let x16 = cmp_max(cmp_min(input, CONST_MAX), CONST_MIN); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + let x17 = cmp_min(cmp_max(input, CONST_MIN), CONST_MAX); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + let x18 = cmp_max(CONST_MIN, cmp_min(input, CONST_MAX)); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + let x19 = cmp_min(CONST_MAX, cmp_max(input, CONST_MIN)); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + let x20 = cmp_max(cmp_min(CONST_MAX, input), CONST_MIN); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + let x21 = cmp_min(cmp_max(CONST_MIN, input), CONST_MAX); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + let x22 = cmp_max(CONST_MIN, cmp_min(CONST_MAX, input)); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + let x23 = cmp_min(CONST_MAX, cmp_max(CONST_MIN, input)); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + let input: f64 = cmp_min_max(1) as f64; let x24 = f64::max(f64::min(input, CONST_F64_MAX), CONST_F64_MIN); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min, min.is_nan(), or max.is_nan() + //~^ manual_clamp + let x25 = f64::min(f64::max(input, CONST_F64_MIN), CONST_F64_MAX); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min, min.is_nan(), or max.is_nan() + //~^ manual_clamp + let x26 = f64::max(CONST_F64_MIN, f64::min(input, CONST_F64_MAX)); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min, min.is_nan(), or max.is_nan() + //~^ manual_clamp + let x27 = f64::min(CONST_F64_MAX, f64::max(input, CONST_F64_MIN)); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min, min.is_nan(), or max.is_nan() + //~^ manual_clamp + let x28 = f64::max(f64::min(CONST_F64_MAX, input), CONST_F64_MIN); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min, min.is_nan(), or max.is_nan() + //~^ manual_clamp + let x29 = f64::min(f64::max(CONST_F64_MIN, input), CONST_F64_MAX); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min, min.is_nan(), or max.is_nan() + //~^ manual_clamp + let x30 = f64::max(CONST_F64_MIN, f64::min(CONST_F64_MAX, input)); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min, min.is_nan(), or max.is_nan() + //~^ manual_clamp + let x31 = f64::min(CONST_F64_MAX, f64::max(CONST_F64_MIN, input)); - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min, min.is_nan(), or max.is_nan() + //~^ manual_clamp } let mut x32 = input; if x32 < CONST_MIN { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + x32 = CONST_MIN; } else if x32 > CONST_MAX { x32 = CONST_MAX; @@ -368,8 +361,8 @@ fn const_main() { // It's important this be the last set of statements let mut x35 = input; if CONST_MAX < x35 { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + x35 = CONST_MAX; } if CONST_MIN > x35 { @@ -530,8 +523,8 @@ fn msrv_1_49() { fn msrv_1_50() { let input = 0; let _ = if input > CONST_MAX { - //~^ ERROR: clamp-like pattern without using clamp function - //~| NOTE: clamp will panic if max < min + //~^ manual_clamp + CONST_MAX } else if input < CONST_MIN { CONST_MIN diff --git a/tests/ui/manual_clamp.stderr b/tests/ui/manual_clamp.stderr index 459d46796d87..4a0e4fa51646 100644 --- a/tests/ui/manual_clamp.stderr +++ b/tests/ui/manual_clamp.stderr @@ -1,5 +1,5 @@ error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:217:5 + --> tests/ui/manual_clamp.rs:212:5 | LL | / if x9 < CONST_MIN { LL | | @@ -15,7 +15,7 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::manual_clamp)]` error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:236:5 + --> tests/ui/manual_clamp.rs:230:5 | LL | / if x11 > CONST_MAX { LL | | @@ -29,7 +29,7 @@ LL | | } = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:246:5 + --> tests/ui/manual_clamp.rs:240:5 | LL | / if CONST_MIN > x12 { LL | | @@ -43,7 +43,7 @@ LL | | } = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:256:5 + --> tests/ui/manual_clamp.rs:250:5 | LL | / if CONST_MAX < x13 { LL | | @@ -57,7 +57,7 @@ LL | | } = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:370:5 + --> tests/ui/manual_clamp.rs:363:5 | LL | / if CONST_MAX < x35 { LL | | @@ -139,7 +139,7 @@ LL | let x4 = input.max(CONST_MIN).min(CONST_MAX); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:188:14 + --> tests/ui/manual_clamp.rs:187:14 | LL | let x5 = input.min(CONST_MAX).max(CONST_MIN); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -147,12 +147,11 @@ LL | let x5 = input.min(CONST_MAX).max(CONST_MIN); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:192:14 + --> tests/ui/manual_clamp.rs:190:14 | LL | let x6 = match input { | ______________^ LL | | -LL | | LL | | x if x > CONST_MAX => CONST_MAX, LL | | x if x < CONST_MIN => CONST_MIN, LL | | x => x, @@ -162,12 +161,11 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:200:14 + --> tests/ui/manual_clamp.rs:197:14 | LL | let x7 = match input { | ______________^ LL | | -LL | | LL | | x if x < CONST_MIN => CONST_MIN, LL | | x if x > CONST_MAX => CONST_MAX, LL | | x => x, @@ -177,12 +175,11 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:208:14 + --> tests/ui/manual_clamp.rs:204:14 | LL | let x8 = match input { | ______________^ LL | | -LL | | LL | | x if CONST_MAX < x => CONST_MAX, LL | | x if CONST_MIN > x => CONST_MIN, LL | | x => x, @@ -192,12 +189,11 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:226:15 + --> tests/ui/manual_clamp.rs:221:15 | LL | let x10 = match input { | _______________^ LL | | -LL | | LL | | x if CONST_MIN > x => CONST_MIN, LL | | x if CONST_MAX < x => CONST_MAX, LL | | x => x, @@ -207,7 +203,7 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:265:15 + --> tests/ui/manual_clamp.rs:259:15 | LL | let x14 = if input > CONST_MAX { | _______________^ @@ -222,7 +218,7 @@ LL | | }; = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:276:19 + --> tests/ui/manual_clamp.rs:270:19 | LL | let x15 = if input > CONST_F64_MAX { | ___________________^ @@ -238,7 +234,7 @@ LL | | }; = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:289:19 + --> tests/ui/manual_clamp.rs:283:19 | LL | let x16 = cmp_max(cmp_min(input, CONST_MAX), CONST_MIN); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -246,7 +242,7 @@ LL | let x16 = cmp_max(cmp_min(input, CONST_MAX), CONST_MIN); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:292:19 + --> tests/ui/manual_clamp.rs:286:19 | LL | let x17 = cmp_min(cmp_max(input, CONST_MIN), CONST_MAX); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -254,7 +250,7 @@ LL | let x17 = cmp_min(cmp_max(input, CONST_MIN), CONST_MAX); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:295:19 + --> tests/ui/manual_clamp.rs:289:19 | LL | let x18 = cmp_max(CONST_MIN, cmp_min(input, CONST_MAX)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -262,7 +258,7 @@ LL | let x18 = cmp_max(CONST_MIN, cmp_min(input, CONST_MAX)); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:298:19 + --> tests/ui/manual_clamp.rs:292:19 | LL | let x19 = cmp_min(CONST_MAX, cmp_max(input, CONST_MIN)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -270,7 +266,7 @@ LL | let x19 = cmp_min(CONST_MAX, cmp_max(input, CONST_MIN)); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:301:19 + --> tests/ui/manual_clamp.rs:295:19 | LL | let x20 = cmp_max(cmp_min(CONST_MAX, input), CONST_MIN); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -278,7 +274,7 @@ LL | let x20 = cmp_max(cmp_min(CONST_MAX, input), CONST_MIN); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:304:19 + --> tests/ui/manual_clamp.rs:298:19 | LL | let x21 = cmp_min(cmp_max(CONST_MIN, input), CONST_MAX); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -286,7 +282,7 @@ LL | let x21 = cmp_min(cmp_max(CONST_MIN, input), CONST_MAX); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:307:19 + --> tests/ui/manual_clamp.rs:301:19 | LL | let x22 = cmp_max(CONST_MIN, cmp_min(CONST_MAX, input)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -294,7 +290,7 @@ LL | let x22 = cmp_max(CONST_MIN, cmp_min(CONST_MAX, input)); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:310:19 + --> tests/ui/manual_clamp.rs:304:19 | LL | let x23 = cmp_min(CONST_MAX, cmp_max(CONST_MIN, input)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)` @@ -302,7 +298,7 @@ LL | let x23 = cmp_min(CONST_MAX, cmp_max(CONST_MIN, input)); = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:314:19 + --> tests/ui/manual_clamp.rs:308:19 | LL | let x24 = f64::max(f64::min(input, CONST_F64_MAX), CONST_F64_MIN); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -311,7 +307,7 @@ LL | let x24 = f64::max(f64::min(input, CONST_F64_MAX), CONST_F64_MIN); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:317:19 + --> tests/ui/manual_clamp.rs:311:19 | LL | let x25 = f64::min(f64::max(input, CONST_F64_MIN), CONST_F64_MAX); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -320,7 +316,7 @@ LL | let x25 = f64::min(f64::max(input, CONST_F64_MIN), CONST_F64_MAX); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:320:19 + --> tests/ui/manual_clamp.rs:314:19 | LL | let x26 = f64::max(CONST_F64_MIN, f64::min(input, CONST_F64_MAX)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -329,7 +325,7 @@ LL | let x26 = f64::max(CONST_F64_MIN, f64::min(input, CONST_F64_MAX)); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:323:19 + --> tests/ui/manual_clamp.rs:317:19 | LL | let x27 = f64::min(CONST_F64_MAX, f64::max(input, CONST_F64_MIN)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -338,7 +334,7 @@ LL | let x27 = f64::min(CONST_F64_MAX, f64::max(input, CONST_F64_MIN)); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:326:19 + --> tests/ui/manual_clamp.rs:320:19 | LL | let x28 = f64::max(f64::min(CONST_F64_MAX, input), CONST_F64_MIN); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -347,7 +343,7 @@ LL | let x28 = f64::max(f64::min(CONST_F64_MAX, input), CONST_F64_MIN); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:329:19 + --> tests/ui/manual_clamp.rs:323:19 | LL | let x29 = f64::min(f64::max(CONST_F64_MIN, input), CONST_F64_MAX); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -356,7 +352,7 @@ LL | let x29 = f64::min(f64::max(CONST_F64_MIN, input), CONST_F64_MAX); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:332:19 + --> tests/ui/manual_clamp.rs:326:19 | LL | let x30 = f64::max(CONST_F64_MIN, f64::min(CONST_F64_MAX, input)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -365,7 +361,7 @@ LL | let x30 = f64::max(CONST_F64_MIN, f64::min(CONST_F64_MAX, input)); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:335:19 + --> tests/ui/manual_clamp.rs:329:19 | LL | let x31 = f64::min(CONST_F64_MAX, f64::max(CONST_F64_MIN, input)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)` @@ -374,7 +370,7 @@ LL | let x31 = f64::min(CONST_F64_MAX, f64::max(CONST_F64_MIN, input)); = note: clamp returns NaN if the input is NaN error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:340:5 + --> tests/ui/manual_clamp.rs:333:5 | LL | / if x32 < CONST_MIN { LL | | @@ -388,7 +384,7 @@ LL | | } = note: clamp will panic if max < min error: clamp-like pattern without using clamp function - --> tests/ui/manual_clamp.rs:532:13 + --> tests/ui/manual_clamp.rs:525:13 | LL | let _ = if input > CONST_MAX { | _____________^ diff --git a/tests/ui/manual_contains.fixed b/tests/ui/manual_contains.fixed new file mode 100644 index 000000000000..d26c948a7817 --- /dev/null +++ b/tests/ui/manual_contains.fixed @@ -0,0 +1,98 @@ +#![warn(clippy::manual_contains)] +#![allow(clippy::eq_op, clippy::useless_vec)] + +fn should_lint() { + let vec: Vec = vec![1, 2, 3, 4, 5, 6]; + let values = &vec[..]; + let _ = values.contains(&4); + //~^ manual_contains + + let vec: Vec = vec![1, 2, 3, 4, 5, 6]; + let values = &vec[..]; + let _ = values.contains(&4); + //~^ manual_contains + + let values: [u8; 6] = [3, 14, 15, 92, 6, 5]; + let _ = values.contains(&10); + //~^ manual_contains + + let num = 14; + let values: [u8; 6] = [3, 14, 15, 92, 6, 5]; + let _ = values.contains(&num); + //~^ manual_contains + + let num = 14; + let values: [u8; 6] = [3, 14, 15, 92, 6, 5]; + let _ = values.contains(&num); + //~^ manual_contains + + let values: [u8; 6] = [3, 14, 15, 92, 6, 5]; + let _ = values.contains(&4); + //~^ manual_contains + + let vec: Vec = vec![1, 2, 3, 4, 5, 6]; + let values = &vec[..]; + let _ = values.contains(&4); + //~^ manual_contains + + let vec: Vec = vec![1, 2, 3, 4, 5, 6]; + let values = &vec[..]; + let a = &4; + let _ = values.contains(a); + //~^ manual_contains + + let vec = vec!["1", "2", "3", "4", "5", "6"]; + let values = &vec[..]; + let _ = values.contains(&"4"); + //~^ manual_contains + + let vec: Vec = vec![1, 2, 3, 4, 5, 6]; + let values = &vec[..]; + let _ = values.contains(&(4 + 1)); + //~^ manual_contains +} + +fn should_not_lint() { + let values: [u8; 6] = [3, 14, 15, 92, 6, 5]; + let _ = values.iter().any(|&v| v > 10); + + let vec: Vec = vec![1, 2, 3, 4, 5, 6]; + let values = &vec[..]; + let _ = values.iter().any(|&v| v % 2 == 0); + let _ = values.iter().any(|&v| v * 2 == 6); + let _ = values.iter().any(|&v| v == v); + let _ = values.iter().any(|&v| 4 == 4); + let _ = values.contains(&4); + + let a = 1; + let b = 2; + let _ = values.iter().any(|&v| a == b); + let _ = values.iter().any(|&v| a == 4); + + let vec: Vec = vec!["1", "2", "3", "4", "5", "6"] + .iter() + .map(|&x| x.to_string()) + .collect(); + let values = &vec[..]; + let _ = values.iter().any(|v| v == "4"); + + let vec: Vec = vec![1, 2, 3, 4, 5, 6]; + let values = &vec[..]; + let mut counter = 0; + let mut count = || { + counter += 1; + counter + }; + let _ = values.iter().any(|&v| v == count()); + let _ = values.iter().any(|&v| v == v * 2); +} + +fn foo(values: &[u8]) -> bool { + values.contains(&10) + //~^ manual_contains +} + +fn bar(values: [u8; 3]) -> bool { + values.contains(&10) + //~^ manual_contains +} diff --git a/tests/ui/manual_contains.rs b/tests/ui/manual_contains.rs new file mode 100644 index 000000000000..fe67d2ee5d5c --- /dev/null +++ b/tests/ui/manual_contains.rs @@ -0,0 +1,98 @@ +#![warn(clippy::manual_contains)] +#![allow(clippy::eq_op, clippy::useless_vec)] + +fn should_lint() { + let vec: Vec = vec![1, 2, 3, 4, 5, 6]; + let values = &vec[..]; + let _ = values.iter().any(|&v| v == 4); + //~^ manual_contains + + let vec: Vec = vec![1, 2, 3, 4, 5, 6]; + let values = &vec[..]; + let _ = values.iter().any(|&v| v == 4); + //~^ manual_contains + + let values: [u8; 6] = [3, 14, 15, 92, 6, 5]; + let _ = values.iter().any(|&v| v == 10); + //~^ manual_contains + + let num = 14; + let values: [u8; 6] = [3, 14, 15, 92, 6, 5]; + let _ = values.iter().any(|&v| v == num); + //~^ manual_contains + + let num = 14; + let values: [u8; 6] = [3, 14, 15, 92, 6, 5]; + let _ = values.iter().any(|&v| num == v); + //~^ manual_contains + + let values: [u8; 6] = [3, 14, 15, 92, 6, 5]; + let _ = values.iter().any(|v| *v == 4); + //~^ manual_contains + + let vec: Vec = vec![1, 2, 3, 4, 5, 6]; + let values = &vec[..]; + let _ = values.iter().any(|&v| 4 == v); + //~^ manual_contains + + let vec: Vec = vec![1, 2, 3, 4, 5, 6]; + let values = &vec[..]; + let a = &4; + let _ = values.iter().any(|v| *v == *a); + //~^ manual_contains + + let vec = vec!["1", "2", "3", "4", "5", "6"]; + let values = &vec[..]; + let _ = values.iter().any(|&v| v == "4"); + //~^ manual_contains + + let vec: Vec = vec![1, 2, 3, 4, 5, 6]; + let values = &vec[..]; + let _ = values.iter().any(|&v| v == 4 + 1); + //~^ manual_contains +} + +fn should_not_lint() { + let values: [u8; 6] = [3, 14, 15, 92, 6, 5]; + let _ = values.iter().any(|&v| v > 10); + + let vec: Vec = vec![1, 2, 3, 4, 5, 6]; + let values = &vec[..]; + let _ = values.iter().any(|&v| v % 2 == 0); + let _ = values.iter().any(|&v| v * 2 == 6); + let _ = values.iter().any(|&v| v == v); + let _ = values.iter().any(|&v| 4 == 4); + let _ = values.contains(&4); + + let a = 1; + let b = 2; + let _ = values.iter().any(|&v| a == b); + let _ = values.iter().any(|&v| a == 4); + + let vec: Vec = vec!["1", "2", "3", "4", "5", "6"] + .iter() + .map(|&x| x.to_string()) + .collect(); + let values = &vec[..]; + let _ = values.iter().any(|v| v == "4"); + + let vec: Vec = vec![1, 2, 3, 4, 5, 6]; + let values = &vec[..]; + let mut counter = 0; + let mut count = || { + counter += 1; + counter + }; + let _ = values.iter().any(|&v| v == count()); + let _ = values.iter().any(|&v| v == v * 2); +} + +fn foo(values: &[u8]) -> bool { + values.iter().any(|&v| v == 10) + //~^ manual_contains +} + +fn bar(values: [u8; 3]) -> bool { + values.iter().any(|&v| v == 10) + //~^ manual_contains +} diff --git a/tests/ui/manual_contains.stderr b/tests/ui/manual_contains.stderr new file mode 100644 index 000000000000..e6e2dea560c6 --- /dev/null +++ b/tests/ui/manual_contains.stderr @@ -0,0 +1,77 @@ +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/manual_contains.rs:7:13 + | +LL | let _ = values.iter().any(|&v| v == 4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `values.contains(&4)` + | + = note: `-D clippy::manual-contains` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_contains)]` + +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/manual_contains.rs:12:13 + | +LL | let _ = values.iter().any(|&v| v == 4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `values.contains(&4)` + +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/manual_contains.rs:16:13 + | +LL | let _ = values.iter().any(|&v| v == 10); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `values.contains(&10)` + +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/manual_contains.rs:21:13 + | +LL | let _ = values.iter().any(|&v| v == num); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `values.contains(&num)` + +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/manual_contains.rs:26:13 + | +LL | let _ = values.iter().any(|&v| num == v); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `values.contains(&num)` + +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/manual_contains.rs:30:13 + | +LL | let _ = values.iter().any(|v| *v == 4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `values.contains(&4)` + +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/manual_contains.rs:35:13 + | +LL | let _ = values.iter().any(|&v| 4 == v); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `values.contains(&4)` + +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/manual_contains.rs:41:13 + | +LL | let _ = values.iter().any(|v| *v == *a); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `values.contains(a)` + +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/manual_contains.rs:46:13 + | +LL | let _ = values.iter().any(|&v| v == "4"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `values.contains(&"4")` + +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/manual_contains.rs:51:13 + | +LL | let _ = values.iter().any(|&v| v == 4 + 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `values.contains(&(4 + 1))` + +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/manual_contains.rs:91:5 + | +LL | values.iter().any(|&v| v == 10) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `values.contains(&10)` + +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/manual_contains.rs:96:5 + | +LL | values.iter().any(|&v| v == 10) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `values.contains(&10)` + +error: aborting due to 12 previous errors + diff --git a/tests/ui/manual_div_ceil.fixed b/tests/ui/manual_div_ceil.fixed index f6eb5a9784ac..57fe8917afe8 100644 --- a/tests/ui/manual_div_ceil.fixed +++ b/tests/ui/manual_div_ceil.fixed @@ -6,12 +6,17 @@ fn main() { let z = 11_u32; // Lint - let _ = x.div_ceil(y); //~ ERROR: manually reimplementing `div_ceil` - let _ = x.div_ceil(y); //~ ERROR: manually reimplementing `div_ceil` - let _ = x.div_ceil(y); //~ ERROR: manually reimplementing `div_ceil` + let _ = x.div_ceil(y); + //~^ manual_div_ceil + let _ = x.div_ceil(y); + //~^ manual_div_ceil + let _ = x.div_ceil(y); + //~^ manual_div_ceil - let _ = 7_u32.div_ceil(4); //~ ERROR: manually reimplementing `div_ceil` - let _ = (7_i32 as u32).div_ceil(4); //~ ERROR: manually reimplementing `div_ceil` + let _ = 7_u32.div_ceil(4); + //~^ manual_div_ceil + let _ = (7_i32 as u32).div_ceil(4); + //~^ manual_div_ceil // No lint let _ = (x + (y - 2)) / y; @@ -32,29 +37,40 @@ fn main() { fn issue_13843() { let x = 3usize; let _ = 2048_usize.div_ceil(x); + //~^ manual_div_ceil let x = 5usize; let _ = 2048usize.div_ceil(x); + //~^ manual_div_ceil let x = 5usize; let _ = 2048_usize.div_ceil(x); + //~^ manual_div_ceil let x = 2048usize; let _ = x.div_ceil(4); + //~^ manual_div_ceil let _: u32 = 2048_u32.div_ceil(6); + //~^ manual_div_ceil let _: usize = 2048_usize.div_ceil(6); + //~^ manual_div_ceil let _: u32 = 0x2048_u32.div_ceil(0x6); + //~^ manual_div_ceil let _ = 2048_u32.div_ceil(6u32); + //~^ manual_div_ceil let _ = 1_000_000_u32.div_ceil(6u32); + //~^ manual_div_ceil } fn issue_13950() { let x = 33u32; let _ = x.div_ceil(8); + //~^ manual_div_ceil let _ = x.div_ceil(8); + //~^ manual_div_ceil let y = -33i32; let _ = (y + -8) / -7; diff --git a/tests/ui/manual_div_ceil.rs b/tests/ui/manual_div_ceil.rs index 2f063afe787d..ec343513e5ce 100644 --- a/tests/ui/manual_div_ceil.rs +++ b/tests/ui/manual_div_ceil.rs @@ -6,12 +6,17 @@ fn main() { let z = 11_u32; // Lint - let _ = (x + (y - 1)) / y; //~ ERROR: manually reimplementing `div_ceil` - let _ = ((y - 1) + x) / y; //~ ERROR: manually reimplementing `div_ceil` - let _ = (x + y - 1) / y; //~ ERROR: manually reimplementing `div_ceil` + let _ = (x + (y - 1)) / y; + //~^ manual_div_ceil + let _ = ((y - 1) + x) / y; + //~^ manual_div_ceil + let _ = (x + y - 1) / y; + //~^ manual_div_ceil - let _ = (7_u32 + (4 - 1)) / 4; //~ ERROR: manually reimplementing `div_ceil` - let _ = (7_i32 as u32 + (4 - 1)) / 4; //~ ERROR: manually reimplementing `div_ceil` + let _ = (7_u32 + (4 - 1)) / 4; + //~^ manual_div_ceil + let _ = (7_i32 as u32 + (4 - 1)) / 4; + //~^ manual_div_ceil // No lint let _ = (x + (y - 2)) / y; @@ -32,29 +37,40 @@ fn main() { fn issue_13843() { let x = 3usize; let _ = (2048 + x - 1) / x; + //~^ manual_div_ceil let x = 5usize; let _ = (2048usize + x - 1) / x; + //~^ manual_div_ceil let x = 5usize; let _ = (2048_usize + x - 1) / x; + //~^ manual_div_ceil let x = 2048usize; let _ = (x + 4 - 1) / 4; + //~^ manual_div_ceil let _: u32 = (2048 + 6 - 1) / 6; + //~^ manual_div_ceil let _: usize = (2048 + 6 - 1) / 6; + //~^ manual_div_ceil let _: u32 = (0x2048 + 0x6 - 1) / 0x6; + //~^ manual_div_ceil let _ = (2048 + 6u32 - 1) / 6u32; + //~^ manual_div_ceil let _ = (1_000_000 + 6u32 - 1) / 6u32; + //~^ manual_div_ceil } fn issue_13950() { let x = 33u32; let _ = (x + 7) / 8; + //~^ manual_div_ceil let _ = (7 + x) / 8; + //~^ manual_div_ceil let y = -33i32; let _ = (y + -8) / -7; diff --git a/tests/ui/manual_div_ceil.stderr b/tests/ui/manual_div_ceil.stderr index 0bac5d8ef1c1..8e14ab274269 100644 --- a/tests/ui/manual_div_ceil.stderr +++ b/tests/ui/manual_div_ceil.stderr @@ -8,91 +8,91 @@ LL | let _ = (x + (y - 1)) / y; = help: to override `-D warnings` add `#[allow(clippy::manual_div_ceil)]` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil.rs:10:13 + --> tests/ui/manual_div_ceil.rs:11:13 | LL | let _ = ((y - 1) + x) / y; | ^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil.rs:11:13 + --> tests/ui/manual_div_ceil.rs:13:13 | LL | let _ = (x + y - 1) / y; | ^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil.rs:13:13 + --> tests/ui/manual_div_ceil.rs:16:13 | LL | let _ = (7_u32 + (4 - 1)) / 4; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `7_u32.div_ceil(4)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil.rs:14:13 + --> tests/ui/manual_div_ceil.rs:18:13 | LL | let _ = (7_i32 as u32 + (4 - 1)) / 4; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `(7_i32 as u32).div_ceil(4)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil.rs:34:13 + --> tests/ui/manual_div_ceil.rs:39:13 | LL | let _ = (2048 + x - 1) / x; | ^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_usize.div_ceil(x)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil.rs:37:13 + --> tests/ui/manual_div_ceil.rs:43:13 | LL | let _ = (2048usize + x - 1) / x; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048usize.div_ceil(x)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil.rs:40:13 + --> tests/ui/manual_div_ceil.rs:47:13 | LL | let _ = (2048_usize + x - 1) / x; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_usize.div_ceil(x)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil.rs:43:13 + --> tests/ui/manual_div_ceil.rs:51:13 | LL | let _ = (x + 4 - 1) / 4; | ^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(4)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil.rs:45:18 + --> tests/ui/manual_div_ceil.rs:54:18 | LL | let _: u32 = (2048 + 6 - 1) / 6; | ^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_u32.div_ceil(6)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil.rs:46:20 + --> tests/ui/manual_div_ceil.rs:56:20 | LL | let _: usize = (2048 + 6 - 1) / 6; | ^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_usize.div_ceil(6)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil.rs:47:18 + --> tests/ui/manual_div_ceil.rs:58:18 | LL | let _: u32 = (0x2048 + 0x6 - 1) / 0x6; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `0x2048_u32.div_ceil(0x6)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil.rs:49:13 + --> tests/ui/manual_div_ceil.rs:61:13 | LL | let _ = (2048 + 6u32 - 1) / 6u32; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_u32.div_ceil(6u32)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil.rs:51:13 + --> tests/ui/manual_div_ceil.rs:64:13 | LL | let _ = (1_000_000 + 6u32 - 1) / 6u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `1_000_000_u32.div_ceil(6u32)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil.rs:56:13 + --> tests/ui/manual_div_ceil.rs:70:13 | LL | let _ = (x + 7) / 8; | ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil.rs:57:13 + --> tests/ui/manual_div_ceil.rs:72:13 | LL | let _ = (7 + x) / 8; | ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)` diff --git a/tests/ui/manual_div_ceil_with_feature.fixed b/tests/ui/manual_div_ceil_with_feature.fixed index 01c58151bc94..f55999c5ad08 100644 --- a/tests/ui/manual_div_ceil_with_feature.fixed +++ b/tests/ui/manual_div_ceil_with_feature.fixed @@ -9,13 +9,20 @@ fn main() { // Lint. let _ = x.div_ceil(y); + //~^ manual_div_ceil let _ = x.div_ceil(y); + //~^ manual_div_ceil let _ = x.div_ceil(y); + //~^ manual_div_ceil let _ = 7_i32.div_ceil(4); + //~^ manual_div_ceil let _ = (7_i32 as u32).div_ceil(4); + //~^ manual_div_ceil let _ = (7_u32 as i32).div_ceil(4); + //~^ manual_div_ceil let _ = z_u.div_ceil(4); + //~^ manual_div_ceil // No lint. let _ = (x + (y - 2)) / y; @@ -27,37 +34,53 @@ fn main() { fn issue_13843() { let x = 3usize; let _ = 2048_usize.div_ceil(x); + //~^ manual_div_ceil let x = 5usize; let _ = 2048usize.div_ceil(x); + //~^ manual_div_ceil let x = 5usize; let _ = 2048_usize.div_ceil(x); + //~^ manual_div_ceil let x = 2048usize; let _ = x.div_ceil(4); + //~^ manual_div_ceil let _ = 2048_i32.div_ceil(4); + //~^ manual_div_ceil let _: u32 = 2048_u32.div_ceil(6); + //~^ manual_div_ceil let _: usize = 2048_usize.div_ceil(6); + //~^ manual_div_ceil let _: u32 = 0x2048_u32.div_ceil(0x6); + //~^ manual_div_ceil let _ = 2048_u32.div_ceil(6u32); + //~^ manual_div_ceil let x = -2; let _ = (-2048_i32).div_ceil(x); + //~^ manual_div_ceil let _ = 1_000_000_u32.div_ceil(6u32); + //~^ manual_div_ceil } fn issue_13950() { let x = 33u32; let _ = x.div_ceil(8); + //~^ manual_div_ceil let _ = x.div_ceil(8); + //~^ manual_div_ceil let y = -33i32; let _ = y.div_ceil(-7); + //~^ manual_div_ceil let _ = y.div_ceil(-7); + //~^ manual_div_ceil let _ = y.div_ceil(-7); + //~^ manual_div_ceil } diff --git a/tests/ui/manual_div_ceil_with_feature.rs b/tests/ui/manual_div_ceil_with_feature.rs index 048ff401581f..8a895f634cb4 100644 --- a/tests/ui/manual_div_ceil_with_feature.rs +++ b/tests/ui/manual_div_ceil_with_feature.rs @@ -9,13 +9,20 @@ fn main() { // Lint. let _ = (x + (y - 1)) / y; + //~^ manual_div_ceil let _ = ((y - 1) + x) / y; + //~^ manual_div_ceil let _ = (x + y - 1) / y; + //~^ manual_div_ceil let _ = (7_i32 + (4 - 1)) / 4; + //~^ manual_div_ceil let _ = (7_i32 as u32 + (4 - 1)) / 4; + //~^ manual_div_ceil let _ = (7_u32 as i32 + (4 - 1)) / 4; + //~^ manual_div_ceil let _ = (z_u + (4 - 1)) / 4; + //~^ manual_div_ceil // No lint. let _ = (x + (y - 2)) / y; @@ -27,37 +34,53 @@ fn main() { fn issue_13843() { let x = 3usize; let _ = (2048 + x - 1) / x; + //~^ manual_div_ceil let x = 5usize; let _ = (2048usize + x - 1) / x; + //~^ manual_div_ceil let x = 5usize; let _ = (2048_usize + x - 1) / x; + //~^ manual_div_ceil let x = 2048usize; let _ = (x + 4 - 1) / 4; + //~^ manual_div_ceil let _ = (2048 + 4 - 1) / 4; + //~^ manual_div_ceil let _: u32 = (2048 + 6 - 1) / 6; + //~^ manual_div_ceil let _: usize = (2048 + 6 - 1) / 6; + //~^ manual_div_ceil let _: u32 = (0x2048 + 0x6 - 1) / 0x6; + //~^ manual_div_ceil let _ = (2048 + 6u32 - 1) / 6u32; + //~^ manual_div_ceil let x = -2; let _ = (-2048 + x - 1) / x; + //~^ manual_div_ceil let _ = (1_000_000 + 6u32 - 1) / 6u32; + //~^ manual_div_ceil } fn issue_13950() { let x = 33u32; let _ = (x + 7) / 8; + //~^ manual_div_ceil let _ = (7 + x) / 8; + //~^ manual_div_ceil let y = -33i32; let _ = (y + -8) / -7; + //~^ manual_div_ceil let _ = (-8 + y) / -7; + //~^ manual_div_ceil let _ = (y - 8) / -7; + //~^ manual_div_ceil } diff --git a/tests/ui/manual_div_ceil_with_feature.stderr b/tests/ui/manual_div_ceil_with_feature.stderr index 807cfd82724e..e1160d962996 100644 --- a/tests/ui/manual_div_ceil_with_feature.stderr +++ b/tests/ui/manual_div_ceil_with_feature.stderr @@ -8,133 +8,133 @@ LL | let _ = (x + (y - 1)) / y; = help: to override `-D warnings` add `#[allow(clippy::manual_div_ceil)]` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil_with_feature.rs:12:13 + --> tests/ui/manual_div_ceil_with_feature.rs:13:13 | LL | let _ = ((y - 1) + x) / y; | ^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil_with_feature.rs:13:13 + --> tests/ui/manual_div_ceil_with_feature.rs:15:13 | LL | let _ = (x + y - 1) / y; | ^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil_with_feature.rs:15:13 + --> tests/ui/manual_div_ceil_with_feature.rs:18:13 | LL | let _ = (7_i32 + (4 - 1)) / 4; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `7_i32.div_ceil(4)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil_with_feature.rs:16:13 + --> tests/ui/manual_div_ceil_with_feature.rs:20:13 | LL | let _ = (7_i32 as u32 + (4 - 1)) / 4; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `(7_i32 as u32).div_ceil(4)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil_with_feature.rs:17:13 + --> tests/ui/manual_div_ceil_with_feature.rs:22:13 | LL | let _ = (7_u32 as i32 + (4 - 1)) / 4; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `(7_u32 as i32).div_ceil(4)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil_with_feature.rs:18:13 + --> tests/ui/manual_div_ceil_with_feature.rs:24:13 | LL | let _ = (z_u + (4 - 1)) / 4; | ^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `z_u.div_ceil(4)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil_with_feature.rs:29:13 + --> tests/ui/manual_div_ceil_with_feature.rs:36:13 | LL | let _ = (2048 + x - 1) / x; | ^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_usize.div_ceil(x)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil_with_feature.rs:32:13 + --> tests/ui/manual_div_ceil_with_feature.rs:40:13 | LL | let _ = (2048usize + x - 1) / x; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048usize.div_ceil(x)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil_with_feature.rs:35:13 + --> tests/ui/manual_div_ceil_with_feature.rs:44:13 | LL | let _ = (2048_usize + x - 1) / x; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_usize.div_ceil(x)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil_with_feature.rs:38:13 + --> tests/ui/manual_div_ceil_with_feature.rs:48:13 | LL | let _ = (x + 4 - 1) / 4; | ^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(4)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil_with_feature.rs:40:13 + --> tests/ui/manual_div_ceil_with_feature.rs:51:13 | LL | let _ = (2048 + 4 - 1) / 4; | ^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_i32.div_ceil(4)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil_with_feature.rs:42:18 + --> tests/ui/manual_div_ceil_with_feature.rs:54:18 | LL | let _: u32 = (2048 + 6 - 1) / 6; | ^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_u32.div_ceil(6)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil_with_feature.rs:43:20 + --> tests/ui/manual_div_ceil_with_feature.rs:56:20 | LL | let _: usize = (2048 + 6 - 1) / 6; | ^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_usize.div_ceil(6)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil_with_feature.rs:44:18 + --> tests/ui/manual_div_ceil_with_feature.rs:58:18 | LL | let _: u32 = (0x2048 + 0x6 - 1) / 0x6; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `0x2048_u32.div_ceil(0x6)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil_with_feature.rs:46:13 + --> tests/ui/manual_div_ceil_with_feature.rs:61:13 | LL | let _ = (2048 + 6u32 - 1) / 6u32; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_u32.div_ceil(6u32)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil_with_feature.rs:49:13 + --> tests/ui/manual_div_ceil_with_feature.rs:65:13 | LL | let _ = (-2048 + x - 1) / x; | ^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `(-2048_i32).div_ceil(x)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil_with_feature.rs:51:13 + --> tests/ui/manual_div_ceil_with_feature.rs:68:13 | LL | let _ = (1_000_000 + 6u32 - 1) / 6u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `1_000_000_u32.div_ceil(6u32)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil_with_feature.rs:56:13 + --> tests/ui/manual_div_ceil_with_feature.rs:74:13 | LL | let _ = (x + 7) / 8; | ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil_with_feature.rs:57:13 + --> tests/ui/manual_div_ceil_with_feature.rs:76:13 | LL | let _ = (7 + x) / 8; | ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil_with_feature.rs:60:13 + --> tests/ui/manual_div_ceil_with_feature.rs:80:13 | LL | let _ = (y + -8) / -7; | ^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `y.div_ceil(-7)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil_with_feature.rs:61:13 + --> tests/ui/manual_div_ceil_with_feature.rs:82:13 | LL | let _ = (-8 + y) / -7; | ^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `y.div_ceil(-7)` error: manually reimplementing `div_ceil` - --> tests/ui/manual_div_ceil_with_feature.rs:62:13 + --> tests/ui/manual_div_ceil_with_feature.rs:84:13 | LL | let _ = (y - 8) / -7; | ^^^^^^^^^^^^ help: consider using `.div_ceil()`: `y.div_ceil(-7)` diff --git a/tests/ui/manual_filter.rs b/tests/ui/manual_filter.rs index 0ac6cbefc4ec..a9d0c35f8bb7 100644 --- a/tests/ui/manual_filter.rs +++ b/tests/ui/manual_filter.rs @@ -3,6 +3,7 @@ fn main() { match Some(0) { + //~^ manual_filter None => None, Some(x) => { if x > 0 { @@ -14,6 +15,7 @@ fn main() { }; match Some(1) { + //~^ manual_filter Some(x) => { if x > 0 { None @@ -25,6 +27,7 @@ fn main() { }; match Some(2) { + //~^ manual_filter Some(x) => { if x > 0 { None @@ -36,6 +39,7 @@ fn main() { }; match Some(3) { + //~^ manual_filter Some(x) => { if x > 0 { Some(x) @@ -48,6 +52,7 @@ fn main() { let y = Some(4); match y { + //~^ manual_filter // Some(4) None => None, Some(x) => { @@ -60,6 +65,7 @@ fn main() { }; match Some(5) { + //~^ manual_filter Some(x) => { if x > 0 { Some(x) @@ -71,6 +77,7 @@ fn main() { }; match Some(6) { + //~^ manual_filter Some(ref x) => { if x > &0 { Some(x) @@ -83,6 +90,7 @@ fn main() { let external_cond = true; match Some(String::new()) { + //~^ manual_filter Some(x) => { if external_cond { Some(x) @@ -94,12 +102,14 @@ fn main() { }; if let Some(x) = Some(7) { + //~^ manual_filter if external_cond { Some(x) } else { None } } else { None }; match &Some(8) { + //~^ manual_filter &Some(x) => { if x != 0 { Some(x) @@ -111,6 +121,7 @@ fn main() { }; match Some(9) { + //~^ manual_filter Some(x) => { if x > 10 && x < 100 { Some(x) @@ -137,6 +148,7 @@ fn main() { #[allow(clippy::blocks_in_conditions)] match Some(11) { + //~^ manual_filter // Lint, statement is preserved by `.filter` Some(x) => { if { @@ -181,6 +193,7 @@ fn main() { true } let _ = match Some(14) { + //~^ manual_filter Some(x) => { if unsafe { f(x) } { Some(x) @@ -191,6 +204,7 @@ fn main() { None => None, }; let _ = match Some(15) { + //~^ manual_filter Some(x) => unsafe { if f(x) { Some(x) } else { None } }, None => None, }; @@ -199,6 +213,7 @@ fn main() { if let Some(_) = Some(16) { Some(16) } else if let Some(x) = Some(16) { + //~^ manual_filter // Lint starting from here if x % 2 == 0 { Some(x) } else { None } } else { diff --git a/tests/ui/manual_filter.stderr b/tests/ui/manual_filter.stderr index 3add706d7f73..63463997f435 100644 --- a/tests/ui/manual_filter.stderr +++ b/tests/ui/manual_filter.stderr @@ -2,9 +2,9 @@ error: manual implementation of `Option::filter` --> tests/ui/manual_filter.rs:5:5 | LL | / match Some(0) { +LL | | LL | | None => None, LL | | Some(x) => { -LL | | if x > 0 { ... | LL | | }, LL | | }; @@ -14,93 +14,94 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::manual_filter)]` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:16:5 + --> tests/ui/manual_filter.rs:17:5 | LL | / match Some(1) { +LL | | LL | | Some(x) => { LL | | if x > 0 { -LL | | None ... | LL | | None => None, LL | | }; | |_____^ help: try: `Some(1).filter(|&x| x <= 0)` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:27:5 + --> tests/ui/manual_filter.rs:29:5 | LL | / match Some(2) { +LL | | LL | | Some(x) => { LL | | if x > 0 { -LL | | None ... | LL | | _ => None, LL | | }; | |_____^ help: try: `Some(2).filter(|&x| x <= 0)` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:38:5 + --> tests/ui/manual_filter.rs:41:5 | LL | / match Some(3) { +LL | | LL | | Some(x) => { LL | | if x > 0 { -LL | | Some(x) ... | LL | | None => None, LL | | }; | |_____^ help: try: `Some(3).filter(|&x| x > 0)` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:50:5 + --> tests/ui/manual_filter.rs:54:5 | LL | / match y { +LL | | LL | | // Some(4) LL | | None => None, -LL | | Some(x) => { ... | LL | | }, LL | | }; | |_____^ help: try: `y.filter(|&x| x <= 0)` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:62:5 + --> tests/ui/manual_filter.rs:67:5 | LL | / match Some(5) { +LL | | LL | | Some(x) => { LL | | if x > 0 { -LL | | Some(x) ... | LL | | _ => None, LL | | }; | |_____^ help: try: `Some(5).filter(|&x| x > 0)` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:73:5 + --> tests/ui/manual_filter.rs:79:5 | LL | / match Some(6) { +LL | | LL | | Some(ref x) => { LL | | if x > &0 { -LL | | Some(x) ... | LL | | _ => None, LL | | }; | |_____^ help: try: `Some(6).as_ref().filter(|&x| x > &0)` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:85:5 + --> tests/ui/manual_filter.rs:92:5 | LL | / match Some(String::new()) { +LL | | LL | | Some(x) => { LL | | if external_cond { -LL | | Some(x) ... | LL | | _ => None, LL | | }; | |_____^ help: try: `Some(String::new()).filter(|x| external_cond)` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:96:5 + --> tests/ui/manual_filter.rs:104:5 | LL | / if let Some(x) = Some(7) { +LL | | LL | | if external_cond { Some(x) } else { None } LL | | } else { LL | | None @@ -108,36 +109,36 @@ LL | | }; | |_____^ help: try: `Some(7).filter(|&x| external_cond)` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:102:5 + --> tests/ui/manual_filter.rs:111:5 | LL | / match &Some(8) { +LL | | LL | | &Some(x) => { LL | | if x != 0 { -LL | | Some(x) ... | LL | | _ => None, LL | | }; | |_____^ help: try: `Some(8).filter(|&x| x != 0)` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:113:5 + --> tests/ui/manual_filter.rs:123:5 | LL | / match Some(9) { +LL | | LL | | Some(x) => { LL | | if x > 10 && x < 100 { -LL | | Some(x) ... | LL | | None => None, LL | | }; | |_____^ help: try: `Some(9).filter(|&x| x > 10 && x < 100)` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:139:5 + --> tests/ui/manual_filter.rs:150:5 | LL | / match Some(11) { +LL | | LL | | // Lint, statement is preserved by `.filter` LL | | Some(x) => { -LL | | if { ... | LL | | None => None, LL | | }; @@ -152,33 +153,35 @@ LL ~ }); | error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:183:13 + --> tests/ui/manual_filter.rs:195:13 | LL | let _ = match Some(14) { | _____________^ +LL | | LL | | Some(x) => { LL | | if unsafe { f(x) } { -LL | | Some(x) ... | LL | | None => None, LL | | }; | |_____^ help: try: `Some(14).filter(|&x| unsafe { f(x) })` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:193:13 + --> tests/ui/manual_filter.rs:206:13 | LL | let _ = match Some(15) { | _____________^ +LL | | LL | | Some(x) => unsafe { if f(x) { Some(x) } else { None } }, LL | | None => None, LL | | }; | |_____^ help: try: `Some(15).filter(|&x| unsafe { f(x) })` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:201:12 + --> tests/ui/manual_filter.rs:215:12 | LL | } else if let Some(x) = Some(16) { | ____________^ +LL | | LL | | // Lint starting from here LL | | if x % 2 == 0 { Some(x) } else { None } LL | | } else { diff --git a/tests/ui/manual_filter_map.fixed b/tests/ui/manual_filter_map.fixed index a44c46c145c6..caf82289031f 100644 --- a/tests/ui/manual_filter_map.fixed +++ b/tests/ui/manual_filter_map.fixed @@ -7,12 +7,15 @@ fn main() { // is_some(), unwrap() let _ = (0..).filter_map(|a| to_opt(a)); + //~^ manual_filter_map // ref pattern, expect() let _ = (0..).filter_map(|a| to_opt(a)); + //~^ manual_filter_map // is_ok(), unwrap_or() let _ = (0..).filter_map(|a| to_res(a).ok()); + //~^ manual_filter_map let _ = (1..5) .filter_map(|y| *to_ref(to_opt(y))); @@ -28,17 +31,28 @@ fn main() { #[rustfmt::skip] fn simple_equal() { iter::>().find_map(|x| x.cloned()); + //~^ manual_find_map iter::<&Option<&u8>>().find_map(|x| x.cloned()); + //~^ manual_find_map iter::<&Option>().find_map(|x| x.as_deref()); + //~^ manual_find_map iter::>().find_map(|y| to_ref(y).cloned()); + //~^ manual_find_map iter::>().find_map(|x| x.ok()); + //~^ manual_find_map iter::<&Result>().find_map(|x| x.ok()); + //~^ manual_find_map iter::<&&Result>().find_map(|x| x.ok()); + //~^ manual_find_map iter::>().find_map(|x| x.cloned().ok()); + //~^ manual_find_map iter::<&Result<&u8, ()>>().find_map(|x| x.cloned().ok()); + //~^ manual_find_map iter::<&Result>().find_map(|x| x.as_deref().ok()); + //~^ manual_find_map iter::>().find_map(|y| to_ref(y).cloned().ok()); + //~^ manual_find_map } fn no_lint() { diff --git a/tests/ui/manual_filter_map.rs b/tests/ui/manual_filter_map.rs index e72d0c4305b3..013c88da6b36 100644 --- a/tests/ui/manual_filter_map.rs +++ b/tests/ui/manual_filter_map.rs @@ -7,42 +7,60 @@ fn main() { // is_some(), unwrap() let _ = (0..).filter(|n| to_opt(*n).is_some()).map(|a| to_opt(a).unwrap()); + //~^ manual_filter_map // ref pattern, expect() let _ = (0..).filter(|&n| to_opt(n).is_some()).map(|a| to_opt(a).expect("hi")); + //~^ manual_filter_map // is_ok(), unwrap_or() let _ = (0..).filter(|&n| to_res(n).is_ok()).map(|a| to_res(a).unwrap_or(1)); + //~^ manual_filter_map let _ = (1..5) .filter(|&x| to_ref(to_opt(x)).is_some()) + //~^ manual_filter_map .map(|y| to_ref(to_opt(y)).unwrap()); let _ = (1..5) .filter(|x| to_ref(to_opt(*x)).is_some()) + //~^ manual_filter_map .map(|y| to_ref(to_opt(y)).unwrap()); let _ = (1..5) .filter(|&x| to_ref(to_res(x)).is_ok()) + //~^ manual_filter_map .map(|y| to_ref(to_res(y)).unwrap()); let _ = (1..5) .filter(|x| to_ref(to_res(*x)).is_ok()) + //~^ manual_filter_map .map(|y| to_ref(to_res(y)).unwrap()); } #[rustfmt::skip] fn simple_equal() { iter::>().find(|x| x.is_some()).map(|x| x.cloned().unwrap()); + //~^ manual_find_map iter::<&Option<&u8>>().find(|x| x.is_some()).map(|x| x.cloned().unwrap()); + //~^ manual_find_map iter::<&Option>().find(|x| x.is_some()).map(|x| x.as_deref().unwrap()); + //~^ manual_find_map iter::>().find(|&x| to_ref(x).is_some()).map(|y| to_ref(y).cloned().unwrap()); + //~^ manual_find_map iter::>().find(|x| x.is_ok()).map(|x| x.unwrap()); + //~^ manual_find_map iter::<&Result>().find(|x| x.is_ok()).map(|x| x.unwrap()); + //~^ manual_find_map iter::<&&Result>().find(|x| x.is_ok()).map(|x| x.unwrap()); + //~^ manual_find_map iter::>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap()); + //~^ manual_find_map iter::<&Result<&u8, ()>>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap()); + //~^ manual_find_map iter::<&Result>().find(|x| x.is_ok()).map(|x| x.as_deref().unwrap()); + //~^ manual_find_map iter::>().find(|&x| to_ref(x).is_ok()).map(|y| to_ref(y).cloned().unwrap()); + //~^ manual_find_map } fn no_lint() { @@ -91,46 +109,55 @@ fn issue_8920() { let _ = vec .iter() .filter(|f| f.option_field.is_some()) + //~^ manual_filter_map .map(|f| f.option_field.clone().unwrap()); let _ = vec .iter() .filter(|f| f.ref_field.is_some()) + //~^ manual_filter_map .map(|f| f.ref_field.cloned().unwrap()); let _ = vec .iter() .filter(|f| f.ref_field.is_some()) + //~^ manual_filter_map .map(|f| f.ref_field.copied().unwrap()); let _ = vec .iter() .filter(|f| f.result_field.is_ok()) + //~^ manual_filter_map .map(|f| f.result_field.clone().unwrap()); let _ = vec .iter() .filter(|f| f.result_field.is_ok()) + //~^ manual_filter_map .map(|f| f.result_field.as_ref().unwrap()); let _ = vec .iter() .filter(|f| f.result_field.is_ok()) + //~^ manual_filter_map .map(|f| f.result_field.as_deref().unwrap()); let _ = vec .iter_mut() .filter(|f| f.result_field.is_ok()) + //~^ manual_filter_map .map(|f| f.result_field.as_mut().unwrap()); let _ = vec .iter_mut() .filter(|f| f.result_field.is_ok()) + //~^ manual_filter_map .map(|f| f.result_field.as_deref_mut().unwrap()); let _ = vec .iter() .filter(|f| f.result_field.is_ok()) + //~^ manual_filter_map .map(|f| f.result_field.to_owned().unwrap()); } @@ -144,6 +171,7 @@ fn issue8010() { let iter = [Enum::A(123), Enum::B].into_iter(); let _x = iter.clone().filter(|x| matches!(x, Enum::A(_))).map(|x| match x { + //~^ manual_filter_map Enum::A(s) => s, _ => unreachable!(), }); @@ -154,6 +182,7 @@ fn issue8010() { let _x = iter .clone() .filter(|x| matches!(x, Enum::A(_))) + //~^ manual_filter_map .map(|x| if let Enum::A(s) = x { s } else { unreachable!() }); #[allow(clippy::unused_unit)] let _x = iter diff --git a/tests/ui/manual_filter_map.stderr b/tests/ui/manual_filter_map.stderr index 2e5056727831..07c894bf0e66 100644 --- a/tests/ui/manual_filter_map.stderr +++ b/tests/ui/manual_filter_map.stderr @@ -13,87 +13,91 @@ LL | let _ = (0..).filter(|n| to_opt(*n).is_some()).map(|a| to_opt(a).unwrap = help: to override `-D warnings` add `#[allow(clippy::manual_filter_map)]` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> tests/ui/manual_filter_map.rs:12:19 + --> tests/ui/manual_filter_map.rs:13:19 | LL | let _ = (0..).filter(|&n| to_opt(n).is_some()).map(|a| to_opt(a).expect("hi")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `filter_map(|a| to_opt(a))` | note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once - --> tests/ui/manual_filter_map.rs:12:31 + --> tests/ui/manual_filter_map.rs:13:31 | LL | let _ = (0..).filter(|&n| to_opt(n).is_some()).map(|a| to_opt(a).expect("hi")); | ^^^^^^^^^ error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> tests/ui/manual_filter_map.rs:15:19 + --> tests/ui/manual_filter_map.rs:17:19 | LL | let _ = (0..).filter(|&n| to_res(n).is_ok()).map(|a| to_res(a).unwrap_or(1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `filter_map(|a| to_res(a).ok())` | note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once - --> tests/ui/manual_filter_map.rs:15:31 + --> tests/ui/manual_filter_map.rs:17:31 | LL | let _ = (0..).filter(|&n| to_res(n).is_ok()).map(|a| to_res(a).unwrap_or(1)); | ^^^^^^^^^ error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> tests/ui/manual_filter_map.rs:18:10 + --> tests/ui/manual_filter_map.rs:21:10 | LL | .filter(|&x| to_ref(to_opt(x)).is_some()) | __________^ +LL | | LL | | .map(|y| to_ref(to_opt(y)).unwrap()); | |____________________________________________^ help: try: `filter_map(|y| *to_ref(to_opt(y)))` | note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once - --> tests/ui/manual_filter_map.rs:18:22 + --> tests/ui/manual_filter_map.rs:21:22 | LL | .filter(|&x| to_ref(to_opt(x)).is_some()) | ^^^^^^^^^^^^^^^^^ error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> tests/ui/manual_filter_map.rs:21:10 + --> tests/ui/manual_filter_map.rs:25:10 | LL | .filter(|x| to_ref(to_opt(*x)).is_some()) | __________^ +LL | | LL | | .map(|y| to_ref(to_opt(y)).unwrap()); | |____________________________________________^ help: try: `filter_map(|y| *to_ref(to_opt(y)))` | note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once - --> tests/ui/manual_filter_map.rs:21:21 + --> tests/ui/manual_filter_map.rs:25:21 | LL | .filter(|x| to_ref(to_opt(*x)).is_some()) | ^^^^^^^^^^^^^^^^^^ error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> tests/ui/manual_filter_map.rs:25:10 + --> tests/ui/manual_filter_map.rs:30:10 | LL | .filter(|&x| to_ref(to_res(x)).is_ok()) | __________^ +LL | | LL | | .map(|y| to_ref(to_res(y)).unwrap()); | |____________________________________________^ help: try: `filter_map(|y| to_ref(to_res(y)).ok())` | note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once - --> tests/ui/manual_filter_map.rs:25:22 + --> tests/ui/manual_filter_map.rs:30:22 | LL | .filter(|&x| to_ref(to_res(x)).is_ok()) | ^^^^^^^^^^^^^^^^^ error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> tests/ui/manual_filter_map.rs:28:10 + --> tests/ui/manual_filter_map.rs:34:10 | LL | .filter(|x| to_ref(to_res(*x)).is_ok()) | __________^ +LL | | LL | | .map(|y| to_ref(to_res(y)).unwrap()); | |____________________________________________^ help: try: `filter_map(|y| to_ref(to_res(y)).ok())` | note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once - --> tests/ui/manual_filter_map.rs:28:21 + --> tests/ui/manual_filter_map.rs:34:21 | LL | .filter(|x| to_ref(to_res(*x)).is_ok()) | ^^^^^^^^^^^^^^^^^^ error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_filter_map.rs:34:27 + --> tests/ui/manual_filter_map.rs:41:27 | LL | iter::>().find(|x| x.is_some()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned())` @@ -102,164 +106,175 @@ LL | iter::>().find(|x| x.is_some()).map(|x| x.cloned().unwrap() = help: to override `-D warnings` add `#[allow(clippy::manual_find_map)]` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_filter_map.rs:35:28 + --> tests/ui/manual_filter_map.rs:43:28 | LL | iter::<&Option<&u8>>().find(|x| x.is_some()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_filter_map.rs:36:31 + --> tests/ui/manual_filter_map.rs:45:31 | LL | iter::<&Option>().find(|x| x.is_some()).map(|x| x.as_deref().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.as_deref())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_filter_map.rs:37:31 + --> tests/ui/manual_filter_map.rs:47:31 | LL | iter::>().find(|&x| to_ref(x).is_some()).map(|y| to_ref(y).cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|y| to_ref(y).cloned())` | note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once - --> tests/ui/manual_filter_map.rs:37:41 + --> tests/ui/manual_filter_map.rs:47:41 | LL | iter::>().find(|&x| to_ref(x).is_some()).map(|y| to_ref(y).cloned().unwrap()); | ^^^^^^^^^ error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_filter_map.rs:39:30 + --> tests/ui/manual_filter_map.rs:50:30 | LL | iter::>().find(|x| x.is_ok()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_filter_map.rs:40:31 + --> tests/ui/manual_filter_map.rs:52:31 | LL | iter::<&Result>().find(|x| x.is_ok()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_filter_map.rs:41:32 + --> tests/ui/manual_filter_map.rs:54:32 | LL | iter::<&&Result>().find(|x| x.is_ok()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_filter_map.rs:42:31 + --> tests/ui/manual_filter_map.rs:56:31 | LL | iter::>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_filter_map.rs:43:32 + --> tests/ui/manual_filter_map.rs:58:32 | LL | iter::<&Result<&u8, ()>>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_filter_map.rs:44:35 + --> tests/ui/manual_filter_map.rs:60:35 | LL | iter::<&Result>().find(|x| x.is_ok()).map(|x| x.as_deref().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.as_deref().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_filter_map.rs:45:35 + --> tests/ui/manual_filter_map.rs:62:35 | LL | iter::>().find(|&x| to_ref(x).is_ok()).map(|y| to_ref(y).cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|y| to_ref(y).cloned().ok())` | note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once - --> tests/ui/manual_filter_map.rs:45:45 + --> tests/ui/manual_filter_map.rs:62:45 | LL | iter::>().find(|&x| to_ref(x).is_ok()).map(|y| to_ref(y).cloned().unwrap()); | ^^^^^^^^^ error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> tests/ui/manual_filter_map.rs:93:10 + --> tests/ui/manual_filter_map.rs:111:10 | LL | .filter(|f| f.option_field.is_some()) | __________^ +LL | | LL | | .map(|f| f.option_field.clone().unwrap()); | |_________________________________________________^ help: try: `filter_map(|f| f.option_field.clone())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> tests/ui/manual_filter_map.rs:98:10 + --> tests/ui/manual_filter_map.rs:117:10 | LL | .filter(|f| f.ref_field.is_some()) | __________^ +LL | | LL | | .map(|f| f.ref_field.cloned().unwrap()); | |_______________________________________________^ help: try: `filter_map(|f| f.ref_field.cloned())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> tests/ui/manual_filter_map.rs:103:10 + --> tests/ui/manual_filter_map.rs:123:10 | LL | .filter(|f| f.ref_field.is_some()) | __________^ +LL | | LL | | .map(|f| f.ref_field.copied().unwrap()); | |_______________________________________________^ help: try: `filter_map(|f| f.ref_field.copied())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> tests/ui/manual_filter_map.rs:108:10 + --> tests/ui/manual_filter_map.rs:129:10 | LL | .filter(|f| f.result_field.is_ok()) | __________^ +LL | | LL | | .map(|f| f.result_field.clone().unwrap()); | |_________________________________________________^ help: try: `filter_map(|f| f.result_field.clone().ok())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> tests/ui/manual_filter_map.rs:113:10 + --> tests/ui/manual_filter_map.rs:135:10 | LL | .filter(|f| f.result_field.is_ok()) | __________^ +LL | | LL | | .map(|f| f.result_field.as_ref().unwrap()); | |__________________________________________________^ help: try: `filter_map(|f| f.result_field.as_ref().ok())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> tests/ui/manual_filter_map.rs:118:10 + --> tests/ui/manual_filter_map.rs:141:10 | LL | .filter(|f| f.result_field.is_ok()) | __________^ +LL | | LL | | .map(|f| f.result_field.as_deref().unwrap()); | |____________________________________________________^ help: try: `filter_map(|f| f.result_field.as_deref().ok())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> tests/ui/manual_filter_map.rs:123:10 + --> tests/ui/manual_filter_map.rs:147:10 | LL | .filter(|f| f.result_field.is_ok()) | __________^ +LL | | LL | | .map(|f| f.result_field.as_mut().unwrap()); | |__________________________________________________^ help: try: `filter_map(|f| f.result_field.as_mut().ok())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> tests/ui/manual_filter_map.rs:128:10 + --> tests/ui/manual_filter_map.rs:153:10 | LL | .filter(|f| f.result_field.is_ok()) | __________^ +LL | | LL | | .map(|f| f.result_field.as_deref_mut().unwrap()); | |________________________________________________________^ help: try: `filter_map(|f| f.result_field.as_deref_mut().ok())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> tests/ui/manual_filter_map.rs:133:10 + --> tests/ui/manual_filter_map.rs:159:10 | LL | .filter(|f| f.result_field.is_ok()) | __________^ +LL | | LL | | .map(|f| f.result_field.to_owned().unwrap()); | |____________________________________________________^ help: try: `filter_map(|f| f.result_field.to_owned().ok())` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> tests/ui/manual_filter_map.rs:146:27 + --> tests/ui/manual_filter_map.rs:173:27 | LL | let _x = iter.clone().filter(|x| matches!(x, Enum::A(_))).map(|x| match x { | ___________________________^ +LL | | LL | | Enum::A(s) => s, LL | | _ => unreachable!(), LL | | }); | |______^ help: try: `filter_map(|x| match x { Enum::A(s) => Some(s), _ => None })` error: `filter(..).map(..)` can be simplified as `filter_map(..)` - --> tests/ui/manual_filter_map.rs:156:10 + --> tests/ui/manual_filter_map.rs:184:10 | LL | .filter(|x| matches!(x, Enum::A(_))) | __________^ +LL | | LL | | .map(|x| if let Enum::A(s) = x { s } else { unreachable!() }); | |_____________________________________________________________________^ help: try: `filter_map(|x| match x { Enum::A(s) => Some(s), _ => None })` diff --git a/tests/ui/manual_find.rs b/tests/ui/manual_find.rs index 0a105b0359e5..20b557f21d14 100644 --- a/tests/ui/manual_find.rs +++ b/tests/ui/manual_find.rs @@ -3,8 +3,8 @@ //@no-rustfix fn vec_string(strings: Vec) -> Option { for s in strings { - //~^ ERROR: manual implementation of `Iterator::find` - //~| NOTE: you may need to dereference some variables + //~^ manual_find + if s == String::new() { return Some(s); } @@ -14,8 +14,8 @@ fn vec_string(strings: Vec) -> Option { fn tuple(arr: Vec<(String, i32)>) -> Option { for (s, _) in arr { - //~^ ERROR: manual implementation of `Iterator::find` - //~| NOTE: you may need to dereference some variables + //~^ manual_find + if s == String::new() { return Some(s); } diff --git a/tests/ui/manual_find_fixable.rs b/tests/ui/manual_find_fixable.rs index 56c3f2629c7a..08a7dd2c6eee 100644 --- a/tests/ui/manual_find_fixable.rs +++ b/tests/ui/manual_find_fixable.rs @@ -8,6 +8,7 @@ const ARRAY: &[u32; 5] = &[2, 7, 1, 9, 3]; fn lookup(n: u32) -> Option { for &v in ARRAY { + //~^ manual_find if v == n { return Some(v); } @@ -17,6 +18,7 @@ fn lookup(n: u32) -> Option { fn with_pat(arr: Vec<(u32, u32)>) -> Option { for (a, _) in arr { + //~^ manual_find if a % 2 == 0 { return Some(a); } @@ -30,6 +32,7 @@ struct Data { } fn with_struct(arr: Vec) -> Option { for el in arr { + //~^ manual_find if el.name.len() == 10 { return Some(el); } @@ -40,6 +43,7 @@ fn with_struct(arr: Vec) -> Option { struct Tuple(usize, usize); fn with_tuple_struct(arr: Vec) -> Option { for Tuple(a, _) in arr { + //~^ manual_find if a >= 3 { return Some(a); } @@ -55,6 +59,7 @@ impl A { } fn with_method_call(arr: Vec) -> Option { for el in arr { + //~^ manual_find if el.should_keep() { return Some(el); } @@ -65,6 +70,7 @@ fn with_method_call(arr: Vec) -> Option { fn with_closure(arr: Vec) -> Option { let f = |el: u32| -> u32 { el + 10 }; for el in arr { + //~^ manual_find if f(el) == 20 { return Some(el); } @@ -75,6 +81,7 @@ fn with_closure(arr: Vec) -> Option { fn with_closure2(arr: HashMap) -> Option { let f = |el: i32| -> bool { el == 10 }; for &el in arr.values() { + //~^ manual_find if f(el) { return Some(el); } @@ -84,6 +91,7 @@ fn with_closure2(arr: HashMap) -> Option { fn with_bool(arr: Vec) -> Option { for el in arr { + //~^ manual_find if el.is_true { return Some(el); } @@ -114,6 +122,7 @@ fn with_else(arr: Vec) -> Option { fn tuple_with_ref(v: [(u8, &u8); 3]) -> Option { for (_, &x) in v { + //~^ manual_find if x > 10 { return Some(x); } @@ -123,6 +132,7 @@ fn tuple_with_ref(v: [(u8, &u8); 3]) -> Option { fn ref_to_tuple_with_ref(v: &[(u8, &u8)]) -> Option { for &(_, &x) in v { + //~^ manual_find if x > 10 { return Some(x); } @@ -132,6 +142,7 @@ fn ref_to_tuple_with_ref(v: &[(u8, &u8)]) -> Option { fn explicit_ret(arr: Vec) -> Option { for x in arr { + //~^ manual_find if x >= 5 { return Some(x); } @@ -187,6 +198,7 @@ fn as_closure() { #[rustfmt::skip] let f = |arr: Vec| -> Option { for x in arr { + //~^ manual_find if x < 1 { return Some(x); } diff --git a/tests/ui/manual_find_fixable.stderr b/tests/ui/manual_find_fixable.stderr index 5ed8be1b3eed..afa453c5a876 100644 --- a/tests/ui/manual_find_fixable.stderr +++ b/tests/ui/manual_find_fixable.stderr @@ -2,6 +2,7 @@ error: manual implementation of `Iterator::find` --> tests/ui/manual_find_fixable.rs:10:5 | LL | / for &v in ARRAY { +LL | | LL | | if v == n { LL | | return Some(v); ... | @@ -12,9 +13,10 @@ LL | | None = help: to override `-D warnings` add `#[allow(clippy::manual_find)]` error: manual implementation of `Iterator::find` - --> tests/ui/manual_find_fixable.rs:19:5 + --> tests/ui/manual_find_fixable.rs:20:5 | LL | / for (a, _) in arr { +LL | | LL | | if a % 2 == 0 { LL | | return Some(a); ... | @@ -22,9 +24,10 @@ LL | | None | |________^ help: replace with an iterator: `arr.into_iter().map(|(a, _)| a).find(|&a| a % 2 == 0)` error: manual implementation of `Iterator::find` - --> tests/ui/manual_find_fixable.rs:32:5 + --> tests/ui/manual_find_fixable.rs:34:5 | LL | / for el in arr { +LL | | LL | | if el.name.len() == 10 { LL | | return Some(el); ... | @@ -34,9 +37,10 @@ LL | | None = note: you may need to dereference some variables error: manual implementation of `Iterator::find` - --> tests/ui/manual_find_fixable.rs:42:5 + --> tests/ui/manual_find_fixable.rs:45:5 | LL | / for Tuple(a, _) in arr { +LL | | LL | | if a >= 3 { LL | | return Some(a); ... | @@ -44,9 +48,10 @@ LL | | None | |________^ help: replace with an iterator: `arr.into_iter().map(|Tuple(a, _)| a).find(|&a| a >= 3)` error: manual implementation of `Iterator::find` - --> tests/ui/manual_find_fixable.rs:57:5 + --> tests/ui/manual_find_fixable.rs:61:5 | LL | / for el in arr { +LL | | LL | | if el.should_keep() { LL | | return Some(el); ... | @@ -56,9 +61,10 @@ LL | | None = note: you may need to dereference some variables error: manual implementation of `Iterator::find` - --> tests/ui/manual_find_fixable.rs:67:5 + --> tests/ui/manual_find_fixable.rs:72:5 | LL | / for el in arr { +LL | | LL | | if f(el) == 20 { LL | | return Some(el); ... | @@ -66,9 +72,10 @@ LL | | None | |________^ help: replace with an iterator: `arr.into_iter().find(|&el| f(el) == 20)` error: manual implementation of `Iterator::find` - --> tests/ui/manual_find_fixable.rs:77:5 + --> tests/ui/manual_find_fixable.rs:83:5 | LL | / for &el in arr.values() { +LL | | LL | | if f(el) { LL | | return Some(el); ... | @@ -76,9 +83,10 @@ LL | | None | |________^ help: replace with an iterator: `arr.values().find(|&&el| f(el)).copied()` error: manual implementation of `Iterator::find` - --> tests/ui/manual_find_fixable.rs:86:5 + --> tests/ui/manual_find_fixable.rs:93:5 | LL | / for el in arr { +LL | | LL | | if el.is_true { LL | | return Some(el); ... | @@ -88,9 +96,10 @@ LL | | None = note: you may need to dereference some variables error: manual implementation of `Iterator::find` - --> tests/ui/manual_find_fixable.rs:116:5 + --> tests/ui/manual_find_fixable.rs:124:5 | LL | / for (_, &x) in v { +LL | | LL | | if x > 10 { LL | | return Some(x); ... | @@ -98,9 +107,10 @@ LL | | None | |________^ help: replace with an iterator: `v.into_iter().map(|(_, &x)| x).find(|&x| x > 10)` error: manual implementation of `Iterator::find` - --> tests/ui/manual_find_fixable.rs:125:5 + --> tests/ui/manual_find_fixable.rs:134:5 | LL | / for &(_, &x) in v { +LL | | LL | | if x > 10 { LL | | return Some(x); ... | @@ -108,9 +118,10 @@ LL | | None | |________^ help: replace with an iterator: `v.iter().map(|&(_, &x)| x).find(|&x| x > 10)` error: manual implementation of `Iterator::find` - --> tests/ui/manual_find_fixable.rs:134:5 + --> tests/ui/manual_find_fixable.rs:144:5 | LL | / for x in arr { +LL | | LL | | if x >= 5 { LL | | return Some(x); ... | @@ -118,9 +129,10 @@ LL | | return None; | |________________^ help: replace with an iterator: `arr.into_iter().find(|&x| x >= 5)` error: manual implementation of `Iterator::find` - --> tests/ui/manual_find_fixable.rs:189:9 + --> tests/ui/manual_find_fixable.rs:200:9 | LL | / for x in arr { +LL | | LL | | if x < 1 { LL | | return Some(x); ... | diff --git a/tests/ui/manual_find_map.fixed b/tests/ui/manual_find_map.fixed index 2d9a356b9bcd..1a452d50261f 100644 --- a/tests/ui/manual_find_map.fixed +++ b/tests/ui/manual_find_map.fixed @@ -7,12 +7,15 @@ fn main() { // is_some(), unwrap() let _ = (0..).find_map(|a| to_opt(a)); + //~^ manual_find_map // ref pattern, expect() let _ = (0..).find_map(|a| to_opt(a)); + //~^ manual_find_map // is_ok(), unwrap_or() let _ = (0..).find_map(|a| to_res(a).ok()); + //~^ manual_find_map let _ = (1..5) .find_map(|y| *to_ref(to_opt(y))); @@ -28,20 +31,34 @@ fn main() { #[rustfmt::skip] fn simple_equal() { iter::>().find_map(|x| x); + //~^ manual_find_map iter::<&Option>().find_map(|x| *x); + //~^ manual_find_map iter::<&&Option>().find_map(|x| **x); + //~^ manual_find_map iter::>().find_map(|x| x.cloned()); + //~^ manual_find_map iter::<&Option<&u8>>().find_map(|x| x.cloned()); + //~^ manual_find_map iter::<&Option>().find_map(|x| x.as_deref()); + //~^ manual_find_map iter::>().find_map(|y| to_ref(y).cloned()); + //~^ manual_find_map iter::>().find_map(|x| x.ok()); + //~^ manual_find_map iter::<&Result>().find_map(|x| x.ok()); + //~^ manual_find_map iter::<&&Result>().find_map(|x| x.ok()); + //~^ manual_find_map iter::>().find_map(|x| x.cloned().ok()); + //~^ manual_find_map iter::<&Result<&u8, ()>>().find_map(|x| x.cloned().ok()); + //~^ manual_find_map iter::<&Result>().find_map(|x| x.as_deref().ok()); + //~^ manual_find_map iter::>().find_map(|y| to_ref(y).cloned().ok()); + //~^ manual_find_map } fn no_lint() { diff --git a/tests/ui/manual_find_map.rs b/tests/ui/manual_find_map.rs index 7c5cc136695a..9415a2d2b572 100644 --- a/tests/ui/manual_find_map.rs +++ b/tests/ui/manual_find_map.rs @@ -7,45 +7,66 @@ fn main() { // is_some(), unwrap() let _ = (0..).find(|n| to_opt(*n).is_some()).map(|a| to_opt(a).unwrap()); + //~^ manual_find_map // ref pattern, expect() let _ = (0..).find(|&n| to_opt(n).is_some()).map(|a| to_opt(a).expect("hi")); + //~^ manual_find_map // is_ok(), unwrap_or() let _ = (0..).find(|&n| to_res(n).is_ok()).map(|a| to_res(a).unwrap_or(1)); + //~^ manual_find_map let _ = (1..5) .find(|&x| to_ref(to_opt(x)).is_some()) + //~^ manual_find_map .map(|y| to_ref(to_opt(y)).unwrap()); let _ = (1..5) .find(|x| to_ref(to_opt(*x)).is_some()) + //~^ manual_find_map .map(|y| to_ref(to_opt(y)).unwrap()); let _ = (1..5) .find(|&x| to_ref(to_res(x)).is_ok()) + //~^ manual_find_map .map(|y| to_ref(to_res(y)).unwrap()); let _ = (1..5) .find(|x| to_ref(to_res(*x)).is_ok()) + //~^ manual_find_map .map(|y| to_ref(to_res(y)).unwrap()); } #[rustfmt::skip] fn simple_equal() { iter::>().find(|x| x.is_some()).map(|x| x.unwrap()); + //~^ manual_find_map iter::<&Option>().find(|x| x.is_some()).map(|x| x.unwrap()); + //~^ manual_find_map iter::<&&Option>().find(|x| x.is_some()).map(|x| x.unwrap()); + //~^ manual_find_map iter::>().find(|x| x.is_some()).map(|x| x.cloned().unwrap()); + //~^ manual_find_map iter::<&Option<&u8>>().find(|x| x.is_some()).map(|x| x.cloned().unwrap()); + //~^ manual_find_map iter::<&Option>().find(|x| x.is_some()).map(|x| x.as_deref().unwrap()); + //~^ manual_find_map iter::>().find(|&x| to_ref(x).is_some()).map(|y| to_ref(y).cloned().unwrap()); + //~^ manual_find_map iter::>().find(|x| x.is_ok()).map(|x| x.unwrap()); + //~^ manual_find_map iter::<&Result>().find(|x| x.is_ok()).map(|x| x.unwrap()); + //~^ manual_find_map iter::<&&Result>().find(|x| x.is_ok()).map(|x| x.unwrap()); + //~^ manual_find_map iter::>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap()); + //~^ manual_find_map iter::<&Result<&u8, ()>>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap()); + //~^ manual_find_map iter::<&Result>().find(|x| x.is_ok()).map(|x| x.as_deref().unwrap()); + //~^ manual_find_map iter::>().find(|&x| to_ref(x).is_ok()).map(|y| to_ref(y).cloned().unwrap()); + //~^ manual_find_map } fn no_lint() { @@ -94,45 +115,54 @@ fn issue_8920() { let _ = vec .iter() .find(|f| f.option_field.is_some()) + //~^ manual_find_map .map(|f| f.option_field.clone().unwrap()); let _ = vec .iter() .find(|f| f.ref_field.is_some()) + //~^ manual_find_map .map(|f| f.ref_field.cloned().unwrap()); let _ = vec .iter() .find(|f| f.ref_field.is_some()) + //~^ manual_find_map .map(|f| f.ref_field.copied().unwrap()); let _ = vec .iter() .find(|f| f.result_field.is_ok()) + //~^ manual_find_map .map(|f| f.result_field.clone().unwrap()); let _ = vec .iter() .find(|f| f.result_field.is_ok()) + //~^ manual_find_map .map(|f| f.result_field.as_ref().unwrap()); let _ = vec .iter() .find(|f| f.result_field.is_ok()) + //~^ manual_find_map .map(|f| f.result_field.as_deref().unwrap()); let _ = vec .iter_mut() .find(|f| f.result_field.is_ok()) + //~^ manual_find_map .map(|f| f.result_field.as_mut().unwrap()); let _ = vec .iter_mut() .find(|f| f.result_field.is_ok()) + //~^ manual_find_map .map(|f| f.result_field.as_deref_mut().unwrap()); let _ = vec .iter() .find(|f| f.result_field.is_ok()) + //~^ manual_find_map .map(|f| f.result_field.to_owned().unwrap()); } diff --git a/tests/ui/manual_find_map.stderr b/tests/ui/manual_find_map.stderr index 2722d59f52a9..8fa6c090e6d2 100644 --- a/tests/ui/manual_find_map.stderr +++ b/tests/ui/manual_find_map.stderr @@ -13,250 +13,263 @@ LL | let _ = (0..).find(|n| to_opt(*n).is_some()).map(|a| to_opt(a).unwrap() = help: to override `-D warnings` add `#[allow(clippy::manual_find_map)]` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:12:19 + --> tests/ui/manual_find_map.rs:13:19 | LL | let _ = (0..).find(|&n| to_opt(n).is_some()).map(|a| to_opt(a).expect("hi")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|a| to_opt(a))` | note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once - --> tests/ui/manual_find_map.rs:12:29 + --> tests/ui/manual_find_map.rs:13:29 | LL | let _ = (0..).find(|&n| to_opt(n).is_some()).map(|a| to_opt(a).expect("hi")); | ^^^^^^^^^ error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:15:19 + --> tests/ui/manual_find_map.rs:17:19 | LL | let _ = (0..).find(|&n| to_res(n).is_ok()).map(|a| to_res(a).unwrap_or(1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|a| to_res(a).ok())` | note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once - --> tests/ui/manual_find_map.rs:15:29 + --> tests/ui/manual_find_map.rs:17:29 | LL | let _ = (0..).find(|&n| to_res(n).is_ok()).map(|a| to_res(a).unwrap_or(1)); | ^^^^^^^^^ error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:18:10 + --> tests/ui/manual_find_map.rs:21:10 | LL | .find(|&x| to_ref(to_opt(x)).is_some()) | __________^ +LL | | LL | | .map(|y| to_ref(to_opt(y)).unwrap()); | |____________________________________________^ help: try: `find_map(|y| *to_ref(to_opt(y)))` | note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once - --> tests/ui/manual_find_map.rs:18:20 + --> tests/ui/manual_find_map.rs:21:20 | LL | .find(|&x| to_ref(to_opt(x)).is_some()) | ^^^^^^^^^^^^^^^^^ error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:21:10 + --> tests/ui/manual_find_map.rs:25:10 | LL | .find(|x| to_ref(to_opt(*x)).is_some()) | __________^ +LL | | LL | | .map(|y| to_ref(to_opt(y)).unwrap()); | |____________________________________________^ help: try: `find_map(|y| *to_ref(to_opt(y)))` | note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once - --> tests/ui/manual_find_map.rs:21:19 + --> tests/ui/manual_find_map.rs:25:19 | LL | .find(|x| to_ref(to_opt(*x)).is_some()) | ^^^^^^^^^^^^^^^^^^ error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:25:10 + --> tests/ui/manual_find_map.rs:30:10 | LL | .find(|&x| to_ref(to_res(x)).is_ok()) | __________^ +LL | | LL | | .map(|y| to_ref(to_res(y)).unwrap()); | |____________________________________________^ help: try: `find_map(|y| to_ref(to_res(y)).ok())` | note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once - --> tests/ui/manual_find_map.rs:25:20 + --> tests/ui/manual_find_map.rs:30:20 | LL | .find(|&x| to_ref(to_res(x)).is_ok()) | ^^^^^^^^^^^^^^^^^ error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:28:10 + --> tests/ui/manual_find_map.rs:34:10 | LL | .find(|x| to_ref(to_res(*x)).is_ok()) | __________^ +LL | | LL | | .map(|y| to_ref(to_res(y)).unwrap()); | |____________________________________________^ help: try: `find_map(|y| to_ref(to_res(y)).ok())` | note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once - --> tests/ui/manual_find_map.rs:28:19 + --> tests/ui/manual_find_map.rs:34:19 | LL | .find(|x| to_ref(to_res(*x)).is_ok()) | ^^^^^^^^^^^^^^^^^^ error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:34:26 + --> tests/ui/manual_find_map.rs:41:26 | LL | iter::>().find(|x| x.is_some()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x)` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:35:27 + --> tests/ui/manual_find_map.rs:43:27 | LL | iter::<&Option>().find(|x| x.is_some()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| *x)` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:36:28 + --> tests/ui/manual_find_map.rs:45:28 | LL | iter::<&&Option>().find(|x| x.is_some()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| **x)` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:37:27 + --> tests/ui/manual_find_map.rs:47:27 | LL | iter::>().find(|x| x.is_some()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:38:28 + --> tests/ui/manual_find_map.rs:49:28 | LL | iter::<&Option<&u8>>().find(|x| x.is_some()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:39:31 + --> tests/ui/manual_find_map.rs:51:31 | LL | iter::<&Option>().find(|x| x.is_some()).map(|x| x.as_deref().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.as_deref())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:40:31 + --> tests/ui/manual_find_map.rs:53:31 | LL | iter::>().find(|&x| to_ref(x).is_some()).map(|y| to_ref(y).cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|y| to_ref(y).cloned())` | note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once - --> tests/ui/manual_find_map.rs:40:41 + --> tests/ui/manual_find_map.rs:53:41 | LL | iter::>().find(|&x| to_ref(x).is_some()).map(|y| to_ref(y).cloned().unwrap()); | ^^^^^^^^^ error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:42:30 + --> tests/ui/manual_find_map.rs:56:30 | LL | iter::>().find(|x| x.is_ok()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:43:31 + --> tests/ui/manual_find_map.rs:58:31 | LL | iter::<&Result>().find(|x| x.is_ok()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:44:32 + --> tests/ui/manual_find_map.rs:60:32 | LL | iter::<&&Result>().find(|x| x.is_ok()).map(|x| x.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:45:31 + --> tests/ui/manual_find_map.rs:62:31 | LL | iter::>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:46:32 + --> tests/ui/manual_find_map.rs:64:32 | LL | iter::<&Result<&u8, ()>>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:47:35 + --> tests/ui/manual_find_map.rs:66:35 | LL | iter::<&Result>().find(|x| x.is_ok()).map(|x| x.as_deref().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.as_deref().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:48:35 + --> tests/ui/manual_find_map.rs:68:35 | LL | iter::>().find(|&x| to_ref(x).is_ok()).map(|y| to_ref(y).cloned().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|y| to_ref(y).cloned().ok())` | note: the suggestion might change the behavior of the program when merging `filter` and `map`, because this expression potentially contains side effects and will only execute once - --> tests/ui/manual_find_map.rs:48:45 + --> tests/ui/manual_find_map.rs:68:45 | LL | iter::>().find(|&x| to_ref(x).is_ok()).map(|y| to_ref(y).cloned().unwrap()); | ^^^^^^^^^ error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:96:10 + --> tests/ui/manual_find_map.rs:117:10 | LL | .find(|f| f.option_field.is_some()) | __________^ +LL | | LL | | .map(|f| f.option_field.clone().unwrap()); | |_________________________________________________^ help: try: `find_map(|f| f.option_field.clone())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:101:10 + --> tests/ui/manual_find_map.rs:123:10 | LL | .find(|f| f.ref_field.is_some()) | __________^ +LL | | LL | | .map(|f| f.ref_field.cloned().unwrap()); | |_______________________________________________^ help: try: `find_map(|f| f.ref_field.cloned())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:106:10 + --> tests/ui/manual_find_map.rs:129:10 | LL | .find(|f| f.ref_field.is_some()) | __________^ +LL | | LL | | .map(|f| f.ref_field.copied().unwrap()); | |_______________________________________________^ help: try: `find_map(|f| f.ref_field.copied())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:111:10 + --> tests/ui/manual_find_map.rs:135:10 | LL | .find(|f| f.result_field.is_ok()) | __________^ +LL | | LL | | .map(|f| f.result_field.clone().unwrap()); | |_________________________________________________^ help: try: `find_map(|f| f.result_field.clone().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:116:10 + --> tests/ui/manual_find_map.rs:141:10 | LL | .find(|f| f.result_field.is_ok()) | __________^ +LL | | LL | | .map(|f| f.result_field.as_ref().unwrap()); | |__________________________________________________^ help: try: `find_map(|f| f.result_field.as_ref().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:121:10 + --> tests/ui/manual_find_map.rs:147:10 | LL | .find(|f| f.result_field.is_ok()) | __________^ +LL | | LL | | .map(|f| f.result_field.as_deref().unwrap()); | |____________________________________________________^ help: try: `find_map(|f| f.result_field.as_deref().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:126:10 + --> tests/ui/manual_find_map.rs:153:10 | LL | .find(|f| f.result_field.is_ok()) | __________^ +LL | | LL | | .map(|f| f.result_field.as_mut().unwrap()); | |__________________________________________________^ help: try: `find_map(|f| f.result_field.as_mut().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:131:10 + --> tests/ui/manual_find_map.rs:159:10 | LL | .find(|f| f.result_field.is_ok()) | __________^ +LL | | LL | | .map(|f| f.result_field.as_deref_mut().unwrap()); | |________________________________________________________^ help: try: `find_map(|f| f.result_field.as_deref_mut().ok())` error: `find(..).map(..)` can be simplified as `find_map(..)` - --> tests/ui/manual_find_map.rs:136:10 + --> tests/ui/manual_find_map.rs:165:10 | LL | .find(|f| f.result_field.is_ok()) | __________^ +LL | | LL | | .map(|f| f.result_field.to_owned().unwrap()); | |____________________________________________________^ help: try: `find_map(|f| f.result_field.to_owned().ok())` diff --git a/tests/ui/manual_flatten.rs b/tests/ui/manual_flatten.rs index d57333ace040..97f35c36e24c 100644 --- a/tests/ui/manual_flatten.rs +++ b/tests/ui/manual_flatten.rs @@ -5,7 +5,8 @@ fn main() { // Test for loop over implicitly adjusted `Iterator` with `if let` expression let x = vec![Some(1), Some(2), Some(3)]; for n in x { - //~^ ERROR: unnecessary `if let` since only the `Some` variant of the iterator element + //~^ manual_flatten + if let Some(y) = n { println!("{}", y); } @@ -14,7 +15,8 @@ fn main() { // Test for loop over implicitly adjusted `Iterator` with `if let` statement let y: Vec> = vec![]; for n in y.clone() { - //~^ ERROR: unnecessary `if let` since only the `Ok` variant of the iterator element i + //~^ manual_flatten + if let Ok(n) = n { println!("{}", n); }; @@ -22,7 +24,8 @@ fn main() { // Test for loop over by reference for n in &y { - //~^ ERROR: unnecessary `if let` since only the `Ok` variant of the iterator element i + //~^ manual_flatten + if let Ok(n) = n { println!("{}", n); } @@ -31,7 +34,8 @@ fn main() { // Test for loop over an implicit reference let z = &y; for n in z { - //~^ ERROR: unnecessary `if let` since only the `Ok` variant of the iterator element i + //~^ manual_flatten + if let Ok(n) = n { println!("{}", n); } @@ -41,7 +45,8 @@ fn main() { let z = vec![Some(1), Some(2), Some(3)]; let z = z.iter(); for n in z { - //~^ ERROR: unnecessary `if let` since only the `Some` variant of the iterator element + //~^ manual_flatten + if let Some(m) = n { println!("{}", m); } @@ -75,7 +80,8 @@ fn main() { let vec_of_ref = vec![&Some(1)]; for n in &vec_of_ref { - //~^ ERROR: unnecessary `if let` since only the `Some` variant of the iterator element + //~^ manual_flatten + if let Some(n) = n { println!("{:?}", n); } @@ -83,7 +89,8 @@ fn main() { let vec_of_ref = &vec_of_ref; for n in vec_of_ref { - //~^ ERROR: unnecessary `if let` since only the `Some` variant of the iterator element + //~^ manual_flatten + if let Some(n) = n { println!("{:?}", n); } @@ -91,7 +98,8 @@ fn main() { let slice_of_ref = &[&Some(1)]; for n in slice_of_ref { - //~^ ERROR: unnecessary `if let` since only the `Some` variant of the iterator element + //~^ manual_flatten + if let Some(n) = n { println!("{:?}", n); } @@ -122,7 +130,8 @@ fn main() { fn run_unformatted_tests() { // Skip rustfmt here on purpose so the suggestion does not fit in one line for n in vec![ - //~^ ERROR: unnecessary `if let` since only the `Some` variant of the iterator element + //~^ manual_flatten + Some(1), Some(2), Some(3) diff --git a/tests/ui/manual_flatten.stderr b/tests/ui/manual_flatten.stderr index 93f7f11b5e64..5ab25658017e 100644 --- a/tests/ui/manual_flatten.stderr +++ b/tests/ui/manual_flatten.stderr @@ -6,14 +6,14 @@ LL | for n in x { | _____| | | LL | | +LL | | LL | | if let Some(y) = n { -LL | | println!("{}", y); -LL | | } +... | LL | | } | |_____^ | help: ...and remove the `if let` statement in the for loop - --> tests/ui/manual_flatten.rs:9:9 + --> tests/ui/manual_flatten.rs:10:9 | LL | / if let Some(y) = n { LL | | println!("{}", y); @@ -23,13 +23,14 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::manual_flatten)]` error: unnecessary `if let` since only the `Ok` variant of the iterator element is used - --> tests/ui/manual_flatten.rs:16:5 + --> tests/ui/manual_flatten.rs:17:5 | LL | for n in y.clone() { | ^ --------- help: try: `y.clone().into_iter().flatten()` | _____| | | LL | | +LL | | LL | | if let Ok(n) = n { LL | | println!("{}", n); LL | | }; @@ -37,7 +38,7 @@ LL | | } | |_____^ | help: ...and remove the `if let` statement in the for loop - --> tests/ui/manual_flatten.rs:18:9 + --> tests/ui/manual_flatten.rs:20:9 | LL | / if let Ok(n) = n { LL | | println!("{}", n); @@ -45,21 +46,21 @@ LL | | }; | |_________^ error: unnecessary `if let` since only the `Ok` variant of the iterator element is used - --> tests/ui/manual_flatten.rs:24:5 + --> tests/ui/manual_flatten.rs:26:5 | LL | for n in &y { | ^ -- help: try: `y.iter().flatten()` | _____| | | LL | | +LL | | LL | | if let Ok(n) = n { -LL | | println!("{}", n); -LL | | } +... | LL | | } | |_____^ | help: ...and remove the `if let` statement in the for loop - --> tests/ui/manual_flatten.rs:26:9 + --> tests/ui/manual_flatten.rs:29:9 | LL | / if let Ok(n) = n { LL | | println!("{}", n); @@ -67,21 +68,21 @@ LL | | } | |_________^ error: unnecessary `if let` since only the `Ok` variant of the iterator element is used - --> tests/ui/manual_flatten.rs:33:5 + --> tests/ui/manual_flatten.rs:36:5 | LL | for n in z { | ^ - help: try: `z.iter().flatten()` | _____| | | LL | | +LL | | LL | | if let Ok(n) = n { -LL | | println!("{}", n); -LL | | } +... | LL | | } | |_____^ | help: ...and remove the `if let` statement in the for loop - --> tests/ui/manual_flatten.rs:35:9 + --> tests/ui/manual_flatten.rs:39:9 | LL | / if let Ok(n) = n { LL | | println!("{}", n); @@ -89,21 +90,21 @@ LL | | } | |_________^ error: unnecessary `if let` since only the `Some` variant of the iterator element is used - --> tests/ui/manual_flatten.rs:43:5 + --> tests/ui/manual_flatten.rs:47:5 | LL | for n in z { | ^ - help: try: `z.flatten()` | _____| | | LL | | +LL | | LL | | if let Some(m) = n { -LL | | println!("{}", m); -LL | | } +... | LL | | } | |_____^ | help: ...and remove the `if let` statement in the for loop - --> tests/ui/manual_flatten.rs:45:9 + --> tests/ui/manual_flatten.rs:50:9 | LL | / if let Some(m) = n { LL | | println!("{}", m); @@ -111,21 +112,21 @@ LL | | } | |_________^ error: unnecessary `if let` since only the `Some` variant of the iterator element is used - --> tests/ui/manual_flatten.rs:77:5 + --> tests/ui/manual_flatten.rs:82:5 | LL | for n in &vec_of_ref { | ^ ----------- help: try: `vec_of_ref.iter().copied().flatten()` | _____| | | LL | | +LL | | LL | | if let Some(n) = n { -LL | | println!("{:?}", n); -LL | | } +... | LL | | } | |_____^ | help: ...and remove the `if let` statement in the for loop - --> tests/ui/manual_flatten.rs:79:9 + --> tests/ui/manual_flatten.rs:85:9 | LL | / if let Some(n) = n { LL | | println!("{:?}", n); @@ -133,21 +134,21 @@ LL | | } | |_________^ error: unnecessary `if let` since only the `Some` variant of the iterator element is used - --> tests/ui/manual_flatten.rs:85:5 + --> tests/ui/manual_flatten.rs:91:5 | LL | for n in vec_of_ref { | ^ ---------- help: try: `vec_of_ref.iter().copied().flatten()` | _____| | | LL | | +LL | | LL | | if let Some(n) = n { -LL | | println!("{:?}", n); -LL | | } +... | LL | | } | |_____^ | help: ...and remove the `if let` statement in the for loop - --> tests/ui/manual_flatten.rs:87:9 + --> tests/ui/manual_flatten.rs:94:9 | LL | / if let Some(n) = n { LL | | println!("{:?}", n); @@ -155,21 +156,21 @@ LL | | } | |_________^ error: unnecessary `if let` since only the `Some` variant of the iterator element is used - --> tests/ui/manual_flatten.rs:93:5 + --> tests/ui/manual_flatten.rs:100:5 | LL | for n in slice_of_ref { | ^ ------------ help: try: `slice_of_ref.iter().copied().flatten()` | _____| | | LL | | +LL | | LL | | if let Some(n) = n { -LL | | println!("{:?}", n); -LL | | } +... | LL | | } | |_____^ | help: ...and remove the `if let` statement in the for loop - --> tests/ui/manual_flatten.rs:95:9 + --> tests/ui/manual_flatten.rs:103:9 | LL | / if let Some(n) = n { LL | | println!("{:?}", n); @@ -177,18 +178,18 @@ LL | | } | |_________^ error: unnecessary `if let` since only the `Some` variant of the iterator element is used - --> tests/ui/manual_flatten.rs:124:5 + --> tests/ui/manual_flatten.rs:132:5 | LL | / for n in vec![ LL | | +LL | | LL | | Some(1), -LL | | Some(2), ... | LL | | } | |_____^ | help: remove the `if let` statement in the for loop and then... - --> tests/ui/manual_flatten.rs:130:9 + --> tests/ui/manual_flatten.rs:139:9 | LL | / if let Some(n) = n { LL | | println!("{:?}", n); diff --git a/tests/ui/manual_float_methods.rs b/tests/ui/manual_float_methods.rs index 66545d180ef9..62cdc1c141d0 100644 --- a/tests/ui/manual_float_methods.rs +++ b/tests/ui/manual_float_methods.rs @@ -22,12 +22,18 @@ fn fn_test_not_inf() -> f64 { fn main() { let x = 1.0f32; if x == f32::INFINITY || x == f32::NEG_INFINITY {} + //~^ manual_is_infinite if x != f32::INFINITY && x != f32::NEG_INFINITY {} + //~^ manual_is_finite if x == INFINITE || x == NEG_INFINITE {} + //~^ manual_is_infinite if x != INFINITE && x != NEG_INFINITE {} + //~^ manual_is_finite let x = 1.0f64; if x == f64::INFINITY || x == f64::NEG_INFINITY {} + //~^ manual_is_infinite if x != f64::INFINITY && x != f64::NEG_INFINITY {} + //~^ manual_is_finite // Don't lint if x.is_infinite() {} if x.is_finite() {} @@ -42,6 +48,7 @@ fn main() { const { let x = 1.0f64; if x == f64::INFINITY || x == f64::NEG_INFINITY {} + //~^ manual_is_infinite } const X: f64 = 1.0f64; if const { X == f64::INFINITY || X == f64::NEG_INFINITY } {} diff --git a/tests/ui/manual_float_methods.stderr b/tests/ui/manual_float_methods.stderr index 1352c5e73cab..352c879c87d7 100644 --- a/tests/ui/manual_float_methods.stderr +++ b/tests/ui/manual_float_methods.stderr @@ -8,7 +8,7 @@ LL | if x == f32::INFINITY || x == f32::NEG_INFINITY {} = help: to override `-D warnings` add `#[allow(clippy::manual_is_infinite)]` error: manually checking if a float is finite - --> tests/ui/manual_float_methods.rs:25:8 + --> tests/ui/manual_float_methods.rs:26:8 | LL | if x != f32::INFINITY && x != f32::NEG_INFINITY {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,13 +32,13 @@ LL + if !x.is_infinite() {} | error: manually checking if a float is infinite - --> tests/ui/manual_float_methods.rs:26:8 + --> tests/ui/manual_float_methods.rs:28:8 | LL | if x == INFINITE || x == NEG_INFINITE {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the dedicated method instead: `x.is_infinite()` error: manually checking if a float is finite - --> tests/ui/manual_float_methods.rs:27:8 + --> tests/ui/manual_float_methods.rs:30:8 | LL | if x != INFINITE && x != NEG_INFINITE {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,13 +60,13 @@ LL + if !x.is_infinite() {} | error: manually checking if a float is infinite - --> tests/ui/manual_float_methods.rs:29:8 + --> tests/ui/manual_float_methods.rs:33:8 | LL | if x == f64::INFINITY || x == f64::NEG_INFINITY {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the dedicated method instead: `x.is_infinite()` error: manually checking if a float is finite - --> tests/ui/manual_float_methods.rs:30:8 + --> tests/ui/manual_float_methods.rs:35:8 | LL | if x != f64::INFINITY && x != f64::NEG_INFINITY {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -88,7 +88,7 @@ LL + if !x.is_infinite() {} | error: manually checking if a float is infinite - --> tests/ui/manual_float_methods.rs:44:12 + --> tests/ui/manual_float_methods.rs:50:12 | LL | if x == f64::INFINITY || x == f64::NEG_INFINITY {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the dedicated method instead: `x.is_infinite()` diff --git a/tests/ui/manual_hash_one.fixed b/tests/ui/manual_hash_one.fixed index edfd9c4a47bb..e45e4bbc3ce7 100644 --- a/tests/ui/manual_hash_one.fixed +++ b/tests/ui/manual_hash_one.fixed @@ -7,18 +7,21 @@ fn returned(b: impl BuildHasher) -> u64 { b.hash_one(&true) + //~^ manual_hash_one } fn unsized_receiver(b: impl BuildHasher, s: &str) { let _ = b.hash_one(&s[4..10]); + //~^ manual_hash_one } fn owned_value(b: impl BuildHasher, v: Vec) -> Vec { let _ = b.hash_one(&v); + //~^ manual_hash_one v } @@ -86,4 +89,5 @@ fn msrv_1_71(b: impl BuildHasher, v: impl Hash) { let _ = b.hash_one(&v); + //~^ manual_hash_one } diff --git a/tests/ui/manual_hash_one.rs b/tests/ui/manual_hash_one.rs index ee61522853f0..c93e26c8f6bf 100644 --- a/tests/ui/manual_hash_one.rs +++ b/tests/ui/manual_hash_one.rs @@ -7,18 +7,21 @@ fn returned(b: impl BuildHasher) -> u64 { let mut hasher = b.build_hasher(); true.hash(&mut hasher); hasher.finish() + //~^ manual_hash_one } fn unsized_receiver(b: impl BuildHasher, s: &str) { let mut hasher = b.build_hasher(); s[4..10].hash(&mut hasher); let _ = hasher.finish(); + //~^ manual_hash_one } fn owned_value(b: impl BuildHasher, v: Vec) -> Vec { let mut hasher = b.build_hasher(); v.hash(&mut hasher); let _ = hasher.finish(); + //~^ manual_hash_one v } @@ -86,4 +89,5 @@ fn msrv_1_71(b: impl BuildHasher, v: impl Hash) { let mut hasher = b.build_hasher(); v.hash(&mut hasher); let _ = hasher.finish(); + //~^ manual_hash_one } diff --git a/tests/ui/manual_hash_one.stderr b/tests/ui/manual_hash_one.stderr index bcff36d9bafc..b0691e2d396c 100644 --- a/tests/ui/manual_hash_one.stderr +++ b/tests/ui/manual_hash_one.stderr @@ -14,7 +14,7 @@ LL ~ b.hash_one(&true) | error: manual implementation of `BuildHasher::hash_one` - --> tests/ui/manual_hash_one.rs:15:13 + --> tests/ui/manual_hash_one.rs:16:13 | LL | let _ = hasher.finish(); | ^^^^^^^^^^^^^^^ @@ -27,7 +27,7 @@ LL ~ let _ = b.hash_one(&s[4..10]); | error: manual implementation of `BuildHasher::hash_one` - --> tests/ui/manual_hash_one.rs:21:13 + --> tests/ui/manual_hash_one.rs:23:13 | LL | let _ = hasher.finish(); | ^^^^^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL ~ let _ = b.hash_one(&v); | error: manual implementation of `BuildHasher::hash_one` - --> tests/ui/manual_hash_one.rs:88:13 + --> tests/ui/manual_hash_one.rs:91:13 | LL | let _ = hasher.finish(); | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/manual_ignore_case_cmp.fixed b/tests/ui/manual_ignore_case_cmp.fixed index 53a124f59c8d..c1c929585cfd 100644 --- a/tests/ui/manual_ignore_case_cmp.fixed +++ b/tests/ui/manual_ignore_case_cmp.fixed @@ -7,24 +7,34 @@ fn main() {} fn variants(a: &str, b: &str) { if a.eq_ignore_ascii_case(b) { + //~^ manual_ignore_case_cmp return; } if a.eq_ignore_ascii_case(b) { + //~^ manual_ignore_case_cmp return; } let r = a.eq_ignore_ascii_case(b); + //~^ manual_ignore_case_cmp let r = r || a.eq_ignore_ascii_case(b); + //~^ manual_ignore_case_cmp r && a.eq_ignore_ascii_case(&b.to_uppercase()); + //~^ manual_ignore_case_cmp // != if !a.eq_ignore_ascii_case(b) { + //~^ manual_ignore_case_cmp return; } if !a.eq_ignore_ascii_case(b) { + //~^ manual_ignore_case_cmp return; } let r = !a.eq_ignore_ascii_case(b); + //~^ manual_ignore_case_cmp let r = r || !a.eq_ignore_ascii_case(b); + //~^ manual_ignore_case_cmp r && !a.eq_ignore_ascii_case(&b.to_uppercase()); + //~^ manual_ignore_case_cmp } fn unsupported(a: char, b: char) { @@ -36,72 +46,111 @@ fn unsupported(a: char, b: char) { fn char(a: char, b: char) { a.eq_ignore_ascii_case(&b); + //~^ manual_ignore_case_cmp a.to_ascii_lowercase() == *&b.to_ascii_lowercase(); *&a.to_ascii_lowercase() == b.to_ascii_lowercase(); a.eq_ignore_ascii_case(&'a'); + //~^ manual_ignore_case_cmp 'a'.eq_ignore_ascii_case(&b); + //~^ manual_ignore_case_cmp } fn u8(a: u8, b: u8) { a.eq_ignore_ascii_case(&b); + //~^ manual_ignore_case_cmp a.eq_ignore_ascii_case(&b'a'); + //~^ manual_ignore_case_cmp b'a'.eq_ignore_ascii_case(&b); + //~^ manual_ignore_case_cmp } fn ref_str(a: &str, b: &str) { a.eq_ignore_ascii_case(b); + //~^ manual_ignore_case_cmp a.to_uppercase().eq_ignore_ascii_case(b); + //~^ manual_ignore_case_cmp a.eq_ignore_ascii_case("a"); + //~^ manual_ignore_case_cmp "a".eq_ignore_ascii_case(b); + //~^ manual_ignore_case_cmp } fn ref_ref_str(a: &&str, b: &&str) { a.eq_ignore_ascii_case(b); + //~^ manual_ignore_case_cmp a.to_uppercase().eq_ignore_ascii_case(b); + //~^ manual_ignore_case_cmp a.eq_ignore_ascii_case("a"); + //~^ manual_ignore_case_cmp "a".eq_ignore_ascii_case(b); + //~^ manual_ignore_case_cmp } fn string(a: String, b: String) { a.eq_ignore_ascii_case(&b); + //~^ manual_ignore_case_cmp a.eq_ignore_ascii_case("a"); + //~^ manual_ignore_case_cmp "a".eq_ignore_ascii_case(&b); + //~^ manual_ignore_case_cmp &a.to_ascii_lowercase() == &b.to_ascii_lowercase(); &&a.to_ascii_lowercase() == &&b.to_ascii_lowercase(); a.eq_ignore_ascii_case("a"); + //~^ manual_ignore_case_cmp "a".eq_ignore_ascii_case(&b); + //~^ manual_ignore_case_cmp } fn ref_string(a: String, b: &String) { a.eq_ignore_ascii_case(b); + //~^ manual_ignore_case_cmp a.eq_ignore_ascii_case("a"); + //~^ manual_ignore_case_cmp "a".eq_ignore_ascii_case(b); + //~^ manual_ignore_case_cmp b.eq_ignore_ascii_case(&a); + //~^ manual_ignore_case_cmp b.eq_ignore_ascii_case("a"); + //~^ manual_ignore_case_cmp "a".eq_ignore_ascii_case(&a); + //~^ manual_ignore_case_cmp } fn string_ref_str(a: String, b: &str) { a.eq_ignore_ascii_case(b); + //~^ manual_ignore_case_cmp a.eq_ignore_ascii_case("a"); + //~^ manual_ignore_case_cmp "a".eq_ignore_ascii_case(b); + //~^ manual_ignore_case_cmp b.eq_ignore_ascii_case(&a); + //~^ manual_ignore_case_cmp b.eq_ignore_ascii_case("a"); + //~^ manual_ignore_case_cmp "a".eq_ignore_ascii_case(&a); + //~^ manual_ignore_case_cmp } fn ref_u8slice(a: &[u8], b: &[u8]) { a.eq_ignore_ascii_case(b); + //~^ manual_ignore_case_cmp } fn u8vec(a: Vec, b: Vec) { a.eq_ignore_ascii_case(&b); + //~^ manual_ignore_case_cmp } fn ref_u8vec(a: Vec, b: &Vec) { a.eq_ignore_ascii_case(b); + //~^ manual_ignore_case_cmp b.eq_ignore_ascii_case(&a); + //~^ manual_ignore_case_cmp } fn ref_osstr(a: &OsStr, b: &OsStr) { a.eq_ignore_ascii_case(b); + //~^ manual_ignore_case_cmp } fn osstring(a: OsString, b: OsString) { a.eq_ignore_ascii_case(b); + //~^ manual_ignore_case_cmp } fn ref_osstring(a: OsString, b: &OsString) { a.eq_ignore_ascii_case(b); + //~^ manual_ignore_case_cmp b.eq_ignore_ascii_case(a); + //~^ manual_ignore_case_cmp } diff --git a/tests/ui/manual_ignore_case_cmp.rs b/tests/ui/manual_ignore_case_cmp.rs index 2a4d84b30ace..ca401e595fe9 100644 --- a/tests/ui/manual_ignore_case_cmp.rs +++ b/tests/ui/manual_ignore_case_cmp.rs @@ -7,24 +7,34 @@ fn main() {} fn variants(a: &str, b: &str) { if a.to_ascii_lowercase() == b.to_ascii_lowercase() { + //~^ manual_ignore_case_cmp return; } if a.to_ascii_uppercase() == b.to_ascii_uppercase() { + //~^ manual_ignore_case_cmp return; } let r = a.to_ascii_lowercase() == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp let r = r || a.to_ascii_uppercase() == b.to_ascii_uppercase(); + //~^ manual_ignore_case_cmp r && a.to_ascii_lowercase() == b.to_uppercase().to_ascii_lowercase(); + //~^ manual_ignore_case_cmp // != if a.to_ascii_lowercase() != b.to_ascii_lowercase() { + //~^ manual_ignore_case_cmp return; } if a.to_ascii_uppercase() != b.to_ascii_uppercase() { + //~^ manual_ignore_case_cmp return; } let r = a.to_ascii_lowercase() != b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp let r = r || a.to_ascii_uppercase() != b.to_ascii_uppercase(); + //~^ manual_ignore_case_cmp r && a.to_ascii_lowercase() != b.to_uppercase().to_ascii_lowercase(); + //~^ manual_ignore_case_cmp } fn unsupported(a: char, b: char) { @@ -36,72 +46,111 @@ fn unsupported(a: char, b: char) { fn char(a: char, b: char) { a.to_ascii_lowercase() == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp a.to_ascii_lowercase() == *&b.to_ascii_lowercase(); *&a.to_ascii_lowercase() == b.to_ascii_lowercase(); a.to_ascii_lowercase() == 'a'; + //~^ manual_ignore_case_cmp 'a' == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp } fn u8(a: u8, b: u8) { a.to_ascii_lowercase() == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp a.to_ascii_lowercase() == b'a'; + //~^ manual_ignore_case_cmp b'a' == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp } fn ref_str(a: &str, b: &str) { a.to_ascii_lowercase() == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp a.to_uppercase().to_ascii_lowercase() == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp a.to_ascii_lowercase() == "a"; + //~^ manual_ignore_case_cmp "a" == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp } fn ref_ref_str(a: &&str, b: &&str) { a.to_ascii_lowercase() == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp a.to_uppercase().to_ascii_lowercase() == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp a.to_ascii_lowercase() == "a"; + //~^ manual_ignore_case_cmp "a" == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp } fn string(a: String, b: String) { a.to_ascii_lowercase() == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp a.to_ascii_lowercase() == "a"; + //~^ manual_ignore_case_cmp "a" == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp &a.to_ascii_lowercase() == &b.to_ascii_lowercase(); &&a.to_ascii_lowercase() == &&b.to_ascii_lowercase(); a.to_ascii_lowercase() == "a"; + //~^ manual_ignore_case_cmp "a" == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp } fn ref_string(a: String, b: &String) { a.to_ascii_lowercase() == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp a.to_ascii_lowercase() == "a"; + //~^ manual_ignore_case_cmp "a" == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp b.to_ascii_lowercase() == a.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp b.to_ascii_lowercase() == "a"; + //~^ manual_ignore_case_cmp "a" == a.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp } fn string_ref_str(a: String, b: &str) { a.to_ascii_lowercase() == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp a.to_ascii_lowercase() == "a"; + //~^ manual_ignore_case_cmp "a" == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp b.to_ascii_lowercase() == a.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp b.to_ascii_lowercase() == "a"; + //~^ manual_ignore_case_cmp "a" == a.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp } fn ref_u8slice(a: &[u8], b: &[u8]) { a.to_ascii_lowercase() == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp } fn u8vec(a: Vec, b: Vec) { a.to_ascii_lowercase() == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp } fn ref_u8vec(a: Vec, b: &Vec) { a.to_ascii_lowercase() == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp b.to_ascii_lowercase() == a.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp } fn ref_osstr(a: &OsStr, b: &OsStr) { a.to_ascii_lowercase() == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp } fn osstring(a: OsString, b: OsString) { a.to_ascii_lowercase() == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp } fn ref_osstring(a: OsString, b: &OsString) { a.to_ascii_lowercase() == b.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp b.to_ascii_lowercase() == a.to_ascii_lowercase(); + //~^ manual_ignore_case_cmp } diff --git a/tests/ui/manual_ignore_case_cmp.stderr b/tests/ui/manual_ignore_case_cmp.stderr index bc6393b66d5c..47378a65799f 100644 --- a/tests/ui/manual_ignore_case_cmp.stderr +++ b/tests/ui/manual_ignore_case_cmp.stderr @@ -16,7 +16,7 @@ LL + if a.eq_ignore_ascii_case(b) { | error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:12:8 + --> tests/ui/manual_ignore_case_cmp.rs:13:8 | LL | if a.to_ascii_uppercase() == b.to_ascii_uppercase() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL + if a.eq_ignore_ascii_case(b) { | error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:15:13 + --> tests/ui/manual_ignore_case_cmp.rs:17:13 | LL | let r = a.to_ascii_lowercase() == b.to_ascii_lowercase(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL + let r = a.eq_ignore_ascii_case(b); | error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:16:18 + --> tests/ui/manual_ignore_case_cmp.rs:19:18 | LL | let r = r || a.to_ascii_uppercase() == b.to_ascii_uppercase(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,7 +52,7 @@ LL + let r = r || a.eq_ignore_ascii_case(b); | error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:17:10 + --> tests/ui/manual_ignore_case_cmp.rs:21:10 | LL | r && a.to_ascii_lowercase() == b.to_uppercase().to_ascii_lowercase(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL + r && a.eq_ignore_ascii_case(&b.to_uppercase()); | error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:19:8 + --> tests/ui/manual_ignore_case_cmp.rs:24:8 | LL | if a.to_ascii_lowercase() != b.to_ascii_lowercase() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -76,7 +76,7 @@ LL + if !a.eq_ignore_ascii_case(b) { | error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:22:8 + --> tests/ui/manual_ignore_case_cmp.rs:28:8 | LL | if a.to_ascii_uppercase() != b.to_ascii_uppercase() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -88,7 +88,7 @@ LL + if !a.eq_ignore_ascii_case(b) { | error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:25:13 + --> tests/ui/manual_ignore_case_cmp.rs:32:13 | LL | let r = a.to_ascii_lowercase() != b.to_ascii_lowercase(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -100,7 +100,7 @@ LL + let r = !a.eq_ignore_ascii_case(b); | error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:26:18 + --> tests/ui/manual_ignore_case_cmp.rs:34:18 | LL | let r = r || a.to_ascii_uppercase() != b.to_ascii_uppercase(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -112,7 +112,7 @@ LL + let r = r || !a.eq_ignore_ascii_case(b); | error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:27:10 + --> tests/ui/manual_ignore_case_cmp.rs:36:10 | LL | r && a.to_ascii_lowercase() != b.to_uppercase().to_ascii_lowercase(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -124,7 +124,7 @@ LL + r && !a.eq_ignore_ascii_case(&b.to_uppercase()); | error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:38:5 + --> tests/ui/manual_ignore_case_cmp.rs:48:5 | LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -136,7 +136,7 @@ LL + a.eq_ignore_ascii_case(&b); | error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:41:5 + --> tests/ui/manual_ignore_case_cmp.rs:52:5 | LL | a.to_ascii_lowercase() == 'a'; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -148,7 +148,7 @@ LL + a.eq_ignore_ascii_case(&'a'); | error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:42:5 + --> tests/ui/manual_ignore_case_cmp.rs:54:5 | LL | 'a' == b.to_ascii_lowercase(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -160,7 +160,7 @@ LL + 'a'.eq_ignore_ascii_case(&b); | error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:45:5 + --> tests/ui/manual_ignore_case_cmp.rs:58:5 | LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -172,7 +172,7 @@ LL + a.eq_ignore_ascii_case(&b); | error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:46:5 + --> tests/ui/manual_ignore_case_cmp.rs:60:5 | LL | a.to_ascii_lowercase() == b'a'; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -184,7 +184,7 @@ LL + a.eq_ignore_ascii_case(&b'a'); | error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:47:5 + --> tests/ui/manual_ignore_case_cmp.rs:62:5 | LL | b'a' == b.to_ascii_lowercase(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -196,7 +196,7 @@ LL + b'a'.eq_ignore_ascii_case(&b); | error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:50:5 + --> tests/ui/manual_ignore_case_cmp.rs:66:5 | LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -207,164 +207,20 @@ LL - a.to_ascii_lowercase() == b.to_ascii_lowercase(); LL + a.eq_ignore_ascii_case(b); | -error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:51:5 - | -LL | a.to_uppercase().to_ascii_lowercase() == b.to_ascii_lowercase(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using `.eq_ignore_ascii_case()` instead - | -LL - a.to_uppercase().to_ascii_lowercase() == b.to_ascii_lowercase(); -LL + a.to_uppercase().eq_ignore_ascii_case(b); - | - -error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:52:5 - | -LL | a.to_ascii_lowercase() == "a"; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using `.eq_ignore_ascii_case()` instead - | -LL - a.to_ascii_lowercase() == "a"; -LL + a.eq_ignore_ascii_case("a"); - | - -error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:53:5 - | -LL | "a" == b.to_ascii_lowercase(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using `.eq_ignore_ascii_case()` instead - | -LL - "a" == b.to_ascii_lowercase(); -LL + "a".eq_ignore_ascii_case(b); - | - -error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:56:5 - | -LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using `.eq_ignore_ascii_case()` instead - | -LL - a.to_ascii_lowercase() == b.to_ascii_lowercase(); -LL + a.eq_ignore_ascii_case(b); - | - -error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:57:5 - | -LL | a.to_uppercase().to_ascii_lowercase() == b.to_ascii_lowercase(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using `.eq_ignore_ascii_case()` instead - | -LL - a.to_uppercase().to_ascii_lowercase() == b.to_ascii_lowercase(); -LL + a.to_uppercase().eq_ignore_ascii_case(b); - | - -error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:58:5 - | -LL | a.to_ascii_lowercase() == "a"; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using `.eq_ignore_ascii_case()` instead - | -LL - a.to_ascii_lowercase() == "a"; -LL + a.eq_ignore_ascii_case("a"); - | - -error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:59:5 - | -LL | "a" == b.to_ascii_lowercase(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using `.eq_ignore_ascii_case()` instead - | -LL - "a" == b.to_ascii_lowercase(); -LL + "a".eq_ignore_ascii_case(b); - | - -error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:62:5 - | -LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using `.eq_ignore_ascii_case()` instead - | -LL - a.to_ascii_lowercase() == b.to_ascii_lowercase(); -LL + a.eq_ignore_ascii_case(&b); - | - -error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:63:5 - | -LL | a.to_ascii_lowercase() == "a"; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using `.eq_ignore_ascii_case()` instead - | -LL - a.to_ascii_lowercase() == "a"; -LL + a.eq_ignore_ascii_case("a"); - | - -error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:64:5 - | -LL | "a" == b.to_ascii_lowercase(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using `.eq_ignore_ascii_case()` instead - | -LL - "a" == b.to_ascii_lowercase(); -LL + "a".eq_ignore_ascii_case(&b); - | - -error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:67:5 - | -LL | a.to_ascii_lowercase() == "a"; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using `.eq_ignore_ascii_case()` instead - | -LL - a.to_ascii_lowercase() == "a"; -LL + a.eq_ignore_ascii_case("a"); - | - error: manual case-insensitive ASCII comparison --> tests/ui/manual_ignore_case_cmp.rs:68:5 | -LL | "a" == b.to_ascii_lowercase(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | a.to_uppercase().to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider using `.eq_ignore_ascii_case()` instead | -LL - "a" == b.to_ascii_lowercase(); -LL + "a".eq_ignore_ascii_case(&b); +LL - a.to_uppercase().to_ascii_lowercase() == b.to_ascii_lowercase(); +LL + a.to_uppercase().eq_ignore_ascii_case(b); | error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:71:5 - | -LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using `.eq_ignore_ascii_case()` instead - | -LL - a.to_ascii_lowercase() == b.to_ascii_lowercase(); -LL + a.eq_ignore_ascii_case(b); - | - -error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:72:5 + --> tests/ui/manual_ignore_case_cmp.rs:70:5 | LL | a.to_ascii_lowercase() == "a"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -376,7 +232,7 @@ LL + a.eq_ignore_ascii_case("a"); | error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:73:5 + --> tests/ui/manual_ignore_case_cmp.rs:72:5 | LL | "a" == b.to_ascii_lowercase(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -387,45 +243,9 @@ LL - "a" == b.to_ascii_lowercase(); LL + "a".eq_ignore_ascii_case(b); | -error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:75:5 - | -LL | b.to_ascii_lowercase() == a.to_ascii_lowercase(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using `.eq_ignore_ascii_case()` instead - | -LL - b.to_ascii_lowercase() == a.to_ascii_lowercase(); -LL + b.eq_ignore_ascii_case(&a); - | - error: manual case-insensitive ASCII comparison --> tests/ui/manual_ignore_case_cmp.rs:76:5 | -LL | b.to_ascii_lowercase() == "a"; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using `.eq_ignore_ascii_case()` instead - | -LL - b.to_ascii_lowercase() == "a"; -LL + b.eq_ignore_ascii_case("a"); - | - -error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:77:5 - | -LL | "a" == a.to_ascii_lowercase(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using `.eq_ignore_ascii_case()` instead - | -LL - "a" == a.to_ascii_lowercase(); -LL + "a".eq_ignore_ascii_case(&a); - | - -error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:80:5 - | LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | @@ -436,7 +256,19 @@ LL + a.eq_ignore_ascii_case(b); | error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:81:5 + --> tests/ui/manual_ignore_case_cmp.rs:78:5 + | +LL | a.to_uppercase().to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL - a.to_uppercase().to_ascii_lowercase() == b.to_ascii_lowercase(); +LL + a.to_uppercase().eq_ignore_ascii_case(b); + | + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:80:5 | LL | a.to_ascii_lowercase() == "a"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -459,57 +291,9 @@ LL - "a" == b.to_ascii_lowercase(); LL + "a".eq_ignore_ascii_case(b); | -error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:84:5 - | -LL | b.to_ascii_lowercase() == a.to_ascii_lowercase(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using `.eq_ignore_ascii_case()` instead - | -LL - b.to_ascii_lowercase() == a.to_ascii_lowercase(); -LL + b.eq_ignore_ascii_case(&a); - | - -error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:85:5 - | -LL | b.to_ascii_lowercase() == "a"; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using `.eq_ignore_ascii_case()` instead - | -LL - b.to_ascii_lowercase() == "a"; -LL + b.eq_ignore_ascii_case("a"); - | - error: manual case-insensitive ASCII comparison --> tests/ui/manual_ignore_case_cmp.rs:86:5 | -LL | "a" == a.to_ascii_lowercase(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using `.eq_ignore_ascii_case()` instead - | -LL - "a" == a.to_ascii_lowercase(); -LL + "a".eq_ignore_ascii_case(&a); - | - -error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:89:5 - | -LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using `.eq_ignore_ascii_case()` instead - | -LL - a.to_ascii_lowercase() == b.to_ascii_lowercase(); -LL + a.eq_ignore_ascii_case(b); - | - -error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:92:5 - | LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | @@ -520,31 +304,55 @@ LL + a.eq_ignore_ascii_case(&b); | error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:95:5 + --> tests/ui/manual_ignore_case_cmp.rs:88:5 | -LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | a.to_ascii_lowercase() == "a"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider using `.eq_ignore_ascii_case()` instead | -LL - a.to_ascii_lowercase() == b.to_ascii_lowercase(); -LL + a.eq_ignore_ascii_case(b); +LL - a.to_ascii_lowercase() == "a"; +LL + a.eq_ignore_ascii_case("a"); + | + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:90:5 + | +LL | "a" == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL - "a" == b.to_ascii_lowercase(); +LL + "a".eq_ignore_ascii_case(&b); + | + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:94:5 + | +LL | a.to_ascii_lowercase() == "a"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL - a.to_ascii_lowercase() == "a"; +LL + a.eq_ignore_ascii_case("a"); | error: manual case-insensitive ASCII comparison --> tests/ui/manual_ignore_case_cmp.rs:96:5 | -LL | b.to_ascii_lowercase() == a.to_ascii_lowercase(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | "a" == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider using `.eq_ignore_ascii_case()` instead | -LL - b.to_ascii_lowercase() == a.to_ascii_lowercase(); -LL + b.eq_ignore_ascii_case(&a); +LL - "a" == b.to_ascii_lowercase(); +LL + "a".eq_ignore_ascii_case(&b); | error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:99:5 + --> tests/ui/manual_ignore_case_cmp.rs:100:5 | LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -558,17 +366,65 @@ LL + a.eq_ignore_ascii_case(b); error: manual case-insensitive ASCII comparison --> tests/ui/manual_ignore_case_cmp.rs:102:5 | -LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); +LL | a.to_ascii_lowercase() == "a"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL - a.to_ascii_lowercase() == "a"; +LL + a.eq_ignore_ascii_case("a"); + | + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:104:5 + | +LL | "a" == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL - "a" == b.to_ascii_lowercase(); +LL + "a".eq_ignore_ascii_case(b); + | + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:107:5 + | +LL | b.to_ascii_lowercase() == a.to_ascii_lowercase(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider using `.eq_ignore_ascii_case()` instead | -LL - a.to_ascii_lowercase() == b.to_ascii_lowercase(); -LL + a.eq_ignore_ascii_case(b); +LL - b.to_ascii_lowercase() == a.to_ascii_lowercase(); +LL + b.eq_ignore_ascii_case(&a); | error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:105:5 + --> tests/ui/manual_ignore_case_cmp.rs:109:5 + | +LL | b.to_ascii_lowercase() == "a"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL - b.to_ascii_lowercase() == "a"; +LL + b.eq_ignore_ascii_case("a"); + | + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:111:5 + | +LL | "a" == a.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL - "a" == a.to_ascii_lowercase(); +LL + "a".eq_ignore_ascii_case(&a); + | + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:115:5 | LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -580,7 +436,151 @@ LL + a.eq_ignore_ascii_case(b); | error: manual case-insensitive ASCII comparison - --> tests/ui/manual_ignore_case_cmp.rs:106:5 + --> tests/ui/manual_ignore_case_cmp.rs:117:5 + | +LL | a.to_ascii_lowercase() == "a"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL - a.to_ascii_lowercase() == "a"; +LL + a.eq_ignore_ascii_case("a"); + | + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:119:5 + | +LL | "a" == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL - "a" == b.to_ascii_lowercase(); +LL + "a".eq_ignore_ascii_case(b); + | + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:122:5 + | +LL | b.to_ascii_lowercase() == a.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL - b.to_ascii_lowercase() == a.to_ascii_lowercase(); +LL + b.eq_ignore_ascii_case(&a); + | + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:124:5 + | +LL | b.to_ascii_lowercase() == "a"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL - b.to_ascii_lowercase() == "a"; +LL + b.eq_ignore_ascii_case("a"); + | + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:126:5 + | +LL | "a" == a.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL - "a" == a.to_ascii_lowercase(); +LL + "a".eq_ignore_ascii_case(&a); + | + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:130:5 + | +LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL - a.to_ascii_lowercase() == b.to_ascii_lowercase(); +LL + a.eq_ignore_ascii_case(b); + | + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:134:5 + | +LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL - a.to_ascii_lowercase() == b.to_ascii_lowercase(); +LL + a.eq_ignore_ascii_case(&b); + | + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:138:5 + | +LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL - a.to_ascii_lowercase() == b.to_ascii_lowercase(); +LL + a.eq_ignore_ascii_case(b); + | + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:140:5 + | +LL | b.to_ascii_lowercase() == a.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL - b.to_ascii_lowercase() == a.to_ascii_lowercase(); +LL + b.eq_ignore_ascii_case(&a); + | + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:144:5 + | +LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL - a.to_ascii_lowercase() == b.to_ascii_lowercase(); +LL + a.eq_ignore_ascii_case(b); + | + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:148:5 + | +LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL - a.to_ascii_lowercase() == b.to_ascii_lowercase(); +LL + a.eq_ignore_ascii_case(b); + | + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:152:5 + | +LL | a.to_ascii_lowercase() == b.to_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `.eq_ignore_ascii_case()` instead + | +LL - a.to_ascii_lowercase() == b.to_ascii_lowercase(); +LL + a.eq_ignore_ascii_case(b); + | + +error: manual case-insensitive ASCII comparison + --> tests/ui/manual_ignore_case_cmp.rs:154:5 | LL | b.to_ascii_lowercase() == a.to_ascii_lowercase(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/manual_inspect.fixed b/tests/ui/manual_inspect.fixed index 0e1b8fe3edb5..44f15d61f856 100644 --- a/tests/ui/manual_inspect.fixed +++ b/tests/ui/manual_inspect.fixed @@ -3,24 +3,29 @@ fn main() { let _ = Some(0).inspect(|&x| { + //~^ manual_inspect println!("{}", x); }); let _ = Some(0).inspect(|&x| { + //~^ manual_inspect println!("{x}"); }); let _ = Some(0).inspect(|&x| { + //~^ manual_inspect println!("{}", x * 5 + 1); }); let _ = Some(0).inspect(|&x| { + //~^ manual_inspect if x == 0 { panic!(); } }); let _ = Some(0).inspect(|&x| { + //~^ manual_inspect if &x == &0 { let _y = x; panic!(); @@ -71,6 +76,7 @@ fn main() { } let _ = Some((String::new(), 0u32)).inspect(|x| { + //~^ manual_inspect if x.1 == 0 { let _x = x.1; panic!(); @@ -96,6 +102,7 @@ fn main() { }); let _ = Some(String::new()).inspect(|x| { + //~^ manual_inspect if x.is_empty() { let _ = || { let _x = x; @@ -106,6 +113,7 @@ fn main() { }); let _ = Some(0).inspect(|&x| { + //~^ manual_inspect if x == 0 { let _ = || { let _x = x; @@ -120,6 +128,7 @@ fn main() { struct Cell2(core::cell::Cell); let _ = Some(Cell2(Cell::new(0u32))).inspect(|x| { + //~^ manual_inspect x.0.set(1); }); @@ -135,16 +144,20 @@ fn main() { } let _: Result<_, ()> = Ok(0).inspect(|&x| { + //~^ manual_inspect println!("{}", x); }); let _: Result<(), _> = Err(0).inspect_err(|&x| { + //~^ manual_inspect println!("{}", x); }); let _ = [0] + //~^ suspicious_map .into_iter() .inspect(|&x| { + //~^ manual_inspect println!("{}", x); }) .count(); diff --git a/tests/ui/manual_inspect.rs b/tests/ui/manual_inspect.rs index 94cdfe391400..d34f2abce6ae 100644 --- a/tests/ui/manual_inspect.rs +++ b/tests/ui/manual_inspect.rs @@ -3,21 +3,25 @@ fn main() { let _ = Some(0).map(|x| { + //~^ manual_inspect println!("{}", x); x }); let _ = Some(0).map(|x| { + //~^ manual_inspect println!("{x}"); x }); let _ = Some(0).map(|x| { + //~^ manual_inspect println!("{}", x * 5 + 1); x }); let _ = Some(0).map(|x| { + //~^ manual_inspect if x == 0 { panic!(); } @@ -25,6 +29,7 @@ fn main() { }); let _ = Some(0).map(|x| { + //~^ manual_inspect if &x == &0 { let _y = x; panic!(); @@ -76,6 +81,7 @@ fn main() { } let _ = Some((String::new(), 0u32)).map(|x| { + //~^ manual_inspect if x.1 == 0 { let _x = x.1; panic!(); @@ -102,6 +108,7 @@ fn main() { }); let _ = Some(String::new()).map(|x| { + //~^ manual_inspect if x.is_empty() { let _ = || { let _x = &x; @@ -113,6 +120,7 @@ fn main() { }); let _ = Some(0).map(|x| { + //~^ manual_inspect if x == 0 { let _ = || { let _x = x; @@ -128,6 +136,7 @@ fn main() { struct Cell2(core::cell::Cell); let _ = Some(Cell2(Cell::new(0u32))).map(|x| { + //~^ manual_inspect x.0.set(1); x }); @@ -144,18 +153,22 @@ fn main() { } let _: Result<_, ()> = Ok(0).map(|x| { + //~^ manual_inspect println!("{}", x); x }); let _: Result<(), _> = Err(0).map_err(|x| { + //~^ manual_inspect println!("{}", x); x }); let _ = [0] + //~^ suspicious_map .into_iter() .map(|x| { + //~^ manual_inspect println!("{}", x); x }) diff --git a/tests/ui/manual_inspect.stderr b/tests/ui/manual_inspect.stderr index 0559b3bd6611..510325d2baaa 100644 --- a/tests/ui/manual_inspect.stderr +++ b/tests/ui/manual_inspect.stderr @@ -9,11 +9,12 @@ LL | let _ = Some(0).map(|x| { help: try | LL ~ let _ = Some(0).inspect(|&x| { +LL | LL ~ println!("{}", x); | error: using `map` over `inspect` - --> tests/ui/manual_inspect.rs:10:21 + --> tests/ui/manual_inspect.rs:11:21 | LL | let _ = Some(0).map(|x| { | ^^^ @@ -21,11 +22,12 @@ LL | let _ = Some(0).map(|x| { help: try | LL ~ let _ = Some(0).inspect(|&x| { +LL | LL ~ println!("{x}"); | error: using `map` over `inspect` - --> tests/ui/manual_inspect.rs:15:21 + --> tests/ui/manual_inspect.rs:17:21 | LL | let _ = Some(0).map(|x| { | ^^^ @@ -33,11 +35,12 @@ LL | let _ = Some(0).map(|x| { help: try | LL ~ let _ = Some(0).inspect(|&x| { +LL | LL ~ println!("{}", x * 5 + 1); | error: using `map` over `inspect` - --> tests/ui/manual_inspect.rs:20:21 + --> tests/ui/manual_inspect.rs:23:21 | LL | let _ = Some(0).map(|x| { | ^^^ @@ -45,13 +48,14 @@ LL | let _ = Some(0).map(|x| { help: try | LL ~ let _ = Some(0).inspect(|&x| { +LL | LL | if x == 0 { LL | panic!(); LL ~ } | error: using `map` over `inspect` - --> tests/ui/manual_inspect.rs:27:21 + --> tests/ui/manual_inspect.rs:31:21 | LL | let _ = Some(0).map(|x| { | ^^^ @@ -59,14 +63,14 @@ LL | let _ = Some(0).map(|x| { help: try | LL ~ let _ = Some(0).inspect(|&x| { -LL | if &x == &0 { -LL | let _y = x; +LL | +... LL | panic!(); LL ~ } | error: using `map` over `inspect` - --> tests/ui/manual_inspect.rs:78:41 + --> tests/ui/manual_inspect.rs:83:41 | LL | let _ = Some((String::new(), 0u32)).map(|x| { | ^^^ @@ -74,14 +78,14 @@ LL | let _ = Some((String::new(), 0u32)).map(|x| { help: try | LL ~ let _ = Some((String::new(), 0u32)).inspect(|x| { -LL | if x.1 == 0 { -LL | let _x = x.1; +LL | +... LL | panic!(); LL ~ } | error: using `map` over `inspect` - --> tests/ui/manual_inspect.rs:104:33 + --> tests/ui/manual_inspect.rs:110:33 | LL | let _ = Some(String::new()).map(|x| { | ^^^ @@ -89,6 +93,7 @@ LL | let _ = Some(String::new()).map(|x| { help: try | LL ~ let _ = Some(String::new()).inspect(|x| { +LL | LL | if x.is_empty() { LL | let _ = || { LL ~ let _x = x; @@ -99,7 +104,7 @@ LL ~ println!("test"); | error: using `map` over `inspect` - --> tests/ui/manual_inspect.rs:115:21 + --> tests/ui/manual_inspect.rs:122:21 | LL | let _ = Some(0).map(|x| { | ^^^ @@ -107,14 +112,14 @@ LL | let _ = Some(0).map(|x| { help: try | LL ~ let _ = Some(0).inspect(|&x| { -LL | if x == 0 { +LL | ... LL | panic!(); LL ~ } | error: using `map` over `inspect` - --> tests/ui/manual_inspect.rs:130:46 + --> tests/ui/manual_inspect.rs:138:46 | LL | let _ = Some(Cell2(Cell::new(0u32))).map(|x| { | ^^^ @@ -122,11 +127,12 @@ LL | let _ = Some(Cell2(Cell::new(0u32))).map(|x| { help: try | LL ~ let _ = Some(Cell2(Cell::new(0u32))).inspect(|x| { +LL | LL ~ x.0.set(1); | error: using `map` over `inspect` - --> tests/ui/manual_inspect.rs:146:34 + --> tests/ui/manual_inspect.rs:155:34 | LL | let _: Result<_, ()> = Ok(0).map(|x| { | ^^^ @@ -134,11 +140,12 @@ LL | let _: Result<_, ()> = Ok(0).map(|x| { help: try | LL ~ let _: Result<_, ()> = Ok(0).inspect(|&x| { +LL | LL ~ println!("{}", x); | error: using `map_err` over `inspect_err` - --> tests/ui/manual_inspect.rs:151:35 + --> tests/ui/manual_inspect.rs:161:35 | LL | let _: Result<(), _> = Err(0).map_err(|x| { | ^^^^^^^ @@ -146,18 +153,19 @@ LL | let _: Result<(), _> = Err(0).map_err(|x| { help: try | LL ~ let _: Result<(), _> = Err(0).inspect_err(|&x| { +LL | LL ~ println!("{}", x); | error: this call to `map()` won't have an effect on the call to `count()` - --> tests/ui/manual_inspect.rs:156:13 + --> tests/ui/manual_inspect.rs:167:13 | LL | let _ = [0] | _____________^ +LL | | LL | | .into_iter() LL | | .map(|x| { -LL | | println!("{}", x); -LL | | x +... | LL | | }) LL | | .count(); | |________________^ @@ -167,7 +175,7 @@ LL | | .count(); = help: to override `-D warnings` add `#[allow(clippy::suspicious_map)]` error: using `map` over `inspect` - --> tests/ui/manual_inspect.rs:158:10 + --> tests/ui/manual_inspect.rs:170:10 | LL | .map(|x| { | ^^^ @@ -175,6 +183,7 @@ LL | .map(|x| { help: try | LL ~ .inspect(|&x| { +LL | LL ~ println!("{}", x); | diff --git a/tests/ui/manual_instant_elapsed.fixed b/tests/ui/manual_instant_elapsed.fixed index 1811337652dd..187802bb76c9 100644 --- a/tests/ui/manual_instant_elapsed.fixed +++ b/tests/ui/manual_instant_elapsed.fixed @@ -15,6 +15,7 @@ fn main() { } let duration = prev_instant.elapsed(); + //~^ manual_instant_elapsed // don't catch let duration = prev_instant.elapsed(); @@ -24,4 +25,6 @@ fn main() { let ref_to_instant = &Instant::now(); (*ref_to_instant).elapsed(); // to ensure parens are added correctly + // + //~^^ manual_instant_elapsed } diff --git a/tests/ui/manual_instant_elapsed.rs b/tests/ui/manual_instant_elapsed.rs index fedca38b158a..61e14e5a3d9d 100644 --- a/tests/ui/manual_instant_elapsed.rs +++ b/tests/ui/manual_instant_elapsed.rs @@ -15,6 +15,7 @@ fn main() { } let duration = Instant::now() - prev_instant; + //~^ manual_instant_elapsed // don't catch let duration = prev_instant.elapsed(); @@ -24,4 +25,6 @@ fn main() { let ref_to_instant = &Instant::now(); Instant::now() - *ref_to_instant; // to ensure parens are added correctly + // + //~^^ manual_instant_elapsed } diff --git a/tests/ui/manual_instant_elapsed.stderr b/tests/ui/manual_instant_elapsed.stderr index e8ffeb5f8ca3..e84f3126f707 100644 --- a/tests/ui/manual_instant_elapsed.stderr +++ b/tests/ui/manual_instant_elapsed.stderr @@ -8,7 +8,7 @@ LL | let duration = Instant::now() - prev_instant; = help: to override `-D warnings` add `#[allow(clippy::manual_instant_elapsed)]` error: manual implementation of `Instant::elapsed` - --> tests/ui/manual_instant_elapsed.rs:26:5 + --> tests/ui/manual_instant_elapsed.rs:27:5 | LL | Instant::now() - *ref_to_instant; // to ensure parens are added correctly | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(*ref_to_instant).elapsed()` diff --git a/tests/ui/manual_is_ascii_check.fixed b/tests/ui/manual_is_ascii_check.fixed index 179149f697db..7b0d19068346 100644 --- a/tests/ui/manual_is_ascii_check.fixed +++ b/tests/ui/manual_is_ascii_check.fixed @@ -3,29 +3,45 @@ fn main() { assert!('x'.is_ascii_lowercase()); + //~^ manual_is_ascii_check assert!('X'.is_ascii_uppercase()); + //~^ manual_is_ascii_check assert!(b'x'.is_ascii_lowercase()); + //~^ manual_is_ascii_check assert!(b'X'.is_ascii_uppercase()); + //~^ manual_is_ascii_check let num = '2'; assert!(num.is_ascii_digit()); + //~^ manual_is_ascii_check assert!(b'1'.is_ascii_digit()); + //~^ manual_is_ascii_check assert!('x'.is_ascii_alphabetic()); + //~^ manual_is_ascii_check assert!(matches!('x', 'A'..='Z' | 'a'..='z' | '_')); b'0'.is_ascii_digit(); + //~^ manual_is_ascii_check b'a'.is_ascii_lowercase(); + //~^ manual_is_ascii_check b'A'.is_ascii_uppercase(); + //~^ manual_is_ascii_check '0'.is_ascii_digit(); + //~^ manual_is_ascii_check 'a'.is_ascii_lowercase(); + //~^ manual_is_ascii_check 'A'.is_ascii_uppercase(); + //~^ manual_is_ascii_check let cool_letter = &'g'; cool_letter.is_ascii_digit(); + //~^ manual_is_ascii_check cool_letter.is_ascii_lowercase(); + //~^ manual_is_ascii_check cool_letter.is_ascii_uppercase(); + //~^ manual_is_ascii_check } #[clippy::msrv = "1.23"] @@ -39,9 +55,13 @@ fn msrv_1_23() { #[clippy::msrv = "1.24"] fn msrv_1_24() { assert!(b'1'.is_ascii_digit()); + //~^ manual_is_ascii_check assert!('X'.is_ascii_uppercase()); + //~^ manual_is_ascii_check assert!('x'.is_ascii_alphabetic()); + //~^ manual_is_ascii_check assert!('x'.is_ascii_hexdigit()); + //~^ manual_is_ascii_check } #[clippy::msrv = "1.46"] @@ -53,14 +73,18 @@ fn msrv_1_46() { #[clippy::msrv = "1.47"] fn msrv_1_47() { const FOO: bool = 'x'.is_ascii_digit(); + //~^ manual_is_ascii_check const BAR: bool = 'x'.is_ascii_hexdigit(); + //~^ manual_is_ascii_check } #[allow(clippy::deref_addrof, clippy::needless_borrow)] fn with_refs() { let cool_letter = &&'g'; cool_letter.is_ascii_digit(); + //~^ manual_is_ascii_check cool_letter.is_ascii_lowercase(); + //~^ manual_is_ascii_check } fn generics() { @@ -79,11 +103,16 @@ fn generics() { { } take_while(|c: char| c.is_ascii_uppercase()); + //~^ manual_is_ascii_check take_while(|c: u8| c.is_ascii_uppercase()); + //~^ manual_is_ascii_check take_while(|c: char| c.is_ascii_uppercase()); + //~^ manual_is_ascii_check } fn adds_type_reference() { let digits: Vec<&char> = ['1', 'A'].iter().take_while(|c: &&char| c.is_ascii_digit()).collect(); + //~^ manual_is_ascii_check let digits: Vec<&mut char> = ['1', 'A'].iter_mut().take_while(|c: &&mut char| c.is_ascii_digit()).collect(); + //~^ manual_is_ascii_check } diff --git a/tests/ui/manual_is_ascii_check.rs b/tests/ui/manual_is_ascii_check.rs index 74f35ce94e84..e4f7fe9f5838 100644 --- a/tests/ui/manual_is_ascii_check.rs +++ b/tests/ui/manual_is_ascii_check.rs @@ -3,29 +3,45 @@ fn main() { assert!(matches!('x', 'a'..='z')); + //~^ manual_is_ascii_check assert!(matches!('X', 'A'..='Z')); + //~^ manual_is_ascii_check assert!(matches!(b'x', b'a'..=b'z')); + //~^ manual_is_ascii_check assert!(matches!(b'X', b'A'..=b'Z')); + //~^ manual_is_ascii_check let num = '2'; assert!(matches!(num, '0'..='9')); + //~^ manual_is_ascii_check assert!(matches!(b'1', b'0'..=b'9')); + //~^ manual_is_ascii_check assert!(matches!('x', 'A'..='Z' | 'a'..='z')); + //~^ manual_is_ascii_check assert!(matches!('x', 'A'..='Z' | 'a'..='z' | '_')); (b'0'..=b'9').contains(&b'0'); + //~^ manual_is_ascii_check (b'a'..=b'z').contains(&b'a'); + //~^ manual_is_ascii_check (b'A'..=b'Z').contains(&b'A'); + //~^ manual_is_ascii_check ('0'..='9').contains(&'0'); + //~^ manual_is_ascii_check ('a'..='z').contains(&'a'); + //~^ manual_is_ascii_check ('A'..='Z').contains(&'A'); + //~^ manual_is_ascii_check let cool_letter = &'g'; ('0'..='9').contains(cool_letter); + //~^ manual_is_ascii_check ('a'..='z').contains(cool_letter); + //~^ manual_is_ascii_check ('A'..='Z').contains(cool_letter); + //~^ manual_is_ascii_check } #[clippy::msrv = "1.23"] @@ -39,9 +55,13 @@ fn msrv_1_23() { #[clippy::msrv = "1.24"] fn msrv_1_24() { assert!(matches!(b'1', b'0'..=b'9')); + //~^ manual_is_ascii_check assert!(matches!('X', 'A'..='Z')); + //~^ manual_is_ascii_check assert!(matches!('x', 'A'..='Z' | 'a'..='z')); + //~^ manual_is_ascii_check assert!(matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F')); + //~^ manual_is_ascii_check } #[clippy::msrv = "1.46"] @@ -53,14 +73,18 @@ fn msrv_1_46() { #[clippy::msrv = "1.47"] fn msrv_1_47() { const FOO: bool = matches!('x', '0'..='9'); + //~^ manual_is_ascii_check const BAR: bool = matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F'); + //~^ manual_is_ascii_check } #[allow(clippy::deref_addrof, clippy::needless_borrow)] fn with_refs() { let cool_letter = &&'g'; ('0'..='9').contains(&&cool_letter); + //~^ manual_is_ascii_check ('a'..='z').contains(*cool_letter); + //~^ manual_is_ascii_check } fn generics() { @@ -79,11 +103,16 @@ fn generics() { { } take_while(|c| ('A'..='Z').contains(&c)); + //~^ manual_is_ascii_check take_while(|c| (b'A'..=b'Z').contains(&c)); + //~^ manual_is_ascii_check take_while(|c: char| ('A'..='Z').contains(&c)); + //~^ manual_is_ascii_check } fn adds_type_reference() { let digits: Vec<&char> = ['1', 'A'].iter().take_while(|c| ('0'..='9').contains(c)).collect(); + //~^ manual_is_ascii_check let digits: Vec<&mut char> = ['1', 'A'].iter_mut().take_while(|c| ('0'..='9').contains(c)).collect(); + //~^ manual_is_ascii_check } diff --git a/tests/ui/manual_is_ascii_check.stderr b/tests/ui/manual_is_ascii_check.stderr index 7b3f0c938b0d..9fd7f457b420 100644 --- a/tests/ui/manual_is_ascii_check.stderr +++ b/tests/ui/manual_is_ascii_check.stderr @@ -8,145 +8,145 @@ LL | assert!(matches!('x', 'a'..='z')); = help: to override `-D warnings` add `#[allow(clippy::manual_is_ascii_check)]` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:6:13 + --> tests/ui/manual_is_ascii_check.rs:7:13 | LL | assert!(matches!('X', 'A'..='Z')); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'X'.is_ascii_uppercase()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:7:13 + --> tests/ui/manual_is_ascii_check.rs:9:13 | LL | assert!(matches!(b'x', b'a'..=b'z')); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'x'.is_ascii_lowercase()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:8:13 + --> tests/ui/manual_is_ascii_check.rs:11:13 | LL | assert!(matches!(b'X', b'A'..=b'Z')); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'X'.is_ascii_uppercase()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:11:13 + --> tests/ui/manual_is_ascii_check.rs:15:13 | LL | assert!(matches!(num, '0'..='9')); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.is_ascii_digit()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:12:13 + --> tests/ui/manual_is_ascii_check.rs:17:13 | LL | assert!(matches!(b'1', b'0'..=b'9')); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'1'.is_ascii_digit()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:13:13 + --> tests/ui/manual_is_ascii_check.rs:19:13 | LL | assert!(matches!('x', 'A'..='Z' | 'a'..='z')); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_alphabetic()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:17:5 + --> tests/ui/manual_is_ascii_check.rs:24:5 | LL | (b'0'..=b'9').contains(&b'0'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'0'.is_ascii_digit()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:18:5 + --> tests/ui/manual_is_ascii_check.rs:26:5 | LL | (b'a'..=b'z').contains(&b'a'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'a'.is_ascii_lowercase()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:19:5 + --> tests/ui/manual_is_ascii_check.rs:28:5 | LL | (b'A'..=b'Z').contains(&b'A'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'A'.is_ascii_uppercase()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:21:5 + --> tests/ui/manual_is_ascii_check.rs:31:5 | LL | ('0'..='9').contains(&'0'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'0'.is_ascii_digit()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:22:5 + --> tests/ui/manual_is_ascii_check.rs:33:5 | LL | ('a'..='z').contains(&'a'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'a'.is_ascii_lowercase()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:23:5 + --> tests/ui/manual_is_ascii_check.rs:35:5 | LL | ('A'..='Z').contains(&'A'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'A'.is_ascii_uppercase()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:26:5 + --> tests/ui/manual_is_ascii_check.rs:39:5 | LL | ('0'..='9').contains(cool_letter); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_digit()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:27:5 + --> tests/ui/manual_is_ascii_check.rs:41:5 | LL | ('a'..='z').contains(cool_letter); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_lowercase()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:28:5 + --> tests/ui/manual_is_ascii_check.rs:43:5 | LL | ('A'..='Z').contains(cool_letter); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_uppercase()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:41:13 + --> tests/ui/manual_is_ascii_check.rs:57:13 | LL | assert!(matches!(b'1', b'0'..=b'9')); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'1'.is_ascii_digit()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:42:13 + --> tests/ui/manual_is_ascii_check.rs:59:13 | LL | assert!(matches!('X', 'A'..='Z')); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'X'.is_ascii_uppercase()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:43:13 + --> tests/ui/manual_is_ascii_check.rs:61:13 | LL | assert!(matches!('x', 'A'..='Z' | 'a'..='z')); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_alphabetic()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:44:13 + --> tests/ui/manual_is_ascii_check.rs:63:13 | LL | assert!(matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F')); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_hexdigit()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:55:23 + --> tests/ui/manual_is_ascii_check.rs:75:23 | LL | const FOO: bool = matches!('x', '0'..='9'); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_digit()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:56:23 + --> tests/ui/manual_is_ascii_check.rs:77:23 | LL | const BAR: bool = matches!('x', '0'..='9' | 'a'..='f' | 'A'..='F'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_hexdigit()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:62:5 + --> tests/ui/manual_is_ascii_check.rs:84:5 | LL | ('0'..='9').contains(&&cool_letter); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_digit()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:63:5 + --> tests/ui/manual_is_ascii_check.rs:86:5 | LL | ('a'..='z').contains(*cool_letter); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_lowercase()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:81:20 + --> tests/ui/manual_is_ascii_check.rs:105:20 | LL | take_while(|c| ('A'..='Z').contains(&c)); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -158,7 +158,7 @@ LL + take_while(|c: char| c.is_ascii_uppercase()); | error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:82:20 + --> tests/ui/manual_is_ascii_check.rs:107:20 | LL | take_while(|c| (b'A'..=b'Z').contains(&c)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -170,13 +170,13 @@ LL + take_while(|c: u8| c.is_ascii_uppercase()); | error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:83:26 + --> tests/ui/manual_is_ascii_check.rs:109:26 | LL | take_while(|c: char| ('A'..='Z').contains(&c)); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `c.is_ascii_uppercase()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:87:63 + --> tests/ui/manual_is_ascii_check.rs:114:63 | LL | let digits: Vec<&char> = ['1', 'A'].iter().take_while(|c| ('0'..='9').contains(c)).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -188,7 +188,7 @@ LL + let digits: Vec<&char> = ['1', 'A'].iter().take_while(|c: &&char| c.is_ | error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:88:71 + --> tests/ui/manual_is_ascii_check.rs:116:71 | LL | let digits: Vec<&mut char> = ['1', 'A'].iter_mut().take_while(|c| ('0'..='9').contains(c)).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/manual_is_power_of_two.fixed b/tests/ui/manual_is_power_of_two.fixed index dda5fe0ec3e7..6f29d76bd210 100644 --- a/tests/ui/manual_is_power_of_two.fixed +++ b/tests/ui/manual_is_power_of_two.fixed @@ -4,13 +4,19 @@ fn main() { let a = 16_u64; let _ = a.is_power_of_two(); + //~^ manual_is_power_of_two let _ = a.is_power_of_two(); + //~^ manual_is_power_of_two // Test different orders of expression let _ = a.is_power_of_two(); + //~^ manual_is_power_of_two let _ = a.is_power_of_two(); + //~^ manual_is_power_of_two let _ = a.is_power_of_two(); + //~^ manual_is_power_of_two let _ = a.is_power_of_two(); + //~^ manual_is_power_of_two let b = 4_i64; diff --git a/tests/ui/manual_is_power_of_two.rs b/tests/ui/manual_is_power_of_two.rs index a1d3a95c4102..0c44d7a660b4 100644 --- a/tests/ui/manual_is_power_of_two.rs +++ b/tests/ui/manual_is_power_of_two.rs @@ -4,13 +4,19 @@ fn main() { let a = 16_u64; let _ = a.count_ones() == 1; + //~^ manual_is_power_of_two let _ = a & (a - 1) == 0; + //~^ manual_is_power_of_two // Test different orders of expression let _ = 1 == a.count_ones(); + //~^ manual_is_power_of_two let _ = (a - 1) & a == 0; + //~^ manual_is_power_of_two let _ = 0 == a & (a - 1); + //~^ manual_is_power_of_two let _ = 0 == (a - 1) & a; + //~^ manual_is_power_of_two let b = 4_i64; diff --git a/tests/ui/manual_is_power_of_two.stderr b/tests/ui/manual_is_power_of_two.stderr index 3cfc6297abf2..ad12ee10565f 100644 --- a/tests/ui/manual_is_power_of_two.stderr +++ b/tests/ui/manual_is_power_of_two.stderr @@ -8,31 +8,31 @@ LL | let _ = a.count_ones() == 1; = help: to override `-D warnings` add `#[allow(clippy::manual_is_power_of_two)]` error: manually reimplementing `is_power_of_two` - --> tests/ui/manual_is_power_of_two.rs:7:13 + --> tests/ui/manual_is_power_of_two.rs:8:13 | LL | let _ = a & (a - 1) == 0; | ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()` error: manually reimplementing `is_power_of_two` - --> tests/ui/manual_is_power_of_two.rs:10:13 + --> tests/ui/manual_is_power_of_two.rs:12:13 | LL | let _ = 1 == a.count_ones(); | ^^^^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()` error: manually reimplementing `is_power_of_two` - --> tests/ui/manual_is_power_of_two.rs:11:13 + --> tests/ui/manual_is_power_of_two.rs:14:13 | LL | let _ = (a - 1) & a == 0; | ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()` error: manually reimplementing `is_power_of_two` - --> tests/ui/manual_is_power_of_two.rs:12:13 + --> tests/ui/manual_is_power_of_two.rs:16:13 | LL | let _ = 0 == a & (a - 1); | ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()` error: manually reimplementing `is_power_of_two` - --> tests/ui/manual_is_power_of_two.rs:13:13 + --> tests/ui/manual_is_power_of_two.rs:18:13 | LL | let _ = 0 == (a - 1) & a; | ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()` diff --git a/tests/ui/manual_is_variant_and.fixed b/tests/ui/manual_is_variant_and.fixed index 8c34b51103c1..c9c184561dd6 100644 --- a/tests/ui/manual_is_variant_and.fixed +++ b/tests/ui/manual_is_variant_and.fixed @@ -13,9 +13,11 @@ fn option_methods() { let _ = opt.is_some_and(|x| x > 1); // Multi-line cases. let _ = opt.is_some_and(|x| { + //~^ manual_is_variant_and x > 1 }); let _ = opt.is_some_and(|x| x > 1); + //~^ manual_is_variant_and let _ = opt .is_some_and(|x| x > 1); @@ -24,6 +26,7 @@ fn option_methods() { let opt2 = Some('a'); let _ = opt2.is_some_and(char::is_alphanumeric); // should lint + //~^ manual_is_variant_and let _ = opt_map!(opt2, |x| x == 'a').unwrap_or_default(); // should not lint } @@ -33,6 +36,7 @@ fn result_methods() { // multi line cases let _ = res.is_ok_and(|x| { + //~^ manual_is_variant_and x > 1 }); let _ = res.is_ok_and(|x| x > 1); @@ -42,6 +46,7 @@ fn result_methods() { let res2: Result = Ok('a'); let _ = res2.is_ok_and(char::is_alphanumeric); // should lint + //~^ manual_is_variant_and let _ = opt_map!(res2, |x| x == 'a').unwrap_or_default(); // should not lint } diff --git a/tests/ui/manual_is_variant_and.rs b/tests/ui/manual_is_variant_and.rs index 25b2489d9421..52c7b56804ce 100644 --- a/tests/ui/manual_is_variant_and.rs +++ b/tests/ui/manual_is_variant_and.rs @@ -11,16 +11,20 @@ fn option_methods() { // Check for `option.map(_).unwrap_or_default()` use. // Single line case. let _ = opt.map(|x| x > 1) + //~^ manual_is_variant_and // Should lint even though this call is on a separate line. .unwrap_or_default(); // Multi-line cases. let _ = opt.map(|x| { + //~^ manual_is_variant_and x > 1 } ).unwrap_or_default(); let _ = opt.map(|x| x > 1).unwrap_or_default(); + //~^ manual_is_variant_and let _ = opt .map(|x| x > 1) + //~^ manual_is_variant_and .unwrap_or_default(); // won't fix because the return type of the closure is not `bool` @@ -28,6 +32,7 @@ fn option_methods() { let opt2 = Some('a'); let _ = opt2.map(char::is_alphanumeric).unwrap_or_default(); // should lint + //~^ manual_is_variant_and let _ = opt_map!(opt2, |x| x == 'a').unwrap_or_default(); // should not lint } @@ -37,10 +42,12 @@ fn result_methods() { // multi line cases let _ = res.map(|x| { + //~^ manual_is_variant_and x > 1 } ).unwrap_or_default(); let _ = res.map(|x| x > 1) + //~^ manual_is_variant_and .unwrap_or_default(); // won't fix because the return type of the closure is not `bool` @@ -48,6 +55,7 @@ fn result_methods() { let res2: Result = Ok('a'); let _ = res2.map(char::is_alphanumeric).unwrap_or_default(); // should lint + //~^ manual_is_variant_and let _ = opt_map!(res2, |x| x == 'a').unwrap_or_default(); // should not lint } diff --git a/tests/ui/manual_is_variant_and.stderr b/tests/ui/manual_is_variant_and.stderr index d3ff7cf8b316..a4fa500580d0 100644 --- a/tests/ui/manual_is_variant_and.stderr +++ b/tests/ui/manual_is_variant_and.stderr @@ -3,7 +3,7 @@ error: called `map().unwrap_or_default()` on an `Option` value | LL | let _ = opt.map(|x| x > 1) | _________________^ -LL | | // Should lint even though this call is on a separate line. +... | LL | | .unwrap_or_default(); | |____________________________^ help: use: `is_some_and(|x| x > 1)` | @@ -11,10 +11,11 @@ LL | | .unwrap_or_default(); = help: to override `-D warnings` add `#[allow(clippy::manual_is_variant_and)]` error: called `map().unwrap_or_default()` on an `Option` value - --> tests/ui/manual_is_variant_and.rs:17:17 + --> tests/ui/manual_is_variant_and.rs:18:17 | LL | let _ = opt.map(|x| { | _________________^ +LL | | LL | | x > 1 LL | | } LL | | ).unwrap_or_default(); @@ -23,35 +24,38 @@ LL | | ).unwrap_or_default(); help: use | LL ~ let _ = opt.is_some_and(|x| { +LL + LL + x > 1 LL ~ }); | error: called `map().unwrap_or_default()` on an `Option` value - --> tests/ui/manual_is_variant_and.rs:21:17 + --> tests/ui/manual_is_variant_and.rs:23:17 | LL | let _ = opt.map(|x| x > 1).unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `is_some_and(|x| x > 1)` error: called `map().unwrap_or_default()` on an `Option` value - --> tests/ui/manual_is_variant_and.rs:23:10 + --> tests/ui/manual_is_variant_and.rs:26:10 | LL | .map(|x| x > 1) | __________^ +LL | | LL | | .unwrap_or_default(); | |____________________________^ help: use: `is_some_and(|x| x > 1)` error: called `map().unwrap_or_default()` on an `Option` value - --> tests/ui/manual_is_variant_and.rs:30:18 + --> tests/ui/manual_is_variant_and.rs:34:18 | LL | let _ = opt2.map(char::is_alphanumeric).unwrap_or_default(); // should lint | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `is_some_and(char::is_alphanumeric)` error: called `map().unwrap_or_default()` on a `Result` value - --> tests/ui/manual_is_variant_and.rs:39:17 + --> tests/ui/manual_is_variant_and.rs:44:17 | LL | let _ = res.map(|x| { | _________________^ +LL | | LL | | x > 1 LL | | } LL | | ).unwrap_or_default(); @@ -60,20 +64,22 @@ LL | | ).unwrap_or_default(); help: use | LL ~ let _ = res.is_ok_and(|x| { +LL + LL + x > 1 LL ~ }); | error: called `map().unwrap_or_default()` on a `Result` value - --> tests/ui/manual_is_variant_and.rs:43:17 + --> tests/ui/manual_is_variant_and.rs:49:17 | LL | let _ = res.map(|x| x > 1) | _________________^ +LL | | LL | | .unwrap_or_default(); | |____________________________^ help: use: `is_ok_and(|x| x > 1)` error: called `map().unwrap_or_default()` on a `Result` value - --> tests/ui/manual_is_variant_and.rs:50:18 + --> tests/ui/manual_is_variant_and.rs:57:18 | LL | let _ = res2.map(char::is_alphanumeric).unwrap_or_default(); // should lint | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `is_ok_and(char::is_alphanumeric)` diff --git a/tests/ui/manual_let_else.rs b/tests/ui/manual_let_else.rs index 2b36c3f3c2fb..d2350d97ed00 100644 --- a/tests/ui/manual_let_else.rs +++ b/tests/ui/manual_let_else.rs @@ -27,17 +27,19 @@ fn main() {} fn fire() { let v = if let Some(v_some) = g() { v_some } else { return }; - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else let v = if let Some(v_some) = g() { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else + v_some } else { return; }; let v = if let Some(v) = g() { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else + // Blocks around the identity should have no impact { { v } } } else { @@ -49,18 +51,20 @@ fn fire() { // continue and break diverge loop { let v = if let Some(v_some) = g() { v_some } else { continue }; - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else + let v = if let Some(v_some) = g() { v_some } else { break }; - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else } // panic also diverges let v = if let Some(v_some) = g() { v_some } else { panic!() }; - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else // abort also diverges let v = if let Some(v_some) = g() { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else + v_some } else { std::process::abort() @@ -68,7 +72,8 @@ fn fire() { // If whose two branches diverge also diverges let v = if let Some(v_some) = g() { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else + v_some } else { if true { return } else { panic!() } @@ -76,7 +81,8 @@ fn fire() { // Diverging after an if still makes the block diverge: let v = if let Some(v_some) = g() { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else + v_some } else { if true {} @@ -85,7 +91,8 @@ fn fire() { // The final expression will need to be turned into a statement. let v = if let Some(v_some) = g() { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else + v_some } else { panic!(); @@ -94,7 +101,8 @@ fn fire() { // Even if the result is buried multiple expressions deep. let v = if let Some(v_some) = g() { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else + v_some } else { panic!(); @@ -110,7 +118,8 @@ fn fire() { // Or if a break gives the value. let v = if let Some(v_some) = g() { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else + v_some } else { loop { @@ -121,7 +130,8 @@ fn fire() { // Even if the break is in a weird position. let v = if let Some(v_some) = g() { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else + v_some } else { 'a: loop { @@ -137,7 +147,8 @@ fn fire() { // A match diverges if all branches diverge: let v = if let Some(v_some) = g() { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else + v_some } else { match 0 { @@ -148,7 +159,8 @@ fn fire() { // An if's expression can cause divergence: let v = if let Some(v_some) = g() { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else + v_some } else { if panic!() {}; @@ -156,7 +168,8 @@ fn fire() { // An expression of a match can cause divergence: let v = if let Some(v_some) = g() { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else + v_some } else { match panic!() { @@ -166,7 +179,8 @@ fn fire() { // Top level else if let v = if let Some(v_some) = g() { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else + v_some } else if true { return; @@ -176,7 +190,8 @@ fn fire() { // All match arms diverge let v = if let Some(v_some) = g() { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else + v_some } else { match (g(), g()) { @@ -194,7 +209,8 @@ fn fire() { // Tuples supported for the declared variables let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else + v_some } else { return; @@ -202,7 +218,8 @@ fn fire() { // Tuples supported with multiple bindings let (w, S { v }) = if let (Some(v_some), w_some) = (g().map(|_| S { v: 0 }), 0) { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else + (w_some, v_some) } else { return; @@ -212,6 +229,7 @@ fn fire() { macro_rules! create_binding_if_some { ($n:ident, $e:expr) => { let $n = if let Some(v) = $e { v } else { return }; + //~^ manual_let_else }; } create_binding_if_some!(w, g()); @@ -221,31 +239,33 @@ fn fire() { } let v = if let Variant::A(a, 0) = e() { a } else { return }; - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else // `mut v` is inserted into the pattern let mut v = if let Variant::B(b) = e() { b } else { return }; - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else // Nesting works let nested = Ok(Some(e())); let v = if let Ok(Some(Variant::B(b))) | Err(Some(Variant::A(b, _))) = nested { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else + b } else { return; }; // dot dot works let v = if let Variant::A(.., a) = e() { a } else { return }; - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else // () is preserved: a bit of an edge case but make sure it stays around let w = if let (Some(v), ()) = (g(), ()) { v } else { return }; - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else // Tuple structs work let w = if let Some(S { v: x }) = Some(S { v: 0 }) { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else + x } else { return; @@ -253,7 +273,8 @@ fn fire() { // Field init shorthand is suggested let v = if let Some(S { v: x }) = Some(S { v: 0 }) { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else + x } else { return; @@ -261,7 +282,8 @@ fn fire() { // Multi-field structs also work let (x, S { v }, w) = if let Some(U { v, w, x }) = None::>> { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else + (x, v, w) } else { return; @@ -378,7 +400,7 @@ fn not_fire() { let ff = Some(1); let _ = match ff { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else Some(value) => value, _ => macro_call!(), }; @@ -455,5 +477,6 @@ fn issue12337() { // we still emit a lint for manual_let_else let _: Option<()> = try { let v = if let Some(v_some) = g() { v_some } else { return }; + //~^ manual_let_else }; } diff --git a/tests/ui/manual_let_else.stderr b/tests/ui/manual_let_else.stderr index dcd5d4561113..8f5cba64d545 100644 --- a/tests/ui/manual_let_else.stderr +++ b/tests/ui/manual_let_else.stderr @@ -12,6 +12,7 @@ error: this could be rewritten as `let...else` | LL | / let v = if let Some(v_some) = g() { LL | | +LL | | LL | | v_some LL | | } else { LL | | return; @@ -26,12 +27,9 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:39:5 + --> tests/ui/manual_let_else.rs:40:5 | LL | / let v = if let Some(v) = g() { -LL | | -LL | | // Blocks around the identity should have no impact -LL | | { { v } } ... | LL | | return; LL | | }; @@ -47,28 +45,29 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:51:9 + --> tests/ui/manual_let_else.rs:53:9 | LL | let v = if let Some(v_some) = g() { v_some } else { continue }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { continue };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:53:9 + --> tests/ui/manual_let_else.rs:56:9 | LL | let v = if let Some(v_some) = g() { v_some } else { break }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { break };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:58:5 + --> tests/ui/manual_let_else.rs:61:5 | LL | let v = if let Some(v_some) = g() { v_some } else { panic!() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { panic!() };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:62:5 + --> tests/ui/manual_let_else.rs:65:5 | LL | / let v = if let Some(v_some) = g() { LL | | +LL | | LL | | v_some LL | | } else { LL | | std::process::abort() @@ -83,10 +82,11 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:70:5 + --> tests/ui/manual_let_else.rs:74:5 | LL | / let v = if let Some(v_some) = g() { LL | | +LL | | LL | | v_some LL | | } else { LL | | if true { return } else { panic!() } @@ -101,13 +101,13 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:78:5 + --> tests/ui/manual_let_else.rs:83:5 | LL | / let v = if let Some(v_some) = g() { LL | | +LL | | LL | | v_some -LL | | } else { -LL | | if true {} +... | LL | | panic!(); LL | | }; | |______^ @@ -121,13 +121,13 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:87:5 + --> tests/ui/manual_let_else.rs:93:5 | LL | / let v = if let Some(v_some) = g() { LL | | +LL | | LL | | v_some -LL | | } else { -LL | | panic!(); +... | LL | | () LL | | }; | |______^ @@ -141,12 +141,12 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:96:5 + --> tests/ui/manual_let_else.rs:103:5 | LL | / let v = if let Some(v_some) = g() { LL | | +LL | | LL | | v_some -LL | | } else { ... | LL | | }; | |______^ @@ -167,12 +167,12 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:112:5 + --> tests/ui/manual_let_else.rs:120:5 | LL | / let v = if let Some(v_some) = g() { LL | | +LL | | LL | | v_some -LL | | } else { ... | LL | | }; | |______^ @@ -188,12 +188,12 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:123:5 + --> tests/ui/manual_let_else.rs:132:5 | LL | / let v = if let Some(v_some) = g() { LL | | +LL | | LL | | v_some -LL | | } else { ... | LL | | }; | |______^ @@ -214,12 +214,12 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:139:5 + --> tests/ui/manual_let_else.rs:149:5 | LL | / let v = if let Some(v_some) = g() { LL | | +LL | | LL | | v_some -LL | | } else { ... | LL | | }; LL | | }; @@ -236,10 +236,11 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:150:5 + --> tests/ui/manual_let_else.rs:161:5 | LL | / let v = if let Some(v_some) = g() { LL | | +LL | | LL | | v_some LL | | } else { LL | | if panic!() {}; @@ -254,12 +255,12 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:158:5 + --> tests/ui/manual_let_else.rs:170:5 | LL | / let v = if let Some(v_some) = g() { LL | | +LL | | LL | | v_some -LL | | } else { ... | LL | | }; LL | | }; @@ -275,12 +276,12 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:168:5 + --> tests/ui/manual_let_else.rs:181:5 | LL | / let v = if let Some(v_some) = g() { LL | | +LL | | LL | | v_some -LL | | } else if true { ... | LL | | panic!("diverge"); LL | | }; @@ -296,12 +297,12 @@ LL + } }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:178:5 + --> tests/ui/manual_let_else.rs:192:5 | LL | / let v = if let Some(v_some) = g() { LL | | +LL | | LL | | v_some -LL | | } else { ... | LL | | }; | |______^ @@ -324,10 +325,11 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:196:5 + --> tests/ui/manual_let_else.rs:211:5 | LL | / let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) { LL | | +LL | | LL | | v_some LL | | } else { LL | | return; @@ -342,10 +344,11 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:204:5 + --> tests/ui/manual_let_else.rs:220:5 | LL | / let (w, S { v }) = if let (Some(v_some), w_some) = (g().map(|_| S { v: 0 }), 0) { LL | | +LL | | LL | | (w_some, v_some) LL | | } else { LL | | return; @@ -360,7 +363,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:214:13 + --> tests/ui/manual_let_else.rs:231:13 | LL | let $n = if let Some(v) = $e { v } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some($n) = g() else { return };` @@ -371,22 +374,23 @@ LL | create_binding_if_some!(w, g()); = note: this error originates in the macro `create_binding_if_some` (in Nightly builds, run with -Z macro-backtrace for more info) error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:223:5 + --> tests/ui/manual_let_else.rs:241:5 | LL | let v = if let Variant::A(a, 0) = e() { a } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(v, 0) = e() else { return };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:227:5 + --> tests/ui/manual_let_else.rs:245:5 | LL | let mut v = if let Variant::B(b) = e() { b } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::B(mut v) = e() else { return };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:232:5 + --> tests/ui/manual_let_else.rs:250:5 | LL | / let v = if let Ok(Some(Variant::B(b))) | Err(Some(Variant::A(b, _))) = nested { LL | | +LL | | LL | | b LL | | } else { LL | | return; @@ -401,22 +405,23 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:239:5 + --> tests/ui/manual_let_else.rs:258:5 | LL | let v = if let Variant::A(.., a) = e() { a } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(.., v) = e() else { return };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:243:5 + --> tests/ui/manual_let_else.rs:262:5 | LL | let w = if let (Some(v), ()) = (g(), ()) { v } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let (Some(w), ()) = (g(), ()) else { return };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:247:5 + --> tests/ui/manual_let_else.rs:266:5 | LL | / let w = if let Some(S { v: x }) = Some(S { v: 0 }) { LL | | +LL | | LL | | x LL | | } else { LL | | return; @@ -431,10 +436,11 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:255:5 + --> tests/ui/manual_let_else.rs:275:5 | LL | / let v = if let Some(S { v: x }) = Some(S { v: 0 }) { LL | | +LL | | LL | | x LL | | } else { LL | | return; @@ -449,10 +455,11 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:263:5 + --> tests/ui/manual_let_else.rs:284:5 | LL | / let (x, S { v }, w) = if let Some(U { v, w, x }) = None::>> { LL | | +LL | | LL | | (x, v, w) LL | | } else { LL | | return; @@ -467,7 +474,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:380:5 + --> tests/ui/manual_let_else.rs:402:5 | LL | / let _ = match ff { LL | | @@ -477,7 +484,7 @@ LL | | }; | |______^ help: consider writing: `let Some(_) = ff else { macro_call!() };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:457:9 + --> tests/ui/manual_let_else.rs:479:9 | LL | let v = if let Some(v_some) = g() { v_some } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };` diff --git a/tests/ui/manual_let_else_match.rs b/tests/ui/manual_let_else_match.rs index c37b5613ff7d..6416753bac10 100644 --- a/tests/ui/manual_let_else_match.rs +++ b/tests/ui/manual_let_else_match.rs @@ -34,14 +34,13 @@ fn main() {} fn fire() { let v = match g() { - //~^ ERROR: this could be rewritten as `let...else` - //~| NOTE: `-D clippy::manual-let-else` implied by `-D warnings` + //~^ manual_let_else Some(v_some) => v_some, None => return, }; let v = match g() { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else Some(v_some) => v_some, _ => return, }; @@ -49,13 +48,13 @@ fn fire() { loop { // More complex pattern for the identity arm and diverging arm let v = match h() { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else (Some(v), None) | (None, Some(v)) => v, (Some(_), Some(_)) | (None, None) => continue, }; // Custom enums are supported as long as the "else" arm is a simple _ let v = match build_enum() { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else Variant::Bar(v) | Variant::Baz(v) => v, _ => continue, }; @@ -64,14 +63,14 @@ fn fire() { // There is a _ in the diverging arm // TODO also support unused bindings aka _v let v = match f() { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else Ok(v) => v, Err(_) => return, }; // Err(()) is an allowed pattern let v = match f().map_err(|_| ()) { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else Ok(v) => v, Err(()) => return, }; @@ -79,20 +78,20 @@ fn fire() { let f = Variant::Bar(1); let _value = match f { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else Variant::Bar(v) | Variant::Baz(v) => v, _ => return, }; let _value = match Some(build_enum()) { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else Some(Variant::Bar(v) | Variant::Baz(v)) => v, _ => return, }; let data = [1_u8, 2, 3, 4, 0, 0, 0, 0]; let data = match data.as_slice() { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else [data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ .., 0] => data, _ => return, }; @@ -173,7 +172,7 @@ fn not_fire() { fn issue11579() { let msg = match Some("hi") { - //~^ ERROR: this could be rewritten as `let...else` + //~^ manual_let_else Some(m) => m, _ => unreachable!("can't happen"), }; diff --git a/tests/ui/manual_let_else_match.stderr b/tests/ui/manual_let_else_match.stderr index 3c0065f64033..393562c629ba 100644 --- a/tests/ui/manual_let_else_match.stderr +++ b/tests/ui/manual_let_else_match.stderr @@ -3,7 +3,6 @@ error: this could be rewritten as `let...else` | LL | / let v = match g() { LL | | -LL | | LL | | Some(v_some) => v_some, LL | | None => return, LL | | }; @@ -13,7 +12,7 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::manual_let_else)]` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else_match.rs:43:5 + --> tests/ui/manual_let_else_match.rs:42:5 | LL | / let v = match g() { LL | | @@ -23,7 +22,7 @@ LL | | }; | |______^ help: consider writing: `let Some(v) = g() else { return };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else_match.rs:51:9 + --> tests/ui/manual_let_else_match.rs:50:9 | LL | / let v = match h() { LL | | @@ -33,7 +32,7 @@ LL | | }; | |__________^ help: consider writing: `let ((Some(v), None) | (None, Some(v))) = h() else { continue };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else_match.rs:57:9 + --> tests/ui/manual_let_else_match.rs:56:9 | LL | / let v = match build_enum() { LL | | @@ -43,7 +42,7 @@ LL | | }; | |__________^ help: consider writing: `let (Variant::Bar(v) | Variant::Baz(v)) = build_enum() else { continue };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else_match.rs:66:5 + --> tests/ui/manual_let_else_match.rs:65:5 | LL | / let v = match f() { LL | | @@ -53,7 +52,7 @@ LL | | }; | |______^ help: consider writing: `let Ok(v) = f() else { return };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else_match.rs:73:5 + --> tests/ui/manual_let_else_match.rs:72:5 | LL | / let v = match f().map_err(|_| ()) { LL | | @@ -63,7 +62,7 @@ LL | | }; | |______^ help: consider writing: `let Ok(v) = f().map_err(|_| ()) else { return };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else_match.rs:81:5 + --> tests/ui/manual_let_else_match.rs:80:5 | LL | / let _value = match f { LL | | @@ -73,7 +72,7 @@ LL | | }; | |______^ help: consider writing: `let (Variant::Bar(_value) | Variant::Baz(_value)) = f else { return };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else_match.rs:87:5 + --> tests/ui/manual_let_else_match.rs:86:5 | LL | / let _value = match Some(build_enum()) { LL | | @@ -83,7 +82,7 @@ LL | | }; | |______^ help: consider writing: `let Some(Variant::Bar(_value) | Variant::Baz(_value)) = Some(build_enum()) else { return };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else_match.rs:94:5 + --> tests/ui/manual_let_else_match.rs:93:5 | LL | / let data = match data.as_slice() { LL | | @@ -93,7 +92,7 @@ LL | | }; | |______^ help: consider writing: `let ([data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ .., 0]) = data.as_slice() else { return };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else_match.rs:175:5 + --> tests/ui/manual_let_else_match.rs:174:5 | LL | / let msg = match Some("hi") { LL | | diff --git a/tests/ui/manual_let_else_question_mark.fixed b/tests/ui/manual_let_else_question_mark.fixed index 6b29ce759857..aca32a49c13b 100644 --- a/tests/ui/manual_let_else_question_mark.fixed +++ b/tests/ui/manual_let_else_question_mark.fixed @@ -27,15 +27,18 @@ fn main() {} fn foo() -> Option<()> { // Fire here, normal case let v = g()?; + //~^ question_mark // Don't fire here, the pattern is refutable let Variant::A(v, w) = e() else { return None }; // Fire here, the pattern is irrefutable let (v, w) = g()?; + //~^ question_mark // Don't fire manual_let_else in this instance: question mark can be used instead. let v = g()?; + //~^ question_mark // Do fire manual_let_else in this instance: question mark cannot be used here due to the return // body. @@ -56,6 +59,7 @@ fn foo() -> Option<()> { #[allow(clippy::question_mark)] { let Some(v) = g() else { return None }; + //~^ manual_let_else } Some(()) @@ -64,6 +68,7 @@ fn foo() -> Option<()> { // lint not just `return None`, but also `return None;` (note the semicolon) fn issue11993(y: Option) -> Option { let x = y?; + //~^^^ question_mark // don't lint: more than one statement in the else body let Some(x) = y else { diff --git a/tests/ui/manual_let_else_question_mark.rs b/tests/ui/manual_let_else_question_mark.rs index e92c4c1375e5..8b43d59816f9 100644 --- a/tests/ui/manual_let_else_question_mark.rs +++ b/tests/ui/manual_let_else_question_mark.rs @@ -27,19 +27,23 @@ fn main() {} fn foo() -> Option<()> { // Fire here, normal case let Some(v) = g() else { return None }; + //~^ question_mark // Don't fire here, the pattern is refutable let Variant::A(v, w) = e() else { return None }; // Fire here, the pattern is irrefutable let Some((v, w)) = g() else { return None }; + //~^ question_mark // Don't fire manual_let_else in this instance: question mark can be used instead. let v = if let Some(v_some) = g() { v_some } else { return None }; + //~^ question_mark // Do fire manual_let_else in this instance: question mark cannot be used here due to the return // body. let v = if let Some(v_some) = g() { + //~^ manual_let_else v_some } else { return Some(()); @@ -51,6 +55,7 @@ fn foo() -> Option<()> { #[allow(clippy::question_mark)] { let v = match g() { + //~^ manual_let_else Some(v_some) => v_some, _ => return None, }; @@ -61,6 +66,7 @@ fn foo() -> Option<()> { #[allow(clippy::question_mark)] { let v = if let Some(v_some) = g() { v_some } else { return None }; + //~^ manual_let_else } Some(()) @@ -71,6 +77,7 @@ fn issue11993(y: Option) -> Option { let Some(x) = y else { return None; }; + //~^^^ question_mark // don't lint: more than one statement in the else body let Some(x) = y else { diff --git a/tests/ui/manual_let_else_question_mark.stderr b/tests/ui/manual_let_else_question_mark.stderr index 434872ca2677..4fdd64d98491 100644 --- a/tests/ui/manual_let_else_question_mark.stderr +++ b/tests/ui/manual_let_else_question_mark.stderr @@ -8,21 +8,22 @@ LL | let Some(v) = g() else { return None }; = help: to override `-D warnings` add `#[allow(clippy::question_mark)]` error: this `let...else` may be rewritten with the `?` operator - --> tests/ui/manual_let_else_question_mark.rs:35:5 + --> tests/ui/manual_let_else_question_mark.rs:36:5 | LL | let Some((v, w)) = g() else { return None }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `let (v, w) = g()?;` error: this block may be rewritten with the `?` operator - --> tests/ui/manual_let_else_question_mark.rs:38:13 + --> tests/ui/manual_let_else_question_mark.rs:40:13 | LL | let v = if let Some(v_some) = g() { v_some } else { return None }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `g()?` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else_question_mark.rs:42:5 + --> tests/ui/manual_let_else_question_mark.rs:45:5 | LL | / let v = if let Some(v_some) = g() { +LL | | LL | | v_some LL | | } else { LL | | return Some(()); @@ -39,22 +40,23 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else_question_mark.rs:53:9 + --> tests/ui/manual_let_else_question_mark.rs:57:9 | LL | / let v = match g() { +LL | | LL | | Some(v_some) => v_some, LL | | _ => return None, LL | | }; | |__________^ help: consider writing: `let Some(v) = g() else { return None };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else_question_mark.rs:63:9 + --> tests/ui/manual_let_else_question_mark.rs:68:9 | LL | let v = if let Some(v_some) = g() { v_some } else { return None }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return None };` error: this `let...else` may be rewritten with the `?` operator - --> tests/ui/manual_let_else_question_mark.rs:71:5 + --> tests/ui/manual_let_else_question_mark.rs:77:5 | LL | / let Some(x) = y else { LL | | return None; diff --git a/tests/ui/manual_main_separator_str.fixed b/tests/ui/manual_main_separator_str.fixed index 6441d6edef8c..6e5478ad009e 100644 --- a/tests/ui/manual_main_separator_str.fixed +++ b/tests/ui/manual_main_separator_str.fixed @@ -19,12 +19,16 @@ struct V { fn main() { // Should lint let _: &str = std::path::MAIN_SEPARATOR_STR; + //~^ manual_main_separator_str let _ = len(std::path::MAIN_SEPARATOR_STR); + //~^ manual_main_separator_str let _: Vec = std::path::MAIN_SEPARATOR_STR.encode_utf16().collect(); + //~^ manual_main_separator_str // Should lint for field `f` only let _ = U { f: std::path::MAIN_SEPARATOR_STR, + //~^ manual_main_separator_str g: &MAIN_SEPARATOR.to_string(), }; diff --git a/tests/ui/manual_main_separator_str.rs b/tests/ui/manual_main_separator_str.rs index 339dfd8bb473..170af2da143f 100644 --- a/tests/ui/manual_main_separator_str.rs +++ b/tests/ui/manual_main_separator_str.rs @@ -19,12 +19,16 @@ struct V { fn main() { // Should lint let _: &str = &MAIN_SEPARATOR.to_string(); + //~^ manual_main_separator_str let _ = len(&MAIN_SEPARATOR.to_string()); + //~^ manual_main_separator_str let _: Vec = MAIN_SEPARATOR.to_string().encode_utf16().collect(); + //~^ manual_main_separator_str // Should lint for field `f` only let _ = U { f: &MAIN_SEPARATOR.to_string(), + //~^ manual_main_separator_str g: &MAIN_SEPARATOR.to_string(), }; diff --git a/tests/ui/manual_main_separator_str.stderr b/tests/ui/manual_main_separator_str.stderr index 78395eb7d664..1c58b8261d4f 100644 --- a/tests/ui/manual_main_separator_str.stderr +++ b/tests/ui/manual_main_separator_str.stderr @@ -8,19 +8,19 @@ LL | let _: &str = &MAIN_SEPARATOR.to_string(); = help: to override `-D warnings` add `#[allow(clippy::manual_main_separator_str)]` error: taking a reference on `std::path::MAIN_SEPARATOR` conversion to `String` - --> tests/ui/manual_main_separator_str.rs:22:17 + --> tests/ui/manual_main_separator_str.rs:23:17 | LL | let _ = len(&MAIN_SEPARATOR.to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `std::path::MAIN_SEPARATOR_STR` error: taking a reference on `std::path::MAIN_SEPARATOR` conversion to `String` - --> tests/ui/manual_main_separator_str.rs:23:23 + --> tests/ui/manual_main_separator_str.rs:25:23 | LL | let _: Vec = MAIN_SEPARATOR.to_string().encode_utf16().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `std::path::MAIN_SEPARATOR_STR` error: taking a reference on `std::path::MAIN_SEPARATOR` conversion to `String` - --> tests/ui/manual_main_separator_str.rs:27:12 + --> tests/ui/manual_main_separator_str.rs:30:12 | LL | f: &MAIN_SEPARATOR.to_string(), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `std::path::MAIN_SEPARATOR_STR` diff --git a/tests/ui/manual_map_option.fixed b/tests/ui/manual_map_option.fixed index 16cee3fd3823..3586979ab358 100644 --- a/tests/ui/manual_map_option.fixed +++ b/tests/ui/manual_map_option.fixed @@ -113,7 +113,16 @@ fn main() { } // #6811 - Some(0).map(|x| vec![x]); + match Some(0) { + Some(x) => Some(vec![x]), + None => None, + }; + + // Don't lint, coercion + let x: Option> = match Some(()) { + Some(_) => Some(vec![b"1234"]), + None => None, + }; option_env!("").map(String::from); diff --git a/tests/ui/manual_map_option.rs b/tests/ui/manual_map_option.rs index 4655acf1406c..9477d0d795d2 100644 --- a/tests/ui/manual_map_option.rs +++ b/tests/ui/manual_map_option.rs @@ -12,21 +12,25 @@ fn main() { match Some(0) { + //~^ manual_map Some(_) => Some(2), None:: => None, }; match Some(0) { + //~^ manual_map Some(x) => Some(x + 1), _ => None, }; match Some("") { + //~^ manual_map Some(x) => Some(x.is_empty()), None => None, }; if let Some(x) = Some(0) { + //~^ manual_map Some(!x) } else { None @@ -34,11 +38,13 @@ fn main() { #[rustfmt::skip] match Some(0) { + //~^ manual_map Some(x) => { Some(std::convert::identity(x)) } None => { None } }; match Some(&String::new()) { + //~^ manual_map Some(x) => Some(str::len(x)), None => None, }; @@ -49,26 +55,31 @@ fn main() { }; match &Some([0, 1]) { + //~^ manual_map Some(x) => Some(x[0]), &None => None, }; match &Some(0) { + //~^ manual_map &Some(x) => Some(x * 2), None => None, }; match Some(String::new()) { + //~^ manual_map Some(ref x) => Some(x.is_empty()), _ => None, }; match &&Some(String::new()) { + //~^ manual_map Some(x) => Some(x.len()), _ => None, }; match &&Some(0) { + //~^ manual_map &&Some(x) => Some(x + x), &&_ => None, }; @@ -82,32 +93,38 @@ fn main() { #[allow(clippy::option_map_unit_fn)] { match &mut Some(String::new()) { + //~^ manual_map Some(x) => Some(x.push_str("")), None => None, }; } match &mut Some(String::new()) { + //~^ manual_map Some(ref x) => Some(x.len()), None => None, }; match &mut &Some(String::new()) { + //~^ manual_map Some(x) => Some(x.is_empty()), &mut _ => None, }; match Some((0, 1, 2)) { + //~^ manual_map Some((x, y, z)) => Some(x + y + z), None => None, }; match Some([1, 2, 3]) { + //~^ manual_map Some([first, ..]) => Some(first), None => None, }; match &Some((String::new(), "test")) { + //~^ manual_map Some((x, y)) => Some((y, x)), None => None, }; @@ -170,7 +187,14 @@ fn main() { None => None, }; + // Don't lint, coercion + let x: Option> = match Some(()) { + Some(_) => Some(vec![b"1234"]), + None => None, + }; + match option_env!("") { + //~^ manual_map Some(x) => Some(String::from(x)), None => None, }; @@ -191,6 +215,7 @@ fn main() { if let Some(_) = Some(0) { Some(0) } else if let Some(x) = Some(0) { + //~^ manual_map Some(x + 1) } else { None @@ -199,6 +224,7 @@ fn main() { if true { Some(0) } else if let Some(x) = Some(0) { + //~^ manual_map Some(x + 1) } else { None diff --git a/tests/ui/manual_map_option.stderr b/tests/ui/manual_map_option.stderr index 47cc18303ba5..8f9bce4c265c 100644 --- a/tests/ui/manual_map_option.stderr +++ b/tests/ui/manual_map_option.stderr @@ -2,6 +2,7 @@ error: manual implementation of `Option::map` --> tests/ui/manual_map_option.rs:14:5 | LL | / match Some(0) { +LL | | LL | | Some(_) => Some(2), LL | | None:: => None, LL | | }; @@ -11,27 +12,30 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::manual_map)]` error: manual implementation of `Option::map` - --> tests/ui/manual_map_option.rs:19:5 + --> tests/ui/manual_map_option.rs:20:5 | LL | / match Some(0) { +LL | | LL | | Some(x) => Some(x + 1), LL | | _ => None, LL | | }; | |_____^ help: try: `Some(0).map(|x| x + 1)` error: manual implementation of `Option::map` - --> tests/ui/manual_map_option.rs:24:5 + --> tests/ui/manual_map_option.rs:26:5 | LL | / match Some("") { +LL | | LL | | Some(x) => Some(x.is_empty()), LL | | None => None, LL | | }; | |_____^ help: try: `Some("").map(|x| x.is_empty())` error: manual implementation of `Option::map` - --> tests/ui/manual_map_option.rs:29:5 + --> tests/ui/manual_map_option.rs:32:5 | LL | / if let Some(x) = Some(0) { +LL | | LL | | Some(!x) LL | | } else { LL | | None @@ -39,145 +43,151 @@ LL | | }; | |_____^ help: try: `Some(0).map(|x| !x)` error: manual implementation of `Option::map` - --> tests/ui/manual_map_option.rs:36:5 + --> tests/ui/manual_map_option.rs:40:5 | LL | / match Some(0) { +LL | | LL | | Some(x) => { Some(std::convert::identity(x)) } LL | | None => { None } LL | | }; | |_____^ help: try: `Some(0).map(std::convert::identity)` error: manual implementation of `Option::map` - --> tests/ui/manual_map_option.rs:41:5 + --> tests/ui/manual_map_option.rs:46:5 | LL | / match Some(&String::new()) { +LL | | LL | | Some(x) => Some(str::len(x)), LL | | None => None, LL | | }; | |_____^ help: try: `Some(&String::new()).map(|x| str::len(x))` error: manual implementation of `Option::map` - --> tests/ui/manual_map_option.rs:51:5 + --> tests/ui/manual_map_option.rs:57:5 | LL | / match &Some([0, 1]) { +LL | | LL | | Some(x) => Some(x[0]), LL | | &None => None, LL | | }; | |_____^ help: try: `Some([0, 1]).as_ref().map(|x| x[0])` error: manual implementation of `Option::map` - --> tests/ui/manual_map_option.rs:56:5 + --> tests/ui/manual_map_option.rs:63:5 | LL | / match &Some(0) { +LL | | LL | | &Some(x) => Some(x * 2), LL | | None => None, LL | | }; | |_____^ help: try: `Some(0).map(|x| x * 2)` error: manual implementation of `Option::map` - --> tests/ui/manual_map_option.rs:61:5 + --> tests/ui/manual_map_option.rs:69:5 | LL | / match Some(String::new()) { +LL | | LL | | Some(ref x) => Some(x.is_empty()), LL | | _ => None, LL | | }; | |_____^ help: try: `Some(String::new()).as_ref().map(|x| x.is_empty())` error: manual implementation of `Option::map` - --> tests/ui/manual_map_option.rs:66:5 + --> tests/ui/manual_map_option.rs:75:5 | LL | / match &&Some(String::new()) { +LL | | LL | | Some(x) => Some(x.len()), LL | | _ => None, LL | | }; | |_____^ help: try: `Some(String::new()).as_ref().map(|x| x.len())` error: manual implementation of `Option::map` - --> tests/ui/manual_map_option.rs:71:5 + --> tests/ui/manual_map_option.rs:81:5 | LL | / match &&Some(0) { +LL | | LL | | &&Some(x) => Some(x + x), LL | | &&_ => None, LL | | }; | |_____^ help: try: `Some(0).map(|x| x + x)` error: manual implementation of `Option::map` - --> tests/ui/manual_map_option.rs:84:9 + --> tests/ui/manual_map_option.rs:95:9 | LL | / match &mut Some(String::new()) { +LL | | LL | | Some(x) => Some(x.push_str("")), LL | | None => None, LL | | }; | |_________^ help: try: `Some(String::new()).as_mut().map(|x| x.push_str(""))` error: manual implementation of `Option::map` - --> tests/ui/manual_map_option.rs:90:5 + --> tests/ui/manual_map_option.rs:102:5 | LL | / match &mut Some(String::new()) { +LL | | LL | | Some(ref x) => Some(x.len()), LL | | None => None, LL | | }; | |_____^ help: try: `Some(String::new()).as_ref().map(|x| x.len())` error: manual implementation of `Option::map` - --> tests/ui/manual_map_option.rs:95:5 + --> tests/ui/manual_map_option.rs:108:5 | LL | / match &mut &Some(String::new()) { +LL | | LL | | Some(x) => Some(x.is_empty()), LL | | &mut _ => None, LL | | }; | |_____^ help: try: `Some(String::new()).as_ref().map(|x| x.is_empty())` error: manual implementation of `Option::map` - --> tests/ui/manual_map_option.rs:100:5 + --> tests/ui/manual_map_option.rs:114:5 | LL | / match Some((0, 1, 2)) { +LL | | LL | | Some((x, y, z)) => Some(x + y + z), LL | | None => None, LL | | }; | |_____^ help: try: `Some((0, 1, 2)).map(|(x, y, z)| x + y + z)` error: manual implementation of `Option::map` - --> tests/ui/manual_map_option.rs:105:5 + --> tests/ui/manual_map_option.rs:120:5 | LL | / match Some([1, 2, 3]) { +LL | | LL | | Some([first, ..]) => Some(first), LL | | None => None, LL | | }; | |_____^ help: try: `Some([1, 2, 3]).map(|[first, ..]| first)` error: manual implementation of `Option::map` - --> tests/ui/manual_map_option.rs:110:5 + --> tests/ui/manual_map_option.rs:126:5 | LL | / match &Some((String::new(), "test")) { +LL | | LL | | Some((x, y)) => Some((y, x)), LL | | None => None, LL | | }; | |_____^ help: try: `Some((String::new(), "test")).as_ref().map(|(x, y)| (y, x))` error: manual implementation of `Option::map` - --> tests/ui/manual_map_option.rs:168:5 - | -LL | / match Some(0) { -LL | | Some(x) => Some(vec![x]), -LL | | None => None, -LL | | }; - | |_____^ help: try: `Some(0).map(|x| vec![x])` - -error: manual implementation of `Option::map` - --> tests/ui/manual_map_option.rs:173:5 + --> tests/ui/manual_map_option.rs:196:5 | LL | / match option_env!("") { +LL | | LL | | Some(x) => Some(String::from(x)), LL | | None => None, LL | | }; | |_____^ help: try: `option_env!("").map(String::from)` error: manual implementation of `Option::map` - --> tests/ui/manual_map_option.rs:193:12 + --> tests/ui/manual_map_option.rs:217:12 | LL | } else if let Some(x) = Some(0) { | ____________^ +LL | | LL | | Some(x + 1) LL | | } else { LL | | None @@ -185,15 +195,16 @@ LL | | }; | |_____^ help: try: `{ Some(0).map(|x| x + 1) }` error: manual implementation of `Option::map` - --> tests/ui/manual_map_option.rs:201:12 + --> tests/ui/manual_map_option.rs:226:12 | LL | } else if let Some(x) = Some(0) { | ____________^ +LL | | LL | | Some(x + 1) LL | | } else { LL | | None LL | | }; | |_____^ help: try: `{ Some(0).map(|x| x + 1) }` -error: aborting due to 21 previous errors +error: aborting due to 20 previous errors diff --git a/tests/ui/manual_map_option_2.fixed b/tests/ui/manual_map_option_2.fixed index f5bb4e0af1ba..d698cc74ea65 100644 --- a/tests/ui/manual_map_option_2.fixed +++ b/tests/ui/manual_map_option_2.fixed @@ -40,9 +40,14 @@ fn main() { None => None, }; - // Lint. `s` is captured by reference, so no lifetime issues. let s = Some(String::new()); + // Lint. `s` is captured by reference, so no lifetime issues. let _ = s.as_ref().map(|x| { if let Some(ref s) = s { (x.clone(), s) } else { panic!() } }); + // Don't lint this, type of `s` is coercioned from `&String` to `&str` + let x: Option<(String, &str)> = match &s { + Some(x) => Some({ if let Some(ref s) = s { (x.clone(), s) } else { panic!() } }), + None => None, + }; // Issue #7820 unsafe fn f(x: u32) -> u32 { @@ -54,3 +59,87 @@ fn main() { let _ = Some(0).map(|x| unsafe { f(x) }); let _ = Some(0).map(|x| unsafe { f(x) }); } + +// issue #12659 +mod with_type_coercion { + trait DummyTrait {} + + fn foo Result>(f: F) { + // Don't lint + let _: Option, ()>> = match Some(0) { + Some(_) => Some(match f() { + Ok(res) => Ok(Box::new(res)), + _ => Err(()), + }), + None => None, + }; + + let _: Option> = match Some(()) { + Some(_) => Some(Box::new(b"1234")), + None => None, + }; + + let x = String::new(); + let _: Option> = match Some(()) { + Some(_) => Some(Box::new(&x)), + None => None, + }; + + let _: Option<&str> = match Some(()) { + Some(_) => Some(&x), + None => None, + }; + + let _ = Some(0).map(|_| match f() { + Ok(res) => Ok(Box::new(res)), + _ => Err(()), + }); + } + + #[allow(clippy::redundant_allocation)] + fn bar() { + fn f(_: Option>) {} + fn g(b: &[u8]) -> Box<&[u8]> { + Box::new(b) + } + + let x: &[u8; 4] = b"1234"; + f(match Some(()) { + Some(_) => Some(Box::new(x)), + None => None, + }); + + let _: Option> = Some(0).map(|_| g(x)); + } + + fn with_fn_ret(s: &Option) -> Option<(String, &str)> { + // Don't lint, `map` doesn't work as the return type is adjusted. + match s { + Some(x) => Some({ if let Some(ref s) = s { (x.clone(), s) } else { panic!() } }), + None => None, + } + } + + fn with_fn_ret_2(s: &Option) -> Option<(String, &str)> { + if true { + // Don't lint, `map` doesn't work as the return type is adjusted. + return match s { + Some(x) => Some({ if let Some(ref s) = s { (x.clone(), s) } else { panic!() } }), + None => None, + }; + } + None + } + + #[allow(clippy::needless_late_init)] + fn with_fn_ret_3<'a>(s: &'a Option) -> Option<(String, &'a str)> { + let x: Option<(String, &'a str)>; + x = { + match s { + Some(x) => Some({ if let Some(ref s) = s { (x.clone(), s) } else { panic!() } }), + None => None, + } + }; + x + } +} diff --git a/tests/ui/manual_map_option_2.rs b/tests/ui/manual_map_option_2.rs index cbc2356e0a2d..069c2381f6db 100644 --- a/tests/ui/manual_map_option_2.rs +++ b/tests/ui/manual_map_option_2.rs @@ -4,6 +4,7 @@ fn main() { // Lint. `y` is declared within the arm, so it isn't captured by the map closure let _ = match Some(0) { + //~^ manual_map Some(x) => Some({ let y = (String::new(), String::new()); (x, y.0) @@ -43,9 +44,15 @@ fn main() { None => None, }; - // Lint. `s` is captured by reference, so no lifetime issues. let s = Some(String::new()); + // Lint. `s` is captured by reference, so no lifetime issues. let _ = match &s { + //~^ manual_map + Some(x) => Some({ if let Some(ref s) = s { (x.clone(), s) } else { panic!() } }), + None => None, + }; + // Don't lint this, type of `s` is coercioned from `&String` to `&str` + let x: Option<(String, &str)> = match &s { Some(x) => Some({ if let Some(ref s) = s { (x.clone(), s) } else { panic!() } }), None => None, }; @@ -56,16 +63,111 @@ fn main() { } unsafe { let _ = match Some(0) { + //~^ manual_map Some(x) => Some(f(x)), None => None, }; } let _ = match Some(0) { + //~^ manual_map Some(x) => unsafe { Some(f(x)) }, None => None, }; let _ = match Some(0) { + //~^ manual_map Some(x) => Some(unsafe { f(x) }), None => None, }; } + +// issue #12659 +mod with_type_coercion { + trait DummyTrait {} + + fn foo Result>(f: F) { + // Don't lint + let _: Option, ()>> = match Some(0) { + Some(_) => Some(match f() { + Ok(res) => Ok(Box::new(res)), + _ => Err(()), + }), + None => None, + }; + + let _: Option> = match Some(()) { + Some(_) => Some(Box::new(b"1234")), + None => None, + }; + + let x = String::new(); + let _: Option> = match Some(()) { + Some(_) => Some(Box::new(&x)), + None => None, + }; + + let _: Option<&str> = match Some(()) { + Some(_) => Some(&x), + None => None, + }; + + let _ = match Some(0) { + //~^ manual_map + Some(_) => Some(match f() { + Ok(res) => Ok(Box::new(res)), + _ => Err(()), + }), + None => None, + }; + } + + #[allow(clippy::redundant_allocation)] + fn bar() { + fn f(_: Option>) {} + fn g(b: &[u8]) -> Box<&[u8]> { + Box::new(b) + } + + let x: &[u8; 4] = b"1234"; + f(match Some(()) { + Some(_) => Some(Box::new(x)), + None => None, + }); + + let _: Option> = match Some(0) { + //~^ manual_map + Some(_) => Some(g(x)), + None => None, + }; + } + + fn with_fn_ret(s: &Option) -> Option<(String, &str)> { + // Don't lint, `map` doesn't work as the return type is adjusted. + match s { + Some(x) => Some({ if let Some(ref s) = s { (x.clone(), s) } else { panic!() } }), + None => None, + } + } + + fn with_fn_ret_2(s: &Option) -> Option<(String, &str)> { + if true { + // Don't lint, `map` doesn't work as the return type is adjusted. + return match s { + Some(x) => Some({ if let Some(ref s) = s { (x.clone(), s) } else { panic!() } }), + None => None, + }; + } + None + } + + #[allow(clippy::needless_late_init)] + fn with_fn_ret_3<'a>(s: &'a Option) -> Option<(String, &'a str)> { + let x: Option<(String, &'a str)>; + x = { + match s { + Some(x) => Some({ if let Some(ref s) = s { (x.clone(), s) } else { panic!() } }), + None => None, + } + }; + x + } +} diff --git a/tests/ui/manual_map_option_2.stderr b/tests/ui/manual_map_option_2.stderr index 78e4677544bc..c9e040ce1d0e 100644 --- a/tests/ui/manual_map_option_2.stderr +++ b/tests/ui/manual_map_option_2.stderr @@ -3,10 +3,10 @@ error: manual implementation of `Option::map` | LL | let _ = match Some(0) { | _____________^ +LL | | LL | | Some(x) => Some({ LL | | let y = (String::new(), String::new()); -LL | | (x, y.0) -LL | | }), +... | LL | | None => None, LL | | }; | |_____^ @@ -22,44 +22,80 @@ LL ~ }); | error: manual implementation of `Option::map` - --> tests/ui/manual_map_option_2.rs:48:13 + --> tests/ui/manual_map_option_2.rs:49:13 | LL | let _ = match &s { | _____________^ +LL | | LL | | Some(x) => Some({ if let Some(ref s) = s { (x.clone(), s) } else { panic!() } }), LL | | None => None, LL | | }; | |_____^ help: try: `s.as_ref().map(|x| { if let Some(ref s) = s { (x.clone(), s) } else { panic!() } })` error: manual implementation of `Option::map` - --> tests/ui/manual_map_option_2.rs:58:17 + --> tests/ui/manual_map_option_2.rs:65:17 | LL | let _ = match Some(0) { | _________________^ +LL | | LL | | Some(x) => Some(f(x)), LL | | None => None, LL | | }; | |_________^ help: try: `Some(0).map(|x| f(x))` error: manual implementation of `Option::map` - --> tests/ui/manual_map_option_2.rs:63:13 + --> tests/ui/manual_map_option_2.rs:71:13 | LL | let _ = match Some(0) { | _____________^ +LL | | LL | | Some(x) => unsafe { Some(f(x)) }, LL | | None => None, LL | | }; | |_____^ help: try: `Some(0).map(|x| unsafe { f(x) })` error: manual implementation of `Option::map` - --> tests/ui/manual_map_option_2.rs:67:13 + --> tests/ui/manual_map_option_2.rs:76:13 | LL | let _ = match Some(0) { | _____________^ +LL | | LL | | Some(x) => Some(unsafe { f(x) }), LL | | None => None, LL | | }; | |_____^ help: try: `Some(0).map(|x| unsafe { f(x) })` -error: aborting due to 5 previous errors +error: manual implementation of `Option::map` + --> tests/ui/manual_map_option_2.rs:113:17 + | +LL | let _ = match Some(0) { + | _________________^ +LL | | +LL | | Some(_) => Some(match f() { +LL | | Ok(res) => Ok(Box::new(res)), +... | +LL | | None => None, +LL | | }; + | |_________^ + | +help: try + | +LL ~ let _ = Some(0).map(|_| match f() { +LL + Ok(res) => Ok(Box::new(res)), +LL + _ => Err(()), +LL ~ }); + | + +error: manual implementation of `Option::map` + --> tests/ui/manual_map_option_2.rs:136:37 + | +LL | let _: Option> = match Some(0) { + | _____________________________________^ +LL | | +LL | | Some(_) => Some(g(x)), +LL | | None => None, +LL | | }; + | |_________^ help: try: `Some(0).map(|_| g(x))` + +error: aborting due to 7 previous errors diff --git a/tests/ui/manual_memcpy/with_loop_counters.rs b/tests/ui/manual_memcpy/with_loop_counters.rs index 786d7e6e2445..c83a26cab21a 100644 --- a/tests/ui/manual_memcpy/with_loop_counters.rs +++ b/tests/ui/manual_memcpy/with_loop_counters.rs @@ -3,57 +3,64 @@ pub fn manual_copy_with_counters(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { let mut count = 0; for i in 3..src.len() { - //~^ ERROR: it looks like you're manually copying between slices - //~| NOTE: `-D clippy::manual-memcpy` implied by `-D warnings` + //~^ manual_memcpy + dst[i] = src[count]; count += 1; } let mut count = 0; for i in 3..src.len() { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[count] = src[i]; count += 1; } let mut count = 3; for i in 0..src.len() { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[count] = src[i]; count += 1; } let mut count = 3; for i in 0..src.len() { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[i] = src[count]; count += 1; } let mut count = 0; for i in 3..(3 + src.len()) { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[i] = src[count]; count += 1; } let mut count = 3; for i in 5..src.len() { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[i] = src[count - 2]; count += 1; } let mut count = 2; for i in 0..dst.len() { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[i] = src[count]; count += 1; } let mut count = 5; for i in 3..10 { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[i] = src[count]; count += 1; } @@ -61,7 +68,8 @@ pub fn manual_copy_with_counters(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) let mut count = 3; let mut count2 = 30; for i in 0..src.len() { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[count] = src[i]; dst2[count2] = src[i]; count += 1; @@ -72,7 +80,8 @@ pub fn manual_copy_with_counters(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) // arithmetic ones let mut count = 0 << 1; for i in 0..1 << 1 { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[count] = src[i + 2]; count += 1; } @@ -80,7 +89,8 @@ pub fn manual_copy_with_counters(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) // make sure incrementing expressions without semicolons at the end of loops are handled correctly. let mut count = 0; for i in 3..src.len() { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[i] = src[count]; count += 1 } diff --git a/tests/ui/manual_memcpy/with_loop_counters.stderr b/tests/ui/manual_memcpy/with_loop_counters.stderr index 41a991e9688f..70da8309f398 100644 --- a/tests/ui/manual_memcpy/with_loop_counters.stderr +++ b/tests/ui/manual_memcpy/with_loop_counters.stderr @@ -17,79 +17,86 @@ error: it looks like you're manually copying between slices | LL | / for i in 3..src.len() { LL | | +LL | | LL | | dst[count] = src[i]; LL | | count += 1; LL | | } | |_____^ help: try replacing the loop by: `dst[..(src.len() - 3)].copy_from_slice(&src[3..]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:20:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:21:5 | LL | / for i in 0..src.len() { LL | | +LL | | LL | | dst[count] = src[i]; LL | | count += 1; LL | | } | |_____^ help: try replacing the loop by: `dst[3..(src.len() + 3)].copy_from_slice(&src[..]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:27:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:29:5 | LL | / for i in 0..src.len() { LL | | +LL | | LL | | dst[i] = src[count]; LL | | count += 1; LL | | } | |_____^ help: try replacing the loop by: `dst[..src.len()].copy_from_slice(&src[3..(src.len() + 3)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:34:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:37:5 | LL | / for i in 3..(3 + src.len()) { LL | | +LL | | LL | | dst[i] = src[count]; LL | | count += 1; LL | | } | |_____^ help: try replacing the loop by: `dst[3..(3 + src.len())].copy_from_slice(&src[..(3 + src.len() - 3)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:41:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:45:5 | LL | / for i in 5..src.len() { LL | | +LL | | LL | | dst[i] = src[count - 2]; LL | | count += 1; LL | | } | |_____^ help: try replacing the loop by: `dst[5..src.len()].copy_from_slice(&src[(3 - 2)..((src.len() - 2) + 3 - 5)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:48:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:53:5 | LL | / for i in 0..dst.len() { LL | | +LL | | LL | | dst[i] = src[count]; LL | | count += 1; LL | | } | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[2..(dst.len() + 2)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:55:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:61:5 | LL | / for i in 3..10 { LL | | +LL | | LL | | dst[i] = src[count]; LL | | count += 1; LL | | } | |_____^ help: try replacing the loop by: `dst[3..10].copy_from_slice(&src[5..(10 + 5 - 3)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:63:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:70:5 | LL | / for i in 0..src.len() { LL | | +LL | | LL | | dst[count] = src[i]; -LL | | dst2[count2] = src[i]; -LL | | count += 1; +... | LL | | count2 += 1; LL | | } | |_____^ @@ -101,20 +108,22 @@ LL + dst2[30..(src.len() + 30)].copy_from_slice(&src[..]); | error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:74:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:82:5 | LL | / for i in 0..1 << 1 { LL | | +LL | | LL | | dst[count] = src[i + 2]; LL | | count += 1; LL | | } | |_____^ help: try replacing the loop by: `dst[(0 << 1)..((1 << 1) + (0 << 1))].copy_from_slice(&src[2..((1 << 1) + 2)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/with_loop_counters.rs:82:5 + --> tests/ui/manual_memcpy/with_loop_counters.rs:91:5 | LL | / for i in 3..src.len() { LL | | +LL | | LL | | dst[i] = src[count]; LL | | count += 1 LL | | } diff --git a/tests/ui/manual_memcpy/without_loop_counters.rs b/tests/ui/manual_memcpy/without_loop_counters.rs index 2f8640cd3f50..a3b8763812d7 100644 --- a/tests/ui/manual_memcpy/without_loop_counters.rs +++ b/tests/ui/manual_memcpy/without_loop_counters.rs @@ -12,32 +12,36 @@ const LOOP_OFFSET: usize = 5000; pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { // plain manual memcpy for i in 0..src.len() { - //~^ ERROR: it looks like you're manually copying between slices - //~| NOTE: `-D clippy::manual-memcpy` implied by `-D warnings` + //~^ manual_memcpy + dst[i] = src[i]; } // dst offset memcpy for i in 0..src.len() { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[i + 10] = src[i]; } // src offset memcpy for i in 0..src.len() { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[i] = src[i + 10]; } // src offset memcpy for i in 11..src.len() { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[i] = src[i - 10]; } // overwrite entire dst for i in 0..dst.len() { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[i] = src[i]; } @@ -51,7 +55,8 @@ pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { // multiple copies - suggest two memcpy statements for i in 10..256 { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[i] = src[i - 5]; dst2[i + 500] = src[i] } @@ -64,7 +69,8 @@ pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { let some_var = 5; // Offset in variable for i in 10..LOOP_OFFSET { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[i + LOOP_OFFSET] = src[i - some_var]; } @@ -78,7 +84,8 @@ pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { // make sure vectors are supported for i in 0..src_vec.len() { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst_vec[i] = src_vec[i]; } @@ -108,24 +115,28 @@ pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { let from = 1; for i in from..from + src.len() { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[i] = src[i - from]; } for i in from..from + 3 { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[i] = src[i - from]; } #[allow(clippy::identity_op)] for i in 0..5 { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[i - 0] = src[i]; } #[allow(clippy::reversed_empty_ranges)] for i in 0..0 { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[i] = src[i]; } @@ -149,19 +160,22 @@ pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { let src = [0, 1, 2, 3, 4]; let mut dst = [0; 4]; for i in 0..4 { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[i] = src[i]; } let mut dst = [0; 6]; for i in 0..5 { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[i] = src[i]; } let mut dst = [0; 5]; for i in 0..5 { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[i] = src[i]; } @@ -208,13 +222,15 @@ pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { let src = [[0; 5]; 5]; let mut dst = [0; 5]; for i in 0..5 { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[i] = src[0][i]; } let src = [[[0; 5]; 5]; 5]; for i in 0..5 { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[i] = src[0][1][i]; } } @@ -222,7 +238,8 @@ pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { #[warn(clippy::needless_range_loop, clippy::manual_memcpy)] pub fn manual_clone(src: &[String], dst: &mut [String]) { for i in 0..src.len() { - //~^ ERROR: it looks like you're manually copying between slices + //~^ manual_memcpy + dst[i] = src[i].clone(); } } diff --git a/tests/ui/manual_memcpy/without_loop_counters.stderr b/tests/ui/manual_memcpy/without_loop_counters.stderr index c881e3fac769..0e656dcbc63a 100644 --- a/tests/ui/manual_memcpy/without_loop_counters.stderr +++ b/tests/ui/manual_memcpy/without_loop_counters.stderr @@ -16,42 +16,47 @@ error: it looks like you're manually copying between slices | LL | / for i in 0..src.len() { LL | | +LL | | LL | | dst[i + 10] = src[i]; LL | | } | |_____^ help: try replacing the loop by: `dst[10..(src.len() + 10)].copy_from_slice(&src[..]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:27:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:28:5 | LL | / for i in 0..src.len() { LL | | +LL | | LL | | dst[i] = src[i + 10]; LL | | } | |_____^ help: try replacing the loop by: `dst[..src.len()].copy_from_slice(&src[10..(src.len() + 10)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:33:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:35:5 | LL | / for i in 11..src.len() { LL | | +LL | | LL | | dst[i] = src[i - 10]; LL | | } | |_____^ help: try replacing the loop by: `dst[11..src.len()].copy_from_slice(&src[(11 - 10)..(src.len() - 10)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:39:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:42:5 | LL | / for i in 0..dst.len() { LL | | +LL | | LL | | dst[i] = src[i]; LL | | } | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[..dst.len()]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:53:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:57:5 | LL | / for i in 10..256 { LL | | +LL | | LL | | dst[i] = src[i - 5]; LL | | dst2[i + 500] = src[i] LL | | } @@ -64,109 +69,121 @@ LL + dst2[(10 + 500)..(256 + 500)].copy_from_slice(&src[10..256]); | error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:66:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:71:5 | LL | / for i in 10..LOOP_OFFSET { LL | | +LL | | LL | | dst[i + LOOP_OFFSET] = src[i - some_var]; LL | | } | |_____^ help: try replacing the loop by: `dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].copy_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:80:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:86:5 | LL | / for i in 0..src_vec.len() { LL | | +LL | | LL | | dst_vec[i] = src_vec[i]; LL | | } | |_____^ help: try replacing the loop by: `dst_vec[..src_vec.len()].copy_from_slice(&src_vec[..]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:110:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:117:5 | LL | / for i in from..from + src.len() { LL | | +LL | | LL | | dst[i] = src[i - from]; LL | | } | |_____^ help: try replacing the loop by: `dst[from..(from + src.len())].copy_from_slice(&src[..(from + src.len() - from)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:115:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:123:5 | LL | / for i in from..from + 3 { LL | | +LL | | LL | | dst[i] = src[i - from]; LL | | } | |_____^ help: try replacing the loop by: `dst[from..(from + 3)].copy_from_slice(&src[..(from + 3 - from)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:121:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:130:5 | LL | / for i in 0..5 { LL | | +LL | | LL | | dst[i - 0] = src[i]; LL | | } | |_____^ help: try replacing the loop by: `dst[..5].copy_from_slice(&src);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:127:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:137:5 | LL | / for i in 0..0 { LL | | +LL | | LL | | dst[i] = src[i]; LL | | } | |_____^ help: try replacing the loop by: `dst[..0].copy_from_slice(&src[..0]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:151:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:162:5 | LL | / for i in 0..4 { LL | | +LL | | LL | | dst[i] = src[i]; LL | | } | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[..4]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:157:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:169:5 | LL | / for i in 0..5 { LL | | +LL | | LL | | dst[i] = src[i]; LL | | } | |_____^ help: try replacing the loop by: `dst[..5].copy_from_slice(&src);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:163:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:176:5 | LL | / for i in 0..5 { LL | | +LL | | LL | | dst[i] = src[i]; LL | | } | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:210:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:224:5 | LL | / for i in 0..5 { LL | | +LL | | LL | | dst[i] = src[0][i]; LL | | } | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[0]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:216:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:231:5 | LL | / for i in 0..5 { LL | | +LL | | LL | | dst[i] = src[0][1][i]; LL | | } | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[0][1]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:224:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:240:5 | LL | / for i in 0..src.len() { LL | | +LL | | LL | | dst[i] = src[i].clone(); LL | | } | |_____^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..]);` diff --git a/tests/ui/manual_midpoint.fixed b/tests/ui/manual_midpoint.fixed new file mode 100644 index 000000000000..63116ced8438 --- /dev/null +++ b/tests/ui/manual_midpoint.fixed @@ -0,0 +1,74 @@ +#![warn(clippy::manual_midpoint)] + +macro_rules! mac { + ($a: expr, $b: expr) => { + ($a + $b) / 2 + }; +} + +macro_rules! add { + ($a: expr, $b: expr) => { + ($a + $b) + }; +} + +macro_rules! two { + () => { + 2 + }; +} + +#[clippy::msrv = "1.84"] +fn older_msrv() { + let a: u32 = 10; + let _ = (a + 5) / 2; +} + +#[clippy::msrv = "1.85"] +fn main() { + let a: u32 = 10; + let _ = u32::midpoint(a, 5); //~ ERROR: manual implementation of `midpoint` + + let f: f32 = 10.0; + let _ = f32::midpoint(f, 5.0); //~ ERROR: manual implementation of `midpoint` + + let _: u32 = 5 + u32::midpoint(8, 8) + 2; //~ ERROR: manual implementation of `midpoint` + let _: u32 = const { u32::midpoint(8, 8) }; //~ ERROR: manual implementation of `midpoint` + let _: f64 = const { f64::midpoint(8.0f64, 8.) }; //~ ERROR: manual implementation of `midpoint` + let _: u32 = u32::midpoint(u32::default(), u32::default()); //~ ERROR: manual implementation of `midpoint` + let _: u32 = u32::midpoint(two!(), two!()); //~ ERROR: manual implementation of `midpoint` + + // Do not lint in presence of an addition with more than 2 operands + let _: u32 = (10 + 20 + 30) / 2; + + // Do not lint if whole or part is coming from a macro + let _ = mac!(10, 20); + let _: u32 = add!(10u32, 20u32) / 2; + let _: u32 = (10 + 20) / two!(); + + // Do not lint if a literal is not present + let _ = (f + 5.0) / (1.0 + 1.0); + + // Do not lint on signed integer types + let i: i32 = 10; + let _ = (i + 5) / 2; + + // Do not lint on (x+1)/2 or (1+x)/2 as this looks more like a `div_ceil()` operation + let _ = (i + 1) / 2; + let _ = (1 + i) / 2; + + // But if we see (x+1.0)/2.0 or (x+1.0)/2.0, it is probably a midpoint operation + let _ = f32::midpoint(f, 1.0); //~ ERROR: manual implementation of `midpoint` + let _ = f32::midpoint(1.0, f); //~ ERROR: manual implementation of `midpoint` +} + +#[clippy::msrv = "1.86"] +fn older_signed_midpoint(i: i32) { + // Do not lint + let _ = (i + 10) / 2; +} + +#[clippy::msrv = "1.87"] +fn signed_midpoint(i: i32) { + let _ = i32::midpoint(i, 10); //~ ERROR: manual implementation of `midpoint` +} diff --git a/tests/ui/manual_midpoint.rs b/tests/ui/manual_midpoint.rs new file mode 100644 index 000000000000..47f1b88c78cd --- /dev/null +++ b/tests/ui/manual_midpoint.rs @@ -0,0 +1,74 @@ +#![warn(clippy::manual_midpoint)] + +macro_rules! mac { + ($a: expr, $b: expr) => { + ($a + $b) / 2 + }; +} + +macro_rules! add { + ($a: expr, $b: expr) => { + ($a + $b) + }; +} + +macro_rules! two { + () => { + 2 + }; +} + +#[clippy::msrv = "1.84"] +fn older_msrv() { + let a: u32 = 10; + let _ = (a + 5) / 2; +} + +#[clippy::msrv = "1.85"] +fn main() { + let a: u32 = 10; + let _ = (a + 5) / 2; //~ ERROR: manual implementation of `midpoint` + + let f: f32 = 10.0; + let _ = (f + 5.0) / 2.0; //~ ERROR: manual implementation of `midpoint` + + let _: u32 = 5 + (8 + 8) / 2 + 2; //~ ERROR: manual implementation of `midpoint` + let _: u32 = const { (8 + 8) / 2 }; //~ ERROR: manual implementation of `midpoint` + let _: f64 = const { (8.0f64 + 8.) / 2. }; //~ ERROR: manual implementation of `midpoint` + let _: u32 = (u32::default() + u32::default()) / 2; //~ ERROR: manual implementation of `midpoint` + let _: u32 = (two!() + two!()) / 2; //~ ERROR: manual implementation of `midpoint` + + // Do not lint in presence of an addition with more than 2 operands + let _: u32 = (10 + 20 + 30) / 2; + + // Do not lint if whole or part is coming from a macro + let _ = mac!(10, 20); + let _: u32 = add!(10u32, 20u32) / 2; + let _: u32 = (10 + 20) / two!(); + + // Do not lint if a literal is not present + let _ = (f + 5.0) / (1.0 + 1.0); + + // Do not lint on signed integer types + let i: i32 = 10; + let _ = (i + 5) / 2; + + // Do not lint on (x+1)/2 or (1+x)/2 as this looks more like a `div_ceil()` operation + let _ = (i + 1) / 2; + let _ = (1 + i) / 2; + + // But if we see (x+1.0)/2.0 or (x+1.0)/2.0, it is probably a midpoint operation + let _ = (f + 1.0) / 2.0; //~ ERROR: manual implementation of `midpoint` + let _ = (1.0 + f) / 2.0; //~ ERROR: manual implementation of `midpoint` +} + +#[clippy::msrv = "1.86"] +fn older_signed_midpoint(i: i32) { + // Do not lint + let _ = (i + 10) / 2; +} + +#[clippy::msrv = "1.87"] +fn signed_midpoint(i: i32) { + let _ = (i + 10) / 2; //~ ERROR: manual implementation of `midpoint` +} diff --git a/tests/ui/manual_midpoint.stderr b/tests/ui/manual_midpoint.stderr new file mode 100644 index 000000000000..3d588e2114df --- /dev/null +++ b/tests/ui/manual_midpoint.stderr @@ -0,0 +1,65 @@ +error: manual implementation of `midpoint` which can overflow + --> tests/ui/manual_midpoint.rs:30:13 + | +LL | let _ = (a + 5) / 2; + | ^^^^^^^^^^^ help: use `u32::midpoint` instead: `u32::midpoint(a, 5)` + | + = note: `-D clippy::manual-midpoint` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_midpoint)]` + +error: manual implementation of `midpoint` which can overflow + --> tests/ui/manual_midpoint.rs:33:13 + | +LL | let _ = (f + 5.0) / 2.0; + | ^^^^^^^^^^^^^^^ help: use `f32::midpoint` instead: `f32::midpoint(f, 5.0)` + +error: manual implementation of `midpoint` which can overflow + --> tests/ui/manual_midpoint.rs:35:22 + | +LL | let _: u32 = 5 + (8 + 8) / 2 + 2; + | ^^^^^^^^^^^ help: use `u32::midpoint` instead: `u32::midpoint(8, 8)` + +error: manual implementation of `midpoint` which can overflow + --> tests/ui/manual_midpoint.rs:36:26 + | +LL | let _: u32 = const { (8 + 8) / 2 }; + | ^^^^^^^^^^^ help: use `u32::midpoint` instead: `u32::midpoint(8, 8)` + +error: manual implementation of `midpoint` which can overflow + --> tests/ui/manual_midpoint.rs:37:26 + | +LL | let _: f64 = const { (8.0f64 + 8.) / 2. }; + | ^^^^^^^^^^^^^^^^^^ help: use `f64::midpoint` instead: `f64::midpoint(8.0f64, 8.)` + +error: manual implementation of `midpoint` which can overflow + --> tests/ui/manual_midpoint.rs:38:18 + | +LL | let _: u32 = (u32::default() + u32::default()) / 2; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `u32::midpoint` instead: `u32::midpoint(u32::default(), u32::default())` + +error: manual implementation of `midpoint` which can overflow + --> tests/ui/manual_midpoint.rs:39:18 + | +LL | let _: u32 = (two!() + two!()) / 2; + | ^^^^^^^^^^^^^^^^^^^^^ help: use `u32::midpoint` instead: `u32::midpoint(two!(), two!())` + +error: manual implementation of `midpoint` which can overflow + --> tests/ui/manual_midpoint.rs:61:13 + | +LL | let _ = (f + 1.0) / 2.0; + | ^^^^^^^^^^^^^^^ help: use `f32::midpoint` instead: `f32::midpoint(f, 1.0)` + +error: manual implementation of `midpoint` which can overflow + --> tests/ui/manual_midpoint.rs:62:13 + | +LL | let _ = (1.0 + f) / 2.0; + | ^^^^^^^^^^^^^^^ help: use `f32::midpoint` instead: `f32::midpoint(1.0, f)` + +error: manual implementation of `midpoint` which can overflow + --> tests/ui/manual_midpoint.rs:73:13 + | +LL | let _ = (i + 10) / 2; + | ^^^^^^^^^^^^ help: use `i32::midpoint` instead: `i32::midpoint(i, 10)` + +error: aborting due to 10 previous errors + diff --git a/tests/ui/manual_next_back.fixed b/tests/ui/manual_next_back.fixed index 75828f355d90..153fbc6fd071 100644 --- a/tests/ui/manual_next_back.fixed +++ b/tests/ui/manual_next_back.fixed @@ -30,5 +30,7 @@ fn main() { // should lint let _ = (0..10).next_back().unwrap(); + //~^ manual_next_back let _ = "something".bytes().next_back(); + //~^ manual_next_back } diff --git a/tests/ui/manual_next_back.rs b/tests/ui/manual_next_back.rs index b980e90e1144..ca71d6a24773 100644 --- a/tests/ui/manual_next_back.rs +++ b/tests/ui/manual_next_back.rs @@ -30,5 +30,7 @@ fn main() { // should lint let _ = (0..10).rev().next().unwrap(); + //~^ manual_next_back let _ = "something".bytes().rev().next(); + //~^ manual_next_back } diff --git a/tests/ui/manual_next_back.stderr b/tests/ui/manual_next_back.stderr index c7e1ceca437c..4ac7b0d21244 100644 --- a/tests/ui/manual_next_back.stderr +++ b/tests/ui/manual_next_back.stderr @@ -8,7 +8,7 @@ LL | let _ = (0..10).rev().next().unwrap(); = help: to override `-D warnings` add `#[allow(clippy::manual_next_back)]` error: manual backwards iteration - --> tests/ui/manual_next_back.rs:33:32 + --> tests/ui/manual_next_back.rs:34:32 | LL | let _ = "something".bytes().rev().next(); | ^^^^^^^^^^^^^ help: use: `.next_back()` diff --git a/tests/ui/manual_non_exhaustive_enum.rs b/tests/ui/manual_non_exhaustive_enum.rs index ffe2bb924673..bb22165d478f 100644 --- a/tests/ui/manual_non_exhaustive_enum.rs +++ b/tests/ui/manual_non_exhaustive_enum.rs @@ -27,6 +27,7 @@ pub enum NoDocHidden { // name of variant with doc hidden does not start with underscore pub enum NoUnderscore { + //~^ manual_non_exhaustive A, B, #[doc(hidden)] diff --git a/tests/ui/manual_non_exhaustive_enum.stderr b/tests/ui/manual_non_exhaustive_enum.stderr index 0a9ac157f850..0f91f24b4a34 100644 --- a/tests/ui/manual_non_exhaustive_enum.stderr +++ b/tests/ui/manual_non_exhaustive_enum.stderr @@ -27,6 +27,7 @@ error: this seems like a manual implementation of the non-exhaustive pattern --> tests/ui/manual_non_exhaustive_enum.rs:29:1 | LL | / pub enum NoUnderscore { +LL | | LL | | A, LL | | B, LL | | #[doc(hidden)] @@ -35,7 +36,7 @@ LL | | } | |_^ | help: remove this variant - --> tests/ui/manual_non_exhaustive_enum.rs:33:5 + --> tests/ui/manual_non_exhaustive_enum.rs:34:5 | LL | C, | ^ diff --git a/tests/ui/manual_ok_err.fixed b/tests/ui/manual_ok_err.fixed index e7e0464c4787..bc169b64be9f 100644 --- a/tests/ui/manual_ok_err.fixed +++ b/tests/ui/manual_ok_err.fixed @@ -89,3 +89,12 @@ const fn cf(x: Result) -> Option { Err(_) => None, } } + +fn issue14239() { + let _ = if false { + None + } else { + "1".parse::().ok() + }; + //~^^^^^ manual_ok_err +} diff --git a/tests/ui/manual_ok_err.rs b/tests/ui/manual_ok_err.rs index 03ad773f47cf..03c730d4b4e4 100644 --- a/tests/ui/manual_ok_err.rs +++ b/tests/ui/manual_ok_err.rs @@ -31,6 +31,7 @@ fn main() { let _ = if let Ok(v) = funcall() { //~^ manual_ok_err + Some(v) } else { None @@ -38,6 +39,7 @@ fn main() { let _ = if let Err(v) = funcall() { //~^ manual_ok_err + Some(v) } else { None @@ -123,3 +125,14 @@ const fn cf(x: Result) -> Option { Err(_) => None, } } + +fn issue14239() { + let _ = if false { + None + } else if let Ok(n) = "1".parse::() { + Some(n) + } else { + None + }; + //~^^^^^ manual_ok_err +} diff --git a/tests/ui/manual_ok_err.stderr b/tests/ui/manual_ok_err.stderr index d0d5e2c81e96..13fceacda107 100644 --- a/tests/ui/manual_ok_err.stderr +++ b/tests/ui/manual_ok_err.stderr @@ -51,6 +51,7 @@ error: manual implementation of `ok` LL | let _ = if let Ok(v) = funcall() { | _____________^ LL | | +LL | | LL | | Some(v) LL | | } else { LL | | None @@ -58,11 +59,12 @@ LL | | }; | |_____^ help: replace with: `funcall().ok()` error: manual implementation of `err` - --> tests/ui/manual_ok_err.rs:39:13 + --> tests/ui/manual_ok_err.rs:40:13 | LL | let _ = if let Err(v) = funcall() { | _____________^ LL | | +LL | | LL | | Some(v) LL | | } else { LL | | None @@ -70,7 +72,7 @@ LL | | }; | |_____^ help: replace with: `funcall().err()` error: manual implementation of `ok` - --> tests/ui/manual_ok_err.rs:47:13 + --> tests/ui/manual_ok_err.rs:49:13 | LL | let _ = match funcall() { | _____________^ @@ -81,7 +83,7 @@ LL | | }; | |_____^ help: replace with: `funcall().ok()` error: manual implementation of `ok` - --> tests/ui/manual_ok_err.rs:64:13 + --> tests/ui/manual_ok_err.rs:66:13 | LL | let _ = match -S { | _____________^ @@ -91,5 +93,23 @@ LL | | _ => None, LL | | }; | |_____^ help: replace with: `(-S).ok()` -error: aborting due to 8 previous errors +error: manual implementation of `ok` + --> tests/ui/manual_ok_err.rs:132:12 + | +LL | } else if let Ok(n) = "1".parse::() { + | ____________^ +LL | | Some(n) +LL | | } else { +LL | | None +LL | | }; + | |_____^ + | +help: replace with + | +LL ~ } else { +LL + "1".parse::().ok() +LL ~ }; + | + +error: aborting due to 9 previous errors diff --git a/tests/ui/manual_ok_or.fixed b/tests/ui/manual_ok_or.fixed index cc53cb416a22..f326822149cd 100644 --- a/tests/ui/manual_ok_or.fixed +++ b/tests/ui/manual_ok_or.fixed @@ -9,12 +9,15 @@ fn main() { // basic case let foo: Option = None; foo.ok_or("error"); + //~^ manual_ok_or // eta expansion case foo.ok_or("error"); + //~^ manual_ok_or // turbo fish syntax None::.ok_or("error"); + //~^ manual_ok_or // multiline case #[rustfmt::skip] diff --git a/tests/ui/manual_ok_or.rs b/tests/ui/manual_ok_or.rs index 39c61a1e490f..7d065eda0ea1 100644 --- a/tests/ui/manual_ok_or.rs +++ b/tests/ui/manual_ok_or.rs @@ -9,16 +9,20 @@ fn main() { // basic case let foo: Option = None; foo.map_or(Err("error"), |v| Ok(v)); + //~^ manual_ok_or // eta expansion case foo.map_or(Err("error"), Ok); + //~^ manual_ok_or // turbo fish syntax None::.map_or(Err("error"), |v| Ok(v)); + //~^ manual_ok_or // multiline case #[rustfmt::skip] foo.map_or(Err::( + //~^ manual_ok_or &format!( "{}{}{}{}{}{}{}", "Alice", "Bob", "Sarah", "Marc", "Sandra", "Eric", "Jenifer") diff --git a/tests/ui/manual_ok_or.stderr b/tests/ui/manual_ok_or.stderr index 2441a75b5c46..e8176f4c31fa 100644 --- a/tests/ui/manual_ok_or.stderr +++ b/tests/ui/manual_ok_or.stderr @@ -8,34 +8,25 @@ LL | foo.map_or(Err("error"), |v| Ok(v)); = help: to override `-D warnings` add `#[allow(clippy::manual_ok_or)]` error: this pattern reimplements `Option::ok_or` - --> tests/ui/manual_ok_or.rs:14:5 + --> tests/ui/manual_ok_or.rs:15:5 | LL | foo.map_or(Err("error"), Ok); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `foo.ok_or("error")` -error: called `map_or(Err(_), Ok)` on an `Option` value - --> tests/ui/manual_ok_or.rs:14:5 - | -LL | foo.map_or(Err("error"), Ok); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `ok_or`: `foo.ok_or("error")` - | - = note: `-D clippy::option-map-or-err-ok` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::option_map_or_err_ok)]` - error: this pattern reimplements `Option::ok_or` - --> tests/ui/manual_ok_or.rs:17:5 + --> tests/ui/manual_ok_or.rs:19:5 | LL | None::.map_or(Err("error"), |v| Ok(v)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `None::.ok_or("error")` error: this pattern reimplements `Option::ok_or` - --> tests/ui/manual_ok_or.rs:21:5 + --> tests/ui/manual_ok_or.rs:24:5 | LL | / foo.map_or(Err::( +LL | | LL | | &format!( LL | | "{}{}{}{}{}{}{}", -LL | | "Alice", "Bob", "Sarah", "Marc", "Sandra", "Eric", "Jenifer") -LL | | ), +... | LL | | |v| Ok(v), LL | | ); | |_____^ @@ -47,5 +38,5 @@ LL + "{}{}{}{}{}{}{}", LL ~ "Alice", "Bob", "Sarah", "Marc", "Sandra", "Eric", "Jenifer")); | -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/manual_option_as_slice.rs b/tests/ui/manual_option_as_slice.rs index 561a8b534014..e1a97a6b2711 100644 --- a/tests/ui/manual_option_as_slice.rs +++ b/tests/ui/manual_option_as_slice.rs @@ -10,6 +10,7 @@ fn check(x: Option) { _ = if let Some(f) = x.as_ref() { //~^ manual_option_as_slice + std::slice::from_ref(f) } else { &[] diff --git a/tests/ui/manual_option_as_slice.stderr b/tests/ui/manual_option_as_slice.stderr index 569269d3e2b7..e240ae8eb7d9 100644 --- a/tests/ui/manual_option_as_slice.stderr +++ b/tests/ui/manual_option_as_slice.stderr @@ -18,6 +18,7 @@ error: use `Option::as_slice` LL | _ = if let Some(f) = x.as_ref() { | _________^ LL | | +LL | | LL | | std::slice::from_ref(f) LL | | } else { LL | | &[] @@ -25,31 +26,31 @@ LL | | }; | |_____^ help: use: `x.as_slice()` error: use `Option::as_slice` - --> tests/ui/manual_option_as_slice.rs:18:9 + --> tests/ui/manual_option_as_slice.rs:19:9 | LL | _ = x.as_ref().map_or(&[][..], std::slice::from_ref); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.as_slice()` error: use `Option::as_slice` - --> tests/ui/manual_option_as_slice.rs:21:9 + --> tests/ui/manual_option_as_slice.rs:22:9 | LL | _ = x.as_ref().map_or_else(Default::default, std::slice::from_ref); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.as_slice()` error: use `Option::as_slice` - --> tests/ui/manual_option_as_slice.rs:24:9 + --> tests/ui/manual_option_as_slice.rs:25:9 | LL | _ = x.as_ref().map(std::slice::from_ref).unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.as_slice()` error: use `Option::as_slice` - --> tests/ui/manual_option_as_slice.rs:27:9 + --> tests/ui/manual_option_as_slice.rs:28:9 | LL | _ = x.as_ref().map_or_else(|| &[42][..0], std::slice::from_ref); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.as_slice()` error: use `Option::as_slice` - --> tests/ui/manual_option_as_slice.rs:32:13 + --> tests/ui/manual_option_as_slice.rs:33:13 | LL | _ = x.as_ref().map_or_else(<&[_]>::default, from_ref); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.as_slice()` diff --git a/tests/ui/manual_pattern_char_comparison.fixed b/tests/ui/manual_pattern_char_comparison.fixed index 03e621d95ba1..b03e83e6b99d 100644 --- a/tests/ui/manual_pattern_char_comparison.fixed +++ b/tests/ui/manual_pattern_char_comparison.fixed @@ -9,16 +9,25 @@ impl NotStr { fn main() { let sentence = "Hello, world!"; sentence.trim_end_matches(['.', ',', '!', '?']); + //~^ manual_pattern_char_comparison sentence.split(['\n', 'X']); + //~^ manual_pattern_char_comparison sentence.split(['\n', 'X']); + //~^ manual_pattern_char_comparison sentence.splitn(3, 'X'); + //~^ manual_pattern_char_comparison sentence.splitn(3, |c: char| c.is_whitespace() || c == 'X'); let char_compare = 'X'; sentence.splitn(3, char_compare); + //~^ manual_pattern_char_comparison sentence.split(['\n', 'X', 'Y']); + //~^ manual_pattern_char_comparison sentence.splitn(3, 'X'); + //~^ manual_pattern_char_comparison sentence.splitn(3, ['X', 'W']); + //~^ manual_pattern_char_comparison sentence.find('🎈'); + //~^ manual_pattern_char_comparison let not_str = NotStr; not_str.find(|c: char| c == 'X'); @@ -58,4 +67,5 @@ fn msrv_1_57() { fn msrv_1_58() { let sentence = "Hello, world!"; sentence.trim_end_matches(['.', ',', '!', '?']); + //~^ manual_pattern_char_comparison } diff --git a/tests/ui/manual_pattern_char_comparison.rs b/tests/ui/manual_pattern_char_comparison.rs index 43e883cd325a..451480df4225 100644 --- a/tests/ui/manual_pattern_char_comparison.rs +++ b/tests/ui/manual_pattern_char_comparison.rs @@ -9,16 +9,25 @@ impl NotStr { fn main() { let sentence = "Hello, world!"; sentence.trim_end_matches(|c: char| c == '.' || c == ',' || c == '!' || c == '?'); + //~^ manual_pattern_char_comparison sentence.split(|c: char| c == '\n' || c == 'X'); + //~^ manual_pattern_char_comparison sentence.split(|c| c == '\n' || c == 'X'); + //~^ manual_pattern_char_comparison sentence.splitn(3, |c: char| c == 'X'); + //~^ manual_pattern_char_comparison sentence.splitn(3, |c: char| c.is_whitespace() || c == 'X'); let char_compare = 'X'; sentence.splitn(3, |c: char| c == char_compare); + //~^ manual_pattern_char_comparison sentence.split(|c: char| matches!(c, '\n' | 'X' | 'Y')); + //~^ manual_pattern_char_comparison sentence.splitn(3, |c: char| matches!(c, 'X')); + //~^ manual_pattern_char_comparison sentence.splitn(3, |c: char| matches!(c, 'X' | 'W')); + //~^ manual_pattern_char_comparison sentence.find(|c| c == '🎈'); + //~^ manual_pattern_char_comparison let not_str = NotStr; not_str.find(|c: char| c == 'X'); @@ -58,4 +67,5 @@ fn msrv_1_57() { fn msrv_1_58() { let sentence = "Hello, world!"; sentence.trim_end_matches(|c: char| c == '.' || c == ',' || c == '!' || c == '?'); + //~^ manual_pattern_char_comparison } diff --git a/tests/ui/manual_pattern_char_comparison.stderr b/tests/ui/manual_pattern_char_comparison.stderr index f185d7c8f676..d4fc3faa066f 100644 --- a/tests/ui/manual_pattern_char_comparison.stderr +++ b/tests/ui/manual_pattern_char_comparison.stderr @@ -8,55 +8,55 @@ LL | sentence.trim_end_matches(|c: char| c == '.' || c == ',' || c == '!' || = help: to override `-D warnings` add `#[allow(clippy::manual_pattern_char_comparison)]` error: this manual char comparison can be written more succinctly - --> tests/ui/manual_pattern_char_comparison.rs:12:20 + --> tests/ui/manual_pattern_char_comparison.rs:13:20 | LL | sentence.split(|c: char| c == '\n' || c == 'X'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using an array of `char`: `['\n', 'X']` error: this manual char comparison can be written more succinctly - --> tests/ui/manual_pattern_char_comparison.rs:13:20 + --> tests/ui/manual_pattern_char_comparison.rs:15:20 | LL | sentence.split(|c| c == '\n' || c == 'X'); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using an array of `char`: `['\n', 'X']` error: this manual char comparison can be written more succinctly - --> tests/ui/manual_pattern_char_comparison.rs:14:24 + --> tests/ui/manual_pattern_char_comparison.rs:17:24 | LL | sentence.splitn(3, |c: char| c == 'X'); | ^^^^^^^^^^^^^^^^^^ help: consider using a `char`: `'X'` error: this manual char comparison can be written more succinctly - --> tests/ui/manual_pattern_char_comparison.rs:17:24 + --> tests/ui/manual_pattern_char_comparison.rs:21:24 | LL | sentence.splitn(3, |c: char| c == char_compare); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a `char`: `char_compare` error: this manual char comparison can be written more succinctly - --> tests/ui/manual_pattern_char_comparison.rs:18:20 + --> tests/ui/manual_pattern_char_comparison.rs:23:20 | LL | sentence.split(|c: char| matches!(c, '\n' | 'X' | 'Y')); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using an array of `char`: `['\n', 'X', 'Y']` error: this manual char comparison can be written more succinctly - --> tests/ui/manual_pattern_char_comparison.rs:19:24 + --> tests/ui/manual_pattern_char_comparison.rs:25:24 | LL | sentence.splitn(3, |c: char| matches!(c, 'X')); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a `char`: `'X'` error: this manual char comparison can be written more succinctly - --> tests/ui/manual_pattern_char_comparison.rs:20:24 + --> tests/ui/manual_pattern_char_comparison.rs:27:24 | LL | sentence.splitn(3, |c: char| matches!(c, 'X' | 'W')); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using an array of `char`: `['X', 'W']` error: this manual char comparison can be written more succinctly - --> tests/ui/manual_pattern_char_comparison.rs:21:19 + --> tests/ui/manual_pattern_char_comparison.rs:29:19 | LL | sentence.find(|c| c == '🎈'); | ^^^^^^^^^^^^^ help: consider using a `char`: `'🎈'` error: this manual char comparison can be written more succinctly - --> tests/ui/manual_pattern_char_comparison.rs:60:31 + --> tests/ui/manual_pattern_char_comparison.rs:69:31 | LL | sentence.trim_end_matches(|c: char| c == '.' || c == ',' || c == '!' || c == '?'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using an array of `char`: `['.', ',', '!', '?']` diff --git a/tests/ui/manual_range_patterns.fixed b/tests/ui/manual_range_patterns.fixed index 60467bf9e884..c05e1fb27b03 100644 --- a/tests/ui/manual_range_patterns.fixed +++ b/tests/ui/manual_range_patterns.fixed @@ -6,7 +6,9 @@ fn main() { let f = 6; let _ = matches!(f, 1..=10); + //~^ manual_range_patterns let _ = matches!(f, 1..=10); + //~^ manual_range_patterns let _ = matches!(f, 4 | 2 | 3 | 1 | 5 | 6 | 9 | 8 | 10); // 7 is missing let _ = matches!(f, | 4); let _ = matches!(f, 4 | 5); @@ -14,34 +16,51 @@ fn main() { let _ = matches!(f, 0 | 2147483647); let _ = matches!(f, -2147483647 | 2147483647); let _ = matches!(f, 1..=4); + //~^ manual_range_patterns let _ = matches!(f, 1..4); + //~^ manual_range_patterns let _ = matches!(f, 1..=48324729); + //~^ manual_range_patterns let _ = matches!(f, 0..=48324730); + //~^ manual_range_patterns let _ = matches!(f, 0..=3); + //~^ manual_range_patterns #[allow(clippy::match_like_matches_macro)] let _ = match f { 1..=10 => true, + //~^ manual_range_patterns _ => false, }; let _ = matches!(f, -5..=3); + //~^ manual_range_patterns let _ = matches!(f, -1 | -5 | 3 | -2 | -4 | -3 | 0 | 1); // 2 is missing let _ = matches!(f, -1_000_001..=1_000_001); + //~^ manual_range_patterns let _ = matches!(f, -1_000_000..=1_000_000 | -1_000_001 | 1_000_002); matches!(f, 0x00..=0x03); + //~^ manual_range_patterns matches!(f, 0x00..=0x07); + //~^ manual_range_patterns matches!(f, -0x09..=0x00); + //~^ manual_range_patterns matches!(f, 0..=5); + //~^ manual_range_patterns matches!(f, 0..5); + //~^ manual_range_patterns matches!(f, 0..10); + //~^ manual_range_patterns matches!(f, 0..=10); + //~^ manual_range_patterns matches!(f, 0..=10); + //~^ manual_range_patterns macro_rules! mac { ($e:expr) => { matches!($e, 1..=10) + //~^ manual_range_patterns }; } mac!(f); diff --git a/tests/ui/manual_range_patterns.rs b/tests/ui/manual_range_patterns.rs index 9cd803334499..e5c403dc5f2e 100644 --- a/tests/ui/manual_range_patterns.rs +++ b/tests/ui/manual_range_patterns.rs @@ -6,7 +6,9 @@ fn main() { let f = 6; let _ = matches!(f, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10); + //~^ manual_range_patterns let _ = matches!(f, 4 | 2 | 3 | 1 | 5 | 6 | 9 | 7 | 8 | 10); + //~^ manual_range_patterns let _ = matches!(f, 4 | 2 | 3 | 1 | 5 | 6 | 9 | 8 | 10); // 7 is missing let _ = matches!(f, | 4); let _ = matches!(f, 4 | 5); @@ -14,34 +16,51 @@ fn main() { let _ = matches!(f, 0 | 2147483647); let _ = matches!(f, -2147483647 | 2147483647); let _ = matches!(f, 1 | (2..=4)); + //~^ manual_range_patterns let _ = matches!(f, 1 | (2..4)); + //~^ manual_range_patterns let _ = matches!(f, (1..=10) | (2..=13) | (14..=48324728) | 48324729); + //~^ manual_range_patterns let _ = matches!(f, 0 | (1..=10) | 48324730 | (2..=13) | (14..=48324728) | 48324729); + //~^ manual_range_patterns let _ = matches!(f, 0..=1 | 0..=2 | 0..=3); + //~^ manual_range_patterns #[allow(clippy::match_like_matches_macro)] let _ = match f { 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 => true, + //~^ manual_range_patterns _ => false, }; let _ = matches!(f, -1 | -5 | 3 | -2 | -4 | -3 | 0 | 1 | 2); + //~^ manual_range_patterns let _ = matches!(f, -1 | -5 | 3 | -2 | -4 | -3 | 0 | 1); // 2 is missing let _ = matches!(f, -1_000_000..=1_000_000 | -1_000_001 | 1_000_001); + //~^ manual_range_patterns let _ = matches!(f, -1_000_000..=1_000_000 | -1_000_001 | 1_000_002); matches!(f, 0x00 | 0x01 | 0x02 | 0x03); + //~^ manual_range_patterns matches!(f, 0x00..=0x05 | 0x06 | 0x07); + //~^ manual_range_patterns matches!(f, -0x09 | -0x08 | -0x07..=0x00); + //~^ manual_range_patterns matches!(f, 0..5 | 5); + //~^ manual_range_patterns matches!(f, 0 | 1..5); + //~^ manual_range_patterns matches!(f, 0..=5 | 6..10); + //~^ manual_range_patterns matches!(f, 0..5 | 5..=10); + //~^ manual_range_patterns matches!(f, 5..=10 | 0..5); + //~^ manual_range_patterns macro_rules! mac { ($e:expr) => { matches!($e, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10) + //~^ manual_range_patterns }; } mac!(f); diff --git a/tests/ui/manual_range_patterns.stderr b/tests/ui/manual_range_patterns.stderr index 7c19fdd475f1..e494e7234d68 100644 --- a/tests/ui/manual_range_patterns.stderr +++ b/tests/ui/manual_range_patterns.stderr @@ -8,109 +8,109 @@ LL | let _ = matches!(f, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10); = help: to override `-D warnings` add `#[allow(clippy::manual_range_patterns)]` error: this OR pattern can be rewritten using a range - --> tests/ui/manual_range_patterns.rs:9:25 + --> tests/ui/manual_range_patterns.rs:10:25 | LL | let _ = matches!(f, 4 | 2 | 3 | 1 | 5 | 6 | 9 | 7 | 8 | 10); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10` error: this OR pattern can be rewritten using a range - --> tests/ui/manual_range_patterns.rs:16:25 + --> tests/ui/manual_range_patterns.rs:18:25 | LL | let _ = matches!(f, 1 | (2..=4)); | ^^^^^^^^^^^ help: try: `1..=4` error: this OR pattern can be rewritten using a range - --> tests/ui/manual_range_patterns.rs:17:25 + --> tests/ui/manual_range_patterns.rs:20:25 | LL | let _ = matches!(f, 1 | (2..4)); | ^^^^^^^^^^ help: try: `1..4` error: this OR pattern can be rewritten using a range - --> tests/ui/manual_range_patterns.rs:18:25 + --> tests/ui/manual_range_patterns.rs:22:25 | LL | let _ = matches!(f, (1..=10) | (2..=13) | (14..=48324728) | 48324729); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=48324729` error: this OR pattern can be rewritten using a range - --> tests/ui/manual_range_patterns.rs:19:25 + --> tests/ui/manual_range_patterns.rs:24:25 | LL | let _ = matches!(f, 0 | (1..=10) | 48324730 | (2..=13) | (14..=48324728) | 48324729); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `0..=48324730` error: this OR pattern can be rewritten using a range - --> tests/ui/manual_range_patterns.rs:20:25 + --> tests/ui/manual_range_patterns.rs:26:25 | LL | let _ = matches!(f, 0..=1 | 0..=2 | 0..=3); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `0..=3` error: this OR pattern can be rewritten using a range - --> tests/ui/manual_range_patterns.rs:23:9 + --> tests/ui/manual_range_patterns.rs:30:9 | LL | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 => true, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10` error: this OR pattern can be rewritten using a range - --> tests/ui/manual_range_patterns.rs:26:25 + --> tests/ui/manual_range_patterns.rs:34:25 | LL | let _ = matches!(f, -1 | -5 | 3 | -2 | -4 | -3 | 0 | 1 | 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-5..=3` error: this OR pattern can be rewritten using a range - --> tests/ui/manual_range_patterns.rs:28:25 + --> tests/ui/manual_range_patterns.rs:37:25 | LL | let _ = matches!(f, -1_000_000..=1_000_000 | -1_000_001 | 1_000_001); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-1_000_001..=1_000_001` error: this OR pattern can be rewritten using a range - --> tests/ui/manual_range_patterns.rs:31:17 + --> tests/ui/manual_range_patterns.rs:41:17 | LL | matches!(f, 0x00 | 0x01 | 0x02 | 0x03); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `0x00..=0x03` error: this OR pattern can be rewritten using a range - --> tests/ui/manual_range_patterns.rs:32:17 + --> tests/ui/manual_range_patterns.rs:43:17 | LL | matches!(f, 0x00..=0x05 | 0x06 | 0x07); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `0x00..=0x07` error: this OR pattern can be rewritten using a range - --> tests/ui/manual_range_patterns.rs:33:17 + --> tests/ui/manual_range_patterns.rs:45:17 | LL | matches!(f, -0x09 | -0x08 | -0x07..=0x00); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-0x09..=0x00` error: this OR pattern can be rewritten using a range - --> tests/ui/manual_range_patterns.rs:35:17 + --> tests/ui/manual_range_patterns.rs:48:17 | LL | matches!(f, 0..5 | 5); | ^^^^^^^^ help: try: `0..=5` error: this OR pattern can be rewritten using a range - --> tests/ui/manual_range_patterns.rs:36:17 + --> tests/ui/manual_range_patterns.rs:50:17 | LL | matches!(f, 0 | 1..5); | ^^^^^^^^ help: try: `0..5` error: this OR pattern can be rewritten using a range - --> tests/ui/manual_range_patterns.rs:38:17 + --> tests/ui/manual_range_patterns.rs:53:17 | LL | matches!(f, 0..=5 | 6..10); | ^^^^^^^^^^^^^ help: try: `0..10` error: this OR pattern can be rewritten using a range - --> tests/ui/manual_range_patterns.rs:39:17 + --> tests/ui/manual_range_patterns.rs:55:17 | LL | matches!(f, 0..5 | 5..=10); | ^^^^^^^^^^^^^ help: try: `0..=10` error: this OR pattern can be rewritten using a range - --> tests/ui/manual_range_patterns.rs:40:17 + --> tests/ui/manual_range_patterns.rs:57:17 | LL | matches!(f, 5..=10 | 0..5); | ^^^^^^^^^^^^^ help: try: `0..=10` error: this OR pattern can be rewritten using a range - --> tests/ui/manual_range_patterns.rs:44:26 + --> tests/ui/manual_range_patterns.rs:62:26 | LL | matches!($e, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10` diff --git a/tests/ui/manual_rem_euclid.fixed b/tests/ui/manual_rem_euclid.fixed index 2d50865586d1..e64654bb6866 100644 --- a/tests/ui/manual_rem_euclid.fixed +++ b/tests/ui/manual_rem_euclid.fixed @@ -11,10 +11,15 @@ fn main() { let value: i32 = 5; let _: i32 = value.rem_euclid(4); + //~^ manual_rem_euclid let _: i32 = value.rem_euclid(4); + //~^ manual_rem_euclid let _: i32 = value.rem_euclid(4); + //~^ manual_rem_euclid let _: i32 = value.rem_euclid(4); + //~^ manual_rem_euclid let _: i32 = 1 + value.rem_euclid(4); + //~^ manual_rem_euclid let _: i32 = (3 + value % 4) % 4; let _: i32 = (-4 + value % -4) % -4; @@ -35,6 +40,7 @@ fn main() { inline!( let value: i32 = 5; let _: i32 = value.rem_euclid(4); + //~^ manual_rem_euclid ); // Do not lint in external macros @@ -47,11 +53,13 @@ fn main() { // Should lint for params too pub fn rem_euclid_4(num: i32) -> i32 { num.rem_euclid(4) + //~^ manual_rem_euclid } // Constant version came later, should still lint pub const fn const_rem_euclid_4(num: i32) -> i32 { num.rem_euclid(4) + //~^ manual_rem_euclid } #[clippy::msrv = "1.37"] @@ -64,6 +72,7 @@ pub fn msrv_1_37() { pub fn msrv_1_38() { let x: i32 = 10; let _: i32 = x.rem_euclid(4); + //~^ manual_rem_euclid } // For const fns: @@ -77,4 +86,5 @@ pub const fn msrv_1_51() { pub const fn msrv_1_52() { let x: i32 = 10; let _: i32 = x.rem_euclid(4); + //~^ manual_rem_euclid } diff --git a/tests/ui/manual_rem_euclid.rs b/tests/ui/manual_rem_euclid.rs index e405a2db4765..4561a7ee9ea4 100644 --- a/tests/ui/manual_rem_euclid.rs +++ b/tests/ui/manual_rem_euclid.rs @@ -11,10 +11,15 @@ fn main() { let value: i32 = 5; let _: i32 = ((value % 4) + 4) % 4; + //~^ manual_rem_euclid let _: i32 = (4 + (value % 4)) % 4; + //~^ manual_rem_euclid let _: i32 = (value % 4 + 4) % 4; + //~^ manual_rem_euclid let _: i32 = (4 + value % 4) % 4; + //~^ manual_rem_euclid let _: i32 = 1 + (4 + value % 4) % 4; + //~^ manual_rem_euclid let _: i32 = (3 + value % 4) % 4; let _: i32 = (-4 + value % -4) % -4; @@ -35,6 +40,7 @@ fn main() { inline!( let value: i32 = 5; let _: i32 = ((value % 4) + 4) % 4; + //~^ manual_rem_euclid ); // Do not lint in external macros @@ -47,11 +53,13 @@ fn main() { // Should lint for params too pub fn rem_euclid_4(num: i32) -> i32 { ((num % 4) + 4) % 4 + //~^ manual_rem_euclid } // Constant version came later, should still lint pub const fn const_rem_euclid_4(num: i32) -> i32 { ((num % 4) + 4) % 4 + //~^ manual_rem_euclid } #[clippy::msrv = "1.37"] @@ -64,6 +72,7 @@ pub fn msrv_1_37() { pub fn msrv_1_38() { let x: i32 = 10; let _: i32 = ((x % 4) + 4) % 4; + //~^ manual_rem_euclid } // For const fns: @@ -77,4 +86,5 @@ pub const fn msrv_1_51() { pub const fn msrv_1_52() { let x: i32 = 10; let _: i32 = ((x % 4) + 4) % 4; + //~^ manual_rem_euclid } diff --git a/tests/ui/manual_rem_euclid.stderr b/tests/ui/manual_rem_euclid.stderr index a19fdadb1c9b..386815b23b68 100644 --- a/tests/ui/manual_rem_euclid.stderr +++ b/tests/ui/manual_rem_euclid.stderr @@ -8,31 +8,31 @@ LL | let _: i32 = ((value % 4) + 4) % 4; = help: to override `-D warnings` add `#[allow(clippy::manual_rem_euclid)]` error: manual `rem_euclid` implementation - --> tests/ui/manual_rem_euclid.rs:14:18 + --> tests/ui/manual_rem_euclid.rs:15:18 | LL | let _: i32 = (4 + (value % 4)) % 4; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)` error: manual `rem_euclid` implementation - --> tests/ui/manual_rem_euclid.rs:15:18 + --> tests/ui/manual_rem_euclid.rs:17:18 | LL | let _: i32 = (value % 4 + 4) % 4; | ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)` error: manual `rem_euclid` implementation - --> tests/ui/manual_rem_euclid.rs:16:18 + --> tests/ui/manual_rem_euclid.rs:19:18 | LL | let _: i32 = (4 + value % 4) % 4; | ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)` error: manual `rem_euclid` implementation - --> tests/ui/manual_rem_euclid.rs:17:22 + --> tests/ui/manual_rem_euclid.rs:21:22 | LL | let _: i32 = 1 + (4 + value % 4) % 4; | ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)` error: manual `rem_euclid` implementation - --> tests/ui/manual_rem_euclid.rs:37:22 + --> tests/ui/manual_rem_euclid.rs:42:22 | LL | let _: i32 = ((value % 4) + 4) % 4; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)` @@ -40,25 +40,25 @@ LL | let _: i32 = ((value % 4) + 4) % 4; = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info) error: manual `rem_euclid` implementation - --> tests/ui/manual_rem_euclid.rs:49:5 + --> tests/ui/manual_rem_euclid.rs:55:5 | LL | ((num % 4) + 4) % 4 | ^^^^^^^^^^^^^^^^^^^ help: consider using: `num.rem_euclid(4)` error: manual `rem_euclid` implementation - --> tests/ui/manual_rem_euclid.rs:54:5 + --> tests/ui/manual_rem_euclid.rs:61:5 | LL | ((num % 4) + 4) % 4 | ^^^^^^^^^^^^^^^^^^^ help: consider using: `num.rem_euclid(4)` error: manual `rem_euclid` implementation - --> tests/ui/manual_rem_euclid.rs:66:18 + --> tests/ui/manual_rem_euclid.rs:74:18 | LL | let _: i32 = ((x % 4) + 4) % 4; | ^^^^^^^^^^^^^^^^^ help: consider using: `x.rem_euclid(4)` error: manual `rem_euclid` implementation - --> tests/ui/manual_rem_euclid.rs:79:18 + --> tests/ui/manual_rem_euclid.rs:88:18 | LL | let _: i32 = ((x % 4) + 4) % 4; | ^^^^^^^^^^^^^^^^^ help: consider using: `x.rem_euclid(4)` diff --git a/tests/ui/manual_repeat_n.fixed b/tests/ui/manual_repeat_n.fixed index 4235b02a89e3..44ad3c02d3b8 100644 --- a/tests/ui/manual_repeat_n.fixed +++ b/tests/ui/manual_repeat_n.fixed @@ -4,14 +4,19 @@ use std::iter::repeat; fn main() { let _ = std::iter::repeat_n(10, 3); + //~^ manual_repeat_n let _ = std::iter::repeat_n(String::from("foo"), 4); + //~^ manual_repeat_n for value in std::iter::repeat_n(5, 3) {} + //~^ manual_repeat_n let _: Vec<_> = std::iter::repeat_n(String::from("bar"), 10).collect(); + //~^ manual_repeat_n let _ = std::iter::repeat_n(vec![1, 2], 2); + //~^ manual_repeat_n } mod foo_lib { diff --git a/tests/ui/manual_repeat_n.rs b/tests/ui/manual_repeat_n.rs index dbf9ac6a14af..ef6d6827d573 100644 --- a/tests/ui/manual_repeat_n.rs +++ b/tests/ui/manual_repeat_n.rs @@ -4,14 +4,19 @@ use std::iter::repeat; fn main() { let _ = repeat(10).take(3); + //~^ manual_repeat_n let _ = repeat(String::from("foo")).take(4); + //~^ manual_repeat_n for value in std::iter::repeat(5).take(3) {} + //~^ manual_repeat_n let _: Vec<_> = std::iter::repeat(String::from("bar")).take(10).collect(); + //~^ manual_repeat_n let _ = repeat(vec![1, 2]).take(2); + //~^ manual_repeat_n } mod foo_lib { diff --git a/tests/ui/manual_repeat_n.stderr b/tests/ui/manual_repeat_n.stderr index 87395b3f8bf1..de968b3ff791 100644 --- a/tests/ui/manual_repeat_n.stderr +++ b/tests/ui/manual_repeat_n.stderr @@ -8,25 +8,25 @@ LL | let _ = repeat(10).take(3); = help: to override `-D warnings` add `#[allow(clippy::manual_repeat_n)]` error: this `repeat().take()` can be written more concisely - --> tests/ui/manual_repeat_n.rs:8:13 + --> tests/ui/manual_repeat_n.rs:9:13 | LL | let _ = repeat(String::from("foo")).take(4); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `repeat_n()` instead: `std::iter::repeat_n(String::from("foo"), 4)` error: this `repeat().take()` can be written more concisely - --> tests/ui/manual_repeat_n.rs:10:18 + --> tests/ui/manual_repeat_n.rs:12:18 | LL | for value in std::iter::repeat(5).take(3) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `repeat_n()` instead: `std::iter::repeat_n(5, 3)` error: this `repeat().take()` can be written more concisely - --> tests/ui/manual_repeat_n.rs:12:21 + --> tests/ui/manual_repeat_n.rs:15:21 | LL | let _: Vec<_> = std::iter::repeat(String::from("bar")).take(10).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `repeat_n()` instead: `std::iter::repeat_n(String::from("bar"), 10)` error: this `repeat().take()` can be written more concisely - --> tests/ui/manual_repeat_n.rs:14:13 + --> tests/ui/manual_repeat_n.rs:18:13 | LL | let _ = repeat(vec![1, 2]).take(2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `repeat_n()` instead: `std::iter::repeat_n(vec![1, 2], 2)` diff --git a/tests/ui/manual_retain.fixed b/tests/ui/manual_retain.fixed index 5540029bf6b1..ca8491131c06 100644 --- a/tests/ui/manual_retain.fixed +++ b/tests/ui/manual_retain.fixed @@ -23,13 +23,18 @@ fn binary_heap_retain() { let mut binary_heap = BinaryHeap::from([1, 2, 3]); // Do lint. binary_heap.retain(|x| x % 2 == 0); + //~^ manual_retain binary_heap.retain(|x| x % 2 == 0); + //~^ manual_retain binary_heap.retain(|x| x % 2 == 0); + //~^ manual_retain // Do lint, because we use pattern matching let mut tuples = BinaryHeap::from([(0, 1), (1, 2), (2, 3)]); tuples.retain(|(ref x, ref y)| *x == 0); + //~^ manual_retain tuples.retain(|(x, y)| *x == 0); + //~^ manual_retain // Do not lint, because type conversion is performed binary_heap = binary_heap @@ -60,7 +65,9 @@ fn btree_map_retain() { let mut btree_map: BTreeMap = (0..8).map(|x| (x, x * 10)).collect(); // Do lint. btree_map.retain(|k, _| k % 2 == 0); + //~^ manual_retain btree_map.retain(|_, &mut v| v % 2 == 0); + //~^ manual_retain btree_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0)); // Do not lint, because the parameters are not matched in tuple pattern @@ -84,13 +91,18 @@ fn btree_set_retain() { // Do lint. btree_set.retain(|x| x % 2 == 0); + //~^ manual_retain btree_set.retain(|x| x % 2 == 0); + //~^ manual_retain btree_set.retain(|x| x % 2 == 0); + //~^ manual_retain // Do lint, because we use pattern matching let mut tuples = BTreeSet::from([(0, 1), (1, 2), (2, 3)]); tuples.retain(|(ref x, ref y)| *x == 0); + //~^ manual_retain tuples.retain(|(x, y)| *x == 0); + //~^ manual_retain // Do not lint, because type conversion is performed btree_set = btree_set @@ -121,7 +133,9 @@ fn hash_map_retain() { let mut hash_map: HashMap = (0..8).map(|x| (x, x * 10)).collect(); // Do lint. hash_map.retain(|k, _| k % 2 == 0); + //~^ manual_retain hash_map.retain(|_, &mut v| v % 2 == 0); + //~^ manual_retain hash_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0)); // Do not lint, because the parameters are not matched in tuple pattern @@ -144,13 +158,18 @@ fn hash_set_retain() { let mut hash_set = HashSet::from([1, 2, 3, 4, 5, 6]); // Do lint. hash_set.retain(|x| x % 2 == 0); + //~^ manual_retain hash_set.retain(|x| x % 2 == 0); + //~^ manual_retain hash_set.retain(|x| x % 2 == 0); + //~^ manual_retain // Do lint, because we use pattern matching let mut tuples = HashSet::from([(0, 1), (1, 2), (2, 3)]); tuples.retain(|(ref x, ref y)| *x == 0); + //~^ manual_retain tuples.retain(|(x, y)| *x == 0); + //~^ manual_retain // Do not lint, because type conversion is performed hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect::>(); @@ -180,6 +199,7 @@ fn string_retain() { let mut s = String::from("foobar"); // Do lint. s.retain(|c| c != 'o'); + //~^ manual_retain // Do not lint, because this expression is not assign. let mut bar: String = s.chars().filter(|&c| c != 'o').to_owned().collect(); @@ -192,13 +212,18 @@ fn vec_retain() { let mut vec = vec![0, 1, 2]; // Do lint. vec.retain(|x| x % 2 == 0); + //~^ manual_retain vec.retain(|x| x % 2 == 0); + //~^ manual_retain vec.retain(|x| x % 2 == 0); + //~^ manual_retain // Do lint, because we use pattern matching let mut tuples = vec![(0, 1), (1, 2), (2, 3)]; tuples.retain(|(ref x, ref y)| *x == 0); + //~^ manual_retain tuples.retain(|(x, y)| *x == 0); + //~^ manual_retain // Do not lint, because type conversion is performed vec = vec.into_iter().filter(|x| x % 2 == 0).collect::>(); @@ -221,8 +246,11 @@ fn vec_deque_retain() { // Do lint. vec_deque.retain(|x| x % 2 == 0); + //~^ manual_retain vec_deque.retain(|x| x % 2 == 0); + //~^ manual_retain vec_deque.retain(|x| x % 2 == 0); + //~^ manual_retain // Do not lint, because type conversion is performed vec_deque = vec_deque @@ -280,10 +308,12 @@ fn issue_10393() { // Do lint let mut vec = vec![(0, 1), (1, 2), (2, 3)]; vec.retain(|(x, y)| *x == 0); + //~^ manual_retain // Do lint let mut tuples = vec![(true, -2), (false, 3)]; tuples.retain(|(_, n)| *n > 0); + //~^ manual_retain } fn issue_11457() { @@ -301,11 +331,17 @@ fn issue_12081() { // Do lint vec.retain(|&x| x == 0); + //~^ manual_retain vec.retain(|&x| x == 0); + //~^ manual_retain vec.retain(|&x| x == 0); + //~^ manual_retain // Do lint vec.retain(|x| *x == 0); + //~^ manual_retain vec.retain(|x| *x == 0); + //~^ manual_retain vec.retain(|x| *x == 0); + //~^ manual_retain } diff --git a/tests/ui/manual_retain.rs b/tests/ui/manual_retain.rs index cee641d9d65f..cd05a41f3f25 100644 --- a/tests/ui/manual_retain.rs +++ b/tests/ui/manual_retain.rs @@ -23,13 +23,18 @@ fn binary_heap_retain() { let mut binary_heap = BinaryHeap::from([1, 2, 3]); // Do lint. binary_heap = binary_heap.into_iter().filter(|x| x % 2 == 0).collect(); + //~^ manual_retain binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).copied().collect(); + //~^ manual_retain binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).cloned().collect(); + //~^ manual_retain // Do lint, because we use pattern matching let mut tuples = BinaryHeap::from([(0, 1), (1, 2), (2, 3)]); tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); + //~^ manual_retain tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); + //~^ manual_retain // Do not lint, because type conversion is performed binary_heap = binary_heap @@ -60,8 +65,11 @@ fn btree_map_retain() { let mut btree_map: BTreeMap = (0..8).map(|x| (x, x * 10)).collect(); // Do lint. btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); + //~^ manual_retain btree_map = btree_map.into_iter().filter(|(_, v)| v % 2 == 0).collect(); + //~^ manual_retain btree_map = btree_map + //~^ manual_retain .into_iter() .filter(|(k, v)| (k % 2 == 0) && (v % 2 == 0)) .collect(); @@ -87,13 +95,18 @@ fn btree_set_retain() { // Do lint. btree_set = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect(); + //~^ manual_retain btree_set = btree_set.iter().filter(|&x| x % 2 == 0).cloned().collect(); + //~^ manual_retain btree_set = btree_set.into_iter().filter(|x| x % 2 == 0).collect(); + //~^ manual_retain // Do lint, because we use pattern matching let mut tuples = BTreeSet::from([(0, 1), (1, 2), (2, 3)]); tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); + //~^ manual_retain tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); + //~^ manual_retain // Do not lint, because type conversion is performed btree_set = btree_set @@ -124,8 +137,11 @@ fn hash_map_retain() { let mut hash_map: HashMap = (0..8).map(|x| (x, x * 10)).collect(); // Do lint. hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); + //~^ manual_retain hash_map = hash_map.into_iter().filter(|(_, v)| v % 2 == 0).collect(); + //~^ manual_retain hash_map = hash_map + //~^ manual_retain .into_iter() .filter(|(k, v)| (k % 2 == 0) && (v % 2 == 0)) .collect(); @@ -150,13 +166,18 @@ fn hash_set_retain() { let mut hash_set = HashSet::from([1, 2, 3, 4, 5, 6]); // Do lint. hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect(); + //~^ manual_retain hash_set = hash_set.iter().filter(|&x| x % 2 == 0).copied().collect(); + //~^ manual_retain hash_set = hash_set.iter().filter(|&x| x % 2 == 0).cloned().collect(); + //~^ manual_retain // Do lint, because we use pattern matching let mut tuples = HashSet::from([(0, 1), (1, 2), (2, 3)]); tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); + //~^ manual_retain tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); + //~^ manual_retain // Do not lint, because type conversion is performed hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect::>(); @@ -186,6 +207,7 @@ fn string_retain() { let mut s = String::from("foobar"); // Do lint. s = s.chars().filter(|&c| c != 'o').to_owned().collect(); + //~^ manual_retain // Do not lint, because this expression is not assign. let mut bar: String = s.chars().filter(|&c| c != 'o').to_owned().collect(); @@ -198,13 +220,18 @@ fn vec_retain() { let mut vec = vec![0, 1, 2]; // Do lint. vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect(); + //~^ manual_retain vec = vec.iter().filter(|&x| x % 2 == 0).cloned().collect(); + //~^ manual_retain vec = vec.into_iter().filter(|x| x % 2 == 0).collect(); + //~^ manual_retain // Do lint, because we use pattern matching let mut tuples = vec![(0, 1), (1, 2), (2, 3)]; tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); + //~^ manual_retain tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); + //~^ manual_retain // Do not lint, because type conversion is performed vec = vec.into_iter().filter(|x| x % 2 == 0).collect::>(); @@ -227,8 +254,11 @@ fn vec_deque_retain() { // Do lint. vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).copied().collect(); + //~^ manual_retain vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).cloned().collect(); + //~^ manual_retain vec_deque = vec_deque.into_iter().filter(|x| x % 2 == 0).collect(); + //~^ manual_retain // Do not lint, because type conversion is performed vec_deque = vec_deque @@ -286,10 +316,12 @@ fn issue_10393() { // Do lint let mut vec = vec![(0, 1), (1, 2), (2, 3)]; vec = vec.into_iter().filter(|(x, y)| *x == 0).collect(); + //~^ manual_retain // Do lint let mut tuples = vec![(true, -2), (false, 3)]; tuples = tuples.into_iter().filter(|(_, n)| *n > 0).collect(); + //~^ manual_retain } fn issue_11457() { @@ -307,11 +339,17 @@ fn issue_12081() { // Do lint vec = vec.iter().filter(|&&x| x == 0).copied().collect(); + //~^ manual_retain vec = vec.iter().filter(|&&x| x == 0).cloned().collect(); + //~^ manual_retain vec = vec.into_iter().filter(|&x| x == 0).collect(); + //~^ manual_retain // Do lint vec = vec.iter().filter(|&x| *x == 0).copied().collect(); + //~^ manual_retain vec = vec.iter().filter(|&x| *x == 0).cloned().collect(); + //~^ manual_retain vec = vec.into_iter().filter(|x| *x == 0).collect(); + //~^ manual_retain } diff --git a/tests/ui/manual_retain.stderr b/tests/ui/manual_retain.stderr index c25c804df758..2f81647dd8b7 100644 --- a/tests/ui/manual_retain.stderr +++ b/tests/ui/manual_retain.stderr @@ -8,229 +8,231 @@ LL | binary_heap = binary_heap.into_iter().filter(|x| x % 2 == 0).collect(); = help: to override `-D warnings` add `#[allow(clippy::manual_retain)]` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:26:5 + --> tests/ui/manual_retain.rs:27:5 | LL | binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:27:5 + --> tests/ui/manual_retain.rs:29:5 | LL | binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:31:5 + --> tests/ui/manual_retain.rs:34:5 | LL | tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:32:5 + --> tests/ui/manual_retain.rs:36:5 | LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:62:5 + --> tests/ui/manual_retain.rs:67:5 | LL | btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|k, _| k % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:63:5 + --> tests/ui/manual_retain.rs:69:5 | LL | btree_map = btree_map.into_iter().filter(|(_, v)| v % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|_, &mut v| v % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:64:5 + --> tests/ui/manual_retain.rs:71:5 | LL | / btree_map = btree_map +LL | | LL | | .into_iter() LL | | .filter(|(k, v)| (k % 2 == 0) && (v % 2 == 0)) LL | | .collect(); | |__________________^ help: consider calling `.retain()` instead: `btree_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:89:5 + --> tests/ui/manual_retain.rs:97:5 | LL | btree_set = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:90:5 + --> tests/ui/manual_retain.rs:99:5 | LL | btree_set = btree_set.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:91:5 + --> tests/ui/manual_retain.rs:101:5 | LL | btree_set = btree_set.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:95:5 + --> tests/ui/manual_retain.rs:106:5 | LL | tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:96:5 + --> tests/ui/manual_retain.rs:108:5 | LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:126:5 + --> tests/ui/manual_retain.rs:139:5 | LL | hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|k, _| k % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:127:5 + --> tests/ui/manual_retain.rs:141:5 | LL | hash_map = hash_map.into_iter().filter(|(_, v)| v % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|_, &mut v| v % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:128:5 + --> tests/ui/manual_retain.rs:143:5 | LL | / hash_map = hash_map +LL | | LL | | .into_iter() LL | | .filter(|(k, v)| (k % 2 == 0) && (v % 2 == 0)) LL | | .collect(); | |__________________^ help: consider calling `.retain()` instead: `hash_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:152:5 + --> tests/ui/manual_retain.rs:168:5 | LL | hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:153:5 + --> tests/ui/manual_retain.rs:170:5 | LL | hash_set = hash_set.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:154:5 + --> tests/ui/manual_retain.rs:172:5 | LL | hash_set = hash_set.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:158:5 + --> tests/ui/manual_retain.rs:177:5 | LL | tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:159:5 + --> tests/ui/manual_retain.rs:179:5 | LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:188:5 + --> tests/ui/manual_retain.rs:209:5 | LL | s = s.chars().filter(|&c| c != 'o').to_owned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `s.retain(|c| c != 'o')` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:200:5 + --> tests/ui/manual_retain.rs:222:5 | LL | vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:201:5 + --> tests/ui/manual_retain.rs:224:5 | LL | vec = vec.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:202:5 + --> tests/ui/manual_retain.rs:226:5 | LL | vec = vec.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:206:5 + --> tests/ui/manual_retain.rs:231:5 | LL | tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:207:5 + --> tests/ui/manual_retain.rs:233:5 | LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:229:5 + --> tests/ui/manual_retain.rs:256:5 | LL | vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:230:5 + --> tests/ui/manual_retain.rs:258:5 | LL | vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:231:5 + --> tests/ui/manual_retain.rs:260:5 | LL | vec_deque = vec_deque.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:288:5 + --> tests/ui/manual_retain.rs:318:5 | LL | vec = vec.into_iter().filter(|(x, y)| *x == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|(x, y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:292:5 + --> tests/ui/manual_retain.rs:323:5 | LL | tuples = tuples.into_iter().filter(|(_, n)| *n > 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(_, n)| *n > 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:309:5 + --> tests/ui/manual_retain.rs:341:5 | LL | vec = vec.iter().filter(|&&x| x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:310:5 + --> tests/ui/manual_retain.rs:343:5 | LL | vec = vec.iter().filter(|&&x| x == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:311:5 + --> tests/ui/manual_retain.rs:345:5 | LL | vec = vec.into_iter().filter(|&x| x == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:314:5 + --> tests/ui/manual_retain.rs:349:5 | LL | vec = vec.iter().filter(|&x| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:315:5 + --> tests/ui/manual_retain.rs:351:5 | LL | vec = vec.iter().filter(|&x| *x == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:316:5 + --> tests/ui/manual_retain.rs:353:5 | LL | vec = vec.into_iter().filter(|x| *x == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)` diff --git a/tests/ui/manual_rotate.fixed b/tests/ui/manual_rotate.fixed index 5d33838a3187..49db8661369e 100644 --- a/tests/ui/manual_rotate.fixed +++ b/tests/ui/manual_rotate.fixed @@ -6,18 +6,29 @@ fn main() { let a_u32 = 1u32; // True positives let y_u8 = x_u8.rotate_right(3); + //~^ manual_rotate let y_u16 = x_u16.rotate_right(7); + //~^ manual_rotate let y_u32 = x_u32.rotate_right(8); + //~^ manual_rotate let y_u64 = x_u64.rotate_right(9); + //~^ manual_rotate let y_i8 = x_i8.rotate_right(3); + //~^ manual_rotate let y_i16 = x_i16.rotate_right(7); + //~^ manual_rotate let y_i32 = x_i32.rotate_right(8); + //~^ manual_rotate let y_i64 = x_i64.rotate_right(9); + //~^ manual_rotate // Plus also works instead of | let y_u32_plus = x_u32.rotate_right(8); + //~^ manual_rotate // Complex expression let y_u32_complex = (x_u32 | 3256).rotate_right(8); + //~^ manual_rotate let y_u64_as = (x_u32 as u64).rotate_right(8); + //~^ manual_rotate // False positives - can't be replaced with a rotation let y_u8_false = (x_u8 >> 6) | (x_u8 << 3); diff --git a/tests/ui/manual_rotate.rs b/tests/ui/manual_rotate.rs index 5377491fb1a3..6445e60aa25d 100644 --- a/tests/ui/manual_rotate.rs +++ b/tests/ui/manual_rotate.rs @@ -6,18 +6,29 @@ fn main() { let a_u32 = 1u32; // True positives let y_u8 = (x_u8 >> 3) | (x_u8 << 5); + //~^ manual_rotate let y_u16 = (x_u16 >> 7) | (x_u16 << 9); + //~^ manual_rotate let y_u32 = (x_u32 >> 8) | (x_u32 << 24); + //~^ manual_rotate let y_u64 = (x_u64 >> 9) | (x_u64 << 55); + //~^ manual_rotate let y_i8 = (x_i8 >> 3) | (x_i8 << 5); + //~^ manual_rotate let y_i16 = (x_i16 >> 7) | (x_i16 << 9); + //~^ manual_rotate let y_i32 = (x_i32 >> 8) | (x_i32 << 24); + //~^ manual_rotate let y_i64 = (x_i64 >> 9) | (x_i64 << 55); + //~^ manual_rotate // Plus also works instead of | let y_u32_plus = (x_u32 >> 8) + (x_u32 << 24); + //~^ manual_rotate // Complex expression let y_u32_complex = ((x_u32 | 3256) >> 8) | ((x_u32 | 3256) << 24); + //~^ manual_rotate let y_u64_as = (x_u32 as u64 >> 8) | ((x_u32 as u64) << 56); + //~^ manual_rotate // False positives - can't be replaced with a rotation let y_u8_false = (x_u8 >> 6) | (x_u8 << 3); diff --git a/tests/ui/manual_rotate.stderr b/tests/ui/manual_rotate.stderr index 52da0861f700..a28721fbb94c 100644 --- a/tests/ui/manual_rotate.stderr +++ b/tests/ui/manual_rotate.stderr @@ -8,61 +8,61 @@ LL | let y_u8 = (x_u8 >> 3) | (x_u8 << 5); = help: to override `-D warnings` add `#[allow(clippy::manual_rotate)]` error: there is no need to manually implement bit rotation - --> tests/ui/manual_rotate.rs:9:17 + --> tests/ui/manual_rotate.rs:10:17 | LL | let y_u16 = (x_u16 >> 7) | (x_u16 << 9); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: this expression can be rewritten as: `x_u16.rotate_right(7)` error: there is no need to manually implement bit rotation - --> tests/ui/manual_rotate.rs:10:17 + --> tests/ui/manual_rotate.rs:12:17 | LL | let y_u32 = (x_u32 >> 8) | (x_u32 << 24); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: this expression can be rewritten as: `x_u32.rotate_right(8)` error: there is no need to manually implement bit rotation - --> tests/ui/manual_rotate.rs:11:17 + --> tests/ui/manual_rotate.rs:14:17 | LL | let y_u64 = (x_u64 >> 9) | (x_u64 << 55); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: this expression can be rewritten as: `x_u64.rotate_right(9)` error: there is no need to manually implement bit rotation - --> tests/ui/manual_rotate.rs:12:16 + --> tests/ui/manual_rotate.rs:16:16 | LL | let y_i8 = (x_i8 >> 3) | (x_i8 << 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: this expression can be rewritten as: `x_i8.rotate_right(3)` error: there is no need to manually implement bit rotation - --> tests/ui/manual_rotate.rs:13:17 + --> tests/ui/manual_rotate.rs:18:17 | LL | let y_i16 = (x_i16 >> 7) | (x_i16 << 9); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: this expression can be rewritten as: `x_i16.rotate_right(7)` error: there is no need to manually implement bit rotation - --> tests/ui/manual_rotate.rs:14:17 + --> tests/ui/manual_rotate.rs:20:17 | LL | let y_i32 = (x_i32 >> 8) | (x_i32 << 24); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: this expression can be rewritten as: `x_i32.rotate_right(8)` error: there is no need to manually implement bit rotation - --> tests/ui/manual_rotate.rs:15:17 + --> tests/ui/manual_rotate.rs:22:17 | LL | let y_i64 = (x_i64 >> 9) | (x_i64 << 55); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: this expression can be rewritten as: `x_i64.rotate_right(9)` error: there is no need to manually implement bit rotation - --> tests/ui/manual_rotate.rs:17:22 + --> tests/ui/manual_rotate.rs:25:22 | LL | let y_u32_plus = (x_u32 >> 8) + (x_u32 << 24); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: this expression can be rewritten as: `x_u32.rotate_right(8)` error: there is no need to manually implement bit rotation - --> tests/ui/manual_rotate.rs:19:25 + --> tests/ui/manual_rotate.rs:28:25 | LL | let y_u32_complex = ((x_u32 | 3256) >> 8) | ((x_u32 | 3256) << 24); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: this expression can be rewritten as: `(x_u32 | 3256).rotate_right(8)` error: there is no need to manually implement bit rotation - --> tests/ui/manual_rotate.rs:20:20 + --> tests/ui/manual_rotate.rs:30:20 | LL | let y_u64_as = (x_u32 as u64 >> 8) | ((x_u32 as u64) << 56); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: this expression can be rewritten as: `(x_u32 as u64).rotate_right(8)` diff --git a/tests/ui/manual_saturating_arithmetic.fixed b/tests/ui/manual_saturating_arithmetic.fixed index 528a65790c4c..3f73d6e5a1a6 100644 --- a/tests/ui/manual_saturating_arithmetic.fixed +++ b/tests/ui/manual_saturating_arithmetic.fixed @@ -4,38 +4,57 @@ use std::{i32, i128, u32, u128}; fn main() { let _ = 1u32.saturating_add(1); + //~^ manual_saturating_arithmetic let _ = 1u32.saturating_add(1); + //~^ manual_saturating_arithmetic let _ = 1u8.saturating_add(1); + //~^ manual_saturating_arithmetic let _ = 1u128.saturating_add(1); let _ = 1u32.checked_add(1).unwrap_or(1234); // ok let _ = 1u8.checked_add(1).unwrap_or(0); // ok let _ = 1u32.saturating_mul(1); + //~^ manual_saturating_arithmetic let _ = 1u32.saturating_sub(1); + //~^ manual_saturating_arithmetic let _ = 1u32.saturating_sub(1); + //~^ manual_saturating_arithmetic let _ = 1u8.saturating_sub(1); + //~^ manual_saturating_arithmetic let _ = 1u32.checked_sub(1).unwrap_or(1234); // ok let _ = 1u8.checked_sub(1).unwrap_or(255); // ok let _ = 1i32.saturating_add(1); + //~^ manual_saturating_arithmetic let _ = 1i32.saturating_add(1); + //~^ manual_saturating_arithmetic let _ = 1i8.saturating_add(1); + //~^ manual_saturating_arithmetic let _ = 1i128.saturating_add(1); let _ = 1i32.saturating_add(-1); + //~^ manual_saturating_arithmetic let _ = 1i32.saturating_add(-1); + //~^ manual_saturating_arithmetic let _ = 1i8.saturating_add(-1); + //~^ manual_saturating_arithmetic let _ = 1i128.saturating_add(-1); let _ = 1i32.checked_add(1).unwrap_or(1234); // ok let _ = 1i8.checked_add(1).unwrap_or(-128); // ok let _ = 1i8.checked_add(-1).unwrap_or(127); // ok let _ = 1i32.saturating_sub(1); + //~^ manual_saturating_arithmetic let _ = 1i32.saturating_sub(1); + //~^ manual_saturating_arithmetic let _ = 1i8.saturating_sub(1); + //~^ manual_saturating_arithmetic let _ = 1i128.saturating_sub(1); let _ = 1i32.saturating_sub(-1); + //~^ manual_saturating_arithmetic let _ = 1i32.saturating_sub(-1); + //~^ manual_saturating_arithmetic let _ = 1i8.saturating_sub(-1); + //~^ manual_saturating_arithmetic let _ = 1i128.saturating_sub(-1); let _ = 1i32.checked_sub(1).unwrap_or(1234); // ok let _ = 1i8.checked_sub(1).unwrap_or(127); // ok diff --git a/tests/ui/manual_saturating_arithmetic.rs b/tests/ui/manual_saturating_arithmetic.rs index 55f3720dfcc0..98246a5cd96c 100644 --- a/tests/ui/manual_saturating_arithmetic.rs +++ b/tests/ui/manual_saturating_arithmetic.rs @@ -4,31 +4,47 @@ use std::{i32, i128, u32, u128}; fn main() { let _ = 1u32.checked_add(1).unwrap_or(u32::max_value()); + //~^ manual_saturating_arithmetic let _ = 1u32.checked_add(1).unwrap_or(u32::MAX); + //~^ manual_saturating_arithmetic let _ = 1u8.checked_add(1).unwrap_or(255); + //~^ manual_saturating_arithmetic let _ = 1u128 + //~^ manual_saturating_arithmetic .checked_add(1) .unwrap_or(340_282_366_920_938_463_463_374_607_431_768_211_455); let _ = 1u32.checked_add(1).unwrap_or(1234); // ok let _ = 1u8.checked_add(1).unwrap_or(0); // ok let _ = 1u32.checked_mul(1).unwrap_or(u32::MAX); + //~^ manual_saturating_arithmetic let _ = 1u32.checked_sub(1).unwrap_or(u32::min_value()); + //~^ manual_saturating_arithmetic let _ = 1u32.checked_sub(1).unwrap_or(u32::MIN); + //~^ manual_saturating_arithmetic let _ = 1u8.checked_sub(1).unwrap_or(0); + //~^ manual_saturating_arithmetic let _ = 1u32.checked_sub(1).unwrap_or(1234); // ok let _ = 1u8.checked_sub(1).unwrap_or(255); // ok let _ = 1i32.checked_add(1).unwrap_or(i32::max_value()); + //~^ manual_saturating_arithmetic let _ = 1i32.checked_add(1).unwrap_or(i32::MAX); + //~^ manual_saturating_arithmetic let _ = 1i8.checked_add(1).unwrap_or(127); + //~^ manual_saturating_arithmetic let _ = 1i128 + //~^ manual_saturating_arithmetic .checked_add(1) .unwrap_or(170_141_183_460_469_231_731_687_303_715_884_105_727); let _ = 1i32.checked_add(-1).unwrap_or(i32::min_value()); + //~^ manual_saturating_arithmetic let _ = 1i32.checked_add(-1).unwrap_or(i32::MIN); + //~^ manual_saturating_arithmetic let _ = 1i8.checked_add(-1).unwrap_or(-128); + //~^ manual_saturating_arithmetic let _ = 1i128 + //~^ manual_saturating_arithmetic .checked_add(-1) .unwrap_or(-170_141_183_460_469_231_731_687_303_715_884_105_728); let _ = 1i32.checked_add(1).unwrap_or(1234); // ok @@ -36,15 +52,23 @@ fn main() { let _ = 1i8.checked_add(-1).unwrap_or(127); // ok let _ = 1i32.checked_sub(1).unwrap_or(i32::min_value()); + //~^ manual_saturating_arithmetic let _ = 1i32.checked_sub(1).unwrap_or(i32::MIN); + //~^ manual_saturating_arithmetic let _ = 1i8.checked_sub(1).unwrap_or(-128); + //~^ manual_saturating_arithmetic let _ = 1i128 + //~^ manual_saturating_arithmetic .checked_sub(1) .unwrap_or(-170_141_183_460_469_231_731_687_303_715_884_105_728); let _ = 1i32.checked_sub(-1).unwrap_or(i32::max_value()); + //~^ manual_saturating_arithmetic let _ = 1i32.checked_sub(-1).unwrap_or(i32::MAX); + //~^ manual_saturating_arithmetic let _ = 1i8.checked_sub(-1).unwrap_or(127); + //~^ manual_saturating_arithmetic let _ = 1i128 + //~^ manual_saturating_arithmetic .checked_sub(-1) .unwrap_or(170_141_183_460_469_231_731_687_303_715_884_105_727); let _ = 1i32.checked_sub(1).unwrap_or(1234); // ok diff --git a/tests/ui/manual_saturating_arithmetic.stderr b/tests/ui/manual_saturating_arithmetic.stderr index b6a8df0f84e1..9d133d8a073b 100644 --- a/tests/ui/manual_saturating_arithmetic.stderr +++ b/tests/ui/manual_saturating_arithmetic.stderr @@ -8,154 +8,159 @@ LL | let _ = 1u32.checked_add(1).unwrap_or(u32::max_value()); = help: to override `-D warnings` add `#[allow(clippy::manual_saturating_arithmetic)]` error: manual saturating arithmetic - --> tests/ui/manual_saturating_arithmetic.rs:7:13 + --> tests/ui/manual_saturating_arithmetic.rs:8:13 | LL | let _ = 1u32.checked_add(1).unwrap_or(u32::MAX); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1u32.saturating_add(1)` error: manual saturating arithmetic - --> tests/ui/manual_saturating_arithmetic.rs:8:13 + --> tests/ui/manual_saturating_arithmetic.rs:10:13 | LL | let _ = 1u8.checked_add(1).unwrap_or(255); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1u8.saturating_add(1)` error: manual saturating arithmetic - --> tests/ui/manual_saturating_arithmetic.rs:9:13 + --> tests/ui/manual_saturating_arithmetic.rs:12:13 | LL | let _ = 1u128 | _____________^ +LL | | LL | | .checked_add(1) LL | | .unwrap_or(340_282_366_920_938_463_463_374_607_431_768_211_455); | |_______________________________________________________________________^ help: consider using `saturating_add`: `1u128.saturating_add(1)` error: manual saturating arithmetic - --> tests/ui/manual_saturating_arithmetic.rs:14:13 + --> tests/ui/manual_saturating_arithmetic.rs:18:13 | LL | let _ = 1u32.checked_mul(1).unwrap_or(u32::MAX); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_mul`: `1u32.saturating_mul(1)` error: manual saturating arithmetic - --> tests/ui/manual_saturating_arithmetic.rs:16:13 + --> tests/ui/manual_saturating_arithmetic.rs:21:13 | LL | let _ = 1u32.checked_sub(1).unwrap_or(u32::min_value()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1u32.saturating_sub(1)` error: manual saturating arithmetic - --> tests/ui/manual_saturating_arithmetic.rs:17:13 + --> tests/ui/manual_saturating_arithmetic.rs:23:13 | LL | let _ = 1u32.checked_sub(1).unwrap_or(u32::MIN); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1u32.saturating_sub(1)` error: manual saturating arithmetic - --> tests/ui/manual_saturating_arithmetic.rs:18:13 + --> tests/ui/manual_saturating_arithmetic.rs:25:13 | LL | let _ = 1u8.checked_sub(1).unwrap_or(0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1u8.saturating_sub(1)` error: manual saturating arithmetic - --> tests/ui/manual_saturating_arithmetic.rs:22:13 + --> tests/ui/manual_saturating_arithmetic.rs:30:13 | LL | let _ = 1i32.checked_add(1).unwrap_or(i32::max_value()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1i32.saturating_add(1)` error: manual saturating arithmetic - --> tests/ui/manual_saturating_arithmetic.rs:23:13 + --> tests/ui/manual_saturating_arithmetic.rs:32:13 | LL | let _ = 1i32.checked_add(1).unwrap_or(i32::MAX); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1i32.saturating_add(1)` error: manual saturating arithmetic - --> tests/ui/manual_saturating_arithmetic.rs:24:13 + --> tests/ui/manual_saturating_arithmetic.rs:34:13 | LL | let _ = 1i8.checked_add(1).unwrap_or(127); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1i8.saturating_add(1)` error: manual saturating arithmetic - --> tests/ui/manual_saturating_arithmetic.rs:25:13 + --> tests/ui/manual_saturating_arithmetic.rs:36:13 | LL | let _ = 1i128 | _____________^ +LL | | LL | | .checked_add(1) LL | | .unwrap_or(170_141_183_460_469_231_731_687_303_715_884_105_727); | |_______________________________________________________________________^ help: consider using `saturating_add`: `1i128.saturating_add(1)` error: manual saturating arithmetic - --> tests/ui/manual_saturating_arithmetic.rs:28:13 + --> tests/ui/manual_saturating_arithmetic.rs:40:13 | LL | let _ = 1i32.checked_add(-1).unwrap_or(i32::min_value()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1i32.saturating_add(-1)` error: manual saturating arithmetic - --> tests/ui/manual_saturating_arithmetic.rs:29:13 + --> tests/ui/manual_saturating_arithmetic.rs:42:13 | LL | let _ = 1i32.checked_add(-1).unwrap_or(i32::MIN); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1i32.saturating_add(-1)` error: manual saturating arithmetic - --> tests/ui/manual_saturating_arithmetic.rs:30:13 + --> tests/ui/manual_saturating_arithmetic.rs:44:13 | LL | let _ = 1i8.checked_add(-1).unwrap_or(-128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1i8.saturating_add(-1)` error: manual saturating arithmetic - --> tests/ui/manual_saturating_arithmetic.rs:31:13 + --> tests/ui/manual_saturating_arithmetic.rs:46:13 | LL | let _ = 1i128 | _____________^ +LL | | LL | | .checked_add(-1) LL | | .unwrap_or(-170_141_183_460_469_231_731_687_303_715_884_105_728); | |________________________________________________________________________^ help: consider using `saturating_add`: `1i128.saturating_add(-1)` error: manual saturating arithmetic - --> tests/ui/manual_saturating_arithmetic.rs:38:13 + --> tests/ui/manual_saturating_arithmetic.rs:54:13 | LL | let _ = 1i32.checked_sub(1).unwrap_or(i32::min_value()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1i32.saturating_sub(1)` error: manual saturating arithmetic - --> tests/ui/manual_saturating_arithmetic.rs:39:13 + --> tests/ui/manual_saturating_arithmetic.rs:56:13 | LL | let _ = 1i32.checked_sub(1).unwrap_or(i32::MIN); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1i32.saturating_sub(1)` error: manual saturating arithmetic - --> tests/ui/manual_saturating_arithmetic.rs:40:13 + --> tests/ui/manual_saturating_arithmetic.rs:58:13 | LL | let _ = 1i8.checked_sub(1).unwrap_or(-128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1i8.saturating_sub(1)` error: manual saturating arithmetic - --> tests/ui/manual_saturating_arithmetic.rs:41:13 + --> tests/ui/manual_saturating_arithmetic.rs:60:13 | LL | let _ = 1i128 | _____________^ +LL | | LL | | .checked_sub(1) LL | | .unwrap_or(-170_141_183_460_469_231_731_687_303_715_884_105_728); | |________________________________________________________________________^ help: consider using `saturating_sub`: `1i128.saturating_sub(1)` error: manual saturating arithmetic - --> tests/ui/manual_saturating_arithmetic.rs:44:13 + --> tests/ui/manual_saturating_arithmetic.rs:64:13 | LL | let _ = 1i32.checked_sub(-1).unwrap_or(i32::max_value()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1i32.saturating_sub(-1)` error: manual saturating arithmetic - --> tests/ui/manual_saturating_arithmetic.rs:45:13 + --> tests/ui/manual_saturating_arithmetic.rs:66:13 | LL | let _ = 1i32.checked_sub(-1).unwrap_or(i32::MAX); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1i32.saturating_sub(-1)` error: manual saturating arithmetic - --> tests/ui/manual_saturating_arithmetic.rs:46:13 + --> tests/ui/manual_saturating_arithmetic.rs:68:13 | LL | let _ = 1i8.checked_sub(-1).unwrap_or(127); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1i8.saturating_sub(-1)` error: manual saturating arithmetic - --> tests/ui/manual_saturating_arithmetic.rs:47:13 + --> tests/ui/manual_saturating_arithmetic.rs:70:13 | LL | let _ = 1i128 | _____________^ +LL | | LL | | .checked_sub(-1) LL | | .unwrap_or(170_141_183_460_469_231_731_687_303_715_884_105_727); | |_______________________________________________________________________^ help: consider using `saturating_sub`: `1i128.saturating_sub(-1)` diff --git a/tests/ui/manual_slice_fill.fixed b/tests/ui/manual_slice_fill.fixed index 397a156a2dc7..bba863247f5d 100644 --- a/tests/ui/manual_slice_fill.fixed +++ b/tests/ui/manual_slice_fill.fixed @@ -1,5 +1,5 @@ #![warn(clippy::manual_slice_fill)] -#![allow(clippy::needless_range_loop)] +#![allow(clippy::needless_range_loop, clippy::useless_vec)] macro_rules! assign_element { ($slice:ident, $index:expr) => { @@ -99,3 +99,27 @@ fn should_not_lint() { *i = None; } } + +fn issue_14192() { + let mut tmp = vec![0; 3]; + + for i in 0..tmp.len() { + tmp[i] = i; + } + + for i in 0..tmp.len() { + tmp[i] = 2 + i; + } + + for i in 0..tmp.len() { + tmp[0] = i; + } +} + +fn issue14189() { + // Should not lint because `!*b` is not constant + let mut tmp = vec![1, 2, 3]; + for b in &mut tmp { + *b = !*b; + } +} diff --git a/tests/ui/manual_slice_fill.rs b/tests/ui/manual_slice_fill.rs index c25127ca613a..44c60dc40f07 100644 --- a/tests/ui/manual_slice_fill.rs +++ b/tests/ui/manual_slice_fill.rs @@ -1,5 +1,5 @@ #![warn(clippy::manual_slice_fill)] -#![allow(clippy::needless_range_loop)] +#![allow(clippy::needless_range_loop, clippy::useless_vec)] macro_rules! assign_element { ($slice:ident, $index:expr) => { @@ -23,21 +23,25 @@ fn should_lint() { let mut some_slice = [1, 2, 3, 4, 5]; for i in 0..some_slice.len() { + //~^ manual_slice_fill some_slice[i] = 0; } let x = 5; for i in 0..some_slice.len() { + //~^ manual_slice_fill some_slice[i] = x; } for i in &mut some_slice { + //~^ manual_slice_fill *i = 0; } // This should trigger `manual_slice_fill`, but the applicability is `MaybeIncorrect` since comments // within the loop might be purely informational. for i in 0..some_slice.len() { + //~^ manual_slice_fill some_slice[i] = 0; // foo } @@ -108,3 +112,27 @@ fn should_not_lint() { *i = None; } } + +fn issue_14192() { + let mut tmp = vec![0; 3]; + + for i in 0..tmp.len() { + tmp[i] = i; + } + + for i in 0..tmp.len() { + tmp[i] = 2 + i; + } + + for i in 0..tmp.len() { + tmp[0] = i; + } +} + +fn issue14189() { + // Should not lint because `!*b` is not constant + let mut tmp = vec![1, 2, 3]; + for b in &mut tmp { + *b = !*b; + } +} diff --git a/tests/ui/manual_slice_fill.stderr b/tests/ui/manual_slice_fill.stderr index 3aa980f69191..38e43d5b4e06 100644 --- a/tests/ui/manual_slice_fill.stderr +++ b/tests/ui/manual_slice_fill.stderr @@ -2,6 +2,7 @@ error: manually filling a slice --> tests/ui/manual_slice_fill.rs:25:5 | LL | / for i in 0..some_slice.len() { +LL | | LL | | some_slice[i] = 0; LL | | } | |_____^ help: try: `some_slice.fill(0);` @@ -10,25 +11,28 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::manual_slice_fill)]` error: manually filling a slice - --> tests/ui/manual_slice_fill.rs:30:5 + --> tests/ui/manual_slice_fill.rs:31:5 | LL | / for i in 0..some_slice.len() { +LL | | LL | | some_slice[i] = x; LL | | } | |_____^ help: try: `some_slice.fill(x);` error: manually filling a slice - --> tests/ui/manual_slice_fill.rs:34:5 + --> tests/ui/manual_slice_fill.rs:36:5 | LL | / for i in &mut some_slice { +LL | | LL | | *i = 0; LL | | } | |_____^ help: try: `some_slice.fill(0);` error: manually filling a slice - --> tests/ui/manual_slice_fill.rs:40:5 + --> tests/ui/manual_slice_fill.rs:43:5 | LL | / for i in 0..some_slice.len() { +LL | | LL | | some_slice[i] = 0; LL | | // foo LL | | } diff --git a/tests/ui/manual_slice_size_calculation.fixed b/tests/ui/manual_slice_size_calculation.fixed index 0603b30e3465..294d1e1506de 100644 --- a/tests/ui/manual_slice_size_calculation.fixed +++ b/tests/ui/manual_slice_size_calculation.fixed @@ -15,18 +15,35 @@ fn main() { // True positives: let _ = std::mem::size_of_val(s_i32); // WARNING + // + //~^^ manual_slice_size_calculation let _ = std::mem::size_of_val(s_i32); // WARNING + // + //~^^ manual_slice_size_calculation let _ = std::mem::size_of_val(s_i32) * 5; // WARNING + // + //~^^ manual_slice_size_calculation let _ = std::mem::size_of_val(*s_i32_ref); // WARNING + // + //~^^ manual_slice_size_calculation let _ = std::mem::size_of_val(**s_i32_ref_ref); // WARNING + // + //~^^ manual_slice_size_calculation let len = s_i32.len(); let size = size_of::(); let _ = std::mem::size_of_val(s_i32); // WARNING + // + //~^^ manual_slice_size_calculation let _ = std::mem::size_of_val(s_i32); // WARNING + // + //~^^ manual_slice_size_calculation let _ = std::mem::size_of_val(s_i32); // WARNING + // + //~^^ manual_slice_size_calculation let _ = std::mem::size_of_val(external!(&[1u64][..])); + //~^ manual_slice_size_calculation // True negatives: let _ = size_of::() + s_i32.len(); // Ok, not a multiplication diff --git a/tests/ui/manual_slice_size_calculation.rs b/tests/ui/manual_slice_size_calculation.rs index 14093e653c09..ae5225663139 100644 --- a/tests/ui/manual_slice_size_calculation.rs +++ b/tests/ui/manual_slice_size_calculation.rs @@ -15,18 +15,35 @@ fn main() { // True positives: let _ = s_i32.len() * size_of::(); // WARNING + // + //~^^ manual_slice_size_calculation let _ = size_of::() * s_i32.len(); // WARNING + // + //~^^ manual_slice_size_calculation let _ = size_of::() * s_i32.len() * 5; // WARNING + // + //~^^ manual_slice_size_calculation let _ = size_of::() * s_i32_ref.len(); // WARNING + // + //~^^ manual_slice_size_calculation let _ = size_of::() * s_i32_ref_ref.len(); // WARNING + // + //~^^ manual_slice_size_calculation let len = s_i32.len(); let size = size_of::(); let _ = len * size_of::(); // WARNING + // + //~^^ manual_slice_size_calculation let _ = s_i32.len() * size; // WARNING + // + //~^^ manual_slice_size_calculation let _ = len * size; // WARNING + // + //~^^ manual_slice_size_calculation let _ = external!(&[1u64][..]).len() * size_of::(); + //~^ manual_slice_size_calculation // True negatives: let _ = size_of::() + s_i32.len(); // Ok, not a multiplication diff --git a/tests/ui/manual_slice_size_calculation.stderr b/tests/ui/manual_slice_size_calculation.stderr index 0397f3a4969a..f07e97a1c863 100644 --- a/tests/ui/manual_slice_size_calculation.stderr +++ b/tests/ui/manual_slice_size_calculation.stderr @@ -8,49 +8,49 @@ LL | let _ = s_i32.len() * size_of::(); // WARNING = help: to override `-D warnings` add `#[allow(clippy::manual_slice_size_calculation)]` error: manual slice size calculation - --> tests/ui/manual_slice_size_calculation.rs:18:13 + --> tests/ui/manual_slice_size_calculation.rs:20:13 | LL | let _ = size_of::() * s_i32.len(); // WARNING | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)` error: manual slice size calculation - --> tests/ui/manual_slice_size_calculation.rs:19:13 + --> tests/ui/manual_slice_size_calculation.rs:23:13 | LL | let _ = size_of::() * s_i32.len() * 5; // WARNING | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)` error: manual slice size calculation - --> tests/ui/manual_slice_size_calculation.rs:20:13 + --> tests/ui/manual_slice_size_calculation.rs:26:13 | LL | let _ = size_of::() * s_i32_ref.len(); // WARNING | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(*s_i32_ref)` error: manual slice size calculation - --> tests/ui/manual_slice_size_calculation.rs:21:13 + --> tests/ui/manual_slice_size_calculation.rs:29:13 | LL | let _ = size_of::() * s_i32_ref_ref.len(); // WARNING | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(**s_i32_ref_ref)` error: manual slice size calculation - --> tests/ui/manual_slice_size_calculation.rs:25:13 + --> tests/ui/manual_slice_size_calculation.rs:35:13 | LL | let _ = len * size_of::(); // WARNING | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)` error: manual slice size calculation - --> tests/ui/manual_slice_size_calculation.rs:26:13 + --> tests/ui/manual_slice_size_calculation.rs:38:13 | LL | let _ = s_i32.len() * size; // WARNING | ^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)` error: manual slice size calculation - --> tests/ui/manual_slice_size_calculation.rs:27:13 + --> tests/ui/manual_slice_size_calculation.rs:41:13 | LL | let _ = len * size; // WARNING | ^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)` error: manual slice size calculation - --> tests/ui/manual_slice_size_calculation.rs:29:13 + --> tests/ui/manual_slice_size_calculation.rs:45:13 | LL | let _ = external!(&[1u64][..]).len() * size_of::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(external!(&[1u64][..]))` diff --git a/tests/ui/manual_split_once.fixed b/tests/ui/manual_split_once.fixed index aaac6a048e1d..76dfb99b787d 100644 --- a/tests/ui/manual_split_once.fixed +++ b/tests/ui/manual_split_once.fixed @@ -9,23 +9,33 @@ use itertools::Itertools; fn main() { let _ = "key=value".splitn(2, '=').nth(2); let _ = "key=value".split_once('=').unwrap().1; + //~^ manual_split_once let _ = "key=value".split_once('=').unwrap().1; + //~^ manual_split_once let (_, _) = "key=value".split_once('=').unwrap(); + //~^ manual_split_once let s = String::from("key=value"); let _ = s.split_once('=').unwrap().1; + //~^ manual_split_once let s = Box::::from("key=value"); let _ = s.split_once('=').unwrap().1; + //~^ manual_split_once let s = &"key=value"; let _ = s.split_once('=').unwrap().1; + //~^ manual_split_once fn _f(s: &str) -> Option<&str> { let _ = s.split_once('=')?.1; + //~^ manual_split_once let _ = s.split_once('=')?.1; + //~^ manual_split_once let _ = s.rsplit_once('=')?.0; + //~^ manual_split_once let _ = s.rsplit_once('=')?.0; + //~^ manual_split_once None } @@ -34,24 +44,31 @@ fn main() { // `rsplitn` gives the results in the reverse order of `rsplit_once` let _ = "key=value".rsplit_once('=').unwrap().0; + //~^ manual_split_once let (_, _) = "key=value".rsplit_once('=').map(|(x, y)| (y, x)).unwrap(); + //~^ manual_split_once let _ = s.rsplit_once('=').map(|x| x.0); + //~^ manual_split_once } fn indirect() -> Option<()> { let (l, r) = "a.b.c".split_once('.').unwrap(); + //~^ manual_split_once let (l, r) = "a.b.c".split_once('.')?; + //~^ manual_split_once let (l, r) = "a.b.c".rsplit_once('.').unwrap(); + //~^ manual_split_once let (l, r) = "a.b.c".rsplit_once('.')?; + //~^ manual_split_once @@ -137,8 +154,10 @@ fn _msrv_1_51() { #[clippy::msrv = "1.52"] fn _msrv_1_52() { let _ = "key=value".split_once('=').unwrap().1; + //~^ manual_split_once let (a, b) = "a.b.c".split_once('.').unwrap(); + //~^ manual_split_once } diff --git a/tests/ui/manual_split_once.rs b/tests/ui/manual_split_once.rs index 113e1737c97d..73602fae3d82 100644 --- a/tests/ui/manual_split_once.rs +++ b/tests/ui/manual_split_once.rs @@ -9,23 +9,33 @@ use itertools::Itertools; fn main() { let _ = "key=value".splitn(2, '=').nth(2); let _ = "key=value".splitn(2, '=').nth(1).unwrap(); + //~^ manual_split_once let _ = "key=value".splitn(2, '=').skip(1).next().unwrap(); + //~^ manual_split_once let (_, _) = "key=value".splitn(2, '=').next_tuple().unwrap(); + //~^ manual_split_once let s = String::from("key=value"); let _ = s.splitn(2, '=').nth(1).unwrap(); + //~^ manual_split_once let s = Box::::from("key=value"); let _ = s.splitn(2, '=').nth(1).unwrap(); + //~^ manual_split_once let s = &"key=value"; let _ = s.splitn(2, '=').skip(1).next().unwrap(); + //~^ manual_split_once fn _f(s: &str) -> Option<&str> { let _ = s.splitn(2, '=').nth(1)?; + //~^ manual_split_once let _ = s.splitn(2, '=').skip(1).next()?; + //~^ manual_split_once let _ = s.rsplitn(2, '=').nth(1)?; + //~^ manual_split_once let _ = s.rsplitn(2, '=').skip(1).next()?; + //~^ manual_split_once None } @@ -34,24 +44,31 @@ fn main() { // `rsplitn` gives the results in the reverse order of `rsplit_once` let _ = "key=value".rsplitn(2, '=').nth(1).unwrap(); + //~^ manual_split_once let (_, _) = "key=value".rsplitn(2, '=').next_tuple().unwrap(); + //~^ manual_split_once let _ = s.rsplitn(2, '=').nth(1); + //~^ manual_split_once } fn indirect() -> Option<()> { let mut iter = "a.b.c".splitn(2, '.'); + //~^ manual_split_once let l = iter.next().unwrap(); let r = iter.next().unwrap(); let mut iter = "a.b.c".splitn(2, '.'); + //~^ manual_split_once let l = iter.next()?; let r = iter.next()?; let mut iter = "a.b.c".rsplitn(2, '.'); + //~^ manual_split_once let r = iter.next().unwrap(); let l = iter.next().unwrap(); let mut iter = "a.b.c".rsplitn(2, '.'); + //~^ manual_split_once let r = iter.next()?; let l = iter.next()?; @@ -137,8 +154,10 @@ fn _msrv_1_51() { #[clippy::msrv = "1.52"] fn _msrv_1_52() { let _ = "key=value".splitn(2, '=').nth(1).unwrap(); + //~^ manual_split_once let mut iter = "a.b.c".splitn(2, '.'); + //~^ manual_split_once let a = iter.next().unwrap(); let b = iter.next().unwrap(); } diff --git a/tests/ui/manual_split_once.stderr b/tests/ui/manual_split_once.stderr index 366d860f25ef..2a44f6e7438c 100644 --- a/tests/ui/manual_split_once.stderr +++ b/tests/ui/manual_split_once.stderr @@ -8,23 +8,17 @@ LL | let _ = "key=value".splitn(2, '=').nth(1).unwrap(); = help: to override `-D warnings` add `#[allow(clippy::manual_split_once)]` error: manual implementation of `split_once` - --> tests/ui/manual_split_once.rs:12:13 + --> tests/ui/manual_split_once.rs:13:13 | LL | let _ = "key=value".splitn(2, '=').skip(1).next().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".split_once('=').unwrap().1` error: manual implementation of `split_once` - --> tests/ui/manual_split_once.rs:13:18 + --> tests/ui/manual_split_once.rs:15:18 | LL | let (_, _) = "key=value".splitn(2, '=').next_tuple().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".split_once('=')` -error: manual implementation of `split_once` - --> tests/ui/manual_split_once.rs:16:13 - | -LL | let _ = s.splitn(2, '=').nth(1).unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.split_once('=').unwrap().1` - error: manual implementation of `split_once` --> tests/ui/manual_split_once.rs:19:13 | @@ -32,58 +26,65 @@ LL | let _ = s.splitn(2, '=').nth(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.split_once('=').unwrap().1` error: manual implementation of `split_once` - --> tests/ui/manual_split_once.rs:22:13 + --> tests/ui/manual_split_once.rs:23:13 + | +LL | let _ = s.splitn(2, '=').nth(1).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.split_once('=').unwrap().1` + +error: manual implementation of `split_once` + --> tests/ui/manual_split_once.rs:27:13 | LL | let _ = s.splitn(2, '=').skip(1).next().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.split_once('=').unwrap().1` error: manual implementation of `split_once` - --> tests/ui/manual_split_once.rs:25:17 + --> tests/ui/manual_split_once.rs:31:17 | LL | let _ = s.splitn(2, '=').nth(1)?; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.split_once('=')?.1` error: manual implementation of `split_once` - --> tests/ui/manual_split_once.rs:26:17 + --> tests/ui/manual_split_once.rs:33:17 | LL | let _ = s.splitn(2, '=').skip(1).next()?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.split_once('=')?.1` error: manual implementation of `rsplit_once` - --> tests/ui/manual_split_once.rs:27:17 + --> tests/ui/manual_split_once.rs:35:17 | LL | let _ = s.rsplitn(2, '=').nth(1)?; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.rsplit_once('=')?.0` error: manual implementation of `rsplit_once` - --> tests/ui/manual_split_once.rs:28:17 + --> tests/ui/manual_split_once.rs:37:17 | LL | let _ = s.rsplitn(2, '=').skip(1).next()?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.rsplit_once('=')?.0` error: manual implementation of `rsplit_once` - --> tests/ui/manual_split_once.rs:36:13 + --> tests/ui/manual_split_once.rs:46:13 | LL | let _ = "key=value".rsplitn(2, '=').nth(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".rsplit_once('=').unwrap().0` error: manual implementation of `rsplit_once` - --> tests/ui/manual_split_once.rs:37:18 + --> tests/ui/manual_split_once.rs:48:18 | LL | let (_, _) = "key=value".rsplitn(2, '=').next_tuple().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".rsplit_once('=').map(|(x, y)| (y, x))` error: manual implementation of `rsplit_once` - --> tests/ui/manual_split_once.rs:38:13 + --> tests/ui/manual_split_once.rs:50:13 | LL | let _ = s.rsplitn(2, '=').nth(1); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.rsplit_once('=').map(|x| x.0)` error: manual implementation of `split_once` - --> tests/ui/manual_split_once.rs:42:5 + --> tests/ui/manual_split_once.rs:55:5 | LL | let mut iter = "a.b.c".splitn(2, '.'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | LL | let l = iter.next().unwrap(); | ----------------------------- first usage here LL | let r = iter.next().unwrap(); @@ -92,15 +93,17 @@ LL | let r = iter.next().unwrap(); help: replace with `split_once` | LL ~ let (l, r) = "a.b.c".split_once('.').unwrap(); +LL | LL ~ LL ~ | error: manual implementation of `split_once` - --> tests/ui/manual_split_once.rs:46:5 + --> tests/ui/manual_split_once.rs:60:5 | LL | let mut iter = "a.b.c".splitn(2, '.'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | LL | let l = iter.next()?; | --------------------- first usage here LL | let r = iter.next()?; @@ -109,15 +112,17 @@ LL | let r = iter.next()?; help: replace with `split_once` | LL ~ let (l, r) = "a.b.c".split_once('.')?; +LL | LL ~ LL ~ | error: manual implementation of `rsplit_once` - --> tests/ui/manual_split_once.rs:50:5 + --> tests/ui/manual_split_once.rs:65:5 | LL | let mut iter = "a.b.c".rsplitn(2, '.'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | LL | let r = iter.next().unwrap(); | ----------------------------- first usage here LL | let l = iter.next().unwrap(); @@ -126,15 +131,17 @@ LL | let l = iter.next().unwrap(); help: replace with `rsplit_once` | LL ~ let (l, r) = "a.b.c".rsplit_once('.').unwrap(); +LL | LL ~ LL ~ | error: manual implementation of `rsplit_once` - --> tests/ui/manual_split_once.rs:54:5 + --> tests/ui/manual_split_once.rs:70:5 | LL | let mut iter = "a.b.c".rsplitn(2, '.'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | LL | let r = iter.next()?; | --------------------- first usage here LL | let l = iter.next()?; @@ -143,21 +150,23 @@ LL | let l = iter.next()?; help: replace with `rsplit_once` | LL ~ let (l, r) = "a.b.c".rsplit_once('.')?; +LL | LL ~ LL ~ | error: manual implementation of `split_once` - --> tests/ui/manual_split_once.rs:139:13 + --> tests/ui/manual_split_once.rs:156:13 | LL | let _ = "key=value".splitn(2, '=').nth(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".split_once('=').unwrap().1` error: manual implementation of `split_once` - --> tests/ui/manual_split_once.rs:141:5 + --> tests/ui/manual_split_once.rs:159:5 | LL | let mut iter = "a.b.c".splitn(2, '.'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | LL | let a = iter.next().unwrap(); | ----------------------------- first usage here LL | let b = iter.next().unwrap(); @@ -166,6 +175,7 @@ LL | let b = iter.next().unwrap(); help: replace with `split_once` | LL ~ let (a, b) = "a.b.c".split_once('.').unwrap(); +LL | LL ~ LL ~ | diff --git a/tests/ui/manual_str_repeat.fixed b/tests/ui/manual_str_repeat.fixed index da6f36f53b0d..bbe4260f6bc8 100644 --- a/tests/ui/manual_str_repeat.fixed +++ b/tests/ui/manual_str_repeat.fixed @@ -6,13 +6,18 @@ use std::iter::repeat; fn main() { let _: String = "test".repeat(10); + //~^ manual_str_repeat let _: String = "x".repeat(10); + //~^ manual_str_repeat let _: String = "'".repeat(10); + //~^ manual_str_repeat let _: String = "\"".repeat(10); + //~^ manual_str_repeat let x = "test"; let count = 10; let _ = x.repeat(count + 2); + //~^ manual_str_repeat macro_rules! m { ($e:expr) => {{ $e }}; @@ -22,6 +27,7 @@ fn main() { let x = &x; let _: String = (*x).repeat(count); + //~^ manual_str_repeat macro_rules! repeat_m { ($e:expr) => {{ repeat($e) }}; @@ -31,6 +37,7 @@ fn main() { let x: Box = Box::from("test"); let _: String = x.repeat(count); + //~^ manual_str_repeat #[derive(Clone)] struct S; @@ -43,9 +50,11 @@ fn main() { let _: String = repeat(Box::new(S)).take(count).collect(); let _: String = Cow::Borrowed("test").repeat(count); + //~^ manual_str_repeat let x = "x".to_owned(); let _: String = x.repeat(count); + //~^ manual_str_repeat let x = 'x'; // Don't lint, not char literal @@ -61,4 +70,5 @@ fn _msrv_1_15() { #[clippy::msrv = "1.16"] fn _msrv_1_16() { let _: String = "test".repeat(10); + //~^ manual_str_repeat } diff --git a/tests/ui/manual_str_repeat.rs b/tests/ui/manual_str_repeat.rs index 686ed4fee7d1..38d2eb4fcad8 100644 --- a/tests/ui/manual_str_repeat.rs +++ b/tests/ui/manual_str_repeat.rs @@ -6,13 +6,18 @@ use std::iter::repeat; fn main() { let _: String = std::iter::repeat("test").take(10).collect(); + //~^ manual_str_repeat let _: String = std::iter::repeat('x').take(10).collect(); + //~^ manual_str_repeat let _: String = std::iter::repeat('\'').take(10).collect(); + //~^ manual_str_repeat let _: String = std::iter::repeat('"').take(10).collect(); + //~^ manual_str_repeat let x = "test"; let count = 10; let _ = repeat(x).take(count + 2).collect::(); + //~^ manual_str_repeat macro_rules! m { ($e:expr) => {{ $e }}; @@ -22,6 +27,7 @@ fn main() { let x = &x; let _: String = repeat(*x).take(count).collect(); + //~^ manual_str_repeat macro_rules! repeat_m { ($e:expr) => {{ repeat($e) }}; @@ -31,6 +37,7 @@ fn main() { let x: Box = Box::from("test"); let _: String = repeat(x).take(count).collect(); + //~^ manual_str_repeat #[derive(Clone)] struct S; @@ -43,9 +50,11 @@ fn main() { let _: String = repeat(Box::new(S)).take(count).collect(); let _: String = repeat(Cow::Borrowed("test")).take(count).collect(); + //~^ manual_str_repeat let x = "x".to_owned(); let _: String = repeat(x).take(count).collect(); + //~^ manual_str_repeat let x = 'x'; // Don't lint, not char literal @@ -61,4 +70,5 @@ fn _msrv_1_15() { #[clippy::msrv = "1.16"] fn _msrv_1_16() { let _: String = std::iter::repeat("test").take(10).collect(); + //~^ manual_str_repeat } diff --git a/tests/ui/manual_str_repeat.stderr b/tests/ui/manual_str_repeat.stderr index d4f8786fb5f1..7998c3f6d97c 100644 --- a/tests/ui/manual_str_repeat.stderr +++ b/tests/ui/manual_str_repeat.stderr @@ -8,55 +8,55 @@ LL | let _: String = std::iter::repeat("test").take(10).collect(); = help: to override `-D warnings` add `#[allow(clippy::manual_str_repeat)]` error: manual implementation of `str::repeat` using iterators - --> tests/ui/manual_str_repeat.rs:9:21 + --> tests/ui/manual_str_repeat.rs:10:21 | LL | let _: String = std::iter::repeat('x').take(10).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"x".repeat(10)` error: manual implementation of `str::repeat` using iterators - --> tests/ui/manual_str_repeat.rs:10:21 + --> tests/ui/manual_str_repeat.rs:12:21 | LL | let _: String = std::iter::repeat('\'').take(10).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"'".repeat(10)` error: manual implementation of `str::repeat` using iterators - --> tests/ui/manual_str_repeat.rs:11:21 + --> tests/ui/manual_str_repeat.rs:14:21 | LL | let _: String = std::iter::repeat('"').take(10).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"\"".repeat(10)` error: manual implementation of `str::repeat` using iterators - --> tests/ui/manual_str_repeat.rs:15:13 + --> tests/ui/manual_str_repeat.rs:19:13 | LL | let _ = repeat(x).take(count + 2).collect::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.repeat(count + 2)` error: manual implementation of `str::repeat` using iterators - --> tests/ui/manual_str_repeat.rs:24:21 + --> tests/ui/manual_str_repeat.rs:29:21 | LL | let _: String = repeat(*x).take(count).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(*x).repeat(count)` error: manual implementation of `str::repeat` using iterators - --> tests/ui/manual_str_repeat.rs:33:21 + --> tests/ui/manual_str_repeat.rs:39:21 | LL | let _: String = repeat(x).take(count).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.repeat(count)` error: manual implementation of `str::repeat` using iterators - --> tests/ui/manual_str_repeat.rs:45:21 + --> tests/ui/manual_str_repeat.rs:52:21 | LL | let _: String = repeat(Cow::Borrowed("test")).take(count).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Cow::Borrowed("test").repeat(count)` error: manual implementation of `str::repeat` using iterators - --> tests/ui/manual_str_repeat.rs:48:21 + --> tests/ui/manual_str_repeat.rs:56:21 | LL | let _: String = repeat(x).take(count).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.repeat(count)` error: manual implementation of `str::repeat` using iterators - --> tests/ui/manual_str_repeat.rs:63:21 + --> tests/ui/manual_str_repeat.rs:72:21 | LL | let _: String = std::iter::repeat("test").take(10).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"test".repeat(10)` diff --git a/tests/ui/manual_string_new.fixed b/tests/ui/manual_string_new.fixed index 2d4c5a029153..02eeb603891a 100644 --- a/tests/ui/manual_string_new.fixed +++ b/tests/ui/manual_string_new.fixed @@ -12,12 +12,15 @@ macro_rules! create_strings_from_macro { fn main() { // Method calls let _ = String::new(); + //~^ manual_string_new let _ = "no warning".to_string(); let _ = String::new(); + //~^ manual_string_new let _ = "no warning".to_owned(); let _: String = String::new(); + //~^ manual_string_new let _: String = "no warning".into(); let _: SomeOtherStruct = "no warning".into(); @@ -25,26 +28,32 @@ fn main() { // Calls let _ = String::new(); + //~^ manual_string_new let _ = String::new(); + //~^ manual_string_new let _ = String::from("no warning"); let _ = SomeOtherStruct::from("no warning"); let _ = SomeOtherStruct::from(""); // Again: no warning. let _ = String::new(); + //~^ manual_string_new let _ = String::try_from("no warning").unwrap(); let _ = String::try_from("no warning").expect("this should not warn"); let _ = SomeOtherStruct::try_from("no warning").unwrap(); let _ = SomeOtherStruct::try_from("").unwrap(); // Again: no warning. let _: String = String::new(); + //~^ manual_string_new let _: String = From::from("no warning"); let _: SomeOtherStruct = From::from("no warning"); let _: SomeOtherStruct = From::from(""); // Again: no warning. let _: String = String::new(); + //~^ manual_string_new let _: String = TryFrom::try_from("no warning").unwrap(); let _: String = TryFrom::try_from("no warning").expect("this should not warn"); let _: String = String::new(); + //~^ manual_string_new let _: SomeOtherStruct = TryFrom::try_from("no_warning").unwrap(); let _: SomeOtherStruct = TryFrom::try_from("").unwrap(); // Again: no warning. diff --git a/tests/ui/manual_string_new.rs b/tests/ui/manual_string_new.rs index 20f0be6aaf97..fb4f58abad26 100644 --- a/tests/ui/manual_string_new.rs +++ b/tests/ui/manual_string_new.rs @@ -12,12 +12,15 @@ macro_rules! create_strings_from_macro { fn main() { // Method calls let _ = "".to_string(); + //~^ manual_string_new let _ = "no warning".to_string(); let _ = "".to_owned(); + //~^ manual_string_new let _ = "no warning".to_owned(); let _: String = "".into(); + //~^ manual_string_new let _: String = "no warning".into(); let _: SomeOtherStruct = "no warning".into(); @@ -25,26 +28,32 @@ fn main() { // Calls let _ = String::from(""); + //~^ manual_string_new let _ = ::from(""); + //~^ manual_string_new let _ = String::from("no warning"); let _ = SomeOtherStruct::from("no warning"); let _ = SomeOtherStruct::from(""); // Again: no warning. let _ = String::try_from("").unwrap(); + //~^ manual_string_new let _ = String::try_from("no warning").unwrap(); let _ = String::try_from("no warning").expect("this should not warn"); let _ = SomeOtherStruct::try_from("no warning").unwrap(); let _ = SomeOtherStruct::try_from("").unwrap(); // Again: no warning. let _: String = From::from(""); + //~^ manual_string_new let _: String = From::from("no warning"); let _: SomeOtherStruct = From::from("no warning"); let _: SomeOtherStruct = From::from(""); // Again: no warning. let _: String = TryFrom::try_from("").unwrap(); + //~^ manual_string_new let _: String = TryFrom::try_from("no warning").unwrap(); let _: String = TryFrom::try_from("no warning").expect("this should not warn"); let _: String = TryFrom::try_from("").expect("this should warn"); + //~^ manual_string_new let _: SomeOtherStruct = TryFrom::try_from("no_warning").unwrap(); let _: SomeOtherStruct = TryFrom::try_from("").unwrap(); // Again: no warning. diff --git a/tests/ui/manual_string_new.stderr b/tests/ui/manual_string_new.stderr index 6b434f405d31..2d98501f62d4 100644 --- a/tests/ui/manual_string_new.stderr +++ b/tests/ui/manual_string_new.stderr @@ -8,49 +8,49 @@ LL | let _ = "".to_string(); = help: to override `-D warnings` add `#[allow(clippy::manual_string_new)]` error: empty String is being created manually - --> tests/ui/manual_string_new.rs:17:13 + --> tests/ui/manual_string_new.rs:18:13 | LL | let _ = "".to_owned(); | ^^^^^^^^^^^^^ help: consider using: `String::new()` error: empty String is being created manually - --> tests/ui/manual_string_new.rs:20:21 + --> tests/ui/manual_string_new.rs:22:21 | LL | let _: String = "".into(); | ^^^^^^^^^ help: consider using: `String::new()` error: empty String is being created manually - --> tests/ui/manual_string_new.rs:27:13 + --> tests/ui/manual_string_new.rs:30:13 | LL | let _ = String::from(""); | ^^^^^^^^^^^^^^^^ help: consider using: `String::new()` error: empty String is being created manually - --> tests/ui/manual_string_new.rs:28:13 + --> tests/ui/manual_string_new.rs:32:13 | LL | let _ = ::from(""); | ^^^^^^^^^^^^^^^^^^ help: consider using: `String::new()` error: empty String is being created manually - --> tests/ui/manual_string_new.rs:33:13 + --> tests/ui/manual_string_new.rs:38:13 | LL | let _ = String::try_from("").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `String::new()` error: empty String is being created manually - --> tests/ui/manual_string_new.rs:39:21 + --> tests/ui/manual_string_new.rs:45:21 | LL | let _: String = From::from(""); | ^^^^^^^^^^^^^^ help: consider using: `String::new()` error: empty String is being created manually - --> tests/ui/manual_string_new.rs:44:21 + --> tests/ui/manual_string_new.rs:51:21 | LL | let _: String = TryFrom::try_from("").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `String::new()` error: empty String is being created manually - --> tests/ui/manual_string_new.rs:47:21 + --> tests/ui/manual_string_new.rs:55:21 | LL | let _: String = TryFrom::try_from("").expect("this should warn"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `String::new()` diff --git a/tests/ui/manual_strip.rs b/tests/ui/manual_strip.rs index 8bd0300e6bcc..086b75a39875 100644 --- a/tests/ui/manual_strip.rs +++ b/tests/ui/manual_strip.rs @@ -5,7 +5,8 @@ fn main() { if s.starts_with("ab") { str::to_string(&s["ab".len()..]); - //~^ ERROR: stripping a prefix manually + //~^ manual_strip + s["ab".len()..].to_string(); str::to_string(&s[2..]); @@ -14,7 +15,8 @@ fn main() { if s.ends_with("bc") { str::to_string(&s[..s.len() - "bc".len()]); - //~^ ERROR: stripping a suffix manually + //~^ manual_strip + s[..s.len() - "bc".len()].to_string(); str::to_string(&s[..s.len() - 2]); @@ -24,7 +26,8 @@ fn main() { // Character patterns if s.starts_with('a') { str::to_string(&s[1..]); - //~^ ERROR: stripping a prefix manually + //~^ manual_strip + s[1..].to_string(); } @@ -32,14 +35,15 @@ fn main() { let prefix = "ab"; if s.starts_with(prefix) { str::to_string(&s[prefix.len()..]); - //~^ ERROR: stripping a prefix manually + //~^ manual_strip } // Constant prefix const PREFIX: &str = "ab"; if s.starts_with(PREFIX) { str::to_string(&s[PREFIX.len()..]); - //~^ ERROR: stripping a prefix manually + //~^ manual_strip + str::to_string(&s[2..]); } @@ -47,14 +51,14 @@ fn main() { const TARGET: &str = "abc"; if TARGET.starts_with(prefix) { str::to_string(&TARGET[prefix.len()..]); - //~^ ERROR: stripping a prefix manually + //~^ manual_strip } // String target - not mutated. let s1: String = "abc".into(); if s1.starts_with("ab") { s1[2..].to_uppercase(); - //~^ ERROR: stripping a prefix manually + //~^ manual_strip } // String target - mutated. (Don't lint.) @@ -70,6 +74,23 @@ fn main() { if s3.starts_with("ab") { s4[2..].to_string(); } + + // Don't propose to reuse the `stripped` identifier as it is overriden + if s.starts_with("ab") { + let stripped = &s["ab".len()..]; + //~^ ERROR: stripping a prefix manually + let stripped = format!("{stripped}-"); + println!("{stripped}{}", &s["ab".len()..]); + } + + // Don't propose to reuse the `stripped` identifier as it is mutable + if s.starts_with("ab") { + let mut stripped = &s["ab".len()..]; + //~^ ERROR: stripping a prefix manually + stripped = ""; + let stripped = format!("{stripped}-"); + println!("{stripped}{}", &s["ab".len()..]); + } } #[clippy::msrv = "1.44"] @@ -85,6 +106,6 @@ fn msrv_1_45() { let s = "abc"; if s.starts_with('a') { s[1..].to_string(); - //~^ ERROR: stripping a prefix manually + //~^ manual_strip } } diff --git a/tests/ui/manual_strip.stderr b/tests/ui/manual_strip.stderr index a70c988a0549..a323ef700e76 100644 --- a/tests/ui/manual_strip.stderr +++ b/tests/ui/manual_strip.stderr @@ -16,6 +16,7 @@ help: try using the `strip_prefix` method LL ~ if let Some() = s.strip_prefix("ab") { LL ~ str::to_string(); LL | +LL | LL ~ .to_string(); LL | LL ~ str::to_string(); @@ -23,13 +24,13 @@ LL ~ .to_string(); | error: stripping a suffix manually - --> tests/ui/manual_strip.rs:16:24 + --> tests/ui/manual_strip.rs:17:24 | LL | str::to_string(&s[..s.len() - "bc".len()]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the suffix was tested here - --> tests/ui/manual_strip.rs:15:5 + --> tests/ui/manual_strip.rs:16:5 | LL | if s.ends_with("bc") { | ^^^^^^^^^^^^^^^^^^^^^ @@ -38,6 +39,7 @@ help: try using the `strip_suffix` method LL ~ if let Some() = s.strip_suffix("bc") { LL ~ str::to_string(); LL | +LL | LL ~ .to_string(); LL | LL ~ str::to_string(); @@ -45,13 +47,13 @@ LL ~ .to_string(); | error: stripping a prefix manually - --> tests/ui/manual_strip.rs:26:24 + --> tests/ui/manual_strip.rs:28:24 | LL | str::to_string(&s[1..]); | ^^^^^^^ | note: the prefix was tested here - --> tests/ui/manual_strip.rs:25:5 + --> tests/ui/manual_strip.rs:27:5 | LL | if s.starts_with('a') { | ^^^^^^^^^^^^^^^^^^^^^^ @@ -60,17 +62,18 @@ help: try using the `strip_prefix` method LL ~ if let Some() = s.strip_prefix('a') { LL ~ str::to_string(); LL | +LL | LL ~ .to_string(); | error: stripping a prefix manually - --> tests/ui/manual_strip.rs:34:24 + --> tests/ui/manual_strip.rs:37:24 | LL | str::to_string(&s[prefix.len()..]); | ^^^^^^^^^^^^^^^^^^ | note: the prefix was tested here - --> tests/ui/manual_strip.rs:33:5 + --> tests/ui/manual_strip.rs:36:5 | LL | if s.starts_with(prefix) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -81,13 +84,13 @@ LL ~ str::to_string(); | error: stripping a prefix manually - --> tests/ui/manual_strip.rs:41:24 + --> tests/ui/manual_strip.rs:44:24 | LL | str::to_string(&s[PREFIX.len()..]); | ^^^^^^^^^^^^^^^^^^ | note: the prefix was tested here - --> tests/ui/manual_strip.rs:40:5 + --> tests/ui/manual_strip.rs:43:5 | LL | if s.starts_with(PREFIX) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -96,17 +99,18 @@ help: try using the `strip_prefix` method LL ~ if let Some() = s.strip_prefix(PREFIX) { LL ~ str::to_string(); LL | +LL | LL ~ str::to_string(); | error: stripping a prefix manually - --> tests/ui/manual_strip.rs:49:24 + --> tests/ui/manual_strip.rs:53:24 | LL | str::to_string(&TARGET[prefix.len()..]); | ^^^^^^^^^^^^^^^^^^^^^^^ | note: the prefix was tested here - --> tests/ui/manual_strip.rs:48:5 + --> tests/ui/manual_strip.rs:52:5 | LL | if TARGET.starts_with(prefix) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -117,13 +121,13 @@ LL ~ str::to_string(); | error: stripping a prefix manually - --> tests/ui/manual_strip.rs:56:9 + --> tests/ui/manual_strip.rs:60:9 | LL | s1[2..].to_uppercase(); | ^^^^^^^ | note: the prefix was tested here - --> tests/ui/manual_strip.rs:55:5 + --> tests/ui/manual_strip.rs:59:5 | LL | if s1.starts_with("ab") { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -134,13 +138,54 @@ LL ~ .to_uppercase(); | error: stripping a prefix manually - --> tests/ui/manual_strip.rs:87:9 + --> tests/ui/manual_strip.rs:80:24 + | +LL | let stripped = &s["ab".len()..]; + | ^^^^^^^^^^^^^^^^ + | +note: the prefix was tested here + --> tests/ui/manual_strip.rs:79:5 + | +LL | if s.starts_with("ab") { + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: try using the `strip_prefix` method + | +LL ~ if let Some() = s.strip_prefix("ab") { +LL ~ let stripped = ; +LL | +LL | let stripped = format!("{stripped}-"); +LL ~ println!("{stripped}{}", ); + | + +error: stripping a prefix manually + --> tests/ui/manual_strip.rs:88:28 + | +LL | let mut stripped = &s["ab".len()..]; + | ^^^^^^^^^^^^^^^^ + | +note: the prefix was tested here + --> tests/ui/manual_strip.rs:87:5 + | +LL | if s.starts_with("ab") { + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: try using the `strip_prefix` method + | +LL ~ if let Some() = s.strip_prefix("ab") { +LL ~ let mut stripped = ; +LL | +LL | stripped = ""; +LL | let stripped = format!("{stripped}-"); +LL ~ println!("{stripped}{}", ); + | + +error: stripping a prefix manually + --> tests/ui/manual_strip.rs:108:9 | LL | s[1..].to_string(); | ^^^^^^ | note: the prefix was tested here - --> tests/ui/manual_strip.rs:86:5 + --> tests/ui/manual_strip.rs:107:5 | LL | if s.starts_with('a') { | ^^^^^^^^^^^^^^^^^^^^^^ @@ -150,5 +195,5 @@ LL ~ if let Some() = s.strip_prefix('a') { LL ~ .to_string(); | -error: aborting due to 8 previous errors +error: aborting due to 10 previous errors diff --git a/tests/ui/manual_strip_fixable.fixed b/tests/ui/manual_strip_fixable.fixed new file mode 100644 index 000000000000..75a3f1645de3 --- /dev/null +++ b/tests/ui/manual_strip_fixable.fixed @@ -0,0 +1,15 @@ +#![warn(clippy::manual_strip)] + +fn main() { + let s = "abc"; + + if let Some(stripped) = s.strip_prefix("ab") { + //~^ ERROR: stripping a prefix manually + println!("{stripped}{}", stripped); + } + + if let Some(stripped) = s.strip_suffix("bc") { + //~^ ERROR: stripping a suffix manually + println!("{stripped}{}", stripped); + } +} diff --git a/tests/ui/manual_strip_fixable.rs b/tests/ui/manual_strip_fixable.rs new file mode 100644 index 000000000000..5080068449e2 --- /dev/null +++ b/tests/ui/manual_strip_fixable.rs @@ -0,0 +1,17 @@ +#![warn(clippy::manual_strip)] + +fn main() { + let s = "abc"; + + if s.starts_with("ab") { + let stripped = &s["ab".len()..]; + //~^ ERROR: stripping a prefix manually + println!("{stripped}{}", &s["ab".len()..]); + } + + if s.ends_with("bc") { + let stripped = &s[..s.len() - "bc".len()]; + //~^ ERROR: stripping a suffix manually + println!("{stripped}{}", &s[..s.len() - "bc".len()]); + } +} diff --git a/tests/ui/manual_strip_fixable.stderr b/tests/ui/manual_strip_fixable.stderr new file mode 100644 index 000000000000..1c276e5d8fdf --- /dev/null +++ b/tests/ui/manual_strip_fixable.stderr @@ -0,0 +1,40 @@ +error: stripping a prefix manually + --> tests/ui/manual_strip_fixable.rs:7:24 + | +LL | let stripped = &s["ab".len()..]; + | ^^^^^^^^^^^^^^^^ + | +note: the prefix was tested here + --> tests/ui/manual_strip_fixable.rs:6:5 + | +LL | if s.starts_with("ab") { + | ^^^^^^^^^^^^^^^^^^^^^^^ + = note: `-D clippy::manual-strip` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_strip)]` +help: try using the `strip_prefix` method + | +LL ~ if let Some(stripped) = s.strip_prefix("ab") { +LL ~ +LL ~ println!("{stripped}{}", stripped); + | + +error: stripping a suffix manually + --> tests/ui/manual_strip_fixable.rs:13:24 + | +LL | let stripped = &s[..s.len() - "bc".len()]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the suffix was tested here + --> tests/ui/manual_strip_fixable.rs:12:5 + | +LL | if s.ends_with("bc") { + | ^^^^^^^^^^^^^^^^^^^^^ +help: try using the `strip_suffix` method + | +LL ~ if let Some(stripped) = s.strip_suffix("bc") { +LL ~ +LL ~ println!("{stripped}{}", stripped); + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/manual_swap_auto_fix.rs b/tests/ui/manual_swap_auto_fix.rs index 702a9e67d3d5..c9880e651cd7 100644 --- a/tests/ui/manual_swap_auto_fix.rs +++ b/tests/ui/manual_swap_auto_fix.rs @@ -4,7 +4,8 @@ fn swap1() { let mut v = [3, 2, 1, 0]; let index = v[0]; - //~^ ERROR: this looks like you are swapping elements of `v` manually + //~^ manual_swap + v[0] = v[index]; v[index] = index; } @@ -12,6 +13,7 @@ fn swap1() { fn swap2() { let mut v = [3, 2, 1, 0]; let tmp = v[0]; + //~^ manual_swap v[0] = v[1]; v[1] = tmp; // check not found in this scope. @@ -23,6 +25,7 @@ fn swap3() { let i1 = 0; let i2 = 1; let temp = v[i1]; + //~^ manual_swap v[i1] = v[i2]; v[i2] = temp; } @@ -32,6 +35,7 @@ fn swap4() { let i1 = 0; let i2 = 1; let temp = v[i1]; + //~^ manual_swap v[i1] = v[i2 + 1]; v[i2 + 1] = temp; } @@ -41,6 +45,7 @@ fn swap5() { let i1 = 0; let i2 = 1; let temp = v[i1]; + //~^ manual_swap v[i1] = v[i2 + 1]; v[i2 + 1] = temp; } @@ -48,7 +53,8 @@ fn swap5() { fn swap6() { let mut v = [0, 1, 2, 3]; let index = v[0]; - //~^ ERROR: this looks like you are swapping elements of `v` manually + //~^ manual_swap + v[0] = v[index + 1]; v[index + 1] = index; } @@ -58,6 +64,7 @@ fn swap7() { let i1 = 0; let i2 = 6; let tmp = v[i1 * 3]; + //~^ manual_swap v[i1 * 3] = v[i2 / 2]; v[i2 / 2] = tmp; } @@ -67,6 +74,7 @@ fn swap8() { let i1 = 1; let i2 = 1; let tmp = v[i1 + i2]; + //~^ manual_swap v[i1 + i2] = v[i2]; v[i2] = tmp; } diff --git a/tests/ui/manual_swap_auto_fix.stderr b/tests/ui/manual_swap_auto_fix.stderr index eecfcd3977be..7ab898fcc726 100644 --- a/tests/ui/manual_swap_auto_fix.stderr +++ b/tests/ui/manual_swap_auto_fix.stderr @@ -3,6 +3,7 @@ error: this looks like you are swapping elements of `v` manually | LL | / let index = v[0]; LL | | +LL | | LL | | v[0] = v[index]; LL | | v[index] = index; | |_____________________^ @@ -16,9 +17,10 @@ LL + v.swap(0, index); | error: this looks like you are swapping elements of `v` manually - --> tests/ui/manual_swap_auto_fix.rs:14:5 + --> tests/ui/manual_swap_auto_fix.rs:15:5 | LL | / let tmp = v[0]; +LL | | LL | | v[0] = v[1]; LL | | v[1] = tmp; | |_______________^ @@ -30,34 +32,38 @@ LL + v.swap(0, 1); | error: this looks like you are swapping elements of `v` manually - --> tests/ui/manual_swap_auto_fix.rs:25:5 + --> tests/ui/manual_swap_auto_fix.rs:27:5 | LL | / let temp = v[i1]; +LL | | LL | | v[i1] = v[i2]; LL | | v[i2] = temp; | |_________________^ help: try: `v.swap(i1, i2);` error: this looks like you are swapping elements of `v` manually - --> tests/ui/manual_swap_auto_fix.rs:34:5 + --> tests/ui/manual_swap_auto_fix.rs:37:5 | LL | / let temp = v[i1]; +LL | | LL | | v[i1] = v[i2 + 1]; LL | | v[i2 + 1] = temp; | |_____________________^ help: try: `v.swap(i1, i2 + 1);` error: this looks like you are swapping elements of `v` manually - --> tests/ui/manual_swap_auto_fix.rs:43:5 + --> tests/ui/manual_swap_auto_fix.rs:47:5 | LL | / let temp = v[i1]; +LL | | LL | | v[i1] = v[i2 + 1]; LL | | v[i2 + 1] = temp; | |_____________________^ help: try: `v.swap(i1, i2 + 1);` error: this looks like you are swapping elements of `v` manually - --> tests/ui/manual_swap_auto_fix.rs:50:5 + --> tests/ui/manual_swap_auto_fix.rs:55:5 | LL | / let index = v[0]; LL | | +LL | | LL | | v[0] = v[index + 1]; LL | | v[index + 1] = index; | |_________________________^ @@ -69,17 +75,19 @@ LL + v.swap(0, index + 1); | error: this looks like you are swapping elements of `v` manually - --> tests/ui/manual_swap_auto_fix.rs:60:5 + --> tests/ui/manual_swap_auto_fix.rs:66:5 | LL | / let tmp = v[i1 * 3]; +LL | | LL | | v[i1 * 3] = v[i2 / 2]; LL | | v[i2 / 2] = tmp; | |____________________^ help: try: `v.swap(i1 * 3, i2 / 2);` error: this looks like you are swapping elements of `v` manually - --> tests/ui/manual_swap_auto_fix.rs:69:5 + --> tests/ui/manual_swap_auto_fix.rs:76:5 | LL | / let tmp = v[i1 + i2]; +LL | | LL | | v[i1 + i2] = v[i2]; LL | | v[i2] = tmp; | |________________^ help: try: `v.swap(i1 + i2, i2);` diff --git a/tests/ui/manual_try_fold.rs b/tests/ui/manual_try_fold.rs index 7299d7cf9862..c91ea41bb84c 100644 --- a/tests/ui/manual_try_fold.rs +++ b/tests/ui/manual_try_fold.rs @@ -57,13 +57,16 @@ fn main() { [1, 2, 3] .iter() .fold(Some(0i32), |sum, i| sum?.checked_add(*i)) + //~^ manual_try_fold .unwrap(); [1, 2, 3] .iter() .fold(NotOption(0i32, 0i32), |sum, i| NotOption(0i32, 0i32)); + //~^ manual_try_fold [1, 2, 3] .iter() .fold(NotOptionButWorse(0i32), |sum, i| NotOptionButWorse(0i32)); + //~^ manual_try_fold // Do not lint [1, 2, 3].iter().try_fold(0i32, |sum, i| sum.checked_add(*i)).unwrap(); [1, 2, 3].iter().fold(0i32, |sum, i| sum + i); @@ -94,6 +97,7 @@ fn msrv_juust_right() { [1, 2, 3] .iter() .fold(Some(0i32), |sum, i| sum?.checked_add(*i)) + //~^ manual_try_fold .unwrap(); } diff --git a/tests/ui/manual_try_fold.stderr b/tests/ui/manual_try_fold.stderr index bc075e87d71f..f2740187878f 100644 --- a/tests/ui/manual_try_fold.stderr +++ b/tests/ui/manual_try_fold.stderr @@ -8,19 +8,19 @@ LL | .fold(Some(0i32), |sum, i| sum?.checked_add(*i)) = help: to override `-D warnings` add `#[allow(clippy::manual_try_fold)]` error: usage of `Iterator::fold` on a type that implements `Try` - --> tests/ui/manual_try_fold.rs:63:10 + --> tests/ui/manual_try_fold.rs:64:10 | LL | .fold(NotOption(0i32, 0i32), |sum, i| NotOption(0i32, 0i32)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(..., |sum, i| ...)` error: usage of `Iterator::fold` on a type that implements `Try` - --> tests/ui/manual_try_fold.rs:66:10 + --> tests/ui/manual_try_fold.rs:68:10 | LL | .fold(NotOptionButWorse(0i32), |sum, i| NotOptionButWorse(0i32)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(0i32, |sum, i| ...)` error: usage of `Iterator::fold` on a type that implements `Try` - --> tests/ui/manual_try_fold.rs:96:10 + --> tests/ui/manual_try_fold.rs:99:10 | LL | .fold(Some(0i32), |sum, i| sum?.checked_add(*i)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(0i32, |sum, i| ...)` diff --git a/tests/ui/manual_unwrap_or.rs b/tests/ui/manual_unwrap_or.rs index cdbe51a41212..c88b6f95da68 100644 --- a/tests/ui/manual_unwrap_or.rs +++ b/tests/ui/manual_unwrap_or.rs @@ -9,18 +9,21 @@ fn option_unwrap_or() { // int case match Some(1) { + //~^ manual_unwrap_or Some(i) => i, None => 42, }; // int case reversed match Some(1) { + //~^ manual_unwrap_or None => 42, Some(i) => i, }; // richer none expr match Some(1) { + //~^ manual_unwrap_or Some(i) => i, None => 1 + 42, }; @@ -28,6 +31,7 @@ fn option_unwrap_or() { // multiline case #[rustfmt::skip] match Some(1) { + //~^ manual_unwrap_or Some(i) => i, None => { 42 + 42 @@ -38,6 +42,7 @@ fn option_unwrap_or() { // string case match Some("Bob") { + //~^ manual_unwrap_or Some(i) => i, None => "Alice", }; @@ -85,6 +90,7 @@ fn option_unwrap_or() { }; if let Some(x) = Some(1) { + //~^ manual_unwrap_or x } else { 42 @@ -118,6 +124,7 @@ fn option_unwrap_or() { fn result_unwrap_or() { // int case match Ok::(1) { + //~^ manual_unwrap_or Ok(i) => i, Err(_) => 42, }; @@ -125,12 +132,14 @@ fn result_unwrap_or() { // int case, scrutinee is a binding let a = Ok::(1); match a { + //~^ manual_unwrap_or Ok(i) => i, Err(_) => 42, }; // int case, suggestion must surround Result expr with parentheses match Ok(1) as Result { + //~^ manual_unwrap_or Ok(i) => i, Err(_) => 42, }; @@ -144,18 +153,21 @@ fn result_unwrap_or() { } let s = S {}; match s.method() { + //~^ manual_unwrap_or Some(i) => i, None => 42, }; // int case reversed match Ok::(1) { + //~^ manual_unwrap_or Err(_) => 42, Ok(i) => i, }; // richer none expr match Ok::(1) { + //~^ manual_unwrap_or Ok(i) => i, Err(_) => 1 + 42, }; @@ -163,6 +175,7 @@ fn result_unwrap_or() { // multiline case #[rustfmt::skip] match Ok::(1) { + //~^ manual_unwrap_or Ok(i) => i, Err(_) => { 42 + 42 @@ -173,6 +186,7 @@ fn result_unwrap_or() { // string case match Ok::<&str, &str>("Bob") { + //~^ manual_unwrap_or Ok(i) => i, Err(_) => "Alice", }; @@ -209,6 +223,7 @@ fn result_unwrap_or() { }; if let Ok(x) = Ok::(1) { + //~^ manual_unwrap_or x } else { 42 @@ -263,6 +278,7 @@ mod issue6965 { fn test() { let _ = match some_macro!() { + //~^ manual_unwrap_or Some(val) => val, None => 0, }; diff --git a/tests/ui/manual_unwrap_or.stderr b/tests/ui/manual_unwrap_or.stderr index a5a64ecb9a3e..a5deb55786e9 100644 --- a/tests/ui/manual_unwrap_or.stderr +++ b/tests/ui/manual_unwrap_or.stderr @@ -2,6 +2,7 @@ error: this pattern reimplements `Option::unwrap_or` --> tests/ui/manual_unwrap_or.rs:11:5 | LL | / match Some(1) { +LL | | LL | | Some(i) => i, LL | | None => 42, LL | | }; @@ -11,30 +12,32 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::manual_unwrap_or)]` error: this pattern reimplements `Option::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:17:5 + --> tests/ui/manual_unwrap_or.rs:18:5 | LL | / match Some(1) { +LL | | LL | | None => 42, LL | | Some(i) => i, LL | | }; | |_____^ help: replace with: `Some(1).unwrap_or(42)` error: this pattern reimplements `Option::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:23:5 + --> tests/ui/manual_unwrap_or.rs:25:5 | LL | / match Some(1) { +LL | | LL | | Some(i) => i, LL | | None => 1 + 42, LL | | }; | |_____^ help: replace with: `Some(1).unwrap_or(1 + 42)` error: this pattern reimplements `Option::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:30:5 + --> tests/ui/manual_unwrap_or.rs:33:5 | LL | / match Some(1) { +LL | | LL | | Some(i) => i, LL | | None => { -LL | | 42 + 42 ... | LL | | }; | |_____^ @@ -49,18 +52,20 @@ LL ~ }); | error: this pattern reimplements `Option::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:40:5 + --> tests/ui/manual_unwrap_or.rs:44:5 | LL | / match Some("Bob") { +LL | | LL | | Some(i) => i, LL | | None => "Alice", LL | | }; | |_____^ help: replace with: `Some("Bob").unwrap_or("Alice")` error: this pattern reimplements `Option::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:87:5 + --> tests/ui/manual_unwrap_or.rs:92:5 | LL | / if let Some(x) = Some(1) { +LL | | LL | | x LL | | } else { LL | | 42 @@ -68,66 +73,72 @@ LL | | }; | |_____^ help: replace with: `Some(1).unwrap_or(42)` error: this pattern reimplements `Result::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:120:5 + --> tests/ui/manual_unwrap_or.rs:126:5 | LL | / match Ok::(1) { +LL | | LL | | Ok(i) => i, LL | | Err(_) => 42, LL | | }; | |_____^ help: replace with: `Ok::(1).unwrap_or(42)` error: this pattern reimplements `Result::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:127:5 + --> tests/ui/manual_unwrap_or.rs:134:5 | LL | / match a { +LL | | LL | | Ok(i) => i, LL | | Err(_) => 42, LL | | }; | |_____^ help: replace with: `a.unwrap_or(42)` error: this pattern reimplements `Result::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:133:5 + --> tests/ui/manual_unwrap_or.rs:141:5 | LL | / match Ok(1) as Result { +LL | | LL | | Ok(i) => i, LL | | Err(_) => 42, LL | | }; | |_____^ help: replace with: `(Ok(1) as Result).unwrap_or(42)` error: this pattern reimplements `Option::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:146:5 + --> tests/ui/manual_unwrap_or.rs:155:5 | LL | / match s.method() { +LL | | LL | | Some(i) => i, LL | | None => 42, LL | | }; | |_____^ help: replace with: `s.method().unwrap_or(42)` error: this pattern reimplements `Result::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:152:5 + --> tests/ui/manual_unwrap_or.rs:162:5 | LL | / match Ok::(1) { +LL | | LL | | Err(_) => 42, LL | | Ok(i) => i, LL | | }; | |_____^ help: replace with: `Ok::(1).unwrap_or(42)` error: this pattern reimplements `Result::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:158:5 + --> tests/ui/manual_unwrap_or.rs:169:5 | LL | / match Ok::(1) { +LL | | LL | | Ok(i) => i, LL | | Err(_) => 1 + 42, LL | | }; | |_____^ help: replace with: `Ok::(1).unwrap_or(1 + 42)` error: this pattern reimplements `Result::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:165:5 + --> tests/ui/manual_unwrap_or.rs:177:5 | LL | / match Ok::(1) { +LL | | LL | | Ok(i) => i, LL | | Err(_) => { -LL | | 42 + 42 ... | LL | | }; | |_____^ @@ -142,18 +153,20 @@ LL ~ }); | error: this pattern reimplements `Result::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:175:5 + --> tests/ui/manual_unwrap_or.rs:188:5 | LL | / match Ok::<&str, &str>("Bob") { +LL | | LL | | Ok(i) => i, LL | | Err(_) => "Alice", LL | | }; | |_____^ help: replace with: `Ok::<&str, &str>("Bob").unwrap_or("Alice")` error: this pattern reimplements `Result::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:211:5 + --> tests/ui/manual_unwrap_or.rs:225:5 | LL | / if let Ok(x) = Ok::(1) { +LL | | LL | | x LL | | } else { LL | | 42 @@ -161,10 +174,11 @@ LL | | }; | |_____^ help: replace with: `Ok::(1).unwrap_or(42)` error: this pattern reimplements `Option::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:265:17 + --> tests/ui/manual_unwrap_or.rs:280:17 | LL | let _ = match some_macro!() { | _________________^ +LL | | LL | | Some(val) => val, LL | | None => 0, LL | | }; diff --git a/tests/ui/manual_unwrap_or_default.rs b/tests/ui/manual_unwrap_or_default.rs index 649f65c89fb0..bedb3f0af0f3 100644 --- a/tests/ui/manual_unwrap_or_default.rs +++ b/tests/ui/manual_unwrap_or_default.rs @@ -4,35 +4,36 @@ fn main() { let x: Option> = None; match x { - //~^ ERROR: match can be simplified with `.unwrap_or_default()` + //~^ manual_unwrap_or_default Some(v) => v, None => Vec::default(), }; let x: Option> = None; match x { - //~^ ERROR: match can be simplified with `.unwrap_or_default()` + //~^ manual_unwrap_or_default Some(v) => v, _ => Vec::default(), }; let x: Option = None; match x { - //~^ ERROR: match can be simplified with `.unwrap_or_default()` + //~^ manual_unwrap_or_default Some(v) => v, None => String::new(), }; let x: Option> = None; match x { - //~^ ERROR: match can be simplified with `.unwrap_or_default()` + //~^ manual_unwrap_or_default None => Vec::default(), Some(v) => v, }; let x: Option> = None; if let Some(v) = x { - //~^ ERROR: if let can be simplified with `.unwrap_or_default()` + //~^ manual_unwrap_or_default + v } else { Vec::default() @@ -50,14 +51,15 @@ fn main() { let x: Result = Ok(String::new()); match x { - //~^ ERROR: match can be simplified with `.unwrap_or_default()` + //~^ manual_unwrap_or_default Ok(v) => v, Err(_) => String::new(), }; let x: Result = Ok(String::new()); if let Ok(v) = x { - //~^ ERROR: if let can be simplified with `.unwrap_or_default()` + //~^ manual_unwrap_or_default + v } else { String::new() @@ -69,6 +71,7 @@ unsafe fn no_deref_ptr(a: Option, b: *const Option) -> i32 { match a { // `*b` being correct depends on `a == Some(_)` Some(_) => match *b { + //~^ manual_unwrap_or_default Some(v) => v, _ => 0, }, diff --git a/tests/ui/manual_unwrap_or_default.stderr b/tests/ui/manual_unwrap_or_default.stderr index 9e3b1be5cb9b..ca9aa159152e 100644 --- a/tests/ui/manual_unwrap_or_default.stderr +++ b/tests/ui/manual_unwrap_or_default.stderr @@ -46,6 +46,7 @@ error: if let can be simplified with `.unwrap_or_default()` | LL | / if let Some(v) = x { LL | | +LL | | LL | | v LL | | } else { LL | | Vec::default() @@ -53,7 +54,7 @@ LL | | }; | |_____^ help: replace it with: `x.unwrap_or_default()` error: match can be simplified with `.unwrap_or_default()` - --> tests/ui/manual_unwrap_or_default.rs:52:5 + --> tests/ui/manual_unwrap_or_default.rs:53:5 | LL | / match x { LL | | @@ -63,10 +64,11 @@ LL | | }; | |_____^ help: replace it with: `x.unwrap_or_default()` error: if let can be simplified with `.unwrap_or_default()` - --> tests/ui/manual_unwrap_or_default.rs:59:5 + --> tests/ui/manual_unwrap_or_default.rs:60:5 | LL | / if let Ok(v) = x { LL | | +LL | | LL | | v LL | | } else { LL | | String::new() @@ -74,10 +76,11 @@ LL | | }; | |_____^ help: replace it with: `x.unwrap_or_default()` error: match can be simplified with `.unwrap_or_default()` - --> tests/ui/manual_unwrap_or_default.rs:71:20 + --> tests/ui/manual_unwrap_or_default.rs:73:20 | LL | Some(_) => match *b { | ____________________^ +LL | | LL | | Some(v) => v, LL | | _ => 0, LL | | }, diff --git a/tests/ui/manual_unwrap_or_default_unfixable.rs b/tests/ui/manual_unwrap_or_default_unfixable.rs index acc54b52816c..c48a4d5ee515 100644 --- a/tests/ui/manual_unwrap_or_default_unfixable.rs +++ b/tests/ui/manual_unwrap_or_default_unfixable.rs @@ -3,13 +3,17 @@ fn issue_12670() { // no auto: type not found #[allow(clippy::match_result_ok)] let _ = if let Some(x) = "1".parse().ok() { + //~^ manual_unwrap_or_default x } else { i32::default() }; let _ = if let Some(x) = None { x } else { i32::default() }; + //~^ manual_unwrap_or_default // auto fix with unwrap_or_default let a: Option = None; let _ = if let Some(x) = a { x } else { i32::default() }; + //~^ manual_unwrap_or_default let _ = if let Some(x) = Some(99) { x } else { i32::default() }; + //~^ manual_unwrap_or_default } diff --git a/tests/ui/manual_unwrap_or_default_unfixable.stderr b/tests/ui/manual_unwrap_or_default_unfixable.stderr index 3849d33cf254..94a7c2f5d2c3 100644 --- a/tests/ui/manual_unwrap_or_default_unfixable.stderr +++ b/tests/ui/manual_unwrap_or_default_unfixable.stderr @@ -3,6 +3,7 @@ error: if let can be simplified with `.unwrap_or_default()` | LL | let _ = if let Some(x) = "1".parse().ok() { | _____________^ +LL | | LL | | x LL | | } else { LL | | i32::default() @@ -13,19 +14,19 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::manual_unwrap_or_default)]` error: if let can be simplified with `.unwrap_or_default()` - --> tests/ui/manual_unwrap_or_default_unfixable.rs:10:13 + --> tests/ui/manual_unwrap_or_default_unfixable.rs:11:13 | LL | let _ = if let Some(x) = None { x } else { i32::default() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `None::.unwrap_or_default()` error: if let can be simplified with `.unwrap_or_default()` - --> tests/ui/manual_unwrap_or_default_unfixable.rs:13:13 + --> tests/ui/manual_unwrap_or_default_unfixable.rs:15:13 | LL | let _ = if let Some(x) = a { x } else { i32::default() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.unwrap_or_default()` error: if let can be simplified with `.unwrap_or_default()` - --> tests/ui/manual_unwrap_or_default_unfixable.rs:14:13 + --> tests/ui/manual_unwrap_or_default_unfixable.rs:17:13 | LL | let _ = if let Some(x) = Some(99) { x } else { i32::default() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `Some(99).unwrap_or_default()` diff --git a/tests/ui/manual_while_let_some.fixed b/tests/ui/manual_while_let_some.fixed index c70d258dfe6e..c0f6522d5fb8 100644 --- a/tests/ui/manual_while_let_some.fixed +++ b/tests/ui/manual_while_let_some.fixed @@ -19,6 +19,7 @@ fn main() { let mut numbers = vec![1, 2, 3, 4, 5]; while let Some(number) = numbers.pop() { + //~^ manual_while_let_some } let mut val = VecInStruct { @@ -27,14 +28,17 @@ fn main() { }; while let Some(number) = val.numbers.pop() { + //~^ manual_while_let_some } while let Some(element) = numbers.pop() { accept_i32(element); + //~^ manual_while_let_some } while let Some(element) = numbers.pop() { accept_i32(element); + //~^ manual_while_let_some } // This should not warn. It "conditionally" pops elements. @@ -78,14 +82,17 @@ fn main() { let mut numbers = vec![(0, 0), (1, 1), (2, 2)]; while let Some((a, b)) = numbers.pop() { + //~^ manual_while_let_some } while let Some(element) = numbers.pop() { accept_i32_tuple(element); + //~^ manual_while_let_some } let mut results = vec![Foo { a: 1, b: 2 }, Foo { a: 3, b: 4 }]; while let Some(Foo { a, b }) = results.pop() { + //~^ manual_while_let_some } } diff --git a/tests/ui/manual_while_let_some.rs b/tests/ui/manual_while_let_some.rs index 415bb5798667..f69eb66af1d7 100644 --- a/tests/ui/manual_while_let_some.rs +++ b/tests/ui/manual_while_let_some.rs @@ -19,6 +19,7 @@ fn main() { let mut numbers = vec![1, 2, 3, 4, 5]; while !numbers.is_empty() { let number = numbers.pop().unwrap(); + //~^ manual_while_let_some } let mut val = VecInStruct { @@ -27,14 +28,17 @@ fn main() { }; while !val.numbers.is_empty() { let number = val.numbers.pop().unwrap(); + //~^ manual_while_let_some } while !numbers.is_empty() { accept_i32(numbers.pop().unwrap()); + //~^ manual_while_let_some } while !numbers.is_empty() { accept_i32(numbers.pop().expect("")); + //~^ manual_while_let_some } // This should not warn. It "conditionally" pops elements. @@ -78,14 +82,17 @@ fn main() { let mut numbers = vec![(0, 0), (1, 1), (2, 2)]; while !numbers.is_empty() { let (a, b) = numbers.pop().unwrap(); + //~^ manual_while_let_some } while !numbers.is_empty() { accept_i32_tuple(numbers.pop().unwrap()); + //~^ manual_while_let_some } let mut results = vec![Foo { a: 1, b: 2 }, Foo { a: 3, b: 4 }]; while !results.is_empty() { let Foo { a, b } = results.pop().unwrap(); + //~^ manual_while_let_some } } diff --git a/tests/ui/manual_while_let_some.stderr b/tests/ui/manual_while_let_some.stderr index 8d444b80aaff..5f2fecb7a0b9 100644 --- a/tests/ui/manual_while_let_some.stderr +++ b/tests/ui/manual_while_let_some.stderr @@ -13,7 +13,7 @@ LL ~ | error: you seem to be trying to pop elements from a `Vec` in a loop - --> tests/ui/manual_while_let_some.rs:29:9 + --> tests/ui/manual_while_let_some.rs:30:9 | LL | let number = val.numbers.pop().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL ~ | error: you seem to be trying to pop elements from a `Vec` in a loop - --> tests/ui/manual_while_let_some.rs:33:20 + --> tests/ui/manual_while_let_some.rs:35:20 | LL | accept_i32(numbers.pop().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL ~ accept_i32(element); | error: you seem to be trying to pop elements from a `Vec` in a loop - --> tests/ui/manual_while_let_some.rs:37:20 + --> tests/ui/manual_while_let_some.rs:40:20 | LL | accept_i32(numbers.pop().expect("")); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL ~ accept_i32(element); | error: you seem to be trying to pop elements from a `Vec` in a loop - --> tests/ui/manual_while_let_some.rs:80:9 + --> tests/ui/manual_while_let_some.rs:84:9 | LL | let (a, b) = numbers.pop().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL ~ | error: you seem to be trying to pop elements from a `Vec` in a loop - --> tests/ui/manual_while_let_some.rs:84:26 + --> tests/ui/manual_while_let_some.rs:89:26 | LL | accept_i32_tuple(numbers.pop().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL ~ accept_i32_tuple(element); | error: you seem to be trying to pop elements from a `Vec` in a loop - --> tests/ui/manual_while_let_some.rs:89:9 + --> tests/ui/manual_while_let_some.rs:95:9 | LL | let Foo { a, b } = results.pop().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/many_single_char_names.rs b/tests/ui/many_single_char_names.rs index 68578340d90e..b60109224855 100644 --- a/tests/ui/many_single_char_names.rs +++ b/tests/ui/many_single_char_names.rs @@ -3,10 +3,10 @@ fn bla() { let a: i32; - //~^ ERROR: 5 bindings with single-character names in scope - //~| NOTE: `-D clippy::many-single-char-names` implied by `-D warnings` - //~| ERROR: 6 bindings with single-character names in scope - //~| ERROR: 5 bindings with single-character names in scope + //~^ many_single_char_names + //~| many_single_char_names + //~| many_single_char_names + let (b, c, d): (i32, i64, i16); { { @@ -32,11 +32,11 @@ fn bla() { } fn bindings(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, g: i32, h: i32) {} -//~^ ERROR: 8 bindings with single-character names in scope +//~^ many_single_char_names fn bindings2() { let (a, b, c, d, e, f, g, h): (bool, bool, bool, bool, bool, bool, bool, bool) = unimplemented!(); - //~^ ERROR: 8 bindings with single-character names in scope + //~^ many_single_char_names } fn shadowing() { diff --git a/tests/ui/map_all_any_identity.fixed b/tests/ui/map_all_any_identity.fixed index c92462ab9c27..35543d239752 100644 --- a/tests/ui/map_all_any_identity.fixed +++ b/tests/ui/map_all_any_identity.fixed @@ -3,6 +3,7 @@ fn main() { let _ = ["foo"].into_iter().any(|s| s == "foo"); //~^ map_all_any_identity + let _ = ["foo"].into_iter().all(|s| s == "foo"); //~^ map_all_any_identity diff --git a/tests/ui/map_all_any_identity.rs b/tests/ui/map_all_any_identity.rs index 0e4a564ca046..704eb821aaaa 100644 --- a/tests/ui/map_all_any_identity.rs +++ b/tests/ui/map_all_any_identity.rs @@ -3,6 +3,7 @@ fn main() { let _ = ["foo"].into_iter().map(|s| s == "foo").any(|a| a); //~^ map_all_any_identity + let _ = ["foo"].into_iter().map(|s| s == "foo").all(std::convert::identity); //~^ map_all_any_identity diff --git a/tests/ui/map_all_any_identity.stderr b/tests/ui/map_all_any_identity.stderr index 39df2a3d9616..24df97d883ac 100644 --- a/tests/ui/map_all_any_identity.stderr +++ b/tests/ui/map_all_any_identity.stderr @@ -13,7 +13,7 @@ LL + let _ = ["foo"].into_iter().any(|s| s == "foo"); | error: usage of `.map(...).all(identity)` - --> tests/ui/map_all_any_identity.rs:6:33 + --> tests/ui/map_all_any_identity.rs:7:33 | LL | let _ = ["foo"].into_iter().map(|s| s == "foo").all(std::convert::identity); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/map_clone.fixed b/tests/ui/map_clone.fixed index f9f8dc1a5123..8db4b21be684 100644 --- a/tests/ui/map_clone.fixed +++ b/tests/ui/map_clone.fixed @@ -12,11 +12,16 @@ fn main() { let _: Vec = vec![5_i8; 6].iter().copied().collect(); + //~^ map_clone let _: Vec = vec![String::new()].iter().cloned().collect(); + //~^ map_clone let _: Vec = vec![42, 43].iter().copied().collect(); + //~^ map_clone let _: Option = Some(Box::new(16)).map(|b| *b); let _: Option = Some(&16).copied(); + //~^ map_clone let _: Option = Some(&1).copied(); + //~^ map_clone // Don't lint these let v = vec![5_i8; 6]; @@ -28,6 +33,7 @@ fn main() { // Issue #498 let _ = std::env::args(); + //~^ map_clone // Issue #4824 item types that aren't references { @@ -67,22 +73,21 @@ fn main() { let x = Some(String::new()); let x = x.as_ref(); // We do this to prevent triggering the `useless_asref` lint. let y = x.cloned(); - //~^ ERROR: you are explicitly cloning with `.map()` + //~^ map_clone + let y = x.cloned(); - //~^ ERROR: you are explicitly cloning with `.map()` - //~| HELP: consider calling the dedicated `cloned` method + //~^ map_clone + let y = x.cloned(); - //~^ ERROR: you are explicitly cloning with `.map()` - //~| HELP: consider calling the dedicated `cloned` method + //~^ map_clone let x: Option = Some(0); let x = x.as_ref(); // We do this to prevent triggering the `useless_asref` lint. let y = x.copied(); - //~^ ERROR: you are explicitly cloning with `.map()` - //~| HELP: consider calling the dedicated `copied` method + //~^ map_clone + let y = x.copied(); - //~^ ERROR: you are explicitly cloning with `.map()` - //~| HELP: consider calling the dedicated `copied` method + //~^ map_clone // Should not suggest `copied` or `cloned` here since `T` is not a reference. let x: Option = Some(0); @@ -93,20 +98,18 @@ fn main() { let x: Result = Ok(String::new()); let x = x.as_ref(); // We do this to prevent triggering the `useless_asref` lint. let y = x.cloned(); - //~^ ERROR: you are explicitly cloning with `.map()` - //~| HELP: consider calling the dedicated `cloned` method + //~^ map_clone + let y = x.cloned(); - //~^ ERROR: you are explicitly cloning with `.map()` - //~| HELP: consider calling the dedicated `cloned` method + //~^ map_clone let x: Result = Ok(0); let x = x.as_ref(); // We do this to prevent triggering the `useless_asref` lint. let y = x.copied(); - //~^ ERROR: you are explicitly cloning with `.map()` - //~| HELP: consider calling the dedicated `copied` method + //~^ map_clone + let y = x.copied(); - //~^ ERROR: you are explicitly cloning with `.map()` - //~| HELP: consider calling the dedicated `copied` method + //~^ map_clone // Should not suggest `copied` or `cloned` here since `T` is not a reference. let x: Result = Ok(0); diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs index a5c19ce06319..a726e3561634 100644 --- a/tests/ui/map_clone.rs +++ b/tests/ui/map_clone.rs @@ -12,11 +12,16 @@ fn main() { let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); + //~^ map_clone let _: Vec = vec![String::new()].iter().map(|x| x.clone()).collect(); + //~^ map_clone let _: Vec = vec![42, 43].iter().map(|&x| x).collect(); + //~^ map_clone let _: Option = Some(Box::new(16)).map(|b| *b); let _: Option = Some(&16).map(|b| *b); + //~^ map_clone let _: Option = Some(&1).map(|x| x.clone()); + //~^ map_clone // Don't lint these let v = vec![5_i8; 6]; @@ -28,6 +33,7 @@ fn main() { // Issue #498 let _ = std::env::args().map(|v| v.clone()); + //~^ map_clone // Issue #4824 item types that aren't references { @@ -67,22 +73,21 @@ fn main() { let x = Some(String::new()); let x = x.as_ref(); // We do this to prevent triggering the `useless_asref` lint. let y = x.map(|x| String::clone(x)); - //~^ ERROR: you are explicitly cloning with `.map()` + //~^ map_clone + let y = x.map(Clone::clone); - //~^ ERROR: you are explicitly cloning with `.map()` - //~| HELP: consider calling the dedicated `cloned` method + //~^ map_clone + let y = x.map(String::clone); - //~^ ERROR: you are explicitly cloning with `.map()` - //~| HELP: consider calling the dedicated `cloned` method + //~^ map_clone let x: Option = Some(0); let x = x.as_ref(); // We do this to prevent triggering the `useless_asref` lint. let y = x.map(|x| u32::clone(x)); - //~^ ERROR: you are explicitly cloning with `.map()` - //~| HELP: consider calling the dedicated `copied` method + //~^ map_clone + let y = x.map(|x| Clone::clone(x)); - //~^ ERROR: you are explicitly cloning with `.map()` - //~| HELP: consider calling the dedicated `copied` method + //~^ map_clone // Should not suggest `copied` or `cloned` here since `T` is not a reference. let x: Option = Some(0); @@ -93,20 +98,18 @@ fn main() { let x: Result = Ok(String::new()); let x = x.as_ref(); // We do this to prevent triggering the `useless_asref` lint. let y = x.map(|x| String::clone(x)); - //~^ ERROR: you are explicitly cloning with `.map()` - //~| HELP: consider calling the dedicated `cloned` method + //~^ map_clone + let y = x.map(|x| Clone::clone(x)); - //~^ ERROR: you are explicitly cloning with `.map()` - //~| HELP: consider calling the dedicated `cloned` method + //~^ map_clone let x: Result = Ok(0); let x = x.as_ref(); // We do this to prevent triggering the `useless_asref` lint. let y = x.map(|x| u32::clone(x)); - //~^ ERROR: you are explicitly cloning with `.map()` - //~| HELP: consider calling the dedicated `copied` method + //~^ map_clone + let y = x.map(|x| Clone::clone(x)); - //~^ ERROR: you are explicitly cloning with `.map()` - //~| HELP: consider calling the dedicated `copied` method + //~^ map_clone // Should not suggest `copied` or `cloned` here since `T` is not a reference. let x: Result = Ok(0); diff --git a/tests/ui/map_clone.stderr b/tests/ui/map_clone.stderr index d9e025de4abe..8bf54e4e8aee 100644 --- a/tests/ui/map_clone.stderr +++ b/tests/ui/map_clone.stderr @@ -8,85 +8,85 @@ LL | let _: Vec = vec![5_i8; 6].iter().map(|x| *x).collect(); = help: to override `-D warnings` add `#[allow(clippy::map_clone)]` error: you are using an explicit closure for cloning elements - --> tests/ui/map_clone.rs:15:26 + --> tests/ui/map_clone.rs:16:26 | LL | let _: Vec = vec![String::new()].iter().map(|x| x.clone()).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `vec![String::new()].iter().cloned()` error: you are using an explicit closure for copying elements - --> tests/ui/map_clone.rs:16:23 + --> tests/ui/map_clone.rs:18:23 | LL | let _: Vec = vec![42, 43].iter().map(|&x| x).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `vec![42, 43].iter().copied()` error: you are using an explicit closure for copying elements - --> tests/ui/map_clone.rs:18:26 + --> tests/ui/map_clone.rs:21:26 | LL | let _: Option = Some(&16).map(|b| *b); | ^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `Some(&16).copied()` error: you are using an explicit closure for copying elements - --> tests/ui/map_clone.rs:19:25 + --> tests/ui/map_clone.rs:23:25 | LL | let _: Option = Some(&1).map(|x| x.clone()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `Some(&1).copied()` error: you are needlessly cloning iterator elements - --> tests/ui/map_clone.rs:30:29 + --> tests/ui/map_clone.rs:35:29 | LL | let _ = std::env::args().map(|v| v.clone()); | ^^^^^^^^^^^^^^^^^^^ help: remove the `map` call error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:69:13 + --> tests/ui/map_clone.rs:75:13 | LL | let y = x.map(|x| String::clone(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:71:13 + --> tests/ui/map_clone.rs:78:13 | LL | let y = x.map(Clone::clone); | ^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:74:13 + --> tests/ui/map_clone.rs:81:13 | LL | let y = x.map(String::clone); | ^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:80:13 + --> tests/ui/map_clone.rs:86:13 | LL | let y = x.map(|x| u32::clone(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `x.copied()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:83:13 + --> tests/ui/map_clone.rs:89:13 | LL | let y = x.map(|x| Clone::clone(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `x.copied()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:95:13 + --> tests/ui/map_clone.rs:100:13 | LL | let y = x.map(|x| String::clone(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:98:13 + --> tests/ui/map_clone.rs:103:13 | LL | let y = x.map(|x| Clone::clone(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:104:13 + --> tests/ui/map_clone.rs:108:13 | LL | let y = x.map(|x| u32::clone(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `x.copied()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:107:13 + --> tests/ui/map_clone.rs:111:13 | LL | let y = x.map(|x| Clone::clone(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `x.copied()` diff --git a/tests/ui/map_collect_result_unit.fixed b/tests/ui/map_collect_result_unit.fixed index 374af105f889..26957e59f14a 100644 --- a/tests/ui/map_collect_result_unit.fixed +++ b/tests/ui/map_collect_result_unit.fixed @@ -3,7 +3,9 @@ fn main() { { let _ = (0..3).try_for_each(|t| Err(t + 1)); + //~^ map_collect_result_unit let _: Result<(), _> = (0..3).try_for_each(|t| Err(t + 1)); + //~^ map_collect_result_unit let _ = (0..3).try_for_each(|t| Err(t + 1)); } diff --git a/tests/ui/map_collect_result_unit.rs b/tests/ui/map_collect_result_unit.rs index 5c6fb23e2372..cdd73bfe6544 100644 --- a/tests/ui/map_collect_result_unit.rs +++ b/tests/ui/map_collect_result_unit.rs @@ -3,7 +3,9 @@ fn main() { { let _ = (0..3).map(|t| Err(t + 1)).collect::>(); + //~^ map_collect_result_unit let _: Result<(), _> = (0..3).map(|t| Err(t + 1)).collect(); + //~^ map_collect_result_unit let _ = (0..3).try_for_each(|t| Err(t + 1)); } diff --git a/tests/ui/map_collect_result_unit.stderr b/tests/ui/map_collect_result_unit.stderr index 8d147340e16a..93293be855bb 100644 --- a/tests/ui/map_collect_result_unit.stderr +++ b/tests/ui/map_collect_result_unit.stderr @@ -8,7 +8,7 @@ LL | let _ = (0..3).map(|t| Err(t + 1)).collect::>(); = help: to override `-D warnings` add `#[allow(clippy::map_collect_result_unit)]` error: `.map().collect()` can be replaced with `.try_for_each()` - --> tests/ui/map_collect_result_unit.rs:6:32 + --> tests/ui/map_collect_result_unit.rs:7:32 | LL | let _: Result<(), _> = (0..3).map(|t| Err(t + 1)).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(0..3).try_for_each(|t| Err(t + 1))` diff --git a/tests/ui/map_err.rs b/tests/ui/map_err.rs index 07c51784407a..0f0c8f6c71cf 100644 --- a/tests/ui/map_err.rs +++ b/tests/ui/map_err.rs @@ -20,7 +20,7 @@ fn main() -> Result<(), Errors> { let x = u32::try_from(-123_i32); println!("{:?}", x.map_err(|_| Errors::Ignored)); - //~^ ERROR: `map_err(|_|...` wildcard pattern discards the original error + //~^ map_err_ignore // Should not warn you because you explicitly ignore the parameter // using a named wildcard value diff --git a/tests/ui/map_flatten.rs b/tests/ui/map_flatten.rs index eafc8b6e81ca..d7e9c9d9900d 100644 --- a/tests/ui/map_flatten.rs +++ b/tests/ui/map_flatten.rs @@ -6,8 +6,9 @@ fn long_span() { let _: Option = Some(1) .map(|x| { - //~^ ERROR: called `map(..).flatten()` on `Option` - //~| NOTE: `-D clippy::map-flatten` implied by `-D warnings` + //~^ map_flatten + + if x <= 5 { Some(x) } else { @@ -18,7 +19,8 @@ fn long_span() { let _: Result = Ok(1) .map(|x| { - //~^ ERROR: called `map(..).flatten()` on `Result` + //~^ map_flatten + if x == 1 { Ok(x) } else { @@ -31,7 +33,8 @@ fn long_span() { fn do_something() { } let _: Result = result .map(|res| { - //~^ ERROR: called `map(..).flatten()` on `Result` + //~^ map_flatten + if res > 0 { do_something(); Ok(res) @@ -44,7 +47,8 @@ fn long_span() { let _: Vec<_> = vec![5_i8; 6] .into_iter() .map(|some_value| { - //~^ ERROR: called `map(..).flatten()` on `Iterator` + //~^ map_flatten + if some_value > 3 { Some(some_value) } else { @@ -62,7 +66,7 @@ fn no_suggestion_if_comments_present() { .iter() // a lovely comment explaining the code in very detail .map(|x| x.iter()) - //~^ ERROR: called `map(..).flatten()` on `Iterator` + //~^ map_flatten // the answer to life, the universe and everything could be here .flatten(); } diff --git a/tests/ui/map_flatten.stderr b/tests/ui/map_flatten.stderr index 34bd174d7dde..704267fea3cf 100644 --- a/tests/ui/map_flatten.stderr +++ b/tests/ui/map_flatten.stderr @@ -3,9 +3,6 @@ error: called `map(..).flatten()` on `Option` | LL | .map(|x| { | __________^ -LL | | -LL | | -LL | | if x <= 5 { ... | LL | | }) LL | | .flatten(); @@ -17,7 +14,8 @@ help: try replacing `map` with `and_then` and remove the `.flatten()` | LL ~ .and_then(|x| { LL + -LL + +LL + +LL + LL + if x <= 5 { LL + Some(x) LL + } else { @@ -27,13 +25,13 @@ LL ~ }); | error: called `map(..).flatten()` on `Result` - --> tests/ui/map_flatten.rs:20:10 + --> tests/ui/map_flatten.rs:21:10 | LL | .map(|x| { | __________^ LL | | +LL | | LL | | if x == 1 { -LL | | Ok(x) ... | LL | | }) LL | | .flatten(); @@ -43,6 +41,7 @@ help: try replacing `map` with `and_then` and remove the `.flatten()` | LL ~ .and_then(|x| { LL + +LL + LL + if x == 1 { LL + Ok(x) LL + } else { @@ -52,13 +51,13 @@ LL ~ }); | error: called `map(..).flatten()` on `Result` - --> tests/ui/map_flatten.rs:33:10 + --> tests/ui/map_flatten.rs:35:10 | LL | .map(|res| { | __________^ LL | | +LL | | LL | | if res > 0 { -LL | | do_something(); ... | LL | | }) LL | | .flatten(); @@ -68,6 +67,7 @@ help: try replacing `map` with `and_then` and remove the `.flatten()` | LL ~ .and_then(|res| { LL + +LL + LL + if res > 0 { LL + do_something(); LL + Ok(res) @@ -78,13 +78,13 @@ LL ~ }); | error: called `map(..).flatten()` on `Iterator` - --> tests/ui/map_flatten.rs:46:10 + --> tests/ui/map_flatten.rs:49:10 | LL | .map(|some_value| { | __________^ LL | | +LL | | LL | | if some_value > 3 { -LL | | Some(some_value) ... | LL | | }) LL | | .flatten() @@ -94,6 +94,7 @@ help: try replacing `map` with `filter_map` and remove the `.flatten()` | LL ~ .filter_map(|some_value| { LL + +LL + LL + if some_value > 3 { LL + Some(some_value) LL + } else { @@ -103,7 +104,7 @@ LL + }) | error: called `map(..).flatten()` on `Iterator` - --> tests/ui/map_flatten.rs:64:10 + --> tests/ui/map_flatten.rs:68:10 | LL | .map(|x| x.iter()) | __________^ diff --git a/tests/ui/map_flatten_fixable.fixed b/tests/ui/map_flatten_fixable.fixed index 1932f412d2ca..948fec970d86 100644 --- a/tests/ui/map_flatten_fixable.fixed +++ b/tests/ui/map_flatten_fixable.fixed @@ -14,18 +14,25 @@ fn main() { let option_id_ref: fn(i8) -> Option = option_id; let option_id_closure = |x| Some(x); let _: Vec<_> = vec![5_i8; 6].into_iter().filter_map(option_id).collect(); + //~^ map_flatten let _: Vec<_> = vec![5_i8; 6].into_iter().filter_map(option_id_ref).collect(); + //~^ map_flatten let _: Vec<_> = vec![5_i8; 6].into_iter().filter_map(option_id_closure).collect(); + //~^ map_flatten let _: Vec<_> = vec![5_i8; 6].into_iter().filter_map(|x| x.checked_add(1)).collect(); + //~^ map_flatten // mapping to Iterator on Iterator let _: Vec<_> = vec![5_i8; 6].into_iter().flat_map(|x| 0..x).collect(); + //~^ map_flatten // mapping to Option on Option let _: Option<_> = (Some(Some(1))).and_then(|x| x); + //~^ map_flatten // mapping to Result on Result let _: Result<_, &str> = (Ok(Ok(1))).and_then(|x| x); + //~^ map_flatten issue8734(); issue8878(); @@ -35,6 +42,7 @@ fn issue8734() { let _ = [0u8, 1, 2, 3] .into_iter() .flat_map(|n| match n { + //~^ map_flatten 1 => [n .saturating_add(1) .saturating_add(1) @@ -54,6 +62,7 @@ fn issue8878() { std::collections::HashMap::::new() .get(&0) .and_then(|_| { + //~^ map_flatten // we need some newlines // so that the span is big enough // for a split output of the diagnostic diff --git a/tests/ui/map_flatten_fixable.rs b/tests/ui/map_flatten_fixable.rs index 093fd9b6cae2..67a91ab94147 100644 --- a/tests/ui/map_flatten_fixable.rs +++ b/tests/ui/map_flatten_fixable.rs @@ -14,18 +14,25 @@ fn main() { let option_id_ref: fn(i8) -> Option = option_id; let option_id_closure = |x| Some(x); let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().collect(); + //~^ map_flatten let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_ref).flatten().collect(); + //~^ map_flatten let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_closure).flatten().collect(); + //~^ map_flatten let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| x.checked_add(1)).flatten().collect(); + //~^ map_flatten // mapping to Iterator on Iterator let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect(); + //~^ map_flatten // mapping to Option on Option let _: Option<_> = (Some(Some(1))).map(|x| x).flatten(); + //~^ map_flatten // mapping to Result on Result let _: Result<_, &str> = (Ok(Ok(1))).map(|x| x).flatten(); + //~^ map_flatten issue8734(); issue8878(); @@ -35,6 +42,7 @@ fn issue8734() { let _ = [0u8, 1, 2, 3] .into_iter() .map(|n| match n { + //~^ map_flatten 1 => [n .saturating_add(1) .saturating_add(1) @@ -55,6 +63,7 @@ fn issue8878() { std::collections::HashMap::::new() .get(&0) .map(|_| { + //~^ map_flatten // we need some newlines // so that the span is big enough // for a split output of the diagnostic diff --git a/tests/ui/map_flatten_fixable.stderr b/tests/ui/map_flatten_fixable.stderr index 095bee52d6d7..05d4d9a6ad85 100644 --- a/tests/ui/map_flatten_fixable.stderr +++ b/tests/ui/map_flatten_fixable.stderr @@ -8,49 +8,49 @@ LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().coll = help: to override `-D warnings` add `#[allow(clippy::map_flatten)]` error: called `map(..).flatten()` on `Iterator` - --> tests/ui/map_flatten_fixable.rs:17:47 + --> tests/ui/map_flatten_fixable.rs:18:47 | LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_ref).flatten().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_ref)` error: called `map(..).flatten()` on `Iterator` - --> tests/ui/map_flatten_fixable.rs:18:47 + --> tests/ui/map_flatten_fixable.rs:20:47 | LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_closure).flatten().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_closure)` error: called `map(..).flatten()` on `Iterator` - --> tests/ui/map_flatten_fixable.rs:19:47 + --> tests/ui/map_flatten_fixable.rs:22:47 | LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| x.checked_add(1)).flatten().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(|x| x.checked_add(1))` error: called `map(..).flatten()` on `Iterator` - --> tests/ui/map_flatten_fixable.rs:22:47 + --> tests/ui/map_flatten_fixable.rs:26:47 | LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `flat_map` and remove the `.flatten()`: `flat_map(|x| 0..x)` error: called `map(..).flatten()` on `Option` - --> tests/ui/map_flatten_fixable.rs:25:40 + --> tests/ui/map_flatten_fixable.rs:30:40 | LL | let _: Option<_> = (Some(Some(1))).map(|x| x).flatten(); | ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)` error: called `map(..).flatten()` on `Result` - --> tests/ui/map_flatten_fixable.rs:28:42 + --> tests/ui/map_flatten_fixable.rs:34:42 | LL | let _: Result<_, &str> = (Ok(Ok(1))).map(|x| x).flatten(); | ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)` error: called `map(..).flatten()` on `Iterator` - --> tests/ui/map_flatten_fixable.rs:37:10 + --> tests/ui/map_flatten_fixable.rs:44:10 | LL | .map(|n| match n { | __________^ +LL | | LL | | 1 => [n LL | | .saturating_add(1) -LL | | .saturating_add(1) ... | LL | | }) LL | | .flatten(); @@ -59,6 +59,7 @@ LL | | .flatten(); help: try replacing `map` with `flat_map` and remove the `.flatten()` | LL ~ .flat_map(|n| match n { +LL + LL + 1 => [n LL + .saturating_add(1) LL + .saturating_add(1) @@ -73,7 +74,7 @@ LL ~ }); | error: called `map(..).flatten()` on `Option` - --> tests/ui/map_flatten_fixable.rs:57:10 + --> tests/ui/map_flatten_fixable.rs:65:10 | LL | .map(|_| { | __________^ @@ -85,6 +86,7 @@ LL | | .flatten(); help: try replacing `map` with `and_then` and remove the `.flatten()` | LL ~ .and_then(|_| { +LL + LL + // we need some newlines LL + // so that the span is big enough LL + // for a split output of the diagnostic diff --git a/tests/ui/map_identity.fixed b/tests/ui/map_identity.fixed index 3257ddc6f72b..83b2dac5fc51 100644 --- a/tests/ui/map_identity.fixed +++ b/tests/ui/map_identity.fixed @@ -5,8 +5,12 @@ fn main() { let x: [u16; 3] = [1, 2, 3]; // should lint let _: Vec<_> = x.iter().map(not_identity).collect(); + //~^ map_identity let _: Vec<_> = x.iter().collect(); + //~^ map_identity + //~| map_identity let _: Option = Some(3); + //~^ map_identity let _: Result = Ok(-3); // should not lint let _: Vec<_> = x.iter().map(|x| 2 * x).collect(); @@ -16,6 +20,7 @@ fn main() { return x + 3; }); let _: Result = Ok(1); + //~^ map_identity let _: Result = Ok(1).map_err(|a: u32| a * 42); // : u32 guides type inference let _ = Ok(1).map_err(|a: u32| a); @@ -26,11 +31,14 @@ fn issue7189() { // should lint let x = [(1, 2), (3, 4)].iter().copied(); let _ = x.clone(); + //~^ map_identity let _ = x.clone(); let _ = x.clone(); + //~^ map_identity let y = [(1, 2, (3, (4,))), (5, 6, (7, (8,)))].iter().copied(); let _ = y.clone(); + //~^ map_identity // should not lint let _ = x.clone().map(|(x, y)| (x, y, y)); @@ -60,6 +68,7 @@ fn issue11764() { // no match ergonomics for `(i32, i32)` let _ = x.iter().copied(); + //~^ map_identity } fn issue13904() { @@ -71,8 +80,10 @@ fn issue13904() { #[allow(unused_mut)] let mut it = [1, 2, 3].into_iter(); let _ = it.next(); + //~^ map_identity // lint let it = [1, 2, 3].into_iter(); let _ = { it }.next(); + //~^ map_identity } diff --git a/tests/ui/map_identity.rs b/tests/ui/map_identity.rs index be3bb9a4f106..e839c551364b 100644 --- a/tests/ui/map_identity.rs +++ b/tests/ui/map_identity.rs @@ -5,9 +5,14 @@ fn main() { let x: [u16; 3] = [1, 2, 3]; // should lint let _: Vec<_> = x.iter().map(not_identity).map(|x| return x).collect(); + //~^ map_identity let _: Vec<_> = x.iter().map(std::convert::identity).map(|y| y).collect(); + //~^ map_identity + //~| map_identity let _: Option = Some(3).map(|x| x); + //~^ map_identity let _: Result = Ok(-3).map(|x| { + //~^ map_identity return x; }); // should not lint @@ -18,6 +23,7 @@ fn main() { return x + 3; }); let _: Result = Ok(1).map_err(|a| a); + //~^ map_identity let _: Result = Ok(1).map_err(|a: u32| a * 42); // : u32 guides type inference let _ = Ok(1).map_err(|a: u32| a); @@ -28,13 +34,17 @@ fn issue7189() { // should lint let x = [(1, 2), (3, 4)].iter().copied(); let _ = x.clone().map(|(x, y)| (x, y)); + //~^ map_identity let _ = x.clone().map(|(x, y)| { + //~^ map_identity return (x, y); }); let _ = x.clone().map(|(x, y)| return (x, y)); + //~^ map_identity let y = [(1, 2, (3, (4,))), (5, 6, (7, (8,)))].iter().copied(); let _ = y.clone().map(|(x, y, (z, (w,)))| (x, y, (z, (w,)))); + //~^ map_identity // should not lint let _ = x.clone().map(|(x, y)| (x, y, y)); @@ -64,6 +74,7 @@ fn issue11764() { // no match ergonomics for `(i32, i32)` let _ = x.iter().copied().map(|(x, y)| (x, y)); + //~^ map_identity } fn issue13904() { @@ -75,8 +86,10 @@ fn issue13904() { #[allow(unused_mut)] let mut it = [1, 2, 3].into_iter(); let _ = it.map(|x| x).next(); + //~^ map_identity // lint let it = [1, 2, 3].into_iter(); let _ = { it }.map(|x| x).next(); + //~^ map_identity } diff --git a/tests/ui/map_identity.stderr b/tests/ui/map_identity.stderr index aa3fc4ae0b5c..9836f3b4cc5f 100644 --- a/tests/ui/map_identity.stderr +++ b/tests/ui/map_identity.stderr @@ -8,79 +8,81 @@ LL | let _: Vec<_> = x.iter().map(not_identity).map(|x| return x).collect(); = help: to override `-D warnings` add `#[allow(clippy::map_identity)]` error: unnecessary map of the identity function - --> tests/ui/map_identity.rs:8:57 + --> tests/ui/map_identity.rs:9:57 | LL | let _: Vec<_> = x.iter().map(std::convert::identity).map(|y| y).collect(); | ^^^^^^^^^^^ help: remove the call to `map` error: unnecessary map of the identity function - --> tests/ui/map_identity.rs:8:29 + --> tests/ui/map_identity.rs:9:29 | LL | let _: Vec<_> = x.iter().map(std::convert::identity).map(|y| y).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` error: unnecessary map of the identity function - --> tests/ui/map_identity.rs:9:32 + --> tests/ui/map_identity.rs:12:32 | LL | let _: Option = Some(3).map(|x| x); | ^^^^^^^^^^^ help: remove the call to `map` error: unnecessary map of the identity function - --> tests/ui/map_identity.rs:10:36 + --> tests/ui/map_identity.rs:14:36 | LL | let _: Result = Ok(-3).map(|x| { | ____________________________________^ +LL | | LL | | return x; LL | | }); | |______^ help: remove the call to `map` error: unnecessary map of the identity function - --> tests/ui/map_identity.rs:20:36 + --> tests/ui/map_identity.rs:25:36 | LL | let _: Result = Ok(1).map_err(|a| a); | ^^^^^^^^^^^^^^^ help: remove the call to `map_err` error: unnecessary map of the identity function - --> tests/ui/map_identity.rs:30:22 + --> tests/ui/map_identity.rs:36:22 | LL | let _ = x.clone().map(|(x, y)| (x, y)); | ^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` error: unnecessary map of the identity function - --> tests/ui/map_identity.rs:31:22 + --> tests/ui/map_identity.rs:38:22 | LL | let _ = x.clone().map(|(x, y)| { | ______________________^ +LL | | LL | | return (x, y); LL | | }); | |______^ help: remove the call to `map` error: unnecessary map of the identity function - --> tests/ui/map_identity.rs:34:22 + --> tests/ui/map_identity.rs:42:22 | LL | let _ = x.clone().map(|(x, y)| return (x, y)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` error: unnecessary map of the identity function - --> tests/ui/map_identity.rs:37:22 + --> tests/ui/map_identity.rs:46:22 | LL | let _ = y.clone().map(|(x, y, (z, (w,)))| (x, y, (z, (w,)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` error: unnecessary map of the identity function - --> tests/ui/map_identity.rs:66:30 + --> tests/ui/map_identity.rs:76:30 | LL | let _ = x.iter().copied().map(|(x, y)| (x, y)); | ^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` error: unnecessary map of the identity function - --> tests/ui/map_identity.rs:77:15 + --> tests/ui/map_identity.rs:88:15 | LL | let _ = it.map(|x| x).next(); | ^^^^^^^^^^^ help: remove the call to `map` error: unnecessary map of the identity function - --> tests/ui/map_identity.rs:81:19 + --> tests/ui/map_identity.rs:93:19 | LL | let _ = { it }.map(|x| x).next(); | ^^^^^^^^^^^ help: remove the call to `map` diff --git a/tests/ui/map_unit_fn.rs b/tests/ui/map_unit_fn.rs index e7f07b50f3ab..3a810196a44d 100644 --- a/tests/ui/map_unit_fn.rs +++ b/tests/ui/map_unit_fn.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![allow(unused)] struct Mappable; diff --git a/tests/ui/map_unwrap_or.rs b/tests/ui/map_unwrap_or.rs index dfaa8f24f987..fba81cb493cd 100644 --- a/tests/ui/map_unwrap_or.rs +++ b/tests/ui/map_unwrap_or.rs @@ -15,25 +15,31 @@ fn option_methods() { // Check for `option.map(_).unwrap_or(_)` use. // Single line case. let _ = opt.map(|x| x + 1) + //~^ map_unwrap_or // Should lint even though this call is on a separate line. .unwrap_or(0); // Multi-line cases. let _ = opt.map(|x| { + //~^ map_unwrap_or x + 1 } ).unwrap_or(0); let _ = opt.map(|x| x + 1) + //~^ map_unwrap_or .unwrap_or({ 0 }); // Single line `map(f).unwrap_or(None)` case. let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); + //~^ map_unwrap_or // Multi-line `map(f).unwrap_or(None)` cases. let _ = opt.map(|x| { + //~^ map_unwrap_or Some(x + 1) } ).unwrap_or(None); let _ = opt + //~^ map_unwrap_or .map(|x| Some(x + 1)) .unwrap_or(None); // macro case @@ -45,20 +51,24 @@ fn option_methods() { // ...but DO lint if the `unwrap_or` argument is not used in the `map` let id: String = "identifier".to_string(); let _ = Some("prefix").map(|p| format!("{}.", p)).unwrap_or(id); + //~^ map_unwrap_or // Check for `option.map(_).unwrap_or_else(_)` use. // Multi-line cases. let _ = opt.map(|x| { + //~^ map_unwrap_or x + 1 } ).unwrap_or_else(|| 0); let _ = opt.map(|x| x + 1) + //~^ map_unwrap_or .unwrap_or_else(|| 0 ); // Check for `map(f).unwrap_or(false)` use. let _ = opt.map(|x| x > 5).unwrap_or(false); + //~^ map_unwrap_or } @@ -69,10 +79,12 @@ fn result_methods() { // Check for `result.map(_).unwrap_or_else(_)` use. // multi line cases let _ = res.map(|x| { + //~^ map_unwrap_or x + 1 } ).unwrap_or_else(|_e| 0); let _ = res.map(|x| x + 1) + //~^ map_unwrap_or .unwrap_or_else(|_e| { 0 }); @@ -97,6 +109,7 @@ fn msrv_1_41() { let res: Result = Ok(1); let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0); + //~^ map_unwrap_or } #[clippy::msrv = "1.69"] @@ -104,6 +117,7 @@ fn msrv_1_69() { let opt: Option = Some(1); let _ = opt.map(|x| x > 5).unwrap_or(false); + //~^ map_unwrap_or } #[clippy::msrv = "1.70"] @@ -111,6 +125,7 @@ fn msrv_1_70() { let opt: Option = Some(1); let _ = opt.map(|x| x > 5).unwrap_or(false); + //~^ map_unwrap_or } mod issue_10579 { diff --git a/tests/ui/map_unwrap_or.stderr b/tests/ui/map_unwrap_or.stderr index d6ddd09c188c..0b6c9b7fcf19 100644 --- a/tests/ui/map_unwrap_or.stderr +++ b/tests/ui/map_unwrap_or.stderr @@ -3,7 +3,7 @@ error: called `map().unwrap_or()` on an `Option` value | LL | let _ = opt.map(|x| x + 1) | _____________^ -LL | | // Should lint even though this call is on a separate line. +... | LL | | .unwrap_or(0); | |_____________________^ | @@ -16,10 +16,11 @@ LL + let _ = opt.map_or(0, |x| x + 1); | error: called `map().unwrap_or()` on an `Option` value - --> tests/ui/map_unwrap_or.rs:21:13 + --> tests/ui/map_unwrap_or.rs:22:13 | LL | let _ = opt.map(|x| { | _____________^ +LL | | LL | | x + 1 LL | | } LL | | ).unwrap_or(0); @@ -28,16 +29,18 @@ LL | | ).unwrap_or(0); help: use `map_or(, )` instead | LL ~ let _ = opt.map_or(0, |x| { +LL | LL | x + 1 LL | } LL ~ ); | error: called `map().unwrap_or()` on an `Option` value - --> tests/ui/map_unwrap_or.rs:25:13 + --> tests/ui/map_unwrap_or.rs:27:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ +LL | | LL | | .unwrap_or({ LL | | 0 LL | | }); @@ -51,7 +54,7 @@ LL ~ }, |x| x + 1); | error: called `map().unwrap_or(None)` on an `Option` value - --> tests/ui/map_unwrap_or.rs:30:13 + --> tests/ui/map_unwrap_or.rs:33:13 | LL | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -63,10 +66,11 @@ LL + let _ = opt.and_then(|x| Some(x + 1)); | error: called `map().unwrap_or(None)` on an `Option` value - --> tests/ui/map_unwrap_or.rs:32:13 + --> tests/ui/map_unwrap_or.rs:36:13 | LL | let _ = opt.map(|x| { | _____________^ +LL | | LL | | Some(x + 1) LL | | } LL | | ).unwrap_or(None); @@ -75,16 +79,18 @@ LL | | ).unwrap_or(None); help: use `and_then()` instead | LL ~ let _ = opt.and_then(|x| { +LL | LL | Some(x + 1) LL | } LL ~ ); | error: called `map().unwrap_or(None)` on an `Option` value - --> tests/ui/map_unwrap_or.rs:36:13 + --> tests/ui/map_unwrap_or.rs:41:13 | LL | let _ = opt | _____________^ +LL | | LL | | .map(|x| Some(x + 1)) LL | | .unwrap_or(None); | |________________________^ @@ -96,7 +102,7 @@ LL + .and_then(|x| Some(x + 1)); | error: called `map().unwrap_or()` on an `Option` value - --> tests/ui/map_unwrap_or.rs:47:13 + --> tests/ui/map_unwrap_or.rs:53:13 | LL | let _ = Some("prefix").map(|p| format!("{}.", p)).unwrap_or(id); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -108,27 +114,29 @@ LL + let _ = Some("prefix").map_or(id, |p| format!("{}.", p)); | error: called `map().unwrap_or_else()` on an `Option` value - --> tests/ui/map_unwrap_or.rs:51:13 + --> tests/ui/map_unwrap_or.rs:58:13 | LL | let _ = opt.map(|x| { | _____________^ +LL | | LL | | x + 1 LL | | } LL | | ).unwrap_or_else(|| 0); | |__________________________^ error: called `map().unwrap_or_else()` on an `Option` value - --> tests/ui/map_unwrap_or.rs:55:13 + --> tests/ui/map_unwrap_or.rs:63:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ +LL | | LL | | .unwrap_or_else(|| LL | | 0 LL | | ); | |_________^ error: called `map().unwrap_or(false)` on an `Option` value - --> tests/ui/map_unwrap_or.rs:61:13 + --> tests/ui/map_unwrap_or.rs:70:13 | LL | let _ = opt.map(|x| x > 5).unwrap_or(false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -140,33 +148,35 @@ LL + let _ = opt.is_some_and(|x| x > 5); | error: called `map().unwrap_or_else()` on a `Result` value - --> tests/ui/map_unwrap_or.rs:71:13 + --> tests/ui/map_unwrap_or.rs:81:13 | LL | let _ = res.map(|x| { | _____________^ +LL | | LL | | x + 1 LL | | } LL | | ).unwrap_or_else(|_e| 0); | |____________________________^ error: called `map().unwrap_or_else()` on a `Result` value - --> tests/ui/map_unwrap_or.rs:75:13 + --> tests/ui/map_unwrap_or.rs:86:13 | LL | let _ = res.map(|x| x + 1) | _____________^ +LL | | LL | | .unwrap_or_else(|_e| { LL | | 0 LL | | }); | |__________^ error: called `map().unwrap_or_else()` on a `Result` value - --> tests/ui/map_unwrap_or.rs:99:13 + --> tests/ui/map_unwrap_or.rs:111:13 | LL | let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or_else(|_e| 0, |x| x + 1)` error: called `map().unwrap_or()` on an `Option` value - --> tests/ui/map_unwrap_or.rs:106:13 + --> tests/ui/map_unwrap_or.rs:119:13 | LL | let _ = opt.map(|x| x > 5).unwrap_or(false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -178,7 +188,7 @@ LL + let _ = opt.map_or(false, |x| x > 5); | error: called `map().unwrap_or(false)` on an `Option` value - --> tests/ui/map_unwrap_or.rs:113:13 + --> tests/ui/map_unwrap_or.rs:127:13 | LL | let _ = opt.map(|x| x > 5).unwrap_or(false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/map_unwrap_or_fixable.rs b/tests/ui/map_unwrap_or_fixable.rs index d3d0ae0154c1..1078c7a3cf34 100644 --- a/tests/ui/map_unwrap_or_fixable.rs +++ b/tests/ui/map_unwrap_or_fixable.rs @@ -14,6 +14,7 @@ fn option_methods() { // Check for `option.map(_).unwrap_or_else(_)` use. // single line case let _ = opt.map(|x| x + 1) + //~^ map_unwrap_or // Should lint even though this call is on a separate line. .unwrap_or_else(|| 0); @@ -44,6 +45,7 @@ fn result_methods() { // Check for `result.map(_).unwrap_or_else(_)` use. // single line case let _ = res.map(|x| x + 1) + //~^ map_unwrap_or // should lint even though this call is on a separate line .unwrap_or_else(|_e| 0); diff --git a/tests/ui/map_unwrap_or_fixable.stderr b/tests/ui/map_unwrap_or_fixable.stderr index 89a7c979f6e9..99e660f8dbd1 100644 --- a/tests/ui/map_unwrap_or_fixable.stderr +++ b/tests/ui/map_unwrap_or_fixable.stderr @@ -3,7 +3,7 @@ error: called `map().unwrap_or_else()` on an `Option` value | LL | let _ = opt.map(|x| x + 1) | _____________^ -LL | | // Should lint even though this call is on a separate line. +... | LL | | .unwrap_or_else(|| 0); | |_____________________________^ help: try: `opt.map_or_else(|| 0, |x| x + 1)` | @@ -11,11 +11,11 @@ LL | | .unwrap_or_else(|| 0); = help: to override `-D warnings` add `#[allow(clippy::map_unwrap_or)]` error: called `map().unwrap_or_else()` on a `Result` value - --> tests/ui/map_unwrap_or_fixable.rs:46:13 + --> tests/ui/map_unwrap_or_fixable.rs:47:13 | LL | let _ = res.map(|x| x + 1) | _____________^ -LL | | // should lint even though this call is on a separate line +... | LL | | .unwrap_or_else(|_e| 0); | |_______________________________^ help: try: `res.map_or_else(|_e| 0, |x| x + 1)` diff --git a/tests/ui/map_with_unused_argument_over_ranges.fixed b/tests/ui/map_with_unused_argument_over_ranges.fixed index 18716e93d1e9..254c46ecae38 100644 --- a/tests/ui/map_with_unused_argument_over_ranges.fixed +++ b/tests/ui/map_with_unused_argument_over_ranges.fixed @@ -23,27 +23,43 @@ macro_rules! r#gen { fn main() { // These should be raised std::iter::repeat_with(|| do_something()).take(10); + //~^ map_with_unused_argument_over_ranges std::iter::repeat_with(|| do_something()).take(10); + //~^ map_with_unused_argument_over_ranges std::iter::repeat_with(|| do_something()).take(11); + //~^ map_with_unused_argument_over_ranges std::iter::repeat_with(|| do_something()).take(7); + //~^ map_with_unused_argument_over_ranges std::iter::repeat_with(|| do_something()).take(8); + //~^ map_with_unused_argument_over_ranges std::iter::repeat_n(3, 10); + //~^ map_with_unused_argument_over_ranges std::iter::repeat_with(|| { + //~^ map_with_unused_argument_over_ranges let x = 3; x + 2 }).take(10); std::iter::repeat_with(|| do_something()).take(10).collect::>(); + //~^ map_with_unused_argument_over_ranges let upper = 4; std::iter::repeat_with(|| do_something()).take(upper); + //~^ map_with_unused_argument_over_ranges let upper_fn = || 4; std::iter::repeat_with(|| do_something()).take(upper_fn()); + //~^ map_with_unused_argument_over_ranges std::iter::repeat_with(|| do_something()).take(upper_fn() + 1); + //~^ map_with_unused_argument_over_ranges std::iter::repeat_with(|| do_something()).take(upper_fn() - 2); + //~^ map_with_unused_argument_over_ranges std::iter::repeat_with(|| do_something()).take(upper_fn() - 1); + //~^ map_with_unused_argument_over_ranges (-3..9).map(|_| do_something()); std::iter::repeat_with(|| do_something()).take(0); + //~^ map_with_unused_argument_over_ranges std::iter::repeat_with(|| do_something()).take(1); + //~^ map_with_unused_argument_over_ranges std::iter::repeat_with(|| do_something()).take((1 << 4) - 0); + //~^ map_with_unused_argument_over_ranges // These should not be raised r#gen!(); let lower = 2; @@ -65,9 +81,11 @@ fn msrv_1_27() { #[clippy::msrv = "1.28"] fn msrv_1_28() { std::iter::repeat_with(|| do_something()).take(10); + //~^ map_with_unused_argument_over_ranges } #[clippy::msrv = "1.81"] fn msrv_1_82() { std::iter::repeat(3).take(10); + //~^ map_with_unused_argument_over_ranges } diff --git a/tests/ui/map_with_unused_argument_over_ranges.rs b/tests/ui/map_with_unused_argument_over_ranges.rs index 596afd51e61f..05c8d64f8012 100644 --- a/tests/ui/map_with_unused_argument_over_ranges.rs +++ b/tests/ui/map_with_unused_argument_over_ranges.rs @@ -23,27 +23,43 @@ macro_rules! r#gen { fn main() { // These should be raised (0..10).map(|_| do_something()); + //~^ map_with_unused_argument_over_ranges (0..10).map(|_foo| do_something()); + //~^ map_with_unused_argument_over_ranges (0..=10).map(|_| do_something()); + //~^ map_with_unused_argument_over_ranges (3..10).map(|_| do_something()); + //~^ map_with_unused_argument_over_ranges (3..=10).map(|_| do_something()); + //~^ map_with_unused_argument_over_ranges (0..10).map(|_| 3); + //~^ map_with_unused_argument_over_ranges (0..10).map(|_| { + //~^ map_with_unused_argument_over_ranges let x = 3; x + 2 }); (0..10).map(|_| do_something()).collect::>(); + //~^ map_with_unused_argument_over_ranges let upper = 4; (0..upper).map(|_| do_something()); + //~^ map_with_unused_argument_over_ranges let upper_fn = || 4; (0..upper_fn()).map(|_| do_something()); + //~^ map_with_unused_argument_over_ranges (0..=upper_fn()).map(|_| do_something()); + //~^ map_with_unused_argument_over_ranges (2..upper_fn()).map(|_| do_something()); + //~^ map_with_unused_argument_over_ranges (2..=upper_fn()).map(|_| do_something()); + //~^ map_with_unused_argument_over_ranges (-3..9).map(|_| do_something()); (9..3).map(|_| do_something()); + //~^ map_with_unused_argument_over_ranges (9..=9).map(|_| do_something()); + //~^ map_with_unused_argument_over_ranges (1..=1 << 4).map(|_| do_something()); + //~^ map_with_unused_argument_over_ranges // These should not be raised r#gen!(); let lower = 2; @@ -65,9 +81,11 @@ fn msrv_1_27() { #[clippy::msrv = "1.28"] fn msrv_1_28() { (0..10).map(|_| do_something()); + //~^ map_with_unused_argument_over_ranges } #[clippy::msrv = "1.81"] fn msrv_1_82() { (0..10).map(|_| 3); + //~^ map_with_unused_argument_over_ranges } diff --git a/tests/ui/map_with_unused_argument_over_ranges.stderr b/tests/ui/map_with_unused_argument_over_ranges.stderr index 840515f95df4..e5c93ceac02a 100644 --- a/tests/ui/map_with_unused_argument_over_ranges.stderr +++ b/tests/ui/map_with_unused_argument_over_ranges.stderr @@ -13,7 +13,7 @@ LL + std::iter::repeat_with(|| do_something()).take(10); | error: map of a closure that does not depend on its parameter over a range - --> tests/ui/map_with_unused_argument_over_ranges.rs:26:5 + --> tests/ui/map_with_unused_argument_over_ranges.rs:27:5 | LL | (0..10).map(|_foo| do_something()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + std::iter::repeat_with(|| do_something()).take(10); | error: map of a closure that does not depend on its parameter over a range - --> tests/ui/map_with_unused_argument_over_ranges.rs:27:5 + --> tests/ui/map_with_unused_argument_over_ranges.rs:29:5 | LL | (0..=10).map(|_| do_something()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + std::iter::repeat_with(|| do_something()).take(11); | error: map of a closure that does not depend on its parameter over a range - --> tests/ui/map_with_unused_argument_over_ranges.rs:28:5 + --> tests/ui/map_with_unused_argument_over_ranges.rs:31:5 | LL | (3..10).map(|_| do_something()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + std::iter::repeat_with(|| do_something()).take(7); | error: map of a closure that does not depend on its parameter over a range - --> tests/ui/map_with_unused_argument_over_ranges.rs:29:5 + --> tests/ui/map_with_unused_argument_over_ranges.rs:33:5 | LL | (3..=10).map(|_| do_something()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + std::iter::repeat_with(|| do_something()).take(8); | error: map of a closure that does not depend on its parameter over a range - --> tests/ui/map_with_unused_argument_over_ranges.rs:30:5 + --> tests/ui/map_with_unused_argument_over_ranges.rs:35:5 | LL | (0..10).map(|_| 3); | ^^^^^^^^^^^^^^^^^^ @@ -73,9 +73,10 @@ LL + std::iter::repeat_n(3, 10); | error: map of a closure that does not depend on its parameter over a range - --> tests/ui/map_with_unused_argument_over_ranges.rs:31:5 + --> tests/ui/map_with_unused_argument_over_ranges.rs:37:5 | LL | / (0..10).map(|_| { +LL | | LL | | let x = 3; LL | | x + 2 LL | | }); @@ -84,13 +85,14 @@ LL | | }); help: remove the explicit range and use `repeat_with` and `take` | LL ~ std::iter::repeat_with(|| { +LL | LL | let x = 3; LL | x + 2 LL ~ }).take(10); | error: map of a closure that does not depend on its parameter over a range - --> tests/ui/map_with_unused_argument_over_ranges.rs:35:5 + --> tests/ui/map_with_unused_argument_over_ranges.rs:42:5 | LL | (0..10).map(|_| do_something()).collect::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -102,7 +104,7 @@ LL + std::iter::repeat_with(|| do_something()).take(10).collect::>(); | error: map of a closure that does not depend on its parameter over a range - --> tests/ui/map_with_unused_argument_over_ranges.rs:37:5 + --> tests/ui/map_with_unused_argument_over_ranges.rs:45:5 | LL | (0..upper).map(|_| do_something()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -114,7 +116,7 @@ LL + std::iter::repeat_with(|| do_something()).take(upper); | error: map of a closure that does not depend on its parameter over a range - --> tests/ui/map_with_unused_argument_over_ranges.rs:39:5 + --> tests/ui/map_with_unused_argument_over_ranges.rs:48:5 | LL | (0..upper_fn()).map(|_| do_something()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -126,7 +128,7 @@ LL + std::iter::repeat_with(|| do_something()).take(upper_fn()); | error: map of a closure that does not depend on its parameter over a range - --> tests/ui/map_with_unused_argument_over_ranges.rs:40:5 + --> tests/ui/map_with_unused_argument_over_ranges.rs:50:5 | LL | (0..=upper_fn()).map(|_| do_something()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -138,7 +140,7 @@ LL + std::iter::repeat_with(|| do_something()).take(upper_fn() + 1); | error: map of a closure that does not depend on its parameter over a range - --> tests/ui/map_with_unused_argument_over_ranges.rs:41:5 + --> tests/ui/map_with_unused_argument_over_ranges.rs:52:5 | LL | (2..upper_fn()).map(|_| do_something()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -150,7 +152,7 @@ LL + std::iter::repeat_with(|| do_something()).take(upper_fn() - 2); | error: map of a closure that does not depend on its parameter over a range - --> tests/ui/map_with_unused_argument_over_ranges.rs:42:5 + --> tests/ui/map_with_unused_argument_over_ranges.rs:54:5 | LL | (2..=upper_fn()).map(|_| do_something()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -162,7 +164,7 @@ LL + std::iter::repeat_with(|| do_something()).take(upper_fn() - 1); | error: map of a closure that does not depend on its parameter over a range - --> tests/ui/map_with_unused_argument_over_ranges.rs:44:5 + --> tests/ui/map_with_unused_argument_over_ranges.rs:57:5 | LL | (9..3).map(|_| do_something()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -174,7 +176,7 @@ LL + std::iter::repeat_with(|| do_something()).take(0); | error: map of a closure that does not depend on its parameter over a range - --> tests/ui/map_with_unused_argument_over_ranges.rs:45:5 + --> tests/ui/map_with_unused_argument_over_ranges.rs:59:5 | LL | (9..=9).map(|_| do_something()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -186,7 +188,7 @@ LL + std::iter::repeat_with(|| do_something()).take(1); | error: map of a closure that does not depend on its parameter over a range - --> tests/ui/map_with_unused_argument_over_ranges.rs:46:5 + --> tests/ui/map_with_unused_argument_over_ranges.rs:61:5 | LL | (1..=1 << 4).map(|_| do_something()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -198,7 +200,7 @@ LL + std::iter::repeat_with(|| do_something()).take((1 << 4) - 0); | error: map of a closure that does not depend on its parameter over a range - --> tests/ui/map_with_unused_argument_over_ranges.rs:67:5 + --> tests/ui/map_with_unused_argument_over_ranges.rs:83:5 | LL | (0..10).map(|_| do_something()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -210,7 +212,7 @@ LL + std::iter::repeat_with(|| do_something()).take(10); | error: map of a closure that does not depend on its parameter over a range - --> tests/ui/map_with_unused_argument_over_ranges.rs:72:5 + --> tests/ui/map_with_unused_argument_over_ranges.rs:89:5 | LL | (0..10).map(|_| 3); | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/map_with_unused_argument_over_ranges_nostd.fixed b/tests/ui/map_with_unused_argument_over_ranges_nostd.fixed index 65e59774905c..15a2780da440 100644 --- a/tests/ui/map_with_unused_argument_over_ranges_nostd.fixed +++ b/tests/ui/map_with_unused_argument_over_ranges_nostd.fixed @@ -5,4 +5,5 @@ use alloc::vec::Vec; fn nostd(v: &mut [i32]) { let _: Vec<_> = core::iter::repeat_n(3 + 1, 10).collect(); + //~^ map_with_unused_argument_over_ranges } diff --git a/tests/ui/map_with_unused_argument_over_ranges_nostd.rs b/tests/ui/map_with_unused_argument_over_ranges_nostd.rs index dda7a69b33f9..58de71facebb 100644 --- a/tests/ui/map_with_unused_argument_over_ranges_nostd.rs +++ b/tests/ui/map_with_unused_argument_over_ranges_nostd.rs @@ -5,4 +5,5 @@ use alloc::vec::Vec; fn nostd(v: &mut [i32]) { let _: Vec<_> = (0..10).map(|_| 3 + 1).collect(); + //~^ map_with_unused_argument_over_ranges } diff --git a/tests/ui/match_as_ref.rs b/tests/ui/match_as_ref.rs index 655e16623697..3a5b1227331e 100644 --- a/tests/ui/match_as_ref.rs +++ b/tests/ui/match_as_ref.rs @@ -4,12 +4,14 @@ fn match_as_ref() { let owned: Option<()> = None; let borrowed: Option<&()> = match owned { + //~^ match_as_ref None => None, Some(ref v) => Some(v), }; let mut mut_owned: Option<()> = None; let borrow_mut: Option<&mut ()> = match mut_owned { + //~^ match_as_ref None => None, Some(ref mut v) => Some(v), }; @@ -28,6 +30,7 @@ mod issue4437 { impl Error for E { fn source(&self) -> Option<&(dyn Error + 'static)> { match self.source { + //~^ match_as_ref Some(ref s) => Some(s), None => None, } diff --git a/tests/ui/match_as_ref.stderr b/tests/ui/match_as_ref.stderr index 97b121424d93..7b40cb80dc6e 100644 --- a/tests/ui/match_as_ref.stderr +++ b/tests/ui/match_as_ref.stderr @@ -3,6 +3,7 @@ error: use `as_ref()` instead | LL | let borrowed: Option<&()> = match owned { | _________________________________^ +LL | | LL | | None => None, LL | | Some(ref v) => Some(v), LL | | }; @@ -12,19 +13,21 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::match_as_ref)]` error: use `as_mut()` instead - --> tests/ui/match_as_ref.rs:12:39 + --> tests/ui/match_as_ref.rs:13:39 | LL | let borrow_mut: Option<&mut ()> = match mut_owned { | _______________________________________^ +LL | | LL | | None => None, LL | | Some(ref mut v) => Some(v), LL | | }; | |_____^ help: try: `mut_owned.as_mut()` error: use `as_ref()` instead - --> tests/ui/match_as_ref.rs:30:13 + --> tests/ui/match_as_ref.rs:32:13 | LL | / match self.source { +LL | | LL | | Some(ref s) => Some(s), LL | | None => None, LL | | } diff --git a/tests/ui/match_bool.fixed b/tests/ui/match_bool.fixed index 61a8e54fa10c..1dfb82db1206 100644 --- a/tests/ui/match_bool.fixed +++ b/tests/ui/match_bool.fixed @@ -55,4 +55,10 @@ fn match_bool() { if !(!test && option == 5) { println!("Hello") }; } +fn issue14099() { + if true { 'a: { + break 'a; + } } +} + fn main() {} diff --git a/tests/ui/match_bool.rs b/tests/ui/match_bool.rs index 9c81d2917869..719b4e51eb6d 100644 --- a/tests/ui/match_bool.rs +++ b/tests/ui/match_bool.rs @@ -5,20 +5,20 @@ fn match_bool() { let test: bool = true; match test { - //~^ ERROR: `match` on a boolean expression + //~^ match_bool true => 0, false => 42, }; let option = 1; match option == 1 { - //~^ ERROR: `match` on a boolean expression + //~^ match_bool true => 1, false => 0, }; match test { - //~^ ERROR: `match` on a boolean expression + //~^ match_bool true => (), false => { println!("Noooo!"); @@ -26,7 +26,7 @@ fn match_bool() { }; match test { - //~^ ERROR: `match` on a boolean expression + //~^ match_bool false => { println!("Noooo!"); }, @@ -34,7 +34,7 @@ fn match_bool() { }; match test && test { - //~^ ERROR: `match` on a boolean expression + //~^ match_bool false => { println!("Noooo!"); }, @@ -42,7 +42,7 @@ fn match_bool() { }; match test { - //~^ ERROR: `match` on a boolean expression + //~^ match_bool false => { println!("Noooo!"); }, @@ -67,40 +67,50 @@ fn match_bool() { }; let _ = match test { - //~^ ERROR: `match` on a boolean expression + //~^ match_bool true if option == 5 => 10, _ => 1, }; let _ = match test { - //~^ ERROR: `match` on a boolean expression + //~^ match_bool false if option == 5 => 10, _ => 1, }; match test { - //~^ ERROR: `match` on a boolean expression + //~^ match_bool true if option == 5 => println!("Hello"), _ => (), }; match test { - //~^ ERROR: `match` on a boolean expression + //~^ match_bool true if option == 5 => (), _ => println!("Hello"), }; match test { - //~^ ERROR: `match` on a boolean expression + //~^ match_bool false if option == 5 => println!("Hello"), _ => (), }; match test { - //~^ ERROR: `match` on a boolean expression + //~^ match_bool false if option == 5 => (), _ => println!("Hello"), }; } +fn issue14099() { + match true { + //~^ match_bool + true => 'a: { + break 'a; + }, + _ => (), + } +} + fn main() {} diff --git a/tests/ui/match_bool.stderr b/tests/ui/match_bool.stderr index a4e504a0a82e..c05742e56339 100644 --- a/tests/ui/match_bool.stderr +++ b/tests/ui/match_bool.stderr @@ -164,5 +164,24 @@ LL | | _ => println!("Hello"), LL | | }; | |_____^ help: consider using an `if`/`else` expression: `if !(!test && option == 5) { println!("Hello") }` -error: aborting due to 12 previous errors +error: `match` on a boolean expression + --> tests/ui/match_bool.rs:107:5 + | +LL | / match true { +LL | | +LL | | true => 'a: { +LL | | break 'a; +LL | | }, +LL | | _ => (), +LL | | } + | |_____^ + | +help: consider using an `if`/`else` expression + | +LL ~ if true { 'a: { +LL + break 'a; +LL + } } + | + +error: aborting due to 13 previous errors diff --git a/tests/ui/match_expr_like_matches_macro.fixed b/tests/ui/match_expr_like_matches_macro.fixed index 05edc024ba9f..8530ab16bfd7 100644 --- a/tests/ui/match_expr_like_matches_macro.fixed +++ b/tests/ui/match_expr_like_matches_macro.fixed @@ -12,18 +12,23 @@ fn main() { // Lint let _y = matches!(x, Some(0)); + //~^^^^ match_like_matches_macro // Lint let _w = x.is_some(); + //~^^^^ redundant_pattern_matching // Turn into is_none let _z = x.is_none(); + //~^^^^ redundant_pattern_matching // Lint let _zz = !matches!(x, Some(r) if r == 0); + //~^^^^ match_like_matches_macro // Lint let _zzz = matches!(x, Some(5)); + //~^ match_like_matches_macro // No lint let _a = match x { @@ -48,16 +53,19 @@ fn main() { { // lint let _ans = matches!(x, E::A(_) | E::B(_)); + //~^^^^^ match_like_matches_macro } { // lint // skip rustfmt to prevent removing block for first pattern #[rustfmt::skip] let _ans = matches!(x, E::A(_) | E::B(_)); + //~^^^^^^^ match_like_matches_macro } { // lint let _ans = !matches!(x, E::B(_) | E::C); + //~^^^^^ match_like_matches_macro } { // no lint @@ -114,12 +122,14 @@ fn main() { // should print "z" in suggestion (#6503) let z = &Some(3); let _z = matches!(z, Some(3)); + //~^^^^ match_like_matches_macro } { // this could also print "z" in suggestion..? let z = Some(3); let _z = matches!(&z, Some(3)); + //~^^^^ match_like_matches_macro } { @@ -134,6 +144,7 @@ fn main() { let z = AnEnum::X; // we can't remove the reference here! let _ = matches!(&z, AnEnum::X); + //~^^^^ match_like_matches_macro foo(z); } } @@ -145,6 +156,7 @@ fn main() { let val = Some(S(42)); // we need the reference here because later val is consumed by fun() let _res = matches!(&val, &Some(ref _a)); + //~^^^^ match_like_matches_macro fun(val); } @@ -154,6 +166,7 @@ fn main() { fn fun(_val: Option) {} let val = Some(S(42)); let _res = matches!(&val, &Some(ref _a)); + //~^^^^ match_like_matches_macro fun(val); } @@ -209,4 +222,5 @@ fn msrv_1_41() { #[clippy::msrv = "1.42"] fn msrv_1_42() { let _y = matches!(Some(5), Some(0)); + //~^^^^ match_like_matches_macro } diff --git a/tests/ui/match_expr_like_matches_macro.rs b/tests/ui/match_expr_like_matches_macro.rs index d6a0313cde43..81017936889e 100644 --- a/tests/ui/match_expr_like_matches_macro.rs +++ b/tests/ui/match_expr_like_matches_macro.rs @@ -15,27 +15,32 @@ fn main() { Some(0) => true, _ => false, }; + //~^^^^ match_like_matches_macro // Lint let _w = match x { Some(_) => true, _ => false, }; + //~^^^^ redundant_pattern_matching // Turn into is_none let _z = match x { Some(_) => false, None => true, }; + //~^^^^ redundant_pattern_matching // Lint let _zz = match x { Some(r) if r == 0 => false, _ => true, }; + //~^^^^ match_like_matches_macro // Lint let _zzz = if let Some(5) = x { true } else { false }; + //~^ match_like_matches_macro // No lint let _a = match x { @@ -64,6 +69,7 @@ fn main() { E::B(_) => true, _ => false, }; + //~^^^^^ match_like_matches_macro } { // lint @@ -76,6 +82,7 @@ fn main() { E::B(_) => true, _ => false, }; + //~^^^^^^^ match_like_matches_macro } { // lint @@ -84,6 +91,7 @@ fn main() { E::C => false, _ => true, }; + //~^^^^^ match_like_matches_macro } { // no lint @@ -143,6 +151,7 @@ fn main() { Some(3) => true, _ => false, }; + //~^^^^ match_like_matches_macro } { @@ -152,6 +161,7 @@ fn main() { Some(3) => true, _ => false, }; + //~^^^^ match_like_matches_macro } { @@ -169,6 +179,7 @@ fn main() { AnEnum::X => true, _ => false, }; + //~^^^^ match_like_matches_macro foo(z); } } @@ -183,6 +194,7 @@ fn main() { &Some(ref _a) => true, _ => false, }; + //~^^^^ match_like_matches_macro fun(val); } @@ -195,6 +207,7 @@ fn main() { &Some(ref _a) => true, _ => false, }; + //~^^^^ match_like_matches_macro fun(val); } @@ -253,4 +266,5 @@ fn msrv_1_42() { Some(0) => true, _ => false, }; + //~^^^^ match_like_matches_macro } diff --git a/tests/ui/match_expr_like_matches_macro.stderr b/tests/ui/match_expr_like_matches_macro.stderr index ffe5772ece90..8fceb05bc6e8 100644 --- a/tests/ui/match_expr_like_matches_macro.stderr +++ b/tests/ui/match_expr_like_matches_macro.stderr @@ -12,7 +12,7 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::match_like_matches_macro)]` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/match_expr_like_matches_macro.rs:20:14 + --> tests/ui/match_expr_like_matches_macro.rs:21:14 | LL | let _w = match x { | ______________^ @@ -25,7 +25,7 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::redundant_pattern_matching)]` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/match_expr_like_matches_macro.rs:26:14 + --> tests/ui/match_expr_like_matches_macro.rs:28:14 | LL | let _z = match x { | ______________^ @@ -35,7 +35,7 @@ LL | | }; | |_____^ help: try: `x.is_none()` error: match expression looks like `matches!` macro - --> tests/ui/match_expr_like_matches_macro.rs:32:15 + --> tests/ui/match_expr_like_matches_macro.rs:35:15 | LL | let _zz = match x { | _______________^ @@ -45,13 +45,13 @@ LL | | }; | |_____^ help: try: `!matches!(x, Some(r) if r == 0)` error: if let .. else expression looks like `matches!` macro - --> tests/ui/match_expr_like_matches_macro.rs:38:16 + --> tests/ui/match_expr_like_matches_macro.rs:42:16 | LL | let _zzz = if let Some(5) = x { true } else { false }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(x, Some(5))` error: match expression looks like `matches!` macro - --> tests/ui/match_expr_like_matches_macro.rs:62:20 + --> tests/ui/match_expr_like_matches_macro.rs:67:20 | LL | let _ans = match x { | ____________________^ @@ -62,7 +62,7 @@ LL | | }; | |_________^ help: try: `matches!(x, E::A(_) | E::B(_))` error: match expression looks like `matches!` macro - --> tests/ui/match_expr_like_matches_macro.rs:72:20 + --> tests/ui/match_expr_like_matches_macro.rs:78:20 | LL | let _ans = match x { | ____________________^ @@ -74,7 +74,7 @@ LL | | }; | |_________^ help: try: `matches!(x, E::A(_) | E::B(_))` error: match expression looks like `matches!` macro - --> tests/ui/match_expr_like_matches_macro.rs:82:20 + --> tests/ui/match_expr_like_matches_macro.rs:89:20 | LL | let _ans = match x { | ____________________^ @@ -85,7 +85,7 @@ LL | | }; | |_________^ help: try: `!matches!(x, E::B(_) | E::C)` error: match expression looks like `matches!` macro - --> tests/ui/match_expr_like_matches_macro.rs:142:18 + --> tests/ui/match_expr_like_matches_macro.rs:150:18 | LL | let _z = match &z { | __________________^ @@ -95,7 +95,7 @@ LL | | }; | |_________^ help: try: `matches!(z, Some(3))` error: match expression looks like `matches!` macro - --> tests/ui/match_expr_like_matches_macro.rs:151:18 + --> tests/ui/match_expr_like_matches_macro.rs:160:18 | LL | let _z = match &z { | __________________^ @@ -105,7 +105,7 @@ LL | | }; | |_________^ help: try: `matches!(&z, Some(3))` error: match expression looks like `matches!` macro - --> tests/ui/match_expr_like_matches_macro.rs:168:21 + --> tests/ui/match_expr_like_matches_macro.rs:178:21 | LL | let _ = match &z { | _____________________^ @@ -115,7 +115,7 @@ LL | | }; | |_____________^ help: try: `matches!(&z, AnEnum::X)` error: match expression looks like `matches!` macro - --> tests/ui/match_expr_like_matches_macro.rs:182:20 + --> tests/ui/match_expr_like_matches_macro.rs:193:20 | LL | let _res = match &val { | ____________________^ @@ -125,7 +125,7 @@ LL | | }; | |_________^ help: try: `matches!(&val, &Some(ref _a))` error: match expression looks like `matches!` macro - --> tests/ui/match_expr_like_matches_macro.rs:194:20 + --> tests/ui/match_expr_like_matches_macro.rs:206:20 | LL | let _res = match &val { | ____________________^ @@ -135,7 +135,7 @@ LL | | }; | |_________^ help: try: `matches!(&val, &Some(ref _a))` error: match expression looks like `matches!` macro - --> tests/ui/match_expr_like_matches_macro.rs:252:14 + --> tests/ui/match_expr_like_matches_macro.rs:265:14 | LL | let _y = match Some(5) { | ______________^ diff --git a/tests/ui/match_on_vec_items.rs b/tests/ui/match_on_vec_items.rs index f7b8500faa4a..f3174ec9734d 100644 --- a/tests/ui/match_on_vec_items.rs +++ b/tests/ui/match_on_vec_items.rs @@ -8,8 +8,7 @@ fn match_with_wildcard() { // Lint, may panic match arr[idx] { - //~^ ERROR: indexing into a vector may panic - //~| NOTE: `-D clippy::match-on-vec-items` implied by `-D warnings` + //~^ match_on_vec_items 0 => println!("0"), 1 => println!("1"), _ => {}, @@ -17,7 +16,7 @@ fn match_with_wildcard() { // Lint, may panic match arr[range] { - //~^ ERROR: indexing into a vector may panic + //~^ match_on_vec_items [0, 1] => println!("0 1"), [1, 2] => println!("1 2"), _ => {}, @@ -31,7 +30,7 @@ fn match_without_wildcard() { // Lint, may panic match arr[idx] { - //~^ ERROR: indexing into a vector may panic + //~^ match_on_vec_items 0 => println!("0"), 1 => println!("1"), num => {}, @@ -39,7 +38,7 @@ fn match_without_wildcard() { // Lint, may panic match arr[range] { - //~^ ERROR: indexing into a vector may panic + //~^ match_on_vec_items [0, 1] => println!("0 1"), [1, 2] => println!("1 2"), [ref sub @ ..] => {}, @@ -53,7 +52,7 @@ fn match_wildcard_and_action() { // Lint, may panic match arr[idx] { - //~^ ERROR: indexing into a vector may panic + //~^ match_on_vec_items 0 => println!("0"), 1 => println!("1"), _ => println!("Hello, World!"), @@ -61,7 +60,7 @@ fn match_wildcard_and_action() { // Lint, may panic match arr[range] { - //~^ ERROR: indexing into a vector may panic + //~^ match_on_vec_items [0, 1] => println!("0 1"), [1, 2] => println!("1 2"), _ => println!("Hello, World!"), @@ -75,7 +74,7 @@ fn match_vec_ref() { // Lint, may panic match arr[idx] { - //~^ ERROR: indexing into a vector may panic + //~^ match_on_vec_items 0 => println!("0"), 1 => println!("1"), _ => {}, @@ -83,7 +82,7 @@ fn match_vec_ref() { // Lint, may panic match arr[range] { - //~^ ERROR: indexing into a vector may panic + //~^ match_on_vec_items [0, 1] => println!("0 1"), [1, 2] => println!("1 2"), _ => {}, diff --git a/tests/ui/match_on_vec_items.stderr b/tests/ui/match_on_vec_items.stderr index e31db3784137..ae79e1305f7f 100644 --- a/tests/ui/match_on_vec_items.stderr +++ b/tests/ui/match_on_vec_items.stderr @@ -8,43 +8,43 @@ LL | match arr[idx] { = help: to override `-D warnings` add `#[allow(clippy::match_on_vec_items)]` error: indexing into a vector may panic - --> tests/ui/match_on_vec_items.rs:19:11 + --> tests/ui/match_on_vec_items.rs:18:11 | LL | match arr[range] { | ^^^^^^^^^^ help: try: `arr.get(range)` error: indexing into a vector may panic - --> tests/ui/match_on_vec_items.rs:33:11 + --> tests/ui/match_on_vec_items.rs:32:11 | LL | match arr[idx] { | ^^^^^^^^ help: try: `arr.get(idx)` error: indexing into a vector may panic - --> tests/ui/match_on_vec_items.rs:41:11 + --> tests/ui/match_on_vec_items.rs:40:11 | LL | match arr[range] { | ^^^^^^^^^^ help: try: `arr.get(range)` error: indexing into a vector may panic - --> tests/ui/match_on_vec_items.rs:55:11 + --> tests/ui/match_on_vec_items.rs:54:11 | LL | match arr[idx] { | ^^^^^^^^ help: try: `arr.get(idx)` error: indexing into a vector may panic - --> tests/ui/match_on_vec_items.rs:63:11 + --> tests/ui/match_on_vec_items.rs:62:11 | LL | match arr[range] { | ^^^^^^^^^^ help: try: `arr.get(range)` error: indexing into a vector may panic - --> tests/ui/match_on_vec_items.rs:77:11 + --> tests/ui/match_on_vec_items.rs:76:11 | LL | match arr[idx] { | ^^^^^^^^ help: try: `arr.get(idx)` error: indexing into a vector may panic - --> tests/ui/match_on_vec_items.rs:85:11 + --> tests/ui/match_on_vec_items.rs:84:11 | LL | match arr[range] { | ^^^^^^^^^^ help: try: `arr.get(range)` diff --git a/tests/ui/match_overlapping_arm.rs b/tests/ui/match_overlapping_arm.rs index a056fdeaa5d0..176287e3d2e0 100644 --- a/tests/ui/match_overlapping_arm.rs +++ b/tests/ui/match_overlapping_arm.rs @@ -7,14 +7,14 @@ fn overlapping() { match 42 { 0..=10 => println!("0..=10"), - //~^ ERROR: some ranges overlap + //~^ match_overlapping_arm 0..=11 => println!("0..=11"), _ => (), } match 42 { 0..=5 => println!("0..=5"), - //~^ ERROR: some ranges overlap + //~^ match_overlapping_arm 6..=7 => println!("6..=7"), FOO..=11 => println!("FOO..=11"), _ => (), @@ -52,7 +52,7 @@ fn overlapping() { match 42 { 0..11 => println!("0..11"), - //~^ ERROR: some ranges overlap + //~^ match_overlapping_arm 0..=11 => println!("0..=11"), _ => (), } @@ -78,13 +78,13 @@ fn overlapping() { match 42 { 5..14 => println!("5..14"), 0..=10 => println!("0..=10"), - //~^ ERROR: some ranges overlap + //~^ match_overlapping_arm _ => (), } match 42 { 0..7 => println!("0..7"), - //~^ ERROR: some ranges overlap + //~^ match_overlapping_arm 0..=10 => println!("0..=10"), _ => (), } @@ -97,7 +97,7 @@ fn overlapping() { match 42 { ..=23 => println!("..=23"), - //~^ ERROR: some ranges overlap + //~^ match_overlapping_arm ..26 => println!("..26"), _ => (), } @@ -107,7 +107,7 @@ fn overlapping() { 5..=10 => (), 0..=20 => (), 21..=30 => (), - //~^ ERROR: some ranges overlap + //~^ match_overlapping_arm 21..=40 => (), _ => (), } @@ -122,7 +122,7 @@ fn overlapping() { // Only warn about the first if there are multiple overlaps match 42u128 { 0..=0x0000_0000_0000_00ff => (), - //~^ ERROR: some ranges overlap + //~^ match_overlapping_arm 0..=0x0000_0000_0000_ffff => (), 0..=0x0000_0000_ffff_ffff => (), 0..=0xffff_ffff_ffff_ffff => (), diff --git a/tests/ui/match_ref_pats.fixed b/tests/ui/match_ref_pats.fixed index f8d47b0fdc7d..8add3da0c99f 100644 --- a/tests/ui/match_ref_pats.fixed +++ b/tests/ui/match_ref_pats.fixed @@ -6,6 +6,7 @@ fn ref_pats() { { let v = &Some(0); match *v { + //~^ match_ref_pats Some(v) => println!("{:?}", v), None => println!("none"), } @@ -23,6 +24,7 @@ fn ref_pats() { // Special case: using `&` both in expr and pats. let w = Some(0); match w { + //~^ match_ref_pats Some(v) => println!("{:?}", v), None => println!("none"), } @@ -35,11 +37,13 @@ fn ref_pats() { let a = &Some(0); if a.is_none() { + //~^ redundant_pattern_matching println!("none"); } let b = Some(0); if b.is_none() { + //~^ redundant_pattern_matching println!("none"); } } @@ -100,6 +104,7 @@ mod issue_7740 { fn issue_7740() { // Issue #7740 match *foobar_variant!(0) { + //~^ match_ref_pats FooBar::Foo => println!("Foo"), FooBar::Bar => println!("Bar"), FooBar::FooBar => println!("FooBar"), diff --git a/tests/ui/match_ref_pats.rs b/tests/ui/match_ref_pats.rs index bcd7bf7ab51b..07889b0dfc24 100644 --- a/tests/ui/match_ref_pats.rs +++ b/tests/ui/match_ref_pats.rs @@ -6,6 +6,7 @@ fn ref_pats() { { let v = &Some(0); match v { + //~^ match_ref_pats &Some(v) => println!("{:?}", v), &None => println!("none"), } @@ -23,6 +24,7 @@ fn ref_pats() { // Special case: using `&` both in expr and pats. let w = Some(0); match &w { + //~^ match_ref_pats &Some(v) => println!("{:?}", v), &None => println!("none"), } @@ -35,11 +37,13 @@ fn ref_pats() { let a = &Some(0); if let &None = a { + //~^ redundant_pattern_matching println!("none"); } let b = Some(0); if let &None = &b { + //~^ redundant_pattern_matching println!("none"); } } @@ -100,6 +104,7 @@ mod issue_7740 { fn issue_7740() { // Issue #7740 match foobar_variant!(0) { + //~^ match_ref_pats &FooBar::Foo => println!("Foo"), &FooBar::Bar => println!("Bar"), &FooBar::FooBar => println!("FooBar"), diff --git a/tests/ui/match_ref_pats.stderr b/tests/ui/match_ref_pats.stderr index fc01ab0a919a..f81b290b32cb 100644 --- a/tests/ui/match_ref_pats.stderr +++ b/tests/ui/match_ref_pats.stderr @@ -2,6 +2,7 @@ error: you don't need to add `&` to all patterns --> tests/ui/match_ref_pats.rs:8:9 | LL | / match v { +LL | | LL | | &Some(v) => println!("{:?}", v), LL | | &None => println!("none"), LL | | } @@ -12,14 +13,16 @@ LL | | } help: instead of prefixing all patterns with `&`, you can dereference the expression | LL ~ match *v { +LL | LL ~ Some(v) => println!("{:?}", v), LL ~ None => println!("none"), | error: you don't need to add `&` to both the expression and the patterns - --> tests/ui/match_ref_pats.rs:25:5 + --> tests/ui/match_ref_pats.rs:26:5 | LL | / match &w { +LL | | LL | | &Some(v) => println!("{:?}", v), LL | | &None => println!("none"), LL | | } @@ -28,12 +31,13 @@ LL | | } help: try | LL ~ match w { +LL | LL ~ Some(v) => println!("{:?}", v), LL ~ None => println!("none"), | error: redundant pattern matching, consider using `is_none()` - --> tests/ui/match_ref_pats.rs:37:12 + --> tests/ui/match_ref_pats.rs:39:12 | LL | if let &None = a { | -------^^^^^---- help: try: `if a.is_none()` @@ -42,15 +46,16 @@ LL | if let &None = a { = help: to override `-D warnings` add `#[allow(clippy::redundant_pattern_matching)]` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/match_ref_pats.rs:42:12 + --> tests/ui/match_ref_pats.rs:45:12 | LL | if let &None = &b { | -------^^^^^----- help: try: `if b.is_none()` error: you don't need to add `&` to all patterns - --> tests/ui/match_ref_pats.rs:102:9 + --> tests/ui/match_ref_pats.rs:106:9 | LL | / match foobar_variant!(0) { +LL | | LL | | &FooBar::Foo => println!("Foo"), LL | | &FooBar::Bar => println!("Bar"), LL | | &FooBar::FooBar => println!("FooBar"), @@ -61,6 +66,7 @@ LL | | } help: instead of prefixing all patterns with `&`, you can dereference the expression | LL ~ match *foobar_variant!(0) { +LL | LL ~ FooBar::Foo => println!("Foo"), LL ~ FooBar::Bar => println!("Bar"), LL ~ FooBar::FooBar => println!("FooBar"), diff --git a/tests/ui/match_result_ok.fixed b/tests/ui/match_result_ok.fixed index 117e0bc68ccc..0e630e6a2904 100644 --- a/tests/ui/match_result_ok.fixed +++ b/tests/ui/match_result_ok.fixed @@ -11,6 +11,7 @@ fn str_to_int(x: &str) -> i32 { if let Ok(y) = x.parse() { y } else { 0 } + //~^ match_result_ok } fn str_to_int_ok(x: &str) -> i32 { @@ -21,6 +22,7 @@ fn str_to_int_ok(x: &str) -> i32 { fn strange_some_no_else(x: &str) -> i32 { { if let Ok(y) = x . parse() { + //~^ match_result_ok return y; }; 0 @@ -47,6 +49,7 @@ impl Wat { fn base_1(x: i32) { let mut wat = Wat { counter: x }; while let Ok(a) = wat.next() { + //~^ match_result_ok println!("{}", a); } } diff --git a/tests/ui/match_result_ok.rs b/tests/ui/match_result_ok.rs index f8a5269024da..63bf6e8ab508 100644 --- a/tests/ui/match_result_ok.rs +++ b/tests/ui/match_result_ok.rs @@ -11,6 +11,7 @@ fn str_to_int(x: &str) -> i32 { if let Some(y) = x.parse().ok() { y } else { 0 } + //~^ match_result_ok } fn str_to_int_ok(x: &str) -> i32 { @@ -21,6 +22,7 @@ fn str_to_int_ok(x: &str) -> i32 { fn strange_some_no_else(x: &str) -> i32 { { if let Some(y) = x . parse() . ok () { + //~^ match_result_ok return y; }; 0 @@ -47,6 +49,7 @@ impl Wat { fn base_1(x: i32) { let mut wat = Wat { counter: x }; while let Some(a) = wat.next().ok() { + //~^ match_result_ok println!("{}", a); } } diff --git a/tests/ui/match_result_ok.stderr b/tests/ui/match_result_ok.stderr index 18b23bd78454..822cc4de77f3 100644 --- a/tests/ui/match_result_ok.stderr +++ b/tests/ui/match_result_ok.stderr @@ -13,7 +13,7 @@ LL + if let Ok(y) = x.parse() { y } else { 0 } | error: matching on `Some` with `ok()` is redundant - --> tests/ui/match_result_ok.rs:23:9 + --> tests/ui/match_result_ok.rs:24:9 | LL | if let Some(y) = x . parse() . ok () { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + if let Ok(y) = x . parse() { | error: matching on `Some` with `ok()` is redundant - --> tests/ui/match_result_ok.rs:49:5 + --> tests/ui/match_result_ok.rs:51:5 | LL | while let Some(a) = wat.next().ok() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/match_same_arms.rs b/tests/ui/match_same_arms.rs index 2f4652dcf32b..55441948e91b 100644 --- a/tests/ui/match_same_arms.rs +++ b/tests/ui/match_same_arms.rs @@ -9,30 +9,36 @@ pub enum Abc { fn match_same_arms() { let _ = match Abc::A { - Abc::A => 0, //~ ERROR: this match arm has an identical body to the `_` wildcard arm + Abc::A => 0, + //~^ match_same_arms Abc::B => 1, _ => 0, }; match (1, 2, 3) { - (1, .., 3) => 42, //~ ERROR: this match arm has an identical body to another arm + (1, .., 3) => 42, + //~^ match_same_arms (.., 3) => 42, _ => 0, }; let _ = match 42 { 42 => 1, - 51 => 1, //~ ERROR: this match arm has an identical body to another arm - 41 => 2, //~ ERROR: this match arm has an identical body to another arm + 51 => 1, + //~^ match_same_arms + 41 => 2, + //~^ match_same_arms 52 => 2, _ => 0, }; let _ = match 42 { 1 => 2, - 2 => 2, //~ ERROR: this match arm has an identical body to another arm - //~^ ERROR: this match arm has an identical body to another arm - 3 => 2, //~ ERROR: this match arm has an identical body to another arm + 2 => 2, + //~^ match_same_arms + //~| match_same_arms + 3 => 2, + //~^ match_same_arms 4 => 3, _ => 0, }; @@ -50,7 +56,7 @@ mod issue4244 { match self { CommandInfo::BuiltIn { name, .. } => name.to_string(), CommandInfo::External { name, .. } => name.to_string(), - //~^ ERROR: this match arm has an identical body to another arm + //~^ match_same_arms } } } diff --git a/tests/ui/match_same_arms.stderr b/tests/ui/match_same_arms.stderr index 4a4772da143a..3744b83d89cc 100644 --- a/tests/ui/match_same_arms.stderr +++ b/tests/ui/match_same_arms.stderr @@ -1,12 +1,13 @@ error: this match arm has an identical body to the `_` wildcard arm --> tests/ui/match_same_arms.rs:12:9 | -LL | Abc::A => 0, - | ^^^^^^^^^^^^^ help: try removing the arm +LL | / Abc::A => 0, +LL | | + | |________^ help: try removing the arm | = help: or try changing either arm body note: `_` wildcard arm here - --> tests/ui/match_same_arms.rs:14:9 + --> tests/ui/match_same_arms.rs:15:9 | LL | _ => 0, | ^^^^^^ @@ -14,7 +15,7 @@ LL | _ => 0, = help: to override `-D warnings` add `#[allow(clippy::match_same_arms)]` error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms.rs:18:9 + --> tests/ui/match_same_arms.rs:19:9 | LL | (1, .., 3) => 42, | ^^^^^^^^^^^^^^^^ @@ -23,11 +24,12 @@ LL | (1, .., 3) => 42, help: or try merging the arm patterns and removing the obsolete arm | LL ~ (1, .., 3) | (.., 3) => 42, +LL | LL ~ _ => 0, | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms.rs:25:9 + --> tests/ui/match_same_arms.rs:27:9 | LL | 51 => 1, | ^^^^^^^ @@ -41,7 +43,7 @@ LL + 51 | 42 => 1, | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms.rs:26:9 + --> tests/ui/match_same_arms.rs:29:9 | LL | 41 => 2, | ^^^^^^^ @@ -50,11 +52,12 @@ LL | 41 => 2, help: or try merging the arm patterns and removing the obsolete arm | LL ~ 41 | 52 => 2, +LL | LL ~ _ => 0, | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms.rs:33:9 + --> tests/ui/match_same_arms.rs:37:9 | LL | 2 => 2, | ^^^^^^ @@ -68,7 +71,7 @@ LL + 2 | 1 => 2, | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms.rs:35:9 + --> tests/ui/match_same_arms.rs:40:9 | LL | 3 => 2, | ^^^^^^ @@ -78,11 +81,12 @@ help: or try merging the arm patterns and removing the obsolete arm | LL ~ 2 => 2, LL | +LL | LL ~ 3 | 1 => 2, | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms.rs:33:9 + --> tests/ui/match_same_arms.rs:37:9 | LL | 2 => 2, | ^^^^^^ @@ -92,11 +96,12 @@ help: or try merging the arm patterns and removing the obsolete arm | LL ~ 2 | 3 => 2, LL | +LL | LL ~ | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms.rs:52:17 + --> tests/ui/match_same_arms.rs:58:17 | LL | CommandInfo::External { name, .. } => name.to_string(), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/match_same_arms2.fixed b/tests/ui/match_same_arms2.fixed index b7d377f1ebff..0d93e2c728d7 100644 --- a/tests/ui/match_same_arms2.fixed +++ b/tests/ui/match_same_arms2.fixed @@ -14,6 +14,7 @@ fn foo() -> bool { fn match_same_arms() { let _ = match 42 { + //~^^^^^^^^^ match_same_arms _ => { foo(); let mut a = 42 + [23].len() as i32; @@ -24,15 +25,16 @@ fn match_same_arms() { a }, }; - //~^^^^^^^^^^^^^^^^^^^ ERROR: this match arm has an identical body to the `_` wildcard arm let _ = match 42 { - 51 | 42 => foo(), //~ ERROR: this match arm has an identical body to another arm + 51 | 42 => foo(), + //~^ match_same_arms _ => true, }; let _ = match Some(42) { - None | Some(_) => 24, //~ ERROR: this match arm has an identical body to another arm + None | Some(_) => 24, + //~^ match_same_arms }; let _ = match Some(42) { @@ -53,7 +55,8 @@ fn match_same_arms() { }; match (Some(42), Some(42)) { - (None, Some(a)) | (Some(a), None) => bar(a), //~ ERROR: this match arm has an identical body to another arm + (None, Some(a)) | (Some(a), None) => bar(a), + //~^ match_same_arms _ => (), } @@ -66,12 +69,14 @@ fn match_same_arms() { }; let _ = match (Some(42), Some(42)) { - (None, Some(a)) | (Some(a), None) if a == 42 => a, //~ ERROR: this match arm has an identical body to another arm + (None, Some(a)) | (Some(a), None) if a == 42 => a, + //~^ match_same_arms _ => 0, }; match (Some(42), Some(42)) { - (Some(a), ..) | (.., Some(a)) => bar(a), //~ ERROR: this match arm has an identical body to another arm + (Some(a), ..) | (.., Some(a)) => bar(a), + //~^ match_same_arms _ => (), } @@ -104,7 +109,8 @@ fn match_same_arms() { } match (x, Some(1i32)) { - (Ok(x), Some(_)) | (Ok(_), Some(x)) => println!("ok {}", x), //~ ERROR: this match arm has an identical body to another arm + (Ok(x), Some(_)) | (Ok(_), Some(x)) => println!("ok {}", x), + //~^ match_same_arms _ => println!("err"), } @@ -118,7 +124,8 @@ fn match_same_arms() { // False negative #2251. match x { Ok(_tmp) => println!("ok"), - Ok(_) | Ok(3) => println!("ok"), //~ ERROR: this match arm has an identical body to another arm + Ok(_) | Ok(3) => println!("ok"), + //~^ match_same_arms Err(_) => { unreachable!(); }, @@ -145,11 +152,11 @@ fn match_same_arms() { 1 | 0 => { empty!(0); }, + //~^^^ match_same_arms x => { empty!(x); }, } - //~^^^^^^^ ERROR: this match arm has an identical body to another arm match_expr_like_matches_macro_priority(); } @@ -193,7 +200,8 @@ fn main() { // Suggest moving `Foo::Z(_)` up. let _ = match Foo::X(0) { - Foo::X(0) | Foo::Z(_) => 1, //~ ERROR: this match arm has an identical body to another arm + Foo::X(0) | Foo::Z(_) => 1, + //~^ match_same_arms Foo::X(_) | Foo::Y(_) => 2, _ => 0, }; @@ -201,7 +209,8 @@ fn main() { // Suggest moving `Foo::X(0)` down. let _ = match Foo::X(0) { Foo::Y(_) | Foo::Z(0) => 2, - Foo::Z(_) | Foo::X(0) => 1, //~ ERROR: this match arm has an identical body to another arm + Foo::Z(_) | Foo::X(0) => 1, + //~^ match_same_arms _ => 0, }; @@ -223,7 +232,8 @@ fn main() { let _ = match None { Some(Bar { y: 10, z: 0, .. }) => 2, None => 50, - Some(Bar { y: 0, x: 5, .. }) | Some(Bar { x: 0, y: 5, .. }) => 1, //~ ERROR: this match arm has an identical body to another arm + Some(Bar { y: 0, x: 5, .. }) | Some(Bar { x: 0, y: 5, .. }) => 1, + //~^ match_same_arms _ => 200, }; @@ -237,6 +247,7 @@ fn main() { let _ = match 0 { 1 | 0 => cfg!(not_enable), + //~^ match_same_arms _ => false, }; } @@ -252,7 +263,7 @@ mod with_lifetime { fn get(&self) -> &'a str { match *self { MaybeStaticStr::Borrowed(s) | MaybeStaticStr::Static(s) => s, - //~^ ERROR: this match arm has an identical body to another arm + //~^ match_same_arms } } } diff --git a/tests/ui/match_same_arms2.rs b/tests/ui/match_same_arms2.rs index dfd15d10c3d3..b0ebc4784f33 100644 --- a/tests/ui/match_same_arms2.rs +++ b/tests/ui/match_same_arms2.rs @@ -23,6 +23,7 @@ fn match_same_arms() { a = -31 - a; a }, + //~^^^^^^^^^ match_same_arms _ => { foo(); let mut a = 42 + [23].len() as i32; @@ -33,17 +34,18 @@ fn match_same_arms() { a }, }; - //~^^^^^^^^^^^^^^^^^^^ ERROR: this match arm has an identical body to the `_` wildcard arm let _ = match 42 { 42 => foo(), - 51 => foo(), //~ ERROR: this match arm has an identical body to another arm + 51 => foo(), + //~^ match_same_arms _ => true, }; let _ = match Some(42) { Some(_) => 24, - None => 24, //~ ERROR: this match arm has an identical body to another arm + None => 24, + //~^ match_same_arms }; let _ = match Some(42) { @@ -65,7 +67,8 @@ fn match_same_arms() { match (Some(42), Some(42)) { (Some(a), None) => bar(a), - (None, Some(a)) => bar(a), //~ ERROR: this match arm has an identical body to another arm + (None, Some(a)) => bar(a), + //~^ match_same_arms _ => (), } @@ -79,12 +82,14 @@ fn match_same_arms() { let _ = match (Some(42), Some(42)) { (Some(a), None) if a == 42 => a, - (None, Some(a)) if a == 42 => a, //~ ERROR: this match arm has an identical body to another arm + (None, Some(a)) if a == 42 => a, + //~^ match_same_arms _ => 0, }; match (Some(42), Some(42)) { - (Some(a), ..) => bar(a), //~ ERROR: this match arm has an identical body to another arm + (Some(a), ..) => bar(a), + //~^ match_same_arms (.., Some(a)) => bar(a), _ => (), } @@ -118,7 +123,8 @@ fn match_same_arms() { } match (x, Some(1i32)) { - (Ok(x), Some(_)) => println!("ok {}", x), //~ ERROR: this match arm has an identical body to another arm + (Ok(x), Some(_)) => println!("ok {}", x), + //~^ match_same_arms (Ok(_), Some(x)) => println!("ok {}", x), _ => println!("err"), } @@ -134,7 +140,8 @@ fn match_same_arms() { match x { Ok(_tmp) => println!("ok"), Ok(3) => println!("ok"), - Ok(_) => println!("ok"), //~ ERROR: this match arm has an identical body to another arm + Ok(_) => println!("ok"), + //~^ match_same_arms Err(_) => { unreachable!(); }, @@ -164,11 +171,11 @@ fn match_same_arms() { 1 => { empty!(0); }, + //~^^^ match_same_arms x => { empty!(x); }, } - //~^^^^^^^ ERROR: this match arm has an identical body to another arm match_expr_like_matches_macro_priority(); } @@ -212,7 +219,8 @@ fn main() { // Suggest moving `Foo::Z(_)` up. let _ = match Foo::X(0) { - Foo::X(0) => 1, //~ ERROR: this match arm has an identical body to another arm + Foo::X(0) => 1, + //~^ match_same_arms Foo::X(_) | Foo::Y(_) => 2, Foo::Z(_) => 1, _ => 0, @@ -222,7 +230,8 @@ fn main() { let _ = match Foo::X(0) { Foo::X(0) => 1, Foo::Y(_) | Foo::Z(0) => 2, - Foo::Z(_) => 1, //~ ERROR: this match arm has an identical body to another arm + Foo::Z(_) => 1, + //~^ match_same_arms _ => 0, }; @@ -245,7 +254,8 @@ fn main() { Some(Bar { x: 0, y: 5, .. }) => 1, Some(Bar { y: 10, z: 0, .. }) => 2, None => 50, - Some(Bar { y: 0, x: 5, .. }) => 1, //~ ERROR: this match arm has an identical body to another arm + Some(Bar { y: 0, x: 5, .. }) => 1, + //~^ match_same_arms _ => 200, }; @@ -260,6 +270,7 @@ fn main() { let _ = match 0 { 0 => cfg!(not_enable), 1 => cfg!(not_enable), + //~^ match_same_arms _ => false, }; } @@ -276,7 +287,7 @@ mod with_lifetime { match *self { MaybeStaticStr::Static(s) => s, MaybeStaticStr::Borrowed(s) => s, - //~^ ERROR: this match arm has an identical body to another arm + //~^ match_same_arms } } } diff --git a/tests/ui/match_same_arms2.stderr b/tests/ui/match_same_arms2.stderr index 525a25e9287b..21a8743cc324 100644 --- a/tests/ui/match_same_arms2.stderr +++ b/tests/ui/match_same_arms2.stderr @@ -7,12 +7,12 @@ LL | | let mut a = 42 + [23].len() as i32; LL | | if true { ... | LL | | }, -LL | | _ => { +LL | | | |________^ help: try removing the arm | = help: or try changing either arm body note: `_` wildcard arm here - --> tests/ui/match_same_arms2.rs:26:9 + --> tests/ui/match_same_arms2.rs:27:9 | LL | / _ => { LL | | foo(); @@ -40,7 +40,7 @@ LL + 51 | 42 => foo(), | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:46:9 + --> tests/ui/match_same_arms2.rs:47:9 | LL | None => 24, | ^^^^^^^^^^ @@ -54,7 +54,7 @@ LL + None | Some(_) => 24, | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:68:9 + --> tests/ui/match_same_arms2.rs:70:9 | LL | (None, Some(a)) => bar(a), | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -68,7 +68,7 @@ LL + (None, Some(a)) | (Some(a), None) => bar(a), | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:82:9 + --> tests/ui/match_same_arms2.rs:85:9 | LL | (None, Some(a)) if a == 42 => a, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -82,7 +82,7 @@ LL + (None, Some(a)) | (Some(a), None) if a == 42 => a, | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:87:9 + --> tests/ui/match_same_arms2.rs:91:9 | LL | (Some(a), ..) => bar(a), | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -91,11 +91,12 @@ LL | (Some(a), ..) => bar(a), help: or try merging the arm patterns and removing the obsolete arm | LL ~ (Some(a), ..) | (.., Some(a)) => bar(a), +LL | LL ~ _ => (), | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:121:9 + --> tests/ui/match_same_arms2.rs:126:9 | LL | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -104,11 +105,12 @@ LL | (Ok(x), Some(_)) => println!("ok {}", x), help: or try merging the arm patterns and removing the obsolete arm | LL ~ (Ok(x), Some(_)) | (Ok(_), Some(x)) => println!("ok {}", x), +LL | LL ~ _ => println!("err"), | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:137:9 + --> tests/ui/match_same_arms2.rs:143:9 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -122,7 +124,7 @@ LL + Ok(_) | Ok(3) => println!("ok"), | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:164:9 + --> tests/ui/match_same_arms2.rs:171:9 | LL | / 1 => { LL | | empty!(0); @@ -140,7 +142,7 @@ LL + 1 | 0 => { | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:215:9 + --> tests/ui/match_same_arms2.rs:222:9 | LL | Foo::X(0) => 1, | ^^^^^^^^^^^^^^ @@ -149,12 +151,13 @@ LL | Foo::X(0) => 1, help: or try merging the arm patterns and removing the obsolete arm | LL ~ Foo::X(0) | Foo::Z(_) => 1, +LL | LL | Foo::X(_) | Foo::Y(_) => 2, LL ~ _ => 0, | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:225:9 + --> tests/ui/match_same_arms2.rs:233:9 | LL | Foo::Z(_) => 1, | ^^^^^^^^^^^^^^ @@ -167,7 +170,7 @@ LL ~ Foo::Z(_) | Foo::X(0) => 1, | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:248:9 + --> tests/ui/match_same_arms2.rs:257:9 | LL | Some(Bar { y: 0, x: 5, .. }) => 1, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -181,7 +184,7 @@ LL ~ Some(Bar { y: 0, x: 5, .. }) | Some(Bar { x: 0, y: 5, .. }) => 1, | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:262:9 + --> tests/ui/match_same_arms2.rs:272:9 | LL | 1 => cfg!(not_enable), | ^^^^^^^^^^^^^^^^^^^^^ @@ -195,7 +198,7 @@ LL + 1 | 0 => cfg!(not_enable), | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:278:17 + --> tests/ui/match_same_arms2.rs:289:17 | LL | MaybeStaticStr::Borrowed(s) => s, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/match_same_arms_non_exhaustive.fixed b/tests/ui/match_same_arms_non_exhaustive.fixed index 804c0a869a9f..0c9398933b80 100644 --- a/tests/ui/match_same_arms_non_exhaustive.fixed +++ b/tests/ui/match_same_arms_non_exhaustive.fixed @@ -41,7 +41,7 @@ pub fn g(x: Ordering) { Ordering::Relaxed => println!("relaxed"), Ordering::Release => println!("release"), Ordering::Acquire => println!("acquire"), - //~^ ERROR: this match arm has an identical body to the `_` wildcard arm + //~^ match_same_arms _ => repeat(), } } @@ -54,7 +54,7 @@ mod g { Ordering::Relaxed => println!("relaxed"), Ordering::Release => println!("release"), Ordering::Acquire => println!("acquire"), - //~^ ERROR: this match arm has an identical body to the `_` wildcard arm + //~^ match_same_arms _ => repeat(), } } diff --git a/tests/ui/match_same_arms_non_exhaustive.rs b/tests/ui/match_same_arms_non_exhaustive.rs index e50663932a1a..304a9e5c28e7 100644 --- a/tests/ui/match_same_arms_non_exhaustive.rs +++ b/tests/ui/match_same_arms_non_exhaustive.rs @@ -42,7 +42,7 @@ pub fn g(x: Ordering) { Ordering::Release => println!("release"), Ordering::Acquire => println!("acquire"), Ordering::AcqRel | Ordering::SeqCst => repeat(), - //~^ ERROR: this match arm has an identical body to the `_` wildcard arm + //~^ match_same_arms _ => repeat(), } } @@ -56,7 +56,7 @@ mod g { Ordering::Release => println!("release"), Ordering::Acquire => println!("acquire"), Ordering::AcqRel | Ordering::SeqCst => repeat(), - //~^ ERROR: this match arm has an identical body to the `_` wildcard arm + //~^ match_same_arms _ => repeat(), } } diff --git a/tests/ui/match_single_binding.rs b/tests/ui/match_single_binding.rs index ff2f842ac39e..ada51254c6cd 100644 --- a/tests/ui/match_single_binding.rs +++ b/tests/ui/match_single_binding.rs @@ -31,12 +31,14 @@ fn main() { let c = 3; // Lint match (a, b, c) { + //~^ match_single_binding (x, y, z) => { println!("{} {} {}", x, y, z); }, } // Lint match (a, b, c) { + //~^ match_single_binding (x, y, z) => println!("{} {} {}", x, y, z), } // Ok @@ -54,10 +56,12 @@ fn main() { } // Lint match a { + //~^ match_single_binding _ => println!("whatever"), } // Lint match a { + //~^ match_single_binding _ => { let x = 29; println!("x has a value of {}", x); @@ -65,6 +69,7 @@ fn main() { } // Lint match a { + //~^ match_single_binding _ => { let e = 5 * a; if e >= 5 { @@ -75,24 +80,29 @@ fn main() { // Lint let p = Point { x: 0, y: 7 }; match p { + //~^ match_single_binding Point { x, y } => println!("Coords: ({}, {})", x, y), } // Lint match p { + //~^ match_single_binding Point { x: x1, y: y1 } => println!("Coords: ({}, {})", x1, y1), } // Lint let x = 5; match x { + //~^ match_single_binding ref r => println!("Got a reference to {}", r), } // Lint let mut x = 5; match x { + //~^ match_single_binding ref mut mr => println!("Got a mutable reference to {}", mr), } // Lint let product = match coords() { + //~^ match_single_binding Point { x, y } => x * y, }; // Lint @@ -101,6 +111,7 @@ fn main() { let _ = v .iter() .map(|i| match i.unwrap() { + //~^ match_single_binding unwrapped => unwrapped, }) .collect::>(); @@ -127,6 +138,7 @@ fn main() { // Lint let x = 1; match x { + //~^ match_single_binding // => _ => println!("Not an array index start"), } @@ -136,6 +148,7 @@ fn issue_8723() { let (mut val, idx) = ("a b", 1); val = match val.split_at(idx) { + //~^ match_single_binding (pre, suf) => { println!("{}", pre); suf @@ -149,12 +162,14 @@ fn side_effects() {} fn issue_9575() { let _ = || match side_effects() { + //~^ match_single_binding _ => println!("Needs curlies"), }; } fn issue_9725(r: Option) { match r { + //~^ match_single_binding x => match x { Some(_) => { println!("Some"); @@ -168,37 +183,46 @@ fn issue_9725(r: Option) { fn issue_10447() -> usize { match 1 { + //~^ match_single_binding _ => (), } let a = match 1 { + //~^ match_single_binding _ => (), }; match 1 { + //~^ match_single_binding _ => side_effects(), } let b = match 1 { + //~^ match_single_binding _ => side_effects(), }; match 1 { + //~^ match_single_binding _ => println!("1"), } let c = match 1 { + //~^ match_single_binding _ => println!("1"), }; let in_expr = [ match 1 { + //~^ match_single_binding _ => (), }, match 1 { + //~^ match_single_binding _ => side_effects(), }, match 1 { + //~^ match_single_binding _ => println!("1"), }, ]; diff --git a/tests/ui/match_single_binding.stderr b/tests/ui/match_single_binding.stderr index 19ab85180ad2..7e1ec32dac2f 100644 --- a/tests/ui/match_single_binding.stderr +++ b/tests/ui/match_single_binding.stderr @@ -2,6 +2,7 @@ error: this match could be written as a `let` statement --> tests/ui/match_single_binding.rs:33:5 | LL | / match (a, b, c) { +LL | | LL | | (x, y, z) => { LL | | println!("{} {} {}", x, y, z); LL | | }, @@ -19,9 +20,10 @@ LL + } | error: this match could be written as a `let` statement - --> tests/ui/match_single_binding.rs:39:5 + --> tests/ui/match_single_binding.rs:40:5 | LL | / match (a, b, c) { +LL | | LL | | (x, y, z) => println!("{} {} {}", x, y, z), LL | | } | |_____^ @@ -33,17 +35,19 @@ LL + println!("{} {} {}", x, y, z); | error: this match could be replaced by its body itself - --> tests/ui/match_single_binding.rs:56:5 + --> tests/ui/match_single_binding.rs:58:5 | LL | / match a { +LL | | LL | | _ => println!("whatever"), LL | | } | |_____^ help: consider using the match body instead: `println!("whatever");` error: this match could be replaced by its body itself - --> tests/ui/match_single_binding.rs:60:5 + --> tests/ui/match_single_binding.rs:63:5 | LL | / match a { +LL | | LL | | _ => { LL | | let x = 29; LL | | println!("x has a value of {}", x); @@ -60,12 +64,12 @@ LL + } | error: this match could be replaced by its body itself - --> tests/ui/match_single_binding.rs:67:5 + --> tests/ui/match_single_binding.rs:71:5 | LL | / match a { +LL | | LL | | _ => { LL | | let e = 5 * a; -LL | | if e >= 5 { ... | LL | | }, LL | | } @@ -82,9 +86,10 @@ LL + } | error: this match could be written as a `let` statement - --> tests/ui/match_single_binding.rs:77:5 + --> tests/ui/match_single_binding.rs:82:5 | LL | / match p { +LL | | LL | | Point { x, y } => println!("Coords: ({}, {})", x, y), LL | | } | |_____^ @@ -96,9 +101,10 @@ LL + println!("Coords: ({}, {})", x, y); | error: this match could be written as a `let` statement - --> tests/ui/match_single_binding.rs:81:5 + --> tests/ui/match_single_binding.rs:87:5 | LL | / match p { +LL | | LL | | Point { x: x1, y: y1 } => println!("Coords: ({}, {})", x1, y1), LL | | } | |_____^ @@ -110,9 +116,10 @@ LL + println!("Coords: ({}, {})", x1, y1); | error: this match could be written as a `let` statement - --> tests/ui/match_single_binding.rs:86:5 + --> tests/ui/match_single_binding.rs:93:5 | LL | / match x { +LL | | LL | | ref r => println!("Got a reference to {}", r), LL | | } | |_____^ @@ -124,9 +131,10 @@ LL + println!("Got a reference to {}", r); | error: this match could be written as a `let` statement - --> tests/ui/match_single_binding.rs:91:5 + --> tests/ui/match_single_binding.rs:99:5 | LL | / match x { +LL | | LL | | ref mut mr => println!("Got a mutable reference to {}", mr), LL | | } | |_____^ @@ -138,9 +146,10 @@ LL + println!("Got a mutable reference to {}", mr); | error: this match could be written as a `let` statement - --> tests/ui/match_single_binding.rs:95:5 + --> tests/ui/match_single_binding.rs:104:5 | LL | / let product = match coords() { +LL | | LL | | Point { x, y } => x * y, LL | | }; | |______^ @@ -152,10 +161,11 @@ LL + let product = x * y; | error: this match could be written as a `let` statement - --> tests/ui/match_single_binding.rs:103:18 + --> tests/ui/match_single_binding.rs:113:18 | LL | .map(|i| match i.unwrap() { | __________________^ +LL | | LL | | unwrapped => unwrapped, LL | | }) | |_________^ @@ -169,18 +179,20 @@ LL ~ }) | error: this match could be replaced by its body itself - --> tests/ui/match_single_binding.rs:129:5 + --> tests/ui/match_single_binding.rs:140:5 | LL | / match x { +LL | | LL | | // => LL | | _ => println!("Not an array index start"), LL | | } | |_____^ help: consider using the match body instead: `println!("Not an array index start")` error: this assignment could be simplified - --> tests/ui/match_single_binding.rs:138:5 + --> tests/ui/match_single_binding.rs:150:5 | LL | / val = match val.split_at(idx) { +LL | | LL | | (pre, suf) => { LL | | println!("{}", pre); LL | | suf @@ -198,10 +210,11 @@ LL ~ }; | error: this match could be replaced by its scrutinee and body - --> tests/ui/match_single_binding.rs:151:16 + --> tests/ui/match_single_binding.rs:164:16 | LL | let _ = || match side_effects() { | ________________^ +LL | | LL | | _ => println!("Needs curlies"), LL | | }; | |_____^ @@ -215,12 +228,12 @@ LL ~ }; | error: this match could be written as a `let` statement - --> tests/ui/match_single_binding.rs:157:5 + --> tests/ui/match_single_binding.rs:171:5 | LL | / match r { +LL | | LL | | x => match x { LL | | Some(_) => { -LL | | println!("Some"); ... | LL | | }, LL | | }; @@ -240,76 +253,85 @@ LL ~ }; | error: this match could be replaced by its body itself - --> tests/ui/match_single_binding.rs:170:5 + --> tests/ui/match_single_binding.rs:185:5 | LL | / match 1 { +LL | | LL | | _ => (), LL | | } | |_____^ help: consider using the match body instead: `();` error: this match could be replaced by its body itself - --> tests/ui/match_single_binding.rs:174:13 + --> tests/ui/match_single_binding.rs:190:13 | LL | let a = match 1 { | _____________^ +LL | | LL | | _ => (), LL | | }; | |_____^ help: consider using the match body instead: `()` error: this match could be replaced by its body itself - --> tests/ui/match_single_binding.rs:178:5 + --> tests/ui/match_single_binding.rs:195:5 | LL | / match 1 { +LL | | LL | | _ => side_effects(), LL | | } | |_____^ help: consider using the match body instead: `side_effects();` error: this match could be replaced by its body itself - --> tests/ui/match_single_binding.rs:182:13 + --> tests/ui/match_single_binding.rs:200:13 | LL | let b = match 1 { | _____________^ +LL | | LL | | _ => side_effects(), LL | | }; | |_____^ help: consider using the match body instead: `side_effects()` error: this match could be replaced by its body itself - --> tests/ui/match_single_binding.rs:186:5 + --> tests/ui/match_single_binding.rs:205:5 | LL | / match 1 { +LL | | LL | | _ => println!("1"), LL | | } | |_____^ help: consider using the match body instead: `println!("1");` error: this match could be replaced by its body itself - --> tests/ui/match_single_binding.rs:190:13 + --> tests/ui/match_single_binding.rs:210:13 | LL | let c = match 1 { | _____________^ +LL | | LL | | _ => println!("1"), LL | | }; | |_____^ help: consider using the match body instead: `println!("1")` error: this match could be replaced by its body itself - --> tests/ui/match_single_binding.rs:195:9 + --> tests/ui/match_single_binding.rs:216:9 | LL | / match 1 { +LL | | LL | | _ => (), LL | | }, | |_________^ help: consider using the match body instead: `()` error: this match could be replaced by its body itself - --> tests/ui/match_single_binding.rs:198:9 + --> tests/ui/match_single_binding.rs:220:9 | LL | / match 1 { +LL | | LL | | _ => side_effects(), LL | | }, | |_________^ help: consider using the match body instead: `side_effects()` error: this match could be replaced by its body itself - --> tests/ui/match_single_binding.rs:201:9 + --> tests/ui/match_single_binding.rs:224:9 | LL | / match 1 { +LL | | LL | | _ => println!("1"), LL | | }, | |_________^ help: consider using the match body instead: `println!("1")` diff --git a/tests/ui/match_single_binding2.fixed b/tests/ui/match_single_binding2.fixed index 5673aa78c76a..988121f50d0f 100644 --- a/tests/ui/match_single_binding2.fixed +++ b/tests/ui/match_single_binding2.fixed @@ -45,6 +45,7 @@ fn main() { // issue #7094 let x = 1; match x { + //~^ match_single_binding 0 => 1, _ => 2, }; diff --git a/tests/ui/match_single_binding2.rs b/tests/ui/match_single_binding2.rs index 575e7f5816b8..a4fb2bd6f381 100644 --- a/tests/ui/match_single_binding2.rs +++ b/tests/ui/match_single_binding2.rs @@ -15,6 +15,7 @@ fn main() { fn size_hint(iter: &AppendIter) -> (usize, Option) { match &iter.inner { Some((iter, _item)) => match iter.size_hint() { + //~^ match_single_binding (min, max) => (min.saturating_add(1), max.and_then(|max| max.checked_add(1))), }, None => (0, Some(0)), @@ -28,6 +29,7 @@ fn main() { #[rustfmt::skip] Some((first, _second)) => { match get_tup() { + //~^ match_single_binding (a, b) => println!("a {:?} and b {:?}", a, b), } }, @@ -39,6 +41,7 @@ fn main() { // Lint (scrutinee has side effects) // issue #7094 match side_effects() { + //~^ match_single_binding _ => println!("Side effects"), } @@ -46,6 +49,7 @@ fn main() { // issue #7094 let x = 1; match match x { + //~^ match_single_binding 0 => 1, _ => 2, } { diff --git a/tests/ui/match_single_binding2.stderr b/tests/ui/match_single_binding2.stderr index 38659596af1f..a24cbe3eed76 100644 --- a/tests/ui/match_single_binding2.stderr +++ b/tests/ui/match_single_binding2.stderr @@ -3,6 +3,7 @@ error: this match could be written as a `let` statement | LL | Some((iter, _item)) => match iter.size_hint() { | ____________________________________^ +LL | | LL | | (min, max) => (min.saturating_add(1), max.and_then(|max| max.checked_add(1))), LL | | }, | |_____________^ @@ -18,9 +19,10 @@ LL ~ }, | error: this match could be written as a `let` statement - --> tests/ui/match_single_binding2.rs:30:13 + --> tests/ui/match_single_binding2.rs:31:13 | LL | / match get_tup() { +LL | | LL | | (a, b) => println!("a {:?} and b {:?}", a, b), LL | | } | |_____________^ @@ -32,9 +34,10 @@ LL + println!("a {:?} and b {:?}", a, b) | error: this match could be replaced by its scrutinee and body - --> tests/ui/match_single_binding2.rs:41:5 + --> tests/ui/match_single_binding2.rs:43:5 | LL | / match side_effects() { +LL | | LL | | _ => println!("Side effects"), LL | | } | |_____^ @@ -46,9 +49,10 @@ LL + println!("Side effects"); | error: this match could be replaced by its scrutinee and body - --> tests/ui/match_single_binding2.rs:48:5 + --> tests/ui/match_single_binding2.rs:51:5 | LL | / match match x { +LL | | LL | | 0 => 1, LL | | _ => 2, LL | | } { @@ -59,6 +63,7 @@ LL | | } help: consider using the scrutinee and body instead | LL ~ match x { +LL + LL + 0 => 1, LL + _ => 2, LL + }; diff --git a/tests/ui/match_str_case_mismatch.fixed b/tests/ui/match_str_case_mismatch.fixed index a608ab0c0cb0..5f41f29f8a46 100644 --- a/tests/ui/match_str_case_mismatch.fixed +++ b/tests/ui/match_str_case_mismatch.fixed @@ -110,6 +110,7 @@ fn as_str_match_mismatch() { match var.to_ascii_lowercase().as_str() { "foo" => {}, "bar" => {}, + //~^ match_str_case_mismatch _ => {}, } } @@ -120,6 +121,7 @@ fn non_alphabetic_mismatch() { match var.to_ascii_lowercase().as_str() { "1234567890" => {}, "~!@#$%^&*()-_=+foo" => {}, + //~^ match_str_case_mismatch "\n\r\t\x7F" => {}, _ => {}, } @@ -132,6 +134,7 @@ fn unicode_cased_mismatch() { "水" => {}, "νερό" => {}, "воды" => {}, + //~^ match_str_case_mismatch "물" => {}, _ => {}, } @@ -143,6 +146,7 @@ fn titlecase_mismatch() { match var.to_lowercase().as_str() { "foolj" => {}, "bardz" => {}, + //~^ match_str_case_mismatch _ => {}, } } @@ -153,6 +157,7 @@ fn no_case_equivalent_mismatch() { match var.to_uppercase().as_str() { "FOOɕ" => {}, "BARʁ" => {}, + //~^ match_str_case_mismatch _ => {}, } } @@ -163,6 +168,7 @@ fn addrof_unary_match_mismatch() { match &*var.to_ascii_lowercase() { "foo" => {}, "bar" => {}, + //~^ match_str_case_mismatch _ => {}, } } @@ -178,6 +184,7 @@ fn alternating_chain_mismatch() { { "FOO" => {}, "BAR" => {}, + //~^ match_str_case_mismatch _ => {}, } } diff --git a/tests/ui/match_str_case_mismatch.rs b/tests/ui/match_str_case_mismatch.rs index 1e4269d1db5d..fa5d5a8ebc31 100644 --- a/tests/ui/match_str_case_mismatch.rs +++ b/tests/ui/match_str_case_mismatch.rs @@ -110,6 +110,7 @@ fn as_str_match_mismatch() { match var.to_ascii_lowercase().as_str() { "foo" => {}, "Bar" => {}, + //~^ match_str_case_mismatch _ => {}, } } @@ -120,6 +121,7 @@ fn non_alphabetic_mismatch() { match var.to_ascii_lowercase().as_str() { "1234567890" => {}, "~!@#$%^&*()-_=+Foo" => {}, + //~^ match_str_case_mismatch "\n\r\t\x7F" => {}, _ => {}, } @@ -132,6 +134,7 @@ fn unicode_cased_mismatch() { "水" => {}, "νερό" => {}, "Воды" => {}, + //~^ match_str_case_mismatch "물" => {}, _ => {}, } @@ -143,6 +146,7 @@ fn titlecase_mismatch() { match var.to_lowercase().as_str() { "foolj" => {}, "barDz" => {}, + //~^ match_str_case_mismatch _ => {}, } } @@ -153,6 +157,7 @@ fn no_case_equivalent_mismatch() { match var.to_uppercase().as_str() { "FOOɕ" => {}, "bARʁ" => {}, + //~^ match_str_case_mismatch _ => {}, } } @@ -163,6 +168,7 @@ fn addrof_unary_match_mismatch() { match &*var.to_ascii_lowercase() { "foo" => {}, "Bar" => {}, + //~^ match_str_case_mismatch _ => {}, } } @@ -178,6 +184,7 @@ fn alternating_chain_mismatch() { { "FOO" => {}, "bAR" => {}, + //~^ match_str_case_mismatch _ => {}, } } diff --git a/tests/ui/match_str_case_mismatch.stderr b/tests/ui/match_str_case_mismatch.stderr index 5b14fd13a53b..8068edfff947 100644 --- a/tests/ui/match_str_case_mismatch.stderr +++ b/tests/ui/match_str_case_mismatch.stderr @@ -13,7 +13,7 @@ LL + "bar" => {}, | error: this `match` arm has a differing case than its expression - --> tests/ui/match_str_case_mismatch.rs:122:9 + --> tests/ui/match_str_case_mismatch.rs:123:9 | LL | "~!@#$%^&*()-_=+Foo" => {}, | ^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + "~!@#$%^&*()-_=+foo" => {}, | error: this `match` arm has a differing case than its expression - --> tests/ui/match_str_case_mismatch.rs:134:9 + --> tests/ui/match_str_case_mismatch.rs:136:9 | LL | "Воды" => {}, | ^^^^^^ @@ -37,7 +37,7 @@ LL + "воды" => {}, | error: this `match` arm has a differing case than its expression - --> tests/ui/match_str_case_mismatch.rs:145:9 + --> tests/ui/match_str_case_mismatch.rs:148:9 | LL | "barDz" => {}, | ^^^^^^ @@ -49,7 +49,7 @@ LL + "bardz" => {}, | error: this `match` arm has a differing case than its expression - --> tests/ui/match_str_case_mismatch.rs:155:9 + --> tests/ui/match_str_case_mismatch.rs:159:9 | LL | "bARʁ" => {}, | ^^^^^^ @@ -61,7 +61,7 @@ LL + "BARʁ" => {}, | error: this `match` arm has a differing case than its expression - --> tests/ui/match_str_case_mismatch.rs:165:9 + --> tests/ui/match_str_case_mismatch.rs:170:9 | LL | "Bar" => {}, | ^^^^^ @@ -73,7 +73,7 @@ LL + "bar" => {}, | error: this `match` arm has a differing case than its expression - --> tests/ui/match_str_case_mismatch.rs:180:9 + --> tests/ui/match_str_case_mismatch.rs:186:9 | LL | "bAR" => {}, | ^^^^^ diff --git a/tests/ui/match_wild_err_arm.rs b/tests/ui/match_wild_err_arm.rs index 8e670ce5bda2..d18d4047e2a6 100644 --- a/tests/ui/match_wild_err_arm.rs +++ b/tests/ui/match_wild_err_arm.rs @@ -21,24 +21,22 @@ fn match_wild_err_arm() { Ok(3) => println!("ok"), Ok(_) => println!("ok"), Err(_) => panic!("err"), - //~^ ERROR: `Err(_)` matches all errors - //~| NOTE: match each error separately or use the error output, or use `.expect(ms + //~^ match_wild_err_arm } match x { Ok(3) => println!("ok"), Ok(_) => println!("ok"), Err(_) => panic!(), - //~^ ERROR: `Err(_)` matches all errors - //~| NOTE: match each error separately or use the error output, or use `.expect(ms + //~^ match_wild_err_arm } match x { Ok(3) => println!("ok"), Ok(_) => println!("ok"), Err(_) => { - //~^ ERROR: `Err(_)` matches all errors - //~| NOTE: match each error separately or use the error output, or use `.expect(ms + //~^ match_wild_err_arm + panic!(); }, } @@ -47,8 +45,7 @@ fn match_wild_err_arm() { Ok(3) => println!("ok"), Ok(_) => println!("ok"), Err(_e) => panic!(), - //~^ ERROR: `Err(_e)` matches all errors - //~| NOTE: match each error separately or use the error output, or use `.expect(ms + //~^ match_wild_err_arm } // Allowed when used in `panic!`. diff --git a/tests/ui/match_wild_err_arm.stderr b/tests/ui/match_wild_err_arm.stderr index f98065d9a591..fc65924f0873 100644 --- a/tests/ui/match_wild_err_arm.stderr +++ b/tests/ui/match_wild_err_arm.stderr @@ -9,7 +9,7 @@ LL | Err(_) => panic!("err"), = help: to override `-D warnings` add `#[allow(clippy::match_wild_err_arm)]` error: `Err(_)` matches all errors - --> tests/ui/match_wild_err_arm.rs:31:9 + --> tests/ui/match_wild_err_arm.rs:30:9 | LL | Err(_) => panic!(), | ^^^^^^ @@ -17,7 +17,7 @@ LL | Err(_) => panic!(), = note: match each error separately or use the error output, or use `.expect(msg)` if the error case is unreachable error: `Err(_)` matches all errors - --> tests/ui/match_wild_err_arm.rs:39:9 + --> tests/ui/match_wild_err_arm.rs:37:9 | LL | Err(_) => { | ^^^^^^ @@ -25,7 +25,7 @@ LL | Err(_) => { = note: match each error separately or use the error output, or use `.expect(msg)` if the error case is unreachable error: `Err(_e)` matches all errors - --> tests/ui/match_wild_err_arm.rs:49:9 + --> tests/ui/match_wild_err_arm.rs:47:9 | LL | Err(_e) => panic!(), | ^^^^^^^ diff --git a/tests/ui/match_wildcard_for_single_variants.fixed b/tests/ui/match_wildcard_for_single_variants.fixed index e5ea2fdde82f..c34f49df6549 100644 --- a/tests/ui/match_wildcard_for_single_variants.fixed +++ b/tests/ui/match_wildcard_for_single_variants.fixed @@ -20,6 +20,7 @@ impl Color { Self::Green => (), Self::Blue => (), Self::Rgb(..) => (), + //~^ match_wildcard_for_single_variants }; } } @@ -30,6 +31,7 @@ fn main() { Foo::A => {}, Foo::B => {}, Foo::C => {}, + //~^ match_wildcard_for_single_variants } let color = Color::Red; @@ -40,6 +42,7 @@ fn main() { Color::Green => {}, Color::Rgb(_r, _g, _b) => {}, Color::Blue => {}, + //~^ match_wildcard_for_single_variants } // check exhaustive wild @@ -48,12 +51,14 @@ fn main() { Color::Green => {}, Color::Rgb(..) => {}, Color::Blue => {}, + //~^ match_wildcard_for_single_variants } match color { Color::Red => {}, Color::Green => {}, Color::Rgb(_, _, _) => {}, Color::Blue => {}, + //~^ match_wildcard_for_single_variants } // shouldn't lint as there is one missing variant @@ -71,6 +76,7 @@ fn main() { Color::Green => (), &Color::Rgb(..) => (), Color::Blue => (), + //~^ match_wildcard_for_single_variants } use self::Color as C; @@ -80,6 +86,7 @@ fn main() { C::Green => (), C::Rgb(..) => (), C::Blue => (), + //~^ match_wildcard_for_single_variants } match color { @@ -87,6 +94,7 @@ fn main() { Color::Green => (), Color::Rgb(..) => (), Color::Blue => (), + //~^ match_wildcard_for_single_variants } match Some(0) { @@ -122,6 +130,7 @@ fn main() { Enum::B => (), Enum::C => (), Enum::__Private => (), + //~^ match_wildcard_for_single_variants } match Enum::A { Enum::A => (), @@ -149,6 +158,7 @@ mod issue9993 { _ if false => 0, Foo::A(_) => 1, Foo::B => 2, + //~^ match_wildcard_for_single_variants }; } } diff --git a/tests/ui/match_wildcard_for_single_variants.rs b/tests/ui/match_wildcard_for_single_variants.rs index dbd7fbe160f0..ecdb7d2fa3af 100644 --- a/tests/ui/match_wildcard_for_single_variants.rs +++ b/tests/ui/match_wildcard_for_single_variants.rs @@ -20,6 +20,7 @@ impl Color { Self::Green => (), Self::Blue => (), _ => (), + //~^ match_wildcard_for_single_variants }; } } @@ -30,6 +31,7 @@ fn main() { Foo::A => {}, Foo::B => {}, _ => {}, + //~^ match_wildcard_for_single_variants } let color = Color::Red; @@ -40,6 +42,7 @@ fn main() { Color::Green => {}, Color::Rgb(_r, _g, _b) => {}, _ => {}, + //~^ match_wildcard_for_single_variants } // check exhaustive wild @@ -48,12 +51,14 @@ fn main() { Color::Green => {}, Color::Rgb(..) => {}, _ => {}, + //~^ match_wildcard_for_single_variants } match color { Color::Red => {}, Color::Green => {}, Color::Rgb(_, _, _) => {}, _ => {}, + //~^ match_wildcard_for_single_variants } // shouldn't lint as there is one missing variant @@ -71,6 +76,7 @@ fn main() { Color::Green => (), &Color::Rgb(..) => (), &_ => (), + //~^ match_wildcard_for_single_variants } use self::Color as C; @@ -80,6 +86,7 @@ fn main() { C::Green => (), C::Rgb(..) => (), _ => (), + //~^ match_wildcard_for_single_variants } match color { @@ -87,6 +94,7 @@ fn main() { Color::Green => (), Color::Rgb(..) => (), _ => (), + //~^ match_wildcard_for_single_variants } match Some(0) { @@ -122,6 +130,7 @@ fn main() { Enum::B => (), Enum::C => (), _ => (), + //~^ match_wildcard_for_single_variants } match Enum::A { Enum::A => (), @@ -149,6 +158,7 @@ mod issue9993 { _ if false => 0, Foo::A(_) => 1, _ => 2, + //~^ match_wildcard_for_single_variants }; } } diff --git a/tests/ui/match_wildcard_for_single_variants.stderr b/tests/ui/match_wildcard_for_single_variants.stderr index 5cc50c823b2c..3c0cc53b1bf2 100644 --- a/tests/ui/match_wildcard_for_single_variants.stderr +++ b/tests/ui/match_wildcard_for_single_variants.stderr @@ -8,55 +8,55 @@ LL | _ => (), = help: to override `-D warnings` add `#[allow(clippy::match_wildcard_for_single_variants)]` error: wildcard matches only a single variant and will also match any future added variants - --> tests/ui/match_wildcard_for_single_variants.rs:32:9 + --> tests/ui/match_wildcard_for_single_variants.rs:33:9 | LL | _ => {}, | ^ help: try: `Foo::C` error: wildcard matches only a single variant and will also match any future added variants - --> tests/ui/match_wildcard_for_single_variants.rs:42:9 + --> tests/ui/match_wildcard_for_single_variants.rs:44:9 | LL | _ => {}, | ^ help: try: `Color::Blue` error: wildcard matches only a single variant and will also match any future added variants - --> tests/ui/match_wildcard_for_single_variants.rs:50:9 + --> tests/ui/match_wildcard_for_single_variants.rs:53:9 | LL | _ => {}, | ^ help: try: `Color::Blue` error: wildcard matches only a single variant and will also match any future added variants - --> tests/ui/match_wildcard_for_single_variants.rs:56:9 + --> tests/ui/match_wildcard_for_single_variants.rs:60:9 | LL | _ => {}, | ^ help: try: `Color::Blue` error: wildcard matches only a single variant and will also match any future added variants - --> tests/ui/match_wildcard_for_single_variants.rs:73:9 + --> tests/ui/match_wildcard_for_single_variants.rs:78:9 | LL | &_ => (), | ^^ help: try: `Color::Blue` error: wildcard matches only a single variant and will also match any future added variants - --> tests/ui/match_wildcard_for_single_variants.rs:82:9 + --> tests/ui/match_wildcard_for_single_variants.rs:88:9 | LL | _ => (), | ^ help: try: `C::Blue` error: wildcard matches only a single variant and will also match any future added variants - --> tests/ui/match_wildcard_for_single_variants.rs:89:9 + --> tests/ui/match_wildcard_for_single_variants.rs:96:9 | LL | _ => (), | ^ help: try: `Color::Blue` error: wildcard matches only a single variant and will also match any future added variants - --> tests/ui/match_wildcard_for_single_variants.rs:124:13 + --> tests/ui/match_wildcard_for_single_variants.rs:132:13 | LL | _ => (), | ^ help: try: `Enum::__Private` error: wildcard matches only a single variant and will also match any future added variants - --> tests/ui/match_wildcard_for_single_variants.rs:151:13 + --> tests/ui/match_wildcard_for_single_variants.rs:160:13 | LL | _ => 2, | ^ help: try: `Foo::B` diff --git a/tests/ui/mem_forget.rs b/tests/ui/mem_forget.rs index 1f508b3bca28..b510af8ac6f1 100644 --- a/tests/ui/mem_forget.rs +++ b/tests/ui/mem_forget.rs @@ -12,23 +12,19 @@ fn main() { let six: Arc = Arc::new(6); memstuff::forget(six); - //~^ ERROR: usage of `mem::forget` on `Drop` type - //~| NOTE: argument has type `std::sync::Arc` + //~^ mem_forget let seven: Rc = Rc::new(7); std::mem::forget(seven); - //~^ ERROR: usage of `mem::forget` on `Drop` type - //~| NOTE: argument has type `std::rc::Rc` + //~^ mem_forget let eight: Vec = vec![8]; forgetSomething(eight); - //~^ ERROR: usage of `mem::forget` on `Drop` type - //~| NOTE: argument has type `std::vec::Vec` + //~^ mem_forget let string = String::new(); std::mem::forget(string); - //~^ ERROR: usage of `mem::forget` on type with `Drop` fields - //~| NOTE: argument has type `std::string::String` + //~^ mem_forget std::mem::forget(7); } diff --git a/tests/ui/mem_forget.stderr b/tests/ui/mem_forget.stderr index 3b0e839e0871..049db54a04b0 100644 --- a/tests/ui/mem_forget.stderr +++ b/tests/ui/mem_forget.stderr @@ -9,7 +9,7 @@ LL | memstuff::forget(six); = help: to override `-D warnings` add `#[allow(clippy::mem_forget)]` error: usage of `mem::forget` on `Drop` type - --> tests/ui/mem_forget.rs:19:5 + --> tests/ui/mem_forget.rs:18:5 | LL | std::mem::forget(seven); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | std::mem::forget(seven); = note: argument has type `std::rc::Rc` error: usage of `mem::forget` on `Drop` type - --> tests/ui/mem_forget.rs:24:5 + --> tests/ui/mem_forget.rs:22:5 | LL | forgetSomething(eight); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | forgetSomething(eight); = note: argument has type `std::vec::Vec` error: usage of `mem::forget` on type with `Drop` fields - --> tests/ui/mem_forget.rs:29:5 + --> tests/ui/mem_forget.rs:26:5 | LL | std::mem::forget(string); | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/mem_replace.fixed b/tests/ui/mem_replace.fixed index 4210dbbe82d3..870ef23113a2 100644 --- a/tests/ui/mem_replace.fixed +++ b/tests/ui/mem_replace.fixed @@ -11,53 +11,76 @@ use std::mem; fn replace_option_with_none() { let mut an_option = Some(1); let _ = an_option.take(); + //~^ mem_replace_option_with_none let an_option = &mut Some(1); let _ = an_option.take(); + //~^ mem_replace_option_with_none } fn replace_with_default() { let mut s = String::from("foo"); let _ = std::mem::take(&mut s); + //~^ mem_replace_with_default + let _ = std::mem::take(&mut s); + //~^ mem_replace_with_default let s = &mut String::from("foo"); let _ = std::mem::take(s); + //~^ mem_replace_with_default let _ = std::mem::take(s); + //~^ mem_replace_with_default + let _ = std::mem::take(s); + //~^ mem_replace_with_default let mut v = vec![123]; let _ = std::mem::take(&mut v); + //~^ mem_replace_with_default let _ = std::mem::take(&mut v); + //~^ mem_replace_with_default let _ = std::mem::take(&mut v); + //~^ mem_replace_with_default let _ = std::mem::take(&mut v); + //~^ mem_replace_with_default let mut hash_map: HashMap = HashMap::new(); let _ = std::mem::take(&mut hash_map); + //~^ mem_replace_with_default let mut btree_map: BTreeMap = BTreeMap::new(); let _ = std::mem::take(&mut btree_map); + //~^ mem_replace_with_default let mut vd: VecDeque = VecDeque::new(); let _ = std::mem::take(&mut vd); + //~^ mem_replace_with_default let mut hash_set: HashSet<&str> = HashSet::new(); let _ = std::mem::take(&mut hash_set); + //~^ mem_replace_with_default let mut btree_set: BTreeSet<&str> = BTreeSet::new(); let _ = std::mem::take(&mut btree_set); + //~^ mem_replace_with_default let mut list: LinkedList = LinkedList::new(); let _ = std::mem::take(&mut list); + //~^ mem_replace_with_default let mut binary_heap: BinaryHeap = BinaryHeap::new(); let _ = std::mem::take(&mut binary_heap); + //~^ mem_replace_with_default let mut tuple = (vec![1, 2], BinaryHeap::::new()); let _ = std::mem::take(&mut tuple); + //~^ mem_replace_with_default let mut refstr = "hello"; let _ = std::mem::take(&mut refstr); + //~^ mem_replace_with_default let mut slice: &[i32] = &[1, 2, 3]; let _ = std::mem::take(&mut slice); + //~^ mem_replace_with_default } // lint is disabled for primitives because in this case `take` @@ -94,6 +117,7 @@ fn msrv_1_39() { fn msrv_1_40() { let mut s = String::from("foo"); let _ = std::mem::take(&mut s); + //~^ mem_replace_with_default } fn issue9824() { @@ -124,8 +148,34 @@ fn issue9824() { // replace option with none let _ = f.0.take(); + //~^ mem_replace_option_with_none let _ = (*f).take(); + //~^ mem_replace_option_with_none let _ = b.opt.take(); + //~^ mem_replace_option_with_none // replace with default let _ = std::mem::take(&mut b.val); + //~^ mem_replace_with_default +} + +#[clippy::msrv = "1.31"] +fn mem_replace_option_with_some() { + let mut an_option = Some(0); + let replaced = an_option.replace(1); + //~^ ERROR: replacing an `Option` with `Some(..)` + + let mut an_option = &mut Some(0); + let replaced = an_option.replace(1); + //~^ ERROR: replacing an `Option` with `Some(..)` + + let (mut opt1, mut opt2) = (Some(0), Some(0)); + let b = true; + let replaced = (if b { &mut opt1 } else { &mut opt2 }).replace(1); + //~^ ERROR: replacing an `Option` with `Some(..)` +} + +#[clippy::msrv = "1.30"] +fn mem_replace_option_with_some_bad_msrv() { + let mut an_option = Some(0); + let replaced = mem::replace(&mut an_option, Some(1)); } diff --git a/tests/ui/mem_replace.rs b/tests/ui/mem_replace.rs index bd7ad78b2af2..b4ed5eafea95 100644 --- a/tests/ui/mem_replace.rs +++ b/tests/ui/mem_replace.rs @@ -11,53 +11,76 @@ use std::mem; fn replace_option_with_none() { let mut an_option = Some(1); let _ = mem::replace(&mut an_option, None); + //~^ mem_replace_option_with_none let an_option = &mut Some(1); let _ = mem::replace(an_option, None); + //~^ mem_replace_option_with_none } fn replace_with_default() { let mut s = String::from("foo"); let _ = std::mem::replace(&mut s, String::default()); + //~^ mem_replace_with_default + let _ = std::mem::replace(&mut s, String::new()); + //~^ mem_replace_with_default let s = &mut String::from("foo"); let _ = std::mem::replace(s, String::default()); + //~^ mem_replace_with_default + let _ = std::mem::replace(s, String::new()); + //~^ mem_replace_with_default let _ = std::mem::replace(s, Default::default()); + //~^ mem_replace_with_default let mut v = vec![123]; let _ = std::mem::replace(&mut v, Vec::default()); + //~^ mem_replace_with_default let _ = std::mem::replace(&mut v, Default::default()); + //~^ mem_replace_with_default let _ = std::mem::replace(&mut v, Vec::new()); + //~^ mem_replace_with_default let _ = std::mem::replace(&mut v, vec![]); + //~^ mem_replace_with_default let mut hash_map: HashMap = HashMap::new(); let _ = std::mem::replace(&mut hash_map, HashMap::new()); + //~^ mem_replace_with_default let mut btree_map: BTreeMap = BTreeMap::new(); let _ = std::mem::replace(&mut btree_map, BTreeMap::new()); + //~^ mem_replace_with_default let mut vd: VecDeque = VecDeque::new(); let _ = std::mem::replace(&mut vd, VecDeque::new()); + //~^ mem_replace_with_default let mut hash_set: HashSet<&str> = HashSet::new(); let _ = std::mem::replace(&mut hash_set, HashSet::new()); + //~^ mem_replace_with_default let mut btree_set: BTreeSet<&str> = BTreeSet::new(); let _ = std::mem::replace(&mut btree_set, BTreeSet::new()); + //~^ mem_replace_with_default let mut list: LinkedList = LinkedList::new(); let _ = std::mem::replace(&mut list, LinkedList::new()); + //~^ mem_replace_with_default let mut binary_heap: BinaryHeap = BinaryHeap::new(); let _ = std::mem::replace(&mut binary_heap, BinaryHeap::new()); + //~^ mem_replace_with_default let mut tuple = (vec![1, 2], BinaryHeap::::new()); let _ = std::mem::replace(&mut tuple, (vec![], BinaryHeap::new())); + //~^ mem_replace_with_default let mut refstr = "hello"; let _ = std::mem::replace(&mut refstr, ""); + //~^ mem_replace_with_default let mut slice: &[i32] = &[1, 2, 3]; let _ = std::mem::replace(&mut slice, &[]); + //~^ mem_replace_with_default } // lint is disabled for primitives because in this case `take` @@ -94,6 +117,7 @@ fn msrv_1_39() { fn msrv_1_40() { let mut s = String::from("foo"); let _ = std::mem::replace(&mut s, String::default()); + //~^ mem_replace_with_default } fn issue9824() { @@ -124,8 +148,34 @@ fn issue9824() { // replace option with none let _ = std::mem::replace(&mut f.0, None); + //~^ mem_replace_option_with_none let _ = std::mem::replace(&mut *f, None); + //~^ mem_replace_option_with_none let _ = std::mem::replace(&mut b.opt, None); + //~^ mem_replace_option_with_none // replace with default let _ = std::mem::replace(&mut b.val, String::default()); + //~^ mem_replace_with_default +} + +#[clippy::msrv = "1.31"] +fn mem_replace_option_with_some() { + let mut an_option = Some(0); + let replaced = mem::replace(&mut an_option, Some(1)); + //~^ ERROR: replacing an `Option` with `Some(..)` + + let mut an_option = &mut Some(0); + let replaced = mem::replace(an_option, Some(1)); + //~^ ERROR: replacing an `Option` with `Some(..)` + + let (mut opt1, mut opt2) = (Some(0), Some(0)); + let b = true; + let replaced = mem::replace(if b { &mut opt1 } else { &mut opt2 }, Some(1)); + //~^ ERROR: replacing an `Option` with `Some(..)` +} + +#[clippy::msrv = "1.30"] +fn mem_replace_option_with_some_bad_msrv() { + let mut an_option = Some(0); + let replaced = mem::replace(&mut an_option, Some(1)); } diff --git a/tests/ui/mem_replace.stderr b/tests/ui/mem_replace.stderr index c33f80b01b85..fb4a367266d3 100644 --- a/tests/ui/mem_replace.stderr +++ b/tests/ui/mem_replace.stderr @@ -8,13 +8,13 @@ LL | let _ = mem::replace(&mut an_option, None); = help: to override `-D warnings` add `#[allow(clippy::mem_replace_option_with_none)]` error: replacing an `Option` with `None` - --> tests/ui/mem_replace.rs:15:13 + --> tests/ui/mem_replace.rs:16:13 | LL | let _ = mem::replace(an_option, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> tests/ui/mem_replace.rs:20:13 + --> tests/ui/mem_replace.rs:22:13 | LL | let _ = std::mem::replace(&mut s, String::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut s)` @@ -23,130 +23,163 @@ LL | let _ = std::mem::replace(&mut s, String::default()); = help: to override `-D warnings` add `#[allow(clippy::mem_replace_with_default)]` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> tests/ui/mem_replace.rs:23:13 + --> tests/ui/mem_replace.rs:24:13 + | +LL | let _ = std::mem::replace(&mut s, String::new()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut s)` + +error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` + --> tests/ui/mem_replace.rs:28:13 | LL | let _ = std::mem::replace(s, String::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(s)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> tests/ui/mem_replace.rs:24:13 + --> tests/ui/mem_replace.rs:30:13 + | +LL | let _ = std::mem::replace(s, String::new()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(s)` + +error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` + --> tests/ui/mem_replace.rs:32:13 | LL | let _ = std::mem::replace(s, Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(s)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> tests/ui/mem_replace.rs:27:13 + --> tests/ui/mem_replace.rs:36:13 | LL | let _ = std::mem::replace(&mut v, Vec::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> tests/ui/mem_replace.rs:28:13 + --> tests/ui/mem_replace.rs:38:13 | LL | let _ = std::mem::replace(&mut v, Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> tests/ui/mem_replace.rs:29:13 + --> tests/ui/mem_replace.rs:40:13 | LL | let _ = std::mem::replace(&mut v, Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> tests/ui/mem_replace.rs:30:13 + --> tests/ui/mem_replace.rs:42:13 | LL | let _ = std::mem::replace(&mut v, vec![]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> tests/ui/mem_replace.rs:33:13 + --> tests/ui/mem_replace.rs:46:13 | LL | let _ = std::mem::replace(&mut hash_map, HashMap::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut hash_map)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> tests/ui/mem_replace.rs:36:13 + --> tests/ui/mem_replace.rs:50:13 | LL | let _ = std::mem::replace(&mut btree_map, BTreeMap::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut btree_map)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> tests/ui/mem_replace.rs:39:13 + --> tests/ui/mem_replace.rs:54:13 | LL | let _ = std::mem::replace(&mut vd, VecDeque::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut vd)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> tests/ui/mem_replace.rs:42:13 + --> tests/ui/mem_replace.rs:58:13 | LL | let _ = std::mem::replace(&mut hash_set, HashSet::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut hash_set)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> tests/ui/mem_replace.rs:45:13 + --> tests/ui/mem_replace.rs:62:13 | LL | let _ = std::mem::replace(&mut btree_set, BTreeSet::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut btree_set)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> tests/ui/mem_replace.rs:48:13 + --> tests/ui/mem_replace.rs:66:13 | LL | let _ = std::mem::replace(&mut list, LinkedList::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut list)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> tests/ui/mem_replace.rs:51:13 + --> tests/ui/mem_replace.rs:70:13 | LL | let _ = std::mem::replace(&mut binary_heap, BinaryHeap::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut binary_heap)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> tests/ui/mem_replace.rs:54:13 + --> tests/ui/mem_replace.rs:74:13 | LL | let _ = std::mem::replace(&mut tuple, (vec![], BinaryHeap::new())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut tuple)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> tests/ui/mem_replace.rs:57:13 + --> tests/ui/mem_replace.rs:78:13 | LL | let _ = std::mem::replace(&mut refstr, ""); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut refstr)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> tests/ui/mem_replace.rs:60:13 + --> tests/ui/mem_replace.rs:82:13 | LL | let _ = std::mem::replace(&mut slice, &[]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut slice)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> tests/ui/mem_replace.rs:96:13 + --> tests/ui/mem_replace.rs:119:13 | LL | let _ = std::mem::replace(&mut s, String::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut s)` error: replacing an `Option` with `None` - --> tests/ui/mem_replace.rs:126:13 + --> tests/ui/mem_replace.rs:150:13 | LL | let _ = std::mem::replace(&mut f.0, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `f.0.take()` error: replacing an `Option` with `None` - --> tests/ui/mem_replace.rs:127:13 + --> tests/ui/mem_replace.rs:152:13 | LL | let _ = std::mem::replace(&mut *f, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `(*f).take()` error: replacing an `Option` with `None` - --> tests/ui/mem_replace.rs:128:13 + --> tests/ui/mem_replace.rs:154:13 | LL | let _ = std::mem::replace(&mut b.opt, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `b.opt.take()` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> tests/ui/mem_replace.rs:130:13 + --> tests/ui/mem_replace.rs:157:13 | LL | let _ = std::mem::replace(&mut b.val, String::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut b.val)` -error: aborting due to 24 previous errors +error: replacing an `Option` with `Some(..)` + --> tests/ui/mem_replace.rs:164:20 + | +LL | let replaced = mem::replace(&mut an_option, Some(1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::replace()` instead: `an_option.replace(1)` + | + = note: `-D clippy::mem-replace-option-with-some` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::mem_replace_option_with_some)]` + +error: replacing an `Option` with `Some(..)` + --> tests/ui/mem_replace.rs:168:20 + | +LL | let replaced = mem::replace(an_option, Some(1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::replace()` instead: `an_option.replace(1)` + +error: replacing an `Option` with `Some(..)` + --> tests/ui/mem_replace.rs:173:20 + | +LL | let replaced = mem::replace(if b { &mut opt1 } else { &mut opt2 }, Some(1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::replace()` instead: `(if b { &mut opt1 } else { &mut opt2 }).replace(1)` + +error: aborting due to 29 previous errors diff --git a/tests/ui/mem_replace_macro.rs b/tests/ui/mem_replace_macro.rs index c14ea2942f3e..9458dade3a9c 100644 --- a/tests/ui/mem_replace_macro.rs +++ b/tests/ui/mem_replace_macro.rs @@ -8,5 +8,6 @@ use proc_macros::{external, inline_macros}; fn main() { let s = &mut String::from("foo"); let _ = inline!(std::mem::replace($s, Default::default())); + //~^ mem_replace_with_default let _ = external!(std::mem::replace($s, Default::default())); } diff --git a/tests/ui/mem_replace_no_std.fixed b/tests/ui/mem_replace_no_std.fixed index 60f523c8ef1e..669450e59d8b 100644 --- a/tests/ui/mem_replace_no_std.fixed +++ b/tests/ui/mem_replace_no_std.fixed @@ -21,16 +21,20 @@ fn panic(info: &PanicInfo) -> ! { fn replace_option_with_none() { let mut an_option = Some(1); let _ = an_option.take(); + //~^ mem_replace_option_with_none let an_option = &mut Some(1); let _ = an_option.take(); + //~^ mem_replace_option_with_none } fn replace_with_default() { let mut refstr = "hello"; let _ = core::mem::take(&mut refstr); + //~^ mem_replace_with_default let mut slice: &[i32] = &[1, 2, 3]; let _ = core::mem::take(&mut slice); + //~^ mem_replace_with_default } // lint is disabled for primitives because in this case `take` @@ -74,8 +78,11 @@ fn issue9824() { // replace option with none let _ = f.0.take(); + //~^ mem_replace_option_with_none let _ = (*f).take(); + //~^ mem_replace_option_with_none let _ = b.opt.take(); + //~^ mem_replace_option_with_none // replace with default let _ = mem::replace(&mut b.val, u8::default()); } diff --git a/tests/ui/mem_replace_no_std.rs b/tests/ui/mem_replace_no_std.rs index d1cb9a5817ba..2cdf1df5196a 100644 --- a/tests/ui/mem_replace_no_std.rs +++ b/tests/ui/mem_replace_no_std.rs @@ -21,16 +21,20 @@ fn panic(info: &PanicInfo) -> ! { fn replace_option_with_none() { let mut an_option = Some(1); let _ = mem::replace(&mut an_option, None); + //~^ mem_replace_option_with_none let an_option = &mut Some(1); let _ = mem::replace(an_option, None); + //~^ mem_replace_option_with_none } fn replace_with_default() { let mut refstr = "hello"; let _ = mem::replace(&mut refstr, ""); + //~^ mem_replace_with_default let mut slice: &[i32] = &[1, 2, 3]; let _ = mem::replace(&mut slice, &[]); + //~^ mem_replace_with_default } // lint is disabled for primitives because in this case `take` @@ -74,8 +78,11 @@ fn issue9824() { // replace option with none let _ = mem::replace(&mut f.0, None); + //~^ mem_replace_option_with_none let _ = mem::replace(&mut *f, None); + //~^ mem_replace_option_with_none let _ = mem::replace(&mut b.opt, None); + //~^ mem_replace_option_with_none // replace with default let _ = mem::replace(&mut b.val, u8::default()); } diff --git a/tests/ui/mem_replace_no_std.stderr b/tests/ui/mem_replace_no_std.stderr index 6ba6d2162a74..926a8288fd31 100644 --- a/tests/ui/mem_replace_no_std.stderr +++ b/tests/ui/mem_replace_no_std.stderr @@ -8,13 +8,13 @@ LL | let _ = mem::replace(&mut an_option, None); = help: to override `-D warnings` add `#[allow(clippy::mem_replace_option_with_none)]` error: replacing an `Option` with `None` - --> tests/ui/mem_replace_no_std.rs:25:13 + --> tests/ui/mem_replace_no_std.rs:26:13 | LL | let _ = mem::replace(an_option, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()` error: replacing a value of type `T` with `T::default()` is better expressed using `core::mem::take` - --> tests/ui/mem_replace_no_std.rs:30:13 + --> tests/ui/mem_replace_no_std.rs:32:13 | LL | let _ = mem::replace(&mut refstr, ""); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `core::mem::take(&mut refstr)` @@ -23,25 +23,25 @@ LL | let _ = mem::replace(&mut refstr, ""); = help: to override `-D warnings` add `#[allow(clippy::mem_replace_with_default)]` error: replacing a value of type `T` with `T::default()` is better expressed using `core::mem::take` - --> tests/ui/mem_replace_no_std.rs:33:13 + --> tests/ui/mem_replace_no_std.rs:36:13 | LL | let _ = mem::replace(&mut slice, &[]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `core::mem::take(&mut slice)` error: replacing an `Option` with `None` - --> tests/ui/mem_replace_no_std.rs:76:13 + --> tests/ui/mem_replace_no_std.rs:80:13 | LL | let _ = mem::replace(&mut f.0, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `f.0.take()` error: replacing an `Option` with `None` - --> tests/ui/mem_replace_no_std.rs:77:13 + --> tests/ui/mem_replace_no_std.rs:82:13 | LL | let _ = mem::replace(&mut *f, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `(*f).take()` error: replacing an `Option` with `None` - --> tests/ui/mem_replace_no_std.rs:78:13 + --> tests/ui/mem_replace_no_std.rs:84:13 | LL | let _ = mem::replace(&mut b.opt, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `b.opt.take()` diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index cb1f695c651c..76b0d131dd41 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -11,6 +11,7 @@ clippy::new_without_default, clippy::needless_pass_by_value, clippy::needless_lifetimes, + clippy::elidable_lifetime_names, clippy::print_stdout, clippy::must_use_candidate, clippy::use_self, @@ -101,6 +102,7 @@ struct BadNew; impl BadNew { fn new() -> i32 { + //~^ new_ret_no_self 0 } } @@ -122,6 +124,7 @@ fn filter_next() { // Multi-line case. let _ = v.iter().filter(|&x| { + //~^ filter_next *x < 0 } ).next(); diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 2e2bd3d874f5..353b999d7da0 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -1,7 +1,8 @@ error: methods called `new` usually return `Self` - --> tests/ui/methods.rs:103:5 + --> tests/ui/methods.rs:104:5 | LL | / fn new() -> i32 { +LL | | LL | | 0 LL | | } | |_____^ @@ -10,10 +11,11 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::new_ret_no_self)]` error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead - --> tests/ui/methods.rs:124:13 + --> tests/ui/methods.rs:126:13 | LL | let _ = v.iter().filter(|&x| { | _____________^ +LL | | LL | | *x < 0 LL | | } LL | | ).next(); diff --git a/tests/ui/methods_fixable.fixed b/tests/ui/methods_fixable.fixed index bb06b5a480ff..49730d811558 100644 --- a/tests/ui/methods_fixable.fixed +++ b/tests/ui/methods_fixable.fixed @@ -7,4 +7,5 @@ fn main() { // Single-line case. let _ = v.iter().find(|&x| *x < 0); + //~^ filter_next } diff --git a/tests/ui/methods_fixable.rs b/tests/ui/methods_fixable.rs index 11de924593ed..a499b63b6f5b 100644 --- a/tests/ui/methods_fixable.rs +++ b/tests/ui/methods_fixable.rs @@ -7,4 +7,5 @@ fn main() { // Single-line case. let _ = v.iter().filter(|&x| *x < 0).next(); + //~^ filter_next } diff --git a/tests/ui/methods_unfixable.rs b/tests/ui/methods_unfixable.rs index ee59983a7573..c19a769f7974 100644 --- a/tests/ui/methods_unfixable.rs +++ b/tests/ui/methods_unfixable.rs @@ -7,5 +7,5 @@ fn main() { pub fn issue10029() { let iter = (0..10); let _ = iter.filter(|_| true).next(); - //~^ ERROR: called `filter(..).next()` on an `Iterator`. This is more succinctly expre + //~^ filter_next } diff --git a/tests/ui/min_ident_chars.rs b/tests/ui/min_ident_chars.rs index 1d89f26b6ee4..f473ac848a8e 100644 --- a/tests/ui/min_ident_chars.rs +++ b/tests/ui/min_ident_chars.rs @@ -7,24 +7,35 @@ extern crate proc_macros; use proc_macros::{external, with_span}; struct A { + //~^ min_ident_chars a: u32, + //~^ min_ident_chars i: u32, A: u32, + //~^ min_ident_chars I: u32, + //~^ min_ident_chars } struct B(u32); +//~^ min_ident_chars struct O { + //~^ min_ident_chars o: u32, + //~^ min_ident_chars } struct i; enum C { + //~^ min_ident_chars D, + //~^ min_ident_chars E, + //~^ min_ident_chars F, + //~^ min_ident_chars j, } @@ -39,8 +50,11 @@ struct AA(T, E); trait Trait { const A: u32 = 0; + //~^ min_ident_chars type A; + //~^ min_ident_chars fn a() {} + //~^ min_ident_chars } fn main() { @@ -55,22 +69,37 @@ fn main() { let z = 1; // Implicitly disallowed idents let h = 1; + //~^ min_ident_chars let e = 2; + //~^ min_ident_chars let l = 3; + //~^ min_ident_chars let l = 4; + //~^ min_ident_chars let o = 6; + //~^ min_ident_chars // 2 len does not lint let hi = 0; // Lint let (h, o, w) = (1, 2, 3); + //~^ min_ident_chars + //~| min_ident_chars for (a, (r, e)) in (0..1000).enumerate().enumerate() {} + //~^ min_ident_chars + //~| min_ident_chars + //~| min_ident_chars let you = Vec4 { x: 1, y: 2, z: 3, w: 4 }; while let (d, o, _i, n, g) = (true, true, false, false, true) {} + //~^ min_ident_chars + //~| min_ident_chars + //~| min_ident_chars let today = true; // Ideally this wouldn't lint, but this would (likely) require global analysis, outta scope // of this lint regardless let o = 1; + //~^ min_ident_chars let o = O { o }; + //~^ min_ident_chars for j in 0..1000 {} for _ in 0..10 {} @@ -85,7 +114,10 @@ fn main() { } fn b() {} +//~^ min_ident_chars fn wrong_pythagoras(a: f32, b: f32) -> f32 { + //~^ min_ident_chars + //~| min_ident_chars a * a + a * b } diff --git a/tests/ui/min_ident_chars.stderr b/tests/ui/min_ident_chars.stderr index 3dd5c9561fd0..bd6c45cf648e 100644 --- a/tests/ui/min_ident_chars.stderr +++ b/tests/ui/min_ident_chars.stderr @@ -8,187 +8,187 @@ LL | struct A { = help: to override `-D warnings` add `#[allow(clippy::min_ident_chars)]` error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:10:5 + --> tests/ui/min_ident_chars.rs:11:5 | LL | a: u32, | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:12:5 + --> tests/ui/min_ident_chars.rs:14:5 | LL | A: u32, | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:13:5 + --> tests/ui/min_ident_chars.rs:16:5 | LL | I: u32, | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:16:8 + --> tests/ui/min_ident_chars.rs:20:8 | LL | struct B(u32); | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:18:8 + --> tests/ui/min_ident_chars.rs:23:8 | LL | struct O { | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:19:5 + --> tests/ui/min_ident_chars.rs:25:5 | LL | o: u32, | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:24:6 + --> tests/ui/min_ident_chars.rs:31:6 | LL | enum C { | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:25:5 + --> tests/ui/min_ident_chars.rs:33:5 | LL | D, | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:26:5 + --> tests/ui/min_ident_chars.rs:35:5 | LL | E, | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:27:5 + --> tests/ui/min_ident_chars.rs:37:5 | LL | F, | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:41:11 + --> tests/ui/min_ident_chars.rs:52:11 | LL | const A: u32 = 0; | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:42:10 + --> tests/ui/min_ident_chars.rs:54:10 | LL | type A; | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:43:8 + --> tests/ui/min_ident_chars.rs:56:8 | LL | fn a() {} | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:57:9 + --> tests/ui/min_ident_chars.rs:71:9 | LL | let h = 1; | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:58:9 + --> tests/ui/min_ident_chars.rs:73:9 | LL | let e = 2; | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:59:9 + --> tests/ui/min_ident_chars.rs:75:9 | LL | let l = 3; | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:60:9 + --> tests/ui/min_ident_chars.rs:77:9 | LL | let l = 4; | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:61:9 + --> tests/ui/min_ident_chars.rs:79:9 | LL | let o = 6; | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:65:10 + --> tests/ui/min_ident_chars.rs:84:10 | LL | let (h, o, w) = (1, 2, 3); | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:65:13 + --> tests/ui/min_ident_chars.rs:84:13 | LL | let (h, o, w) = (1, 2, 3); | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:66:10 + --> tests/ui/min_ident_chars.rs:87:10 | LL | for (a, (r, e)) in (0..1000).enumerate().enumerate() {} | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:66:14 + --> tests/ui/min_ident_chars.rs:87:14 | LL | for (a, (r, e)) in (0..1000).enumerate().enumerate() {} | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:66:17 + --> tests/ui/min_ident_chars.rs:87:17 | LL | for (a, (r, e)) in (0..1000).enumerate().enumerate() {} | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:68:16 + --> tests/ui/min_ident_chars.rs:92:16 | LL | while let (d, o, _i, n, g) = (true, true, false, false, true) {} | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:68:19 + --> tests/ui/min_ident_chars.rs:92:19 | LL | while let (d, o, _i, n, g) = (true, true, false, false, true) {} | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:68:29 + --> tests/ui/min_ident_chars.rs:92:29 | LL | while let (d, o, _i, n, g) = (true, true, false, false, true) {} | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:72:9 + --> tests/ui/min_ident_chars.rs:99:9 | LL | let o = 1; | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:73:9 + --> tests/ui/min_ident_chars.rs:101:9 | LL | let o = O { o }; | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:87:4 + --> tests/ui/min_ident_chars.rs:116:4 | LL | fn b() {} | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:88:21 + --> tests/ui/min_ident_chars.rs:118:21 | LL | fn wrong_pythagoras(a: f32, b: f32) -> f32 { | ^ error: this ident consists of a single char - --> tests/ui/min_ident_chars.rs:88:29 + --> tests/ui/min_ident_chars.rs:118:29 | LL | fn wrong_pythagoras(a: f32, b: f32) -> f32 { | ^ diff --git a/tests/ui/min_max.rs b/tests/ui/min_max.rs index cf64f85f9bb5..f3eeb85f20ed 100644 --- a/tests/ui/min_max.rs +++ b/tests/ui/min_max.rs @@ -20,17 +20,19 @@ impl NotOrd { fn main() { let x = 2usize; min(1, max(3, x)); - //~^ ERROR: this `min`/`max` combination leads to constant result - //~| NOTE: `-D clippy::min-max` implied by `-D warnings` + //~^ min_max + min(max(3, x), 1); - //~^ ERROR: this `min`/`max` combination leads to constant result + //~^ min_max + max(min(x, 1), 3); - //~^ ERROR: this `min`/`max` combination leads to constant result + //~^ min_max + max(3, min(x, 1)); - //~^ ERROR: this `min`/`max` combination leads to constant result + //~^ min_max my_max(3, my_min(x, 1)); - //~^ ERROR: this `min`/`max` combination leads to constant result + //~^ min_max min(3, max(1, x)); // ok, could be 1, 2 or 3 depending on x @@ -41,32 +43,37 @@ fn main() { let s = "Hello"; min("Apple", max("Zoo", s)); - //~^ ERROR: this `min`/`max` combination leads to constant result + //~^ min_max + max(min(s, "Apple"), "Zoo"); - //~^ ERROR: this `min`/`max` combination leads to constant result + //~^ min_max max("Apple", min(s, "Zoo")); // ok let f = 3f32; x.min(1).max(3); - //~^ ERROR: this `min`/`max` combination leads to constant result + //~^ min_max + x.max(3).min(1); - //~^ ERROR: this `min`/`max` combination leads to constant result + //~^ min_max + f.max(3f32).min(1f32); - //~^ ERROR: this `min`/`max` combination leads to constant result + //~^ min_max x.max(1).min(3); // ok x.min(3).max(1); // ok f.min(3f32).max(1f32); // ok max(x.min(1), 3); - //~^ ERROR: this `min`/`max` combination leads to constant result + //~^ min_max + min(x.max(1), 3); // ok s.max("Zoo").min("Apple"); - //~^ ERROR: this `min`/`max` combination leads to constant result + //~^ min_max + s.min("Apple").max("Zoo"); - //~^ ERROR: this `min`/`max` combination leads to constant result + //~^ min_max s.min("Zoo").max("Apple"); // ok diff --git a/tests/ui/min_max.stderr b/tests/ui/min_max.stderr index bb1a82e320d9..84b4d3754552 100644 --- a/tests/ui/min_max.stderr +++ b/tests/ui/min_max.stderr @@ -14,67 +14,67 @@ LL | min(max(3, x), 1); | ^^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> tests/ui/min_max.rs:27:5 + --> tests/ui/min_max.rs:28:5 | LL | max(min(x, 1), 3); | ^^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> tests/ui/min_max.rs:29:5 + --> tests/ui/min_max.rs:31:5 | LL | max(3, min(x, 1)); | ^^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> tests/ui/min_max.rs:32:5 + --> tests/ui/min_max.rs:34:5 | LL | my_max(3, my_min(x, 1)); | ^^^^^^^^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> tests/ui/min_max.rs:43:5 + --> tests/ui/min_max.rs:45:5 | LL | min("Apple", max("Zoo", s)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> tests/ui/min_max.rs:45:5 + --> tests/ui/min_max.rs:48:5 | LL | max(min(s, "Apple"), "Zoo"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> tests/ui/min_max.rs:51:5 + --> tests/ui/min_max.rs:54:5 | LL | x.min(1).max(3); | ^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> tests/ui/min_max.rs:53:5 + --> tests/ui/min_max.rs:57:5 | LL | x.max(3).min(1); | ^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> tests/ui/min_max.rs:55:5 + --> tests/ui/min_max.rs:60:5 | LL | f.max(3f32).min(1f32); | ^^^^^^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> tests/ui/min_max.rs:62:5 + --> tests/ui/min_max.rs:67:5 | LL | max(x.min(1), 3); | ^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> tests/ui/min_max.rs:66:5 + --> tests/ui/min_max.rs:72:5 | LL | s.max("Zoo").min("Apple"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: this `min`/`max` combination leads to constant result - --> tests/ui/min_max.rs:68:5 + --> tests/ui/min_max.rs:75:5 | LL | s.min("Apple").max("Zoo"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/min_rust_version_attr.rs b/tests/ui/min_rust_version_attr.rs index 5fe3306d6fc8..4627bef28a29 100644 --- a/tests/ui/min_rust_version_attr.rs +++ b/tests/ui/min_rust_version_attr.rs @@ -11,13 +11,13 @@ fn just_under_msrv() { #[clippy::msrv = "1.43.0"] fn meets_msrv() { let log2_10 = 3.321928094887362; - //~^ ERROR: approximate value of `f{32, 64}::consts::LOG2_10` found + //~^ approx_constant } #[clippy::msrv = "1.44.0"] fn just_above_msrv() { let log2_10 = 3.321928094887362; - //~^ ERROR: approximate value of `f{32, 64}::consts::LOG2_10` found + //~^ approx_constant } #[clippy::msrv = "1.42"] @@ -28,7 +28,7 @@ fn no_patch_under() { #[clippy::msrv = "1.43"] fn no_patch_meets() { let log2_10 = 3.321928094887362; - //~^ ERROR: approximate value of `f{32, 64}::consts::LOG2_10` found + //~^ approx_constant } fn inner_attr_under() { @@ -39,7 +39,7 @@ fn inner_attr_under() { fn inner_attr_meets() { #![clippy::msrv = "1.43"] let log2_10 = 3.321928094887362; - //~^ ERROR: approximate value of `f{32, 64}::consts::LOG2_10` found + //~^ approx_constant } // https://github.com/rust-lang/rust-clippy/issues/6920 @@ -50,7 +50,7 @@ fn scoping() { // Should warn let log2_10 = 3.321928094887362; - //~^ ERROR: approximate value of `f{32, 64}::consts::LOG2_10` found + //~^ approx_constant mod a { #![clippy::msrv = "1.42.0"] @@ -58,7 +58,7 @@ fn scoping() { fn should_warn() { #![clippy::msrv = "1.43.0"] let log2_10 = 3.321928094887362; - //~^ ERROR: approximate value of `f{32, 64}::consts::LOG2_10` found + //~^ approx_constant } fn should_not_warn() { diff --git a/tests/ui/mismatching_type_param_order.rs b/tests/ui/mismatching_type_param_order.rs index a4560f9e9a99..11ff865b583b 100644 --- a/tests/ui/mismatching_type_param_order.rs +++ b/tests/ui/mismatching_type_param_order.rs @@ -9,12 +9,12 @@ fn main() { // lint on both params impl Foo {} - //~^ ERROR: `Foo` has a similarly named generic type parameter `B` in its declaration, - //~| ERROR: `Foo` has a similarly named generic type parameter `A` in its declaration, + //~^ mismatching_type_param_order + //~| mismatching_type_param_order // lint on the 2nd param impl Foo {} - //~^ ERROR: `Foo` has a similarly named generic type parameter `A` in its declaration, + //~^ mismatching_type_param_order // should not lint impl Foo {} @@ -26,8 +26,8 @@ fn main() { // should not lint on lifetimes impl<'m, 'l, B, A> FooLifetime<'m, 'l, B, A> {} - //~^ ERROR: `FooLifetime` has a similarly named generic type parameter `B` in its decl - //~| ERROR: `FooLifetime` has a similarly named generic type parameter `A` in its decl + //~^ mismatching_type_param_order + //~| mismatching_type_param_order struct Bar { x: i32, @@ -44,9 +44,9 @@ fn main() { } impl FooEnum {} - //~^ ERROR: `FooEnum` has a similarly named generic type parameter `C` in its declarat - //~| ERROR: `FooEnum` has a similarly named generic type parameter `A` in its declarat - //~| ERROR: `FooEnum` has a similarly named generic type parameter `B` in its declarat + //~^ mismatching_type_param_order + //~| mismatching_type_param_order + //~| mismatching_type_param_order // also works for unions union FooUnion @@ -58,8 +58,8 @@ fn main() { } impl FooUnion where A: Copy {} - //~^ ERROR: `FooUnion` has a similarly named generic type parameter `B` in its declara - //~| ERROR: `FooUnion` has a similarly named generic type parameter `A` in its declara + //~^ mismatching_type_param_order + //~| mismatching_type_param_order impl FooUnion where diff --git a/tests/ui/misnamed_getters.fixed b/tests/ui/misnamed_getters.fixed index 70af604b2144..cada5307b1c8 100644 --- a/tests/ui/misnamed_getters.fixed +++ b/tests/ui/misnamed_getters.fixed @@ -10,32 +10,37 @@ struct A { impl A { fn a(&self) -> &u8 { - //~^ ERROR: getter function appears to return the wrong field - //~| NOTE: `-D clippy::misnamed-getters` implied by `-D warnings` + //~^ misnamed_getters + &self.a } fn a_mut(&mut self) -> &mut u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &mut self.a } fn b(self) -> u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + self.b } fn b_mut(&mut self) -> &mut u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &mut self.b } fn c(&self) -> &u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &self.c } fn c_mut(&mut self) -> &mut u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &mut self.c } } @@ -47,21 +52,25 @@ union B { impl B { unsafe fn a(&self) -> &u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &self.a } unsafe fn a_mut(&mut self) -> &mut u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &mut self.a } unsafe fn b(self) -> u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + self.b } unsafe fn b_mut(&mut self) -> &mut u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &mut self.b } @@ -74,21 +83,25 @@ impl B { } unsafe fn a_unchecked(&self) -> &u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &self.a } unsafe fn a_unchecked_mut(&mut self) -> &mut u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &mut self.a } unsafe fn b_unchecked(self) -> u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + self.b } unsafe fn b_unchecked_mut(&mut self) -> &mut u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &mut self.b } @@ -121,20 +134,24 @@ impl core::ops::DerefMut for D { impl D { fn a(&self) -> &u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &self.a } fn a_mut(&mut self) -> &mut u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &mut self.a } fn d(&self) -> &u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &self.d } fn d_mut(&mut self) -> &mut u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &mut self.d } } diff --git a/tests/ui/misnamed_getters.rs b/tests/ui/misnamed_getters.rs index 23c3e7bc5cf7..f529c56b4717 100644 --- a/tests/ui/misnamed_getters.rs +++ b/tests/ui/misnamed_getters.rs @@ -10,32 +10,37 @@ struct A { impl A { fn a(&self) -> &u8 { - //~^ ERROR: getter function appears to return the wrong field - //~| NOTE: `-D clippy::misnamed-getters` implied by `-D warnings` + //~^ misnamed_getters + &self.b } fn a_mut(&mut self) -> &mut u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &mut self.b } fn b(self) -> u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + self.a } fn b_mut(&mut self) -> &mut u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &mut self.a } fn c(&self) -> &u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &self.b } fn c_mut(&mut self) -> &mut u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &mut self.a } } @@ -47,21 +52,25 @@ union B { impl B { unsafe fn a(&self) -> &u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &self.b } unsafe fn a_mut(&mut self) -> &mut u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &mut self.b } unsafe fn b(self) -> u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + self.a } unsafe fn b_mut(&mut self) -> &mut u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &mut self.a } @@ -74,21 +83,25 @@ impl B { } unsafe fn a_unchecked(&self) -> &u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &self.b } unsafe fn a_unchecked_mut(&mut self) -> &mut u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &mut self.b } unsafe fn b_unchecked(self) -> u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + self.a } unsafe fn b_unchecked_mut(&mut self) -> &mut u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &mut self.a } @@ -121,20 +134,24 @@ impl core::ops::DerefMut for D { impl D { fn a(&self) -> &u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &self.b } fn a_mut(&mut self) -> &mut u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &mut self.b } fn d(&self) -> &u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &self.b } fn d_mut(&mut self) -> &mut u8 { - //~^ ERROR: getter function appears to return the wrong field + //~^ misnamed_getters + &mut self.b } } diff --git a/tests/ui/misnamed_getters.stderr b/tests/ui/misnamed_getters.stderr index 056fa2be9215..5dd1d75bcf6f 100644 --- a/tests/ui/misnamed_getters.stderr +++ b/tests/ui/misnamed_getters.stderr @@ -17,135 +17,105 @@ error: getter function appears to return the wrong field | LL | / fn a_mut(&mut self) -> &mut u8 { LL | | +LL | | LL | | &mut self.b | | ----------- help: consider using: `&mut self.a` LL | | } | |_____^ error: getter function appears to return the wrong field - --> tests/ui/misnamed_getters.rs:22:5 + --> tests/ui/misnamed_getters.rs:23:5 | LL | / fn b(self) -> u8 { LL | | +LL | | LL | | self.a | | ------ help: consider using: `self.b` LL | | } | |_____^ error: getter function appears to return the wrong field - --> tests/ui/misnamed_getters.rs:27:5 + --> tests/ui/misnamed_getters.rs:29:5 | LL | / fn b_mut(&mut self) -> &mut u8 { LL | | +LL | | LL | | &mut self.a | | ----------- help: consider using: `&mut self.b` LL | | } | |_____^ error: getter function appears to return the wrong field - --> tests/ui/misnamed_getters.rs:32:5 + --> tests/ui/misnamed_getters.rs:35:5 | LL | / fn c(&self) -> &u8 { LL | | +LL | | LL | | &self.b | | ------- help: consider using: `&self.c` LL | | } | |_____^ error: getter function appears to return the wrong field - --> tests/ui/misnamed_getters.rs:37:5 + --> tests/ui/misnamed_getters.rs:41:5 | LL | / fn c_mut(&mut self) -> &mut u8 { LL | | +LL | | LL | | &mut self.a | | ----------- help: consider using: `&mut self.c` LL | | } | |_____^ error: getter function appears to return the wrong field - --> tests/ui/misnamed_getters.rs:49:5 + --> tests/ui/misnamed_getters.rs:54:5 | LL | / unsafe fn a(&self) -> &u8 { LL | | +LL | | LL | | &self.b | | ------- help: consider using: `&self.a` LL | | } | |_____^ error: getter function appears to return the wrong field - --> tests/ui/misnamed_getters.rs:53:5 + --> tests/ui/misnamed_getters.rs:59:5 | LL | / unsafe fn a_mut(&mut self) -> &mut u8 { LL | | +LL | | LL | | &mut self.b | | ----------- help: consider using: `&mut self.a` LL | | } | |_____^ error: getter function appears to return the wrong field - --> tests/ui/misnamed_getters.rs:58:5 + --> tests/ui/misnamed_getters.rs:65:5 | LL | / unsafe fn b(self) -> u8 { LL | | +LL | | LL | | self.a | | ------ help: consider using: `self.b` LL | | } | |_____^ error: getter function appears to return the wrong field - --> tests/ui/misnamed_getters.rs:63:5 + --> tests/ui/misnamed_getters.rs:71:5 | LL | / unsafe fn b_mut(&mut self) -> &mut u8 { LL | | +LL | | LL | | &mut self.a | | ----------- help: consider using: `&mut self.b` LL | | } | |_____^ -error: getter function appears to return the wrong field - --> tests/ui/misnamed_getters.rs:76:5 - | -LL | / unsafe fn a_unchecked(&self) -> &u8 { -LL | | -LL | | &self.b - | | ------- help: consider using: `&self.a` -LL | | } - | |_____^ - -error: getter function appears to return the wrong field - --> tests/ui/misnamed_getters.rs:80:5 - | -LL | / unsafe fn a_unchecked_mut(&mut self) -> &mut u8 { -LL | | -LL | | &mut self.b - | | ----------- help: consider using: `&mut self.a` -LL | | } - | |_____^ - error: getter function appears to return the wrong field --> tests/ui/misnamed_getters.rs:85:5 | -LL | / unsafe fn b_unchecked(self) -> u8 { +LL | / unsafe fn a_unchecked(&self) -> &u8 { LL | | -LL | | self.a - | | ------ help: consider using: `self.b` -LL | | } - | |_____^ - -error: getter function appears to return the wrong field - --> tests/ui/misnamed_getters.rs:90:5 - | -LL | / unsafe fn b_unchecked_mut(&mut self) -> &mut u8 { -LL | | -LL | | &mut self.a - | | ----------- help: consider using: `&mut self.b` -LL | | } - | |_____^ - -error: getter function appears to return the wrong field - --> tests/ui/misnamed_getters.rs:123:5 - | -LL | / fn a(&self) -> &u8 { LL | | LL | | &self.b | | ------- help: consider using: `&self.a` @@ -153,9 +123,10 @@ LL | | } | |_____^ error: getter function appears to return the wrong field - --> tests/ui/misnamed_getters.rs:127:5 + --> tests/ui/misnamed_getters.rs:90:5 | -LL | / fn a_mut(&mut self) -> &mut u8 { +LL | / unsafe fn a_unchecked_mut(&mut self) -> &mut u8 { +LL | | LL | | LL | | &mut self.b | | ----------- help: consider using: `&mut self.a` @@ -163,20 +134,66 @@ LL | | } | |_____^ error: getter function appears to return the wrong field - --> tests/ui/misnamed_getters.rs:132:5 + --> tests/ui/misnamed_getters.rs:96:5 + | +LL | / unsafe fn b_unchecked(self) -> u8 { +LL | | +LL | | +LL | | self.a + | | ------ help: consider using: `self.b` +LL | | } + | |_____^ + +error: getter function appears to return the wrong field + --> tests/ui/misnamed_getters.rs:102:5 + | +LL | / unsafe fn b_unchecked_mut(&mut self) -> &mut u8 { +LL | | +LL | | +LL | | &mut self.a + | | ----------- help: consider using: `&mut self.b` +LL | | } + | |_____^ + +error: getter function appears to return the wrong field + --> tests/ui/misnamed_getters.rs:136:5 + | +LL | / fn a(&self) -> &u8 { +LL | | +LL | | +LL | | &self.b + | | ------- help: consider using: `&self.a` +LL | | } + | |_____^ + +error: getter function appears to return the wrong field + --> tests/ui/misnamed_getters.rs:141:5 + | +LL | / fn a_mut(&mut self) -> &mut u8 { +LL | | +LL | | +LL | | &mut self.b + | | ----------- help: consider using: `&mut self.a` +LL | | } + | |_____^ + +error: getter function appears to return the wrong field + --> tests/ui/misnamed_getters.rs:147:5 | LL | / fn d(&self) -> &u8 { LL | | +LL | | LL | | &self.b | | ------- help: consider using: `&self.d` LL | | } | |_____^ error: getter function appears to return the wrong field - --> tests/ui/misnamed_getters.rs:136:5 + --> tests/ui/misnamed_getters.rs:152:5 | LL | / fn d_mut(&mut self) -> &mut u8 { LL | | +LL | | LL | | &mut self.b | | ----------- help: consider using: `&mut self.d` LL | | } diff --git a/tests/ui/missing_asserts_for_indexing.fixed b/tests/ui/missing_asserts_for_indexing.fixed index ac44a6f3fdb2..3bbafe0bba3f 100644 --- a/tests/ui/missing_asserts_for_indexing.fixed +++ b/tests/ui/missing_asserts_for_indexing.fixed @@ -28,25 +28,25 @@ fn sum_with_assert_ge_other_way(v: &[u8]) -> u8 { fn sum_with_assert_lt(v: &[u8]) -> u8 { assert!(v.len() > 4); v[0] + v[1] + v[2] + v[3] + v[4] - //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the + //~^ missing_asserts_for_indexing } fn sum_with_assert_le(v: &[u8]) -> u8 { assert!(v.len() > 4); v[0] + v[1] + v[2] + v[3] + v[4] - //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the + //~^ missing_asserts_for_indexing } fn sum_with_incorrect_assert_len(v: &[u8]) -> u8 { assert!(v.len() > 4); v[0] + v[1] + v[2] + v[3] + v[4] - //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the + //~^ missing_asserts_for_indexing } fn sum_with_incorrect_assert_len2(v: &[u8]) -> u8 { assert!(v.len() > 4); v[0] + v[1] + v[2] + v[3] + v[4] - //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the + //~^ missing_asserts_for_indexing } // ok, don't lint for single array access @@ -64,7 +64,8 @@ fn subslice_ok(v: &[u8]) { fn subslice_bad(v: &[u8]) { assert!(v.len() > 3); let _ = v[0]; - //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the + //~^ missing_asserts_for_indexing + let _ = v[1..4]; } @@ -78,7 +79,8 @@ fn subslice_inclusive_ok(v: &[u8]) { fn subslice_inclusive_bad(v: &[u8]) { assert!(v.len() > 4); let _ = v[0]; - //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the + //~^ missing_asserts_for_indexing + let _ = v[1..=4]; } @@ -93,15 +95,17 @@ fn index_different_slices_wrong_len(v1: &[u8], v2: &[u8]) { assert!(v1.len() > 12); assert!(v2.len() > 15); let _ = v1[0] + v1[12]; - //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the + //~^ missing_asserts_for_indexing + let _ = v2[5] + v2[15]; - //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the + //~^ missing_asserts_for_indexing } fn index_different_slices_one_wrong_len(v1: &[u8], v2: &[u8]) { assert!(v1.len() > 12); assert!(v2.len() > 15); let _ = v1[0] + v1[12]; - //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the + //~^ missing_asserts_for_indexing + let _ = v2[5] + v2[15]; } @@ -125,11 +129,13 @@ fn issue11835(v1: &[u8], v2: &[u8], v3: &[u8], v4: &[u8]) { assert!(4 == v4.len()); let _ = v1[0] + v1[1] + v1[2]; - //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the + //~^ missing_asserts_for_indexing + let _ = v2[0] + v2[1] + v2[2]; let _ = v3[0] + v3[1] + v3[2]; - //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the + //~^ missing_asserts_for_indexing + let _ = v4[0] + v4[1] + v4[2]; } diff --git a/tests/ui/missing_asserts_for_indexing.rs b/tests/ui/missing_asserts_for_indexing.rs index f05d5fea57dc..f8ea0173c13f 100644 --- a/tests/ui/missing_asserts_for_indexing.rs +++ b/tests/ui/missing_asserts_for_indexing.rs @@ -28,25 +28,25 @@ fn sum_with_assert_ge_other_way(v: &[u8]) -> u8 { fn sum_with_assert_lt(v: &[u8]) -> u8 { assert!(v.len() < 5); v[0] + v[1] + v[2] + v[3] + v[4] - //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the + //~^ missing_asserts_for_indexing } fn sum_with_assert_le(v: &[u8]) -> u8 { assert!(v.len() <= 5); v[0] + v[1] + v[2] + v[3] + v[4] - //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the + //~^ missing_asserts_for_indexing } fn sum_with_incorrect_assert_len(v: &[u8]) -> u8 { assert!(v.len() > 3); v[0] + v[1] + v[2] + v[3] + v[4] - //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the + //~^ missing_asserts_for_indexing } fn sum_with_incorrect_assert_len2(v: &[u8]) -> u8 { assert!(v.len() >= 4); v[0] + v[1] + v[2] + v[3] + v[4] - //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the + //~^ missing_asserts_for_indexing } // ok, don't lint for single array access @@ -64,7 +64,8 @@ fn subslice_ok(v: &[u8]) { fn subslice_bad(v: &[u8]) { assert!(v.len() >= 3); let _ = v[0]; - //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the + //~^ missing_asserts_for_indexing + let _ = v[1..4]; } @@ -78,7 +79,8 @@ fn subslice_inclusive_ok(v: &[u8]) { fn subslice_inclusive_bad(v: &[u8]) { assert!(v.len() >= 4); let _ = v[0]; - //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the + //~^ missing_asserts_for_indexing + let _ = v[1..=4]; } @@ -93,15 +95,17 @@ fn index_different_slices_wrong_len(v1: &[u8], v2: &[u8]) { assert!(v1.len() >= 12); assert!(v2.len() >= 15); let _ = v1[0] + v1[12]; - //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the + //~^ missing_asserts_for_indexing + let _ = v2[5] + v2[15]; - //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the + //~^ missing_asserts_for_indexing } fn index_different_slices_one_wrong_len(v1: &[u8], v2: &[u8]) { assert!(v1.len() >= 12); assert!(v2.len() > 15); let _ = v1[0] + v1[12]; - //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the + //~^ missing_asserts_for_indexing + let _ = v2[5] + v2[15]; } @@ -125,11 +129,13 @@ fn issue11835(v1: &[u8], v2: &[u8], v3: &[u8], v4: &[u8]) { assert!(4 == v4.len()); let _ = v1[0] + v1[1] + v1[2]; - //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the + //~^ missing_asserts_for_indexing + let _ = v2[0] + v2[1] + v2[2]; let _ = v3[0] + v3[1] + v3[2]; - //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the + //~^ missing_asserts_for_indexing + let _ = v4[0] + v4[1] + v4[2]; } diff --git a/tests/ui/missing_asserts_for_indexing.stderr b/tests/ui/missing_asserts_for_indexing.stderr index 2e63cd4a0e50..5d30920ccf52 100644 --- a/tests/ui/missing_asserts_for_indexing.stderr +++ b/tests/ui/missing_asserts_for_indexing.stderr @@ -147,7 +147,7 @@ LL | assert!(v.len() >= 3); | --------------------- help: provide the highest index that is indexed with: `assert!(v.len() > 3)` LL | let _ = v[0]; | _____________^ -LL | | +... | LL | | let _ = v[1..4]; | |___________________^ | @@ -157,37 +157,37 @@ note: slice indexed here LL | let _ = v[0]; | ^^^^ note: slice indexed here - --> tests/ui/missing_asserts_for_indexing.rs:68:13 + --> tests/ui/missing_asserts_for_indexing.rs:69:13 | LL | let _ = v[1..4]; | ^^^^^^^ = note: asserting the length before indexing will elide bounds checks error: indexing into a slice multiple times with an `assert` that does not cover the highest index - --> tests/ui/missing_asserts_for_indexing.rs:80:13 + --> tests/ui/missing_asserts_for_indexing.rs:81:13 | LL | assert!(v.len() >= 4); | --------------------- help: provide the highest index that is indexed with: `assert!(v.len() > 4)` LL | let _ = v[0]; | _____________^ -LL | | +... | LL | | let _ = v[1..=4]; | |____________________^ | note: slice indexed here - --> tests/ui/missing_asserts_for_indexing.rs:80:13 + --> tests/ui/missing_asserts_for_indexing.rs:81:13 | LL | let _ = v[0]; | ^^^^ note: slice indexed here - --> tests/ui/missing_asserts_for_indexing.rs:82:13 + --> tests/ui/missing_asserts_for_indexing.rs:84:13 | LL | let _ = v[1..=4]; | ^^^^^^^^ = note: asserting the length before indexing will elide bounds checks error: indexing into a slice multiple times with an `assert` that does not cover the highest index - --> tests/ui/missing_asserts_for_indexing.rs:95:13 + --> tests/ui/missing_asserts_for_indexing.rs:97:13 | LL | assert!(v1.len() >= 12); | ----------------------- help: provide the highest index that is indexed with: `assert!(v1.len() > 12)` @@ -196,19 +196,19 @@ LL | let _ = v1[0] + v1[12]; | ^^^^^^^^^^^^^^ | note: slice indexed here - --> tests/ui/missing_asserts_for_indexing.rs:95:13 + --> tests/ui/missing_asserts_for_indexing.rs:97:13 | LL | let _ = v1[0] + v1[12]; | ^^^^^ note: slice indexed here - --> tests/ui/missing_asserts_for_indexing.rs:95:21 + --> tests/ui/missing_asserts_for_indexing.rs:97:21 | LL | let _ = v1[0] + v1[12]; | ^^^^^^ = note: asserting the length before indexing will elide bounds checks error: indexing into a slice multiple times with an `assert` that does not cover the highest index - --> tests/ui/missing_asserts_for_indexing.rs:97:13 + --> tests/ui/missing_asserts_for_indexing.rs:100:13 | LL | assert!(v2.len() >= 15); | ----------------------- help: provide the highest index that is indexed with: `assert!(v2.len() > 15)` @@ -217,19 +217,19 @@ LL | let _ = v2[5] + v2[15]; | ^^^^^^^^^^^^^^ | note: slice indexed here - --> tests/ui/missing_asserts_for_indexing.rs:97:13 + --> tests/ui/missing_asserts_for_indexing.rs:100:13 | LL | let _ = v2[5] + v2[15]; | ^^^^^ note: slice indexed here - --> tests/ui/missing_asserts_for_indexing.rs:97:21 + --> tests/ui/missing_asserts_for_indexing.rs:100:21 | LL | let _ = v2[5] + v2[15]; | ^^^^^^ = note: asserting the length before indexing will elide bounds checks error: indexing into a slice multiple times with an `assert` that does not cover the highest index - --> tests/ui/missing_asserts_for_indexing.rs:103:13 + --> tests/ui/missing_asserts_for_indexing.rs:106:13 | LL | assert!(v1.len() >= 12); | ----------------------- help: provide the highest index that is indexed with: `assert!(v1.len() > 12)` @@ -238,19 +238,19 @@ LL | let _ = v1[0] + v1[12]; | ^^^^^^^^^^^^^^ | note: slice indexed here - --> tests/ui/missing_asserts_for_indexing.rs:103:13 + --> tests/ui/missing_asserts_for_indexing.rs:106:13 | LL | let _ = v1[0] + v1[12]; | ^^^^^ note: slice indexed here - --> tests/ui/missing_asserts_for_indexing.rs:103:21 + --> tests/ui/missing_asserts_for_indexing.rs:106:21 | LL | let _ = v1[0] + v1[12]; | ^^^^^^ = note: asserting the length before indexing will elide bounds checks error: indexing into a slice multiple times with an `assert` that does not cover the highest index - --> tests/ui/missing_asserts_for_indexing.rs:127:13 + --> tests/ui/missing_asserts_for_indexing.rs:131:13 | LL | assert!(v1.len() == 2); | ---------------------- help: provide the highest index that is indexed with: `assert!(v1.len() == 3)` @@ -259,24 +259,24 @@ LL | let _ = v1[0] + v1[1] + v1[2]; | ^^^^^^^^^^^^^^^^^^^^^ | note: slice indexed here - --> tests/ui/missing_asserts_for_indexing.rs:127:13 + --> tests/ui/missing_asserts_for_indexing.rs:131:13 | LL | let _ = v1[0] + v1[1] + v1[2]; | ^^^^^ note: slice indexed here - --> tests/ui/missing_asserts_for_indexing.rs:127:21 + --> tests/ui/missing_asserts_for_indexing.rs:131:21 | LL | let _ = v1[0] + v1[1] + v1[2]; | ^^^^^ note: slice indexed here - --> tests/ui/missing_asserts_for_indexing.rs:127:29 + --> tests/ui/missing_asserts_for_indexing.rs:131:29 | LL | let _ = v1[0] + v1[1] + v1[2]; | ^^^^^ = note: asserting the length before indexing will elide bounds checks error: indexing into a slice multiple times with an `assert` that does not cover the highest index - --> tests/ui/missing_asserts_for_indexing.rs:131:13 + --> tests/ui/missing_asserts_for_indexing.rs:136:13 | LL | assert!(2 == v3.len()); | ---------------------- help: provide the highest index that is indexed with: `assert!(v3.len() == 3)` @@ -285,17 +285,17 @@ LL | let _ = v3[0] + v3[1] + v3[2]; | ^^^^^^^^^^^^^^^^^^^^^ | note: slice indexed here - --> tests/ui/missing_asserts_for_indexing.rs:131:13 + --> tests/ui/missing_asserts_for_indexing.rs:136:13 | LL | let _ = v3[0] + v3[1] + v3[2]; | ^^^^^ note: slice indexed here - --> tests/ui/missing_asserts_for_indexing.rs:131:21 + --> tests/ui/missing_asserts_for_indexing.rs:136:21 | LL | let _ = v3[0] + v3[1] + v3[2]; | ^^^^^ note: slice indexed here - --> tests/ui/missing_asserts_for_indexing.rs:131:29 + --> tests/ui/missing_asserts_for_indexing.rs:136:29 | LL | let _ = v3[0] + v3[1] + v3[2]; | ^^^^^ diff --git a/tests/ui/missing_asserts_for_indexing_unfixable.rs b/tests/ui/missing_asserts_for_indexing_unfixable.rs index de53079a4760..a520151a2dd9 100644 --- a/tests/ui/missing_asserts_for_indexing_unfixable.rs +++ b/tests/ui/missing_asserts_for_indexing_unfixable.rs @@ -3,18 +3,20 @@ fn sum(v: &[u8]) -> u8 { v[0] + v[1] + v[2] + v[3] + v[4] - //~^ ERROR: indexing into a slice multiple times without an `assert` + //~^ missing_asserts_for_indexing } fn subslice(v: &[u8]) { let _ = v[0]; - //~^ ERROR: indexing into a slice multiple times without an `assert` + //~^ missing_asserts_for_indexing + let _ = v[1..4]; } fn variables(v: &[u8]) -> u8 { let a = v[0]; - //~^ ERROR: indexing into a slice multiple times without an `assert` + //~^ missing_asserts_for_indexing + let b = v[1]; let c = v[2]; a + b + c @@ -22,13 +24,16 @@ fn variables(v: &[u8]) -> u8 { fn index_different_slices(v1: &[u8], v2: &[u8]) { let _ = v1[0] + v1[12]; + //~^ missing_asserts_for_indexing let _ = v2[5] + v2[15]; + //~^ missing_asserts_for_indexing } fn index_different_slices2(v1: &[u8], v2: &[u8]) { assert!(v1.len() > 12); let _ = v1[0] + v1[12]; let _ = v2[5] + v2[15]; + //~^ missing_asserts_for_indexing } struct Foo<'a> { @@ -38,7 +43,7 @@ struct Foo<'a> { fn index_struct_field(f: &Foo<'_>) { let _ = f.v[0] + f.v[1]; - //~^ ERROR: indexing into a slice multiple times without an `assert` + //~^ missing_asserts_for_indexing } fn index_struct_different_fields(f: &Foo<'_>) { @@ -52,7 +57,7 @@ fn shadowing() { let x: &[i32] = &[1]; let _ = x[0] + x[1]; - //~^ ERROR: indexing into a slice multiple times without an `assert` + //~^ missing_asserts_for_indexing } pub fn issue11856(values: &[i32]) -> usize { diff --git a/tests/ui/missing_asserts_for_indexing_unfixable.stderr b/tests/ui/missing_asserts_for_indexing_unfixable.stderr index b575e09966ce..24109b052a8a 100644 --- a/tests/ui/missing_asserts_for_indexing_unfixable.stderr +++ b/tests/ui/missing_asserts_for_indexing_unfixable.stderr @@ -39,7 +39,7 @@ error: indexing into a slice multiple times without an `assert` | LL | let _ = v[0]; | _____________^ -LL | | +... | LL | | let _ = v[1..4]; | |___________________^ | @@ -50,130 +50,131 @@ note: slice indexed here LL | let _ = v[0]; | ^^^^ note: slice indexed here - --> tests/ui/missing_asserts_for_indexing_unfixable.rs:12:13 + --> tests/ui/missing_asserts_for_indexing_unfixable.rs:13:13 | LL | let _ = v[1..4]; | ^^^^^^^ = note: asserting the length before indexing will elide bounds checks error: indexing into a slice multiple times without an `assert` - --> tests/ui/missing_asserts_for_indexing_unfixable.rs:16:13 + --> tests/ui/missing_asserts_for_indexing_unfixable.rs:17:13 | LL | let a = v[0]; | _____________^ LL | | +LL | | LL | | let b = v[1]; LL | | let c = v[2]; | |________________^ | = help: consider asserting the length before indexing: `assert!(v.len() > 2);` note: slice indexed here - --> tests/ui/missing_asserts_for_indexing_unfixable.rs:16:13 + --> tests/ui/missing_asserts_for_indexing_unfixable.rs:17:13 | LL | let a = v[0]; | ^^^^ note: slice indexed here - --> tests/ui/missing_asserts_for_indexing_unfixable.rs:18:13 + --> tests/ui/missing_asserts_for_indexing_unfixable.rs:20:13 | LL | let b = v[1]; | ^^^^ note: slice indexed here - --> tests/ui/missing_asserts_for_indexing_unfixable.rs:19:13 + --> tests/ui/missing_asserts_for_indexing_unfixable.rs:21:13 | LL | let c = v[2]; | ^^^^ = note: asserting the length before indexing will elide bounds checks error: indexing into a slice multiple times without an `assert` - --> tests/ui/missing_asserts_for_indexing_unfixable.rs:24:13 + --> tests/ui/missing_asserts_for_indexing_unfixable.rs:26:13 | LL | let _ = v1[0] + v1[12]; | ^^^^^^^^^^^^^^ | = help: consider asserting the length before indexing: `assert!(v1.len() > 12);` note: slice indexed here - --> tests/ui/missing_asserts_for_indexing_unfixable.rs:24:13 + --> tests/ui/missing_asserts_for_indexing_unfixable.rs:26:13 | LL | let _ = v1[0] + v1[12]; | ^^^^^ note: slice indexed here - --> tests/ui/missing_asserts_for_indexing_unfixable.rs:24:21 + --> tests/ui/missing_asserts_for_indexing_unfixable.rs:26:21 | LL | let _ = v1[0] + v1[12]; | ^^^^^^ = note: asserting the length before indexing will elide bounds checks error: indexing into a slice multiple times without an `assert` - --> tests/ui/missing_asserts_for_indexing_unfixable.rs:25:13 + --> tests/ui/missing_asserts_for_indexing_unfixable.rs:28:13 | LL | let _ = v2[5] + v2[15]; | ^^^^^^^^^^^^^^ | = help: consider asserting the length before indexing: `assert!(v2.len() > 15);` note: slice indexed here - --> tests/ui/missing_asserts_for_indexing_unfixable.rs:25:13 + --> tests/ui/missing_asserts_for_indexing_unfixable.rs:28:13 | LL | let _ = v2[5] + v2[15]; | ^^^^^ note: slice indexed here - --> tests/ui/missing_asserts_for_indexing_unfixable.rs:25:21 + --> tests/ui/missing_asserts_for_indexing_unfixable.rs:28:21 | LL | let _ = v2[5] + v2[15]; | ^^^^^^ = note: asserting the length before indexing will elide bounds checks error: indexing into a slice multiple times without an `assert` - --> tests/ui/missing_asserts_for_indexing_unfixable.rs:31:13 + --> tests/ui/missing_asserts_for_indexing_unfixable.rs:35:13 | LL | let _ = v2[5] + v2[15]; | ^^^^^^^^^^^^^^ | = help: consider asserting the length before indexing: `assert!(v2.len() > 15);` note: slice indexed here - --> tests/ui/missing_asserts_for_indexing_unfixable.rs:31:13 + --> tests/ui/missing_asserts_for_indexing_unfixable.rs:35:13 | LL | let _ = v2[5] + v2[15]; | ^^^^^ note: slice indexed here - --> tests/ui/missing_asserts_for_indexing_unfixable.rs:31:21 + --> tests/ui/missing_asserts_for_indexing_unfixable.rs:35:21 | LL | let _ = v2[5] + v2[15]; | ^^^^^^ = note: asserting the length before indexing will elide bounds checks error: indexing into a slice multiple times without an `assert` - --> tests/ui/missing_asserts_for_indexing_unfixable.rs:40:13 + --> tests/ui/missing_asserts_for_indexing_unfixable.rs:45:13 | LL | let _ = f.v[0] + f.v[1]; | ^^^^^^^^^^^^^^^ | = help: consider asserting the length before indexing: `assert!(f.v.len() > 1);` note: slice indexed here - --> tests/ui/missing_asserts_for_indexing_unfixable.rs:40:13 + --> tests/ui/missing_asserts_for_indexing_unfixable.rs:45:13 | LL | let _ = f.v[0] + f.v[1]; | ^^^^^^ note: slice indexed here - --> tests/ui/missing_asserts_for_indexing_unfixable.rs:40:22 + --> tests/ui/missing_asserts_for_indexing_unfixable.rs:45:22 | LL | let _ = f.v[0] + f.v[1]; | ^^^^^^ = note: asserting the length before indexing will elide bounds checks error: indexing into a slice multiple times without an `assert` - --> tests/ui/missing_asserts_for_indexing_unfixable.rs:54:13 + --> tests/ui/missing_asserts_for_indexing_unfixable.rs:59:13 | LL | let _ = x[0] + x[1]; | ^^^^^^^^^^^ | = help: consider asserting the length before indexing: `assert!(x.len() > 1);` note: slice indexed here - --> tests/ui/missing_asserts_for_indexing_unfixable.rs:54:13 + --> tests/ui/missing_asserts_for_indexing_unfixable.rs:59:13 | LL | let _ = x[0] + x[1]; | ^^^^ note: slice indexed here - --> tests/ui/missing_asserts_for_indexing_unfixable.rs:54:20 + --> tests/ui/missing_asserts_for_indexing_unfixable.rs:59:20 | LL | let _ = x[0] + x[1]; | ^^^^ diff --git a/tests/ui/missing_const_for_fn/cant_be_const.rs b/tests/ui/missing_const_for_fn/cant_be_const.rs index cdfdcd5007a8..aef5eb5b890a 100644 --- a/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -1,3 +1,4 @@ +//@ check-pass //! False-positive tests to ensure we don't suggest `const` for things where it would cause a //! compilation error. //! The .stderr output of this test should be empty. Otherwise it's a bug somewhere. diff --git a/tests/ui/missing_const_for_fn/could_be_const.fixed b/tests/ui/missing_const_for_fn/could_be_const.fixed index 689060468c57..10df44e73b85 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.fixed +++ b/tests/ui/missing_const_for_fn/could_be_const.fixed @@ -11,45 +11,44 @@ struct Game { impl Game { // Could be const pub const fn new() -> Self { - //~^ ERROR: this could be a `const fn` - //~| NOTE: `-D clippy::missing-const-for-fn` implied by `-D warnings` + //~^ missing_const_for_fn Self { guess: 42 } } const fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T; N]) -> &'a [T; N] { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn b } } // Could be const const fn one() -> i32 { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn 1 } // Could also be const const fn two() -> i32 { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn let abc = 2; abc } // Could be const (since Rust 1.39) const fn string() -> String { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn String::new() } // Could be const const unsafe fn four() -> i32 { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn 4 } // Could also be const const fn generic(t: T) -> T { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn t } @@ -58,7 +57,7 @@ fn sub(x: u32) -> usize { } const fn generic_arr(t: [T; 1]) -> T { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn t[0] } @@ -72,7 +71,7 @@ mod with_drop { impl B { // This can be const, because `a` is passed by reference pub const fn b(self, a: &A) -> B { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn B } } @@ -82,7 +81,7 @@ mod with_drop { mod const_fn_stabilized_before_msrv { // This could be const because `u8::is_ascii_digit` is a stable const function in 1.47. const fn const_fn_stabilized_before_msrv(byte: u8) { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn byte.is_ascii_digit(); } } @@ -94,7 +93,7 @@ fn msrv_1_45() -> i32 { #[clippy::msrv = "1.46"] const fn msrv_1_46() -> i32 { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn 46 } @@ -114,7 +113,7 @@ impl const Drop for D { // Lint this, since it can be dropped in const contexts // FIXME(const_trait_impl) const fn d(this: D) {} -//~^ ERROR: this could be a `const fn` +//~^ missing_const_for_fn mod msrv { struct Foo(*const u8, &'static u8); @@ -122,12 +121,12 @@ mod msrv { impl Foo { #[clippy::msrv = "1.58"] const fn deref_ptr_can_be_const(self) -> usize { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn unsafe { *self.0 as usize } } const fn deref_copied_val(self) -> usize { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn *self.1 as usize } } @@ -138,7 +137,7 @@ mod msrv { #[clippy::msrv = "1.56"] const fn union_access_can_be_const() { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn let bar = Bar { val: 1 }; let _ = unsafe { bar.val }; } @@ -146,12 +145,12 @@ mod msrv { #[clippy::msrv = "1.62"] mod with_extern { const extern "C" fn c() {} - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn #[rustfmt::skip] #[allow(missing_abi)] const extern fn implicit_c() {} - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn // any item functions in extern block won't trigger this lint extern "C" { @@ -168,11 +167,13 @@ mod issue12677 { impl Wrapper { #[must_use] pub const fn new(strings: Vec) -> Self { + //~^ missing_const_for_fn Self { strings } } #[must_use] pub const fn empty() -> Self { + //~^ missing_const_for_fn Self { strings: Vec::new() } } } @@ -184,6 +185,7 @@ mod issue12677 { impl Other { pub const fn new(text: String) -> Self { + //~^ missing_const_for_fn let vec = Vec::new(); Self { text, vec } } @@ -203,18 +205,19 @@ mod with_ty_alias { // is. Because the associate ty could have no default, therefore would cause ICE, as demonstrated // in this test. const fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {} + //~^ missing_const_for_fn } mod extern_fn { const extern "C-unwind" fn c_unwind() {} - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn const extern "system" fn system() {} - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn const extern "system-unwind" fn system_unwind() {} - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn } const fn mut_add(x: &mut i32) { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn *x += 1; } diff --git a/tests/ui/missing_const_for_fn/could_be_const.rs b/tests/ui/missing_const_for_fn/could_be_const.rs index 492c47d7e49b..bc44b34daef7 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.rs +++ b/tests/ui/missing_const_for_fn/could_be_const.rs @@ -11,45 +11,44 @@ struct Game { impl Game { // Could be const pub fn new() -> Self { - //~^ ERROR: this could be a `const fn` - //~| NOTE: `-D clippy::missing-const-for-fn` implied by `-D warnings` + //~^ missing_const_for_fn Self { guess: 42 } } fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T; N]) -> &'a [T; N] { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn b } } // Could be const fn one() -> i32 { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn 1 } // Could also be const fn two() -> i32 { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn let abc = 2; abc } // Could be const (since Rust 1.39) fn string() -> String { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn String::new() } // Could be const unsafe fn four() -> i32 { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn 4 } // Could also be const fn generic(t: T) -> T { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn t } @@ -58,7 +57,7 @@ fn sub(x: u32) -> usize { } fn generic_arr(t: [T; 1]) -> T { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn t[0] } @@ -72,7 +71,7 @@ mod with_drop { impl B { // This can be const, because `a` is passed by reference pub fn b(self, a: &A) -> B { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn B } } @@ -82,7 +81,7 @@ mod with_drop { mod const_fn_stabilized_before_msrv { // This could be const because `u8::is_ascii_digit` is a stable const function in 1.47. fn const_fn_stabilized_before_msrv(byte: u8) { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn byte.is_ascii_digit(); } } @@ -94,7 +93,7 @@ fn msrv_1_45() -> i32 { #[clippy::msrv = "1.46"] fn msrv_1_46() -> i32 { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn 46 } @@ -114,7 +113,7 @@ impl const Drop for D { // Lint this, since it can be dropped in const contexts // FIXME(const_trait_impl) fn d(this: D) {} -//~^ ERROR: this could be a `const fn` +//~^ missing_const_for_fn mod msrv { struct Foo(*const u8, &'static u8); @@ -122,12 +121,12 @@ mod msrv { impl Foo { #[clippy::msrv = "1.58"] fn deref_ptr_can_be_const(self) -> usize { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn unsafe { *self.0 as usize } } fn deref_copied_val(self) -> usize { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn *self.1 as usize } } @@ -138,7 +137,7 @@ mod msrv { #[clippy::msrv = "1.56"] fn union_access_can_be_const() { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn let bar = Bar { val: 1 }; let _ = unsafe { bar.val }; } @@ -146,12 +145,12 @@ mod msrv { #[clippy::msrv = "1.62"] mod with_extern { extern "C" fn c() {} - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn #[rustfmt::skip] #[allow(missing_abi)] extern fn implicit_c() {} - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn // any item functions in extern block won't trigger this lint extern "C" { @@ -168,11 +167,13 @@ mod issue12677 { impl Wrapper { #[must_use] pub fn new(strings: Vec) -> Self { + //~^ missing_const_for_fn Self { strings } } #[must_use] pub fn empty() -> Self { + //~^ missing_const_for_fn Self { strings: Vec::new() } } } @@ -184,6 +185,7 @@ mod issue12677 { impl Other { pub fn new(text: String) -> Self { + //~^ missing_const_for_fn let vec = Vec::new(); Self { text, vec } } @@ -203,18 +205,19 @@ mod with_ty_alias { // is. Because the associate ty could have no default, therefore would cause ICE, as demonstrated // in this test. fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {} + //~^ missing_const_for_fn } mod extern_fn { extern "C-unwind" fn c_unwind() {} - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn extern "system" fn system() {} - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn extern "system-unwind" fn system_unwind() {} - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn } fn mut_add(x: &mut i32) { - //~^ ERROR: this could be a `const fn` + //~^ missing_const_for_fn *x += 1; } diff --git a/tests/ui/missing_const_for_fn/could_be_const.stderr b/tests/ui/missing_const_for_fn/could_be_const.stderr index a06703e2ebf2..5df5a54ff521 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.stderr +++ b/tests/ui/missing_const_for_fn/could_be_const.stderr @@ -3,7 +3,6 @@ error: this could be a `const fn` | LL | / pub fn new() -> Self { LL | | -LL | | LL | | Self { guess: 42 } LL | | } | |_____^ @@ -16,7 +15,7 @@ LL | pub const fn new() -> Self { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:19:5 + --> tests/ui/missing_const_for_fn/could_be_const.rs:18:5 | LL | / fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T; N]) -> &'a [T; N] { LL | | @@ -30,7 +29,7 @@ LL | const fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T; | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:26:1 + --> tests/ui/missing_const_for_fn/could_be_const.rs:25:1 | LL | / fn one() -> i32 { LL | | @@ -44,7 +43,7 @@ LL | const fn one() -> i32 { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:32:1 + --> tests/ui/missing_const_for_fn/could_be_const.rs:31:1 | LL | / fn two() -> i32 { LL | | @@ -59,7 +58,7 @@ LL | const fn two() -> i32 { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:39:1 + --> tests/ui/missing_const_for_fn/could_be_const.rs:38:1 | LL | / fn string() -> String { LL | | @@ -73,7 +72,7 @@ LL | const fn string() -> String { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:45:1 + --> tests/ui/missing_const_for_fn/could_be_const.rs:44:1 | LL | / unsafe fn four() -> i32 { LL | | @@ -87,7 +86,7 @@ LL | const unsafe fn four() -> i32 { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:51:1 + --> tests/ui/missing_const_for_fn/could_be_const.rs:50:1 | LL | / fn generic(t: T) -> T { LL | | @@ -101,7 +100,7 @@ LL | const fn generic(t: T) -> T { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:60:1 + --> tests/ui/missing_const_for_fn/could_be_const.rs:59:1 | LL | / fn generic_arr(t: [T; 1]) -> T { LL | | @@ -115,7 +114,7 @@ LL | const fn generic_arr(t: [T; 1]) -> T { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:74:9 + --> tests/ui/missing_const_for_fn/could_be_const.rs:73:9 | LL | / pub fn b(self, a: &A) -> B { LL | | @@ -129,7 +128,7 @@ LL | pub const fn b(self, a: &A) -> B { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:84:5 + --> tests/ui/missing_const_for_fn/could_be_const.rs:83:5 | LL | / fn const_fn_stabilized_before_msrv(byte: u8) { LL | | @@ -143,7 +142,7 @@ LL | const fn const_fn_stabilized_before_msrv(byte: u8) { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:96:1 + --> tests/ui/missing_const_for_fn/could_be_const.rs:95:1 | LL | / fn msrv_1_46() -> i32 { LL | | @@ -157,7 +156,7 @@ LL | const fn msrv_1_46() -> i32 { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:116:1 + --> tests/ui/missing_const_for_fn/could_be_const.rs:115:1 | LL | fn d(this: D) {} | ^^^^^^^^^^^^^^^^ @@ -168,7 +167,7 @@ LL | const fn d(this: D) {} | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:124:9 + --> tests/ui/missing_const_for_fn/could_be_const.rs:123:9 | LL | / fn deref_ptr_can_be_const(self) -> usize { LL | | @@ -182,7 +181,7 @@ LL | const fn deref_ptr_can_be_const(self) -> usize { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:129:9 + --> tests/ui/missing_const_for_fn/could_be_const.rs:128:9 | LL | / fn deref_copied_val(self) -> usize { LL | | @@ -196,7 +195,7 @@ LL | const fn deref_copied_val(self) -> usize { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:140:5 + --> tests/ui/missing_const_for_fn/could_be_const.rs:139:5 | LL | / fn union_access_can_be_const() { LL | | @@ -211,7 +210,7 @@ LL | const fn union_access_can_be_const() { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:148:9 + --> tests/ui/missing_const_for_fn/could_be_const.rs:147:9 | LL | extern "C" fn c() {} | ^^^^^^^^^^^^^^^^^^^^ @@ -222,7 +221,7 @@ LL | const extern "C" fn c() {} | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:153:9 + --> tests/ui/missing_const_for_fn/could_be_const.rs:152:9 | LL | extern fn implicit_c() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -233,9 +232,10 @@ LL | const extern fn implicit_c() {} | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:170:9 + --> tests/ui/missing_const_for_fn/could_be_const.rs:169:9 | LL | / pub fn new(strings: Vec) -> Self { +LL | | LL | | Self { strings } LL | | } | |_________^ @@ -249,6 +249,7 @@ error: this could be a `const fn` --> tests/ui/missing_const_for_fn/could_be_const.rs:175:9 | LL | / pub fn empty() -> Self { +LL | | LL | | Self { strings: Vec::new() } LL | | } | |_________^ @@ -259,9 +260,10 @@ LL | pub const fn empty() -> Self { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:186:9 + --> tests/ui/missing_const_for_fn/could_be_const.rs:187:9 | LL | / pub fn new(text: String) -> Self { +LL | | LL | | let vec = Vec::new(); LL | | Self { text, vec } LL | | } @@ -273,7 +275,7 @@ LL | pub const fn new(text: String) -> Self { | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:205:5 + --> tests/ui/missing_const_for_fn/could_be_const.rs:207:5 | LL | fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -284,7 +286,7 @@ LL | const fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {} | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:209:5 + --> tests/ui/missing_const_for_fn/could_be_const.rs:212:5 | LL | extern "C-unwind" fn c_unwind() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -295,7 +297,7 @@ LL | const extern "C-unwind" fn c_unwind() {} | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:211:5 + --> tests/ui/missing_const_for_fn/could_be_const.rs:214:5 | LL | extern "system" fn system() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -306,7 +308,7 @@ LL | const extern "system" fn system() {} | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:213:5 + --> tests/ui/missing_const_for_fn/could_be_const.rs:216:5 | LL | extern "system-unwind" fn system_unwind() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -317,7 +319,7 @@ LL | const extern "system-unwind" fn system_unwind() {} | +++++ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:217:1 + --> tests/ui/missing_const_for_fn/could_be_const.rs:220:1 | LL | / fn mut_add(x: &mut i32) { LL | | diff --git a/tests/ui/missing_const_for_thread_local.fixed b/tests/ui/missing_const_for_thread_local.fixed index 90b31b9b5d21..2efe10c153da 100644 --- a/tests/ui/missing_const_for_thread_local.fixed +++ b/tests/ui/missing_const_for_thread_local.fixed @@ -6,8 +6,8 @@ fn main() { // lint and suggest const thread_local! { static BUF_1: RefCell = const { RefCell::new(String::new()) }; + //~^ missing_const_for_thread_local } - //~^^ ERROR: initializer for `thread_local` value can be made `const` // don't lint thread_local! { @@ -16,23 +16,25 @@ fn main() { thread_local! { static SIMPLE:i32 = const { 1 }; + //~^ missing_const_for_thread_local } - //~^^ ERROR: initializer for `thread_local` value can be made `const` // lint and suggest const for all non const items thread_local! { static BUF_3_CAN_BE_MADE_CONST: RefCell = const { RefCell::new(String::new()) }; + //~^ missing_const_for_thread_local static CONST_MIXED_WITH:i32 = const { 1 }; static BUF_4_CAN_BE_MADE_CONST: RefCell = const { RefCell::new(String::new()) }; + //~^ missing_const_for_thread_local } - //~^^^^ ERROR: initializer for `thread_local` value can be made `const` - //~^^^ ERROR: initializer for `thread_local` value can be made `const` thread_local! { static PEEL_ME: i32 = const { 1 }; - //~^ ERROR: initializer for `thread_local` value can be made `const` + //~^ missing_const_for_thread_local + static PEEL_ME_MANY: i32 = const { { let x = 1; x * x } }; - //~^ ERROR: initializer for `thread_local` value can be made `const` + //~^ missing_const_for_thread_local + } } diff --git a/tests/ui/missing_const_for_thread_local.rs b/tests/ui/missing_const_for_thread_local.rs index f97e4848fd7a..119cc5a99fa0 100644 --- a/tests/ui/missing_const_for_thread_local.rs +++ b/tests/ui/missing_const_for_thread_local.rs @@ -6,8 +6,8 @@ fn main() { // lint and suggest const thread_local! { static BUF_1: RefCell = RefCell::new(String::new()); + //~^ missing_const_for_thread_local } - //~^^ ERROR: initializer for `thread_local` value can be made `const` // don't lint thread_local! { @@ -16,23 +16,25 @@ fn main() { thread_local! { static SIMPLE:i32 = 1; + //~^ missing_const_for_thread_local } - //~^^ ERROR: initializer for `thread_local` value can be made `const` // lint and suggest const for all non const items thread_local! { static BUF_3_CAN_BE_MADE_CONST: RefCell = RefCell::new(String::new()); + //~^ missing_const_for_thread_local static CONST_MIXED_WITH:i32 = const { 1 }; static BUF_4_CAN_BE_MADE_CONST: RefCell = RefCell::new(String::new()); + //~^ missing_const_for_thread_local } - //~^^^^ ERROR: initializer for `thread_local` value can be made `const` - //~^^^ ERROR: initializer for `thread_local` value can be made `const` thread_local! { static PEEL_ME: i32 = { 1 }; - //~^ ERROR: initializer for `thread_local` value can be made `const` + //~^ missing_const_for_thread_local + static PEEL_ME_MANY: i32 = { let x = 1; x * x }; - //~^ ERROR: initializer for `thread_local` value can be made `const` + //~^ missing_const_for_thread_local + } } diff --git a/tests/ui/missing_const_for_thread_local.stderr b/tests/ui/missing_const_for_thread_local.stderr index c143a37454f5..4e90c10c92f8 100644 --- a/tests/ui/missing_const_for_thread_local.stderr +++ b/tests/ui/missing_const_for_thread_local.stderr @@ -20,7 +20,7 @@ LL | static BUF_3_CAN_BE_MADE_CONST: RefCell = RefCell::new(Stri | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `const { RefCell::new(String::new()) }` error: initializer for `thread_local` value can be made `const` - --> tests/ui/missing_const_for_thread_local.rs:26:59 + --> tests/ui/missing_const_for_thread_local.rs:27:59 | LL | static BUF_4_CAN_BE_MADE_CONST: RefCell = RefCell::new(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `const { RefCell::new(String::new()) }` @@ -32,7 +32,7 @@ LL | static PEEL_ME: i32 = { 1 }; | ^^^^^ help: replace with: `const { 1 }` error: initializer for `thread_local` value can be made `const` - --> tests/ui/missing_const_for_thread_local.rs:34:36 + --> tests/ui/missing_const_for_thread_local.rs:35:36 | LL | static PEEL_ME_MANY: i32 = { let x = 1; x * x }; | ^^^^^^^^^^^^^^^^^^^^ help: replace with: `const { { let x = 1; x * x } }` diff --git a/tests/ui/missing_doc.rs b/tests/ui/missing_doc.rs index 31bc4309582e..705de959cb7d 100644 --- a/tests/ui/missing_doc.rs +++ b/tests/ui/missing_doc.rs @@ -17,15 +17,18 @@ use proc_macros::with_span; use std::arch::global_asm; type Typedef = String; +//~^ missing_docs_in_private_items pub type PubTypedef = String; mod module_no_dox {} +//~^ missing_docs_in_private_items pub mod pub_module_no_dox {} /// dox pub fn foo() {} pub fn foo2() {} fn foo3() {} +//~^ missing_docs_in_private_items #[allow(clippy::missing_docs_in_private_items)] pub fn foo4() {} @@ -40,8 +43,13 @@ mod a { } enum Baz { + //~^ missing_docs_in_private_items BazA { a: isize, b: isize }, + //~^ missing_docs_in_private_items + //~| missing_docs_in_private_items + //~| missing_docs_in_private_items BarB, + //~^ missing_docs_in_private_items } pub enum PubBaz { @@ -66,6 +74,7 @@ pub enum PubBaz3 { pub fn baz() {} const FOO: u32 = 0; +//~^ missing_docs_in_private_items /// dox pub const FOO1: u32 = 0; #[allow(clippy::missing_docs_in_private_items)] @@ -75,6 +84,7 @@ pub const FOO3: u32 = 0; pub const FOO4: u32 = 0; static BAR: u32 = 0; +//~^ missing_docs_in_private_items /// dox pub static BAR1: u32 = 0; #[allow(clippy::missing_docs_in_private_items)] @@ -84,17 +94,20 @@ pub static BAR3: u32 = 0; pub static BAR4: u32 = 0; mod internal_impl { + //~^ missing_docs_in_private_items /// dox pub fn documented() {} pub fn undocumented1() {} pub fn undocumented2() {} fn undocumented3() {} + //~^ missing_docs_in_private_items /// dox pub mod globbed { /// dox pub fn also_documented() {} pub fn also_undocumented1() {} fn also_undocumented2() {} + //~^ missing_docs_in_private_items } } /// dox @@ -120,6 +133,7 @@ with_span!(span pub const FOO2_PM: u32 = 0;); const _: () = (); fn issue13298() { + //~^ missing_docs_in_private_items // Rustdoc doesn't generate documentation for items within other items like fns or consts const MSG: &str = "Hello, world!"; } diff --git a/tests/ui/missing_doc.stderr b/tests/ui/missing_doc.stderr index 6554eed16106..63e440b82d14 100644 --- a/tests/ui/missing_doc.stderr +++ b/tests/ui/missing_doc.stderr @@ -8,89 +8,91 @@ LL | type Typedef = String; = help: to override `-D warnings` add `#[allow(clippy::missing_docs_in_private_items)]` error: missing documentation for a module - --> tests/ui/missing_doc.rs:22:1 + --> tests/ui/missing_doc.rs:23:1 | LL | mod module_no_dox {} | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> tests/ui/missing_doc.rs:28:1 + --> tests/ui/missing_doc.rs:30:1 | LL | fn foo3() {} | ^^^^^^^^^^^^ error: missing documentation for an enum - --> tests/ui/missing_doc.rs:42:1 + --> tests/ui/missing_doc.rs:45:1 | LL | / enum Baz { +LL | | LL | | BazA { a: isize, b: isize }, -LL | | BarB, +... | LL | | } | |_^ error: missing documentation for a variant - --> tests/ui/missing_doc.rs:43:5 + --> tests/ui/missing_doc.rs:47:5 | LL | BazA { a: isize, b: isize }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a struct field - --> tests/ui/missing_doc.rs:43:12 + --> tests/ui/missing_doc.rs:47:12 | LL | BazA { a: isize, b: isize }, | ^^^^^^^^ error: missing documentation for a struct field - --> tests/ui/missing_doc.rs:43:22 + --> tests/ui/missing_doc.rs:47:22 | LL | BazA { a: isize, b: isize }, | ^^^^^^^^ error: missing documentation for a variant - --> tests/ui/missing_doc.rs:44:5 + --> tests/ui/missing_doc.rs:51:5 | LL | BarB, | ^^^^ error: missing documentation for a constant - --> tests/ui/missing_doc.rs:68:1 + --> tests/ui/missing_doc.rs:76:1 | LL | const FOO: u32 = 0; | ^^^^^^^^^^^^^^^^^^^ error: missing documentation for a static - --> tests/ui/missing_doc.rs:77:1 + --> tests/ui/missing_doc.rs:86:1 | LL | static BAR: u32 = 0; | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a module - --> tests/ui/missing_doc.rs:86:1 + --> tests/ui/missing_doc.rs:96:1 | LL | / mod internal_impl { +LL | | LL | | /// dox LL | | pub fn documented() {} -LL | | pub fn undocumented1() {} ... | LL | | } | |_^ error: missing documentation for a function - --> tests/ui/missing_doc.rs:91:5 + --> tests/ui/missing_doc.rs:102:5 | LL | fn undocumented3() {} | ^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> tests/ui/missing_doc.rs:97:9 + --> tests/ui/missing_doc.rs:109:9 | LL | fn also_undocumented2() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> tests/ui/missing_doc.rs:122:1 + --> tests/ui/missing_doc.rs:135:1 | LL | / fn issue13298() { +LL | | LL | | // Rustdoc doesn't generate documentation for items within other items like fns or consts LL | | const MSG: &str = "Hello, world!"; LL | | } diff --git a/tests/ui/missing_doc_crate.rs b/tests/ui/missing_doc_crate.rs index fdb23af279df..e6e783a2bb40 100644 --- a/tests/ui/missing_doc_crate.rs +++ b/tests/ui/missing_doc_crate.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::missing_docs_in_private_items)] #![allow(clippy::doc_include_without_cfg)] #![doc = include_str!("../../README.md")] diff --git a/tests/ui/missing_doc_crate_missing.rs b/tests/ui/missing_doc_crate_missing.rs index 73584ac8c67d..f55d8b67cb84 100644 --- a/tests/ui/missing_doc_crate_missing.rs +++ b/tests/ui/missing_doc_crate_missing.rs @@ -1,5 +1,4 @@ #![warn(clippy::missing_docs_in_private_items)] -//~^ ERROR: missing documentation for the crate -//~| NOTE: `-D clippy::missing-docs-in-private-items` implied by `-D warnings` +//~^ missing_docs_in_private_items fn main() {} diff --git a/tests/ui/missing_doc_impl.rs b/tests/ui/missing_doc_impl.rs index 520ddbe16b82..034ce31dfe76 100644 --- a/tests/ui/missing_doc_impl.rs +++ b/tests/ui/missing_doc_impl.rs @@ -11,13 +11,17 @@ extern crate proc_macros; use proc_macros::with_span; struct Foo { + //~^ missing_docs_in_private_items a: isize, + //~^ missing_docs_in_private_items b: isize, + //~^ missing_docs_in_private_items } pub struct PubFoo { pub a: isize, b: isize, + //~^ missing_docs_in_private_items } #[allow(clippy::missing_docs_in_private_items)] @@ -65,9 +69,11 @@ pub trait E: Sized { impl Foo { pub fn new() -> Self { + //~^ missing_docs_in_private_items Foo { a: 0, b: 0 } } fn bar() {} + //~^ missing_docs_in_private_items } impl PubFoo { @@ -76,6 +82,7 @@ impl PubFoo { pub fn foo1() {} #[must_use = "yep"] fn foo2() -> u32 { + //~^ missing_docs_in_private_items 1 } #[allow(clippy::missing_docs_in_private_items)] diff --git a/tests/ui/missing_doc_impl.stderr b/tests/ui/missing_doc_impl.stderr index e2052c346df8..999ff06f593e 100644 --- a/tests/ui/missing_doc_impl.stderr +++ b/tests/ui/missing_doc_impl.stderr @@ -2,8 +2,9 @@ error: missing documentation for a struct --> tests/ui/missing_doc_impl.rs:13:1 | LL | / struct Foo { +LL | | LL | | a: isize, -LL | | b: isize, +... | LL | | } | |_^ | @@ -11,41 +12,43 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::missing_docs_in_private_items)]` error: missing documentation for a struct field - --> tests/ui/missing_doc_impl.rs:14:5 + --> tests/ui/missing_doc_impl.rs:15:5 | LL | a: isize, | ^^^^^^^^ error: missing documentation for a struct field - --> tests/ui/missing_doc_impl.rs:15:5 + --> tests/ui/missing_doc_impl.rs:17:5 | LL | b: isize, | ^^^^^^^^ error: missing documentation for a struct field - --> tests/ui/missing_doc_impl.rs:20:5 + --> tests/ui/missing_doc_impl.rs:23:5 | LL | b: isize, | ^^^^^^^^ error: missing documentation for an associated function - --> tests/ui/missing_doc_impl.rs:67:5 + --> tests/ui/missing_doc_impl.rs:71:5 | LL | / pub fn new() -> Self { +LL | | LL | | Foo { a: 0, b: 0 } LL | | } | |_____^ error: missing documentation for an associated function - --> tests/ui/missing_doc_impl.rs:70:5 + --> tests/ui/missing_doc_impl.rs:75:5 | LL | fn bar() {} | ^^^^^^^^^^^ error: missing documentation for an associated function - --> tests/ui/missing_doc_impl.rs:78:5 + --> tests/ui/missing_doc_impl.rs:84:5 | LL | / fn foo2() -> u32 { +LL | | LL | | 1 LL | | } | |_____^ diff --git a/tests/ui/missing_fields_in_debug.rs b/tests/ui/missing_fields_in_debug.rs index 68867ec819d1..14803b5485a1 100644 --- a/tests/ui/missing_fields_in_debug.rs +++ b/tests/ui/missing_fields_in_debug.rs @@ -12,7 +12,8 @@ struct NamedStruct1Ignored { } impl fmt::Debug for NamedStruct1Ignored { - //~^ ERROR: manual `Debug` impl does not include all fields + //~^ missing_fields_in_debug + // unused field: hidden fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter @@ -31,7 +32,8 @@ struct NamedStructMultipleIgnored { } impl fmt::Debug for NamedStructMultipleIgnored { - //~^ ERROR: manual `Debug` impl does not include all fields + //~^ missing_fields_in_debug + // unused fields: hidden, hidden2, hidden4 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter @@ -93,7 +95,8 @@ struct MultiExprDebugImpl { // ok impl fmt::Debug for MultiExprDebugImpl { - //~^ ERROR: manual `Debug` impl does not include all fields + //~^ missing_fields_in_debug + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { let mut f = formatter.debug_struct("MultiExprDebugImpl"); f.field("a", &self.a); diff --git a/tests/ui/missing_fields_in_debug.stderr b/tests/ui/missing_fields_in_debug.stderr index 5e51194c4b37..75b551e1f5c7 100644 --- a/tests/ui/missing_fields_in_debug.stderr +++ b/tests/ui/missing_fields_in_debug.stderr @@ -2,9 +2,6 @@ error: manual `Debug` impl does not include all fields --> tests/ui/missing_fields_in_debug.rs:14:1 | LL | / impl fmt::Debug for NamedStruct1Ignored { -LL | | -LL | | // unused field: hidden -LL | | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { ... | LL | | } | |_^ @@ -20,28 +17,25 @@ LL | hidden: u32, = help: to override `-D warnings` add `#[allow(clippy::missing_fields_in_debug)]` error: manual `Debug` impl does not include all fields - --> tests/ui/missing_fields_in_debug.rs:33:1 + --> tests/ui/missing_fields_in_debug.rs:34:1 | LL | / impl fmt::Debug for NamedStructMultipleIgnored { -LL | | -LL | | // unused fields: hidden, hidden2, hidden4 -LL | | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { ... | LL | | } | |_^ | note: this field is unused - --> tests/ui/missing_fields_in_debug.rs:27:5 + --> tests/ui/missing_fields_in_debug.rs:28:5 | LL | hidden: u32, | ^^^^^^^^^^^ note: this field is unused - --> tests/ui/missing_fields_in_debug.rs:28:5 + --> tests/ui/missing_fields_in_debug.rs:29:5 | LL | hidden2: String, | ^^^^^^^^^^^^^^^ note: this field is unused - --> tests/ui/missing_fields_in_debug.rs:30:5 + --> tests/ui/missing_fields_in_debug.rs:31:5 | LL | hidden4: ((((u8), u16), u32), u64), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,18 +43,18 @@ LL | hidden4: ((((u8), u16), u32), u64), = help: consider calling `.finish_non_exhaustive()` if you intend to ignore fields error: manual `Debug` impl does not include all fields - --> tests/ui/missing_fields_in_debug.rs:95:1 + --> tests/ui/missing_fields_in_debug.rs:97:1 | LL | / impl fmt::Debug for MultiExprDebugImpl { LL | | +LL | | LL | | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { -LL | | let mut f = formatter.debug_struct("MultiExprDebugImpl"); ... | LL | | } | |_^ | note: this field is unused - --> tests/ui/missing_fields_in_debug.rs:91:5 + --> tests/ui/missing_fields_in_debug.rs:93:5 | LL | b: String, | ^^^^^^^^^ diff --git a/tests/ui/missing_inline.rs b/tests/ui/missing_inline.rs index dca85b94d5ee..c1801005b777 100644 --- a/tests/ui/missing_inline.rs +++ b/tests/ui/missing_inline.rs @@ -18,8 +18,8 @@ pub mod pub_module {} // ok fn foo() {} // missing #[inline] pub fn pub_foo() {} -//~^ ERROR: missing `#[inline]` for a function -//~| NOTE: `-D clippy::missing-inline-in-public-items` implied by `-D warnings` +//~^ missing_inline_in_public_items + #[inline] pub fn pub_foo_inline() {} // ok #[inline(always)] @@ -37,7 +37,8 @@ pub trait PubBar { fn PubBar_a(); // ok // missing #[inline] fn PubBar_b() {} - //~^ ERROR: missing `#[inline]` for a default trait method + //~^ missing_inline_in_public_items + #[inline] fn PubBar_c() {} // ok } @@ -53,13 +54,15 @@ impl PubBar for Foo { impl PubBar for PubFoo { // missing #[inline] fn PubBar_a() {} - //~^ ERROR: missing `#[inline]` for a method + //~^ missing_inline_in_public_items + // missing #[inline] fn PubBar_b() {} - //~^ ERROR: missing `#[inline]` for a method + //~^ missing_inline_in_public_items + // missing #[inline] fn PubBar_c() {} - //~^ ERROR: missing `#[inline]` for a method + //~^ missing_inline_in_public_items } // do not need inline because Foo is not exported @@ -71,7 +74,7 @@ impl Foo { impl PubFoo { // missing #[inline] pub fn PubFooImpl() {} - //~^ ERROR: missing `#[inline]` for a method + //~^ missing_inline_in_public_items } // do not lint this since users cannot control the external code diff --git a/tests/ui/missing_inline.stderr b/tests/ui/missing_inline.stderr index c2bb37141a02..99ee828e805c 100644 --- a/tests/ui/missing_inline.stderr +++ b/tests/ui/missing_inline.stderr @@ -14,25 +14,25 @@ LL | fn PubBar_b() {} | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method - --> tests/ui/missing_inline.rs:55:5 + --> tests/ui/missing_inline.rs:56:5 | LL | fn PubBar_a() {} | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method - --> tests/ui/missing_inline.rs:58:5 + --> tests/ui/missing_inline.rs:60:5 | LL | fn PubBar_b() {} | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method - --> tests/ui/missing_inline.rs:61:5 + --> tests/ui/missing_inline.rs:64:5 | LL | fn PubBar_c() {} | ^^^^^^^^^^^^^^^^ error: missing `#[inline]` for a method - --> tests/ui/missing_inline.rs:73:5 + --> tests/ui/missing_inline.rs:76:5 | LL | pub fn PubFooImpl() {} | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/missing_inline_executable.rs b/tests/ui/missing_inline_executable.rs index 6e0400ac935b..444a7f1c964f 100644 --- a/tests/ui/missing_inline_executable.rs +++ b/tests/ui/missing_inline_executable.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::missing_inline_in_public_items)] pub fn foo() {} diff --git a/tests/ui/missing_inline_proc_macro.rs b/tests/ui/missing_inline_proc_macro.rs index e47a198c6aea..ce368304f725 100644 --- a/tests/ui/missing_inline_proc_macro.rs +++ b/tests/ui/missing_inline_proc_macro.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::missing_inline_in_public_items)] extern crate proc_macro; diff --git a/tests/ui/missing_panics_doc.rs b/tests/ui/missing_panics_doc.rs index b0fa8e988598..95e361c5d555 100644 --- a/tests/ui/missing_panics_doc.rs +++ b/tests/ui/missing_panics_doc.rs @@ -11,17 +11,20 @@ fn main() {} /// This needs to be documented pub fn unwrap() { + //~^ missing_panics_doc let result = Err("Hi"); result.unwrap() } /// This needs to be documented pub fn panic() { + //~^ missing_panics_doc panic!("This function panics") } /// This needs to be documented pub fn inner_body(opt: Option) { + //~^ missing_panics_doc opt.map(|x| { if x == 10 { panic!() @@ -31,17 +34,20 @@ pub fn inner_body(opt: Option) { /// This needs to be documented pub fn unreachable_and_panic() { + //~^ missing_panics_doc if true { unreachable!() } else { panic!() } } /// This needs to be documented pub fn assert_eq() { + //~^ missing_panics_doc let x = 0; assert_eq!(x, 0); } /// This needs to be documented pub fn assert_ne() { + //~^ missing_panics_doc let x = 0; assert_ne!(x, 0); } @@ -149,30 +155,36 @@ pub fn debug_assertions() { // `pub` is required, because the lint does not consider unreachable items pub mod issue10240 { pub fn option_unwrap(v: &[T]) -> &T { + //~^ missing_panics_doc let o: Option<&T> = v.last(); o.unwrap() } pub fn option_expect(v: &[T]) -> &T { + //~^ missing_panics_doc let o: Option<&T> = v.last(); o.expect("passed an empty thing") } pub fn result_unwrap(v: &[T]) -> &T { + //~^ missing_panics_doc let res: Result<&T, &str> = v.last().ok_or("oh noes"); res.unwrap() } pub fn result_expect(v: &[T]) -> &T { + //~^ missing_panics_doc let res: Result<&T, &str> = v.last().ok_or("oh noes"); res.expect("passed an empty thing") } pub fn last_unwrap(v: &[u32]) -> u32 { + //~^ missing_panics_doc *v.last().unwrap() } pub fn last_expect(v: &[u32]) -> u32 { + //~^ missing_panics_doc *v.last().expect("passed an empty thing") } } diff --git a/tests/ui/missing_panics_doc.stderr b/tests/ui/missing_panics_doc.stderr index c6a939d86f7c..a83e2fa367dd 100644 --- a/tests/ui/missing_panics_doc.stderr +++ b/tests/ui/missing_panics_doc.stderr @@ -5,7 +5,7 @@ LL | pub fn unwrap() { | ^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:15:5 + --> tests/ui/missing_panics_doc.rs:16:5 | LL | result.unwrap() | ^^^^^^^^^^^^^^^ @@ -13,133 +13,133 @@ LL | result.unwrap() = help: to override `-D warnings` add `#[allow(clippy::missing_panics_doc)]` error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:19:1 + --> tests/ui/missing_panics_doc.rs:20:1 | LL | pub fn panic() { | ^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:20:5 + --> tests/ui/missing_panics_doc.rs:22:5 | LL | panic!("This function panics") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:24:1 + --> tests/ui/missing_panics_doc.rs:26:1 | LL | pub fn inner_body(opt: Option) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:27:13 + --> tests/ui/missing_panics_doc.rs:30:13 | LL | panic!() | ^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:33:1 + --> tests/ui/missing_panics_doc.rs:36:1 | LL | pub fn unreachable_and_panic() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:34:39 + --> tests/ui/missing_panics_doc.rs:38:39 | LL | if true { unreachable!() } else { panic!() } | ^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:38:1 + --> tests/ui/missing_panics_doc.rs:42:1 | LL | pub fn assert_eq() { | ^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:40:5 + --> tests/ui/missing_panics_doc.rs:45:5 | LL | assert_eq!(x, 0); | ^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:44:1 + --> tests/ui/missing_panics_doc.rs:49:1 | LL | pub fn assert_ne() { | ^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:46:5 + --> tests/ui/missing_panics_doc.rs:52:5 | LL | assert_ne!(x, 0); | ^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:151:5 + --> tests/ui/missing_panics_doc.rs:157:5 | LL | pub fn option_unwrap(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:153:9 + --> tests/ui/missing_panics_doc.rs:160:9 | LL | o.unwrap() | ^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:156:5 + --> tests/ui/missing_panics_doc.rs:163:5 | LL | pub fn option_expect(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:158:9 + --> tests/ui/missing_panics_doc.rs:166:9 | LL | o.expect("passed an empty thing") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:161:5 + --> tests/ui/missing_panics_doc.rs:169:5 | LL | pub fn result_unwrap(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:163:9 + --> tests/ui/missing_panics_doc.rs:172:9 | LL | res.unwrap() | ^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:166:5 + --> tests/ui/missing_panics_doc.rs:175:5 | LL | pub fn result_expect(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:168:9 + --> tests/ui/missing_panics_doc.rs:178:9 | LL | res.expect("passed an empty thing") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:171:5 + --> tests/ui/missing_panics_doc.rs:181:5 | LL | pub fn last_unwrap(v: &[u32]) -> u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:172:10 + --> tests/ui/missing_panics_doc.rs:183:10 | LL | *v.last().unwrap() | ^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:175:5 + --> tests/ui/missing_panics_doc.rs:186:5 | LL | pub fn last_expect(v: &[u32]) -> u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:176:10 + --> tests/ui/missing_panics_doc.rs:188:10 | LL | *v.last().expect("passed an empty thing") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/missing_spin_loop.fixed b/tests/ui/missing_spin_loop.fixed index b6520d478be8..03fbf8ccc8a3 100644 --- a/tests/ui/missing_spin_loop.fixed +++ b/tests/ui/missing_spin_loop.fixed @@ -8,16 +8,22 @@ fn main() { let b = AtomicBool::new(true); // Those should lint while b.load(Ordering::Acquire) { std::hint::spin_loop() } + //~^ missing_spin_loop while !b.load(Ordering::SeqCst) { std::hint::spin_loop() } + //~^ missing_spin_loop while b.load(Ordering::Acquire) == false { std::hint::spin_loop() } + //~^ missing_spin_loop while { true == b.load(Ordering::Acquire) } { std::hint::spin_loop() } + //~^ missing_spin_loop while b.compare_exchange(true, false, Ordering::Acquire, Ordering::Relaxed) != Ok(true) { std::hint::spin_loop() } + //~^ missing_spin_loop while Ok(false) != b.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) { std::hint::spin_loop() } + //~^ missing_spin_loop // This is OK, as the body is not empty while b.load(Ordering::Acquire) { diff --git a/tests/ui/missing_spin_loop.rs b/tests/ui/missing_spin_loop.rs index 7b115c66ade6..bf18590b9408 100644 --- a/tests/ui/missing_spin_loop.rs +++ b/tests/ui/missing_spin_loop.rs @@ -8,16 +8,22 @@ fn main() { let b = AtomicBool::new(true); // Those should lint while b.load(Ordering::Acquire) {} + //~^ missing_spin_loop while !b.load(Ordering::SeqCst) {} + //~^ missing_spin_loop while b.load(Ordering::Acquire) == false {} + //~^ missing_spin_loop while { true == b.load(Ordering::Acquire) } {} + //~^ missing_spin_loop while b.compare_exchange(true, false, Ordering::Acquire, Ordering::Relaxed) != Ok(true) {} + //~^ missing_spin_loop while Ok(false) != b.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) {} + //~^ missing_spin_loop // This is OK, as the body is not empty while b.load(Ordering::Acquire) { diff --git a/tests/ui/missing_spin_loop.stderr b/tests/ui/missing_spin_loop.stderr index 12f4b53a3d18..98c32d042346 100644 --- a/tests/ui/missing_spin_loop.stderr +++ b/tests/ui/missing_spin_loop.stderr @@ -8,31 +8,31 @@ LL | while b.load(Ordering::Acquire) {} = help: to override `-D warnings` add `#[allow(clippy::missing_spin_loop)]` error: busy-waiting loop should at least have a spin loop hint - --> tests/ui/missing_spin_loop.rs:12:37 + --> tests/ui/missing_spin_loop.rs:13:37 | LL | while !b.load(Ordering::SeqCst) {} | ^^ help: try: `{ std::hint::spin_loop() }` error: busy-waiting loop should at least have a spin loop hint - --> tests/ui/missing_spin_loop.rs:14:46 + --> tests/ui/missing_spin_loop.rs:16:46 | LL | while b.load(Ordering::Acquire) == false {} | ^^ help: try: `{ std::hint::spin_loop() }` error: busy-waiting loop should at least have a spin loop hint - --> tests/ui/missing_spin_loop.rs:16:49 + --> tests/ui/missing_spin_loop.rs:19:49 | LL | while { true == b.load(Ordering::Acquire) } {} | ^^ help: try: `{ std::hint::spin_loop() }` error: busy-waiting loop should at least have a spin loop hint - --> tests/ui/missing_spin_loop.rs:18:93 + --> tests/ui/missing_spin_loop.rs:22:93 | LL | while b.compare_exchange(true, false, Ordering::Acquire, Ordering::Relaxed) != Ok(true) {} | ^^ help: try: `{ std::hint::spin_loop() }` error: busy-waiting loop should at least have a spin loop hint - --> tests/ui/missing_spin_loop.rs:20:94 + --> tests/ui/missing_spin_loop.rs:25:94 | LL | while Ok(false) != b.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) {} | ^^ help: try: `{ std::hint::spin_loop() }` diff --git a/tests/ui/missing_spin_loop_no_std.fixed b/tests/ui/missing_spin_loop_no_std.fixed index 771ab1ab21a8..a525d414670e 100644 --- a/tests/ui/missing_spin_loop_no_std.fixed +++ b/tests/ui/missing_spin_loop_no_std.fixed @@ -9,5 +9,6 @@ pub fn main(_argc: isize, _argv: *const *const u8) -> isize { let b = AtomicBool::new(true); // This should lint with `core::hint::spin_loop()` while b.load(Ordering::Acquire) { core::hint::spin_loop() } + //~^ missing_spin_loop 0 } diff --git a/tests/ui/missing_spin_loop_no_std.rs b/tests/ui/missing_spin_loop_no_std.rs index bf890fc4066b..3b421f32c34f 100644 --- a/tests/ui/missing_spin_loop_no_std.rs +++ b/tests/ui/missing_spin_loop_no_std.rs @@ -9,5 +9,6 @@ pub fn main(_argc: isize, _argv: *const *const u8) -> isize { let b = AtomicBool::new(true); // This should lint with `core::hint::spin_loop()` while b.load(Ordering::Acquire) {} + //~^ missing_spin_loop 0 } diff --git a/tests/ui/missing_trait_methods.rs b/tests/ui/missing_trait_methods.rs index 55b904bde59a..7af186ba3322 100644 --- a/tests/ui/missing_trait_methods.rs +++ b/tests/ui/missing_trait_methods.rs @@ -20,10 +20,11 @@ trait B { struct Partial; impl A for Partial {} -//~^ ERROR: missing trait method provided by default: `provided` +//~^ missing_trait_methods impl B for Partial { - //~^ ERROR: missing trait method provided by default: `b` + //~^ missing_trait_methods + fn required() {} fn a(_: usize) -> usize { @@ -56,5 +57,8 @@ trait MissingMultiple { } impl MissingMultiple for Partial {} +//~^ missing_trait_methods +//~| missing_trait_methods +//~| missing_trait_methods fn main() {} diff --git a/tests/ui/missing_trait_methods.stderr b/tests/ui/missing_trait_methods.stderr index 9c4968b022d7..d9fb8951ab3d 100644 --- a/tests/ui/missing_trait_methods.stderr +++ b/tests/ui/missing_trait_methods.stderr @@ -25,19 +25,7 @@ LL | fn b<'a, T: AsRef<[u8]>>(a: &'a T) -> &'a [u8] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing trait method provided by default: `one` - --> tests/ui/missing_trait_methods.rs:58:1 - | -LL | impl MissingMultiple for Partial {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: implement the method - --> tests/ui/missing_trait_methods.rs:53:5 - | -LL | fn one() {} - | ^^^^^^^^ - -error: missing trait method provided by default: `two` - --> tests/ui/missing_trait_methods.rs:58:1 + --> tests/ui/missing_trait_methods.rs:59:1 | LL | impl MissingMultiple for Partial {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -45,11 +33,11 @@ LL | impl MissingMultiple for Partial {} help: implement the method --> tests/ui/missing_trait_methods.rs:54:5 | -LL | fn two() {} +LL | fn one() {} | ^^^^^^^^ -error: missing trait method provided by default: `three` - --> tests/ui/missing_trait_methods.rs:58:1 +error: missing trait method provided by default: `two` + --> tests/ui/missing_trait_methods.rs:59:1 | LL | impl MissingMultiple for Partial {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -57,6 +45,18 @@ LL | impl MissingMultiple for Partial {} help: implement the method --> tests/ui/missing_trait_methods.rs:55:5 | +LL | fn two() {} + | ^^^^^^^^ + +error: missing trait method provided by default: `three` + --> tests/ui/missing_trait_methods.rs:59:1 + | +LL | impl MissingMultiple for Partial {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: implement the method + --> tests/ui/missing_trait_methods.rs:56:5 + | LL | fn three() {} | ^^^^^^^^^^ diff --git a/tests/ui/mistyped_literal_suffix.fixed b/tests/ui/mistyped_literal_suffix.fixed index b84b3dc349ec..a0190acc5d4b 100644 --- a/tests/ui/mistyped_literal_suffix.fixed +++ b/tests/ui/mistyped_literal_suffix.fixed @@ -14,35 +14,58 @@ use proc_macros::with_span; fn main() { let fail14 = 2_i32; + //~^ mistyped_literal_suffixes let fail15 = 4_i64; + //~^ mistyped_literal_suffixes let fail16 = 7_i8; // + // + //~^^ mistyped_literal_suffixes let fail17 = 23_i16; // + // + //~^^ mistyped_literal_suffixes let ok18 = 23_128; let fail20 = 2_i8; // + // + //~^^ mistyped_literal_suffixes let fail21 = 4_i16; // + // + //~^^ mistyped_literal_suffixes let ok24 = 12.34_64; let fail25 = 1E2_f32; + //~^ mistyped_literal_suffixes let fail26 = 43E7_f64; + //~^ mistyped_literal_suffixes let fail27 = 243E17_f32; + //~^ mistyped_literal_suffixes let fail28 = 241_251_235E723_f64; + //~^ mistyped_literal_suffixes let ok29 = 42279.911_32; // testing that the suggestion actually fits in its type let fail30 = 127_i8; // should be i8 + // + //~^^ mistyped_literal_suffixes let fail31 = 240_u8; // should be u8 + // + //~^^ mistyped_literal_suffixes let ok32 = 360_8; // doesn't fit in either, should be ignored let fail33 = 0x1234_i16; + //~^ mistyped_literal_suffixes let fail34 = 0xABCD_u16; + //~^ mistyped_literal_suffixes let ok35 = 0x12345_16; let fail36 = 0xFFFF_FFFF_FFFF_FFFF_u64; // u64 + // + //~^^ mistyped_literal_suffixes // issue #6129 let ok37 = 123_32.123; let ok38 = 124_64.0; let _ = 1.123_45E1_f32; + //~^ mistyped_literal_suffixes let _ = with_span!(1 2_u32); } diff --git a/tests/ui/mistyped_literal_suffix.rs b/tests/ui/mistyped_literal_suffix.rs index a47a736067a8..12a26204e755 100644 --- a/tests/ui/mistyped_literal_suffix.rs +++ b/tests/ui/mistyped_literal_suffix.rs @@ -14,35 +14,58 @@ use proc_macros::with_span; fn main() { let fail14 = 2_32; + //~^ mistyped_literal_suffixes let fail15 = 4_64; + //~^ mistyped_literal_suffixes let fail16 = 7_8; // + // + //~^^ mistyped_literal_suffixes let fail17 = 23_16; // + // + //~^^ mistyped_literal_suffixes let ok18 = 23_128; let fail20 = 2__8; // + // + //~^^ mistyped_literal_suffixes let fail21 = 4___16; // + // + //~^^ mistyped_literal_suffixes let ok24 = 12.34_64; let fail25 = 1E2_32; + //~^ mistyped_literal_suffixes let fail26 = 43E7_64; + //~^ mistyped_literal_suffixes let fail27 = 243E17_32; + //~^ mistyped_literal_suffixes let fail28 = 241251235E723_64; + //~^ mistyped_literal_suffixes let ok29 = 42279.911_32; // testing that the suggestion actually fits in its type let fail30 = 127_8; // should be i8 + // + //~^^ mistyped_literal_suffixes let fail31 = 240_8; // should be u8 + // + //~^^ mistyped_literal_suffixes let ok32 = 360_8; // doesn't fit in either, should be ignored let fail33 = 0x1234_16; + //~^ mistyped_literal_suffixes let fail34 = 0xABCD_16; + //~^ mistyped_literal_suffixes let ok35 = 0x12345_16; let fail36 = 0xFFFF_FFFF_FFFF_FFFF_64; // u64 + // + //~^^ mistyped_literal_suffixes // issue #6129 let ok37 = 123_32.123; let ok38 = 124_64.0; let _ = 1.12345E1_32; + //~^ mistyped_literal_suffixes let _ = with_span!(1 2_u32); } diff --git a/tests/ui/mistyped_literal_suffix.stderr b/tests/ui/mistyped_literal_suffix.stderr index 56bfb06d8e66..9c6b2fab21c3 100644 --- a/tests/ui/mistyped_literal_suffix.stderr +++ b/tests/ui/mistyped_literal_suffix.stderr @@ -7,91 +7,91 @@ LL | let fail14 = 2_32; = note: `#[deny(clippy::mistyped_literal_suffixes)]` on by default error: mistyped literal suffix - --> tests/ui/mistyped_literal_suffix.rs:17:18 + --> tests/ui/mistyped_literal_suffix.rs:18:18 | LL | let fail15 = 4_64; | ^^^^ help: did you mean to write: `4_i64` error: mistyped literal suffix - --> tests/ui/mistyped_literal_suffix.rs:18:18 + --> tests/ui/mistyped_literal_suffix.rs:20:18 | LL | let fail16 = 7_8; // | ^^^ help: did you mean to write: `7_i8` error: mistyped literal suffix - --> tests/ui/mistyped_literal_suffix.rs:19:18 + --> tests/ui/mistyped_literal_suffix.rs:23:18 | LL | let fail17 = 23_16; // | ^^^^^ help: did you mean to write: `23_i16` error: mistyped literal suffix - --> tests/ui/mistyped_literal_suffix.rs:22:18 + --> tests/ui/mistyped_literal_suffix.rs:28:18 | LL | let fail20 = 2__8; // | ^^^^ help: did you mean to write: `2_i8` error: mistyped literal suffix - --> tests/ui/mistyped_literal_suffix.rs:23:18 + --> tests/ui/mistyped_literal_suffix.rs:31:18 | LL | let fail21 = 4___16; // | ^^^^^^ help: did you mean to write: `4_i16` error: mistyped literal suffix - --> tests/ui/mistyped_literal_suffix.rs:26:18 + --> tests/ui/mistyped_literal_suffix.rs:36:18 | LL | let fail25 = 1E2_32; | ^^^^^^ help: did you mean to write: `1E2_f32` error: mistyped literal suffix - --> tests/ui/mistyped_literal_suffix.rs:27:18 + --> tests/ui/mistyped_literal_suffix.rs:38:18 | LL | let fail26 = 43E7_64; | ^^^^^^^ help: did you mean to write: `43E7_f64` error: mistyped literal suffix - --> tests/ui/mistyped_literal_suffix.rs:28:18 + --> tests/ui/mistyped_literal_suffix.rs:40:18 | LL | let fail27 = 243E17_32; | ^^^^^^^^^ help: did you mean to write: `243E17_f32` error: mistyped literal suffix - --> tests/ui/mistyped_literal_suffix.rs:29:18 + --> tests/ui/mistyped_literal_suffix.rs:42:18 | LL | let fail28 = 241251235E723_64; | ^^^^^^^^^^^^^^^^ help: did you mean to write: `241_251_235E723_f64` error: mistyped literal suffix - --> tests/ui/mistyped_literal_suffix.rs:33:18 + --> tests/ui/mistyped_literal_suffix.rs:47:18 | LL | let fail30 = 127_8; // should be i8 | ^^^^^ help: did you mean to write: `127_i8` error: mistyped literal suffix - --> tests/ui/mistyped_literal_suffix.rs:34:18 + --> tests/ui/mistyped_literal_suffix.rs:50:18 | LL | let fail31 = 240_8; // should be u8 | ^^^^^ help: did you mean to write: `240_u8` error: mistyped literal suffix - --> tests/ui/mistyped_literal_suffix.rs:36:18 + --> tests/ui/mistyped_literal_suffix.rs:54:18 | LL | let fail33 = 0x1234_16; | ^^^^^^^^^ help: did you mean to write: `0x1234_i16` error: mistyped literal suffix - --> tests/ui/mistyped_literal_suffix.rs:37:18 + --> tests/ui/mistyped_literal_suffix.rs:56:18 | LL | let fail34 = 0xABCD_16; | ^^^^^^^^^ help: did you mean to write: `0xABCD_u16` error: mistyped literal suffix - --> tests/ui/mistyped_literal_suffix.rs:39:18 + --> tests/ui/mistyped_literal_suffix.rs:59:18 | LL | let fail36 = 0xFFFF_FFFF_FFFF_FFFF_64; // u64 | ^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean to write: `0xFFFF_FFFF_FFFF_FFFF_u64` error: mistyped literal suffix - --> tests/ui/mistyped_literal_suffix.rs:45:13 + --> tests/ui/mistyped_literal_suffix.rs:67:13 | LL | let _ = 1.12345E1_32; | ^^^^^^^^^^^^ help: did you mean to write: `1.123_45E1_f32` diff --git a/tests/ui/mixed_attributes_style/auxiliary/submodule.rs b/tests/ui/mixed_attributes_style/auxiliary/submodule.rs index df44b07a6941..43d22940415f 100644 --- a/tests/ui/mixed_attributes_style/auxiliary/submodule.rs +++ b/tests/ui/mixed_attributes_style/auxiliary/submodule.rs @@ -3,7 +3,6 @@ #![allow(dead_code)] #[allow(unused)] -//~^ ERROR: item has both inner and outer attributes mod foo { #![allow(dead_code)] } diff --git a/tests/ui/mixed_attributes_style/global_allow.rs b/tests/ui/mixed_attributes_style/global_allow.rs index 153262e65570..19a45e720a60 100644 --- a/tests/ui/mixed_attributes_style/global_allow.rs +++ b/tests/ui/mixed_attributes_style/global_allow.rs @@ -1,4 +1,5 @@ -// issue 12436 +// https://github.com/rust-lang/rust-clippy/issues/12436 +//@check-pass #![allow(clippy::mixed_attributes_style)] #[path = "auxiliary/submodule.rs"] diff --git a/tests/ui/mixed_attributes_style/mod_declaration.rs b/tests/ui/mixed_attributes_style/mod_declaration.rs index b0f1f0bda9e6..8cef6a80048a 100644 --- a/tests/ui/mixed_attributes_style/mod_declaration.rs +++ b/tests/ui/mixed_attributes_style/mod_declaration.rs @@ -1,3 +1,5 @@ +//@error-in-other-file: item has both inner and outer attributes +//@no-rustfix #[path = "auxiliary/submodule.rs"] // don't lint. /// This doc comment should not lint, it could be used to add context to the original module doc mod submodule; diff --git a/tests/ui/mixed_attributes_style/mod_declaration.stderr b/tests/ui/mixed_attributes_style/mod_declaration.stderr index 968c537c7e44..1239742a05b7 100644 --- a/tests/ui/mixed_attributes_style/mod_declaration.stderr +++ b/tests/ui/mixed_attributes_style/mod_declaration.stderr @@ -2,7 +2,6 @@ error: item has both inner and outer attributes --> tests/ui/mixed_attributes_style/auxiliary/submodule.rs:5:1 | LL | / #[allow(unused)] -LL | | LL | | mod foo { LL | | #![allow(dead_code)] | |________________________^ diff --git a/tests/ui/mixed_read_write_in_expression.rs b/tests/ui/mixed_read_write_in_expression.rs index 241536abdfbd..2ead166bf801 100644 --- a/tests/ui/mixed_read_write_in_expression.rs +++ b/tests/ui/mixed_read_write_in_expression.rs @@ -12,11 +12,12 @@ fn main() { x = 1; 1 } + x; - //~^ ERROR: unsequenced read of `x` + //~^ mixed_read_write_in_expression // Example from iss#277 x += { - //~^ ERROR: unsequenced read of `x` + //~^ mixed_read_write_in_expression + x = 20; 2 }; @@ -30,7 +31,7 @@ fn main() { let base = Foo { a: 4, b: 5 }; let foo = Foo { a: x, - //~^ ERROR: unsequenced read of `x` + //~^ mixed_read_write_in_expression ..{ x = 6; base @@ -40,7 +41,8 @@ fn main() { let closure = || { let mut x = 0; x += { - //~^ ERROR: unsequenced read of `x` + //~^ mixed_read_write_in_expression + x = 20; 2 }; diff --git a/tests/ui/mixed_read_write_in_expression.stderr b/tests/ui/mixed_read_write_in_expression.stderr index 796d4ccd26b7..e34dce2bb132 100644 --- a/tests/ui/mixed_read_write_in_expression.stderr +++ b/tests/ui/mixed_read_write_in_expression.stderr @@ -19,31 +19,31 @@ LL | x += { | ^ | note: whether read occurs before this write depends on evaluation order - --> tests/ui/mixed_read_write_in_expression.rs:20:9 + --> tests/ui/mixed_read_write_in_expression.rs:21:9 | LL | x = 20; | ^^^^^^ error: unsequenced read of `x` - --> tests/ui/mixed_read_write_in_expression.rs:32:12 + --> tests/ui/mixed_read_write_in_expression.rs:33:12 | LL | a: x, | ^ | note: whether read occurs before this write depends on evaluation order - --> tests/ui/mixed_read_write_in_expression.rs:35:13 + --> tests/ui/mixed_read_write_in_expression.rs:36:13 | LL | x = 6; | ^^^^^ error: unsequenced read of `x` - --> tests/ui/mixed_read_write_in_expression.rs:42:9 + --> tests/ui/mixed_read_write_in_expression.rs:43:9 | LL | x += { | ^ | note: whether read occurs before this write depends on evaluation order - --> tests/ui/mixed_read_write_in_expression.rs:44:13 + --> tests/ui/mixed_read_write_in_expression.rs:46:13 | LL | x = 20; | ^^^^^^ diff --git a/tests/ui/module_inception.rs b/tests/ui/module_inception.rs index ad46e0c29aee..15b7fb877770 100644 --- a/tests/ui/module_inception.rs +++ b/tests/ui/module_inception.rs @@ -3,14 +3,15 @@ pub mod foo2 { pub mod bar2 { pub mod bar2 { - //~^ ERROR: module has the same name as its containing module - //~| NOTE: `-D clippy::module-inception` implied by `-D warnings` + //~^ module_inception + pub mod foo2 {} } pub mod foo2 {} } pub mod foo2 { - //~^ ERROR: module has the same name as its containing module + //~^ module_inception + pub mod bar2 {} } } @@ -18,13 +19,15 @@ pub mod foo2 { mod foo { mod bar { mod bar { - //~^ ERROR: module has the same name as its containing module + //~^ module_inception + mod foo {} } mod foo {} } mod foo { - //~^ ERROR: module has the same name as its containing module + //~^ module_inception + mod bar {} } } diff --git a/tests/ui/module_inception.stderr b/tests/ui/module_inception.stderr index 455f5372747a..8e7d555cebc6 100644 --- a/tests/ui/module_inception.stderr +++ b/tests/ui/module_inception.stderr @@ -16,24 +16,27 @@ error: module has the same name as its containing module | LL | / pub mod foo2 { LL | | +LL | | LL | | pub mod bar2 {} LL | | } | |_____^ error: module has the same name as its containing module - --> tests/ui/module_inception.rs:20:9 + --> tests/ui/module_inception.rs:21:9 | LL | / mod bar { LL | | +LL | | LL | | mod foo {} LL | | } | |_________^ error: module has the same name as its containing module - --> tests/ui/module_inception.rs:26:5 + --> tests/ui/module_inception.rs:28:5 | LL | / mod foo { LL | | +LL | | LL | | mod bar {} LL | | } | |_____^ diff --git a/tests/ui/module_name_repetitions.rs b/tests/ui/module_name_repetitions.rs index 71d8ac7a1f0e..2fde98d7927c 100644 --- a/tests/ui/module_name_repetitions.rs +++ b/tests/ui/module_name_repetitions.rs @@ -6,16 +6,19 @@ pub mod foo { pub fn foo() {} pub fn foo_bar() {} - //~^ ERROR: item name starts with its containing module's name - //~| NOTE: `-D clippy::module-name-repetitions` implied by `-D warnings` + //~^ module_name_repetitions + pub fn bar_foo() {} - //~^ ERROR: item name ends with its containing module's name + //~^ module_name_repetitions + pub struct FooCake; - //~^ ERROR: item name starts with its containing module's name + //~^ module_name_repetitions + pub enum CakeFoo {} - //~^ ERROR: item name ends with its containing module's name + //~^ module_name_repetitions + pub struct Foo7Bar; - //~^ ERROR: item name starts with its containing module's name + //~^ module_name_repetitions // Should not warn pub struct Foobar; @@ -28,7 +31,7 @@ pub mod foo { pub use error::Error; // ... but should still warn when the item is reexported to create a *public* path with repetition. pub use error::FooError; - //~^ ERROR: item name starts with its containing module's name + //~^ module_name_repetitions // FIXME: This should also warn because it creates the public path `foo::FooIter`. mod iter { diff --git a/tests/ui/module_name_repetitions.stderr b/tests/ui/module_name_repetitions.stderr index 8fd8b3948753..9000c44a3902 100644 --- a/tests/ui/module_name_repetitions.stderr +++ b/tests/ui/module_name_repetitions.stderr @@ -14,25 +14,25 @@ LL | pub fn bar_foo() {} | ^^^^^^^ error: item name starts with its containing module's name - --> tests/ui/module_name_repetitions.rs:13:16 + --> tests/ui/module_name_repetitions.rs:14:16 | LL | pub struct FooCake; | ^^^^^^^ error: item name ends with its containing module's name - --> tests/ui/module_name_repetitions.rs:15:14 + --> tests/ui/module_name_repetitions.rs:17:14 | LL | pub enum CakeFoo {} | ^^^^^^^ error: item name starts with its containing module's name - --> tests/ui/module_name_repetitions.rs:17:16 + --> tests/ui/module_name_repetitions.rs:20:16 | LL | pub struct Foo7Bar; | ^^^^^^^ error: item name starts with its containing module's name - --> tests/ui/module_name_repetitions.rs:30:20 + --> tests/ui/module_name_repetitions.rs:33:20 | LL | pub use error::FooError; | ^^^^^^^^ diff --git a/tests/ui/modulo_arithmetic_float.rs b/tests/ui/modulo_arithmetic_float.rs index a5b63bed531b..0e08174f686e 100644 --- a/tests/ui/modulo_arithmetic_float.rs +++ b/tests/ui/modulo_arithmetic_float.rs @@ -6,67 +6,62 @@ fn main() { // Lint when both sides are const and of the opposite sign -1.6 % 2.1; - //~^ ERROR: you are using modulo operator on constants with different signs: `-1.600 % - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + 1.6 % -2.1; - //~^ ERROR: you are using modulo operator on constants with different signs: `1.600 % - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + (1.1 - 2.3) % (1.1 + 2.3); - //~^ ERROR: you are using modulo operator on constants with different signs: `-1.200 % - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + (1.1 + 2.3) % (1.1 - 2.3); - //~^ ERROR: you are using modulo operator on constants with different signs: `3.400 % - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic // Lint on floating point numbers let a_f16: f16 = -1.6; let mut b_f16: f16 = 2.1; a_f16 % b_f16; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + b_f16 % a_f16; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + b_f16 %= a_f16; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic // Lint on floating point numbers let a_f32: f32 = -1.6; let mut b_f32: f32 = 2.1; a_f32 % b_f32; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + b_f32 % a_f32; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + b_f32 %= a_f32; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic let a_f64: f64 = -1.6; let mut b_f64: f64 = 2.1; a_f64 % b_f64; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + b_f64 % a_f64; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + b_f64 %= a_f64; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic let a_f128: f128 = -1.6; let mut b_f128: f128 = 2.1; a_f128 % b_f128; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + b_f128 % a_f128; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + b_f128 %= a_f128; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic // No lint when both sides are const and of the same sign 1.6 % 2.1; diff --git a/tests/ui/modulo_arithmetic_float.stderr b/tests/ui/modulo_arithmetic_float.stderr index 2b4937552bda..91b5c80ce9f4 100644 --- a/tests/ui/modulo_arithmetic_float.stderr +++ b/tests/ui/modulo_arithmetic_float.stderr @@ -33,7 +33,7 @@ LL | (1.1 + 2.3) % (1.1 - 2.3); = note: double check for expected result especially when interoperating with different languages error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_float.rs:24:5 + --> tests/ui/modulo_arithmetic_float.rs:23:5 | LL | a_f16 % b_f16; | ^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | a_f16 % b_f16; = note: double check for expected result especially when interoperating with different languages error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_float.rs:27:5 + --> tests/ui/modulo_arithmetic_float.rs:26:5 | LL | b_f16 % a_f16; | ^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | b_f16 % a_f16; = note: double check for expected result especially when interoperating with different languages error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_float.rs:30:5 + --> tests/ui/modulo_arithmetic_float.rs:29:5 | LL | b_f16 %= a_f16; | ^^^^^^^^^^^^^^ @@ -57,7 +57,7 @@ LL | b_f16 %= a_f16; = note: double check for expected result especially when interoperating with different languages error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_float.rs:37:5 + --> tests/ui/modulo_arithmetic_float.rs:35:5 | LL | a_f32 % b_f32; | ^^^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | a_f32 % b_f32; = note: double check for expected result especially when interoperating with different languages error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_float.rs:40:5 + --> tests/ui/modulo_arithmetic_float.rs:38:5 | LL | b_f32 % a_f32; | ^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | b_f32 % a_f32; = note: double check for expected result especially when interoperating with different languages error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_float.rs:43:5 + --> tests/ui/modulo_arithmetic_float.rs:41:5 | LL | b_f32 %= a_f32; | ^^^^^^^^^^^^^^ @@ -81,7 +81,7 @@ LL | b_f32 %= a_f32; = note: double check for expected result especially when interoperating with different languages error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_float.rs:49:5 + --> tests/ui/modulo_arithmetic_float.rs:46:5 | LL | a_f64 % b_f64; | ^^^^^^^^^^^^^ @@ -89,7 +89,7 @@ LL | a_f64 % b_f64; = note: double check for expected result especially when interoperating with different languages error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_float.rs:52:5 + --> tests/ui/modulo_arithmetic_float.rs:49:5 | LL | b_f64 % a_f64; | ^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL | b_f64 % a_f64; = note: double check for expected result especially when interoperating with different languages error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_float.rs:55:5 + --> tests/ui/modulo_arithmetic_float.rs:52:5 | LL | b_f64 %= a_f64; | ^^^^^^^^^^^^^^ @@ -105,7 +105,7 @@ LL | b_f64 %= a_f64; = note: double check for expected result especially when interoperating with different languages error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_float.rs:61:5 + --> tests/ui/modulo_arithmetic_float.rs:57:5 | LL | a_f128 % b_f128; | ^^^^^^^^^^^^^^^ @@ -113,7 +113,7 @@ LL | a_f128 % b_f128; = note: double check for expected result especially when interoperating with different languages error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_float.rs:64:5 + --> tests/ui/modulo_arithmetic_float.rs:60:5 | LL | b_f128 % a_f128; | ^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL | b_f128 % a_f128; = note: double check for expected result especially when interoperating with different languages error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_float.rs:67:5 + --> tests/ui/modulo_arithmetic_float.rs:63:5 | LL | b_f128 %= a_f128; | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/modulo_arithmetic_integral.rs b/tests/ui/modulo_arithmetic_integral.rs index c427b8580e17..d7cd910e43cb 100644 --- a/tests/ui/modulo_arithmetic_integral.rs +++ b/tests/ui/modulo_arithmetic_integral.rs @@ -6,77 +6,69 @@ fn main() { let a = -1; let mut b = 2; a % b; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + b % a; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + b %= a; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic let a_i8: i8 = 1; let mut b_i8: i8 = 2; a_i8 % b_i8; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + b_i8 %= a_i8; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic let a_i16: i16 = 1; let mut b_i16: i16 = 2; a_i16 % b_i16; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + b_i16 %= a_i16; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic let a_i32: i32 = 1; let mut b_i32: i32 = 2; a_i32 % b_i32; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + b_i32 %= a_i32; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic let a_i64: i64 = 1; let mut b_i64: i64 = 2; a_i64 % b_i64; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + b_i64 %= a_i64; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic let a_i128: i128 = 1; let mut b_i128: i128 = 2; a_i128 % b_i128; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + b_i128 %= a_i128; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic let a_isize: isize = 1; let mut b_isize: isize = 2; a_isize % b_isize; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + b_isize %= a_isize; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic let a = 1; let mut b = 2; a % b; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + b %= a; - //~^ ERROR: you are using modulo operator on types that might have different signs - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic // No lint on unsigned integral value let a_u8: u8 = 17; diff --git a/tests/ui/modulo_arithmetic_integral.stderr b/tests/ui/modulo_arithmetic_integral.stderr index f1cfe791a03b..d1b71cdab5e4 100644 --- a/tests/ui/modulo_arithmetic_integral.stderr +++ b/tests/ui/modulo_arithmetic_integral.stderr @@ -28,7 +28,7 @@ LL | b %= a; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_integral.rs:20:5 + --> tests/ui/modulo_arithmetic_integral.rs:19:5 | LL | a_i8 % b_i8; | ^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL | a_i8 % b_i8; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_integral.rs:23:5 + --> tests/ui/modulo_arithmetic_integral.rs:22:5 | LL | b_i8 %= a_i8; | ^^^^^^^^^^^^ @@ -46,7 +46,7 @@ LL | b_i8 %= a_i8; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_integral.rs:29:5 + --> tests/ui/modulo_arithmetic_integral.rs:27:5 | LL | a_i16 % b_i16; | ^^^^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | a_i16 % b_i16; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_integral.rs:32:5 + --> tests/ui/modulo_arithmetic_integral.rs:30:5 | LL | b_i16 %= a_i16; | ^^^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | b_i16 %= a_i16; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_integral.rs:38:5 + --> tests/ui/modulo_arithmetic_integral.rs:35:5 | LL | a_i32 % b_i32; | ^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | a_i32 % b_i32; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_integral.rs:41:5 + --> tests/ui/modulo_arithmetic_integral.rs:38:5 | LL | b_i32 %= a_i32; | ^^^^^^^^^^^^^^ @@ -82,7 +82,7 @@ LL | b_i32 %= a_i32; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_integral.rs:47:5 + --> tests/ui/modulo_arithmetic_integral.rs:43:5 | LL | a_i64 % b_i64; | ^^^^^^^^^^^^^ @@ -91,7 +91,7 @@ LL | a_i64 % b_i64; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_integral.rs:50:5 + --> tests/ui/modulo_arithmetic_integral.rs:46:5 | LL | b_i64 %= a_i64; | ^^^^^^^^^^^^^^ @@ -100,7 +100,7 @@ LL | b_i64 %= a_i64; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_integral.rs:56:5 + --> tests/ui/modulo_arithmetic_integral.rs:51:5 | LL | a_i128 % b_i128; | ^^^^^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL | a_i128 % b_i128; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_integral.rs:59:5 + --> tests/ui/modulo_arithmetic_integral.rs:54:5 | LL | b_i128 %= a_i128; | ^^^^^^^^^^^^^^^^ @@ -118,7 +118,7 @@ LL | b_i128 %= a_i128; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_integral.rs:65:5 + --> tests/ui/modulo_arithmetic_integral.rs:59:5 | LL | a_isize % b_isize; | ^^^^^^^^^^^^^^^^^ @@ -127,7 +127,7 @@ LL | a_isize % b_isize; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_integral.rs:68:5 + --> tests/ui/modulo_arithmetic_integral.rs:62:5 | LL | b_isize %= a_isize; | ^^^^^^^^^^^^^^^^^^ @@ -136,7 +136,7 @@ LL | b_isize %= a_isize; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_integral.rs:74:5 + --> tests/ui/modulo_arithmetic_integral.rs:67:5 | LL | a % b; | ^^^^^ @@ -145,7 +145,7 @@ LL | a % b; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on types that might have different signs - --> tests/ui/modulo_arithmetic_integral.rs:77:5 + --> tests/ui/modulo_arithmetic_integral.rs:70:5 | LL | b %= a; | ^^^^^^ diff --git a/tests/ui/modulo_arithmetic_integral_const.rs b/tests/ui/modulo_arithmetic_integral_const.rs index dbc679a69825..9f5fb697df0e 100644 --- a/tests/ui/modulo_arithmetic_integral_const.rs +++ b/tests/ui/modulo_arithmetic_integral_const.rs @@ -9,57 +9,55 @@ fn main() { // Lint when both sides are const and of the opposite sign -1 % 2; - //~^ ERROR: you are using modulo operator on constants with different signs: `-1 % 2` - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + 1 % -2; - //~^ ERROR: you are using modulo operator on constants with different signs: `1 % -2` - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + (1 - 2) % (1 + 2); - //~^ ERROR: you are using modulo operator on constants with different signs: `-1 % 3` - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + (1 + 2) % (1 - 2); - //~^ ERROR: you are using modulo operator on constants with different signs: `3 % -1` - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + 35 * (7 - 4 * 2) % (-500 * -600); - //~^ ERROR: you are using modulo operator on constants with different signs: `-35 % 30 - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic -1i8 % 2i8; - //~^ ERROR: you are using modulo operator on constants with different signs: `-1 % 2` - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + 1i8 % -2i8; - //~^ ERROR: you are using modulo operator on constants with different signs: `1 % -2` - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + -1i16 % 2i16; - //~^ ERROR: you are using modulo operator on constants with different signs: `-1 % 2` - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + 1i16 % -2i16; - //~^ ERROR: you are using modulo operator on constants with different signs: `1 % -2` - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + -1i32 % 2i32; - //~^ ERROR: you are using modulo operator on constants with different signs: `-1 % 2` - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + 1i32 % -2i32; - //~^ ERROR: you are using modulo operator on constants with different signs: `1 % -2` - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + -1i64 % 2i64; - //~^ ERROR: you are using modulo operator on constants with different signs: `-1 % 2` - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + 1i64 % -2i64; - //~^ ERROR: you are using modulo operator on constants with different signs: `1 % -2` - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + -1i128 % 2i128; - //~^ ERROR: you are using modulo operator on constants with different signs: `-1 % 2` - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + 1i128 % -2i128; - //~^ ERROR: you are using modulo operator on constants with different signs: `1 % -2` - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + -1isize % 2isize; - //~^ ERROR: you are using modulo operator on constants with different signs: `-1 % 2` - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic + 1isize % -2isize; - //~^ ERROR: you are using modulo operator on constants with different signs: `1 % -2` - //~| NOTE: double check for expected result especially when interoperating with differ + //~^ modulo_arithmetic // No lint when both sides are const and of the same sign 1 % 2; diff --git a/tests/ui/modulo_arithmetic_integral_const.stderr b/tests/ui/modulo_arithmetic_integral_const.stderr index 722d9b83660e..12edee8cf425 100644 --- a/tests/ui/modulo_arithmetic_integral_const.stderr +++ b/tests/ui/modulo_arithmetic_integral_const.stderr @@ -46,7 +46,7 @@ LL | 35 * (7 - 4 * 2) % (-500 * -600); = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `-1 % 2` - --> tests/ui/modulo_arithmetic_integral_const.rs:27:5 + --> tests/ui/modulo_arithmetic_integral_const.rs:26:5 | LL | -1i8 % 2i8; | ^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | -1i8 % 2i8; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `1 % -2` - --> tests/ui/modulo_arithmetic_integral_const.rs:30:5 + --> tests/ui/modulo_arithmetic_integral_const.rs:29:5 | LL | 1i8 % -2i8; | ^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | 1i8 % -2i8; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `-1 % 2` - --> tests/ui/modulo_arithmetic_integral_const.rs:33:5 + --> tests/ui/modulo_arithmetic_integral_const.rs:32:5 | LL | -1i16 % 2i16; | ^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | -1i16 % 2i16; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `1 % -2` - --> tests/ui/modulo_arithmetic_integral_const.rs:36:5 + --> tests/ui/modulo_arithmetic_integral_const.rs:35:5 | LL | 1i16 % -2i16; | ^^^^^^^^^^^^ @@ -82,7 +82,7 @@ LL | 1i16 % -2i16; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `-1 % 2` - --> tests/ui/modulo_arithmetic_integral_const.rs:39:5 + --> tests/ui/modulo_arithmetic_integral_const.rs:38:5 | LL | -1i32 % 2i32; | ^^^^^^^^^^^^ @@ -91,7 +91,7 @@ LL | -1i32 % 2i32; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `1 % -2` - --> tests/ui/modulo_arithmetic_integral_const.rs:42:5 + --> tests/ui/modulo_arithmetic_integral_const.rs:41:5 | LL | 1i32 % -2i32; | ^^^^^^^^^^^^ @@ -100,7 +100,7 @@ LL | 1i32 % -2i32; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `-1 % 2` - --> tests/ui/modulo_arithmetic_integral_const.rs:45:5 + --> tests/ui/modulo_arithmetic_integral_const.rs:44:5 | LL | -1i64 % 2i64; | ^^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL | -1i64 % 2i64; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `1 % -2` - --> tests/ui/modulo_arithmetic_integral_const.rs:48:5 + --> tests/ui/modulo_arithmetic_integral_const.rs:47:5 | LL | 1i64 % -2i64; | ^^^^^^^^^^^^ @@ -118,7 +118,7 @@ LL | 1i64 % -2i64; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `-1 % 2` - --> tests/ui/modulo_arithmetic_integral_const.rs:51:5 + --> tests/ui/modulo_arithmetic_integral_const.rs:50:5 | LL | -1i128 % 2i128; | ^^^^^^^^^^^^^^ @@ -127,7 +127,7 @@ LL | -1i128 % 2i128; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `1 % -2` - --> tests/ui/modulo_arithmetic_integral_const.rs:54:5 + --> tests/ui/modulo_arithmetic_integral_const.rs:53:5 | LL | 1i128 % -2i128; | ^^^^^^^^^^^^^^ @@ -136,7 +136,7 @@ LL | 1i128 % -2i128; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `-1 % 2` - --> tests/ui/modulo_arithmetic_integral_const.rs:57:5 + --> tests/ui/modulo_arithmetic_integral_const.rs:56:5 | LL | -1isize % 2isize; | ^^^^^^^^^^^^^^^^ @@ -145,7 +145,7 @@ LL | -1isize % 2isize; = note: or consider using `rem_euclid` or similar function error: you are using modulo operator on constants with different signs: `1 % -2` - --> tests/ui/modulo_arithmetic_integral_const.rs:60:5 + --> tests/ui/modulo_arithmetic_integral_const.rs:59:5 | LL | 1isize % -2isize; | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/modulo_one.rs b/tests/ui/modulo_one.rs index c332a15f1577..63ae61059cb8 100644 --- a/tests/ui/modulo_one.rs +++ b/tests/ui/modulo_one.rs @@ -1,4 +1,5 @@ #![warn(clippy::modulo_one)] +#![allow(unconditional_panic)] #![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::identity_op)] static STATIC_ONE: usize = 2 - 1; @@ -6,33 +7,34 @@ static STATIC_NEG_ONE: i64 = 1 - 2; fn main() { 10 % 1; - //~^ ERROR: any number modulo 1 will be 0 - //~| NOTE: `-D clippy::modulo-one` implied by `-D warnings` + //~^ modulo_one + 10 % -1; - //~^ ERROR: any number modulo -1 will panic/overflow or result in 0 + //~^ modulo_one + 10 % 2; // also caught by rustc i32::MIN % (-1); - //~^ ERROR: this operation will panic at runtime - //~| NOTE: `#[deny(unconditional_panic)]` on by default - //~| ERROR: any number modulo -1 will panic/overflow or result in 0 + //~^ modulo_one const ONE: u32 = 1 * 1; const NEG_ONE: i64 = 1 - 2; const INT_MIN: i64 = i64::MIN; 2 % ONE; - //~^ ERROR: any number modulo 1 will be 0 + //~^ modulo_one + // NOT caught by lint 5 % STATIC_ONE; 2 % NEG_ONE; - //~^ ERROR: any number modulo -1 will panic/overflow or result in 0 + //~^ modulo_one + // NOT caught by lint 5 % STATIC_NEG_ONE; // also caught by rustc INT_MIN % NEG_ONE; - //~^ ERROR: this operation will panic at runtime - //~| ERROR: any number modulo -1 will panic/overflow or result in 0 + //~^ modulo_one + // Not caught by lint, we don't look into static items, even if entirely immutable. INT_MIN % STATIC_NEG_ONE; } diff --git a/tests/ui/modulo_one.stderr b/tests/ui/modulo_one.stderr index aedcf24eae71..1c9c79d1c621 100644 --- a/tests/ui/modulo_one.stderr +++ b/tests/ui/modulo_one.stderr @@ -1,19 +1,5 @@ -error: this operation will panic at runtime - --> tests/ui/modulo_one.rs:15:5 - | -LL | i32::MIN % (-1); - | ^^^^^^^^^^^^^^^ attempt to compute `i32::MIN % -1_i32`, which would overflow - | - = note: `#[deny(unconditional_panic)]` on by default - -error: this operation will panic at runtime - --> tests/ui/modulo_one.rs:33:5 - | -LL | INT_MIN % NEG_ONE; - | ^^^^^^^^^^^^^^^^^ attempt to compute `i64::MIN % -1_i64`, which would overflow - error: any number modulo 1 will be 0 - --> tests/ui/modulo_one.rs:8:5 + --> tests/ui/modulo_one.rs:9:5 | LL | 10 % 1; | ^^^^^^ @@ -22,13 +8,13 @@ LL | 10 % 1; = help: to override `-D warnings` add `#[allow(clippy::modulo_one)]` error: any number modulo -1 will panic/overflow or result in 0 - --> tests/ui/modulo_one.rs:11:5 + --> tests/ui/modulo_one.rs:12:5 | LL | 10 % -1; | ^^^^^^^ error: any number modulo -1 will panic/overflow or result in 0 - --> tests/ui/modulo_one.rs:15:5 + --> tests/ui/modulo_one.rs:17:5 | LL | i32::MIN % (-1); | ^^^^^^^^^^^^^^^ @@ -40,16 +26,16 @@ LL | 2 % ONE; | ^^^^^^^ error: any number modulo -1 will panic/overflow or result in 0 - --> tests/ui/modulo_one.rs:28:5 + --> tests/ui/modulo_one.rs:29:5 | LL | 2 % NEG_ONE; | ^^^^^^^^^^^ error: any number modulo -1 will panic/overflow or result in 0 - --> tests/ui/modulo_one.rs:33:5 + --> tests/ui/modulo_one.rs:35:5 | LL | INT_MIN % NEG_ONE; | ^^^^^^^^^^^^^^^^^ -error: aborting due to 8 previous errors +error: aborting due to 6 previous errors diff --git a/tests/ui/msrv_attributes_without_early_lints.rs b/tests/ui/msrv_attributes_without_early_lints.rs new file mode 100644 index 000000000000..dcef1a485fce --- /dev/null +++ b/tests/ui/msrv_attributes_without_early_lints.rs @@ -0,0 +1,14 @@ +//@check-pass + +#![allow(clippy::all, clippy::pedantic, clippy::restriction, clippy::nursery)] +#![forbid(clippy::ptr_as_ptr)] + +/// MSRV checking in late passes skips checking the parent nodes if no early pass sees a +/// `#[clippy::msrv]` attribute +/// +/// Here we ensure that even if all early passes are allowed (above) the attribute is still detected +/// in late lints such as `clippy::ptr_as_ptr` +#[clippy::msrv = "1.37"] +fn f(p: *const i32) { + let _ = p as *const i64; +} diff --git a/tests/ui/multi_assignments.rs b/tests/ui/multi_assignments.rs index cdbf13b68889..5a0d9a7aa37c 100644 --- a/tests/ui/multi_assignments.rs +++ b/tests/ui/multi_assignments.rs @@ -2,15 +2,18 @@ fn main() { let (mut a, mut b, mut c, mut d) = ((), (), (), ()); a = b = c; - //~^ ERROR: assignments don't nest intuitively - //~| NOTE: `-D clippy::multi-assignments` implied by `-D warnings` + //~^ multi_assignments + a = b = c = d; - //~^ ERROR: assignments don't nest intuitively - //~| ERROR: assignments don't nest intuitively + //~^ multi_assignments + //~| multi_assignments + a = b = { c }; - //~^ ERROR: assignments don't nest intuitively + //~^ multi_assignments + a = { b = c }; - //~^ ERROR: assignments don't nest intuitively + //~^ multi_assignments + a = (b = c); - //~^ ERROR: assignments don't nest intuitively + //~^ multi_assignments } diff --git a/tests/ui/multi_assignments.stderr b/tests/ui/multi_assignments.stderr index 53c22fcdb4c0..f56489c0b4b7 100644 --- a/tests/ui/multi_assignments.stderr +++ b/tests/ui/multi_assignments.stderr @@ -20,19 +20,19 @@ LL | a = b = c = d; | ^^^^^^^^^ error: assignments don't nest intuitively - --> tests/ui/multi_assignments.rs:10:5 + --> tests/ui/multi_assignments.rs:11:5 | LL | a = b = { c }; | ^^^^^^^^^^^^^ error: assignments don't nest intuitively - --> tests/ui/multi_assignments.rs:12:5 + --> tests/ui/multi_assignments.rs:14:5 | LL | a = { b = c }; | ^^^^^^^^^^^^^ error: assignments don't nest intuitively - --> tests/ui/multi_assignments.rs:14:5 + --> tests/ui/multi_assignments.rs:17:5 | LL | a = (b = c); | ^^^^^^^^^^^ diff --git a/tests/ui/multiple_bound_locations.rs b/tests/ui/multiple_bound_locations.rs index de9d994782ec..95b269d8935d 100644 --- a/tests/ui/multiple_bound_locations.rs +++ b/tests/ui/multiple_bound_locations.rs @@ -1,21 +1,21 @@ #![warn(clippy::multiple_bound_locations)] fn ty(a: F) -//~^ ERROR: bound is defined in more than one place +//~^ multiple_bound_locations where F: Sized, { } fn lifetime<'a, 'b: 'a, 'c>(a: &'b str, b: &'a str, c: &'c str) -//~^ ERROR: bound is defined in more than one place +//~^ multiple_bound_locations where 'b: 'c, { } fn ty_pred() -//~^ ERROR: bound is defined in more than one place +//~^ multiple_bound_locations where for<'a> F: Send + 'a, { @@ -25,21 +25,21 @@ struct B; impl B { fn ty(a: F) - //~^ ERROR: bound is defined in more than one place + //~^ multiple_bound_locations where F: Sized, { } fn lifetime<'a, 'b: 'a, 'c>(a: &'b str, b: &'a str, c: &'c str) - //~^ ERROR: bound is defined in more than one place + //~^ multiple_bound_locations where 'b: 'c, { } fn ty_pred() - //~^ ERROR: bound is defined in more than one place + //~^ multiple_bound_locations where for<'a> F: Send + 'a, { diff --git a/tests/ui/multiple_unsafe_ops_per_block.rs b/tests/ui/multiple_unsafe_ops_per_block.rs index 87d3517cd5f2..016fd89a7b7a 100644 --- a/tests/ui/multiple_unsafe_ops_per_block.rs +++ b/tests/ui/multiple_unsafe_ops_per_block.rs @@ -36,6 +36,7 @@ static mut STATIC: i32 = 0; fn test1() { unsafe { + //~^ multiple_unsafe_ops_per_block STATIC += 1; not_very_safe(); } @@ -45,6 +46,7 @@ fn test2() { let u = U { i: 0 }; unsafe { + //~^ multiple_unsafe_ops_per_block drop(u.u); *raw_ptr(); } @@ -52,6 +54,7 @@ fn test2() { fn test3() { unsafe { + //~^ multiple_unsafe_ops_per_block asm!("nop"); sample.not_very_safe(); STATIC = 0; @@ -61,6 +64,7 @@ fn test3() { fn test_all() { let u = U { i: 0 }; unsafe { + //~^ multiple_unsafe_ops_per_block drop(u.u); drop(STATIC); sample.not_very_safe(); @@ -105,6 +109,7 @@ fn correct3() { unsafe fn read_char_bad(ptr: *const u8) -> char { unsafe { char::from_u32_unchecked(*ptr.cast::()) } + //~^ multiple_unsafe_ops_per_block } // no lint @@ -123,6 +128,7 @@ fn issue10259() { fn _fn_ptr(x: unsafe fn()) { unsafe { + //~^ multiple_unsafe_ops_per_block x(); x(); } @@ -134,6 +140,7 @@ fn _assoc_const() { } fn _f() { unsafe { + //~^ multiple_unsafe_ops_per_block T::X(); T::X(); } @@ -144,6 +151,7 @@ fn _field_fn_ptr(x: unsafe fn()) { struct X(unsafe fn()); let x = X(x); unsafe { + //~^ multiple_unsafe_ops_per_block x.0(); x.0(); } diff --git a/tests/ui/multiple_unsafe_ops_per_block.stderr b/tests/ui/multiple_unsafe_ops_per_block.stderr index a9417a9ef91c..3130cecc2525 100644 --- a/tests/ui/multiple_unsafe_ops_per_block.stderr +++ b/tests/ui/multiple_unsafe_ops_per_block.stderr @@ -2,18 +2,19 @@ error: this `unsafe` block contains 2 unsafe operations, expected only one --> tests/ui/multiple_unsafe_ops_per_block.rs:38:5 | LL | / unsafe { +LL | | LL | | STATIC += 1; LL | | not_very_safe(); LL | | } | |_____^ | note: modification of a mutable static occurs here - --> tests/ui/multiple_unsafe_ops_per_block.rs:39:9 + --> tests/ui/multiple_unsafe_ops_per_block.rs:40:9 | LL | STATIC += 1; | ^^^^^^^^^^^ note: unsafe function call occurs here - --> tests/ui/multiple_unsafe_ops_per_block.rs:40:9 + --> tests/ui/multiple_unsafe_ops_per_block.rs:41:9 | LL | not_very_safe(); | ^^^^^^^^^^^^^^^ @@ -21,29 +22,31 @@ LL | not_very_safe(); = help: to override `-D warnings` add `#[allow(clippy::multiple_unsafe_ops_per_block)]` error: this `unsafe` block contains 2 unsafe operations, expected only one - --> tests/ui/multiple_unsafe_ops_per_block.rs:47:5 + --> tests/ui/multiple_unsafe_ops_per_block.rs:48:5 | LL | / unsafe { +LL | | LL | | drop(u.u); LL | | *raw_ptr(); LL | | } | |_____^ | note: union field access occurs here - --> tests/ui/multiple_unsafe_ops_per_block.rs:48:14 + --> tests/ui/multiple_unsafe_ops_per_block.rs:50:14 | LL | drop(u.u); | ^^^ note: raw pointer dereference occurs here - --> tests/ui/multiple_unsafe_ops_per_block.rs:49:9 + --> tests/ui/multiple_unsafe_ops_per_block.rs:51:9 | LL | *raw_ptr(); | ^^^^^^^^^^ error: this `unsafe` block contains 3 unsafe operations, expected only one - --> tests/ui/multiple_unsafe_ops_per_block.rs:54:5 + --> tests/ui/multiple_unsafe_ops_per_block.rs:56:5 | LL | / unsafe { +LL | | LL | | asm!("nop"); LL | | sample.not_very_safe(); LL | | STATIC = 0; @@ -51,137 +54,140 @@ LL | | } | |_____^ | note: inline assembly used here - --> tests/ui/multiple_unsafe_ops_per_block.rs:55:9 + --> tests/ui/multiple_unsafe_ops_per_block.rs:58:9 | LL | asm!("nop"); | ^^^^^^^^^^^ note: unsafe method call occurs here - --> tests/ui/multiple_unsafe_ops_per_block.rs:56:9 + --> tests/ui/multiple_unsafe_ops_per_block.rs:59:9 | LL | sample.not_very_safe(); | ^^^^^^^^^^^^^^^^^^^^^^ note: modification of a mutable static occurs here - --> tests/ui/multiple_unsafe_ops_per_block.rs:57:9 + --> tests/ui/multiple_unsafe_ops_per_block.rs:60:9 | LL | STATIC = 0; | ^^^^^^^^^^ error: this `unsafe` block contains 6 unsafe operations, expected only one - --> tests/ui/multiple_unsafe_ops_per_block.rs:63:5 + --> tests/ui/multiple_unsafe_ops_per_block.rs:66:5 | LL | / unsafe { +LL | | LL | | drop(u.u); LL | | drop(STATIC); -LL | | sample.not_very_safe(); ... | LL | | asm!("nop"); LL | | } | |_____^ | note: union field access occurs here - --> tests/ui/multiple_unsafe_ops_per_block.rs:64:14 + --> tests/ui/multiple_unsafe_ops_per_block.rs:68:14 | LL | drop(u.u); | ^^^ note: access of a mutable static occurs here - --> tests/ui/multiple_unsafe_ops_per_block.rs:65:14 + --> tests/ui/multiple_unsafe_ops_per_block.rs:69:14 | LL | drop(STATIC); | ^^^^^^ note: unsafe method call occurs here - --> tests/ui/multiple_unsafe_ops_per_block.rs:66:9 + --> tests/ui/multiple_unsafe_ops_per_block.rs:70:9 | LL | sample.not_very_safe(); | ^^^^^^^^^^^^^^^^^^^^^^ note: unsafe function call occurs here - --> tests/ui/multiple_unsafe_ops_per_block.rs:67:9 + --> tests/ui/multiple_unsafe_ops_per_block.rs:71:9 | LL | not_very_safe(); | ^^^^^^^^^^^^^^^ note: raw pointer dereference occurs here - --> tests/ui/multiple_unsafe_ops_per_block.rs:68:9 + --> tests/ui/multiple_unsafe_ops_per_block.rs:72:9 | LL | *raw_ptr(); | ^^^^^^^^^^ note: inline assembly used here - --> tests/ui/multiple_unsafe_ops_per_block.rs:69:9 + --> tests/ui/multiple_unsafe_ops_per_block.rs:73:9 | LL | asm!("nop"); | ^^^^^^^^^^^ error: this `unsafe` block contains 2 unsafe operations, expected only one - --> tests/ui/multiple_unsafe_ops_per_block.rs:107:5 + --> tests/ui/multiple_unsafe_ops_per_block.rs:111:5 | LL | unsafe { char::from_u32_unchecked(*ptr.cast::()) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: unsafe function call occurs here - --> tests/ui/multiple_unsafe_ops_per_block.rs:107:14 + --> tests/ui/multiple_unsafe_ops_per_block.rs:111:14 | LL | unsafe { char::from_u32_unchecked(*ptr.cast::()) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: raw pointer dereference occurs here - --> tests/ui/multiple_unsafe_ops_per_block.rs:107:39 + --> tests/ui/multiple_unsafe_ops_per_block.rs:111:39 | LL | unsafe { char::from_u32_unchecked(*ptr.cast::()) } | ^^^^^^^^^^^^^^^^^^ error: this `unsafe` block contains 2 unsafe operations, expected only one - --> tests/ui/multiple_unsafe_ops_per_block.rs:125:5 + --> tests/ui/multiple_unsafe_ops_per_block.rs:130:5 | LL | / unsafe { +LL | | LL | | x(); LL | | x(); LL | | } | |_____^ | note: unsafe function call occurs here - --> tests/ui/multiple_unsafe_ops_per_block.rs:126:9 + --> tests/ui/multiple_unsafe_ops_per_block.rs:132:9 | LL | x(); | ^^^ note: unsafe function call occurs here - --> tests/ui/multiple_unsafe_ops_per_block.rs:127:9 + --> tests/ui/multiple_unsafe_ops_per_block.rs:133:9 | LL | x(); | ^^^ error: this `unsafe` block contains 2 unsafe operations, expected only one - --> tests/ui/multiple_unsafe_ops_per_block.rs:136:9 + --> tests/ui/multiple_unsafe_ops_per_block.rs:142:9 | LL | / unsafe { +LL | | LL | | T::X(); LL | | T::X(); LL | | } | |_________^ | note: unsafe function call occurs here - --> tests/ui/multiple_unsafe_ops_per_block.rs:137:13 + --> tests/ui/multiple_unsafe_ops_per_block.rs:144:13 | LL | T::X(); | ^^^^^^ note: unsafe function call occurs here - --> tests/ui/multiple_unsafe_ops_per_block.rs:138:13 + --> tests/ui/multiple_unsafe_ops_per_block.rs:145:13 | LL | T::X(); | ^^^^^^ error: this `unsafe` block contains 2 unsafe operations, expected only one - --> tests/ui/multiple_unsafe_ops_per_block.rs:146:5 + --> tests/ui/multiple_unsafe_ops_per_block.rs:153:5 | LL | / unsafe { +LL | | LL | | x.0(); LL | | x.0(); LL | | } | |_____^ | note: unsafe function call occurs here - --> tests/ui/multiple_unsafe_ops_per_block.rs:147:9 + --> tests/ui/multiple_unsafe_ops_per_block.rs:155:9 | LL | x.0(); | ^^^^^ note: unsafe function call occurs here - --> tests/ui/multiple_unsafe_ops_per_block.rs:148:9 + --> tests/ui/multiple_unsafe_ops_per_block.rs:156:9 | LL | x.0(); | ^^^^^ diff --git a/tests/ui/must_use_candidates.fixed b/tests/ui/must_use_candidates.fixed index 2459af606884..b5d356a50217 100644 --- a/tests/ui/must_use_candidates.fixed +++ b/tests/ui/must_use_candidates.fixed @@ -14,11 +14,13 @@ pub struct MyAtomic(AtomicBool); pub struct MyPure; #[must_use] pub fn pure(i: u8) -> u8 { + //~^ must_use_candidate i } impl MyPure { #[must_use] pub fn inherent_pure(&self) -> u8 { + //~^ must_use_candidate 0 } } @@ -50,6 +52,7 @@ pub fn with_callback bool>(f: &F) -> bool { } #[must_use] pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool { + //~^ must_use_candidate true } @@ -62,6 +65,7 @@ pub fn atomics(b: &AtomicBool) -> bool { } #[must_use] pub fn rcd(_x: Rc) -> bool { + //~^ must_use_candidate true } @@ -70,6 +74,7 @@ pub fn rcmut(_x: Rc<&mut u32>) -> bool { } #[must_use] pub fn arcd(_x: Arc) -> bool { + //~^ must_use_candidate false } diff --git a/tests/ui/must_use_candidates.rs b/tests/ui/must_use_candidates.rs index 5f9b2449552a..14ea16662fdb 100644 --- a/tests/ui/must_use_candidates.rs +++ b/tests/ui/must_use_candidates.rs @@ -14,11 +14,13 @@ pub struct MyAtomic(AtomicBool); pub struct MyPure; pub fn pure(i: u8) -> u8 { + //~^ must_use_candidate i } impl MyPure { pub fn inherent_pure(&self) -> u8 { + //~^ must_use_candidate 0 } } @@ -50,6 +52,7 @@ pub fn with_callback bool>(f: &F) -> bool { } pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool { + //~^ must_use_candidate true } @@ -62,6 +65,7 @@ pub fn atomics(b: &AtomicBool) -> bool { } pub fn rcd(_x: Rc) -> bool { + //~^ must_use_candidate true } @@ -70,6 +74,7 @@ pub fn rcmut(_x: Rc<&mut u32>) -> bool { } pub fn arcd(_x: Arc) -> bool { + //~^ must_use_candidate false } diff --git a/tests/ui/must_use_candidates.stderr b/tests/ui/must_use_candidates.stderr index 2117e37866e2..590253d95f9e 100644 --- a/tests/ui/must_use_candidates.stderr +++ b/tests/ui/must_use_candidates.stderr @@ -8,25 +8,25 @@ LL | pub fn pure(i: u8) -> u8 { = help: to override `-D warnings` add `#[allow(clippy::must_use_candidate)]` error: this method could have a `#[must_use]` attribute - --> tests/ui/must_use_candidates.rs:21:5 + --> tests/ui/must_use_candidates.rs:22:5 | LL | pub fn inherent_pure(&self) -> u8 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn inherent_pure(&self) -> u8` error: this function could have a `#[must_use]` attribute - --> tests/ui/must_use_candidates.rs:52:1 + --> tests/ui/must_use_candidates.rs:54:1 | LL | pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool` error: this function could have a `#[must_use]` attribute - --> tests/ui/must_use_candidates.rs:64:1 + --> tests/ui/must_use_candidates.rs:67:1 | LL | pub fn rcd(_x: Rc) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn rcd(_x: Rc) -> bool` error: this function could have a `#[must_use]` attribute - --> tests/ui/must_use_candidates.rs:72:1 + --> tests/ui/must_use_candidates.rs:76:1 | LL | pub fn arcd(_x: Arc) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn arcd(_x: Arc) -> bool` diff --git a/tests/ui/must_use_unit.fixed b/tests/ui/must_use_unit.fixed index 7e2a72960492..683754a98c82 100644 --- a/tests/ui/must_use_unit.fixed +++ b/tests/ui/must_use_unit.fixed @@ -7,10 +7,13 @@ extern crate proc_macros; use proc_macros::external; pub fn must_use_default() {} +//~^ must_use_unit pub fn must_use_unit() -> () {} +//~^ must_use_unit pub fn must_use_with_note() {} +//~^ must_use_unit fn main() { must_use_default(); @@ -23,4 +26,3 @@ fn main() { fn foo() {} ); } - diff --git a/tests/ui/must_use_unit.rs b/tests/ui/must_use_unit.rs index f41b1a7c8005..519b8fa36821 100644 --- a/tests/ui/must_use_unit.rs +++ b/tests/ui/must_use_unit.rs @@ -8,12 +8,15 @@ use proc_macros::external; #[must_use] pub fn must_use_default() {} +//~^ must_use_unit #[must_use] pub fn must_use_unit() -> () {} +//~^ must_use_unit #[must_use = "With note"] pub fn must_use_with_note() {} +//~^ must_use_unit fn main() { must_use_default(); @@ -26,4 +29,3 @@ fn main() { fn foo() {} ); } - diff --git a/tests/ui/must_use_unit.stderr b/tests/ui/must_use_unit.stderr index c2ee2edda7dc..8f2af0cbd291 100644 --- a/tests/ui/must_use_unit.stderr +++ b/tests/ui/must_use_unit.stderr @@ -10,7 +10,7 @@ LL | pub fn must_use_default() {} = help: to override `-D warnings` add `#[allow(clippy::must_use_unit)]` error: this unit-returning function has a `#[must_use]` attribute - --> tests/ui/must_use_unit.rs:13:1 + --> tests/ui/must_use_unit.rs:14:1 | LL | #[must_use] | ----------- help: remove the attribute @@ -18,7 +18,7 @@ LL | pub fn must_use_unit() -> () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this unit-returning function has a `#[must_use]` attribute - --> tests/ui/must_use_unit.rs:16:1 + --> tests/ui/must_use_unit.rs:18:1 | LL | #[must_use = "With note"] | ------------------------- help: remove the attribute diff --git a/tests/ui/must_use_unit_12320.rs b/tests/ui/must_use_unit_unfixable.rs similarity index 62% rename from tests/ui/must_use_unit_12320.rs rename to tests/ui/must_use_unit_unfixable.rs index 39dcafdb38b5..0dba7996bac3 100644 --- a/tests/ui/must_use_unit_12320.rs +++ b/tests/ui/must_use_unit_unfixable.rs @@ -1,11 +1,11 @@ -//@aux-build:proc_macros.rs //@no-rustfix -#![warn(clippy::must_use_unit)] -#![allow(clippy::unused_unit)] - #[cfg_attr(all(), must_use, deprecated)] fn issue_12320() {} +//~^ must_use_unit #[cfg_attr(all(), deprecated, doc = "foo", must_use)] fn issue_12320_2() {} +//~^ must_use_unit + +fn main() {} diff --git a/tests/ui/must_use_unit_12320.stderr b/tests/ui/must_use_unit_unfixable.stderr similarity index 62% rename from tests/ui/must_use_unit_12320.stderr rename to tests/ui/must_use_unit_unfixable.stderr index b3e1cbc04576..087682199afb 100644 --- a/tests/ui/must_use_unit_12320.stderr +++ b/tests/ui/must_use_unit_unfixable.stderr @@ -1,25 +1,25 @@ error: this unit-returning function has a `#[must_use]` attribute - --> tests/ui/must_use_unit_12320.rs:8:1 + --> tests/ui/must_use_unit_unfixable.rs:4:1 | LL | fn issue_12320() {} | ^^^^^^^^^^^^^^^^ | help: remove `must_use` - --> tests/ui/must_use_unit_12320.rs:7:19 + --> tests/ui/must_use_unit_unfixable.rs:3:19 | LL | #[cfg_attr(all(), must_use, deprecated)] | ^^^^^^^^ - = note: `-D clippy::double-must-use` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::double_must_use)]` + = note: `-D clippy::must-use-unit` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::must_use_unit)]` error: this unit-returning function has a `#[must_use]` attribute - --> tests/ui/must_use_unit_12320.rs:11:1 + --> tests/ui/must_use_unit_unfixable.rs:8:1 | LL | fn issue_12320_2() {} | ^^^^^^^^^^^^^^^^^^ | help: remove `must_use` - --> tests/ui/must_use_unit_12320.rs:10:44 + --> tests/ui/must_use_unit_unfixable.rs:7:44 | LL | #[cfg_attr(all(), deprecated, doc = "foo", must_use)] | ^^^^^^^^ diff --git a/tests/ui/mut_from_ref.rs b/tests/ui/mut_from_ref.rs index 0ab6d77de1e1..b8c10f3eeb8f 100644 --- a/tests/ui/mut_from_ref.rs +++ b/tests/ui/mut_from_ref.rs @@ -5,14 +5,15 @@ struct Foo; impl Foo { fn this_wont_hurt_a_bit(&self) -> &mut Foo { - //~^ ERROR: mutable borrow from immutable input(s) + //~^ mut_from_ref + unsafe { unimplemented!() } } } trait Ouch { fn ouch(x: &Foo) -> &mut Foo; - //~^ ERROR: mutable borrow from immutable input(s) + //~^ mut_from_ref } impl Ouch for Foo { @@ -22,17 +23,20 @@ impl Ouch for Foo { } fn fail(x: &u32) -> &mut u16 { - //~^ ERROR: mutable borrow from immutable input(s) + //~^ mut_from_ref + unsafe { unimplemented!() } } fn fail_lifetime<'a>(x: &'a u32, y: &mut u32) -> &'a mut u32 { - //~^ ERROR: mutable borrow from immutable input(s) + //~^ mut_from_ref + unsafe { unimplemented!() } } fn fail_double<'a, 'b>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 { - //~^ ERROR: mutable borrow from immutable input(s) + //~^ mut_from_ref + unsafe { unimplemented!() } } @@ -47,7 +51,8 @@ fn also_works<'a>(x: &'a u32, y: &'a mut u32) -> &'a mut u32 { } unsafe fn also_broken(x: &u32) -> &mut u32 { - //~^ ERROR: mutable borrow from immutable input(s) + //~^ mut_from_ref + unimplemented!() } diff --git a/tests/ui/mut_from_ref.stderr b/tests/ui/mut_from_ref.stderr index 34fe91b5b3ac..8c3c8e0c3d85 100644 --- a/tests/ui/mut_from_ref.stderr +++ b/tests/ui/mut_from_ref.stderr @@ -13,61 +13,61 @@ LL | fn this_wont_hurt_a_bit(&self) -> &mut Foo { = help: to override `-D warnings` add `#[allow(clippy::mut_from_ref)]` error: mutable borrow from immutable input(s) - --> tests/ui/mut_from_ref.rs:14:25 + --> tests/ui/mut_from_ref.rs:15:25 | LL | fn ouch(x: &Foo) -> &mut Foo; | ^^^^^^^^ | note: immutable borrow here - --> tests/ui/mut_from_ref.rs:14:16 + --> tests/ui/mut_from_ref.rs:15:16 | LL | fn ouch(x: &Foo) -> &mut Foo; | ^^^^ error: mutable borrow from immutable input(s) - --> tests/ui/mut_from_ref.rs:24:21 + --> tests/ui/mut_from_ref.rs:25:21 | LL | fn fail(x: &u32) -> &mut u16 { | ^^^^^^^^ | note: immutable borrow here - --> tests/ui/mut_from_ref.rs:24:12 + --> tests/ui/mut_from_ref.rs:25:12 | LL | fn fail(x: &u32) -> &mut u16 { | ^^^^ error: mutable borrow from immutable input(s) - --> tests/ui/mut_from_ref.rs:29:50 + --> tests/ui/mut_from_ref.rs:31:50 | LL | fn fail_lifetime<'a>(x: &'a u32, y: &mut u32) -> &'a mut u32 { | ^^^^^^^^^^^ | note: immutable borrow here - --> tests/ui/mut_from_ref.rs:29:25 + --> tests/ui/mut_from_ref.rs:31:25 | LL | fn fail_lifetime<'a>(x: &'a u32, y: &mut u32) -> &'a mut u32 { | ^^^^^^^ error: mutable borrow from immutable input(s) - --> tests/ui/mut_from_ref.rs:34:67 + --> tests/ui/mut_from_ref.rs:37:67 | LL | fn fail_double<'a, 'b>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 { | ^^^^^^^^^^^ | note: immutable borrow here - --> tests/ui/mut_from_ref.rs:34:27 + --> tests/ui/mut_from_ref.rs:37:27 | LL | fn fail_double<'a, 'b>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 { | ^^^^^^^ ^^^^^^^ error: mutable borrow from immutable input(s) - --> tests/ui/mut_from_ref.rs:49:35 + --> tests/ui/mut_from_ref.rs:53:35 | LL | unsafe fn also_broken(x: &u32) -> &mut u32 { | ^^^^^^^^ | note: immutable borrow here - --> tests/ui/mut_from_ref.rs:49:26 + --> tests/ui/mut_from_ref.rs:53:26 | LL | unsafe fn also_broken(x: &u32) -> &mut u32 { | ^^^^ diff --git a/tests/ui/mut_key.rs b/tests/ui/mut_key.rs index 43ff705c4775..29dc2d020132 100644 --- a/tests/ui/mut_key.rs +++ b/tests/ui/mut_key.rs @@ -29,11 +29,12 @@ impl Hash for Key { } fn should_not_take_this_arg(m: &mut HashMap, _n: usize) -> HashSet { - //~^ ERROR: mutable key type - //~| NOTE: `-D clippy::mutable-key-type` implied by `-D warnings` - //~| ERROR: mutable key type + //~^ mutable_key_type + //~| mutable_key_type + let _other: HashMap = HashMap::new(); - //~^ ERROR: mutable key type + //~^ mutable_key_type + m.keys().cloned().collect() } @@ -61,7 +62,7 @@ fn generics_are_ok_too(_m: &mut HashSet) { fn tuples(_m: &mut HashMap<((), U), ()>) {} fn tuples_bad(_m: &mut HashMap<(Key, U), bool>) {} -//~^ ERROR: mutable key type +//~^ mutable_key_type fn main() { let _ = should_not_take_this_arg(&mut HashMap::new(), 1); @@ -74,29 +75,39 @@ fn main() { raw_mut_ptr_is_ok(&mut HashMap::new()); let _map = HashMap::, usize>::new(); - //~^ ERROR: mutable key type + //~^ mutable_key_type + let _map = HashMap::<&mut Cell, usize>::new(); - //~^ ERROR: mutable key type + //~^ mutable_key_type + // Collection types from `std` who's impl of `Hash` or `Ord` delegate their type parameters let _map = HashMap::>, usize>::new(); - //~^ ERROR: mutable key type + //~^ mutable_key_type + let _map = HashMap::, ()>, usize>::new(); - //~^ ERROR: mutable key type + //~^ mutable_key_type + let _map = HashMap::>, usize>::new(); - //~^ ERROR: mutable key type + //~^ mutable_key_type + let _map = HashMap::>, usize>::new(); - //~^ ERROR: mutable key type + //~^ mutable_key_type + let _map = HashMap::>, usize>::new(); - //~^ ERROR: mutable key type + //~^ mutable_key_type + let _map = HashMap::>>, usize>::new(); - //~^ ERROR: mutable key type + //~^ mutable_key_type + // Smart pointers from `std` who's impl of `Hash` or `Ord` delegate their type parameters let _map = HashMap::>, usize>::new(); - //~^ ERROR: mutable key type + //~^ mutable_key_type + let _map = HashMap::>, usize>::new(); - //~^ ERROR: mutable key type + //~^ mutable_key_type + let _map = HashMap::>, usize>::new(); - //~^ ERROR: mutable key type + //~^ mutable_key_type // Not interior mutability let _map = HashMap::<&mut usize, usize>::new(); diff --git a/tests/ui/mut_key.stderr b/tests/ui/mut_key.stderr index 8698ed4fd678..0d504584fbae 100644 --- a/tests/ui/mut_key.stderr +++ b/tests/ui/mut_key.stderr @@ -31,7 +31,7 @@ LL | let _other: HashMap = HashMap::new(); = note: ... because it contains `UnsafeCell`, which has interior mutability error: mutable key type - --> tests/ui/mut_key.rs:63:22 + --> tests/ui/mut_key.rs:64:22 | LL | fn tuples_bad(_m: &mut HashMap<(Key, U), bool>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -42,7 +42,7 @@ LL | fn tuples_bad(_m: &mut HashMap<(Key, U), bool>) {} = note: ... because it contains `UnsafeCell`, which has interior mutability error: mutable key type - --> tests/ui/mut_key.rs:76:5 + --> tests/ui/mut_key.rs:77:5 | LL | let _map = HashMap::, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -51,7 +51,7 @@ LL | let _map = HashMap::, usize>::new(); = note: ... because it contains `UnsafeCell`, which has interior mutability error: mutable key type - --> tests/ui/mut_key.rs:78:5 + --> tests/ui/mut_key.rs:80:5 | LL | let _map = HashMap::<&mut Cell, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL | let _map = HashMap::<&mut Cell, usize>::new(); = note: ... because it contains `UnsafeCell`, which has interior mutability error: mutable key type - --> tests/ui/mut_key.rs:81:5 + --> tests/ui/mut_key.rs:84:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -71,7 +71,7 @@ LL | let _map = HashMap::>, usize>::new(); = note: ... because it contains `UnsafeCell`, which has interior mutability error: mutable key type - --> tests/ui/mut_key.rs:83:5 + --> tests/ui/mut_key.rs:87:5 | LL | let _map = HashMap::, ()>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -81,7 +81,7 @@ LL | let _map = HashMap::, ()>, usize>::new(); = note: ... because it contains `UnsafeCell`, which has interior mutability error: mutable key type - --> tests/ui/mut_key.rs:85:5 + --> tests/ui/mut_key.rs:90:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -91,7 +91,7 @@ LL | let _map = HashMap::>, usize>::new(); = note: ... because it contains `UnsafeCell`, which has interior mutability error: mutable key type - --> tests/ui/mut_key.rs:87:5 + --> tests/ui/mut_key.rs:93:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -101,7 +101,7 @@ LL | let _map = HashMap::>, usize>::new(); = note: ... because it contains `UnsafeCell`, which has interior mutability error: mutable key type - --> tests/ui/mut_key.rs:89:5 + --> tests/ui/mut_key.rs:96:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -111,7 +111,7 @@ LL | let _map = HashMap::>, usize>::new(); = note: ... because it contains `UnsafeCell`, which has interior mutability error: mutable key type - --> tests/ui/mut_key.rs:91:5 + --> tests/ui/mut_key.rs:99:5 | LL | let _map = HashMap::>>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -122,7 +122,7 @@ LL | let _map = HashMap::>>, usize>::new(); = note: ... because it contains `UnsafeCell`, which has interior mutability error: mutable key type - --> tests/ui/mut_key.rs:94:5 + --> tests/ui/mut_key.rs:103:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -132,7 +132,7 @@ LL | let _map = HashMap::>, usize>::new(); = note: ... because it contains `UnsafeCell`, which has interior mutability error: mutable key type - --> tests/ui/mut_key.rs:96:5 + --> tests/ui/mut_key.rs:106:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -142,7 +142,7 @@ LL | let _map = HashMap::>, usize>::new(); = note: ... because it contains `UnsafeCell`, which has interior mutability error: mutable key type - --> tests/ui/mut_key.rs:98:5 + --> tests/ui/mut_key.rs:109:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/mut_mut.rs b/tests/ui/mut_mut.rs index 4c45bc980265..bbcdbc89b6a4 100644 --- a/tests/ui/mut_mut.rs +++ b/tests/ui/mut_mut.rs @@ -13,6 +13,7 @@ extern crate proc_macros; use proc_macros::{external, inline_macros}; fn fun(x: &mut &mut u32) -> bool { + //~^ mut_mut **x > 0 } @@ -30,21 +31,29 @@ macro_rules! mut_ptr { #[inline_macros] fn main() { let mut x = &mut &mut 1u32; + //~^ mut_mut { let mut y = &mut x; + //~^ mut_mut } if fun(x) { let y: &mut &mut u32 = &mut &mut 2; + //~^ mut_mut + //~| mut_mut **y + **x; } if fun(x) { let y: &mut &mut &mut u32 = &mut &mut &mut 2; + //~^ mut_mut + //~| mut_mut + //~| mut_mut ***y + **x; } let mut z = inline!(&mut $(&mut 3u32)); + //~^ mut_mut } fn issue939() { diff --git a/tests/ui/mut_mut.stderr b/tests/ui/mut_mut.stderr index 42853fdc008c..74b0c9ba145a 100644 --- a/tests/ui/mut_mut.stderr +++ b/tests/ui/mut_mut.stderr @@ -8,13 +8,13 @@ LL | fn fun(x: &mut &mut u32) -> bool { = help: to override `-D warnings` add `#[allow(clippy::mut_mut)]` error: generally you want to avoid `&mut &mut _` if possible - --> tests/ui/mut_mut.rs:32:17 + --> tests/ui/mut_mut.rs:33:17 | LL | let mut x = &mut &mut 1u32; | ^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> tests/ui/mut_mut.rs:47:25 + --> tests/ui/mut_mut.rs:55:25 | LL | let mut z = inline!(&mut $(&mut 3u32)); | ^ @@ -22,37 +22,37 @@ LL | let mut z = inline!(&mut $(&mut 3u32)); = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info) error: this expression mutably borrows a mutable reference. Consider reborrowing - --> tests/ui/mut_mut.rs:34:21 + --> tests/ui/mut_mut.rs:36:21 | LL | let mut y = &mut x; | ^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> tests/ui/mut_mut.rs:38:32 + --> tests/ui/mut_mut.rs:41:32 | LL | let y: &mut &mut u32 = &mut &mut 2; | ^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> tests/ui/mut_mut.rs:38:16 + --> tests/ui/mut_mut.rs:41:16 | LL | let y: &mut &mut u32 = &mut &mut 2; | ^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> tests/ui/mut_mut.rs:43:37 + --> tests/ui/mut_mut.rs:48:37 | LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> tests/ui/mut_mut.rs:43:16 + --> tests/ui/mut_mut.rs:48:16 | LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> tests/ui/mut_mut.rs:43:21 + --> tests/ui/mut_mut.rs:48:21 | LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^ diff --git a/tests/ui/mut_mutex_lock.fixed b/tests/ui/mut_mutex_lock.fixed index 29c5a27cb624..5790ee8c1b02 100644 --- a/tests/ui/mut_mutex_lock.fixed +++ b/tests/ui/mut_mutex_lock.fixed @@ -8,11 +8,13 @@ fn mut_mutex_lock() { let value_mutex = Arc::get_mut(&mut value_rc).unwrap(); let mut value = value_mutex.get_mut().unwrap(); + //~^ mut_mutex_lock *value += 1; let mut value_mutex = Mutex::new(42_u8); let mut_ref_mut_ref_mutex = &mut &mut value_mutex; let mut value = mut_ref_mut_ref_mutex.get_mut().unwrap(); + //~^ mut_mutex_lock *value += 1; } diff --git a/tests/ui/mut_mutex_lock.rs b/tests/ui/mut_mutex_lock.rs index fcdb3ff97dbc..7286afac823b 100644 --- a/tests/ui/mut_mutex_lock.rs +++ b/tests/ui/mut_mutex_lock.rs @@ -8,11 +8,13 @@ fn mut_mutex_lock() { let value_mutex = Arc::get_mut(&mut value_rc).unwrap(); let mut value = value_mutex.lock().unwrap(); + //~^ mut_mutex_lock *value += 1; let mut value_mutex = Mutex::new(42_u8); let mut_ref_mut_ref_mutex = &mut &mut value_mutex; let mut value = mut_ref_mut_ref_mutex.lock().unwrap(); + //~^ mut_mutex_lock *value += 1; } diff --git a/tests/ui/mut_mutex_lock.stderr b/tests/ui/mut_mutex_lock.stderr index 92601c4c6121..67543c73c6ee 100644 --- a/tests/ui/mut_mutex_lock.stderr +++ b/tests/ui/mut_mutex_lock.stderr @@ -8,7 +8,7 @@ LL | let mut value = value_mutex.lock().unwrap(); = help: to override `-D warnings` add `#[allow(clippy::mut_mutex_lock)]` error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference - --> tests/ui/mut_mutex_lock.rs:15:43 + --> tests/ui/mut_mutex_lock.rs:16:43 | LL | let mut value = mut_ref_mut_ref_mutex.lock().unwrap(); | ^^^^ help: change this to: `get_mut` diff --git a/tests/ui/mut_range_bound.rs b/tests/ui/mut_range_bound.rs index 7aebbf4981ee..107a6229b86d 100644 --- a/tests/ui/mut_range_bound.rs +++ b/tests/ui/mut_range_bound.rs @@ -6,8 +6,7 @@ fn mut_range_bound_upper() { let mut m = 4; for i in 0..m { m = 5; - //~^ ERROR: attempt to mutate range bound within loop - //~| NOTE: the range of the loop is unchanged + //~^ mut_range_bound } } @@ -15,8 +14,7 @@ fn mut_range_bound_lower() { let mut m = 4; for i in m..10 { m *= 2; - //~^ ERROR: attempt to mutate range bound within loop - //~| NOTE: the range of the loop is unchanged + //~^ mut_range_bound } } @@ -25,11 +23,10 @@ fn mut_range_bound_both() { let mut n = 6; for i in m..n { m = 5; - //~^ ERROR: attempt to mutate range bound within loop - //~| NOTE: the range of the loop is unchanged + //~^ mut_range_bound + n = 7; - //~^ ERROR: attempt to mutate range bound within loop - //~| NOTE: the range of the loop is unchanged + //~^ mut_range_bound } } @@ -44,8 +41,8 @@ fn mut_borrow_range_bound() { let mut m = 4; for i in 0..m { let n = &mut m; - //~^ ERROR: attempt to mutate range bound within loop - //~| NOTE: the range of the loop is unchanged + //~^ mut_range_bound + *n += 1; } } @@ -79,8 +76,8 @@ fn mut_range_bound_no_immediate_break() { for i in 0..m { // warning because it is not immediately followed by break m = 2; - //~^ ERROR: attempt to mutate range bound within loop - //~| NOTE: the range of the loop is unchanged + //~^ mut_range_bound + if m == 4 { break; } @@ -91,8 +88,8 @@ fn mut_range_bound_no_immediate_break() { if n == 4 { // FIXME: warning because it is not immediately followed by break n = 1; - //~^ ERROR: attempt to mutate range bound within loop - //~| NOTE: the range of the loop is unchanged + //~^ mut_range_bound + let _ = 2; break; } diff --git a/tests/ui/mut_range_bound.stderr b/tests/ui/mut_range_bound.stderr index 6f93b0ebe6fc..3aae6e2dca6d 100644 --- a/tests/ui/mut_range_bound.stderr +++ b/tests/ui/mut_range_bound.stderr @@ -9,7 +9,7 @@ LL | m = 5; = help: to override `-D warnings` add `#[allow(clippy::mut_range_bound)]` error: attempt to mutate range bound within loop - --> tests/ui/mut_range_bound.rs:17:9 + --> tests/ui/mut_range_bound.rs:16:9 | LL | m *= 2; | ^ @@ -17,7 +17,7 @@ LL | m *= 2; = note: the range of the loop is unchanged error: attempt to mutate range bound within loop - --> tests/ui/mut_range_bound.rs:27:9 + --> tests/ui/mut_range_bound.rs:25:9 | LL | m = 5; | ^ @@ -25,7 +25,7 @@ LL | m = 5; = note: the range of the loop is unchanged error: attempt to mutate range bound within loop - --> tests/ui/mut_range_bound.rs:30:9 + --> tests/ui/mut_range_bound.rs:28:9 | LL | n = 7; | ^ @@ -33,7 +33,7 @@ LL | n = 7; = note: the range of the loop is unchanged error: attempt to mutate range bound within loop - --> tests/ui/mut_range_bound.rs:46:22 + --> tests/ui/mut_range_bound.rs:43:22 | LL | let n = &mut m; | ^ @@ -41,7 +41,7 @@ LL | let n = &mut m; = note: the range of the loop is unchanged error: attempt to mutate range bound within loop - --> tests/ui/mut_range_bound.rs:81:9 + --> tests/ui/mut_range_bound.rs:78:9 | LL | m = 2; | ^ @@ -49,7 +49,7 @@ LL | m = 2; = note: the range of the loop is unchanged error: attempt to mutate range bound within loop - --> tests/ui/mut_range_bound.rs:93:13 + --> tests/ui/mut_range_bound.rs:90:13 | LL | n = 1; | ^ diff --git a/tests/ui/mut_reference.rs b/tests/ui/mut_reference.rs index 1d7faaa5e75e..f664c373cdc3 100644 --- a/tests/ui/mut_reference.rs +++ b/tests/ui/mut_reference.rs @@ -28,16 +28,16 @@ impl MyStruct { fn main() { // Functions takes_an_immutable_reference(&mut 42); - //~^ ERROR: the function `takes_an_immutable_reference` doesn't need a mutable referen - //~| NOTE: `-D clippy::unnecessary-mut-passed` implied by `-D warnings` + //~^ unnecessary_mut_passed + let as_ptr: fn(&i32) = takes_an_immutable_reference; as_ptr(&mut 42); - //~^ ERROR: the function `as_ptr` doesn't need a mutable reference + //~^ unnecessary_mut_passed // Methods let my_struct = MyStruct; my_struct.takes_an_immutable_reference(&mut 42); - //~^ ERROR: the method `takes_an_immutable_reference` doesn't need a mutable reference + //~^ unnecessary_mut_passed // No error diff --git a/tests/ui/mutex_atomic.rs b/tests/ui/mutex_atomic.rs index 3a51538b7424..80a712a9286a 100644 --- a/tests/ui/mutex_atomic.rs +++ b/tests/ui/mutex_atomic.rs @@ -6,32 +6,40 @@ fn main() { use std::sync::Mutex; Mutex::new(true); - //~^ ERROR: consider using an `AtomicBool` instead of a `Mutex` here; if you just want - //~| NOTE: `-D clippy::mutex-atomic` implied by `-D warnings` + //~^ mutex_atomic + Mutex::new(5usize); - //~^ ERROR: consider using an `AtomicUsize` instead of a `Mutex` here; if you just wan + //~^ mutex_atomic + Mutex::new(9isize); - //~^ ERROR: consider using an `AtomicIsize` instead of a `Mutex` here; if you just wan + //~^ mutex_atomic + let mut x = 4u32; Mutex::new(&x as *const u32); - //~^ ERROR: consider using an `AtomicPtr` instead of a `Mutex` here; if you just want + //~^ mutex_atomic + Mutex::new(&mut x as *mut u32); - //~^ ERROR: consider using an `AtomicPtr` instead of a `Mutex` here; if you just want + //~^ mutex_atomic + Mutex::new(0u32); - //~^ ERROR: consider using an `AtomicU32` instead of a `Mutex` here; if you just wan - //~| NOTE: `-D clippy::mutex-integer` implied by `-D warnings` + //~^ mutex_integer + Mutex::new(0i32); - //~^ ERROR: consider using an `AtomicI32` instead of a `Mutex` here; if you just wan + //~^ mutex_integer + Mutex::new(0f32); // there are no float atomics, so this should not lint Mutex::new(0u8); - //~^ ERROR: consider using an `AtomicU8` instead of a `Mutex` here; if you just wan + //~^ mutex_integer + Mutex::new(0i16); - //~^ ERROR: consider using an `AtomicI16` instead of a `Mutex` here; if you just wan + //~^ mutex_integer + let _x: Mutex = Mutex::new(0); - //~^ ERROR: consider using an `AtomicI8` instead of a `Mutex` here; if you just wan + //~^ mutex_integer + const X: i64 = 0; Mutex::new(X); - //~^ ERROR: consider using an `AtomicI64` instead of a `Mutex` here; if you just wan + //~^ mutex_integer // there are no 128 atomics, so these two should not lint { diff --git a/tests/ui/mutex_atomic.stderr b/tests/ui/mutex_atomic.stderr index 683a7b939db3..838fc1d7c36e 100644 --- a/tests/ui/mutex_atomic.stderr +++ b/tests/ui/mutex_atomic.stderr @@ -14,25 +14,25 @@ LL | Mutex::new(5usize); | ^^^^^^^^^^^^^^^^^^ error: consider using an `AtomicIsize` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>` - --> tests/ui/mutex_atomic.rs:13:5 + --> tests/ui/mutex_atomic.rs:14:5 | LL | Mutex::new(9isize); | ^^^^^^^^^^^^^^^^^^ error: consider using an `AtomicPtr` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>` - --> tests/ui/mutex_atomic.rs:16:5 + --> tests/ui/mutex_atomic.rs:18:5 | LL | Mutex::new(&x as *const u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: consider using an `AtomicPtr` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>` - --> tests/ui/mutex_atomic.rs:18:5 + --> tests/ui/mutex_atomic.rs:21:5 | LL | Mutex::new(&mut x as *mut u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: consider using an `AtomicU32` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>` - --> tests/ui/mutex_atomic.rs:20:5 + --> tests/ui/mutex_atomic.rs:24:5 | LL | Mutex::new(0u32); | ^^^^^^^^^^^^^^^^ @@ -41,31 +41,31 @@ LL | Mutex::new(0u32); = help: to override `-D warnings` add `#[allow(clippy::mutex_integer)]` error: consider using an `AtomicI32` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>` - --> tests/ui/mutex_atomic.rs:23:5 + --> tests/ui/mutex_atomic.rs:27:5 | LL | Mutex::new(0i32); | ^^^^^^^^^^^^^^^^ error: consider using an `AtomicU8` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>` - --> tests/ui/mutex_atomic.rs:26:5 + --> tests/ui/mutex_atomic.rs:31:5 | LL | Mutex::new(0u8); | ^^^^^^^^^^^^^^^ error: consider using an `AtomicI16` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>` - --> tests/ui/mutex_atomic.rs:28:5 + --> tests/ui/mutex_atomic.rs:34:5 | LL | Mutex::new(0i16); | ^^^^^^^^^^^^^^^^ error: consider using an `AtomicI8` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>` - --> tests/ui/mutex_atomic.rs:30:25 + --> tests/ui/mutex_atomic.rs:37:25 | LL | let _x: Mutex = Mutex::new(0); | ^^^^^^^^^^^^^ error: consider using an `AtomicI64` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>` - --> tests/ui/mutex_atomic.rs:33:5 + --> tests/ui/mutex_atomic.rs:41:5 | LL | Mutex::new(X); | ^^^^^^^^^^^^^ diff --git a/tests/ui/needless_arbitrary_self_type.fixed b/tests/ui/needless_arbitrary_self_type.fixed index 530eb77d83d2..adb9096c9f24 100644 --- a/tests/ui/needless_arbitrary_self_type.fixed +++ b/tests/ui/needless_arbitrary_self_type.fixed @@ -8,6 +8,7 @@ pub enum ValType { impl ValType { pub fn bad(self) { + //~^ needless_arbitrary_self_type unimplemented!(); } @@ -16,6 +17,7 @@ impl ValType { } pub fn mut_bad(mut self) { + //~^ needless_arbitrary_self_type unimplemented!(); } @@ -24,6 +26,7 @@ impl ValType { } pub fn ref_bad(&self) { + //~^ needless_arbitrary_self_type unimplemented!(); } @@ -32,6 +35,7 @@ impl ValType { } pub fn ref_bad_with_lifetime<'a>(&'a self) { + //~^ needless_arbitrary_self_type unimplemented!(); } @@ -40,6 +44,7 @@ impl ValType { } pub fn mut_ref_bad(&mut self) { + //~^ needless_arbitrary_self_type unimplemented!(); } @@ -48,6 +53,7 @@ impl ValType { } pub fn mut_ref_bad_with_lifetime<'a>(&'a mut self) { + //~^ needless_arbitrary_self_type unimplemented!(); } @@ -66,7 +72,9 @@ impl ValType { trait Foo<'r#struct> { fn f1(&'r#struct self) {} + //~^ needless_arbitrary_self_type fn f2(&'r#struct mut self) {} + //~^ needless_arbitrary_self_type } fn main() {} diff --git a/tests/ui/needless_arbitrary_self_type.rs b/tests/ui/needless_arbitrary_self_type.rs index 5a1ff96a11cc..550546ed24fd 100644 --- a/tests/ui/needless_arbitrary_self_type.rs +++ b/tests/ui/needless_arbitrary_self_type.rs @@ -8,6 +8,7 @@ pub enum ValType { impl ValType { pub fn bad(self: Self) { + //~^ needless_arbitrary_self_type unimplemented!(); } @@ -16,6 +17,7 @@ impl ValType { } pub fn mut_bad(mut self: Self) { + //~^ needless_arbitrary_self_type unimplemented!(); } @@ -24,6 +26,7 @@ impl ValType { } pub fn ref_bad(self: &Self) { + //~^ needless_arbitrary_self_type unimplemented!(); } @@ -32,6 +35,7 @@ impl ValType { } pub fn ref_bad_with_lifetime<'a>(self: &'a Self) { + //~^ needless_arbitrary_self_type unimplemented!(); } @@ -40,6 +44,7 @@ impl ValType { } pub fn mut_ref_bad(self: &mut Self) { + //~^ needless_arbitrary_self_type unimplemented!(); } @@ -48,6 +53,7 @@ impl ValType { } pub fn mut_ref_bad_with_lifetime<'a>(self: &'a mut Self) { + //~^ needless_arbitrary_self_type unimplemented!(); } @@ -66,7 +72,9 @@ impl ValType { trait Foo<'r#struct> { fn f1(self: &'r#struct Self) {} + //~^ needless_arbitrary_self_type fn f2(self: &'r#struct mut Self) {} + //~^ needless_arbitrary_self_type } fn main() {} diff --git a/tests/ui/needless_arbitrary_self_type.stderr b/tests/ui/needless_arbitrary_self_type.stderr index 7ebbbaa122f5..b5c0aae8310f 100644 --- a/tests/ui/needless_arbitrary_self_type.stderr +++ b/tests/ui/needless_arbitrary_self_type.stderr @@ -8,43 +8,43 @@ LL | pub fn bad(self: Self) { = help: to override `-D warnings` add `#[allow(clippy::needless_arbitrary_self_type)]` error: the type of the `self` parameter does not need to be arbitrary - --> tests/ui/needless_arbitrary_self_type.rs:18:20 + --> tests/ui/needless_arbitrary_self_type.rs:19:20 | LL | pub fn mut_bad(mut self: Self) { | ^^^^^^^^^^^^^^ help: consider to change this parameter to: `mut self` error: the type of the `self` parameter does not need to be arbitrary - --> tests/ui/needless_arbitrary_self_type.rs:26:20 + --> tests/ui/needless_arbitrary_self_type.rs:28:20 | LL | pub fn ref_bad(self: &Self) { | ^^^^^^^^^^^ help: consider to change this parameter to: `&self` error: the type of the `self` parameter does not need to be arbitrary - --> tests/ui/needless_arbitrary_self_type.rs:34:38 + --> tests/ui/needless_arbitrary_self_type.rs:37:38 | LL | pub fn ref_bad_with_lifetime<'a>(self: &'a Self) { | ^^^^^^^^^^^^^^ help: consider to change this parameter to: `&'a self` error: the type of the `self` parameter does not need to be arbitrary - --> tests/ui/needless_arbitrary_self_type.rs:42:24 + --> tests/ui/needless_arbitrary_self_type.rs:46:24 | LL | pub fn mut_ref_bad(self: &mut Self) { | ^^^^^^^^^^^^^^^ help: consider to change this parameter to: `&mut self` error: the type of the `self` parameter does not need to be arbitrary - --> tests/ui/needless_arbitrary_self_type.rs:50:42 + --> tests/ui/needless_arbitrary_self_type.rs:55:42 | LL | pub fn mut_ref_bad_with_lifetime<'a>(self: &'a mut Self) { | ^^^^^^^^^^^^^^^^^^ help: consider to change this parameter to: `&'a mut self` error: the type of the `self` parameter does not need to be arbitrary - --> tests/ui/needless_arbitrary_self_type.rs:68:11 + --> tests/ui/needless_arbitrary_self_type.rs:74:11 | LL | fn f1(self: &'r#struct Self) {} | ^^^^^^^^^^^^^^^^^^^^^ help: consider to change this parameter to: `&'r#struct self` error: the type of the `self` parameter does not need to be arbitrary - --> tests/ui/needless_arbitrary_self_type.rs:69:11 + --> tests/ui/needless_arbitrary_self_type.rs:76:11 | LL | fn f2(self: &'r#struct mut Self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider to change this parameter to: `&'r#struct mut self` diff --git a/tests/ui/needless_arbitrary_self_type_unfixable.fixed b/tests/ui/needless_arbitrary_self_type_unfixable.fixed index 62a6e5932435..f4ee0a8bd072 100644 --- a/tests/ui/needless_arbitrary_self_type_unfixable.fixed +++ b/tests/ui/needless_arbitrary_self_type_unfixable.fixed @@ -40,6 +40,7 @@ mod issue_6089 { impl T2 for S2 { #[allow(clippy::needless_lifetimes)] fn call_with_mut_self(&mut self) {} + //~^ needless_arbitrary_self_type } } diff --git a/tests/ui/needless_arbitrary_self_type_unfixable.rs b/tests/ui/needless_arbitrary_self_type_unfixable.rs index 00871f9f450c..3f29025c1362 100644 --- a/tests/ui/needless_arbitrary_self_type_unfixable.rs +++ b/tests/ui/needless_arbitrary_self_type_unfixable.rs @@ -40,6 +40,7 @@ mod issue_6089 { impl T2 for S2 { #[allow(clippy::needless_lifetimes)] fn call_with_mut_self(self: &mut Self) {} + //~^ needless_arbitrary_self_type } } diff --git a/tests/ui/needless_as_bytes.fixed b/tests/ui/needless_as_bytes.fixed index 74b4ba5be798..9cbc7b9c2651 100644 --- a/tests/ui/needless_as_bytes.fixed +++ b/tests/ui/needless_as_bytes.fixed @@ -16,11 +16,13 @@ impl S { fn main() { if "some string".is_empty() { //~^ needless_as_bytes + println!("len = {}", "some string".len()); //~^ needless_as_bytes } if "some string".is_empty() { //~^ needless_as_bytes + println!("len = {}", "some string".len()); //~^ needless_as_bytes } @@ -28,11 +30,13 @@ fn main() { let s = String::from("yet another string"); if s.is_empty() { //~^ needless_as_bytes + println!("len = {}", s.len()); //~^ needless_as_bytes } if s.is_empty() { //~^ needless_as_bytes + println!("len = {}", s.len()); //~^ needless_as_bytes } diff --git a/tests/ui/needless_as_bytes.rs b/tests/ui/needless_as_bytes.rs index ffcce60bbbef..7de699647e85 100644 --- a/tests/ui/needless_as_bytes.rs +++ b/tests/ui/needless_as_bytes.rs @@ -16,11 +16,13 @@ impl S { fn main() { if "some string".as_bytes().is_empty() { //~^ needless_as_bytes + println!("len = {}", "some string".as_bytes().len()); //~^ needless_as_bytes } if "some string".bytes().is_empty() { //~^ needless_as_bytes + println!("len = {}", "some string".bytes().len()); //~^ needless_as_bytes } @@ -28,11 +30,13 @@ fn main() { let s = String::from("yet another string"); if s.as_bytes().is_empty() { //~^ needless_as_bytes + println!("len = {}", s.as_bytes().len()); //~^ needless_as_bytes } if s.bytes().is_empty() { //~^ needless_as_bytes + println!("len = {}", s.bytes().len()); //~^ needless_as_bytes } diff --git a/tests/ui/needless_as_bytes.stderr b/tests/ui/needless_as_bytes.stderr index 138c6630ae7d..0eead9815f8a 100644 --- a/tests/ui/needless_as_bytes.stderr +++ b/tests/ui/needless_as_bytes.stderr @@ -8,43 +8,43 @@ LL | if "some string".as_bytes().is_empty() { = help: to override `-D warnings` add `#[allow(clippy::needless_as_bytes)]` error: needless call to `as_bytes` - --> tests/ui/needless_as_bytes.rs:19:30 + --> tests/ui/needless_as_bytes.rs:20:30 | LL | println!("len = {}", "some string".as_bytes().len()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: `len()` can be called directly on strings: `"some string".len()` error: needless call to `bytes` - --> tests/ui/needless_as_bytes.rs:22:8 + --> tests/ui/needless_as_bytes.rs:23:8 | LL | if "some string".bytes().is_empty() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: `is_empty()` can be called directly on strings: `"some string".is_empty()` error: needless call to `bytes` - --> tests/ui/needless_as_bytes.rs:24:30 + --> tests/ui/needless_as_bytes.rs:26:30 | LL | println!("len = {}", "some string".bytes().len()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: `len()` can be called directly on strings: `"some string".len()` error: needless call to `as_bytes` - --> tests/ui/needless_as_bytes.rs:29:8 + --> tests/ui/needless_as_bytes.rs:31:8 | LL | if s.as_bytes().is_empty() { | ^^^^^^^^^^^^^^^^^^^^^^^ help: `is_empty()` can be called directly on strings: `s.is_empty()` error: needless call to `as_bytes` - --> tests/ui/needless_as_bytes.rs:31:30 + --> tests/ui/needless_as_bytes.rs:34:30 | LL | println!("len = {}", s.as_bytes().len()); | ^^^^^^^^^^^^^^^^^^ help: `len()` can be called directly on strings: `s.len()` error: needless call to `bytes` - --> tests/ui/needless_as_bytes.rs:34:8 + --> tests/ui/needless_as_bytes.rs:37:8 | LL | if s.bytes().is_empty() { | ^^^^^^^^^^^^^^^^^^^^ help: `is_empty()` can be called directly on strings: `s.is_empty()` error: needless call to `bytes` - --> tests/ui/needless_as_bytes.rs:36:30 + --> tests/ui/needless_as_bytes.rs:40:30 | LL | println!("len = {}", s.bytes().len()); | ^^^^^^^^^^^^^^^ help: `len()` can be called directly on strings: `s.len()` diff --git a/tests/ui/needless_bitwise_bool.fixed b/tests/ui/needless_bitwise_bool.fixed index a8176618c1f2..89a3c1474f25 100644 --- a/tests/ui/needless_bitwise_bool.fixed +++ b/tests/ui/needless_bitwise_bool.fixed @@ -21,6 +21,7 @@ fn main() { println!("true") } if y && !x { + //~^ needless_bitwise_bool println!("true") } diff --git a/tests/ui/needless_bitwise_bool.rs b/tests/ui/needless_bitwise_bool.rs index f190eb2b76e7..f5aa7a9f3d9e 100644 --- a/tests/ui/needless_bitwise_bool.rs +++ b/tests/ui/needless_bitwise_bool.rs @@ -21,6 +21,7 @@ fn main() { println!("true") } if y & !x { + //~^ needless_bitwise_bool println!("true") } diff --git a/tests/ui/needless_bool/fixable.fixed b/tests/ui/needless_bool/fixable.fixed index ec63c4fd6a26..0664abf0944d 100644 --- a/tests/ui/needless_bool/fixable.fixed +++ b/tests/ui/needless_bool/fixable.fixed @@ -39,17 +39,26 @@ fn main() { let x = true; let y = false; x; + //~^^^^^ needless_bool !x; + //~^^^^^ needless_bool !(x && y); + //~^^^^^ needless_bool let a = 0; let b = 1; a != b; + //~^^^^^ needless_bool a == b; + //~^^^^^ needless_bool a >= b; + //~^^^^^ needless_bool a > b; + //~^^^^^ needless_bool a <= b; + //~^^^^^ needless_bool a < b; + //~^^^^^ needless_bool if x { x } else { @@ -74,26 +83,32 @@ fn main() { fn bool_ret3(x: bool) -> bool { return x; + //~^^^^^ needless_bool } fn bool_ret4(x: bool) -> bool { return !x; + //~^^^^^ needless_bool } fn bool_ret5(x: bool, y: bool) -> bool { return x && y; + //~^^^^^ needless_bool } fn bool_ret6(x: bool, y: bool) -> bool { return !(x && y); + //~^^^^^ needless_bool } fn needless_bool(x: bool) { if x {}; + //~^ bool_comparison } fn needless_bool2(x: bool) { if !x {}; + //~^ bool_comparison } fn needless_bool3(x: bool) { @@ -104,7 +119,9 @@ fn needless_bool3(x: bool) { } if x {}; + //~^ bool_comparison if !x {}; + //~^ bool_comparison } fn needless_bool_in_the_suggestion_wraps_the_predicate_of_if_else_statement_in_brackets() { @@ -114,6 +131,7 @@ fn needless_bool_in_the_suggestion_wraps_the_predicate_of_if_else_statement_in_b let x = if b { true } else { !returns_bool() }; + //~^^^^^ needless_bool } unsafe fn no(v: u8) -> u8 { @@ -123,10 +141,13 @@ unsafe fn no(v: u8) -> u8 { #[allow(clippy::unnecessary_operation)] fn needless_bool_condition() -> bool { (unsafe { no(4) } & 1 != 0); + //~^^^^^ needless_bool let _brackets_unneeded = unsafe { no(4) } & 1 != 0; + //~^ needless_bool fn foo() -> bool { // parentheses are needed here (unsafe { no(4) } & 1 != 0) + //~^ needless_bool } foo() @@ -138,8 +159,11 @@ fn issue12846() { // parentheses are needed here let _x = (a && b).then(|| todo!()); + //~^ needless_bool let _x = (a && b) as u8; + //~^ needless_bool // parentheses are not needed here let _x = a.then(|| todo!()); + //~^ needless_bool } diff --git a/tests/ui/needless_bool/fixable.rs b/tests/ui/needless_bool/fixable.rs index 8694aa715908..7507a6af408b 100644 --- a/tests/ui/needless_bool/fixable.rs +++ b/tests/ui/needless_bool/fixable.rs @@ -43,16 +43,19 @@ fn main() { } else { false }; + //~^^^^^ needless_bool if x { false } else { true }; + //~^^^^^ needless_bool if x && y { false } else { true }; + //~^^^^^ needless_bool let a = 0; let b = 1; @@ -61,31 +64,37 @@ fn main() { } else { true }; + //~^^^^^ needless_bool if a != b { false } else { true }; + //~^^^^^ needless_bool if a < b { false } else { true }; + //~^^^^^ needless_bool if a <= b { false } else { true }; + //~^^^^^ needless_bool if a > b { false } else { true }; + //~^^^^^ needless_bool if a >= b { false } else { true }; + //~^^^^^ needless_bool if x { x } else { @@ -114,6 +123,7 @@ fn bool_ret3(x: bool) -> bool { } else { return false; }; + //~^^^^^ needless_bool } fn bool_ret4(x: bool) -> bool { @@ -122,6 +132,7 @@ fn bool_ret4(x: bool) -> bool { } else { return true; }; + //~^^^^^ needless_bool } fn bool_ret5(x: bool, y: bool) -> bool { @@ -130,6 +141,7 @@ fn bool_ret5(x: bool, y: bool) -> bool { } else { return false; }; + //~^^^^^ needless_bool } fn bool_ret6(x: bool, y: bool) -> bool { @@ -138,14 +150,17 @@ fn bool_ret6(x: bool, y: bool) -> bool { } else { return true; }; + //~^^^^^ needless_bool } fn needless_bool(x: bool) { if x == true {}; + //~^ bool_comparison } fn needless_bool2(x: bool) { if x == false {}; + //~^ bool_comparison } fn needless_bool3(x: bool) { @@ -156,7 +171,9 @@ fn needless_bool3(x: bool) { } if x == true {}; + //~^ bool_comparison if x == false {}; + //~^ bool_comparison } fn needless_bool_in_the_suggestion_wraps_the_predicate_of_if_else_statement_in_brackets() { @@ -170,6 +187,7 @@ fn needless_bool_in_the_suggestion_wraps_the_predicate_of_if_else_statement_in_b } else { true }; + //~^^^^^ needless_bool } unsafe fn no(v: u8) -> u8 { @@ -183,10 +201,13 @@ fn needless_bool_condition() -> bool { } else { false }; + //~^^^^^ needless_bool let _brackets_unneeded = if unsafe { no(4) } & 1 != 0 { true } else { false }; + //~^ needless_bool fn foo() -> bool { // parentheses are needed here if unsafe { no(4) } & 1 != 0 { true } else { false } + //~^ needless_bool } foo() @@ -198,8 +219,11 @@ fn issue12846() { // parentheses are needed here let _x = if a && b { true } else { false }.then(|| todo!()); + //~^ needless_bool let _x = if a && b { true } else { false } as u8; + //~^ needless_bool // parentheses are not needed here let _x = if a { true } else { false }.then(|| todo!()); + //~^ needless_bool } diff --git a/tests/ui/needless_bool/fixable.stderr b/tests/ui/needless_bool/fixable.stderr index 99b5b9983448..3f117ee5a502 100644 --- a/tests/ui/needless_bool/fixable.stderr +++ b/tests/ui/needless_bool/fixable.stderr @@ -12,7 +12,7 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::needless_bool)]` error: this if-then-else expression returns a bool literal - --> tests/ui/needless_bool/fixable.rs:46:5 + --> tests/ui/needless_bool/fixable.rs:47:5 | LL | / if x { LL | | false @@ -22,7 +22,7 @@ LL | | }; | |_____^ help: you can reduce it to: `!x` error: this if-then-else expression returns a bool literal - --> tests/ui/needless_bool/fixable.rs:51:5 + --> tests/ui/needless_bool/fixable.rs:53:5 | LL | / if x && y { LL | | false @@ -32,7 +32,7 @@ LL | | }; | |_____^ help: you can reduce it to: `!(x && y)` error: this if-then-else expression returns a bool literal - --> tests/ui/needless_bool/fixable.rs:59:5 + --> tests/ui/needless_bool/fixable.rs:62:5 | LL | / if a == b { LL | | false @@ -42,7 +42,7 @@ LL | | }; | |_____^ help: you can reduce it to: `a != b` error: this if-then-else expression returns a bool literal - --> tests/ui/needless_bool/fixable.rs:64:5 + --> tests/ui/needless_bool/fixable.rs:68:5 | LL | / if a != b { LL | | false @@ -52,7 +52,7 @@ LL | | }; | |_____^ help: you can reduce it to: `a == b` error: this if-then-else expression returns a bool literal - --> tests/ui/needless_bool/fixable.rs:69:5 + --> tests/ui/needless_bool/fixable.rs:74:5 | LL | / if a < b { LL | | false @@ -62,7 +62,7 @@ LL | | }; | |_____^ help: you can reduce it to: `a >= b` error: this if-then-else expression returns a bool literal - --> tests/ui/needless_bool/fixable.rs:74:5 + --> tests/ui/needless_bool/fixable.rs:80:5 | LL | / if a <= b { LL | | false @@ -72,7 +72,7 @@ LL | | }; | |_____^ help: you can reduce it to: `a > b` error: this if-then-else expression returns a bool literal - --> tests/ui/needless_bool/fixable.rs:79:5 + --> tests/ui/needless_bool/fixable.rs:86:5 | LL | / if a > b { LL | | false @@ -82,7 +82,7 @@ LL | | }; | |_____^ help: you can reduce it to: `a <= b` error: this if-then-else expression returns a bool literal - --> tests/ui/needless_bool/fixable.rs:84:5 + --> tests/ui/needless_bool/fixable.rs:92:5 | LL | / if a >= b { LL | | false @@ -92,7 +92,7 @@ LL | | }; | |_____^ help: you can reduce it to: `a < b` error: this if-then-else expression returns a bool literal - --> tests/ui/needless_bool/fixable.rs:112:5 + --> tests/ui/needless_bool/fixable.rs:121:5 | LL | / if x { LL | | return true; @@ -102,7 +102,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return x` error: this if-then-else expression returns a bool literal - --> tests/ui/needless_bool/fixable.rs:120:5 + --> tests/ui/needless_bool/fixable.rs:130:5 | LL | / if x { LL | | return false; @@ -112,7 +112,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return !x` error: this if-then-else expression returns a bool literal - --> tests/ui/needless_bool/fixable.rs:128:5 + --> tests/ui/needless_bool/fixable.rs:139:5 | LL | / if x && y { LL | | return true; @@ -122,7 +122,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return x && y` error: this if-then-else expression returns a bool literal - --> tests/ui/needless_bool/fixable.rs:136:5 + --> tests/ui/needless_bool/fixable.rs:148:5 | LL | / if x && y { LL | | return false; @@ -132,7 +132,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return !(x && y)` error: equality checks against true are unnecessary - --> tests/ui/needless_bool/fixable.rs:144:8 + --> tests/ui/needless_bool/fixable.rs:157:8 | LL | if x == true {}; | ^^^^^^^^^ help: try simplifying it as shown: `x` @@ -141,25 +141,25 @@ LL | if x == true {}; = help: to override `-D warnings` add `#[allow(clippy::bool_comparison)]` error: equality checks against false can be replaced by a negation - --> tests/ui/needless_bool/fixable.rs:148:8 + --> tests/ui/needless_bool/fixable.rs:162:8 | LL | if x == false {}; | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: equality checks against true are unnecessary - --> tests/ui/needless_bool/fixable.rs:158:8 + --> tests/ui/needless_bool/fixable.rs:173:8 | LL | if x == true {}; | ^^^^^^^^^ help: try simplifying it as shown: `x` error: equality checks against false can be replaced by a negation - --> tests/ui/needless_bool/fixable.rs:159:8 + --> tests/ui/needless_bool/fixable.rs:175:8 | LL | if x == false {}; | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: this if-then-else expression returns a bool literal - --> tests/ui/needless_bool/fixable.rs:168:12 + --> tests/ui/needless_bool/fixable.rs:185:12 | LL | } else if returns_bool() { | ____________^ @@ -170,7 +170,7 @@ LL | | }; | |_____^ help: you can reduce it to: `{ !returns_bool() }` error: this if-then-else expression returns a bool literal - --> tests/ui/needless_bool/fixable.rs:181:5 + --> tests/ui/needless_bool/fixable.rs:199:5 | LL | / if unsafe { no(4) } & 1 != 0 { LL | | true @@ -180,31 +180,31 @@ LL | | }; | |_____^ help: you can reduce it to: `(unsafe { no(4) } & 1 != 0)` error: this if-then-else expression returns a bool literal - --> tests/ui/needless_bool/fixable.rs:186:30 + --> tests/ui/needless_bool/fixable.rs:205:30 | LL | let _brackets_unneeded = if unsafe { no(4) } & 1 != 0 { true } else { false }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `unsafe { no(4) } & 1 != 0` error: this if-then-else expression returns a bool literal - --> tests/ui/needless_bool/fixable.rs:189:9 + --> tests/ui/needless_bool/fixable.rs:209:9 | LL | if unsafe { no(4) } & 1 != 0 { true } else { false } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `(unsafe { no(4) } & 1 != 0)` error: this if-then-else expression returns a bool literal - --> tests/ui/needless_bool/fixable.rs:200:14 + --> tests/ui/needless_bool/fixable.rs:221:14 | LL | let _x = if a && b { true } else { false }.then(|| todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `(a && b)` error: this if-then-else expression returns a bool literal - --> tests/ui/needless_bool/fixable.rs:201:14 + --> tests/ui/needless_bool/fixable.rs:223:14 | LL | let _x = if a && b { true } else { false } as u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `(a && b)` error: this if-then-else expression returns a bool literal - --> tests/ui/needless_bool/fixable.rs:204:14 + --> tests/ui/needless_bool/fixable.rs:227:14 | LL | let _x = if a { true } else { false }.then(|| todo!()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `a` diff --git a/tests/ui/needless_bool/simple.rs b/tests/ui/needless_bool/simple.rs index 588bb88f4461..40ffeae6c56f 100644 --- a/tests/ui/needless_bool/simple.rs +++ b/tests/ui/needless_bool/simple.rs @@ -16,11 +16,13 @@ fn main() { } else { true }; + //~^^^^^ needless_bool if x { false } else { false }; + //~^^^^^ needless_bool if x { x } else { @@ -36,6 +38,7 @@ fn bool_ret(x: bool) -> bool { } else { return true; }; + //~^^^^^ needless_bool } fn bool_ret2(x: bool) -> bool { @@ -44,4 +47,5 @@ fn bool_ret2(x: bool) -> bool { } else { return false; }; + //~^^^^^ needless_bool } diff --git a/tests/ui/needless_bool/simple.stderr b/tests/ui/needless_bool/simple.stderr index bf30a56f43e7..077e9b5df47c 100644 --- a/tests/ui/needless_bool/simple.stderr +++ b/tests/ui/needless_bool/simple.stderr @@ -12,7 +12,7 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::needless_bool)]` error: this if-then-else expression will always return false - --> tests/ui/needless_bool/simple.rs:19:5 + --> tests/ui/needless_bool/simple.rs:20:5 | LL | / if x { LL | | false @@ -22,7 +22,7 @@ LL | | }; | |_____^ error: this if-then-else expression will always return true - --> tests/ui/needless_bool/simple.rs:34:5 + --> tests/ui/needless_bool/simple.rs:36:5 | LL | / if x { LL | | return true; @@ -32,7 +32,7 @@ LL | | }; | |_____^ error: this if-then-else expression will always return false - --> tests/ui/needless_bool/simple.rs:42:5 + --> tests/ui/needless_bool/simple.rs:45:5 | LL | / if x { LL | | return false; diff --git a/tests/ui/needless_bool_assign.fixed b/tests/ui/needless_bool_assign.fixed index 7b10fe78c681..e0c717ecda21 100644 --- a/tests/ui/needless_bool_assign.fixed +++ b/tests/ui/needless_bool_assign.fixed @@ -11,7 +11,9 @@ fn main() { }; let mut a = Data { field: false }; a.field = random() && random(); + //~^^^^^ needless_bool_assign a.field = !(random() && random()); + //~^^^^^ needless_bool_assign // Do not lint… if random() { a.field = false; @@ -22,6 +24,8 @@ fn main() { // This one also triggers lint `clippy::if_same_then_else` // which does not suggest a rewrite. random(); a.field = true; + //~^^^^^ if_same_then_else + //~| needless_bool_assign let mut b = false; if random() { a.field = false; diff --git a/tests/ui/needless_bool_assign.rs b/tests/ui/needless_bool_assign.rs index 85c0a5777fee..3e4fecefa785 100644 --- a/tests/ui/needless_bool_assign.rs +++ b/tests/ui/needless_bool_assign.rs @@ -15,11 +15,13 @@ fn main() { } else { a.field = false } + //~^^^^^ needless_bool_assign if random() && random() { a.field = false; } else { a.field = true } + //~^^^^^ needless_bool_assign // Do not lint… if random() { a.field = false; @@ -34,6 +36,8 @@ fn main() { } else { a.field = true; } + //~^^^^^ if_same_then_else + //~| needless_bool_assign let mut b = false; if random() { a.field = false; diff --git a/tests/ui/needless_bool_assign.stderr b/tests/ui/needless_bool_assign.stderr index 2d80dded39c3..f33a4bc0c592 100644 --- a/tests/ui/needless_bool_assign.stderr +++ b/tests/ui/needless_bool_assign.stderr @@ -12,7 +12,7 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::needless_bool_assign)]` error: this if-then-else expression assigns a bool literal - --> tests/ui/needless_bool_assign.rs:18:5 + --> tests/ui/needless_bool_assign.rs:19:5 | LL | / if random() && random() { LL | | a.field = false; @@ -22,7 +22,7 @@ LL | | } | |_____^ help: you can reduce it to: `a.field = !(random() && random());` error: this if-then-else expression assigns a bool literal - --> tests/ui/needless_bool_assign.rs:32:5 + --> tests/ui/needless_bool_assign.rs:34:5 | LL | / if random() { LL | | a.field = true; @@ -32,7 +32,7 @@ LL | | } | |_____^ help: you can reduce it to: `random(); a.field = true;` error: this `if` has identical blocks - --> tests/ui/needless_bool_assign.rs:32:17 + --> tests/ui/needless_bool_assign.rs:34:17 | LL | if random() { | _________________^ @@ -41,7 +41,7 @@ LL | | } else { | |_____^ | note: same as this - --> tests/ui/needless_bool_assign.rs:34:12 + --> tests/ui/needless_bool_assign.rs:36:12 | LL | } else { | ____________^ diff --git a/tests/ui/needless_borrow.fixed b/tests/ui/needless_borrow.fixed index 2763830e09c9..d7d344452c5d 100644 --- a/tests/ui/needless_borrow.fixed +++ b/tests/ui/needless_borrow.fixed @@ -14,10 +14,14 @@ fn main() { let ref_a = &a; let _ = x(&a); // no warning let _ = x(&a); // warn + // + //~^^ needless_borrow let mut b = 5; mut_ref(&mut b); // no warning mut_ref(&mut b); // warn + // + //~^^ needless_borrow let s = &String::from("hi"); let s_ident = f(&s); // should not error, because `&String` implements Copy, but `String` does not @@ -30,14 +34,17 @@ fn main() { 45 => { println!("foo"); &a + //~^ needless_borrow }, 46 => &a, + //~^ needless_borrow 47 => { println!("foo"); loop { println!("{}", a); if a == 25 { break ref_a; + //~^ needless_borrow } } }, @@ -45,12 +52,17 @@ fn main() { }; let _ = x(&a); + //~^ needless_borrow let _ = x(&a); + //~^ needless_borrow let _ = x(&mut b); + //~^ needless_borrow let _ = x(ref_a); + //~^ needless_borrow { let b = &mut b; x(b); + //~^ needless_borrow } // Issue #8191 @@ -58,9 +70,13 @@ fn main() { let mut x = &mut x; mut_ref(x); + //~^ needless_borrow mut_ref(x); + //~^ needless_borrow let y: &mut i32 = x; + //~^ needless_borrow let y: &mut i32 = x; + //~^ needless_borrow let y = match 0 { // Don't lint. Removing the borrow would move 'x' @@ -70,12 +86,14 @@ fn main() { let y: &mut i32 = match 0 { // Lint here. The type given above triggers auto-borrow. 0 => x, + //~^ needless_borrow _ => &mut *x, }; fn ref_mut_i32(_: &mut i32) {} ref_mut_i32(match 0 { // Lint here. The type given above triggers auto-borrow. 0 => x, + //~^ needless_borrow _ => &mut *x, }); // use 'x' after to make sure it's still usable in the fixed code. @@ -88,8 +106,10 @@ fn main() { let x = (1, 2); let _ = x.0; + //~^ needless_borrow let x = &x as *const (i32, i32); let _ = unsafe { (*x).0 }; + //~^ needless_borrow // Issue #8367 trait Foo { @@ -100,6 +120,7 @@ fn main() { } (&()).foo(); // Don't lint. `()` doesn't implement `Foo` (&()).foo(); + //~^ needless_borrow impl Foo for i32 { fn foo(self) {} @@ -109,6 +130,7 @@ fn main() { } (&5).foo(); // Don't lint. `5` will call `::foo` (&5).foo(); + //~^ needless_borrow trait FooRef { fn foo_ref(&self); @@ -135,6 +157,7 @@ fn main() { // issue #11786 let x: (&str,) = ("",); + //~^ needless_borrow } #[allow(clippy::needless_borrowed_reference)] @@ -177,6 +200,7 @@ mod issue9160 { { fn calls_field(&self) -> T { (self.f)() + //~^ needless_borrow } } @@ -186,6 +210,7 @@ mod issue9160 { { fn calls_mut_field(&mut self) -> T { (self.f)() + //~^ needless_borrow } } } @@ -223,6 +248,7 @@ fn issue9383() { }; let _ = &mut (&mut x.u).x; let _ = &mut { x.u }.x; + //~^ needless_borrow let _ = &mut ({ &mut x.u }).x; let mut x = U { @@ -230,11 +256,14 @@ fn issue9383() { }; let _ = &mut (&mut x.u).x; let _ = &mut { x.u }.x; + //~^ needless_borrow let _ = &mut ({ &mut x.u }).x; let mut x = U { u: Wrap(Foo { x: 0 }) }; let _ = &mut x.u.x; + //~^ needless_borrow let _ = &mut { x.u }.x; + //~^ needless_borrow let _ = &mut ({ &mut x.u }).x; } } @@ -256,6 +285,7 @@ fn issue_12268() { let option = Some((&1,)); let x = (&1,); option.unwrap_or((x.0,)); - //~^ ERROR: this expression creates a reference which is immediately dereferenced by the + //~^ needless_borrow + // compiler } diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs index b46f82b18c64..1f05b90b4728 100644 --- a/tests/ui/needless_borrow.rs +++ b/tests/ui/needless_borrow.rs @@ -14,10 +14,14 @@ fn main() { let ref_a = &a; let _ = x(&a); // no warning let _ = x(&&a); // warn + // + //~^^ needless_borrow let mut b = 5; mut_ref(&mut b); // no warning mut_ref(&mut &mut b); // warn + // + //~^^ needless_borrow let s = &String::from("hi"); let s_ident = f(&s); // should not error, because `&String` implements Copy, but `String` does not @@ -30,14 +34,17 @@ fn main() { 45 => { println!("foo"); &&a + //~^ needless_borrow }, 46 => &&a, + //~^ needless_borrow 47 => { println!("foo"); loop { println!("{}", a); if a == 25 { break &ref_a; + //~^ needless_borrow } } }, @@ -45,12 +52,17 @@ fn main() { }; let _ = x(&&&a); + //~^ needless_borrow let _ = x(&mut &&a); + //~^ needless_borrow let _ = x(&&&mut b); + //~^ needless_borrow let _ = x(&&ref_a); + //~^ needless_borrow { let b = &mut b; x(&b); + //~^ needless_borrow } // Issue #8191 @@ -58,9 +70,13 @@ fn main() { let mut x = &mut x; mut_ref(&mut x); + //~^ needless_borrow mut_ref(&mut &mut x); + //~^ needless_borrow let y: &mut i32 = &mut x; + //~^ needless_borrow let y: &mut i32 = &mut &mut x; + //~^ needless_borrow let y = match 0 { // Don't lint. Removing the borrow would move 'x' @@ -70,12 +86,14 @@ fn main() { let y: &mut i32 = match 0 { // Lint here. The type given above triggers auto-borrow. 0 => &mut x, + //~^ needless_borrow _ => &mut *x, }; fn ref_mut_i32(_: &mut i32) {} ref_mut_i32(match 0 { // Lint here. The type given above triggers auto-borrow. 0 => &mut x, + //~^ needless_borrow _ => &mut *x, }); // use 'x' after to make sure it's still usable in the fixed code. @@ -88,8 +106,10 @@ fn main() { let x = (1, 2); let _ = (&x).0; + //~^ needless_borrow let x = &x as *const (i32, i32); let _ = unsafe { (&*x).0 }; + //~^ needless_borrow // Issue #8367 trait Foo { @@ -100,6 +120,7 @@ fn main() { } (&()).foo(); // Don't lint. `()` doesn't implement `Foo` (&&()).foo(); + //~^ needless_borrow impl Foo for i32 { fn foo(self) {} @@ -109,6 +130,7 @@ fn main() { } (&5).foo(); // Don't lint. `5` will call `::foo` (&&5).foo(); + //~^ needless_borrow trait FooRef { fn foo_ref(&self); @@ -135,6 +157,7 @@ fn main() { // issue #11786 let x: (&str,) = (&"",); + //~^ needless_borrow } #[allow(clippy::needless_borrowed_reference)] @@ -177,6 +200,7 @@ mod issue9160 { { fn calls_field(&self) -> T { (&self.f)() + //~^ needless_borrow } } @@ -186,6 +210,7 @@ mod issue9160 { { fn calls_mut_field(&mut self) -> T { (&mut self.f)() + //~^ needless_borrow } } } @@ -223,6 +248,7 @@ fn issue9383() { }; let _ = &mut (&mut x.u).x; let _ = &mut (&mut { x.u }).x; + //~^ needless_borrow let _ = &mut ({ &mut x.u }).x; let mut x = U { @@ -230,11 +256,14 @@ fn issue9383() { }; let _ = &mut (&mut x.u).x; let _ = &mut (&mut { x.u }).x; + //~^ needless_borrow let _ = &mut ({ &mut x.u }).x; let mut x = U { u: Wrap(Foo { x: 0 }) }; let _ = &mut (&mut x.u).x; + //~^ needless_borrow let _ = &mut (&mut { x.u }).x; + //~^ needless_borrow let _ = &mut ({ &mut x.u }).x; } } @@ -256,6 +285,7 @@ fn issue_12268() { let option = Some((&1,)); let x = (&1,); option.unwrap_or((&x.0,)); - //~^ ERROR: this expression creates a reference which is immediately dereferenced by the + //~^ needless_borrow + // compiler } diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr index 4b2b17e7e570..b036b1e47d18 100644 --- a/tests/ui/needless_borrow.stderr +++ b/tests/ui/needless_borrow.stderr @@ -8,163 +8,163 @@ LL | let _ = x(&&a); // warn = help: to override `-D warnings` add `#[allow(clippy::needless_borrow)]` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:20:13 + --> tests/ui/needless_borrow.rs:22:13 | LL | mut_ref(&mut &mut b); // warn | ^^^^^^^^^^^ help: change this to: `&mut b` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:32:13 + --> tests/ui/needless_borrow.rs:36:13 | LL | &&a | ^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:34:15 + --> tests/ui/needless_borrow.rs:39:15 | LL | 46 => &&a, | ^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:40:27 + --> tests/ui/needless_borrow.rs:46:27 | LL | break &ref_a; | ^^^^^^ help: change this to: `ref_a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:47:15 + --> tests/ui/needless_borrow.rs:54:15 | LL | let _ = x(&&&a); | ^^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:48:15 + --> tests/ui/needless_borrow.rs:56:15 | LL | let _ = x(&mut &&a); | ^^^^^^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:49:15 + --> tests/ui/needless_borrow.rs:58:15 | LL | let _ = x(&&&mut b); | ^^^^^^^^ help: change this to: `&mut b` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:50:15 + --> tests/ui/needless_borrow.rs:60:15 | LL | let _ = x(&&ref_a); | ^^^^^^^ help: change this to: `ref_a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:53:11 + --> tests/ui/needless_borrow.rs:64:11 | LL | x(&b); | ^^ help: change this to: `b` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:60:13 + --> tests/ui/needless_borrow.rs:72:13 | LL | mut_ref(&mut x); | ^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:61:13 + --> tests/ui/needless_borrow.rs:74:13 | LL | mut_ref(&mut &mut x); | ^^^^^^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:62:23 + --> tests/ui/needless_borrow.rs:76:23 | LL | let y: &mut i32 = &mut x; | ^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:63:23 + --> tests/ui/needless_borrow.rs:78:23 | LL | let y: &mut i32 = &mut &mut x; | ^^^^^^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:72:14 + --> tests/ui/needless_borrow.rs:88:14 | LL | 0 => &mut x, | ^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:78:14 + --> tests/ui/needless_borrow.rs:95:14 | LL | 0 => &mut x, | ^^^^^^ help: change this to: `x` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:90:13 + --> tests/ui/needless_borrow.rs:108:13 | LL | let _ = (&x).0; | ^^^^ help: change this to: `x` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:92:22 + --> tests/ui/needless_borrow.rs:111:22 | LL | let _ = unsafe { (&*x).0 }; | ^^^^^ help: change this to: `(*x)` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:102:5 + --> tests/ui/needless_borrow.rs:122:5 | LL | (&&()).foo(); | ^^^^^^ help: change this to: `(&())` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:111:5 + --> tests/ui/needless_borrow.rs:132:5 | LL | (&&5).foo(); | ^^^^^ help: change this to: `(&5)` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:137:23 + --> tests/ui/needless_borrow.rs:159:23 | LL | let x: (&str,) = (&"",); | ^^^ help: change this to: `""` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:179:13 + --> tests/ui/needless_borrow.rs:202:13 | LL | (&self.f)() | ^^^^^^^^^ help: change this to: `(self.f)` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:188:13 + --> tests/ui/needless_borrow.rs:212:13 | LL | (&mut self.f)() | ^^^^^^^^^^^^^ help: change this to: `(self.f)` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:225:22 + --> tests/ui/needless_borrow.rs:250:22 | LL | let _ = &mut (&mut { x.u }).x; | ^^^^^^^^^^^^^^ help: change this to: `{ x.u }` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:232:22 + --> tests/ui/needless_borrow.rs:258:22 | LL | let _ = &mut (&mut { x.u }).x; | ^^^^^^^^^^^^^^ help: change this to: `{ x.u }` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:236:22 + --> tests/ui/needless_borrow.rs:263:22 | LL | let _ = &mut (&mut x.u).x; | ^^^^^^^^^^ help: change this to: `x.u` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:237:22 + --> tests/ui/needless_borrow.rs:265:22 | LL | let _ = &mut (&mut { x.u }).x; | ^^^^^^^^^^^^^^ help: change this to: `{ x.u }` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:258:23 + --> tests/ui/needless_borrow.rs:287:23 | LL | option.unwrap_or((&x.0,)); | ^^^^ help: change this to: `x.0` diff --git a/tests/ui/needless_borrow_pat.fixed b/tests/ui/needless_borrow_pat.fixed index 8f8887f08a27..fe966a716df7 100644 --- a/tests/ui/needless_borrow_pat.fixed +++ b/tests/ui/needless_borrow_pat.fixed @@ -57,22 +57,22 @@ fn main() { // Err, reference to a &String let _: &String = match Some(&x) { Some(x) => x, - //~^ ERROR: this pattern creates a reference to a reference - //~| NOTE: `-D clippy::needless-borrow` implied by `-D warnings` + //~^ needless_borrow None => return, }; // Err, reference to a &String. let _: &String = match Some(&x) { Some(x) => x, - //~^ ERROR: this pattern creates a reference to a reference + //~^ needless_borrow None => return, }; // Err, reference to a &String let _: &String = match Some(&x) { Some(x) => { - //~^ ERROR: this pattern creates a reference to a reference + //~^ needless_borrow + f1(x); f1(x); x @@ -83,19 +83,21 @@ fn main() { // Err, reference to a &String match Some(&x) { Some(x) => m1!(x), - //~^ ERROR: this pattern creates a reference to a reference + //~^ needless_borrow None => return, }; // Err, reference to a &String let _ = |&x: &&String| { - //~^ ERROR: this pattern creates a reference to a reference + //~^ needless_borrow + let _: &String = x; }; // Err, reference to a &String let (y,) = (&x,); - //~^ ERROR: this pattern creates a reference to a reference + //~^ needless_borrow + let _: &String = y; let y = &&x; @@ -106,7 +108,7 @@ fn main() { // Err, reference to a &u32. Don't suggest adding a reference to the field access. let _: u32 = match Some(&x) { Some(x) => x.0, - //~^ ERROR: this pattern creates a reference to a reference + //~^ needless_borrow None => return, }; @@ -117,14 +119,15 @@ fn main() { // Err, reference to &u32. let _: &u32 = match E::A(&0) { E::A(x) | E::B(x) => x, - //~^ ERROR: this pattern creates a reference to a reference + //~^ needless_borrow }; // Err, reference to &String. if_chain! { if true; if let Some(x) = Some(&String::new()); - //~^ ERROR: this pattern creates a reference to a reference + //~^ needless_borrow + then { f1(x); } @@ -133,7 +136,8 @@ fn main() { // Err, reference to a &String fn f2<'a>(&x: &&'a String) -> &'a String { - //~^ ERROR: this pattern creates a reference to a reference + //~^ needless_borrow + let _: &String = x; x } @@ -141,7 +145,8 @@ fn f2<'a>(&x: &&'a String) -> &'a String { trait T1 { // Err, reference to a &String fn f(&x: &&String) { - //~^ ERROR: this pattern creates a reference to a reference + //~^ needless_borrow + let _: &String = x; } } @@ -150,7 +155,8 @@ struct S; impl T1 for S { // Err, reference to a &String fn f(&x: &&String) { - //~^ ERROR: this pattern creates a reference to a reference + //~^ needless_borrow + let _: &String = x; } } diff --git a/tests/ui/needless_borrow_pat.rs b/tests/ui/needless_borrow_pat.rs index 56dbd923f256..a6b43855cad1 100644 --- a/tests/ui/needless_borrow_pat.rs +++ b/tests/ui/needless_borrow_pat.rs @@ -57,22 +57,22 @@ fn main() { // Err, reference to a &String let _: &String = match Some(&x) { Some(ref x) => x, - //~^ ERROR: this pattern creates a reference to a reference - //~| NOTE: `-D clippy::needless-borrow` implied by `-D warnings` + //~^ needless_borrow None => return, }; // Err, reference to a &String. let _: &String = match Some(&x) { Some(ref x) => *x, - //~^ ERROR: this pattern creates a reference to a reference + //~^ needless_borrow None => return, }; // Err, reference to a &String let _: &String = match Some(&x) { Some(ref x) => { - //~^ ERROR: this pattern creates a reference to a reference + //~^ needless_borrow + f1(x); f1(*x); x @@ -83,19 +83,21 @@ fn main() { // Err, reference to a &String match Some(&x) { Some(ref x) => m1!(x), - //~^ ERROR: this pattern creates a reference to a reference + //~^ needless_borrow None => return, }; // Err, reference to a &String let _ = |&ref x: &&String| { - //~^ ERROR: this pattern creates a reference to a reference + //~^ needless_borrow + let _: &String = x; }; // Err, reference to a &String let (ref y,) = (&x,); - //~^ ERROR: this pattern creates a reference to a reference + //~^ needless_borrow + let _: &String = *y; let y = &&x; @@ -106,7 +108,7 @@ fn main() { // Err, reference to a &u32. Don't suggest adding a reference to the field access. let _: u32 = match Some(&x) { Some(ref x) => x.0, - //~^ ERROR: this pattern creates a reference to a reference + //~^ needless_borrow None => return, }; @@ -117,14 +119,15 @@ fn main() { // Err, reference to &u32. let _: &u32 = match E::A(&0) { E::A(ref x) | E::B(ref x) => *x, - //~^ ERROR: this pattern creates a reference to a reference + //~^ needless_borrow }; // Err, reference to &String. if_chain! { if true; if let Some(ref x) = Some(&String::new()); - //~^ ERROR: this pattern creates a reference to a reference + //~^ needless_borrow + then { f1(x); } @@ -133,7 +136,8 @@ fn main() { // Err, reference to a &String fn f2<'a>(&ref x: &&'a String) -> &'a String { - //~^ ERROR: this pattern creates a reference to a reference + //~^ needless_borrow + let _: &String = x; *x } @@ -141,7 +145,8 @@ fn f2<'a>(&ref x: &&'a String) -> &'a String { trait T1 { // Err, reference to a &String fn f(&ref x: &&String) { - //~^ ERROR: this pattern creates a reference to a reference + //~^ needless_borrow + let _: &String = x; } } @@ -150,7 +155,8 @@ struct S; impl T1 for S { // Err, reference to a &String fn f(&ref x: &&String) { - //~^ ERROR: this pattern creates a reference to a reference + //~^ needless_borrow + let _: &String = *x; } } diff --git a/tests/ui/needless_borrow_pat.stderr b/tests/ui/needless_borrow_pat.stderr index 035376cabaf4..25c570eb7ff7 100644 --- a/tests/ui/needless_borrow_pat.stderr +++ b/tests/ui/needless_borrow_pat.stderr @@ -8,7 +8,7 @@ LL | Some(ref x) => x, = help: to override `-D warnings` add `#[allow(clippy::needless_borrow)]` error: this pattern creates a reference to a reference - --> tests/ui/needless_borrow_pat.rs:67:14 + --> tests/ui/needless_borrow_pat.rs:66:14 | LL | Some(ref x) => *x, | ^^^^^ @@ -20,7 +20,7 @@ LL + Some(x) => x, | error: this pattern creates a reference to a reference - --> tests/ui/needless_borrow_pat.rs:74:14 + --> tests/ui/needless_borrow_pat.rs:73:14 | LL | Some(ref x) => { | ^^^^^ @@ -29,6 +29,7 @@ help: try | LL ~ Some(x) => { LL | +LL | LL | f1(x); LL ~ f1(x); | @@ -46,7 +47,7 @@ LL | let _ = |&ref x: &&String| { | ^^^^^ help: try: `x` error: this pattern creates a reference to a reference - --> tests/ui/needless_borrow_pat.rs:97:10 + --> tests/ui/needless_borrow_pat.rs:98:10 | LL | let (ref y,) = (&x,); | ^^^^^ @@ -55,17 +56,18 @@ help: try | LL ~ let (y,) = (&x,); LL | +LL | LL ~ let _: &String = y; | error: this pattern creates a reference to a reference - --> tests/ui/needless_borrow_pat.rs:108:14 + --> tests/ui/needless_borrow_pat.rs:110:14 | LL | Some(ref x) => x.0, | ^^^^^ help: try: `x` error: this pattern creates a reference to a reference - --> tests/ui/needless_borrow_pat.rs:119:14 + --> tests/ui/needless_borrow_pat.rs:121:14 | LL | E::A(ref x) | E::B(ref x) => *x, | ^^^^^ ^^^^^ @@ -77,13 +79,13 @@ LL + E::A(x) | E::B(x) => x, | error: this pattern creates a reference to a reference - --> tests/ui/needless_borrow_pat.rs:126:21 + --> tests/ui/needless_borrow_pat.rs:128:21 | LL | if let Some(ref x) = Some(&String::new()); | ^^^^^ help: try: `x` error: this pattern creates a reference to a reference - --> tests/ui/needless_borrow_pat.rs:135:12 + --> tests/ui/needless_borrow_pat.rs:138:12 | LL | fn f2<'a>(&ref x: &&'a String) -> &'a String { | ^^^^^ @@ -92,18 +94,19 @@ help: try | LL ~ fn f2<'a>(&x: &&'a String) -> &'a String { LL | +LL | LL | let _: &String = x; LL ~ x | error: this pattern creates a reference to a reference - --> tests/ui/needless_borrow_pat.rs:143:11 + --> tests/ui/needless_borrow_pat.rs:147:11 | LL | fn f(&ref x: &&String) { | ^^^^^ help: try: `x` error: this pattern creates a reference to a reference - --> tests/ui/needless_borrow_pat.rs:152:11 + --> tests/ui/needless_borrow_pat.rs:157:11 | LL | fn f(&ref x: &&String) { | ^^^^^ @@ -112,6 +115,7 @@ help: try | LL ~ fn f(&x: &&String) { LL | +LL | LL ~ let _: &String = x; | diff --git a/tests/ui/needless_borrowed_ref.fixed b/tests/ui/needless_borrowed_ref.fixed index 5d2fd0950ee4..e4504bc2784c 100644 --- a/tests/ui/needless_borrowed_ref.fixed +++ b/tests/ui/needless_borrowed_ref.fixed @@ -28,32 +28,48 @@ fn should_lint( ) { let mut v = Vec::::new(); let _ = v.iter_mut().filter(|a| a.is_empty()); + //~^ needless_borrowed_reference let var = 3; let thingy = Some(&var); if let Some(v) = thingy {} + //~^ needless_borrowed_reference if let &[a, ref b] = slice_of_refs {} + //~^ needless_borrowed_reference let [a, ..] = &array; + //~^ needless_borrowed_reference let [a, b, ..] = &array; + //~^ needless_borrowed_reference if let [a, b] = slice {} + //~^ needless_borrowed_reference if let [a, b] = &vec[..] {} + //~^ needless_borrowed_reference if let [a, b, ..] = slice {} + //~^ needless_borrowed_reference if let [a, .., b] = slice {} + //~^ needless_borrowed_reference if let [.., a, b] = slice {} + //~^ needless_borrowed_reference if let [a, _] = slice {} + //~^ needless_borrowed_reference if let (a, b, c) = &tuple {} + //~^ needless_borrowed_reference if let (a, _, c) = &tuple {} + //~^ needless_borrowed_reference if let (a, ..) = &tuple {} + //~^ needless_borrowed_reference if let TupleStruct(a, ..) = &tuple_struct {} + //~^ needless_borrowed_reference if let Struct { + //~^ needless_borrowed_reference a, b: b, c: renamed, @@ -61,6 +77,7 @@ fn should_lint( {} if let Struct { a, b: _, .. } = &s {} + //~^ needless_borrowed_reference } fn should_not_lint( diff --git a/tests/ui/needless_borrowed_ref.rs b/tests/ui/needless_borrowed_ref.rs index 556fd3a35427..7edfda60b979 100644 --- a/tests/ui/needless_borrowed_ref.rs +++ b/tests/ui/needless_borrowed_ref.rs @@ -28,32 +28,48 @@ fn should_lint( ) { let mut v = Vec::::new(); let _ = v.iter_mut().filter(|&ref a| a.is_empty()); + //~^ needless_borrowed_reference let var = 3; let thingy = Some(&var); if let Some(&ref v) = thingy {} + //~^ needless_borrowed_reference if let &[&ref a, ref b] = slice_of_refs {} + //~^ needless_borrowed_reference let &[ref a, ..] = &array; + //~^ needless_borrowed_reference let &[ref a, ref b, ..] = &array; + //~^ needless_borrowed_reference if let &[ref a, ref b] = slice {} + //~^ needless_borrowed_reference if let &[ref a, ref b] = &vec[..] {} + //~^ needless_borrowed_reference if let &[ref a, ref b, ..] = slice {} + //~^ needless_borrowed_reference if let &[ref a, .., ref b] = slice {} + //~^ needless_borrowed_reference if let &[.., ref a, ref b] = slice {} + //~^ needless_borrowed_reference if let &[ref a, _] = slice {} + //~^ needless_borrowed_reference if let &(ref a, ref b, ref c) = &tuple {} + //~^ needless_borrowed_reference if let &(ref a, _, ref c) = &tuple {} + //~^ needless_borrowed_reference if let &(ref a, ..) = &tuple {} + //~^ needless_borrowed_reference if let &TupleStruct(ref a, ..) = &tuple_struct {} + //~^ needless_borrowed_reference if let &Struct { + //~^ needless_borrowed_reference ref a, b: ref b, c: ref renamed, @@ -61,6 +77,7 @@ fn should_lint( {} if let &Struct { ref a, b: _, .. } = &s {} + //~^ needless_borrowed_reference } fn should_not_lint( diff --git a/tests/ui/needless_borrowed_ref.stderr b/tests/ui/needless_borrowed_ref.stderr index b8181e2805c9..bfa3cafdedeb 100644 --- a/tests/ui/needless_borrowed_ref.stderr +++ b/tests/ui/needless_borrowed_ref.stderr @@ -13,7 +13,7 @@ LL + let _ = v.iter_mut().filter(|a| a.is_empty()); | error: this pattern takes a reference on something that is being dereferenced - --> tests/ui/needless_borrowed_ref.rs:34:17 + --> tests/ui/needless_borrowed_ref.rs:35:17 | LL | if let Some(&ref v) = thingy {} | ^^^^^^ @@ -25,7 +25,7 @@ LL + if let Some(v) = thingy {} | error: this pattern takes a reference on something that is being dereferenced - --> tests/ui/needless_borrowed_ref.rs:36:14 + --> tests/ui/needless_borrowed_ref.rs:38:14 | LL | if let &[&ref a, ref b] = slice_of_refs {} | ^^^^^^ @@ -37,7 +37,7 @@ LL + if let &[a, ref b] = slice_of_refs {} | error: dereferencing a slice pattern where every element takes a reference - --> tests/ui/needless_borrowed_ref.rs:38:9 + --> tests/ui/needless_borrowed_ref.rs:41:9 | LL | let &[ref a, ..] = &array; | ^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + let [a, ..] = &array; | error: dereferencing a slice pattern where every element takes a reference - --> tests/ui/needless_borrowed_ref.rs:39:9 + --> tests/ui/needless_borrowed_ref.rs:43:9 | LL | let &[ref a, ref b, ..] = &array; | ^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + let [a, b, ..] = &array; | error: dereferencing a slice pattern where every element takes a reference - --> tests/ui/needless_borrowed_ref.rs:41:12 + --> tests/ui/needless_borrowed_ref.rs:46:12 | LL | if let &[ref a, ref b] = slice {} | ^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + if let [a, b] = slice {} | error: dereferencing a slice pattern where every element takes a reference - --> tests/ui/needless_borrowed_ref.rs:42:12 + --> tests/ui/needless_borrowed_ref.rs:48:12 | LL | if let &[ref a, ref b] = &vec[..] {} | ^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + if let [a, b] = &vec[..] {} | error: dereferencing a slice pattern where every element takes a reference - --> tests/ui/needless_borrowed_ref.rs:44:12 + --> tests/ui/needless_borrowed_ref.rs:51:12 | LL | if let &[ref a, ref b, ..] = slice {} | ^^^^^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL + if let [a, b, ..] = slice {} | error: dereferencing a slice pattern where every element takes a reference - --> tests/ui/needless_borrowed_ref.rs:45:12 + --> tests/ui/needless_borrowed_ref.rs:53:12 | LL | if let &[ref a, .., ref b] = slice {} | ^^^^^^^^^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL + if let [a, .., b] = slice {} | error: dereferencing a slice pattern where every element takes a reference - --> tests/ui/needless_borrowed_ref.rs:46:12 + --> tests/ui/needless_borrowed_ref.rs:55:12 | LL | if let &[.., ref a, ref b] = slice {} | ^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL + if let [.., a, b] = slice {} | error: dereferencing a slice pattern where every element takes a reference - --> tests/ui/needless_borrowed_ref.rs:48:12 + --> tests/ui/needless_borrowed_ref.rs:58:12 | LL | if let &[ref a, _] = slice {} | ^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL + if let [a, _] = slice {} | error: dereferencing a tuple pattern where every element takes a reference - --> tests/ui/needless_borrowed_ref.rs:50:12 + --> tests/ui/needless_borrowed_ref.rs:61:12 | LL | if let &(ref a, ref b, ref c) = &tuple {} | ^^^^^^^^^^^^^^^^^^^^^^ @@ -145,7 +145,7 @@ LL + if let (a, b, c) = &tuple {} | error: dereferencing a tuple pattern where every element takes a reference - --> tests/ui/needless_borrowed_ref.rs:51:12 + --> tests/ui/needless_borrowed_ref.rs:63:12 | LL | if let &(ref a, _, ref c) = &tuple {} | ^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL + if let (a, _, c) = &tuple {} | error: dereferencing a tuple pattern where every element takes a reference - --> tests/ui/needless_borrowed_ref.rs:52:12 + --> tests/ui/needless_borrowed_ref.rs:65:12 | LL | if let &(ref a, ..) = &tuple {} | ^^^^^^^^^^^^ @@ -169,7 +169,7 @@ LL + if let (a, ..) = &tuple {} | error: dereferencing a tuple pattern where every element takes a reference - --> tests/ui/needless_borrowed_ref.rs:54:12 + --> tests/ui/needless_borrowed_ref.rs:68:12 | LL | if let &TupleStruct(ref a, ..) = &tuple_struct {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -181,10 +181,11 @@ LL + if let TupleStruct(a, ..) = &tuple_struct {} | error: dereferencing a struct pattern where every field's pattern takes a reference - --> tests/ui/needless_borrowed_ref.rs:56:12 + --> tests/ui/needless_borrowed_ref.rs:71:12 | LL | if let &Struct { | ____________^ +LL | | LL | | ref a, LL | | b: ref b, LL | | c: ref renamed, @@ -194,13 +195,14 @@ LL | | } = &s help: try removing the `&` and `ref` parts | LL ~ if let Struct { +LL | LL ~ a, LL ~ b: b, LL ~ c: renamed, | error: dereferencing a struct pattern where every field's pattern takes a reference - --> tests/ui/needless_borrowed_ref.rs:63:12 + --> tests/ui/needless_borrowed_ref.rs:79:12 | LL | if let &Struct { ref a, b: _, .. } = &s {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/needless_borrows_for_generic_args.fixed b/tests/ui/needless_borrows_for_generic_args.fixed index c1dc8b5e8d09..8dea0d259772 100644 --- a/tests/ui/needless_borrows_for_generic_args.fixed +++ b/tests/ui/needless_borrows_for_generic_args.fixed @@ -14,11 +14,14 @@ use std::process::Command; fn main() { let _ = Command::new("ls").args(["-a", "-l"]).status().unwrap(); + //~^ needless_borrows_for_generic_args let _ = Path::new(".").join("."); + //~^ needless_borrows_for_generic_args let _ = Any::type_id(&""); // Don't lint. `Any` is only bound let _ = Box::new(&""); // Don't lint. Type parameter appears in return type let _ = Some("").unwrap_or(&""); let _ = std::fs::write("x", "".to_string()); + //~^ needless_borrows_for_generic_args { #[derive(Clone, Copy)] @@ -34,6 +37,7 @@ fn main() { fn deref_target_is_x>(_: T) {} deref_target_is_x(X); + //~^ needless_borrows_for_generic_args } { fn multiple_constraints(_: T) @@ -47,6 +51,7 @@ fn main() { } multiple_constraints([[""]]); + //~^ needless_borrows_for_generic_args } { #[derive(Clone, Copy)] @@ -67,6 +72,7 @@ fn main() { } multiple_constraints_normalizes_to_same(X, X); + //~^ needless_borrows_for_generic_args } { fn only_sized(_: T) {} @@ -125,6 +131,7 @@ fn main() { #[allow(unused_mut)] fn warn(mut x: &mut Iter) { takes_iter(x) + //~^ needless_borrows_for_generic_args } } #[clippy::msrv = "1.52.0"] @@ -134,6 +141,7 @@ fn main() { #[clippy::msrv = "1.53.0"] { let _ = Command::new("ls").args(["-a", "-l"]).status().unwrap(); + //~^ needless_borrows_for_generic_args }; { let env = "env".to_owned(); @@ -245,6 +253,7 @@ fn main() { // 8 foo::<&[u8; 100]>(&a); foo(a); + //~^ needless_borrows_for_generic_args } { struct S; @@ -329,9 +338,13 @@ fn main() { let x = String::new(); f(&x); // Don't lint, not a copy, makes it unavailable later f(String::new()); // Lint, makes no difference + // + //~^^ needless_borrows_for_generic_args let y = "".to_owned(); f(&y); // Don't lint f("".to_owned()); // Lint + // + //~^^ needless_borrows_for_generic_args } { fn takes_writer(_: T) {} diff --git a/tests/ui/needless_borrows_for_generic_args.rs b/tests/ui/needless_borrows_for_generic_args.rs index c7f66824d581..bc2db6774e96 100644 --- a/tests/ui/needless_borrows_for_generic_args.rs +++ b/tests/ui/needless_borrows_for_generic_args.rs @@ -14,11 +14,14 @@ use std::process::Command; fn main() { let _ = Command::new("ls").args(&["-a", "-l"]).status().unwrap(); + //~^ needless_borrows_for_generic_args let _ = Path::new(".").join(&&"."); + //~^ needless_borrows_for_generic_args let _ = Any::type_id(&""); // Don't lint. `Any` is only bound let _ = Box::new(&""); // Don't lint. Type parameter appears in return type let _ = Some("").unwrap_or(&""); let _ = std::fs::write("x", &"".to_string()); + //~^ needless_borrows_for_generic_args { #[derive(Clone, Copy)] @@ -34,6 +37,7 @@ fn main() { fn deref_target_is_x>(_: T) {} deref_target_is_x(&X); + //~^ needless_borrows_for_generic_args } { fn multiple_constraints(_: T) @@ -47,6 +51,7 @@ fn main() { } multiple_constraints(&[[""]]); + //~^ needless_borrows_for_generic_args } { #[derive(Clone, Copy)] @@ -67,6 +72,7 @@ fn main() { } multiple_constraints_normalizes_to_same(&X, X); + //~^ needless_borrows_for_generic_args } { fn only_sized(_: T) {} @@ -125,6 +131,7 @@ fn main() { #[allow(unused_mut)] fn warn(mut x: &mut Iter) { takes_iter(&mut x) + //~^ needless_borrows_for_generic_args } } #[clippy::msrv = "1.52.0"] @@ -134,6 +141,7 @@ fn main() { #[clippy::msrv = "1.53.0"] { let _ = Command::new("ls").args(&["-a", "-l"]).status().unwrap(); + //~^ needless_borrows_for_generic_args }; { let env = "env".to_owned(); @@ -245,6 +253,7 @@ fn main() { // 8 foo::<&[u8; 100]>(&a); foo(&a); + //~^ needless_borrows_for_generic_args } { struct S; @@ -329,9 +338,13 @@ fn main() { let x = String::new(); f(&x); // Don't lint, not a copy, makes it unavailable later f(&String::new()); // Lint, makes no difference + // + //~^^ needless_borrows_for_generic_args let y = "".to_owned(); f(&y); // Don't lint f(&"".to_owned()); // Lint + // + //~^^ needless_borrows_for_generic_args } { fn takes_writer(_: T) {} diff --git a/tests/ui/needless_borrows_for_generic_args.stderr b/tests/ui/needless_borrows_for_generic_args.stderr index fba0755d14b5..8829854e3073 100644 --- a/tests/ui/needless_borrows_for_generic_args.stderr +++ b/tests/ui/needless_borrows_for_generic_args.stderr @@ -8,61 +8,61 @@ LL | let _ = Command::new("ls").args(&["-a", "-l"]).status().unwrap(); = help: to override `-D warnings` add `#[allow(clippy::needless_borrows_for_generic_args)]` error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:17:33 + --> tests/ui/needless_borrows_for_generic_args.rs:18:33 | LL | let _ = Path::new(".").join(&&"."); | ^^^^^ help: change this to: `"."` error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:21:33 + --> tests/ui/needless_borrows_for_generic_args.rs:23:33 | LL | let _ = std::fs::write("x", &"".to_string()); | ^^^^^^^^^^^^^^^ help: change this to: `"".to_string()` error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:36:27 + --> tests/ui/needless_borrows_for_generic_args.rs:39:27 | LL | deref_target_is_x(&X); | ^^ help: change this to: `X` error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:49:30 + --> tests/ui/needless_borrows_for_generic_args.rs:53:30 | LL | multiple_constraints(&[[""]]); | ^^^^^^^ help: change this to: `[[""]]` error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:69:49 + --> tests/ui/needless_borrows_for_generic_args.rs:74:49 | LL | multiple_constraints_normalizes_to_same(&X, X); | ^^ help: change this to: `X` error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:127:24 + --> tests/ui/needless_borrows_for_generic_args.rs:133:24 | LL | takes_iter(&mut x) | ^^^^^^ help: change this to: `x` error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:136:41 + --> tests/ui/needless_borrows_for_generic_args.rs:143:41 | LL | let _ = Command::new("ls").args(&["-a", "-l"]).status().unwrap(); | ^^^^^^^^^^^^^ help: change this to: `["-a", "-l"]` error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:247:13 + --> tests/ui/needless_borrows_for_generic_args.rs:255:13 | LL | foo(&a); | ^^ help: change this to: `a` error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:331:11 + --> tests/ui/needless_borrows_for_generic_args.rs:340:11 | LL | f(&String::new()); // Lint, makes no difference | ^^^^^^^^^^^^^^ help: change this to: `String::new()` error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:334:11 + --> tests/ui/needless_borrows_for_generic_args.rs:345:11 | LL | f(&"".to_owned()); // Lint | ^^^^^^^^^^^^^^ help: change this to: `"".to_owned()` diff --git a/tests/ui/needless_character_iteration.fixed b/tests/ui/needless_character_iteration.fixed index f0bf84a41d7e..e25db9bb590f 100644 --- a/tests/ui/needless_character_iteration.fixed +++ b/tests/ui/needless_character_iteration.fixed @@ -16,25 +16,29 @@ fn magic(_: char) {} fn main() { "foo".is_ascii(); - //~^ ERROR: checking if a string is ascii using iterators + //~^ needless_character_iteration + !"foo".is_ascii(); - //~^ ERROR: checking if a string is ascii using iterators + //~^ needless_character_iteration + "foo".is_ascii(); - //~^ ERROR: checking if a string is ascii using iterators + //~^ needless_character_iteration + !"foo".is_ascii(); - //~^ ERROR: checking if a string is ascii using iterators + //~^ needless_character_iteration let s = String::new(); s.is_ascii(); - //~^ ERROR: checking if a string is ascii using iterators + //~^ needless_character_iteration + !"foo".to_string().is_ascii(); - //~^ ERROR: checking if a string is ascii using iterators + //~^ needless_character_iteration "foo".is_ascii(); !"foo".is_ascii(); S::default().field().is_ascii(); - //~^ ERROR: checking if a string is ascii using iterators + //~^ needless_character_iteration // Should not lint! "foo".chars().all(|c| { diff --git a/tests/ui/needless_character_iteration.rs b/tests/ui/needless_character_iteration.rs index 2805d2438b4a..9b184dab6bc8 100644 --- a/tests/ui/needless_character_iteration.rs +++ b/tests/ui/needless_character_iteration.rs @@ -16,33 +16,39 @@ fn magic(_: char) {} fn main() { "foo".chars().all(|c| c.is_ascii()); - //~^ ERROR: checking if a string is ascii using iterators + //~^ needless_character_iteration + "foo".chars().any(|c| !c.is_ascii()); - //~^ ERROR: checking if a string is ascii using iterators + //~^ needless_character_iteration + "foo".chars().all(|c| char::is_ascii(&c)); - //~^ ERROR: checking if a string is ascii using iterators + //~^ needless_character_iteration + "foo".chars().any(|c| !char::is_ascii(&c)); - //~^ ERROR: checking if a string is ascii using iterators + //~^ needless_character_iteration let s = String::new(); s.chars().all(|c| c.is_ascii()); - //~^ ERROR: checking if a string is ascii using iterators + //~^ needless_character_iteration + "foo".to_string().chars().any(|c| !c.is_ascii()); - //~^ ERROR: checking if a string is ascii using iterators + //~^ needless_character_iteration "foo".chars().all(|c| { - //~^ ERROR: checking if a string is ascii using iterators + //~^ needless_character_iteration + let x = c; x.is_ascii() }); "foo".chars().any(|c| { - //~^ ERROR: checking if a string is ascii using iterators + //~^ needless_character_iteration + let x = c; !x.is_ascii() }); S::default().field().chars().all(|x| x.is_ascii()); - //~^ ERROR: checking if a string is ascii using iterators + //~^ needless_character_iteration // Should not lint! "foo".chars().all(|c| { diff --git a/tests/ui/needless_character_iteration.stderr b/tests/ui/needless_character_iteration.stderr index 7966033555f5..995404996644 100644 --- a/tests/ui/needless_character_iteration.stderr +++ b/tests/ui/needless_character_iteration.stderr @@ -8,57 +8,59 @@ LL | "foo".chars().all(|c| c.is_ascii()); = help: to override `-D warnings` add `#[allow(clippy::needless_character_iteration)]` error: checking if a string is ascii using iterators - --> tests/ui/needless_character_iteration.rs:20:5 + --> tests/ui/needless_character_iteration.rs:21:5 | LL | "foo".chars().any(|c| !c.is_ascii()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!"foo".is_ascii()` error: checking if a string is ascii using iterators - --> tests/ui/needless_character_iteration.rs:22:5 + --> tests/ui/needless_character_iteration.rs:24:5 | LL | "foo".chars().all(|c| char::is_ascii(&c)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"foo".is_ascii()` error: checking if a string is ascii using iterators - --> tests/ui/needless_character_iteration.rs:24:5 + --> tests/ui/needless_character_iteration.rs:27:5 | LL | "foo".chars().any(|c| !char::is_ascii(&c)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!"foo".is_ascii()` error: checking if a string is ascii using iterators - --> tests/ui/needless_character_iteration.rs:28:5 + --> tests/ui/needless_character_iteration.rs:31:5 | LL | s.chars().all(|c| c.is_ascii()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.is_ascii()` error: checking if a string is ascii using iterators - --> tests/ui/needless_character_iteration.rs:30:5 + --> tests/ui/needless_character_iteration.rs:34:5 | LL | "foo".to_string().chars().any(|c| !c.is_ascii()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!"foo".to_string().is_ascii()` error: checking if a string is ascii using iterators - --> tests/ui/needless_character_iteration.rs:33:5 + --> tests/ui/needless_character_iteration.rs:37:5 | LL | / "foo".chars().all(|c| { LL | | +LL | | LL | | let x = c; LL | | x.is_ascii() LL | | }); | |______^ help: try: `"foo".is_ascii()` error: checking if a string is ascii using iterators - --> tests/ui/needless_character_iteration.rs:38:5 + --> tests/ui/needless_character_iteration.rs:43:5 | LL | / "foo".chars().any(|c| { LL | | +LL | | LL | | let x = c; LL | | !x.is_ascii() LL | | }); | |______^ help: try: `!"foo".is_ascii()` error: checking if a string is ascii using iterators - --> tests/ui/needless_character_iteration.rs:44:5 + --> tests/ui/needless_character_iteration.rs:50:5 | LL | S::default().field().chars().all(|x| x.is_ascii()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `S::default().field().is_ascii()` diff --git a/tests/ui/needless_collect.fixed b/tests/ui/needless_collect.fixed index bd83581bdd97..bad8c307586c 100644 --- a/tests/ui/needless_collect.fixed +++ b/tests/ui/needless_collect.fixed @@ -1,4 +1,10 @@ -#![allow(unused, clippy::needless_if, clippy::suspicious_map, clippy::iter_count)] +#![allow( + unused, + clippy::needless_if, + clippy::suspicious_map, + clippy::iter_count, + clippy::manual_contains +)] use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList}; @@ -7,16 +13,21 @@ use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedL fn main() { let sample = [1; 5]; let len = sample.iter().count(); + //~^ needless_collect if sample.iter().next().is_none() { + //~^ needless_collect // Empty } sample.iter().cloned().any(|x| x == 1); + //~^ needless_collect // #7164 HashMap's and BTreeMap's `len` usage should not be linted sample.iter().map(|x| (x, x)).collect::>().len(); sample.iter().map(|x| (x, x)).collect::>().len(); sample.iter().map(|x| (x, x)).next().is_none(); + //~^ needless_collect sample.iter().map(|x| (x, x)).next().is_none(); + //~^ needless_collect // Notice the `HashSet`--this should not be linted sample.iter().collect::>().len(); @@ -24,19 +35,27 @@ fn main() { sample.iter().collect::>().len(); sample.iter().count(); + //~^ needless_collect sample.iter().next().is_none(); + //~^ needless_collect sample.iter().cloned().any(|x| x == 1); + //~^ needless_collect sample.iter().any(|x| x == &1); + //~^ needless_collect // `BinaryHeap` doesn't have `contains` method sample.iter().count(); + //~^ needless_collect sample.iter().next().is_none(); + //~^ needless_collect // Don't lint string from str let _ = ["", ""].into_iter().collect::().is_empty(); let _ = sample.iter().next().is_none(); + //~^ needless_collect let _ = sample.iter().any(|x| x == &0); + //~^ needless_collect struct VecWrapper(Vec); impl core::ops::Deref for VecWrapper { @@ -59,14 +78,20 @@ fn main() { } let _ = sample.iter().next().is_none(); + //~^ needless_collect let _ = sample.iter().any(|x| x == &0); + //~^ needless_collect #[allow(clippy::double_parens)] { Vec::::new().extend((0..10)); + //~^ needless_collect foo((0..10)); + //~^ needless_collect bar((0..10).collect::>(), (0..10)); + //~^ needless_collect baz((0..10), (), ('a'..='z')) + //~^ needless_collect } let values = [1, 2, 3, 4]; diff --git a/tests/ui/needless_collect.rs b/tests/ui/needless_collect.rs index 6a81a767bbb6..3dfb5194f404 100644 --- a/tests/ui/needless_collect.rs +++ b/tests/ui/needless_collect.rs @@ -1,4 +1,10 @@ -#![allow(unused, clippy::needless_if, clippy::suspicious_map, clippy::iter_count)] +#![allow( + unused, + clippy::needless_if, + clippy::suspicious_map, + clippy::iter_count, + clippy::manual_contains +)] use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList}; @@ -7,16 +13,21 @@ use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedL fn main() { let sample = [1; 5]; let len = sample.iter().collect::>().len(); + //~^ needless_collect if sample.iter().collect::>().is_empty() { + //~^ needless_collect // Empty } sample.iter().cloned().collect::>().contains(&1); + //~^ needless_collect // #7164 HashMap's and BTreeMap's `len` usage should not be linted sample.iter().map(|x| (x, x)).collect::>().len(); sample.iter().map(|x| (x, x)).collect::>().len(); sample.iter().map(|x| (x, x)).collect::>().is_empty(); + //~^ needless_collect sample.iter().map(|x| (x, x)).collect::>().is_empty(); + //~^ needless_collect // Notice the `HashSet`--this should not be linted sample.iter().collect::>().len(); @@ -24,19 +35,27 @@ fn main() { sample.iter().collect::>().len(); sample.iter().collect::>().len(); + //~^ needless_collect sample.iter().collect::>().is_empty(); + //~^ needless_collect sample.iter().cloned().collect::>().contains(&1); + //~^ needless_collect sample.iter().collect::>().contains(&&1); + //~^ needless_collect // `BinaryHeap` doesn't have `contains` method sample.iter().collect::>().len(); + //~^ needless_collect sample.iter().collect::>().is_empty(); + //~^ needless_collect // Don't lint string from str let _ = ["", ""].into_iter().collect::().is_empty(); let _ = sample.iter().collect::>().is_empty(); + //~^ needless_collect let _ = sample.iter().collect::>().contains(&&0); + //~^ needless_collect struct VecWrapper(Vec); impl core::ops::Deref for VecWrapper { @@ -59,14 +78,20 @@ fn main() { } let _ = sample.iter().collect::>().is_empty(); + //~^ needless_collect let _ = sample.iter().collect::>().contains(&&0); + //~^ needless_collect #[allow(clippy::double_parens)] { Vec::::new().extend((0..10).collect::>()); + //~^ needless_collect foo((0..10).collect::>()); + //~^ needless_collect bar((0..10).collect::>(), (0..10).collect::>()); + //~^ needless_collect baz((0..10), (), ('a'..='z').collect::>()) + //~^ needless_collect } let values = [1, 2, 3, 4]; diff --git a/tests/ui/needless_collect.stderr b/tests/ui/needless_collect.stderr index ea317896d368..00745eb2923c 100644 --- a/tests/ui/needless_collect.stderr +++ b/tests/ui/needless_collect.stderr @@ -1,5 +1,5 @@ error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:9:29 + --> tests/ui/needless_collect.rs:15:29 | LL | let len = sample.iter().collect::>().len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `count()` @@ -8,109 +8,109 @@ LL | let len = sample.iter().collect::>().len(); = help: to override `-D warnings` add `#[allow(clippy::needless_collect)]` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:10:22 + --> tests/ui/needless_collect.rs:17:22 | LL | if sample.iter().collect::>().is_empty() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:13:28 + --> tests/ui/needless_collect.rs:21:28 | LL | sample.iter().cloned().collect::>().contains(&1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == 1)` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:18:35 + --> tests/ui/needless_collect.rs:27:35 | LL | sample.iter().map(|x| (x, x)).collect::>().is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:19:35 + --> tests/ui/needless_collect.rs:29:35 | LL | sample.iter().map(|x| (x, x)).collect::>().is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:26:19 + --> tests/ui/needless_collect.rs:37:19 | LL | sample.iter().collect::>().len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `count()` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:27:19 + --> tests/ui/needless_collect.rs:39:19 | LL | sample.iter().collect::>().is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:28:28 + --> tests/ui/needless_collect.rs:41:28 | LL | sample.iter().cloned().collect::>().contains(&1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == 1)` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:29:19 + --> tests/ui/needless_collect.rs:43:19 | LL | sample.iter().collect::>().contains(&&1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == &1)` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:32:19 + --> tests/ui/needless_collect.rs:47:19 | LL | sample.iter().collect::>().len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `count()` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:33:19 + --> tests/ui/needless_collect.rs:49:19 | LL | sample.iter().collect::>().is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:38:27 + --> tests/ui/needless_collect.rs:55:27 | LL | let _ = sample.iter().collect::>().is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:39:27 + --> tests/ui/needless_collect.rs:57:27 | LL | let _ = sample.iter().collect::>().contains(&&0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == &0)` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:61:27 + --> tests/ui/needless_collect.rs:80:27 | LL | let _ = sample.iter().collect::>().is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:62:27 + --> tests/ui/needless_collect.rs:82:27 | LL | let _ = sample.iter().collect::>().contains(&&0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == &0)` error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:66:40 + --> tests/ui/needless_collect.rs:87:40 | LL | Vec::::new().extend((0..10).collect::>()); | ^^^^^^^^^^^^^^^^^^^^ help: remove this call error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:67:20 + --> tests/ui/needless_collect.rs:89:20 | LL | foo((0..10).collect::>()); | ^^^^^^^^^^^^^^^^^^^^ help: remove this call error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:68:49 + --> tests/ui/needless_collect.rs:91:49 | LL | bar((0..10).collect::>(), (0..10).collect::>()); | ^^^^^^^^^^^^^^^^^^^^ help: remove this call error: avoid using `collect()` when not needed - --> tests/ui/needless_collect.rs:69:37 + --> tests/ui/needless_collect.rs:93:37 | LL | baz((0..10), (), ('a'..='z').collect::>()) | ^^^^^^^^^^^^^^^^^^^^ help: remove this call diff --git a/tests/ui/needless_collect_indirect.rs b/tests/ui/needless_collect_indirect.rs index 9d66c5f255fe..57d0f2b99480 100644 --- a/tests/ui/needless_collect_indirect.rs +++ b/tests/ui/needless_collect_indirect.rs @@ -7,17 +7,20 @@ use std::collections::{BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; fn main() { let sample = [1; 5]; let indirect_iter = sample.iter().collect::>(); - //~^ ERROR: avoid using `collect()` when not needed - //~| NOTE: `-D clippy::needless-collect` implied by `-D warnings` + //~^ needless_collect + indirect_iter.into_iter().map(|x| (x, x + 1)).collect::>(); let indirect_len = sample.iter().collect::>(); - //~^ ERROR: avoid using `collect()` when not needed + //~^ needless_collect + indirect_len.len(); let indirect_empty = sample.iter().collect::>(); - //~^ ERROR: avoid using `collect()` when not needed + //~^ needless_collect + indirect_empty.is_empty(); let indirect_contains = sample.iter().collect::>(); - //~^ ERROR: avoid using `collect()` when not needed + //~^ needless_collect + indirect_contains.contains(&&5); let indirect_negative = sample.iter().collect::>(); indirect_negative.len(); @@ -30,7 +33,8 @@ fn main() { let a = "a".to_string(); let sample = vec![a.clone(), "b".to_string(), "c".to_string()]; let non_copy_contains = sample.into_iter().collect::>(); - //~^ ERROR: avoid using `collect()` when not needed + //~^ needless_collect + non_copy_contains.contains(&a); // Fix #5991 @@ -60,25 +64,29 @@ mod issue7110 { fn lint_vec(string: &str) -> usize { let buffer: Vec<&str> = string.split('/').collect(); - //~^ ERROR: avoid using `collect()` when not needed + //~^ needless_collect + buffer.len() } fn lint_vec_deque() -> usize { let sample = [1; 5]; let indirect_len: VecDeque<_> = sample.iter().collect(); - //~^ ERROR: avoid using `collect()` when not needed + //~^ needless_collect + indirect_len.len() } fn lint_linked_list() -> usize { let sample = [1; 5]; let indirect_len: LinkedList<_> = sample.iter().collect(); - //~^ ERROR: avoid using `collect()` when not needed + //~^ needless_collect + indirect_len.len() } fn lint_binary_heap() -> usize { let sample = [1; 5]; let indirect_len: BinaryHeap<_> = sample.iter().collect(); - //~^ ERROR: avoid using `collect()` when not needed + //~^ needless_collect + indirect_len.len() } fn dont_lint(string: &str) -> usize { @@ -139,7 +147,8 @@ mod issue_8553 { for i in 0..2 { let y: Vec = vec.iter().map(|k| k * k).collect(); - //~^ ERROR: avoid using `collect()` when not needed + //~^ needless_collect + let z: Vec = vec.iter().map(|k| k * k).collect(); // Do lint y.contains(&i); @@ -165,7 +174,8 @@ mod issue_8553 { while n > 2 { let y: Vec = vec.iter().map(|k| k * k).collect(); - //~^ ERROR: avoid using `collect()` when not needed + //~^ needless_collect + let z: Vec = vec.iter().map(|k| k * k).collect(); // Do lint y.contains(&n); @@ -195,7 +205,8 @@ mod issue_8553 { loop { if n < 2 { let y: Vec = vec.iter().map(|k| k * k).collect(); - //~^ ERROR: avoid using `collect()` when not needed + //~^ needless_collect + let z: Vec = vec.iter().map(|k| k * k).collect(); // Do lint y.contains(&n); @@ -232,7 +243,8 @@ mod issue_8553 { while let Some(value) = optional { let y: Vec = vec.iter().map(|k| k * k).collect(); - //~^ ERROR: avoid using `collect()` when not needed + //~^ needless_collect + let z: Vec = vec.iter().map(|k| k * k).collect(); if n < 2 { // Do lint @@ -258,7 +270,8 @@ mod issue_8553 { let vec = vec![1, 2]; let v: Vec = vec.iter().map(|i| i * i).collect(); let w = v.iter().collect::>(); - //~^ ERROR: avoid using `collect()` when not needed + //~^ needless_collect + // Do lint for _ in 0..w.len() { todo!(); @@ -281,7 +294,8 @@ mod issue_8553 { let mut vec = vec![1, 2]; let mut v: Vec = vec.iter().map(|i| i * i).collect(); let mut w = v.iter().collect::>(); - //~^ ERROR: avoid using `collect()` when not needed + //~^ needless_collect + // Do lint while 1 == w.len() { todo!(); @@ -304,7 +318,8 @@ mod issue_8553 { let mut vec = vec![1, 2]; let mut v: Vec = vec.iter().map(|i| i * i).collect(); let mut w = v.iter().collect::>(); - //~^ ERROR: avoid using `collect()` when not needed + //~^ needless_collect + // Do lint while let Some(i) = Some(w.len()) { todo!(); diff --git a/tests/ui/needless_collect_indirect.stderr b/tests/ui/needless_collect_indirect.stderr index f25c02937545..c7bf1b14df80 100644 --- a/tests/ui/needless_collect_indirect.stderr +++ b/tests/ui/needless_collect_indirect.stderr @@ -22,7 +22,7 @@ error: avoid using `collect()` when not needed | LL | let indirect_len = sample.iter().collect::>(); | ^^^^^^^ -LL | +... LL | indirect_len.len(); | ------------------ the iterator could be used here instead | @@ -30,15 +30,16 @@ help: take the original Iterator's count instead of collecting it and finding th | LL ~ LL | +LL | LL ~ sample.iter().count(); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:16:40 + --> tests/ui/needless_collect_indirect.rs:17:40 | LL | let indirect_empty = sample.iter().collect::>(); | ^^^^^^^ -LL | +... LL | indirect_empty.is_empty(); | ------------------------- the iterator could be used here instead | @@ -46,15 +47,16 @@ help: check if the original Iterator has anything instead of collecting it and s | LL ~ LL | +LL | LL ~ sample.iter().next().is_none(); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:19:43 + --> tests/ui/needless_collect_indirect.rs:21:43 | LL | let indirect_contains = sample.iter().collect::>(); | ^^^^^^^ -LL | +... LL | indirect_contains.contains(&&5); | ------------------------------- the iterator could be used here instead | @@ -62,15 +64,16 @@ help: check if the original Iterator contains an element instead of collecting t | LL ~ LL | +LL | LL ~ sample.iter().any(|x| x == &5); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:32:48 + --> tests/ui/needless_collect_indirect.rs:35:48 | LL | let non_copy_contains = sample.into_iter().collect::>(); | ^^^^^^^ -LL | +... LL | non_copy_contains.contains(&a); | ------------------------------ the iterator could be used here instead | @@ -78,15 +81,16 @@ help: check if the original Iterator contains an element instead of collecting t | LL ~ LL | +LL | LL ~ sample.into_iter().any(|x| x == a); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:62:51 + --> tests/ui/needless_collect_indirect.rs:66:51 | LL | let buffer: Vec<&str> = string.split('/').collect(); | ^^^^^^^ -LL | +... LL | buffer.len() | ------------ the iterator could be used here instead | @@ -94,15 +98,16 @@ help: take the original Iterator's count instead of collecting it and finding th | LL ~ LL | +LL | LL ~ string.split('/').count() | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:68:55 + --> tests/ui/needless_collect_indirect.rs:73:55 | LL | let indirect_len: VecDeque<_> = sample.iter().collect(); | ^^^^^^^ -LL | +... LL | indirect_len.len() | ------------------ the iterator could be used here instead | @@ -110,21 +115,6 @@ help: take the original Iterator's count instead of collecting it and finding th | LL ~ LL | -LL ~ sample.iter().count() - | - -error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:74:57 - | -LL | let indirect_len: LinkedList<_> = sample.iter().collect(); - | ^^^^^^^ -LL | -LL | indirect_len.len() - | ------------------ the iterator could be used here instead - | -help: take the original Iterator's count instead of collecting it and finding the length - | -LL ~ LL | LL ~ sample.iter().count() | @@ -132,9 +122,9 @@ LL ~ sample.iter().count() error: avoid using `collect()` when not needed --> tests/ui/needless_collect_indirect.rs:80:57 | -LL | let indirect_len: BinaryHeap<_> = sample.iter().collect(); +LL | let indirect_len: LinkedList<_> = sample.iter().collect(); | ^^^^^^^ -LL | +... LL | indirect_len.len() | ------------------ the iterator could be used here instead | @@ -142,11 +132,29 @@ help: take the original Iterator's count instead of collecting it and finding th | LL ~ LL | +LL | LL ~ sample.iter().count() | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:141:59 + --> tests/ui/needless_collect_indirect.rs:87:57 + | +LL | let indirect_len: BinaryHeap<_> = sample.iter().collect(); + | ^^^^^^^ +... +LL | indirect_len.len() + | ------------------ the iterator could be used here instead + | +help: take the original Iterator's count instead of collecting it and finding the length + | +LL ~ +LL | +LL | +LL ~ sample.iter().count() + | + +error: avoid using `collect()` when not needed + --> tests/ui/needless_collect_indirect.rs:149:59 | LL | let y: Vec = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -158,13 +166,13 @@ help: check if the original Iterator contains an element instead of collecting t | LL ~ LL | -LL | let z: Vec = vec.iter().map(|k| k * k).collect(); +... LL | // Do lint LL ~ vec.iter().map(|k| k * k).any(|x| x == i); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:167:59 + --> tests/ui/needless_collect_indirect.rs:176:59 | LL | let y: Vec = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -176,13 +184,13 @@ help: check if the original Iterator contains an element instead of collecting t | LL ~ LL | -LL | let z: Vec = vec.iter().map(|k| k * k).collect(); +... LL | // Do lint LL ~ vec.iter().map(|k| k * k).any(|x| x == n); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:197:63 + --> tests/ui/needless_collect_indirect.rs:207:63 | LL | let y: Vec = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -194,13 +202,13 @@ help: check if the original Iterator contains an element instead of collecting t | LL ~ LL | -LL | let z: Vec = vec.iter().map(|k| k * k).collect(); +... LL | // Do lint LL ~ vec.iter().map(|k| k * k).any(|x| x == n); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:234:59 + --> tests/ui/needless_collect_indirect.rs:245:59 | LL | let y: Vec = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -218,7 +226,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == n); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:260:26 + --> tests/ui/needless_collect_indirect.rs:272:26 | LL | let w = v.iter().collect::>(); | ^^^^^^^ @@ -230,12 +238,13 @@ help: take the original Iterator's count instead of collecting it and finding th | LL ~ LL | +LL | LL | // Do lint LL ~ for _ in 0..v.iter().count() { | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:283:30 + --> tests/ui/needless_collect_indirect.rs:296:30 | LL | let mut w = v.iter().collect::>(); | ^^^^^^^ @@ -247,12 +256,13 @@ help: take the original Iterator's count instead of collecting it and finding th | LL ~ LL | +LL | LL | // Do lint LL ~ while 1 == v.iter().count() { | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:306:30 + --> tests/ui/needless_collect_indirect.rs:320:30 | LL | let mut w = v.iter().collect::>(); | ^^^^^^^ @@ -264,6 +274,7 @@ help: take the original Iterator's count instead of collecting it and finding th | LL ~ LL | +LL | LL | // Do lint LL ~ while let Some(i) = Some(v.iter().count()) { | diff --git a/tests/ui/needless_continue.rs b/tests/ui/needless_continue.rs index 334a2b32775f..e873db6dee14 100644 --- a/tests/ui/needless_continue.rs +++ b/tests/ui/needless_continue.rs @@ -28,7 +28,8 @@ fn main() { let i = 0; println!("bar {} ", i); } else { - //~^ ERROR: this `else` block is redundant + //~^ needless_continue + continue; } @@ -44,7 +45,8 @@ fn main() { } if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 { - //~^ ERROR: there is no need for an explicit `else` block for this `if` expression + //~^ needless_continue + continue; } else { println!("Blabber"); @@ -58,7 +60,7 @@ fn main() { fn simple_loop() { loop { continue; - //~^ ERROR: this `continue` expression is redundant + //~^ needless_continue } } @@ -66,7 +68,7 @@ fn simple_loop2() { loop { println!("bleh"); continue; - //~^ ERROR: this `continue` expression is redundant + //~^ needless_continue } } @@ -74,7 +76,8 @@ fn simple_loop2() { fn simple_loop3() { loop { continue - //~^ ERROR: this `continue` expression is redundant + //~^ needless_continue + } } @@ -83,7 +86,8 @@ fn simple_loop4() { loop { println!("bleh"); continue - //~^ ERROR: this `continue` expression is redundant + //~^ needless_continue + } } @@ -91,7 +95,7 @@ fn simple_loop5() { loop { println!("bleh"); { continue } - //~^ ERROR: this `continue` expression is redundant + //~^ needless_continue } } @@ -142,14 +146,16 @@ mod issue_2329 { if condition() { println!("bar-3"); } else { - //~^ ERROR: this `else` block is redundant + //~^ needless_continue + continue 'inner; } println!("bar-4"); update_condition(); if condition() { - //~^ ERROR: there is no need for an explicit `else` block for this `if` ex + //~^ needless_continue + continue; } else { println!("bar-5"); @@ -172,7 +178,7 @@ fn issue_13641() { while std::hint::black_box(true) { 'b: loop { continue 'b; - //~^ ERROR: this `continue` expression is redundant + //~^ needless_continue } } } @@ -188,9 +194,11 @@ mod issue_4077 { } else if !some_expr() { println!("bar-8"); continue 'inner; + //~^ needless_continue } else { println!("bar-9"); continue 'inner; + //~^ needless_continue } } } @@ -201,6 +209,7 @@ mod issue_4077 { Err(_) => { println!("bar-10"); continue; + //~^ needless_continue }, } } @@ -208,6 +217,7 @@ mod issue_4077 { loop { if true { } else { + //~^ needless_continue // redundant `else` continue; // redundant `continue` } @@ -215,6 +225,7 @@ mod issue_4077 { loop { if some_expr() { + //~^ needless_continue continue; } else { do_something(); diff --git a/tests/ui/needless_continue.stderr b/tests/ui/needless_continue.stderr index ec39d6234195..878c1e731e32 100644 --- a/tests/ui/needless_continue.stderr +++ b/tests/ui/needless_continue.stderr @@ -4,6 +4,7 @@ error: this `else` block is redundant LL | } else { | ________________^ LL | | +LL | | LL | | continue; LL | | } | |_________^ @@ -27,6 +28,7 @@ LL | | } } if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 { + continue; } else { println!("Blabber"); @@ -38,13 +40,13 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::needless_continue)]` error: there is no need for an explicit `else` block for this `if` expression - --> tests/ui/needless_continue.rs:46:9 + --> tests/ui/needless_continue.rs:47:9 | LL | / if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 { LL | | +LL | | LL | | continue; -LL | | } else { -LL | | println!("Blabber"); +... | LL | | println!("Jabber"); LL | | } | |_________^ @@ -52,6 +54,7 @@ LL | | } = help: consider dropping the `else` clause if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 { + continue; } { @@ -60,7 +63,7 @@ LL | | } } error: this `continue` expression is redundant - --> tests/ui/needless_continue.rs:60:9 + --> tests/ui/needless_continue.rs:62:9 | LL | continue; | ^^^^^^^^ @@ -68,7 +71,7 @@ LL | continue; = help: consider dropping the `continue` expression error: this `continue` expression is redundant - --> tests/ui/needless_continue.rs:68:9 + --> tests/ui/needless_continue.rs:70:9 | LL | continue; | ^^^^^^^^ @@ -76,7 +79,7 @@ LL | continue; = help: consider dropping the `continue` expression error: this `continue` expression is redundant - --> tests/ui/needless_continue.rs:76:9 + --> tests/ui/needless_continue.rs:78:9 | LL | continue | ^^^^^^^^ @@ -84,7 +87,7 @@ LL | continue = help: consider dropping the `continue` expression error: this `continue` expression is redundant - --> tests/ui/needless_continue.rs:85:9 + --> tests/ui/needless_continue.rs:88:9 | LL | continue | ^^^^^^^^ @@ -92,7 +95,7 @@ LL | continue = help: consider dropping the `continue` expression error: this `continue` expression is redundant - --> tests/ui/needless_continue.rs:93:11 + --> tests/ui/needless_continue.rs:97:11 | LL | { continue } | ^^^^^^^^ @@ -100,11 +103,12 @@ LL | { continue } = help: consider dropping the `continue` expression error: this `else` block is redundant - --> tests/ui/needless_continue.rs:144:24 + --> tests/ui/needless_continue.rs:148:24 | LL | } else { | ________________________^ LL | | +LL | | LL | | continue 'inner; LL | | } | |_________________^ @@ -117,6 +121,7 @@ LL | | } update_condition(); if condition() { + continue; } else { println!("bar-5"); @@ -125,10 +130,11 @@ LL | | } } error: there is no need for an explicit `else` block for this `if` expression - --> tests/ui/needless_continue.rs:151:17 + --> tests/ui/needless_continue.rs:156:17 | LL | / if condition() { LL | | +LL | | LL | | continue; LL | | } else { LL | | println!("bar-5"); @@ -138,6 +144,7 @@ LL | | } = help: consider dropping the `else` clause if condition() { + continue; } { @@ -145,7 +152,7 @@ LL | | } } error: this `continue` expression is redundant - --> tests/ui/needless_continue.rs:174:13 + --> tests/ui/needless_continue.rs:180:13 | LL | continue 'b; | ^^^^^^^^^^^ @@ -153,7 +160,7 @@ LL | continue 'b; = help: consider dropping the `continue` expression error: this `continue` expression is redundant - --> tests/ui/needless_continue.rs:190:21 + --> tests/ui/needless_continue.rs:196:21 | LL | continue 'inner; | ^^^^^^^^^^^^^^^ @@ -161,7 +168,7 @@ LL | continue 'inner; = help: consider dropping the `continue` expression error: this `continue` expression is redundant - --> tests/ui/needless_continue.rs:193:21 + --> tests/ui/needless_continue.rs:200:21 | LL | continue 'inner; | ^^^^^^^^^^^^^^^ @@ -169,7 +176,7 @@ LL | continue 'inner; = help: consider dropping the `continue` expression error: this `continue` expression is redundant - --> tests/ui/needless_continue.rs:203:21 + --> tests/ui/needless_continue.rs:211:21 | LL | continue; | ^^^^^^^^ @@ -177,10 +184,11 @@ LL | continue; = help: consider dropping the `continue` expression error: this `else` block is redundant - --> tests/ui/needless_continue.rs:210:20 + --> tests/ui/needless_continue.rs:219:20 | LL | } else { | ____________________^ +LL | | LL | | // redundant `else` LL | | continue; // redundant `continue` LL | | } @@ -193,9 +201,10 @@ LL | | } } error: there is no need for an explicit `else` block for this `if` expression - --> tests/ui/needless_continue.rs:217:13 + --> tests/ui/needless_continue.rs:227:13 | LL | / if some_expr() { +LL | | LL | | continue; LL | | } else { LL | | do_something(); @@ -204,6 +213,7 @@ LL | | } | = help: consider dropping the `else` clause if some_expr() { + continue; } { diff --git a/tests/ui/needless_doc_main.rs b/tests/ui/needless_doc_main.rs index fee05926ce4f..cf01cae2e8fd 100644 --- a/tests/ui/needless_doc_main.rs +++ b/tests/ui/needless_doc_main.rs @@ -6,7 +6,6 @@ /// ``` /// fn main() { //~^ ERROR: needless `fn main` in doctest -//~| NOTE: `-D clippy::needless-doctest-main` implied by `-D warnings` /// unimplemented!(); /// } /// ``` diff --git a/tests/ui/needless_doc_main.stderr b/tests/ui/needless_doc_main.stderr index 7e362cf377ce..9ba2ad306dac 100644 --- a/tests/ui/needless_doc_main.stderr +++ b/tests/ui/needless_doc_main.stderr @@ -4,7 +4,6 @@ error: needless `fn main` in doctest LL | /// fn main() { | _____^ LL | | -LL | | LL | | /// unimplemented!(); LL | | /// } | |_____^ @@ -13,7 +12,7 @@ LL | | /// } = help: to override `-D warnings` add `#[allow(clippy::needless_doctest_main)]` error: needless `fn main` in doctest - --> tests/ui/needless_doc_main.rs:16:5 + --> tests/ui/needless_doc_main.rs:15:5 | LL | /// fn main() -> () { | _____^ @@ -23,7 +22,7 @@ LL | | /// } | |_____^ error: needless `fn main` in doctest - --> tests/ui/needless_doc_main.rs:24:5 + --> tests/ui/needless_doc_main.rs:23:5 | LL | /// fn main() { | _____^ @@ -33,7 +32,7 @@ LL | | /// } | |_____^ error: needless `fn main` in doctest - --> tests/ui/needless_doc_main.rs:32:5 + --> tests/ui/needless_doc_main.rs:31:5 | LL | /// // the fn is not always the first line | _____^ diff --git a/tests/ui/needless_else.fixed b/tests/ui/needless_else.fixed index 240b79bae13c..0455910c3ee8 100644 --- a/tests/ui/needless_else.fixed +++ b/tests/ui/needless_else.fixed @@ -21,6 +21,7 @@ fn main() { if b { println!("Foobar"); } + //~^^ needless_else if b { println!("Foobar"); diff --git a/tests/ui/needless_else.rs b/tests/ui/needless_else.rs index ad84da170535..236ac631a49e 100644 --- a/tests/ui/needless_else.rs +++ b/tests/ui/needless_else.rs @@ -22,6 +22,7 @@ fn main() { println!("Foobar"); } else { } + //~^^ needless_else if b { println!("Foobar"); diff --git a/tests/ui/needless_for_each_fixable.fixed b/tests/ui/needless_for_each_fixable.fixed index 2362314290e6..fa23e18318f1 100644 --- a/tests/ui/needless_for_each_fixable.fixed +++ b/tests/ui/needless_for_each_fixable.fixed @@ -13,27 +13,34 @@ fn should_lint() { let v: Vec = Vec::new(); let mut acc = 0; for elem in v.iter() { + //~^ needless_for_each acc += elem; } for elem in v.into_iter() { + //~^ needless_for_each acc += elem; } for elem in [1, 2, 3].iter() { + //~^ needless_for_each acc += elem; } let mut hash_map: HashMap = HashMap::new(); for (k, v) in hash_map.iter() { + //~^ needless_for_each acc += k + v; } for (k, v) in hash_map.iter_mut() { + //~^ needless_for_each acc += *k + *v; } for k in hash_map.keys() { + //~^ needless_for_each acc += k; } for v in hash_map.values() { + //~^ needless_for_each acc += v; } @@ -41,6 +48,7 @@ fn should_lint() { Vec::new() } for elem in my_vec().iter() { + //~^ needless_for_each acc += elem; } } diff --git a/tests/ui/needless_for_each_fixable.rs b/tests/ui/needless_for_each_fixable.rs index 5b1186daa229..2c7e68a6f512 100644 --- a/tests/ui/needless_for_each_fixable.rs +++ b/tests/ui/needless_for_each_fixable.rs @@ -13,27 +13,34 @@ fn should_lint() { let v: Vec = Vec::new(); let mut acc = 0; v.iter().for_each(|elem| { + //~^ needless_for_each acc += elem; }); v.into_iter().for_each(|elem| { + //~^ needless_for_each acc += elem; }); [1, 2, 3].iter().for_each(|elem| { + //~^ needless_for_each acc += elem; }); let mut hash_map: HashMap = HashMap::new(); hash_map.iter().for_each(|(k, v)| { + //~^ needless_for_each acc += k + v; }); hash_map.iter_mut().for_each(|(k, v)| { + //~^ needless_for_each acc += *k + *v; }); hash_map.keys().for_each(|k| { + //~^ needless_for_each acc += k; }); hash_map.values().for_each(|v| { + //~^ needless_for_each acc += v; }); @@ -41,6 +48,7 @@ fn should_lint() { Vec::new() } my_vec().iter().for_each(|elem| { + //~^ needless_for_each acc += elem; }); } diff --git a/tests/ui/needless_for_each_fixable.stderr b/tests/ui/needless_for_each_fixable.stderr index 21342d052561..013a3fa3e36d 100644 --- a/tests/ui/needless_for_each_fixable.stderr +++ b/tests/ui/needless_for_each_fixable.stderr @@ -2,6 +2,7 @@ error: needless use of `for_each` --> tests/ui/needless_for_each_fixable.rs:15:5 | LL | / v.iter().for_each(|elem| { +LL | | LL | | acc += elem; LL | | }); | |_______^ @@ -11,14 +12,16 @@ LL | | }); help: try | LL ~ for elem in v.iter() { +LL + LL + acc += elem; LL + } | error: needless use of `for_each` - --> tests/ui/needless_for_each_fixable.rs:18:5 + --> tests/ui/needless_for_each_fixable.rs:19:5 | LL | / v.into_iter().for_each(|elem| { +LL | | LL | | acc += elem; LL | | }); | |_______^ @@ -26,14 +29,16 @@ LL | | }); help: try | LL ~ for elem in v.into_iter() { +LL + LL + acc += elem; LL + } | error: needless use of `for_each` - --> tests/ui/needless_for_each_fixable.rs:22:5 + --> tests/ui/needless_for_each_fixable.rs:24:5 | LL | / [1, 2, 3].iter().for_each(|elem| { +LL | | LL | | acc += elem; LL | | }); | |_______^ @@ -41,14 +46,16 @@ LL | | }); help: try | LL ~ for elem in [1, 2, 3].iter() { +LL + LL + acc += elem; LL + } | error: needless use of `for_each` - --> tests/ui/needless_for_each_fixable.rs:27:5 + --> tests/ui/needless_for_each_fixable.rs:30:5 | LL | / hash_map.iter().for_each(|(k, v)| { +LL | | LL | | acc += k + v; LL | | }); | |_______^ @@ -56,14 +63,16 @@ LL | | }); help: try | LL ~ for (k, v) in hash_map.iter() { +LL + LL + acc += k + v; LL + } | error: needless use of `for_each` - --> tests/ui/needless_for_each_fixable.rs:30:5 + --> tests/ui/needless_for_each_fixable.rs:34:5 | LL | / hash_map.iter_mut().for_each(|(k, v)| { +LL | | LL | | acc += *k + *v; LL | | }); | |_______^ @@ -71,14 +80,16 @@ LL | | }); help: try | LL ~ for (k, v) in hash_map.iter_mut() { +LL + LL + acc += *k + *v; LL + } | error: needless use of `for_each` - --> tests/ui/needless_for_each_fixable.rs:33:5 + --> tests/ui/needless_for_each_fixable.rs:38:5 | LL | / hash_map.keys().for_each(|k| { +LL | | LL | | acc += k; LL | | }); | |_______^ @@ -86,14 +97,16 @@ LL | | }); help: try | LL ~ for k in hash_map.keys() { +LL + LL + acc += k; LL + } | error: needless use of `for_each` - --> tests/ui/needless_for_each_fixable.rs:36:5 + --> tests/ui/needless_for_each_fixable.rs:42:5 | LL | / hash_map.values().for_each(|v| { +LL | | LL | | acc += v; LL | | }); | |_______^ @@ -101,14 +114,16 @@ LL | | }); help: try | LL ~ for v in hash_map.values() { +LL + LL + acc += v; LL + } | error: needless use of `for_each` - --> tests/ui/needless_for_each_fixable.rs:43:5 + --> tests/ui/needless_for_each_fixable.rs:50:5 | LL | / my_vec().iter().for_each(|elem| { +LL | | LL | | acc += elem; LL | | }); | |_______^ @@ -116,6 +131,7 @@ LL | | }); help: try | LL ~ for elem in my_vec().iter() { +LL + LL + acc += elem; LL + } | diff --git a/tests/ui/needless_for_each_unfixable.rs b/tests/ui/needless_for_each_unfixable.rs index 2220cf9e11ee..159cbe49828f 100644 --- a/tests/ui/needless_for_each_unfixable.rs +++ b/tests/ui/needless_for_each_unfixable.rs @@ -6,8 +6,8 @@ fn main() { let v: Vec = Vec::new(); // This is unfixable because the closure includes `return`. v.iter().for_each(|v| { - //~^ ERROR: needless use of `for_each` - //~| NOTE: `-D clippy::needless-for-each` implied by `-D warnings` + //~^ needless_for_each + if *v == 10 { return; } else { diff --git a/tests/ui/needless_for_each_unfixable.stderr b/tests/ui/needless_for_each_unfixable.stderr index 722016b12125..3a3a240c5a3a 100644 --- a/tests/ui/needless_for_each_unfixable.stderr +++ b/tests/ui/needless_for_each_unfixable.stderr @@ -15,7 +15,7 @@ help: try | LL ~ for v in v.iter() { LL + -LL + +LL + LL + if *v == 10 { LL + return; LL + } else { diff --git a/tests/ui/needless_if.fixed b/tests/ui/needless_if.fixed index 79e33a7218b7..6208ca19b82b 100644 --- a/tests/ui/needless_if.fixed +++ b/tests/ui/needless_if.fixed @@ -25,13 +25,16 @@ fn maybe_side_effect() -> bool { fn main() { // Lint + //~^ needless_if // Do not remove the condition maybe_side_effect(); + //~^ needless_if // Do not lint if (true) { } else { } ({ + //~^ needless_if return; }); // Do not lint if `else if` is present @@ -48,6 +51,7 @@ fn main() { {} // Can lint nested `if let`s ({ + //~^ needless_if if let true = true && true { @@ -91,12 +95,15 @@ fn main() { // Must be placed into an expression context to not be interpreted as a block ({ maybe_side_effect() }); + //~^ needless_if // Would be a block followed by `&&true` - a double reference to `true` ({ maybe_side_effect() } && true); + //~^ needless_if // Don't leave trailing attributes #[allow(unused)] true; + //~^ needless_if let () = if maybe_side_effect() {}; } diff --git a/tests/ui/needless_if.rs b/tests/ui/needless_if.rs index 2c135fb22bf8..b459ff877be6 100644 --- a/tests/ui/needless_if.rs +++ b/tests/ui/needless_if.rs @@ -25,13 +25,16 @@ fn maybe_side_effect() -> bool { fn main() { // Lint if (true) {} + //~^ needless_if // Do not remove the condition if maybe_side_effect() {} + //~^ needless_if // Do not lint if (true) { } else { } if { + //~^ needless_if return; } {} // Do not lint if `else if` is present @@ -48,6 +51,7 @@ fn main() { {} // Can lint nested `if let`s if { + //~^ needless_if if let true = true && true { @@ -92,12 +96,15 @@ fn main() { // Must be placed into an expression context to not be interpreted as a block if { maybe_side_effect() } {} + //~^ needless_if // Would be a block followed by `&&true` - a double reference to `true` if { maybe_side_effect() } && true {} + //~^ needless_if // Don't leave trailing attributes #[allow(unused)] if true {} + //~^ needless_if let () = if maybe_side_effect() {}; } diff --git a/tests/ui/needless_if.stderr b/tests/ui/needless_if.stderr index cbfeb979d2f2..eeb8d044526d 100644 --- a/tests/ui/needless_if.stderr +++ b/tests/ui/needless_if.stderr @@ -8,15 +8,16 @@ LL | if (true) {} = help: to override `-D warnings` add `#[allow(clippy::needless_if)]` error: this `if` branch is empty - --> tests/ui/needless_if.rs:29:5 + --> tests/ui/needless_if.rs:30:5 | LL | if maybe_side_effect() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `maybe_side_effect();` error: this `if` branch is empty - --> tests/ui/needless_if.rs:34:5 + --> tests/ui/needless_if.rs:36:5 | LL | / if { +LL | | LL | | return; LL | | } {} | |________^ @@ -24,14 +25,16 @@ LL | | } {} help: you can remove it | LL ~ ({ +LL + LL + return; LL + }); | error: this `if` branch is empty - --> tests/ui/needless_if.rs:50:5 + --> tests/ui/needless_if.rs:53:5 | LL | / if { +LL | | LL | | if let true = true LL | | && true ... | @@ -42,6 +45,7 @@ LL | | {} help: you can remove it | LL ~ ({ +LL + LL + if let true = true LL + && true LL + { @@ -53,19 +57,19 @@ LL + } && true); | error: this `if` branch is empty - --> tests/ui/needless_if.rs:94:5 + --> tests/ui/needless_if.rs:98:5 | LL | if { maybe_side_effect() } {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `({ maybe_side_effect() });` error: this `if` branch is empty - --> tests/ui/needless_if.rs:96:5 + --> tests/ui/needless_if.rs:101:5 | LL | if { maybe_side_effect() } && true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `({ maybe_side_effect() } && true);` error: this `if` branch is empty - --> tests/ui/needless_if.rs:100:5 + --> tests/ui/needless_if.rs:106:5 | LL | if true {} | ^^^^^^^^^^ help: you can remove it: `true;` diff --git a/tests/ui/needless_late_init.fixed b/tests/ui/needless_late_init.fixed index b4bd53ce7bf7..eb67e6cc8282 100644 --- a/tests/ui/needless_late_init.fixed +++ b/tests/ui/needless_late_init.fixed @@ -25,22 +25,28 @@ impl std::ops::Drop for SignificantDrop { fn simple() { + //~^ needless_late_init let a = "zero"; + //~^ needless_late_init + //~^ needless_late_init let b = 1; let c = 2; + //~^ needless_late_init let d: usize = 1; + //~^ needless_late_init let e = format!("{}", d); } fn main() { + //~^ needless_late_init let n = 1; let a = match n { 1 => "one", @@ -50,6 +56,7 @@ fn main() { }; + //~^ needless_late_init let b = if n == 3 { "four" } else { @@ -57,6 +64,7 @@ fn main() { }; + //~^ needless_late_init let d = if true { let temp = 5; temp @@ -65,6 +73,7 @@ fn main() { }; + //~^ needless_late_init let e = if true { format!("{} {}", a, b) } else { @@ -72,12 +81,14 @@ fn main() { }; + //~^ needless_late_init let f = match 1 { 1 => "three", _ => return, }; // has semi + //~^ needless_late_init let g: usize = if true { 5 } else { @@ -86,14 +97,17 @@ fn main() { // Drop order only matters if both are significant + //~^ needless_late_init let y = SignificantDrop; let x = 1; + //~^ needless_late_init let y = 1; let x = SignificantDrop; + //~^ needless_late_init // types that should be considered insignificant let y = 1; let y = "2"; @@ -113,6 +127,7 @@ async fn in_async() -> &'static str { } + //~^ needless_late_init let n = 1; let a = match n { 1 => f().await, @@ -130,6 +145,7 @@ const fn in_const() -> &'static str { } + //~^ needless_late_init let n = 1; let a = match n { 1 => f(), diff --git a/tests/ui/needless_late_init.rs b/tests/ui/needless_late_init.rs index e25483625a68..7de2202dc323 100644 --- a/tests/ui/needless_late_init.rs +++ b/tests/ui/needless_late_init.rs @@ -25,22 +25,28 @@ impl std::ops::Drop for SignificantDrop { fn simple() { let a; + //~^ needless_late_init a = "zero"; let b; + //~^ needless_late_init let c; + //~^ needless_late_init b = 1; c = 2; let d: usize; + //~^ needless_late_init d = 1; let e; + //~^ needless_late_init e = format!("{}", d); } fn main() { let a; + //~^ needless_late_init let n = 1; match n { 1 => a = "one", @@ -50,6 +56,7 @@ fn main() { } let b; + //~^ needless_late_init if n == 3 { b = "four"; } else { @@ -57,6 +64,7 @@ fn main() { } let d; + //~^ needless_late_init if true { let temp = 5; d = temp; @@ -65,6 +73,7 @@ fn main() { } let e; + //~^ needless_late_init if true { e = format!("{} {}", a, b); } else { @@ -72,12 +81,14 @@ fn main() { } let f; + //~^ needless_late_init match 1 { 1 => f = "three", _ => return, }; // has semi let g: usize; + //~^ needless_late_init if true { g = 5; } else { @@ -86,14 +97,17 @@ fn main() { // Drop order only matters if both are significant let x; + //~^ needless_late_init let y = SignificantDrop; x = 1; let x; + //~^ needless_late_init let y = 1; x = SignificantDrop; let x; + //~^ needless_late_init // types that should be considered insignificant let y = 1; let y = "2"; @@ -113,6 +127,7 @@ async fn in_async() -> &'static str { } let a; + //~^ needless_late_init let n = 1; match n { 1 => a = f().await, @@ -130,6 +145,7 @@ const fn in_const() -> &'static str { } let a; + //~^ needless_late_init let n = 1; match n { 1 => a = f(), diff --git a/tests/ui/needless_late_init.stderr b/tests/ui/needless_late_init.stderr index de048091cfbe..02fd2811da58 100644 --- a/tests/ui/needless_late_init.stderr +++ b/tests/ui/needless_late_init.stderr @@ -3,6 +3,7 @@ error: unneeded late initialization | LL | let a; | ^^^^^^ created here +LL | LL | a = "zero"; | ^^^^^^^^^^ initialised here | @@ -11,71 +12,79 @@ LL | a = "zero"; help: move the declaration `a` here | LL ~ +LL | LL ~ let a = "zero"; | error: unneeded late initialization - --> tests/ui/needless_late_init.rs:30:5 + --> tests/ui/needless_late_init.rs:31:5 | LL | let b; | ^^^^^^ created here -LL | let c; +... LL | b = 1; | ^^^^^ initialised here | help: move the declaration `b` here | LL ~ +LL | LL | let c; +LL | LL ~ let b = 1; | error: unneeded late initialization - --> tests/ui/needless_late_init.rs:31:5 + --> tests/ui/needless_late_init.rs:33:5 | LL | let c; | ^^^^^^ created here -LL | b = 1; +... LL | c = 2; | ^^^^^ initialised here | help: move the declaration `c` here | LL ~ +LL | LL | b = 1; LL ~ let c = 2; | error: unneeded late initialization - --> tests/ui/needless_late_init.rs:35:5 + --> tests/ui/needless_late_init.rs:38:5 | LL | let d: usize; | ^^^^^^^^^^^^^ created here +LL | LL | d = 1; | ^^^^^ initialised here | help: move the declaration `d` here | LL ~ +LL | LL ~ let d: usize = 1; | error: unneeded late initialization - --> tests/ui/needless_late_init.rs:38:5 + --> tests/ui/needless_late_init.rs:42:5 | LL | let e; | ^^^^^^ created here +LL | LL | e = format!("{}", d); | ^^^^^^^^^^^^^^^^^^^^ initialised here | help: move the declaration `e` here | LL ~ +LL | LL ~ let e = format!("{}", d); | error: unneeded late initialization - --> tests/ui/needless_late_init.rs:43:5 + --> tests/ui/needless_late_init.rs:48:5 | LL | let a; | ^^^^^^ @@ -83,6 +92,7 @@ LL | let a; help: move the declaration `a` here and remove the assignments from the `match` arms | LL ~ +LL | LL | let n = 1; LL ~ let a = match n { LL ~ 1 => "one", @@ -93,7 +103,7 @@ LL ~ }; | error: unneeded late initialization - --> tests/ui/needless_late_init.rs:52:5 + --> tests/ui/needless_late_init.rs:58:5 | LL | let b; | ^^^^^^ @@ -101,6 +111,7 @@ LL | let b; help: move the declaration `b` here and remove the assignments from the branches | LL ~ +LL | LL ~ let b = if n == 3 { LL ~ "four" LL | } else { @@ -109,7 +120,7 @@ LL ~ }; | error: unneeded late initialization - --> tests/ui/needless_late_init.rs:59:5 + --> tests/ui/needless_late_init.rs:66:5 | LL | let d; | ^^^^^^ @@ -117,6 +128,7 @@ LL | let d; help: move the declaration `d` here and remove the assignments from the branches | LL ~ +LL | LL ~ let d = if true { LL | let temp = 5; LL ~ temp @@ -126,7 +138,7 @@ LL ~ }; | error: unneeded late initialization - --> tests/ui/needless_late_init.rs:67:5 + --> tests/ui/needless_late_init.rs:75:5 | LL | let e; | ^^^^^^ @@ -134,6 +146,7 @@ LL | let e; help: move the declaration `e` here and remove the assignments from the branches | LL ~ +LL | LL ~ let e = if true { LL ~ format!("{} {}", a, b) LL | } else { @@ -142,7 +155,7 @@ LL ~ }; | error: unneeded late initialization - --> tests/ui/needless_late_init.rs:74:5 + --> tests/ui/needless_late_init.rs:83:5 | LL | let f; | ^^^^^^ @@ -150,12 +163,13 @@ LL | let f; help: move the declaration `f` here and remove the assignments from the `match` arms | LL ~ +LL | LL ~ let f = match 1 { LL ~ 1 => "three", | error: unneeded late initialization - --> tests/ui/needless_late_init.rs:80:5 + --> tests/ui/needless_late_init.rs:90:5 | LL | let g: usize; | ^^^^^^^^^^^^^ @@ -163,6 +177,7 @@ LL | let g: usize; help: move the declaration `g` here and remove the assignments from the branches | LL ~ +LL | LL ~ let g: usize = if true { LL ~ 5 LL | } else { @@ -171,39 +186,24 @@ LL ~ }; | error: unneeded late initialization - --> tests/ui/needless_late_init.rs:88:5 + --> tests/ui/needless_late_init.rs:99:5 | LL | let x; | ^^^^^^ created here -LL | let y = SignificantDrop; +... LL | x = 1; | ^^^^^ initialised here | help: move the declaration `x` here | LL ~ +LL | LL | let y = SignificantDrop; LL ~ let x = 1; | error: unneeded late initialization - --> tests/ui/needless_late_init.rs:92:5 - | -LL | let x; - | ^^^^^^ created here -LL | let y = 1; -LL | x = SignificantDrop; - | ^^^^^^^^^^^^^^^^^^^ initialised here - | -help: move the declaration `x` here - | -LL ~ -LL | let y = 1; -LL ~ let x = SignificantDrop; - | - -error: unneeded late initialization - --> tests/ui/needless_late_init.rs:96:5 + --> tests/ui/needless_late_init.rs:104:5 | LL | let x; | ^^^^^^ created here @@ -214,14 +214,31 @@ LL | x = SignificantDrop; help: move the declaration `x` here | LL ~ -LL | // types that should be considered insignificant +LL | +LL | let y = 1; +LL ~ let x = SignificantDrop; + | + +error: unneeded late initialization + --> tests/ui/needless_late_init.rs:109:5 + | +LL | let x; + | ^^^^^^ created here +... +LL | x = SignificantDrop; + | ^^^^^^^^^^^^^^^^^^^ initialised here + | +help: move the declaration `x` here + | +LL ~ +LL | ... LL | let y = Box::new(4); LL ~ let x = SignificantDrop; | error: unneeded late initialization - --> tests/ui/needless_late_init.rs:115:5 + --> tests/ui/needless_late_init.rs:129:5 | LL | let a; | ^^^^^^ @@ -229,6 +246,7 @@ LL | let a; help: move the declaration `a` here and remove the assignments from the `match` arms | LL ~ +LL | LL | let n = 1; LL ~ let a = match n { LL ~ 1 => f().await, @@ -239,7 +257,7 @@ LL ~ }; | error: unneeded late initialization - --> tests/ui/needless_late_init.rs:132:5 + --> tests/ui/needless_late_init.rs:147:5 | LL | let a; | ^^^^^^ @@ -247,6 +265,7 @@ LL | let a; help: move the declaration `a` here and remove the assignments from the `match` arms | LL ~ +LL | LL | let n = 1; LL ~ let a = match n { LL ~ 1 => f(), diff --git a/tests/ui/needless_lifetimes.fixed b/tests/ui/needless_lifetimes.fixed index 86cf9a9cdb63..d59393fb3f3c 100644 --- a/tests/ui/needless_lifetimes.fixed +++ b/tests/ui/needless_lifetimes.fixed @@ -1,6 +1,6 @@ //@aux-build:proc_macros.rs -#![warn(clippy::needless_lifetimes)] +#![warn(clippy::needless_lifetimes, clippy::elidable_lifetime_names)] #![allow( unused, clippy::boxed_local, @@ -9,15 +9,18 @@ clippy::redundant_allocation, clippy::unnecessary_wraps, dyn_drop, - clippy::get_first + clippy::get_first, + elided_named_lifetimes )] extern crate proc_macros; use proc_macros::inline_macros; fn distinct_lifetimes(_x: &u8, _y: &u8, _z: u8) {} +//~^ needless_lifetimes fn distinct_and_static(_x: &u8, _y: &u8, _z: &'static u8) {} +//~^ needless_lifetimes // No error; same lifetime on two params. fn same_lifetime_on_input<'a>(_x: &'a u8, _y: &'a u8) {} @@ -28,6 +31,7 @@ fn only_static_on_input(_x: &u8, _y: &u8, _z: &'static u8) {} fn mut_and_static_input(_x: &mut u8, _y: &'static str) {} fn in_and_out(x: &u8, _y: u8) -> &u8 { + //~^ needless_lifetimes x } @@ -40,6 +44,7 @@ fn multiple_in_and_out_1<'a>(x: &'a u8, _y: &'a u8) -> &'a u8 { // fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8 // ^^^ fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8 { + //~^ needless_lifetimes x } @@ -47,6 +52,7 @@ fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8 { // fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8 // ^^^ fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8 { + //~^ needless_lifetimes y } @@ -64,6 +70,7 @@ fn in_static_and_out<'a>(x: &'a u8, _y: &'static u8) -> &'a u8 { // fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()> // ^^^ fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()> { + //~^ needless_lifetimes Ok(x) } @@ -71,6 +78,7 @@ fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()> { // fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()> // ^^^ fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()> { + //~^ needless_lifetimes Ok(y) } @@ -80,53 +88,19 @@ fn deep_reference_2<'a>(x: Result<&'a u8, &'a u8>) -> &'a u8 { } fn deep_reference_3(x: &u8, _y: u8) -> Result<&u8, ()> { + //~^ needless_lifetimes Ok(x) } // Where-clause, but without lifetimes. fn where_clause_without_lt(x: &u8, _y: u8) -> Result<&u8, ()> +//~^ needless_lifetimes where T: Copy, { Ok(x) } -type Ref<'r> = &'r u8; - -// No error; same lifetime on two params. -fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) {} - -fn lifetime_param_2(_x: Ref<'_>, _y: &u8) {} - -// No error; bounded lifetime. -fn lifetime_param_3<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) {} - -// No error; bounded lifetime. -fn lifetime_param_4<'a, 'b>(_x: Ref<'a>, _y: &'b u8) -where - 'b: 'a, -{ -} - -struct Lt<'a, I: 'static> { - x: &'a I, -} - -// No error; fn bound references `'a`. -fn fn_bound<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> -where - F: Fn(Lt<'a, I>) -> Lt<'a, I>, -{ - unreachable!() -} - -fn fn_bound_2(_m: Lt<'_, I>, _f: F) -> Lt<'_, I> -where - for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I>, -{ - unreachable!() -} - // No error; see below. fn fn_bound_3<'a, F: FnOnce(&'a i32)>(x: &'a i32, f: F) { f(x); @@ -151,6 +125,7 @@ struct X { impl X { fn self_and_out(&self) -> &u8 { + //~^ needless_lifetimes &self.x } @@ -158,6 +133,7 @@ impl X { // fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8 // ^^^ fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8 { + //~^ needless_lifetimes &self.x } @@ -165,10 +141,12 @@ impl X { // fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8 // ^^^^^ fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8 { + //~^ needless_lifetimes x } fn distinct_self_and_in(&self, _x: &u8) {} + //~^ needless_lifetimes // No error; same lifetimes on two params. fn self_and_same_in<'s>(&'s self, _x: &'s u8) {} @@ -187,33 +165,12 @@ fn already_elided<'a>(_: &u8, _: &'a u8) -> &'a u8 { unimplemented!() } -fn struct_with_lt(_foo: Foo<'_>) -> &str { - unimplemented!() -} - -// No warning; two input lifetimes (named on the reference, anonymous on `Foo`). -fn struct_with_lt2<'a>(_foo: &'a Foo) -> &'a str { - unimplemented!() -} - -// No warning; two input lifetimes (anonymous on the reference, named on `Foo`). -fn struct_with_lt3<'a>(_foo: &Foo<'a>) -> &'a str { - unimplemented!() -} - -// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is -// valid: -// fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str -// ^^ -fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str { - unimplemented!() -} - // Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is // valid: // fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str // ^^^^ fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str { + //~^ needless_lifetimes unimplemented!() } @@ -229,42 +186,23 @@ fn trait_obj_elided<'a>(_arg: &'a dyn WithLifetime) -> &'a str { // Should warn because there is no lifetime on `Drop`, so this would be // unambiguous if we elided the lifetime. fn trait_obj_elided2(_arg: &dyn Drop) -> &str { + //~^ needless_lifetimes unimplemented!() } type FooAlias<'a> = Foo<'a>; -fn alias_with_lt(_foo: FooAlias<'_>) -> &str { - unimplemented!() -} - -// No warning; two input lifetimes (named on the reference, anonymous on `FooAlias`). -fn alias_with_lt2<'a>(_foo: &'a FooAlias) -> &'a str { - unimplemented!() -} - -// No warning; two input lifetimes (anonymous on the reference, named on `FooAlias`). -fn alias_with_lt3<'a>(_foo: &FooAlias<'a>) -> &'a str { - unimplemented!() -} - -// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is -// valid: -// fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str -// ^^ -fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str { - unimplemented!() -} - // Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is // valid: // fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str // ^^^^^^^^^ fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str { + //~^ needless_lifetimes unimplemented!() } fn named_input_elided_output(_arg: &str) -> &str { + //~^ needless_lifetimes unimplemented!() } @@ -273,6 +211,7 @@ fn elided_input_named_output<'a>(_arg: &str) -> &'a str { } fn trait_bound_ok>(_: &u8, _: T) { + //~^ needless_lifetimes unimplemented!() } fn trait_bound<'a, T: WithLifetime<'a>>(_: &'a u8, _: T) { @@ -304,37 +243,16 @@ fn test<'a>(x: &'a [u8]) -> u8 { *y } -// Issue #3284: give hint regarding lifetime in return type. -struct Cow<'a> { - x: &'a str, -} -fn out_return_type_lts(e: &str) -> Cow<'_> { - unimplemented!() -} - // Make sure we still warn on implementations mod issue4291 { trait BadTrait { fn needless_lt(x: &u8) {} + //~^ needless_lifetimes } impl BadTrait for () { fn needless_lt(_x: &u8) {} - } -} - -mod issue2944 { - trait Foo {} - struct Bar; - struct Baz<'a> { - bar: &'a Bar, - } - - impl Foo for Baz<'_> {} - impl Bar { - fn baz(&self) -> impl Foo + '_ { - Baz { bar: self } - } + //~^ needless_lifetimes } } @@ -365,6 +283,7 @@ mod nested_elision_sites { f(i) } fn impl_trait_elidable_nested_anonymous_lifetimes(i: &i32, f: impl Fn(&i32) -> &i32) -> &i32 { + //~^ needless_lifetimes f(i) } @@ -374,6 +293,7 @@ mod nested_elision_sites { } // lint fn generics_elidable &i32>(i: &i32, f: T) -> &i32 { + //~^ needless_lifetimes f(i) } @@ -386,6 +306,7 @@ mod nested_elision_sites { } // lint fn where_clause_elidable(i: &i32, f: T) -> &i32 + //~^ needless_lifetimes where T: Fn(&i32) -> &i32, { @@ -401,6 +322,7 @@ mod nested_elision_sites { } // lint fn pointer_fn_elidable(i: &i32, f: fn(&i32) -> &i32) -> &i32 { + //~^ needless_lifetimes f(i) } @@ -414,9 +336,11 @@ mod nested_elision_sites { // lint fn nested_fn_pointer_3(_: &i32) -> fn(fn(&i32) -> &i32) -> i32 { + //~^ needless_lifetimes |f| 42 } fn nested_fn_pointer_4(_: &i32) -> impl Fn(fn(&i32)) { + //~^ needless_lifetimes |f| () } } @@ -439,17 +363,21 @@ mod issue7296 { struct Foo; impl Foo { fn implicit(&self) -> &() { + //~^ needless_lifetimes &() } fn implicit_mut(&mut self) -> &() { + //~^ needless_lifetimes &() } #[clippy::msrv = "1.81"] fn explicit(self: &Arc) -> &() { + //~^ needless_lifetimes &() } #[clippy::msrv = "1.81"] fn explicit_mut(self: &mut Rc) -> &() { + //~^ needless_lifetimes &() } #[clippy::msrv = "1.80"] @@ -462,20 +390,25 @@ mod issue7296 { } fn lifetime_elsewhere(self: Box, here: &()) -> &() { + //~^ needless_lifetimes &() } } trait Bar { fn implicit(&self) -> &(); + //~^ needless_lifetimes fn implicit_provided(&self) -> &() { + //~^ needless_lifetimes &() } #[clippy::msrv = "1.81"] fn explicit(self: &Arc) -> &(); + //~^ needless_lifetimes #[clippy::msrv = "1.81"] fn explicit_provided(self: &Arc) -> &() { + //~^ needless_lifetimes &() } #[clippy::msrv = "1.80"] @@ -486,7 +419,9 @@ mod issue7296 { } fn lifetime_elsewhere(self: Box, here: &()) -> &(); + //~^ needless_lifetimes fn lifetime_elsewhere_provided(self: Box, here: &()) -> &() { + //~^ needless_lifetimes &() } } @@ -496,8 +431,10 @@ mod pr_9743_false_negative_fix { #![allow(unused)] fn foo(x: &u8, y: &'_ u8) {} + //~^ needless_lifetimes fn bar(x: &u8, y: &'_ u8, z: &'_ u8) {} + //~^ needless_lifetimes } mod pr_9743_output_lifetime_checks { @@ -505,11 +442,13 @@ mod pr_9743_output_lifetime_checks { // lint: only one input fn one_input(x: &u8) -> &u8 { + //~^ needless_lifetimes unimplemented!() } // lint: multiple inputs, output would not be elided fn multiple_inputs_output_not_elided<'b>(x: &u8, y: &'b u8, z: &'b u8) -> &'b u8 { + //~^ needless_lifetimes unimplemented!() } @@ -526,6 +465,7 @@ mod in_macro { // lint local macro expands to function with needless lifetimes inline! { fn one_input(x: &u8) -> &u8 { + //~^ needless_lifetimes unimplemented!() } } @@ -594,85 +534,4 @@ mod issue13749bis { impl<'a, T: 'a> Generic {} } -mod issue13923 { - struct Py<'py> { - data: &'py str, - } - - enum Content<'t, 'py> { - Py(Py<'py>), - T1(&'t str), - T2(&'t str), - } - - enum ContentString<'t> { - T1(&'t str), - T2(&'t str), - } - - impl<'t, 'py> ContentString<'t> { - // `'py` cannot be elided - fn map_content1(self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> { - match self { - Self::T1(content) => Content::T1(f(content)), - Self::T2(content) => Content::T2(f(content)), - } - } - } - - impl<'t> ContentString<'t> { - // `'py` can be elided because of `&self` - fn map_content2(&self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, '_> { - match self { - Self::T1(content) => Content::T1(f(content)), - Self::T2(content) => Content::T2(f(content)), - } - } - } - - impl<'t> ContentString<'t> { - // `'py` can be elided because of `&'_ self` - fn map_content3(&'_ self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, '_> { - match self { - Self::T1(content) => Content::T1(f(content)), - Self::T2(content) => Content::T2(f(content)), - } - } - } - - impl<'t, 'py> ContentString<'t> { - // `'py` should not be elided as the default lifetime, even if working, could be named as `'t` - fn map_content4(self, f: impl FnOnce(&'t str) -> &'t str, o: &'t str) -> Content<'t, 'py> { - match self { - Self::T1(content) => Content::T1(f(content)), - Self::T2(_) => Content::T2(o), - } - } - } - - impl<'t> ContentString<'t> { - // `'py` can be elided because of `&Self` - fn map_content5( - self: std::pin::Pin<&Self>, - f: impl FnOnce(&'t str) -> &'t str, - o: &'t str, - ) -> Content<'t, '_> { - match *self { - Self::T1(content) => Content::T1(f(content)), - Self::T2(_) => Content::T2(o), - } - } - } - - struct Cx<'a, 'b> { - a: &'a u32, - b: &'b u32, - } - - // `'c` cannot be elided because we have several input lifetimes - fn one_explicit<'b>(x: Cx<'_, 'b>) -> &'b u32 { - x.b - } -} - fn main() {} diff --git a/tests/ui/needless_lifetimes.rs b/tests/ui/needless_lifetimes.rs index 1ee0f4c6092a..e24907ab5fcd 100644 --- a/tests/ui/needless_lifetimes.rs +++ b/tests/ui/needless_lifetimes.rs @@ -1,6 +1,6 @@ //@aux-build:proc_macros.rs -#![warn(clippy::needless_lifetimes)] +#![warn(clippy::needless_lifetimes, clippy::elidable_lifetime_names)] #![allow( unused, clippy::boxed_local, @@ -9,15 +9,18 @@ clippy::redundant_allocation, clippy::unnecessary_wraps, dyn_drop, - clippy::get_first + clippy::get_first, + elided_named_lifetimes )] extern crate proc_macros; use proc_macros::inline_macros; fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {} +//~^ needless_lifetimes fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {} +//~^ needless_lifetimes // No error; same lifetime on two params. fn same_lifetime_on_input<'a>(_x: &'a u8, _y: &'a u8) {} @@ -28,6 +31,7 @@ fn only_static_on_input(_x: &u8, _y: &u8, _z: &'static u8) {} fn mut_and_static_input(_x: &mut u8, _y: &'static str) {} fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { + //~^ needless_lifetimes x } @@ -40,6 +44,7 @@ fn multiple_in_and_out_1<'a>(x: &'a u8, _y: &'a u8) -> &'a u8 { // fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8 // ^^^ fn multiple_in_and_out_2a<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 { + //~^ needless_lifetimes x } @@ -47,6 +52,7 @@ fn multiple_in_and_out_2a<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 { // fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8 // ^^^ fn multiple_in_and_out_2b<'a, 'b>(_x: &'a u8, y: &'b u8) -> &'b u8 { + //~^ needless_lifetimes y } @@ -64,6 +70,7 @@ fn in_static_and_out<'a>(x: &'a u8, _y: &'static u8) -> &'a u8 { // fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()> // ^^^ fn deep_reference_1a<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> { + //~^ needless_lifetimes Ok(x) } @@ -71,6 +78,7 @@ fn deep_reference_1a<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> { // fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()> // ^^^ fn deep_reference_1b<'a, 'b>(_x: &'a u8, y: &'b u8) -> Result<&'b u8, ()> { + //~^ needless_lifetimes Ok(y) } @@ -80,53 +88,19 @@ fn deep_reference_2<'a>(x: Result<&'a u8, &'a u8>) -> &'a u8 { } fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { + //~^ needless_lifetimes Ok(x) } // Where-clause, but without lifetimes. fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> +//~^ needless_lifetimes where T: Copy, { Ok(x) } -type Ref<'r> = &'r u8; - -// No error; same lifetime on two params. -fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) {} - -fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {} - -// No error; bounded lifetime. -fn lifetime_param_3<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) {} - -// No error; bounded lifetime. -fn lifetime_param_4<'a, 'b>(_x: Ref<'a>, _y: &'b u8) -where - 'b: 'a, -{ -} - -struct Lt<'a, I: 'static> { - x: &'a I, -} - -// No error; fn bound references `'a`. -fn fn_bound<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> -where - F: Fn(Lt<'a, I>) -> Lt<'a, I>, -{ - unreachable!() -} - -fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> -where - for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I>, -{ - unreachable!() -} - // No error; see below. fn fn_bound_3<'a, F: FnOnce(&'a i32)>(x: &'a i32, f: F) { f(x); @@ -151,6 +125,7 @@ struct X { impl X { fn self_and_out<'s>(&'s self) -> &'s u8 { + //~^ needless_lifetimes &self.x } @@ -158,6 +133,7 @@ impl X { // fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8 // ^^^ fn self_and_in_out_1<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 { + //~^ needless_lifetimes &self.x } @@ -165,10 +141,12 @@ impl X { // fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8 // ^^^^^ fn self_and_in_out_2<'s, 't>(&'s self, x: &'t u8) -> &'t u8 { + //~^ needless_lifetimes x } fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {} + //~^ needless_lifetimes // No error; same lifetimes on two params. fn self_and_same_in<'s>(&'s self, _x: &'s u8) {} @@ -187,33 +165,12 @@ fn already_elided<'a>(_: &u8, _: &'a u8) -> &'a u8 { unimplemented!() } -fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { - unimplemented!() -} - -// No warning; two input lifetimes (named on the reference, anonymous on `Foo`). -fn struct_with_lt2<'a>(_foo: &'a Foo) -> &'a str { - unimplemented!() -} - -// No warning; two input lifetimes (anonymous on the reference, named on `Foo`). -fn struct_with_lt3<'a>(_foo: &Foo<'a>) -> &'a str { - unimplemented!() -} - -// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is -// valid: -// fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str -// ^^ -fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str { - unimplemented!() -} - // Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is // valid: // fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str // ^^^^ fn struct_with_lt4b<'a, 'b>(_foo: &'a Foo<'b>) -> &'b str { + //~^ needless_lifetimes unimplemented!() } @@ -229,42 +186,23 @@ fn trait_obj_elided<'a>(_arg: &'a dyn WithLifetime) -> &'a str { // Should warn because there is no lifetime on `Drop`, so this would be // unambiguous if we elided the lifetime. fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str { + //~^ needless_lifetimes unimplemented!() } type FooAlias<'a> = Foo<'a>; -fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { - unimplemented!() -} - -// No warning; two input lifetimes (named on the reference, anonymous on `FooAlias`). -fn alias_with_lt2<'a>(_foo: &'a FooAlias) -> &'a str { - unimplemented!() -} - -// No warning; two input lifetimes (anonymous on the reference, named on `FooAlias`). -fn alias_with_lt3<'a>(_foo: &FooAlias<'a>) -> &'a str { - unimplemented!() -} - -// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is -// valid: -// fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str -// ^^ -fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str { - unimplemented!() -} - // Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is // valid: // fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str // ^^^^^^^^^ fn alias_with_lt4b<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'b str { + //~^ needless_lifetimes unimplemented!() } fn named_input_elided_output<'a>(_arg: &'a str) -> &str { + //~^ needless_lifetimes unimplemented!() } @@ -273,6 +211,7 @@ fn elided_input_named_output<'a>(_arg: &str) -> &'a str { } fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { + //~^ needless_lifetimes unimplemented!() } fn trait_bound<'a, T: WithLifetime<'a>>(_: &'a u8, _: T) { @@ -304,37 +243,16 @@ fn test<'a>(x: &'a [u8]) -> u8 { *y } -// Issue #3284: give hint regarding lifetime in return type. -struct Cow<'a> { - x: &'a str, -} -fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> { - unimplemented!() -} - // Make sure we still warn on implementations mod issue4291 { trait BadTrait { fn needless_lt<'a>(x: &'a u8) {} + //~^ needless_lifetimes } impl BadTrait for () { fn needless_lt<'a>(_x: &'a u8) {} - } -} - -mod issue2944 { - trait Foo {} - struct Bar; - struct Baz<'a> { - bar: &'a Bar, - } - - impl<'a> Foo for Baz<'a> {} - impl Bar { - fn baz<'a>(&'a self) -> impl Foo + 'a { - Baz { bar: self } - } + //~^ needless_lifetimes } } @@ -365,6 +283,7 @@ mod nested_elision_sites { f(i) } fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 { + //~^ needless_lifetimes f(i) } @@ -374,6 +293,7 @@ mod nested_elision_sites { } // lint fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 { + //~^ needless_lifetimes f(i) } @@ -386,6 +306,7 @@ mod nested_elision_sites { } // lint fn where_clause_elidable<'a, T>(i: &'a i32, f: T) -> &'a i32 + //~^ needless_lifetimes where T: Fn(&i32) -> &i32, { @@ -401,6 +322,7 @@ mod nested_elision_sites { } // lint fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 { + //~^ needless_lifetimes f(i) } @@ -414,9 +336,11 @@ mod nested_elision_sites { // lint fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 { + //~^ needless_lifetimes |f| 42 } fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) { + //~^ needless_lifetimes |f| () } } @@ -439,17 +363,21 @@ mod issue7296 { struct Foo; impl Foo { fn implicit<'a>(&'a self) -> &'a () { + //~^ needless_lifetimes &() } fn implicit_mut<'a>(&'a mut self) -> &'a () { + //~^ needless_lifetimes &() } #[clippy::msrv = "1.81"] fn explicit<'a>(self: &'a Arc) -> &'a () { + //~^ needless_lifetimes &() } #[clippy::msrv = "1.81"] fn explicit_mut<'a>(self: &'a mut Rc) -> &'a () { + //~^ needless_lifetimes &() } #[clippy::msrv = "1.80"] @@ -462,20 +390,25 @@ mod issue7296 { } fn lifetime_elsewhere<'a>(self: Box, here: &'a ()) -> &'a () { + //~^ needless_lifetimes &() } } trait Bar { fn implicit<'a>(&'a self) -> &'a (); + //~^ needless_lifetimes fn implicit_provided<'a>(&'a self) -> &'a () { + //~^ needless_lifetimes &() } #[clippy::msrv = "1.81"] fn explicit<'a>(self: &'a Arc) -> &'a (); + //~^ needless_lifetimes #[clippy::msrv = "1.81"] fn explicit_provided<'a>(self: &'a Arc) -> &'a () { + //~^ needless_lifetimes &() } #[clippy::msrv = "1.80"] @@ -486,7 +419,9 @@ mod issue7296 { } fn lifetime_elsewhere<'a>(self: Box, here: &'a ()) -> &'a (); + //~^ needless_lifetimes fn lifetime_elsewhere_provided<'a>(self: Box, here: &'a ()) -> &'a () { + //~^ needless_lifetimes &() } } @@ -496,8 +431,10 @@ mod pr_9743_false_negative_fix { #![allow(unused)] fn foo<'a>(x: &'a u8, y: &'_ u8) {} + //~^ needless_lifetimes fn bar<'a>(x: &'a u8, y: &'_ u8, z: &'_ u8) {} + //~^ needless_lifetimes } mod pr_9743_output_lifetime_checks { @@ -505,11 +442,13 @@ mod pr_9743_output_lifetime_checks { // lint: only one input fn one_input<'a>(x: &'a u8) -> &'a u8 { + //~^ needless_lifetimes unimplemented!() } // lint: multiple inputs, output would not be elided fn multiple_inputs_output_not_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'b u8 { + //~^ needless_lifetimes unimplemented!() } @@ -526,6 +465,7 @@ mod in_macro { // lint local macro expands to function with needless lifetimes inline! { fn one_input<'a>(x: &'a u8) -> &'a u8 { + //~^ needless_lifetimes unimplemented!() } } @@ -594,85 +534,4 @@ mod issue13749bis { impl<'a, T: 'a> Generic {} } -mod issue13923 { - struct Py<'py> { - data: &'py str, - } - - enum Content<'t, 'py> { - Py(Py<'py>), - T1(&'t str), - T2(&'t str), - } - - enum ContentString<'t> { - T1(&'t str), - T2(&'t str), - } - - impl<'t, 'py> ContentString<'t> { - // `'py` cannot be elided - fn map_content1(self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> { - match self { - Self::T1(content) => Content::T1(f(content)), - Self::T2(content) => Content::T2(f(content)), - } - } - } - - impl<'t, 'py> ContentString<'t> { - // `'py` can be elided because of `&self` - fn map_content2(&self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> { - match self { - Self::T1(content) => Content::T1(f(content)), - Self::T2(content) => Content::T2(f(content)), - } - } - } - - impl<'t, 'py> ContentString<'t> { - // `'py` can be elided because of `&'_ self` - fn map_content3(&'_ self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> { - match self { - Self::T1(content) => Content::T1(f(content)), - Self::T2(content) => Content::T2(f(content)), - } - } - } - - impl<'t, 'py> ContentString<'t> { - // `'py` should not be elided as the default lifetime, even if working, could be named as `'t` - fn map_content4(self, f: impl FnOnce(&'t str) -> &'t str, o: &'t str) -> Content<'t, 'py> { - match self { - Self::T1(content) => Content::T1(f(content)), - Self::T2(_) => Content::T2(o), - } - } - } - - impl<'t, 'py> ContentString<'t> { - // `'py` can be elided because of `&Self` - fn map_content5( - self: std::pin::Pin<&Self>, - f: impl FnOnce(&'t str) -> &'t str, - o: &'t str, - ) -> Content<'t, 'py> { - match *self { - Self::T1(content) => Content::T1(f(content)), - Self::T2(_) => Content::T2(o), - } - } - } - - struct Cx<'a, 'b> { - a: &'a u32, - b: &'b u32, - } - - // `'c` cannot be elided because we have several input lifetimes - fn one_explicit<'b>(x: Cx<'_, 'b>) -> &'b u32 { - &x.b - } -} - fn main() {} diff --git a/tests/ui/needless_lifetimes.stderr b/tests/ui/needless_lifetimes.stderr index 465d529bf16c..138d0498c43e 100644 --- a/tests/ui/needless_lifetimes.stderr +++ b/tests/ui/needless_lifetimes.stderr @@ -1,16 +1,5 @@ -error: elided lifetime has a name - --> tests/ui/needless_lifetimes.rs:267:52 - | -LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str { - | -- ^ this elided lifetime gets resolved as `'a` - | | - | lifetime `'a` declared here - | - = note: `-D elided-named-lifetimes` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(elided_named_lifetimes)]` - error: the following explicit lifetimes could be elided: 'a, 'b - --> tests/ui/needless_lifetimes.rs:18:23 + --> tests/ui/needless_lifetimes.rs:19:23 | LL | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {} | ^^ ^^ ^^ ^^ @@ -24,7 +13,7 @@ LL + fn distinct_lifetimes(_x: &u8, _y: &u8, _z: u8) {} | error: the following explicit lifetimes could be elided: 'a, 'b - --> tests/ui/needless_lifetimes.rs:20:24 + --> tests/ui/needless_lifetimes.rs:22:24 | LL | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {} | ^^ ^^ ^^ ^^ @@ -36,7 +25,7 @@ LL + fn distinct_and_static(_x: &u8, _y: &u8, _z: &'static u8) {} | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:30:15 + --> tests/ui/needless_lifetimes.rs:33:15 | LL | fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { | ^^ ^^ ^^ @@ -48,7 +37,7 @@ LL + fn in_and_out(x: &u8, _y: u8) -> &u8 { | error: the following explicit lifetimes could be elided: 'b - --> tests/ui/needless_lifetimes.rs:42:31 + --> tests/ui/needless_lifetimes.rs:46:31 | LL | fn multiple_in_and_out_2a<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 { | ^^ ^^ @@ -60,7 +49,7 @@ LL + fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8 { | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:49:27 + --> tests/ui/needless_lifetimes.rs:54:27 | LL | fn multiple_in_and_out_2b<'a, 'b>(_x: &'a u8, y: &'b u8) -> &'b u8 { | ^^ ^^ @@ -72,7 +61,7 @@ LL + fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8 { | error: the following explicit lifetimes could be elided: 'b - --> tests/ui/needless_lifetimes.rs:66:26 + --> tests/ui/needless_lifetimes.rs:72:26 | LL | fn deep_reference_1a<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> { | ^^ ^^ @@ -84,7 +73,7 @@ LL + fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()> { | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:73:22 + --> tests/ui/needless_lifetimes.rs:80:22 | LL | fn deep_reference_1b<'a, 'b>(_x: &'a u8, y: &'b u8) -> Result<&'b u8, ()> { | ^^ ^^ @@ -96,7 +85,7 @@ LL + fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()> { | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:82:21 + --> tests/ui/needless_lifetimes.rs:90:21 | LL | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { | ^^ ^^ ^^ @@ -108,7 +97,7 @@ LL + fn deep_reference_3(x: &u8, _y: u8) -> Result<&u8, ()> { | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:87:28 + --> tests/ui/needless_lifetimes.rs:96:28 | LL | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> | ^^ ^^ ^^ @@ -119,32 +108,8 @@ LL - fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> LL + fn where_clause_without_lt(x: &u8, _y: u8) -> Result<&u8, ()> | -error: the following explicit lifetimes could be elided: 'a, 'b - --> tests/ui/needless_lifetimes.rs:99:21 - | -LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {} - | ^^ ^^ ^^ ^^ - | -help: elide the lifetimes - | -LL - fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {} -LL + fn lifetime_param_2(_x: Ref<'_>, _y: &u8) {} - | - -error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:123:15 - | -LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> - | ^^ ^^ ^^ - | -help: elide the lifetimes - | -LL - fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> -LL + fn fn_bound_2(_m: Lt<'_, I>, _f: F) -> Lt<'_, I> - | - error: the following explicit lifetimes could be elided: 's - --> tests/ui/needless_lifetimes.rs:153:21 + --> tests/ui/needless_lifetimes.rs:127:21 | LL | fn self_and_out<'s>(&'s self) -> &'s u8 { | ^^ ^^ ^^ @@ -156,7 +121,7 @@ LL + fn self_and_out(&self) -> &u8 { | error: the following explicit lifetimes could be elided: 't - --> tests/ui/needless_lifetimes.rs:160:30 + --> tests/ui/needless_lifetimes.rs:135:30 | LL | fn self_and_in_out_1<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 { | ^^ ^^ @@ -168,7 +133,7 @@ LL + fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8 { | error: the following explicit lifetimes could be elided: 's - --> tests/ui/needless_lifetimes.rs:167:26 + --> tests/ui/needless_lifetimes.rs:143:26 | LL | fn self_and_in_out_2<'s, 't>(&'s self, x: &'t u8) -> &'t u8 { | ^^ ^^ @@ -180,7 +145,7 @@ LL + fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8 { | error: the following explicit lifetimes could be elided: 's, 't - --> tests/ui/needless_lifetimes.rs:171:29 + --> tests/ui/needless_lifetimes.rs:148:29 | LL | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {} | ^^ ^^ ^^ ^^ @@ -192,31 +157,7 @@ LL + fn distinct_self_and_in(&self, _x: &u8) {} | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:190:19 - | -LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { - | ^^ ^^ ^^ - | -help: elide the lifetimes - | -LL - fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { -LL + fn struct_with_lt(_foo: Foo<'_>) -> &str { - | - -error: the following explicit lifetimes could be elided: 'b - --> tests/ui/needless_lifetimes.rs:208:25 - | -LL | fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str { - | ^^ ^^ - | -help: elide the lifetimes - | -LL - fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str { -LL + fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str { - | - -error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:216:21 + --> tests/ui/needless_lifetimes.rs:172:21 | LL | fn struct_with_lt4b<'a, 'b>(_foo: &'a Foo<'b>) -> &'b str { | ^^ ^^ @@ -228,7 +169,7 @@ LL + fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str { | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:231:22 + --> tests/ui/needless_lifetimes.rs:188:22 | LL | fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str { | ^^ ^^ ^^ @@ -240,31 +181,7 @@ LL + fn trait_obj_elided2(_arg: &dyn Drop) -> &str { | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:237:18 - | -LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { - | ^^ ^^ ^^ - | -help: elide the lifetimes - | -LL - fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { -LL + fn alias_with_lt(_foo: FooAlias<'_>) -> &str { - | - -error: the following explicit lifetimes could be elided: 'b - --> tests/ui/needless_lifetimes.rs:255:24 - | -LL | fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str { - | ^^ ^^ - | -help: elide the lifetimes - | -LL - fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str { -LL + fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str { - | - -error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:263:20 + --> tests/ui/needless_lifetimes.rs:199:20 | LL | fn alias_with_lt4b<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'b str { | ^^ ^^ @@ -276,7 +193,7 @@ LL + fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str { | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:267:30 + --> tests/ui/needless_lifetimes.rs:204:30 | LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str { | ^^ ^^ ^ @@ -288,7 +205,7 @@ LL + fn named_input_elided_output(_arg: &str) -> &str { | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:275:19 + --> tests/ui/needless_lifetimes.rs:213:19 | LL | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { | ^^ ^^ @@ -300,19 +217,7 @@ LL + fn trait_bound_ok>(_: &u8, _: T) { | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:311:24 - | -LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> { - | ^^ ^^ ^^ - | -help: elide the lifetimes - | -LL - fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> { -LL + fn out_return_type_lts(e: &str) -> Cow<'_> { - | - -error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:318:24 + --> tests/ui/needless_lifetimes.rs:249:24 | LL | fn needless_lt<'a>(x: &'a u8) {} | ^^ ^^ @@ -324,7 +229,7 @@ LL + fn needless_lt(x: &u8) {} | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:322:24 + --> tests/ui/needless_lifetimes.rs:254:24 | LL | fn needless_lt<'a>(_x: &'a u8) {} | ^^ ^^ @@ -336,31 +241,7 @@ LL + fn needless_lt(_x: &u8) {} | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:333:10 - | -LL | impl<'a> Foo for Baz<'a> {} - | ^^ ^^ - | -help: elide the lifetimes - | -LL - impl<'a> Foo for Baz<'a> {} -LL + impl Foo for Baz<'_> {} - | - -error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:335:16 - | -LL | fn baz<'a>(&'a self) -> impl Foo + 'a { - | ^^ ^^ ^^ - | -help: elide the lifetimes - | -LL - fn baz<'a>(&'a self) -> impl Foo + 'a { -LL + fn baz(&self) -> impl Foo + '_ { - | - -error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:367:55 + --> tests/ui/needless_lifetimes.rs:285:55 | LL | fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 { | ^^ ^^ ^^ @@ -372,7 +253,7 @@ LL + fn impl_trait_elidable_nested_anonymous_lifetimes(i: &i32, f: impl Fn(& | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:376:26 + --> tests/ui/needless_lifetimes.rs:295:26 | LL | fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 { | ^^ ^^ ^^ @@ -384,7 +265,7 @@ LL + fn generics_elidable &i32>(i: &i32, f: T) -> &i32 { | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:388:30 + --> tests/ui/needless_lifetimes.rs:308:30 | LL | fn where_clause_elidable<'a, T>(i: &'a i32, f: T) -> &'a i32 | ^^ ^^ ^^ @@ -396,7 +277,7 @@ LL + fn where_clause_elidable(i: &i32, f: T) -> &i32 | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:403:28 + --> tests/ui/needless_lifetimes.rs:324:28 | LL | fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 { | ^^ ^^ ^^ @@ -408,7 +289,7 @@ LL + fn pointer_fn_elidable(i: &i32, f: fn(&i32) -> &i32) -> &i32 { | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:416:28 + --> tests/ui/needless_lifetimes.rs:338:28 | LL | fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 { | ^^ ^^ @@ -420,7 +301,7 @@ LL + fn nested_fn_pointer_3(_: &i32) -> fn(fn(&i32) -> &i32) -> i32 { | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:419:28 + --> tests/ui/needless_lifetimes.rs:342:28 | LL | fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) { | ^^ ^^ @@ -432,7 +313,7 @@ LL + fn nested_fn_pointer_4(_: &i32) -> impl Fn(fn(&i32)) { | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:441:21 + --> tests/ui/needless_lifetimes.rs:365:21 | LL | fn implicit<'a>(&'a self) -> &'a () { | ^^ ^^ ^^ @@ -444,7 +325,7 @@ LL + fn implicit(&self) -> &() { | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:444:25 + --> tests/ui/needless_lifetimes.rs:369:25 | LL | fn implicit_mut<'a>(&'a mut self) -> &'a () { | ^^ ^^ ^^ @@ -456,7 +337,7 @@ LL + fn implicit_mut(&mut self) -> &() { | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:448:21 + --> tests/ui/needless_lifetimes.rs:374:21 | LL | fn explicit<'a>(self: &'a Arc) -> &'a () { | ^^ ^^ ^^ @@ -468,7 +349,7 @@ LL + fn explicit(self: &Arc) -> &() { | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:452:25 + --> tests/ui/needless_lifetimes.rs:379:25 | LL | fn explicit_mut<'a>(self: &'a mut Rc) -> &'a () { | ^^ ^^ ^^ @@ -480,7 +361,7 @@ LL + fn explicit_mut(self: &mut Rc) -> &() { | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:464:31 + --> tests/ui/needless_lifetimes.rs:392:31 | LL | fn lifetime_elsewhere<'a>(self: Box, here: &'a ()) -> &'a () { | ^^ ^^ ^^ @@ -492,7 +373,7 @@ LL + fn lifetime_elsewhere(self: Box, here: &()) -> &() { | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:470:21 + --> tests/ui/needless_lifetimes.rs:399:21 | LL | fn implicit<'a>(&'a self) -> &'a (); | ^^ ^^ ^^ @@ -504,7 +385,7 @@ LL + fn implicit(&self) -> &(); | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:471:30 + --> tests/ui/needless_lifetimes.rs:401:30 | LL | fn implicit_provided<'a>(&'a self) -> &'a () { | ^^ ^^ ^^ @@ -516,7 +397,7 @@ LL + fn implicit_provided(&self) -> &() { | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:476:21 + --> tests/ui/needless_lifetimes.rs:407:21 | LL | fn explicit<'a>(self: &'a Arc) -> &'a (); | ^^ ^^ ^^ @@ -528,7 +409,7 @@ LL + fn explicit(self: &Arc) -> &(); | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:478:30 + --> tests/ui/needless_lifetimes.rs:410:30 | LL | fn explicit_provided<'a>(self: &'a Arc) -> &'a () { | ^^ ^^ ^^ @@ -540,7 +421,7 @@ LL + fn explicit_provided(self: &Arc) -> &() { | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:488:31 + --> tests/ui/needless_lifetimes.rs:421:31 | LL | fn lifetime_elsewhere<'a>(self: Box, here: &'a ()) -> &'a (); | ^^ ^^ ^^ @@ -552,7 +433,7 @@ LL + fn lifetime_elsewhere(self: Box, here: &()) -> &(); | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:489:40 + --> tests/ui/needless_lifetimes.rs:423:40 | LL | fn lifetime_elsewhere_provided<'a>(self: Box, here: &'a ()) -> &'a () { | ^^ ^^ ^^ @@ -564,7 +445,7 @@ LL + fn lifetime_elsewhere_provided(self: Box, here: &()) -> &() { | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:498:12 + --> tests/ui/needless_lifetimes.rs:433:12 | LL | fn foo<'a>(x: &'a u8, y: &'_ u8) {} | ^^ ^^ @@ -576,7 +457,7 @@ LL + fn foo(x: &u8, y: &'_ u8) {} | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:500:12 + --> tests/ui/needless_lifetimes.rs:436:12 | LL | fn bar<'a>(x: &'a u8, y: &'_ u8, z: &'_ u8) {} | ^^ ^^ @@ -588,7 +469,7 @@ LL + fn bar(x: &u8, y: &'_ u8, z: &'_ u8) {} | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:507:18 + --> tests/ui/needless_lifetimes.rs:444:18 | LL | fn one_input<'a>(x: &'a u8) -> &'a u8 { | ^^ ^^ ^^ @@ -600,7 +481,7 @@ LL + fn one_input(x: &u8) -> &u8 { | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:512:42 + --> tests/ui/needless_lifetimes.rs:450:42 | LL | fn multiple_inputs_output_not_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'b u8 { | ^^ ^^ @@ -612,7 +493,7 @@ LL + fn multiple_inputs_output_not_elided<'b>(x: &u8, y: &'b u8, z: &'b u8) | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:528:22 + --> tests/ui/needless_lifetimes.rs:467:22 | LL | fn one_input<'a>(x: &'a u8) -> &'a u8 { | ^^ ^^ ^^ @@ -624,64 +505,5 @@ LL - fn one_input<'a>(x: &'a u8) -> &'a u8 { LL + fn one_input(x: &u8) -> &u8 { | -error: the following explicit lifetimes could be elided: 'py - --> tests/ui/needless_lifetimes.rs:623:14 - | -LL | impl<'t, 'py> ContentString<'t> { - | ^^^ -LL | // `'py` can be elided because of `&self` -LL | fn map_content2(&self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> { - | ^^^ - | -help: elide the lifetimes - | -LL ~ impl<'t> ContentString<'t> { -LL | // `'py` can be elided because of `&self` -LL ~ fn map_content2(&self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, '_> { - | - -error: the following explicit lifetimes could be elided: 'py - --> tests/ui/needless_lifetimes.rs:633:14 - | -LL | impl<'t, 'py> ContentString<'t> { - | ^^^ -LL | // `'py` can be elided because of `&'_ self` -LL | fn map_content3(&'_ self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> { - | ^^^ - | -help: elide the lifetimes - | -LL ~ impl<'t> ContentString<'t> { -LL | // `'py` can be elided because of `&'_ self` -LL ~ fn map_content3(&'_ self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, '_> { - | - -error: the following explicit lifetimes could be elided: 'py - --> tests/ui/needless_lifetimes.rs:653:14 - | -LL | impl<'t, 'py> ContentString<'t> { - | ^^^ -... -LL | ) -> Content<'t, 'py> { - | ^^^ - | -help: elide the lifetimes - | -LL ~ impl<'t> ContentString<'t> { -LL | // `'py` can be elided because of `&Self` -... -LL | o: &'t str, -LL ~ ) -> Content<'t, '_> { - | - -error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_lifetimes.rs:674:9 - | -LL | &x.b - | ^^^^ help: change this to: `x.b` - | - = note: `-D clippy::needless-borrow` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::needless_borrow)]` - -error: aborting due to 56 previous errors +error: aborting due to 42 previous errors diff --git a/tests/ui/needless_match.fixed b/tests/ui/needless_match.fixed index 06c6169d0da0..b2c2bbfaa361 100644 --- a/tests/ui/needless_match.fixed +++ b/tests/ui/needless_match.fixed @@ -61,6 +61,7 @@ fn result_match() { fn if_let_option() { let _ = Some(1); + //~^ needless_match fn do_something() {} @@ -96,7 +97,9 @@ fn if_let_option_result() -> Result<(), ()> { fn if_let_result() { let x: Result = Ok(1); let _: Result = x; + //~^ needless_match let _: Result = x; + //~^ needless_match // Input type mismatch, don't trigger #[allow(clippy::question_mark)] let _: Result = if let Err(e) = Ok(1) { Err(e) } else { x }; diff --git a/tests/ui/needless_match.rs b/tests/ui/needless_match.rs index 6b71de68e1be..1cb670edc60f 100644 --- a/tests/ui/needless_match.rs +++ b/tests/ui/needless_match.rs @@ -13,6 +13,7 @@ enum Simple { fn useless_match() { let i = 10; let _: i32 = match i { + //~^ needless_match 0 => 0, 1 => 1, 2 => 2, @@ -20,6 +21,7 @@ fn useless_match() { }; let s = "test"; let _: &str = match s { + //~^ needless_match "a" => "a", "b" => "b", s => s, @@ -29,6 +31,7 @@ fn useless_match() { fn custom_type_match() { let se = Simple::A; let _: Simple = match se { + //~^ needless_match Simple::A => Simple::A, Simple::B => Simple::B, Simple::C => Simple::C, @@ -51,6 +54,7 @@ fn custom_type_match() { fn option_match(x: Option) { let _: Option = match x { + //~^ needless_match Some(a) => Some(a), None => None, }; @@ -67,10 +71,12 @@ fn func_ret_err(err: T) -> Result { fn result_match() { let _: Result = match Ok(1) { + //~^ needless_match Ok(a) => Ok(a), Err(err) => Err(err), }; let _: Result = match func_ret_err(0_i32) { + //~^ needless_match Err(err) => Err(err), Ok(a) => Ok(a), }; @@ -84,6 +90,7 @@ fn result_match() { fn if_let_option() { let _ = if let Some(a) = Some(1) { Some(a) } else { None }; + //~^ needless_match fn do_something() {} @@ -119,7 +126,9 @@ fn if_let_option_result() -> Result<(), ()> { fn if_let_result() { let x: Result = Ok(1); let _: Result = if let Err(e) = x { Err(e) } else { x }; + //~^ needless_match let _: Result = if let Ok(val) = x { Ok(val) } else { x }; + //~^ needless_match // Input type mismatch, don't trigger #[allow(clippy::question_mark)] let _: Result = if let Err(e) = Ok(1) { Err(e) } else { x }; @@ -127,6 +136,7 @@ fn if_let_result() { fn if_let_custom_enum(x: Simple) { let _: Simple = if let Simple::A = x { + //~^ needless_match Simple::A } else if let Simple::B = x { Simple::B @@ -166,6 +176,7 @@ mod issue8542 { let bb = false; let _: Complex = match ce { + //~^ needless_match Complex::A(a) => Complex::A(a), Complex::B(a, b) => Complex::B(a, b), Complex::C(a, b, c) => Complex::C(a, b, c), @@ -250,12 +261,14 @@ mod issue9084 { // should lint let _ = match e { + //~^ needless_match _ if some_bool => e, _ => e, }; // should lint let _ = match e { + //~^ needless_match Some(i) => Some(i), _ if some_bool => e, _ => e, @@ -337,6 +350,7 @@ pub fn issue13574() -> Option<()> { // Same const, should lint let _ = { if let Some(num) = A { + //~^ needless_match Some(num) } else if let Some(num) = A { Some(num) diff --git a/tests/ui/needless_match.stderr b/tests/ui/needless_match.stderr index 1410585cb2e3..719b0ef88469 100644 --- a/tests/ui/needless_match.stderr +++ b/tests/ui/needless_match.stderr @@ -3,6 +3,7 @@ error: this match expression is unnecessary | LL | let _: i32 = match i { | __________________^ +LL | | LL | | 0 => 0, LL | | 1 => 1, LL | | 2 => 2, @@ -14,10 +15,11 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::needless_match)]` error: this match expression is unnecessary - --> tests/ui/needless_match.rs:22:19 + --> tests/ui/needless_match.rs:23:19 | LL | let _: &str = match s { | ___________________^ +LL | | LL | | "a" => "a", LL | | "b" => "b", LL | | s => s, @@ -25,10 +27,11 @@ LL | | }; | |_____^ help: replace it with: `s` error: this match expression is unnecessary - --> tests/ui/needless_match.rs:31:21 + --> tests/ui/needless_match.rs:33:21 | LL | let _: Simple = match se { | _____________________^ +LL | | LL | | Simple::A => Simple::A, LL | | Simple::B => Simple::B, LL | | Simple::C => Simple::C, @@ -37,94 +40,99 @@ LL | | }; | |_____^ help: replace it with: `se` error: this match expression is unnecessary - --> tests/ui/needless_match.rs:53:26 + --> tests/ui/needless_match.rs:56:26 | LL | let _: Option = match x { | __________________________^ +LL | | LL | | Some(a) => Some(a), LL | | None => None, LL | | }; | |_____^ help: replace it with: `x` error: this match expression is unnecessary - --> tests/ui/needless_match.rs:69:31 + --> tests/ui/needless_match.rs:73:31 | LL | let _: Result = match Ok(1) { | _______________________________^ +LL | | LL | | Ok(a) => Ok(a), LL | | Err(err) => Err(err), LL | | }; | |_____^ help: replace it with: `Ok(1)` error: this match expression is unnecessary - --> tests/ui/needless_match.rs:73:31 + --> tests/ui/needless_match.rs:78:31 | LL | let _: Result = match func_ret_err(0_i32) { | _______________________________^ +LL | | LL | | Err(err) => Err(err), LL | | Ok(a) => Ok(a), LL | | }; | |_____^ help: replace it with: `func_ret_err(0_i32)` error: this if-let expression is unnecessary - --> tests/ui/needless_match.rs:86:13 + --> tests/ui/needless_match.rs:92:13 | LL | let _ = if let Some(a) = Some(1) { Some(a) } else { None }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `Some(1)` error: this if-let expression is unnecessary - --> tests/ui/needless_match.rs:121:31 + --> tests/ui/needless_match.rs:128:31 | LL | let _: Result = if let Err(e) = x { Err(e) } else { x }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x` error: this if-let expression is unnecessary - --> tests/ui/needless_match.rs:122:31 + --> tests/ui/needless_match.rs:130:31 | LL | let _: Result = if let Ok(val) = x { Ok(val) } else { x }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x` error: this if-let expression is unnecessary - --> tests/ui/needless_match.rs:129:21 + --> tests/ui/needless_match.rs:138:21 | LL | let _: Simple = if let Simple::A = x { | _____________________^ +LL | | LL | | Simple::A LL | | } else if let Simple::B = x { -LL | | Simple::B ... | LL | | x LL | | }; | |_____^ help: replace it with: `x` error: this match expression is unnecessary - --> tests/ui/needless_match.rs:168:26 + --> tests/ui/needless_match.rs:178:26 | LL | let _: Complex = match ce { | __________________________^ +LL | | LL | | Complex::A(a) => Complex::A(a), LL | | Complex::B(a, b) => Complex::B(a, b), -LL | | Complex::C(a, b, c) => Complex::C(a, b, c), -LL | | Complex::D(E::VariantA(ea, eb), b) => Complex::D(E::VariantA(ea, eb), b), +... | LL | | Complex::D(E::VariantB(ea, eb), b) => Complex::D(E::VariantB(ea, eb), b), LL | | }; | |_________^ help: replace it with: `ce` error: this match expression is unnecessary - --> tests/ui/needless_match.rs:252:17 + --> tests/ui/needless_match.rs:263:17 | LL | let _ = match e { | _________________^ +LL | | LL | | _ if some_bool => e, LL | | _ => e, LL | | }; | |_________^ help: replace it with: `e` error: this match expression is unnecessary - --> tests/ui/needless_match.rs:258:17 + --> tests/ui/needless_match.rs:270:17 | LL | let _ = match e { | _________________^ +LL | | LL | | Some(i) => Some(i), LL | | _ if some_bool => e, LL | | _ => e, @@ -132,12 +140,12 @@ LL | | }; | |_________^ help: replace it with: `e` error: this if-let expression is unnecessary - --> tests/ui/needless_match.rs:339:9 + --> tests/ui/needless_match.rs:352:9 | LL | / if let Some(num) = A { +LL | | LL | | Some(num) LL | | } else if let Some(num) = A { -LL | | Some(num) ... | LL | | None LL | | } diff --git a/tests/ui/needless_maybe_sized.fixed b/tests/ui/needless_maybe_sized.fixed index 4d24a7cee619..f8b164396990 100644 --- a/tests/ui/needless_maybe_sized.fixed +++ b/tests/ui/needless_maybe_sized.fixed @@ -7,27 +7,34 @@ extern crate proc_macros; use proc_macros::external; fn directly(t: &T) {} +//~^ needless_maybe_sized trait A: Sized {} trait B: A {} fn depth_1(t: &T) {} +//~^ needless_maybe_sized fn depth_2(t: &T) {} +//~^ needless_maybe_sized // We only need to show one fn multiple_paths(t: &T) {} +//~^ needless_maybe_sized fn in_where(t: &T) where T: Sized, + //~^ needless_maybe_sized { } fn mixed_1(t: &T) + //~^ needless_maybe_sized { } fn mixed_2(t: &T) +//~^ needless_maybe_sized where T: Sized, { @@ -36,38 +43,50 @@ where fn mixed_3(t: &T) where T: Sized, + //~^ needless_maybe_sized { } struct Struct(T); +//~^ needless_maybe_sized impl Struct { + //~^ needless_maybe_sized fn method(&self) {} + //~^ needless_maybe_sized } enum Enum { + //~^ needless_maybe_sized Variant(&'static T), } union Union<'a, T: Sized> { + //~^ needless_maybe_sized a: &'a T, } trait Trait { + //~^ needless_maybe_sized fn trait_method() {} + //~^ needless_maybe_sized type GAT; + //~^ needless_maybe_sized type Assoc: Sized + ?Sized; // False negative } trait SecondInTrait: Send + Sized {} fn second_in_trait() {} +//~^ needless_maybe_sized fn impl_trait(_: &(impl Sized)) {} +//~^ needless_maybe_sized trait GenericTrait: Sized {} fn in_generic_trait, U>() {} +//~^ needless_maybe_sized mod larger_graph { // C1 C2 Sized @@ -83,6 +102,7 @@ mod larger_graph { trait A1: B1 + B2 {} fn larger_graph() {} + //~^ needless_maybe_sized } // Should not lint diff --git a/tests/ui/needless_maybe_sized.rs b/tests/ui/needless_maybe_sized.rs index ef66f9a4f2ae..e4312b40563f 100644 --- a/tests/ui/needless_maybe_sized.rs +++ b/tests/ui/needless_maybe_sized.rs @@ -7,29 +7,36 @@ extern crate proc_macros; use proc_macros::external; fn directly(t: &T) {} +//~^ needless_maybe_sized trait A: Sized {} trait B: A {} fn depth_1(t: &T) {} +//~^ needless_maybe_sized fn depth_2(t: &T) {} +//~^ needless_maybe_sized // We only need to show one fn multiple_paths(t: &T) {} +//~^ needless_maybe_sized fn in_where(t: &T) where T: Sized + ?Sized, + //~^ needless_maybe_sized { } fn mixed_1(t: &T) where T: ?Sized, + //~^ needless_maybe_sized { } fn mixed_2(t: &T) +//~^ needless_maybe_sized where T: Sized, { @@ -39,38 +46,50 @@ fn mixed_3(t: &T) where T: Sized, T: ?Sized, + //~^ needless_maybe_sized { } struct Struct(T); +//~^ needless_maybe_sized impl Struct { + //~^ needless_maybe_sized fn method(&self) {} + //~^ needless_maybe_sized } enum Enum { + //~^ needless_maybe_sized Variant(&'static T), } union Union<'a, T: Sized + ?Sized> { + //~^ needless_maybe_sized a: &'a T, } trait Trait { + //~^ needless_maybe_sized fn trait_method() {} + //~^ needless_maybe_sized type GAT; + //~^ needless_maybe_sized type Assoc: Sized + ?Sized; // False negative } trait SecondInTrait: Send + Sized {} fn second_in_trait() {} +//~^ needless_maybe_sized fn impl_trait(_: &(impl Sized + ?Sized)) {} +//~^ needless_maybe_sized trait GenericTrait: Sized {} fn in_generic_trait + ?Sized, U>() {} +//~^ needless_maybe_sized mod larger_graph { // C1 C2 Sized @@ -86,6 +105,7 @@ mod larger_graph { trait A1: B1 + B2 {} fn larger_graph() {} + //~^ needless_maybe_sized } // Should not lint diff --git a/tests/ui/needless_maybe_sized.stderr b/tests/ui/needless_maybe_sized.stderr index 3b1d2b49b062..30dcaa48e429 100644 --- a/tests/ui/needless_maybe_sized.stderr +++ b/tests/ui/needless_maybe_sized.stderr @@ -18,13 +18,13 @@ LL + fn directly(t: &T) {} | error: `?Sized` bound is ignored because of a `Sized` requirement - --> tests/ui/needless_maybe_sized.rs:14:19 + --> tests/ui/needless_maybe_sized.rs:15:19 | LL | fn depth_1(t: &T) {} | ^^^^^^ | note: `T` cannot be unsized because of the bound - --> tests/ui/needless_maybe_sized.rs:14:15 + --> tests/ui/needless_maybe_sized.rs:15:15 | LL | fn depth_1(t: &T) {} | ^ @@ -36,13 +36,13 @@ LL + fn depth_1(t: &T) {} | error: `?Sized` bound is ignored because of a `Sized` requirement - --> tests/ui/needless_maybe_sized.rs:15:19 + --> tests/ui/needless_maybe_sized.rs:17:19 | LL | fn depth_2(t: &T) {} | ^^^^^^ | note: `T` cannot be unsized because of the bound - --> tests/ui/needless_maybe_sized.rs:15:15 + --> tests/ui/needless_maybe_sized.rs:17:15 | LL | fn depth_2(t: &T) {} | ^ @@ -55,13 +55,13 @@ LL + fn depth_2(t: &T) {} | error: `?Sized` bound is ignored because of a `Sized` requirement - --> tests/ui/needless_maybe_sized.rs:18:30 + --> tests/ui/needless_maybe_sized.rs:21:30 | LL | fn multiple_paths(t: &T) {} | ^^^^^^ | note: `T` cannot be unsized because of the bound - --> tests/ui/needless_maybe_sized.rs:18:22 + --> tests/ui/needless_maybe_sized.rs:21:22 | LL | fn multiple_paths(t: &T) {} | ^ @@ -73,13 +73,13 @@ LL + fn multiple_paths(t: &T) {} | error: `?Sized` bound is ignored because of a `Sized` requirement - --> tests/ui/needless_maybe_sized.rs:22:16 + --> tests/ui/needless_maybe_sized.rs:26:16 | LL | T: Sized + ?Sized, | ^^^^^^ | note: `T` cannot be unsized because of the bound - --> tests/ui/needless_maybe_sized.rs:22:8 + --> tests/ui/needless_maybe_sized.rs:26:8 | LL | T: Sized + ?Sized, | ^^^^^ @@ -90,13 +90,13 @@ LL + T: Sized, | error: `?Sized` bound is ignored because of a `Sized` requirement - --> tests/ui/needless_maybe_sized.rs:28:8 + --> tests/ui/needless_maybe_sized.rs:33:8 | LL | T: ?Sized, | ^^^^^^ | note: `T` cannot be unsized because of the bound - --> tests/ui/needless_maybe_sized.rs:26:15 + --> tests/ui/needless_maybe_sized.rs:31:15 | LL | fn mixed_1(t: &T) | ^^^^^ @@ -107,13 +107,13 @@ LL - T: ?Sized, | error: `?Sized` bound is ignored because of a `Sized` requirement - --> tests/ui/needless_maybe_sized.rs:32:15 + --> tests/ui/needless_maybe_sized.rs:38:15 | LL | fn mixed_2(t: &T) | ^^^^^^ | note: `T` cannot be unsized because of the bound - --> tests/ui/needless_maybe_sized.rs:34:8 + --> tests/ui/needless_maybe_sized.rs:41:8 | LL | T: Sized, | ^^^^^ @@ -124,13 +124,13 @@ LL + fn mixed_2(t: &T) | error: `?Sized` bound is ignored because of a `Sized` requirement - --> tests/ui/needless_maybe_sized.rs:41:8 + --> tests/ui/needless_maybe_sized.rs:48:8 | LL | T: ?Sized, | ^^^^^^ | note: `T` cannot be unsized because of the bound - --> tests/ui/needless_maybe_sized.rs:40:8 + --> tests/ui/needless_maybe_sized.rs:47:8 | LL | T: Sized, | ^^^^^ @@ -142,13 +142,13 @@ LL + T: Sized, | error: `?Sized` bound is ignored because of a `Sized` requirement - --> tests/ui/needless_maybe_sized.rs:45:26 + --> tests/ui/needless_maybe_sized.rs:53:26 | LL | struct Struct(T); | ^^^^^^ | note: `T` cannot be unsized because of the bound - --> tests/ui/needless_maybe_sized.rs:45:18 + --> tests/ui/needless_maybe_sized.rs:53:18 | LL | struct Struct(T); | ^^^^^ @@ -159,13 +159,13 @@ LL + struct Struct(T); | error: `?Sized` bound is ignored because of a `Sized` requirement - --> tests/ui/needless_maybe_sized.rs:47:17 + --> tests/ui/needless_maybe_sized.rs:56:17 | LL | impl Struct { | ^^^^^^ | note: `T` cannot be unsized because of the bound - --> tests/ui/needless_maybe_sized.rs:47:9 + --> tests/ui/needless_maybe_sized.rs:56:9 | LL | impl Struct { | ^^^^^ @@ -176,13 +176,13 @@ LL + impl Struct { | error: `?Sized` bound is ignored because of a `Sized` requirement - --> tests/ui/needless_maybe_sized.rs:48:26 + --> tests/ui/needless_maybe_sized.rs:58:26 | LL | fn method(&self) {} | ^^^^^^ | note: `U` cannot be unsized because of the bound - --> tests/ui/needless_maybe_sized.rs:48:18 + --> tests/ui/needless_maybe_sized.rs:58:18 | LL | fn method(&self) {} | ^^^^^ @@ -193,13 +193,13 @@ LL + fn method(&self) {} | error: `?Sized` bound is ignored because of a `Sized` requirement - --> tests/ui/needless_maybe_sized.rs:51:22 + --> tests/ui/needless_maybe_sized.rs:62:22 | LL | enum Enum { | ^^^^^^ | note: `T` cannot be unsized because of the bound - --> tests/ui/needless_maybe_sized.rs:51:14 + --> tests/ui/needless_maybe_sized.rs:62:14 | LL | enum Enum { | ^^^^^ @@ -210,13 +210,13 @@ LL + enum Enum { | error: `?Sized` bound is ignored because of a `Sized` requirement - --> tests/ui/needless_maybe_sized.rs:55:28 + --> tests/ui/needless_maybe_sized.rs:67:28 | LL | union Union<'a, T: Sized + ?Sized> { | ^^^^^^ | note: `T` cannot be unsized because of the bound - --> tests/ui/needless_maybe_sized.rs:55:20 + --> tests/ui/needless_maybe_sized.rs:67:20 | LL | union Union<'a, T: Sized + ?Sized> { | ^^^^^ @@ -227,13 +227,13 @@ LL + union Union<'a, T: Sized> { | error: `?Sized` bound is ignored because of a `Sized` requirement - --> tests/ui/needless_maybe_sized.rs:59:24 + --> tests/ui/needless_maybe_sized.rs:72:24 | LL | trait Trait { | ^^^^^^ | note: `T` cannot be unsized because of the bound - --> tests/ui/needless_maybe_sized.rs:59:16 + --> tests/ui/needless_maybe_sized.rs:72:16 | LL | trait Trait { | ^^^^^ @@ -244,13 +244,13 @@ LL + trait Trait { | error: `?Sized` bound is ignored because of a `Sized` requirement - --> tests/ui/needless_maybe_sized.rs:60:32 + --> tests/ui/needless_maybe_sized.rs:74:32 | LL | fn trait_method() {} | ^^^^^^ | note: `U` cannot be unsized because of the bound - --> tests/ui/needless_maybe_sized.rs:60:24 + --> tests/ui/needless_maybe_sized.rs:74:24 | LL | fn trait_method() {} | ^^^^^ @@ -261,13 +261,13 @@ LL + fn trait_method() {} | error: `?Sized` bound is ignored because of a `Sized` requirement - --> tests/ui/needless_maybe_sized.rs:62:25 + --> tests/ui/needless_maybe_sized.rs:77:25 | LL | type GAT; | ^^^^^^ | note: `U` cannot be unsized because of the bound - --> tests/ui/needless_maybe_sized.rs:62:17 + --> tests/ui/needless_maybe_sized.rs:77:17 | LL | type GAT; | ^^^^^ @@ -278,13 +278,13 @@ LL + type GAT; | error: `?Sized` bound is ignored because of a `Sized` requirement - --> tests/ui/needless_maybe_sized.rs:68:23 + --> tests/ui/needless_maybe_sized.rs:84:23 | LL | fn second_in_trait() {} | ^^^^^^ | note: `T` cannot be unsized because of the bound - --> tests/ui/needless_maybe_sized.rs:68:32 + --> tests/ui/needless_maybe_sized.rs:84:32 | LL | fn second_in_trait() {} | ^^^^^^^^^^^^^ @@ -296,13 +296,13 @@ LL + fn second_in_trait() {} | error: `?Sized` bound is ignored because of a `Sized` requirement - --> tests/ui/needless_maybe_sized.rs:70:33 + --> tests/ui/needless_maybe_sized.rs:87:33 | LL | fn impl_trait(_: &(impl Sized + ?Sized)) {} | ^^^^^^ | note: `impl Sized + ?Sized` cannot be unsized because of the bound - --> tests/ui/needless_maybe_sized.rs:70:25 + --> tests/ui/needless_maybe_sized.rs:87:25 | LL | fn impl_trait(_: &(impl Sized + ?Sized)) {} | ^^^^^ @@ -313,13 +313,13 @@ LL + fn impl_trait(_: &(impl Sized)) {} | error: `?Sized` bound is ignored because of a `Sized` requirement - --> tests/ui/needless_maybe_sized.rs:73:42 + --> tests/ui/needless_maybe_sized.rs:91:42 | LL | fn in_generic_trait + ?Sized, U>() {} | ^^^^^^ | note: `T` cannot be unsized because of the bound - --> tests/ui/needless_maybe_sized.rs:73:24 + --> tests/ui/needless_maybe_sized.rs:91:24 | LL | fn in_generic_trait + ?Sized, U>() {} | ^^^^^^^^^^^^^^^ @@ -331,13 +331,13 @@ LL + fn in_generic_trait, U>() {} | error: `?Sized` bound is ignored because of a `Sized` requirement - --> tests/ui/needless_maybe_sized.rs:88:29 + --> tests/ui/needless_maybe_sized.rs:107:29 | LL | fn larger_graph() {} | ^^^^^^ | note: `T` cannot be unsized because of the bound - --> tests/ui/needless_maybe_sized.rs:88:24 + --> tests/ui/needless_maybe_sized.rs:107:24 | LL | fn larger_graph() {} | ^^ diff --git a/tests/ui/needless_option_as_deref.fixed b/tests/ui/needless_option_as_deref.fixed index 84eaf12fc139..fd639f3b57fa 100644 --- a/tests/ui/needless_option_as_deref.fixed +++ b/tests/ui/needless_option_as_deref.fixed @@ -5,11 +5,14 @@ fn main() { // should lint let _: Option<&usize> = Some(&1); + //~^ needless_option_as_deref let _: Option<&mut usize> = Some(&mut 1); + //~^ needless_option_as_deref let mut y = 0; let mut x = Some(&mut y); let _ = x; + //~^ needless_option_as_deref // should not lint let _ = Some(Box::new(1)).as_deref(); @@ -70,3 +73,16 @@ mod issue_non_copy_13077 { pub field: (), } } + +mod issue14148 { + pub trait SomeTrait { + fn something(&self, mut maybe_side_effect: Option<&mut String>) { + other(maybe_side_effect.as_deref_mut()); + other(maybe_side_effect); + } + } + + fn other(_maybe_side_effect: Option<&mut String>) { + unimplemented!() + } +} diff --git a/tests/ui/needless_option_as_deref.rs b/tests/ui/needless_option_as_deref.rs index fff1e45d846f..cbf7935794b3 100644 --- a/tests/ui/needless_option_as_deref.rs +++ b/tests/ui/needless_option_as_deref.rs @@ -5,11 +5,14 @@ fn main() { // should lint let _: Option<&usize> = Some(&1).as_deref(); + //~^ needless_option_as_deref let _: Option<&mut usize> = Some(&mut 1).as_deref_mut(); + //~^ needless_option_as_deref let mut y = 0; let mut x = Some(&mut y); let _ = x.as_deref_mut(); + //~^ needless_option_as_deref // should not lint let _ = Some(Box::new(1)).as_deref(); @@ -70,3 +73,16 @@ mod issue_non_copy_13077 { pub field: (), } } + +mod issue14148 { + pub trait SomeTrait { + fn something(&self, mut maybe_side_effect: Option<&mut String>) { + other(maybe_side_effect.as_deref_mut()); + other(maybe_side_effect); + } + } + + fn other(_maybe_side_effect: Option<&mut String>) { + unimplemented!() + } +} diff --git a/tests/ui/needless_option_as_deref.stderr b/tests/ui/needless_option_as_deref.stderr index a05d0aa9276a..bd19dc75eed6 100644 --- a/tests/ui/needless_option_as_deref.stderr +++ b/tests/ui/needless_option_as_deref.stderr @@ -8,13 +8,13 @@ LL | let _: Option<&usize> = Some(&1).as_deref(); = help: to override `-D warnings` add `#[allow(clippy::needless_option_as_deref)]` error: derefed type is same as origin - --> tests/ui/needless_option_as_deref.rs:8:33 + --> tests/ui/needless_option_as_deref.rs:9:33 | LL | let _: Option<&mut usize> = Some(&mut 1).as_deref_mut(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(&mut 1)` error: derefed type is same as origin - --> tests/ui/needless_option_as_deref.rs:12:13 + --> tests/ui/needless_option_as_deref.rs:14:13 | LL | let _ = x.as_deref_mut(); | ^^^^^^^^^^^^^^^^ help: try: `x` diff --git a/tests/ui/needless_option_take.fixed b/tests/ui/needless_option_take.fixed index 6514b67ef7a7..a8bd50b79899 100644 --- a/tests/ui/needless_option_take.fixed +++ b/tests/ui/needless_option_take.fixed @@ -21,7 +21,7 @@ fn main() { let x = Some(3); x.as_ref(); - //~^ ERROR: called `Option::take()` on a temporary value + //~^ needless_option_take println!("Testing non erroneous option_take_on_temporary"); let mut x = Some(3); @@ -29,30 +29,31 @@ fn main() { let mut x = Some(3); let y = x.as_mut(); - //~^ ERROR: called `Option::take()` on a temporary value + //~^ needless_option_take + let y = x.replace(289); - //~^ ERROR: called `Option::take()` on a temporary value + //~^ needless_option_take let y = Some(3).as_mut(); - //~^ ERROR: called `Option::take()` on a temporary value + //~^ needless_option_take let y = Option::as_mut(&mut x); - //~^ ERROR: called `Option::take()` on a temporary value + //~^ needless_option_take let x = return_option(); let x = return_option(); - //~^ ERROR: called `Option::take()` on a temporary value + //~^ needless_option_take let x = MyStruct::get_option(); let x = MyStruct::get_option(); - //~^ ERROR: called `Option::take()` on a temporary value + //~^ needless_option_take let mut my_vec = vec![1, 2, 3]; my_vec.push(4); let y = my_vec.first(); let y = my_vec.first(); - //~^ ERROR: called `Option::take()` on a temporary value + //~^ needless_option_take let y = my_vec.first(); - //~^ ERROR: called `Option::take()` on a temporary value + //~^ needless_option_take } diff --git a/tests/ui/needless_option_take.rs b/tests/ui/needless_option_take.rs index c6807718a758..8141ee43db11 100644 --- a/tests/ui/needless_option_take.rs +++ b/tests/ui/needless_option_take.rs @@ -21,7 +21,7 @@ fn main() { let x = Some(3); x.as_ref().take(); - //~^ ERROR: called `Option::take()` on a temporary value + //~^ needless_option_take println!("Testing non erroneous option_take_on_temporary"); let mut x = Some(3); @@ -29,30 +29,31 @@ fn main() { let mut x = Some(3); let y = x.as_mut().take(); - //~^ ERROR: called `Option::take()` on a temporary value + //~^ needless_option_take + let y = x.replace(289).take(); - //~^ ERROR: called `Option::take()` on a temporary value + //~^ needless_option_take let y = Some(3).as_mut().take(); - //~^ ERROR: called `Option::take()` on a temporary value + //~^ needless_option_take let y = Option::as_mut(&mut x).take(); - //~^ ERROR: called `Option::take()` on a temporary value + //~^ needless_option_take let x = return_option(); let x = return_option().take(); - //~^ ERROR: called `Option::take()` on a temporary value + //~^ needless_option_take let x = MyStruct::get_option(); let x = MyStruct::get_option().take(); - //~^ ERROR: called `Option::take()` on a temporary value + //~^ needless_option_take let mut my_vec = vec![1, 2, 3]; my_vec.push(4); let y = my_vec.first(); let y = my_vec.first().take(); - //~^ ERROR: called `Option::take()` on a temporary value + //~^ needless_option_take let y = my_vec.first().take(); - //~^ ERROR: called `Option::take()` on a temporary value + //~^ needless_option_take } diff --git a/tests/ui/needless_option_take.stderr b/tests/ui/needless_option_take.stderr index 3fc339ed79e2..9054463c07cd 100644 --- a/tests/ui/needless_option_take.stderr +++ b/tests/ui/needless_option_take.stderr @@ -21,7 +21,7 @@ LL | let y = x.as_mut().take(); = note: `as_mut` creates a temporary value, so calling take() has no effect error: called `Option::take()` on a temporary value - --> tests/ui/needless_option_take.rs:33:13 + --> tests/ui/needless_option_take.rs:34:13 | LL | let y = x.replace(289).take(); | ^^^^^^^^^^^^^^------- @@ -31,7 +31,7 @@ LL | let y = x.replace(289).take(); = note: `replace` creates a temporary value, so calling take() has no effect error: called `Option::take()` on a temporary value - --> tests/ui/needless_option_take.rs:36:13 + --> tests/ui/needless_option_take.rs:37:13 | LL | let y = Some(3).as_mut().take(); | ^^^^^^^^^^^^^^^^------- @@ -41,7 +41,7 @@ LL | let y = Some(3).as_mut().take(); = note: `as_mut` creates a temporary value, so calling take() has no effect error: called `Option::take()` on a temporary value - --> tests/ui/needless_option_take.rs:39:13 + --> tests/ui/needless_option_take.rs:40:13 | LL | let y = Option::as_mut(&mut x).take(); | ^^^^^^^^^^^^^^^^^^^^^^------- @@ -51,7 +51,7 @@ LL | let y = Option::as_mut(&mut x).take(); = note: `as_mut` creates a temporary value, so calling take() has no effect error: called `Option::take()` on a temporary value - --> tests/ui/needless_option_take.rs:43:13 + --> tests/ui/needless_option_take.rs:44:13 | LL | let x = return_option().take(); | ^^^^^^^^^^^^^^^------- @@ -61,7 +61,7 @@ LL | let x = return_option().take(); = note: `return_option` creates a temporary value, so calling take() has no effect error: called `Option::take()` on a temporary value - --> tests/ui/needless_option_take.rs:47:13 + --> tests/ui/needless_option_take.rs:48:13 | LL | let x = MyStruct::get_option().take(); | ^^^^^^^^^^^^^^^^^^^^^^------- @@ -71,7 +71,7 @@ LL | let x = MyStruct::get_option().take(); = note: `get_option` creates a temporary value, so calling take() has no effect error: called `Option::take()` on a temporary value - --> tests/ui/needless_option_take.rs:53:13 + --> tests/ui/needless_option_take.rs:54:13 | LL | let y = my_vec.first().take(); | ^^^^^^^^^^^^^^------- @@ -81,7 +81,7 @@ LL | let y = my_vec.first().take(); = note: `first` creates a temporary value, so calling take() has no effect error: called `Option::take()` on a temporary value - --> tests/ui/needless_option_take.rs:56:13 + --> tests/ui/needless_option_take.rs:57:13 | LL | let y = my_vec.first().take(); | ^^^^^^^^^^^^^^------- diff --git a/tests/ui/needless_parens_on_range_literals.fixed b/tests/ui/needless_parens_on_range_literals.fixed index b4d9e3297c49..7abcbc0c6e32 100644 --- a/tests/ui/needless_parens_on_range_literals.fixed +++ b/tests/ui/needless_parens_on_range_literals.fixed @@ -5,9 +5,15 @@ fn main() { let _ = 'a'..='z'; + //~^ needless_parens_on_range_literals + //~| needless_parens_on_range_literals let _ = 'a'..'z'; + //~^ needless_parens_on_range_literals let _ = (1.)..2.; let _ = (1.)..2.; + //~^ needless_parens_on_range_literals let _ = 'a'..; + //~^ needless_parens_on_range_literals let _ = ..'z'; + //~^ needless_parens_on_range_literals } diff --git a/tests/ui/needless_parens_on_range_literals.rs b/tests/ui/needless_parens_on_range_literals.rs index 2f0e54f80d85..2a6f9305883b 100644 --- a/tests/ui/needless_parens_on_range_literals.rs +++ b/tests/ui/needless_parens_on_range_literals.rs @@ -5,9 +5,15 @@ fn main() { let _ = ('a')..=('z'); + //~^ needless_parens_on_range_literals + //~| needless_parens_on_range_literals let _ = 'a'..('z'); + //~^ needless_parens_on_range_literals let _ = (1.)..2.; let _ = (1.)..(2.); + //~^ needless_parens_on_range_literals let _ = ('a')..; + //~^ needless_parens_on_range_literals let _ = ..('z'); + //~^ needless_parens_on_range_literals } diff --git a/tests/ui/needless_parens_on_range_literals.stderr b/tests/ui/needless_parens_on_range_literals.stderr index d293ecce69fb..082b2cd8cade 100644 --- a/tests/ui/needless_parens_on_range_literals.stderr +++ b/tests/ui/needless_parens_on_range_literals.stderr @@ -14,25 +14,25 @@ LL | let _ = ('a')..=('z'); | ^^^^^ help: try: `'z'` error: needless parenthesis on range literals can be removed - --> tests/ui/needless_parens_on_range_literals.rs:8:18 + --> tests/ui/needless_parens_on_range_literals.rs:10:18 | LL | let _ = 'a'..('z'); | ^^^^^ help: try: `'z'` error: needless parenthesis on range literals can be removed - --> tests/ui/needless_parens_on_range_literals.rs:10:19 + --> tests/ui/needless_parens_on_range_literals.rs:13:19 | LL | let _ = (1.)..(2.); | ^^^^ help: try: `2.` error: needless parenthesis on range literals can be removed - --> tests/ui/needless_parens_on_range_literals.rs:11:13 + --> tests/ui/needless_parens_on_range_literals.rs:15:13 | LL | let _ = ('a')..; | ^^^^^ help: try: `'a'` error: needless parenthesis on range literals can be removed - --> tests/ui/needless_parens_on_range_literals.rs:12:15 + --> tests/ui/needless_parens_on_range_literals.rs:17:15 | LL | let _ = ..('z'); | ^^^^^ help: try: `'z'` diff --git a/tests/ui/needless_pass_by_ref_mut.rs b/tests/ui/needless_pass_by_ref_mut.rs index 162ec82aeded..f0c5a716ac99 100644 --- a/tests/ui/needless_pass_by_ref_mut.rs +++ b/tests/ui/needless_pass_by_ref_mut.rs @@ -9,7 +9,8 @@ use std::ptr::NonNull; fn foo(s: &mut Vec, b: &u32, x: &mut u32) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ needless_pass_by_ref_mut + *x += *b + s.len() as u32; } @@ -34,7 +35,8 @@ fn foo5(s: &mut Vec) { } fn foo6(s: &mut Vec) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ needless_pass_by_ref_mut + non_mut_ref(s); } @@ -44,10 +46,11 @@ struct Bar; impl Bar { fn bar(&mut self) {} - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ needless_pass_by_ref_mut fn mushroom(&self, vec: &mut Vec) -> usize { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ needless_pass_by_ref_mut + vec.len() } } @@ -124,35 +127,44 @@ async fn f7(x: &mut i32, y: i32, z: &mut i32, a: i32) { } async fn a1(x: &mut i32) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ needless_pass_by_ref_mut + println!("{:?}", x); } async fn a2(x: &mut i32, y: String) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ needless_pass_by_ref_mut + println!("{:?}", x); } async fn a3(x: &mut i32, y: String, z: String) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ needless_pass_by_ref_mut + println!("{:?}", x); } async fn a4(x: &mut i32, y: i32) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ needless_pass_by_ref_mut + println!("{:?}", x); } async fn a5(x: i32, y: &mut i32) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ needless_pass_by_ref_mut + println!("{:?}", x); } async fn a6(x: i32, y: &mut i32) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ needless_pass_by_ref_mut + println!("{:?}", x); } async fn a7(x: i32, y: i32, z: &mut i32) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ needless_pass_by_ref_mut + println!("{:?}", z); } async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ needless_pass_by_ref_mut + //~| needless_pass_by_ref_mut + println!("{:?}", z); } @@ -186,14 +198,12 @@ fn lint_attr(s: &mut u32) {} #[cfg(not(feature = "a"))] fn cfg_warn(s: &mut u32) {} -//~^ ERROR: this argument is a mutable reference, but not used mutably -//~| NOTE: this is cfg-gated and may require further changes +//~^ needless_pass_by_ref_mut #[cfg(not(feature = "a"))] mod foo { fn cfg_warn(s: &mut u32) {} - //~^ ERROR: this argument is a mutable reference, but not used mutably - //~| NOTE: this is cfg-gated and may require further changes + //~^ needless_pass_by_ref_mut } // Should not warn. @@ -206,7 +216,8 @@ async fn inner_async(x: &mut i32, y: &mut u32) { } async fn inner_async2(x: &mut i32, y: &mut u32) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ needless_pass_by_ref_mut + async { *x += 1; } @@ -214,7 +225,8 @@ async fn inner_async2(x: &mut i32, y: &mut u32) { } async fn inner_async3(x: &mut i32, y: &mut u32) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ needless_pass_by_ref_mut + async { *y += 1; } @@ -233,6 +245,7 @@ async fn async_vec2(b: &mut Vec) { fn non_mut(n: &str) {} //Should warn async fn call_in_closure1(n: &mut str) { + //~^ needless_pass_by_ref_mut (|| non_mut(n))() } fn str_mut(str: &mut String) -> bool { @@ -252,7 +265,8 @@ async fn closure(n: &mut usize) -> impl '_ + FnMut() { // Should warn. fn closure2(n: &mut usize) -> impl '_ + FnMut() -> usize { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ needless_pass_by_ref_mut + || *n + 1 } @@ -263,7 +277,8 @@ async fn closure3(n: &mut usize) { // Should warn. async fn closure4(n: &mut usize) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ needless_pass_by_ref_mut + (|| { let _x = *n + 1; })(); @@ -317,17 +332,20 @@ struct MutSelf { impl MutSelf { fn bar(&mut self) {} - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ needless_pass_by_ref_mut + async fn foo(&mut self, u: &mut i32, v: &mut u32) { - //~^ ERROR: this argument is a mutable reference, but not used mutably - //~| ERROR: this argument is a mutable reference, but not used mutably + //~^ needless_pass_by_ref_mut + //~| needless_pass_by_ref_mut + async { *u += 1; } .await; } async fn foo2(&mut self, u: &mut i32, v: &mut u32) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ needless_pass_by_ref_mut + async { self.a += 1; *u += 1; @@ -343,16 +361,26 @@ impl MutSelfTrait for MutSelf { // `is_from_proc_macro` stress tests fn _empty_tup(x: &mut (())) {} +//~^ needless_pass_by_ref_mut fn _single_tup(x: &mut ((i32,))) {} +//~^ needless_pass_by_ref_mut fn _multi_tup(x: &mut ((i32, u32))) {} +//~^ needless_pass_by_ref_mut fn _fn(x: &mut (fn())) {} +//~^ needless_pass_by_ref_mut #[rustfmt::skip] fn _extern_rust_fn(x: &mut extern "Rust" fn()) {} +//~^ needless_pass_by_ref_mut fn _extern_c_fn(x: &mut extern "C" fn()) {} +//~^ needless_pass_by_ref_mut fn _unsafe_fn(x: &mut unsafe fn()) {} +//~^ needless_pass_by_ref_mut fn _unsafe_extern_fn(x: &mut unsafe extern "C" fn()) {} +//~^ needless_pass_by_ref_mut fn _fn_with_arg(x: &mut unsafe extern "C" fn(i32)) {} +//~^ needless_pass_by_ref_mut fn _fn_with_ret(x: &mut unsafe extern "C" fn() -> (i32)) {} +//~^ needless_pass_by_ref_mut fn main() { let mut u = 0; diff --git a/tests/ui/needless_pass_by_ref_mut.stderr b/tests/ui/needless_pass_by_ref_mut.stderr index f462fa9099ed..6637a255b5f5 100644 --- a/tests/ui/needless_pass_by_ref_mut.stderr +++ b/tests/ui/needless_pass_by_ref_mut.stderr @@ -8,79 +8,79 @@ LL | fn foo(s: &mut Vec, b: &u32, x: &mut u32) { = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:36:12 + --> tests/ui/needless_pass_by_ref_mut.rs:37:12 | LL | fn foo6(s: &mut Vec) { | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:46:12 + --> tests/ui/needless_pass_by_ref_mut.rs:48:12 | LL | fn bar(&mut self) {} | ^^^^^^^^^ help: consider changing to: `&self` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:49:29 + --> tests/ui/needless_pass_by_ref_mut.rs:51:29 | LL | fn mushroom(&self, vec: &mut Vec) -> usize { | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:126:16 + --> tests/ui/needless_pass_by_ref_mut.rs:129:16 | LL | async fn a1(x: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:130:16 + --> tests/ui/needless_pass_by_ref_mut.rs:134:16 | LL | async fn a2(x: &mut i32, y: String) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:134:16 + --> tests/ui/needless_pass_by_ref_mut.rs:139:16 | LL | async fn a3(x: &mut i32, y: String, z: String) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:138:16 + --> tests/ui/needless_pass_by_ref_mut.rs:144:16 | LL | async fn a4(x: &mut i32, y: i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:142:24 + --> tests/ui/needless_pass_by_ref_mut.rs:149:24 | LL | async fn a5(x: i32, y: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:146:24 + --> tests/ui/needless_pass_by_ref_mut.rs:154:24 | LL | async fn a6(x: i32, y: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:150:32 + --> tests/ui/needless_pass_by_ref_mut.rs:159:32 | LL | async fn a7(x: i32, y: i32, z: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:154:24 + --> tests/ui/needless_pass_by_ref_mut.rs:164:24 | LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:154:45 + --> tests/ui/needless_pass_by_ref_mut.rs:164:45 | LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:188:16 + --> tests/ui/needless_pass_by_ref_mut.rs:200:16 | LL | fn cfg_warn(s: &mut u32) {} | ^^^^^^^^ help: consider changing to: `&u32` @@ -88,7 +88,7 @@ LL | fn cfg_warn(s: &mut u32) {} = note: this is cfg-gated and may require further changes error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:194:20 + --> tests/ui/needless_pass_by_ref_mut.rs:205:20 | LL | fn cfg_warn(s: &mut u32) {} | ^^^^^^^^ help: consider changing to: `&u32` @@ -96,115 +96,115 @@ LL | fn cfg_warn(s: &mut u32) {} = note: this is cfg-gated and may require further changes error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:208:39 + --> tests/ui/needless_pass_by_ref_mut.rs:218:39 | LL | async fn inner_async2(x: &mut i32, y: &mut u32) { | ^^^^^^^^ help: consider changing to: `&u32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:216:26 + --> tests/ui/needless_pass_by_ref_mut.rs:227:26 | LL | async fn inner_async3(x: &mut i32, y: &mut u32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:235:30 + --> tests/ui/needless_pass_by_ref_mut.rs:247:30 | LL | async fn call_in_closure1(n: &mut str) { | ^^^^^^^^ help: consider changing to: `&str` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:254:16 + --> tests/ui/needless_pass_by_ref_mut.rs:267:16 | LL | fn closure2(n: &mut usize) -> impl '_ + FnMut() -> usize { | ^^^^^^^^^^ help: consider changing to: `&usize` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:265:22 + --> tests/ui/needless_pass_by_ref_mut.rs:279:22 | LL | async fn closure4(n: &mut usize) { | ^^^^^^^^^^ help: consider changing to: `&usize` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:319:12 + --> tests/ui/needless_pass_by_ref_mut.rs:334:12 | LL | fn bar(&mut self) {} | ^^^^^^^^^ help: consider changing to: `&self` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:321:18 + --> tests/ui/needless_pass_by_ref_mut.rs:337:18 | LL | async fn foo(&mut self, u: &mut i32, v: &mut u32) { | ^^^^^^^^^ help: consider changing to: `&self` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:321:45 + --> tests/ui/needless_pass_by_ref_mut.rs:337:45 | LL | async fn foo(&mut self, u: &mut i32, v: &mut u32) { | ^^^^^^^^ help: consider changing to: `&u32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:329:46 + --> tests/ui/needless_pass_by_ref_mut.rs:346:46 | LL | async fn foo2(&mut self, u: &mut i32, v: &mut u32) { | ^^^^^^^^ help: consider changing to: `&u32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:345:18 + --> tests/ui/needless_pass_by_ref_mut.rs:363:18 | LL | fn _empty_tup(x: &mut (())) {} | ^^^^^^^^^ help: consider changing to: `&()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:346:19 + --> tests/ui/needless_pass_by_ref_mut.rs:365:19 | LL | fn _single_tup(x: &mut ((i32,))) {} | ^^^^^^^^^^^^^ help: consider changing to: `&(i32,)` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:347:18 + --> tests/ui/needless_pass_by_ref_mut.rs:367:18 | LL | fn _multi_tup(x: &mut ((i32, u32))) {} | ^^^^^^^^^^^^^^^^^ help: consider changing to: `&(i32, u32)` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:348:11 + --> tests/ui/needless_pass_by_ref_mut.rs:369:11 | LL | fn _fn(x: &mut (fn())) {} | ^^^^^^^^^^^ help: consider changing to: `&fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:350:23 + --> tests/ui/needless_pass_by_ref_mut.rs:372:23 | LL | fn _extern_rust_fn(x: &mut extern "Rust" fn()) {} | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&extern "Rust" fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:351:20 + --> tests/ui/needless_pass_by_ref_mut.rs:374:20 | LL | fn _extern_c_fn(x: &mut extern "C" fn()) {} | ^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&extern "C" fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:352:18 + --> tests/ui/needless_pass_by_ref_mut.rs:376:18 | LL | fn _unsafe_fn(x: &mut unsafe fn()) {} | ^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:353:25 + --> tests/ui/needless_pass_by_ref_mut.rs:378:25 | LL | fn _unsafe_extern_fn(x: &mut unsafe extern "C" fn()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:354:20 + --> tests/ui/needless_pass_by_ref_mut.rs:380:20 | LL | fn _fn_with_arg(x: &mut unsafe extern "C" fn(i32)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn(i32)` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:355:20 + --> tests/ui/needless_pass_by_ref_mut.rs:382:20 | LL | fn _fn_with_ret(x: &mut unsafe extern "C" fn() -> (i32)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn() -> (i32)` diff --git a/tests/ui/needless_pass_by_ref_mut2.fixed b/tests/ui/needless_pass_by_ref_mut2.fixed index f26b39ea6a16..0e2ac0202364 100644 --- a/tests/ui/needless_pass_by_ref_mut2.fixed +++ b/tests/ui/needless_pass_by_ref_mut2.fixed @@ -6,7 +6,8 @@ #![warn(clippy::needless_pass_by_ref_mut)] async fn inner_async3(x: &i32, y: &mut u32) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ needless_pass_by_ref_mut + async { *y += 1; } @@ -14,7 +15,8 @@ async fn inner_async3(x: &i32, y: &mut u32) { } async fn inner_async4(u: &mut i32, v: &u32) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ needless_pass_by_ref_mut + async { *u += 1; } diff --git a/tests/ui/needless_pass_by_ref_mut2.rs b/tests/ui/needless_pass_by_ref_mut2.rs index 4220215b1fe9..9201d9a27298 100644 --- a/tests/ui/needless_pass_by_ref_mut2.rs +++ b/tests/ui/needless_pass_by_ref_mut2.rs @@ -6,7 +6,8 @@ #![warn(clippy::needless_pass_by_ref_mut)] async fn inner_async3(x: &mut i32, y: &mut u32) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ needless_pass_by_ref_mut + async { *y += 1; } @@ -14,7 +15,8 @@ async fn inner_async3(x: &mut i32, y: &mut u32) { } async fn inner_async4(u: &mut i32, v: &mut u32) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ needless_pass_by_ref_mut + async { *u += 1; } diff --git a/tests/ui/needless_pass_by_ref_mut2.stderr b/tests/ui/needless_pass_by_ref_mut2.stderr index 1c0136cf5d59..9876a6b50718 100644 --- a/tests/ui/needless_pass_by_ref_mut2.stderr +++ b/tests/ui/needless_pass_by_ref_mut2.stderr @@ -8,7 +8,7 @@ LL | async fn inner_async3(x: &mut i32, y: &mut u32) { = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut2.rs:16:39 + --> tests/ui/needless_pass_by_ref_mut2.rs:17:39 | LL | async fn inner_async4(u: &mut i32, v: &mut u32) { | ^^^^^^^^ help: consider changing to: `&u32` diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index a8d9db95dcc7..885fb409417b 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -17,8 +17,8 @@ use std::mem::MaybeUninit; // `v` should be warned // `w`, `x` and `y` are allowed (moved or mutated) fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec { - //~^ ERROR: this argument is passed by value, but not consumed in the function body - //~| NOTE: `-D clippy::needless-pass-by-value` implied by `-D warnings` + //~^ needless_pass_by_value + assert_eq!(v.len(), 42); consume(w); @@ -33,15 +33,17 @@ fn consume(_: T) {} struct Wrapper(String); fn bar(x: String, y: Wrapper) { - //~^ ERROR: this argument is passed by value, but not consumed in the function body - //~| ERROR: this argument is passed by value, but not consumed in the function body + //~^ needless_pass_by_value + //~| needless_pass_by_value + assert_eq!(x.len(), 42); assert_eq!(y.0.len(), 42); } // V implements `Borrow`, but should be warned correctly fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: V) { - //~^ ERROR: this argument is passed by value, but not consumed in the function body + //~^ needless_pass_by_value + println!("{}", t.borrow()); println!("{}", u.as_ref()); consume(&v); @@ -54,7 +56,8 @@ fn test_fn i32>(f: F) { // x should be warned, but y is ok fn test_match(x: Option>, y: Option>) { - //~^ ERROR: this argument is passed by value, but not consumed in the function body + //~^ needless_pass_by_value + match x { Some(Some(_)) => 1, // not moved _ => 0, @@ -68,8 +71,9 @@ fn test_match(x: Option>, y: Option>) { // x and y should be warned, but z is ok fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { - //~^ ERROR: this argument is passed by value, but not consumed in the function body - //~| ERROR: this argument is passed by value, but not consumed in the function body + //~^ needless_pass_by_value + //~| needless_pass_by_value + let Wrapper(s) = z; // moved let Wrapper(ref t) = y; // not moved let Wrapper(_) = y; // still not moved @@ -86,13 +90,14 @@ impl<'a, T> Serialize for &'a T where T: Serialize {} impl Serialize for i32 {} fn test_blanket_ref(vals: T, serializable: S) {} -//~^ ERROR: this argument is passed by value, but not consumed in the function body +//~^ needless_pass_by_value fn issue_2114(s: String, t: String, u: Vec, v: Vec) { - //~^ ERROR: this argument is passed by value, but not consumed in the function body - //~| ERROR: this argument is passed by value, but not consumed in the function body - //~| ERROR: this argument is passed by value, but not consumed in the function body - //~| ERROR: this argument is passed by value, but not consumed in the function body + //~^ needless_pass_by_value + //~| needless_pass_by_value + //~| needless_pass_by_value + //~| needless_pass_by_value + s.capacity(); let _ = t.clone(); u.capacity(); @@ -106,9 +111,9 @@ impl S { self, // taking `self` by value is always allowed s: String, - //~^ ERROR: this argument is passed by value, but not consumed in the function bod + //~^ needless_pass_by_value t: String, - //~^ ERROR: this argument is passed by value, but not consumed in the function bod + //~^ needless_pass_by_value ) -> usize { s.len() + t.capacity() } @@ -118,8 +123,8 @@ impl S { } fn baz(&self, uu: U, ss: Self) {} - //~^ ERROR: this argument is passed by value, but not consumed in the function body - //~| ERROR: this argument is passed by value, but not consumed in the function body + //~^ needless_pass_by_value + //~| needless_pass_by_value } trait FalsePositive { @@ -142,16 +147,18 @@ fn range>(range: T) { struct CopyWrapper(u32); fn bar_copy(x: u32, y: CopyWrapper) { - //~^ ERROR: this argument is passed by value, but not consumed in the function body + //~^ needless_pass_by_value + assert_eq!(x, 42); assert_eq!(y.0, 42); } // x and y should be warned, but z is ok fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { - //~^ ERROR: this argument is passed by value, but not consumed in the function body - //~| ERROR: this argument is passed by value, but not consumed in the function body - //~| ERROR: this argument is passed by value, but not consumed in the function body + //~^ needless_pass_by_value + //~| needless_pass_by_value + //~| needless_pass_by_value + let CopyWrapper(s) = z; // moved let CopyWrapper(ref t) = y; // not moved let CopyWrapper(_) = y; // still not moved @@ -164,13 +171,13 @@ fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { trait Bar<'a, A> {} impl<'b, T> Bar<'b, T> for T {} fn some_fun<'b, S: Bar<'b, ()>>(items: S) {} -//~^ ERROR: this argument is passed by value, but not consumed in the function body +//~^ needless_pass_by_value // Also this should not cause an ICE. See #2831 trait Club<'a, A> {} impl Club<'static, T> for T {} fn more_fun(items: impl Club<'static, i32>) {} -//~^ ERROR: this argument is passed by value, but not consumed in the function body +//~^ needless_pass_by_value fn is_sync(_: T) where diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index 2c90da51252a..4ac4fdce972d 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -20,43 +20,43 @@ LL | fn bar(x: String, y: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body - --> tests/ui/needless_pass_by_value.rs:43:71 + --> tests/ui/needless_pass_by_value.rs:44:71 | LL | fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: V) { | ^ help: consider taking a reference instead: `&V` error: this argument is passed by value, but not consumed in the function body - --> tests/ui/needless_pass_by_value.rs:56:18 + --> tests/ui/needless_pass_by_value.rs:58:18 | LL | fn test_match(x: Option>, y: Option>) { | ^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&Option>` error: this argument is passed by value, but not consumed in the function body - --> tests/ui/needless_pass_by_value.rs:70:24 + --> tests/ui/needless_pass_by_value.rs:73:24 | LL | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body - --> tests/ui/needless_pass_by_value.rs:70:36 + --> tests/ui/needless_pass_by_value.rs:73:36 | LL | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` error: this argument is passed by value, but not consumed in the function body - --> tests/ui/needless_pass_by_value.rs:88:49 + --> tests/ui/needless_pass_by_value.rs:92:49 | LL | fn test_blanket_ref(vals: T, serializable: S) {} | ^ help: consider taking a reference instead: `&T` error: this argument is passed by value, but not consumed in the function body - --> tests/ui/needless_pass_by_value.rs:91:18 + --> tests/ui/needless_pass_by_value.rs:95:18 | LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body - --> tests/ui/needless_pass_by_value.rs:91:29 + --> tests/ui/needless_pass_by_value.rs:95:29 | LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ @@ -73,13 +73,13 @@ LL + let _ = t.to_string(); | error: this argument is passed by value, but not consumed in the function body - --> tests/ui/needless_pass_by_value.rs:91:40 + --> tests/ui/needless_pass_by_value.rs:95:40 | LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ help: consider taking a reference instead: `&Vec` error: this argument is passed by value, but not consumed in the function body - --> tests/ui/needless_pass_by_value.rs:91:53 + --> tests/ui/needless_pass_by_value.rs:95:53 | LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ @@ -96,85 +96,85 @@ LL + let _ = v.to_owned(); | error: this argument is passed by value, but not consumed in the function body - --> tests/ui/needless_pass_by_value.rs:108:12 + --> tests/ui/needless_pass_by_value.rs:113:12 | LL | s: String, | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body - --> tests/ui/needless_pass_by_value.rs:110:12 + --> tests/ui/needless_pass_by_value.rs:115:12 | LL | t: String, | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body - --> tests/ui/needless_pass_by_value.rs:120:23 + --> tests/ui/needless_pass_by_value.rs:125:23 | LL | fn baz(&self, uu: U, ss: Self) {} | ^ help: consider taking a reference instead: `&U` error: this argument is passed by value, but not consumed in the function body - --> tests/ui/needless_pass_by_value.rs:120:30 + --> tests/ui/needless_pass_by_value.rs:125:30 | LL | fn baz(&self, uu: U, ss: Self) {} | ^^^^ help: consider taking a reference instead: `&Self` error: this argument is passed by value, but not consumed in the function body - --> tests/ui/needless_pass_by_value.rs:144:24 + --> tests/ui/needless_pass_by_value.rs:149:24 | LL | fn bar_copy(x: u32, y: CopyWrapper) { | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` | help: or consider marking this type as `Copy` - --> tests/ui/needless_pass_by_value.rs:142:1 + --> tests/ui/needless_pass_by_value.rs:147:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> tests/ui/needless_pass_by_value.rs:151:29 + --> tests/ui/needless_pass_by_value.rs:157:29 | LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` | help: or consider marking this type as `Copy` - --> tests/ui/needless_pass_by_value.rs:142:1 + --> tests/ui/needless_pass_by_value.rs:147:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> tests/ui/needless_pass_by_value.rs:151:45 + --> tests/ui/needless_pass_by_value.rs:157:45 | LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` | help: or consider marking this type as `Copy` - --> tests/ui/needless_pass_by_value.rs:142:1 + --> tests/ui/needless_pass_by_value.rs:147:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> tests/ui/needless_pass_by_value.rs:151:61 + --> tests/ui/needless_pass_by_value.rs:157:61 | LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` | help: or consider marking this type as `Copy` - --> tests/ui/needless_pass_by_value.rs:142:1 + --> tests/ui/needless_pass_by_value.rs:147:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> tests/ui/needless_pass_by_value.rs:166:40 + --> tests/ui/needless_pass_by_value.rs:173:40 | LL | fn some_fun<'b, S: Bar<'b, ()>>(items: S) {} | ^ help: consider taking a reference instead: `&S` error: this argument is passed by value, but not consumed in the function body - --> tests/ui/needless_pass_by_value.rs:172:20 + --> tests/ui/needless_pass_by_value.rs:179:20 | LL | fn more_fun(items: impl Club<'static, i32>) {} | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&impl Club<'static, i32>` diff --git a/tests/ui/needless_pass_by_value_proc_macro.rs b/tests/ui/needless_pass_by_value_proc_macro.rs index c603163c145f..67516a962e75 100644 --- a/tests/ui/needless_pass_by_value_proc_macro.rs +++ b/tests/ui/needless_pass_by_value_proc_macro.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::needless_pass_by_value)] extern crate proc_macro; diff --git a/tests/ui/needless_pub_self.fixed b/tests/ui/needless_pub_self.fixed index d9f7b92d0901..7b4601ba8a37 100644 --- a/tests/ui/needless_pub_self.fixed +++ b/tests/ui/needless_pub_self.fixed @@ -11,13 +11,16 @@ extern crate proc_macros; fn a() {} +//~^ needless_pub_self fn b() {} +//~^ needless_pub_self pub fn c() {} mod a { pub(in super) fn d() {} pub(super) fn e() {} fn f() {} + //~^ needless_pub_self } external! { diff --git a/tests/ui/needless_pub_self.rs b/tests/ui/needless_pub_self.rs index 9f0ec76477e6..f64a56c37989 100644 --- a/tests/ui/needless_pub_self.rs +++ b/tests/ui/needless_pub_self.rs @@ -11,13 +11,16 @@ extern crate proc_macros; pub(self) fn a() {} +//~^ needless_pub_self pub(in self) fn b() {} +//~^ needless_pub_self pub fn c() {} mod a { pub(in super) fn d() {} pub(super) fn e() {} pub(self) fn f() {} + //~^ needless_pub_self } external! { diff --git a/tests/ui/needless_pub_self.stderr b/tests/ui/needless_pub_self.stderr index 1fdd84165659..c362d11804ec 100644 --- a/tests/ui/needless_pub_self.stderr +++ b/tests/ui/needless_pub_self.stderr @@ -9,7 +9,7 @@ LL | pub(self) fn a() {} = help: remove it error: unnecessary `pub(in self)` - --> tests/ui/needless_pub_self.rs:14:1 + --> tests/ui/needless_pub_self.rs:15:1 | LL | pub(in self) fn b() {} | ^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | pub(in self) fn b() {} = help: remove it error: unnecessary `pub(self)` - --> tests/ui/needless_pub_self.rs:20:5 + --> tests/ui/needless_pub_self.rs:22:5 | LL | pub(self) fn f() {} | ^^^^^^^^^ diff --git a/tests/ui/needless_question_mark.fixed b/tests/ui/needless_question_mark.fixed index 92f01c217c1c..375c38771eb6 100644 --- a/tests/ui/needless_question_mark.fixed +++ b/tests/ui/needless_question_mark.fixed @@ -18,6 +18,7 @@ struct TR { fn simple_option_bad1(to: TO) -> Option { // return as a statement return to.magic; + //~^ needless_question_mark } // formatting will add a semi-colon, which would make @@ -26,16 +27,19 @@ fn simple_option_bad1(to: TO) -> Option { fn simple_option_bad2(to: TO) -> Option { // return as an expression return to.magic + //~^ needless_question_mark } fn simple_option_bad3(to: TO) -> Option { // block value "return" to.magic + //~^ needless_question_mark } fn simple_option_bad4(to: Option) -> Option { // single line closure to.and_then(|t| t.magic) + //~^ needless_question_mark } // formatting this will remove the block brackets, making @@ -45,11 +49,13 @@ fn simple_option_bad5(to: Option) -> Option { // closure with body to.and_then(|t| { t.magic + //~^ needless_question_mark }) } fn simple_result_bad1(tr: TR) -> Result { return tr.magic; + //~^ needless_question_mark } // formatting will add a semi-colon, which would make @@ -57,14 +63,17 @@ fn simple_result_bad1(tr: TR) -> Result { #[rustfmt::skip] fn simple_result_bad2(tr: TR) -> Result { return tr.magic + //~^ needless_question_mark } fn simple_result_bad3(tr: TR) -> Result { tr.magic + //~^ needless_question_mark } fn simple_result_bad4(tr: Result) -> Result { tr.and_then(|t| t.magic) + //~^ needless_question_mark } // formatting this will remove the block brackets, making @@ -73,6 +82,7 @@ fn simple_result_bad4(tr: Result) -> Result { fn simple_result_bad5(tr: Result) -> Result { tr.and_then(|t| { t.magic + //~^ needless_question_mark }) } @@ -80,6 +90,7 @@ fn also_bad(tr: Result) -> Result { if tr.is_ok() { let t = tr.unwrap(); return t.magic; + //~^ needless_question_mark } Err(false) } @@ -115,6 +126,7 @@ pub fn test1() { macro_rules! some_and_qmark_in_macro { ($expr:expr) => { || -> Option<_> { Some($expr) }() + //~^ needless_question_mark }; } @@ -126,6 +138,7 @@ pub fn test2() { async fn async_option_bad(to: TO) -> Option { let _ = Some(3); to.magic + //~^ needless_question_mark } async fn async_deref_ref(s: Option<&String>) -> Option<&str> { @@ -134,8 +147,10 @@ async fn async_deref_ref(s: Option<&String>) -> Option<&str> { async fn async_result_bad(s: TR) -> Result { s.magic + //~^ needless_question_mark } async fn async_wrapped(a: Option) -> Option { { a } + //~^ needless_question_mark } diff --git a/tests/ui/needless_question_mark.rs b/tests/ui/needless_question_mark.rs index 21c858c291ff..5f6bd0c0f166 100644 --- a/tests/ui/needless_question_mark.rs +++ b/tests/ui/needless_question_mark.rs @@ -18,6 +18,7 @@ struct TR { fn simple_option_bad1(to: TO) -> Option { // return as a statement return Some(to.magic?); + //~^ needless_question_mark } // formatting will add a semi-colon, which would make @@ -26,16 +27,19 @@ fn simple_option_bad1(to: TO) -> Option { fn simple_option_bad2(to: TO) -> Option { // return as an expression return Some(to.magic?) + //~^ needless_question_mark } fn simple_option_bad3(to: TO) -> Option { // block value "return" Some(to.magic?) + //~^ needless_question_mark } fn simple_option_bad4(to: Option) -> Option { // single line closure to.and_then(|t| Some(t.magic?)) + //~^ needless_question_mark } // formatting this will remove the block brackets, making @@ -45,11 +49,13 @@ fn simple_option_bad5(to: Option) -> Option { // closure with body to.and_then(|t| { Some(t.magic?) + //~^ needless_question_mark }) } fn simple_result_bad1(tr: TR) -> Result { return Ok(tr.magic?); + //~^ needless_question_mark } // formatting will add a semi-colon, which would make @@ -57,14 +63,17 @@ fn simple_result_bad1(tr: TR) -> Result { #[rustfmt::skip] fn simple_result_bad2(tr: TR) -> Result { return Ok(tr.magic?) + //~^ needless_question_mark } fn simple_result_bad3(tr: TR) -> Result { Ok(tr.magic?) + //~^ needless_question_mark } fn simple_result_bad4(tr: Result) -> Result { tr.and_then(|t| Ok(t.magic?)) + //~^ needless_question_mark } // formatting this will remove the block brackets, making @@ -73,6 +82,7 @@ fn simple_result_bad4(tr: Result) -> Result { fn simple_result_bad5(tr: Result) -> Result { tr.and_then(|t| { Ok(t.magic?) + //~^ needless_question_mark }) } @@ -80,6 +90,7 @@ fn also_bad(tr: Result) -> Result { if tr.is_ok() { let t = tr.unwrap(); return Ok(t.magic?); + //~^ needless_question_mark } Err(false) } @@ -115,6 +126,7 @@ pub fn test1() { macro_rules! some_and_qmark_in_macro { ($expr:expr) => { || -> Option<_> { Some(Some($expr)?) }() + //~^ needless_question_mark }; } @@ -126,6 +138,7 @@ pub fn test2() { async fn async_option_bad(to: TO) -> Option { let _ = Some(3); Some(to.magic?) + //~^ needless_question_mark } async fn async_deref_ref(s: Option<&String>) -> Option<&str> { @@ -134,8 +147,10 @@ async fn async_deref_ref(s: Option<&String>) -> Option<&str> { async fn async_result_bad(s: TR) -> Result { Ok(s.magic?) + //~^ needless_question_mark } async fn async_wrapped(a: Option) -> Option { { Some(a?) } + //~^ needless_question_mark } diff --git a/tests/ui/needless_question_mark.stderr b/tests/ui/needless_question_mark.stderr index 0a1cb5979708..55da4f28976c 100644 --- a/tests/ui/needless_question_mark.stderr +++ b/tests/ui/needless_question_mark.stderr @@ -8,67 +8,67 @@ LL | return Some(to.magic?); = help: to override `-D warnings` add `#[allow(clippy::needless_question_mark)]` error: question mark operator is useless here - --> tests/ui/needless_question_mark.rs:28:12 + --> tests/ui/needless_question_mark.rs:29:12 | LL | return Some(to.magic?) | ^^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `to.magic` error: question mark operator is useless here - --> tests/ui/needless_question_mark.rs:33:5 + --> tests/ui/needless_question_mark.rs:35:5 | LL | Some(to.magic?) | ^^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `to.magic` error: question mark operator is useless here - --> tests/ui/needless_question_mark.rs:38:21 + --> tests/ui/needless_question_mark.rs:41:21 | LL | to.and_then(|t| Some(t.magic?)) | ^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `t.magic` error: question mark operator is useless here - --> tests/ui/needless_question_mark.rs:47:9 + --> tests/ui/needless_question_mark.rs:51:9 | LL | Some(t.magic?) | ^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `t.magic` error: question mark operator is useless here - --> tests/ui/needless_question_mark.rs:52:12 + --> tests/ui/needless_question_mark.rs:57:12 | LL | return Ok(tr.magic?); | ^^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `tr.magic` error: question mark operator is useless here - --> tests/ui/needless_question_mark.rs:59:12 + --> tests/ui/needless_question_mark.rs:65:12 | LL | return Ok(tr.magic?) | ^^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `tr.magic` error: question mark operator is useless here - --> tests/ui/needless_question_mark.rs:63:5 + --> tests/ui/needless_question_mark.rs:70:5 | LL | Ok(tr.magic?) | ^^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `tr.magic` error: question mark operator is useless here - --> tests/ui/needless_question_mark.rs:67:21 + --> tests/ui/needless_question_mark.rs:75:21 | LL | tr.and_then(|t| Ok(t.magic?)) | ^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `t.magic` error: question mark operator is useless here - --> tests/ui/needless_question_mark.rs:75:9 + --> tests/ui/needless_question_mark.rs:84:9 | LL | Ok(t.magic?) | ^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `t.magic` error: question mark operator is useless here - --> tests/ui/needless_question_mark.rs:82:16 + --> tests/ui/needless_question_mark.rs:92:16 | LL | return Ok(t.magic?); | ^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `t.magic` error: question mark operator is useless here - --> tests/ui/needless_question_mark.rs:117:27 + --> tests/ui/needless_question_mark.rs:128:27 | LL | || -> Option<_> { Some(Some($expr)?) }() | ^^^^^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `Some($expr)` @@ -79,19 +79,19 @@ LL | let _x = some_and_qmark_in_macro!(x?); = note: this error originates in the macro `some_and_qmark_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: question mark operator is useless here - --> tests/ui/needless_question_mark.rs:128:5 + --> tests/ui/needless_question_mark.rs:140:5 | LL | Some(to.magic?) | ^^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `to.magic` error: question mark operator is useless here - --> tests/ui/needless_question_mark.rs:136:5 + --> tests/ui/needless_question_mark.rs:149:5 | LL | Ok(s.magic?) | ^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `s.magic` error: question mark operator is useless here - --> tests/ui/needless_question_mark.rs:140:7 + --> tests/ui/needless_question_mark.rs:154:7 | LL | { Some(a?) } | ^^^^^^^^ help: try removing question mark and `Some()`: `a` diff --git a/tests/ui/needless_range_loop.rs b/tests/ui/needless_range_loop.rs index 75f1896eded1..8a1c1be289cf 100644 --- a/tests/ui/needless_range_loop.rs +++ b/tests/ui/needless_range_loop.rs @@ -14,8 +14,8 @@ fn main() { let mut vec = vec![1, 2, 3, 4]; let vec2 = vec![1, 2, 3, 4]; for i in 0..vec.len() { - //~^ ERROR: the loop variable `i` is only used to index `vec` - //~| NOTE: `-D clippy::needless-range-loop` implied by `-D warnings` + //~^ needless_range_loop + println!("{}", vec[i]); } @@ -25,23 +25,27 @@ fn main() { } for i in 0..vec.len() { - //~^ ERROR: the loop variable `i` is only used to index `vec` + //~^ needless_range_loop + let _ = vec[i]; } // ICE #746 for j in 0..4 { - //~^ ERROR: the loop variable `j` is only used to index `STATIC` + //~^ needless_range_loop + println!("{:?}", STATIC[j]); } for j in 0..4 { - //~^ ERROR: the loop variable `j` is only used to index `CONST` + //~^ needless_range_loop + println!("{:?}", CONST[j]); } for i in 0..vec.len() { - //~^ ERROR: the loop variable `i` is used to index `vec` + //~^ needless_range_loop + println!("{} {}", vec[i], i); } for i in 0..vec.len() { @@ -50,48 +54,57 @@ fn main() { } for i in 0..vec.len() { - //~^ ERROR: the loop variable `i` is only used to index `vec2` + //~^ needless_range_loop + println!("{}", vec2[i]); } for i in 5..vec.len() { - //~^ ERROR: the loop variable `i` is only used to index `vec` + //~^ needless_range_loop + println!("{}", vec[i]); } for i in 0..MAX_LEN { - //~^ ERROR: the loop variable `i` is only used to index `vec` + //~^ needless_range_loop + println!("{}", vec[i]); } for i in 0..=MAX_LEN { - //~^ ERROR: the loop variable `i` is only used to index `vec` + //~^ needless_range_loop + println!("{}", vec[i]); } for i in 5..10 { - //~^ ERROR: the loop variable `i` is only used to index `vec` + //~^ needless_range_loop + println!("{}", vec[i]); } for i in 5..=10 { - //~^ ERROR: the loop variable `i` is only used to index `vec` + //~^ needless_range_loop + println!("{}", vec[i]); } for i in 5..vec.len() { - //~^ ERROR: the loop variable `i` is used to index `vec` + //~^ needless_range_loop + println!("{} {}", vec[i], i); } for i in 5..10 { - //~^ ERROR: the loop variable `i` is used to index `vec` + //~^ needless_range_loop + println!("{} {}", vec[i], i); } // #2542 for i in 0..vec.len() { - //~^ ERROR: the loop variable `i` is used to index `vec` + //~^ needless_range_loop + vec[i] = Some(1).unwrap_or_else(|| panic!("error on {}", i)); } diff --git a/tests/ui/needless_range_loop.stderr b/tests/ui/needless_range_loop.stderr index 831b8511e434..23c085f9d3b2 100644 --- a/tests/ui/needless_range_loop.stderr +++ b/tests/ui/needless_range_loop.stderr @@ -25,7 +25,7 @@ LL + for in &vec { | error: the loop variable `j` is only used to index `STATIC` - --> tests/ui/needless_range_loop.rs:33:14 + --> tests/ui/needless_range_loop.rs:34:14 | LL | for j in 0..4 { | ^^^^ @@ -37,7 +37,7 @@ LL + for in &STATIC { | error: the loop variable `j` is only used to index `CONST` - --> tests/ui/needless_range_loop.rs:38:14 + --> tests/ui/needless_range_loop.rs:40:14 | LL | for j in 0..4 { | ^^^^ @@ -49,7 +49,7 @@ LL + for in &CONST { | error: the loop variable `i` is used to index `vec` - --> tests/ui/needless_range_loop.rs:43:14 + --> tests/ui/needless_range_loop.rs:46:14 | LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + for (i, ) in vec.iter().enumerate() { | error: the loop variable `i` is only used to index `vec2` - --> tests/ui/needless_range_loop.rs:52:14 + --> tests/ui/needless_range_loop.rs:56:14 | LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + for in vec2.iter().take(vec.len()) { | error: the loop variable `i` is only used to index `vec` - --> tests/ui/needless_range_loop.rs:57:14 + --> tests/ui/needless_range_loop.rs:62:14 | LL | for i in 5..vec.len() { | ^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + for in vec.iter().skip(5) { | error: the loop variable `i` is only used to index `vec` - --> tests/ui/needless_range_loop.rs:62:14 + --> tests/ui/needless_range_loop.rs:68:14 | LL | for i in 0..MAX_LEN { | ^^^^^^^^^^ @@ -97,7 +97,7 @@ LL + for in vec.iter().take(MAX_LEN) { | error: the loop variable `i` is only used to index `vec` - --> tests/ui/needless_range_loop.rs:67:14 + --> tests/ui/needless_range_loop.rs:74:14 | LL | for i in 0..=MAX_LEN { | ^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL + for in vec.iter().take(MAX_LEN + 1) { | error: the loop variable `i` is only used to index `vec` - --> tests/ui/needless_range_loop.rs:72:14 + --> tests/ui/needless_range_loop.rs:80:14 | LL | for i in 5..10 { | ^^^^^ @@ -121,7 +121,7 @@ LL + for in vec.iter().take(10).skip(5) { | error: the loop variable `i` is only used to index `vec` - --> tests/ui/needless_range_loop.rs:77:14 + --> tests/ui/needless_range_loop.rs:86:14 | LL | for i in 5..=10 { | ^^^^^^ @@ -133,7 +133,7 @@ LL + for in vec.iter().take(10 + 1).skip(5) { | error: the loop variable `i` is used to index `vec` - --> tests/ui/needless_range_loop.rs:82:14 + --> tests/ui/needless_range_loop.rs:92:14 | LL | for i in 5..vec.len() { | ^^^^^^^^^^^^ @@ -145,7 +145,7 @@ LL + for (i, ) in vec.iter().enumerate().skip(5) { | error: the loop variable `i` is used to index `vec` - --> tests/ui/needless_range_loop.rs:87:14 + --> tests/ui/needless_range_loop.rs:98:14 | LL | for i in 5..10 { | ^^^^^ @@ -157,7 +157,7 @@ LL + for (i, ) in vec.iter().enumerate().take(10).skip(5) { | error: the loop variable `i` is used to index `vec` - --> tests/ui/needless_range_loop.rs:93:14 + --> tests/ui/needless_range_loop.rs:105:14 | LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ diff --git a/tests/ui/needless_range_loop2.rs b/tests/ui/needless_range_loop2.rs index 787ff18f338d..68784a8df19d 100644 --- a/tests/ui/needless_range_loop2.rs +++ b/tests/ui/needless_range_loop2.rs @@ -9,8 +9,8 @@ fn main() { let ns = vec![2, 3, 5, 7]; for i in 3..10 { - //~^ ERROR: the loop variable `i` is only used to index `ns` - //~| NOTE: `-D clippy::needless-range-loop` implied by `-D warnings` + //~^ needless_range_loop + println!("{}", ns[i]); } @@ -32,14 +32,16 @@ fn main() { let mut ms = vec![1, 2, 3, 4, 5, 6]; for i in 0..ms.len() { - //~^ ERROR: the loop variable `i` is only used to index `ms` + //~^ needless_range_loop + ms[i] *= 2; } assert_eq!(ms, vec![2, 4, 6, 8, 10, 12]); let mut ms = vec![1, 2, 3, 4, 5, 6]; for i in 0..ms.len() { - //~^ ERROR: the loop variable `i` is only used to index `ms` + //~^ needless_range_loop + let x = &mut ms[i]; *x *= 2; } @@ -64,7 +66,8 @@ fn main() { let mut vec = vec![0; 9]; for i in x..x + 4 { - //~^ ERROR: the loop variable `i` is only used to index `vec` + //~^ needless_range_loop + vec[i] += 1; } @@ -72,24 +75,28 @@ fn main() { let mut vec = vec![0; 10]; for i in x..=x + 4 { - //~^ ERROR: the loop variable `i` is only used to index `vec` + //~^ needless_range_loop + vec[i] += 1; } let arr = [1, 2, 3]; for i in 0..3 { - //~^ ERROR: the loop variable `i` is only used to index `arr` + //~^ needless_range_loop + println!("{}", arr[i]); } for i in 0..2 { - //~^ ERROR: the loop variable `i` is only used to index `arr` + //~^ needless_range_loop + println!("{}", arr[i]); } for i in 1..3 { - //~^ ERROR: the loop variable `i` is only used to index `arr` + //~^ needless_range_loop + println!("{}", arr[i]); } diff --git a/tests/ui/needless_range_loop2.stderr b/tests/ui/needless_range_loop2.stderr index f37e1f2872d0..cb979b3f3c24 100644 --- a/tests/ui/needless_range_loop2.stderr +++ b/tests/ui/needless_range_loop2.stderr @@ -25,7 +25,7 @@ LL + for in &mut ms { | error: the loop variable `i` is only used to index `ms` - --> tests/ui/needless_range_loop2.rs:41:14 + --> tests/ui/needless_range_loop2.rs:42:14 | LL | for i in 0..ms.len() { | ^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + for in &mut ms { | error: the loop variable `i` is only used to index `vec` - --> tests/ui/needless_range_loop2.rs:66:14 + --> tests/ui/needless_range_loop2.rs:68:14 | LL | for i in x..x + 4 { | ^^^^^^^^ @@ -49,7 +49,7 @@ LL + for in vec.iter_mut().skip(x).take(4) { | error: the loop variable `i` is only used to index `vec` - --> tests/ui/needless_range_loop2.rs:74:14 + --> tests/ui/needless_range_loop2.rs:77:14 | LL | for i in x..=x + 4 { | ^^^^^^^^^ @@ -61,7 +61,7 @@ LL + for in vec.iter_mut().skip(x).take(4 + 1) { | error: the loop variable `i` is only used to index `arr` - --> tests/ui/needless_range_loop2.rs:81:14 + --> tests/ui/needless_range_loop2.rs:85:14 | LL | for i in 0..3 { | ^^^^ @@ -73,7 +73,7 @@ LL + for in &arr { | error: the loop variable `i` is only used to index `arr` - --> tests/ui/needless_range_loop2.rs:86:14 + --> tests/ui/needless_range_loop2.rs:91:14 | LL | for i in 0..2 { | ^^^^ @@ -85,7 +85,7 @@ LL + for in arr.iter().take(2) { | error: the loop variable `i` is only used to index `arr` - --> tests/ui/needless_range_loop2.rs:91:14 + --> tests/ui/needless_range_loop2.rs:97:14 | LL | for i in 1..3 { | ^^^^ diff --git a/tests/ui/needless_raw_string.fixed b/tests/ui/needless_raw_string.fixed index ab061467488a..88f9096db03c 100644 --- a/tests/ui/needless_raw_string.fixed +++ b/tests/ui/needless_raw_string.fixed @@ -3,31 +3,41 @@ fn main() { "aaa"; + //~^ needless_raw_strings r#""aaa""#; r#"\s"#; b"aaa"; + //~^ needless_raw_strings br#""aaa""#; br#"\s"#; c"aaa"; + //~^ needless_raw_strings cr#""aaa""#; cr#"\s"#; " + //~^ needless_raw_strings a multiline string "; "no hashes"; + //~^ needless_raw_strings b"no hashes"; + //~^ needless_raw_strings c"no hashes"; + //~^ needless_raw_strings } fn issue_13503() { println!("SELECT * FROM posts"); + //~^ needless_raw_strings println!("SELECT * FROM posts"); + //~^ needless_raw_strings println!(r##"SELECT * FROM "posts""##); // Test arguments as well println!("{}", "foobar".len()); + //~^ needless_raw_strings } diff --git a/tests/ui/needless_raw_string.rs b/tests/ui/needless_raw_string.rs index 5be8bdeb4ad0..6913b8b75546 100644 --- a/tests/ui/needless_raw_string.rs +++ b/tests/ui/needless_raw_string.rs @@ -3,31 +3,41 @@ fn main() { r#"aaa"#; + //~^ needless_raw_strings r#""aaa""#; r#"\s"#; br#"aaa"#; + //~^ needless_raw_strings br#""aaa""#; br#"\s"#; cr#"aaa"#; + //~^ needless_raw_strings cr#""aaa""#; cr#"\s"#; r#" + //~^ needless_raw_strings a multiline string "#; r"no hashes"; + //~^ needless_raw_strings br"no hashes"; + //~^ needless_raw_strings cr"no hashes"; + //~^ needless_raw_strings } fn issue_13503() { println!(r"SELECT * FROM posts"); + //~^ needless_raw_strings println!(r#"SELECT * FROM posts"#); + //~^ needless_raw_strings println!(r##"SELECT * FROM "posts""##); // Test arguments as well println!("{}", r"foobar".len()); + //~^ needless_raw_strings } diff --git a/tests/ui/needless_raw_string.stderr b/tests/ui/needless_raw_string.stderr index 5169f0855738..99c60b10b21b 100644 --- a/tests/ui/needless_raw_string.stderr +++ b/tests/ui/needless_raw_string.stderr @@ -13,7 +13,7 @@ LL + "aaa"; | error: unnecessary raw string literal - --> tests/ui/needless_raw_string.rs:8:5 + --> tests/ui/needless_raw_string.rs:9:5 | LL | br#"aaa"#; | ^^^^^^^^^ @@ -25,7 +25,7 @@ LL + b"aaa"; | error: unnecessary raw string literal - --> tests/ui/needless_raw_string.rs:11:5 + --> tests/ui/needless_raw_string.rs:13:5 | LL | cr#"aaa"#; | ^^^^^^^^^ @@ -37,9 +37,10 @@ LL + c"aaa"; | error: unnecessary raw string literal - --> tests/ui/needless_raw_string.rs:15:5 + --> tests/ui/needless_raw_string.rs:18:5 | LL | / r#" +LL | | LL | | a LL | | multiline LL | | string @@ -49,14 +50,14 @@ LL | | "#; help: use a plain string literal instead | LL ~ " -LL | a -LL | multiline +LL | +... LL | string LL ~ "; | error: unnecessary raw string literal - --> tests/ui/needless_raw_string.rs:21:5 + --> tests/ui/needless_raw_string.rs:25:5 | LL | r"no hashes"; | ^^^^^^^^^^^^ @@ -68,7 +69,7 @@ LL + "no hashes"; | error: unnecessary raw string literal - --> tests/ui/needless_raw_string.rs:22:5 + --> tests/ui/needless_raw_string.rs:27:5 | LL | br"no hashes"; | ^^^^^^^^^^^^^ @@ -80,7 +81,7 @@ LL + b"no hashes"; | error: unnecessary raw string literal - --> tests/ui/needless_raw_string.rs:23:5 + --> tests/ui/needless_raw_string.rs:29:5 | LL | cr"no hashes"; | ^^^^^^^^^^^^^ @@ -92,7 +93,7 @@ LL + c"no hashes"; | error: unnecessary raw string literal - --> tests/ui/needless_raw_string.rs:27:14 + --> tests/ui/needless_raw_string.rs:34:14 | LL | println!(r"SELECT * FROM posts"); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -104,7 +105,7 @@ LL + println!("SELECT * FROM posts"); | error: unnecessary raw string literal - --> tests/ui/needless_raw_string.rs:28:14 + --> tests/ui/needless_raw_string.rs:36:14 | LL | println!(r#"SELECT * FROM posts"#); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -116,7 +117,7 @@ LL + println!("SELECT * FROM posts"); | error: unnecessary raw string literal - --> tests/ui/needless_raw_string.rs:32:20 + --> tests/ui/needless_raw_string.rs:41:20 | LL | println!("{}", r"foobar".len()); | ^^^^^^^^^ diff --git a/tests/ui/needless_raw_string_hashes.fixed b/tests/ui/needless_raw_string_hashes.fixed index 4c1137091071..bc7da202df4a 100644 --- a/tests/ui/needless_raw_string_hashes.fixed +++ b/tests/ui/needless_raw_string_hashes.fixed @@ -3,33 +3,51 @@ fn main() { r"\aaa"; + //~^ needless_raw_string_hashes r#"Hello "world"!"#; + //~^ needless_raw_string_hashes r####" "### "## "# "####; + //~^ needless_raw_string_hashes r###" "aa" "# "## "###; + //~^ needless_raw_string_hashes br"\aaa"; + //~^ needless_raw_string_hashes br#"Hello "world"!"#; + //~^ needless_raw_string_hashes br####" "### "## "# "####; + //~^ needless_raw_string_hashes br###" "aa" "# "## "###; + //~^ needless_raw_string_hashes cr"\aaa"; + //~^ needless_raw_string_hashes cr#"Hello "world"!"#; + //~^ needless_raw_string_hashes cr####" "### "## "# "####; + //~^ needless_raw_string_hashes cr###" "aa" "# "## "###; + //~^ needless_raw_string_hashes r" + //~^ needless_raw_string_hashes \a multiline string "; r"rust"; + //~^ needless_raw_string_hashes r"hello world"; + //~^ needless_raw_string_hashes } fn issue_13503() { println!(r"SELECT * FROM posts"); println!(r"SELECT * FROM posts"); + //~^ needless_raw_string_hashes println!(r#"SELECT * FROM "posts""#); + //~^ needless_raw_string_hashes println!(r#"SELECT * FROM "posts""#); + //~^ needless_raw_string_hashes // Test arguments as well println!("{}", r"foobar".len()); diff --git a/tests/ui/needless_raw_string_hashes.rs b/tests/ui/needless_raw_string_hashes.rs index 7b6b4e784eea..3f2f92a4097c 100644 --- a/tests/ui/needless_raw_string_hashes.rs +++ b/tests/ui/needless_raw_string_hashes.rs @@ -3,33 +3,51 @@ fn main() { r#"\aaa"#; + //~^ needless_raw_string_hashes r##"Hello "world"!"##; + //~^ needless_raw_string_hashes r######" "### "## "# "######; + //~^ needless_raw_string_hashes r######" "aa" "# "## "######; + //~^ needless_raw_string_hashes br#"\aaa"#; + //~^ needless_raw_string_hashes br##"Hello "world"!"##; + //~^ needless_raw_string_hashes br######" "### "## "# "######; + //~^ needless_raw_string_hashes br######" "aa" "# "## "######; + //~^ needless_raw_string_hashes cr#"\aaa"#; + //~^ needless_raw_string_hashes cr##"Hello "world"!"##; + //~^ needless_raw_string_hashes cr######" "### "## "# "######; + //~^ needless_raw_string_hashes cr######" "aa" "# "## "######; + //~^ needless_raw_string_hashes r#" + //~^ needless_raw_string_hashes \a multiline string "#; r###"rust"###; + //~^ needless_raw_string_hashes r#"hello world"#; + //~^ needless_raw_string_hashes } fn issue_13503() { println!(r"SELECT * FROM posts"); println!(r#"SELECT * FROM posts"#); + //~^ needless_raw_string_hashes println!(r##"SELECT * FROM "posts""##); + //~^ needless_raw_string_hashes println!(r##"SELECT * FROM "posts""##); + //~^ needless_raw_string_hashes // Test arguments as well println!("{}", r"foobar".len()); diff --git a/tests/ui/needless_raw_string_hashes.stderr b/tests/ui/needless_raw_string_hashes.stderr index a213ba3e7438..853ee7092528 100644 --- a/tests/ui/needless_raw_string_hashes.stderr +++ b/tests/ui/needless_raw_string_hashes.stderr @@ -13,7 +13,7 @@ LL + r"\aaa"; | error: unnecessary hashes around raw string literal - --> tests/ui/needless_raw_string_hashes.rs:6:5 + --> tests/ui/needless_raw_string_hashes.rs:7:5 | LL | r##"Hello "world"!"##; | ^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + r#"Hello "world"!"#; | error: unnecessary hashes around raw string literal - --> tests/ui/needless_raw_string_hashes.rs:7:5 + --> tests/ui/needless_raw_string_hashes.rs:9:5 | LL | r######" "### "## "# "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + r####" "### "## "# "####; | error: unnecessary hashes around raw string literal - --> tests/ui/needless_raw_string_hashes.rs:8:5 + --> tests/ui/needless_raw_string_hashes.rs:11:5 | LL | r######" "aa" "# "## "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + r###" "aa" "# "## "###; | error: unnecessary hashes around raw string literal - --> tests/ui/needless_raw_string_hashes.rs:9:5 + --> tests/ui/needless_raw_string_hashes.rs:13:5 | LL | br#"\aaa"#; | ^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + br"\aaa"; | error: unnecessary hashes around raw string literal - --> tests/ui/needless_raw_string_hashes.rs:10:5 + --> tests/ui/needless_raw_string_hashes.rs:15:5 | LL | br##"Hello "world"!"##; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + br#"Hello "world"!"#; | error: unnecessary hashes around raw string literal - --> tests/ui/needless_raw_string_hashes.rs:11:5 + --> tests/ui/needless_raw_string_hashes.rs:17:5 | LL | br######" "### "## "# "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + br####" "### "## "# "####; | error: unnecessary hashes around raw string literal - --> tests/ui/needless_raw_string_hashes.rs:12:5 + --> tests/ui/needless_raw_string_hashes.rs:19:5 | LL | br######" "aa" "# "## "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL + br###" "aa" "# "## "###; | error: unnecessary hashes around raw string literal - --> tests/ui/needless_raw_string_hashes.rs:13:5 + --> tests/ui/needless_raw_string_hashes.rs:21:5 | LL | cr#"\aaa"#; | ^^^^^^^^^^ @@ -109,7 +109,7 @@ LL + cr"\aaa"; | error: unnecessary hashes around raw string literal - --> tests/ui/needless_raw_string_hashes.rs:14:5 + --> tests/ui/needless_raw_string_hashes.rs:23:5 | LL | cr##"Hello "world"!"##; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL + cr#"Hello "world"!"#; | error: unnecessary hashes around raw string literal - --> tests/ui/needless_raw_string_hashes.rs:15:5 + --> tests/ui/needless_raw_string_hashes.rs:25:5 | LL | cr######" "### "## "# "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL + cr####" "### "## "# "####; | error: unnecessary hashes around raw string literal - --> tests/ui/needless_raw_string_hashes.rs:16:5 + --> tests/ui/needless_raw_string_hashes.rs:27:5 | LL | cr######" "aa" "# "## "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -145,9 +145,10 @@ LL + cr###" "aa" "# "## "###; | error: unnecessary hashes around raw string literal - --> tests/ui/needless_raw_string_hashes.rs:18:5 + --> tests/ui/needless_raw_string_hashes.rs:30:5 | LL | / r#" +LL | | LL | | \a LL | | multiline LL | | string @@ -157,14 +158,14 @@ LL | | "#; help: remove all the hashes around the string literal | LL ~ r" -LL | \a -LL | multiline +LL | +... LL | string LL ~ "; | error: unnecessary hashes around raw string literal - --> tests/ui/needless_raw_string_hashes.rs:24:5 + --> tests/ui/needless_raw_string_hashes.rs:37:5 | LL | r###"rust"###; | ^^^^^^^^^^^^^ @@ -176,7 +177,7 @@ LL + r"rust"; | error: unnecessary hashes around raw string literal - --> tests/ui/needless_raw_string_hashes.rs:25:5 + --> tests/ui/needless_raw_string_hashes.rs:39:5 | LL | r#"hello world"#; | ^^^^^^^^^^^^^^^^ @@ -188,7 +189,7 @@ LL + r"hello world"; | error: unnecessary hashes around raw string literal - --> tests/ui/needless_raw_string_hashes.rs:30:14 + --> tests/ui/needless_raw_string_hashes.rs:45:14 | LL | println!(r#"SELECT * FROM posts"#); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -200,7 +201,7 @@ LL + println!(r"SELECT * FROM posts"); | error: unnecessary hashes around raw string literal - --> tests/ui/needless_raw_string_hashes.rs:31:14 + --> tests/ui/needless_raw_string_hashes.rs:47:14 | LL | println!(r##"SELECT * FROM "posts""##); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -212,7 +213,7 @@ LL + println!(r#"SELECT * FROM "posts""#); | error: unnecessary hashes around raw string literal - --> tests/ui/needless_raw_string_hashes.rs:32:14 + --> tests/ui/needless_raw_string_hashes.rs:49:14 | LL | println!(r##"SELECT * FROM "posts""##); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/needless_return.fixed b/tests/ui/needless_return.fixed index aa2a274525bc..efc073ebe874 100644 --- a/tests/ui/needless_return.fixed +++ b/tests/ui/needless_return.fixed @@ -27,35 +27,43 @@ fn test_end_of_fn() -> bool { return true; } true + //~^ needless_return } fn test_no_semicolon() -> bool { true + //~^ needless_return } #[rustfmt::skip] fn test_multiple_semicolon() -> bool { true + //~^ needless_return } #[rustfmt::skip] fn test_multiple_semicolon_with_spaces() -> bool { true + //~^ needless_return } fn test_if_block() -> bool { if true { true + //~^ needless_return } else { false + //~^ needless_return } } fn test_match(x: bool) -> bool { match x { true => false, + //~^ needless_return false => { true + //~^ needless_return }, } } @@ -63,20 +71,26 @@ fn test_match(x: bool) -> bool { fn test_closure() { let _ = || { true + //~^ needless_return }; let _ = || true; + //~^ needless_return } fn test_macro_call() -> i32 { the_answer!() + //~^ needless_return } fn test_void_fun() { + //~^^ needless_return } fn test_void_if_fun(b: bool) { if b { + //~^^ needless_return } else { + //~^^ needless_return } } @@ -84,6 +98,7 @@ fn test_void_match(x: u32) { match x { 0 => (), _ => (), + //~^ needless_return } } @@ -92,8 +107,10 @@ fn test_nested_match(x: u32) { 0 => (), 1 => { let _ = 42; + //~^^ needless_return }, _ => (), + //~^ needless_return } } @@ -107,8 +124,10 @@ fn borrows_but_not_last(value: bool) -> String { let x = RefCell::::default(); let _a = x.borrow().clone(); String::from("test") + //~^ needless_return } else { String::new() + //~^ needless_return } } @@ -131,18 +150,22 @@ mod issue6501 { #[allow(clippy::unnecessary_lazy_evaluations)] fn foo(bar: Result<(), ()>) { bar.unwrap_or_else(|_| {}) + //~^ needless_return } fn test_closure() { let _ = || { + //~^^ needless_return }; let _ = || {}; + //~^ needless_return } struct Foo; #[allow(clippy::unnecessary_lazy_evaluations)] fn bar(res: Result) -> Foo { res.unwrap_or_else(|_| Foo) + //~^ needless_return } } @@ -152,25 +175,31 @@ async fn async_test_end_of_fn() -> bool { return true; } true + //~^ needless_return } async fn async_test_no_semicolon() -> bool { true + //~^ needless_return } async fn async_test_if_block() -> bool { if true { true + //~^ needless_return } else { false + //~^ needless_return } } async fn async_test_match(x: bool) -> bool { match x { true => false, + //~^ needless_return false => { true + //~^ needless_return }, } } @@ -178,20 +207,26 @@ async fn async_test_match(x: bool) -> bool { async fn async_test_closure() { let _ = || { true + //~^ needless_return }; let _ = || true; + //~^ needless_return } async fn async_test_macro_call() -> i32 { the_answer!() + //~^ needless_return } async fn async_test_void_fun() { + //~^^ needless_return } async fn async_test_void_if_fun(b: bool) { if b { + //~^^ needless_return } else { + //~^^ needless_return } } @@ -199,6 +234,7 @@ async fn async_test_void_match(x: u32) { match x { 0 => (), _ => (), + //~^ needless_return } } @@ -212,8 +248,10 @@ async fn async_borrows_but_not_last(value: bool) -> String { let x = RefCell::::default(); let _a = x.borrow().clone(); String::from("test") + //~^ needless_return } else { String::new() + //~^ needless_return } } @@ -230,6 +268,7 @@ fn needless_return_macro() -> String { let _ = "foo"; let _ = "bar"; format!("Hello {}", "world!") + //~^ needless_return } fn issue_9361(n: i32) -> i32 { @@ -271,8 +310,10 @@ fn issue8336(x: i32) -> bool { if x > 0 { println!("something"); true + //~^ needless_return } else { false + //~^ needless_return } } @@ -280,9 +321,11 @@ fn issue8156(x: u8) -> u64 { match x { 80 => { 10 + //~^ needless_return }, _ => { 100 + //~^ needless_return }, } } @@ -291,6 +334,7 @@ fn issue8156(x: u8) -> u64 { fn issue9192() -> i32 { { 0 + //~^ needless_return } } @@ -298,8 +342,10 @@ fn issue9503(x: usize) -> isize { unsafe { if x > 12 { *(x as *const isize) + //~^ needless_return } else { !*(x as *const isize) + //~^ needless_return } } } @@ -307,11 +353,13 @@ fn issue9503(x: usize) -> isize { mod issue9416 { pub fn with_newline() { let _ = 42; + //~^^ needless_return } #[rustfmt::skip] pub fn oneline() { let _ = 42; + //~^ needless_return } } @@ -324,18 +372,22 @@ fn issue9947() -> Result<(), String> { fn issue10051() -> Result { if true { Ok(format!("ok!")) + //~^ needless_return } else { Err(format!("err!")) + //~^ needless_return } } mod issue10049 { fn single() -> u32 { if true { 1 } else { 2 } + //~^ needless_return } fn multiple(b1: bool, b2: bool, b3: bool) -> u32 { (if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 }) + //~^ needless_return } } @@ -357,10 +409,12 @@ fn allow_works() -> i32 { fn conjunctive_blocks() -> String { ({ "a".to_string() } + "b" + { "c" }) + //~^ needless_return } fn issue12907() -> String { "".split("").next().unwrap().to_string() + //~^ needless_return } fn issue13458() { diff --git a/tests/ui/needless_return.rs b/tests/ui/needless_return.rs index bf67cfd3698a..283d86f25fe5 100644 --- a/tests/ui/needless_return.rs +++ b/tests/ui/needless_return.rs @@ -27,35 +27,43 @@ fn test_end_of_fn() -> bool { return true; } return true; + //~^ needless_return } fn test_no_semicolon() -> bool { return true; + //~^ needless_return } #[rustfmt::skip] fn test_multiple_semicolon() -> bool { return true;;; + //~^ needless_return } #[rustfmt::skip] fn test_multiple_semicolon_with_spaces() -> bool { return true;; ; ; + //~^ needless_return } fn test_if_block() -> bool { if true { return true; + //~^ needless_return } else { return false; + //~^ needless_return } } fn test_match(x: bool) -> bool { match x { true => return false, + //~^ needless_return false => { return true; + //~^ needless_return }, } } @@ -63,23 +71,29 @@ fn test_match(x: bool) -> bool { fn test_closure() { let _ = || { return true; + //~^ needless_return }; let _ = || return true; + //~^ needless_return } fn test_macro_call() -> i32 { return the_answer!(); + //~^ needless_return } fn test_void_fun() { return; + //~^^ needless_return } fn test_void_if_fun(b: bool) { if b { return; + //~^^ needless_return } else { return; + //~^^ needless_return } } @@ -87,6 +101,7 @@ fn test_void_match(x: u32) { match x { 0 => (), _ => return, + //~^ needless_return } } @@ -96,8 +111,10 @@ fn test_nested_match(x: u32) { 1 => { let _ = 42; return; + //~^^ needless_return }, _ => return, + //~^ needless_return } } @@ -111,8 +128,10 @@ fn borrows_but_not_last(value: bool) -> String { let x = RefCell::::default(); let _a = x.borrow().clone(); return String::from("test"); + //~^ needless_return } else { return String::new(); + //~^ needless_return } } @@ -135,19 +154,23 @@ mod issue6501 { #[allow(clippy::unnecessary_lazy_evaluations)] fn foo(bar: Result<(), ()>) { bar.unwrap_or_else(|_| return) + //~^ needless_return } fn test_closure() { let _ = || { return; + //~^^ needless_return }; let _ = || return; + //~^ needless_return } struct Foo; #[allow(clippy::unnecessary_lazy_evaluations)] fn bar(res: Result) -> Foo { res.unwrap_or_else(|_| return Foo) + //~^ needless_return } } @@ -157,25 +180,31 @@ async fn async_test_end_of_fn() -> bool { return true; } return true; + //~^ needless_return } async fn async_test_no_semicolon() -> bool { return true; + //~^ needless_return } async fn async_test_if_block() -> bool { if true { return true; + //~^ needless_return } else { return false; + //~^ needless_return } } async fn async_test_match(x: bool) -> bool { match x { true => return false, + //~^ needless_return false => { return true; + //~^ needless_return }, } } @@ -183,23 +212,29 @@ async fn async_test_match(x: bool) -> bool { async fn async_test_closure() { let _ = || { return true; + //~^ needless_return }; let _ = || return true; + //~^ needless_return } async fn async_test_macro_call() -> i32 { return the_answer!(); + //~^ needless_return } async fn async_test_void_fun() { return; + //~^^ needless_return } async fn async_test_void_if_fun(b: bool) { if b { return; + //~^^ needless_return } else { return; + //~^^ needless_return } } @@ -207,6 +242,7 @@ async fn async_test_void_match(x: u32) { match x { 0 => (), _ => return, + //~^ needless_return } } @@ -220,8 +256,10 @@ async fn async_borrows_but_not_last(value: bool) -> String { let x = RefCell::::default(); let _a = x.borrow().clone(); return String::from("test"); + //~^ needless_return } else { return String::new(); + //~^ needless_return } } @@ -238,6 +276,7 @@ fn needless_return_macro() -> String { let _ = "foo"; let _ = "bar"; return format!("Hello {}", "world!"); + //~^ needless_return } fn issue_9361(n: i32) -> i32 { @@ -279,8 +318,10 @@ fn issue8336(x: i32) -> bool { if x > 0 { println!("something"); return true; + //~^ needless_return } else { return false; + //~^ needless_return }; } @@ -288,9 +329,11 @@ fn issue8156(x: u8) -> u64 { match x { 80 => { return 10; + //~^ needless_return }, _ => { return 100; + //~^ needless_return }, }; } @@ -299,6 +342,7 @@ fn issue8156(x: u8) -> u64 { fn issue9192() -> i32 { { return 0; + //~^ needless_return }; } @@ -306,8 +350,10 @@ fn issue9503(x: usize) -> isize { unsafe { if x > 12 { return *(x as *const isize); + //~^ needless_return } else { return !*(x as *const isize); + //~^ needless_return }; }; } @@ -315,13 +361,14 @@ fn issue9503(x: usize) -> isize { mod issue9416 { pub fn with_newline() { let _ = 42; - return; + //~^^ needless_return } #[rustfmt::skip] pub fn oneline() { let _ = 42; return; + //~^ needless_return } } @@ -334,18 +381,22 @@ fn issue9947() -> Result<(), String> { fn issue10051() -> Result { if true { return Ok(format!("ok!")); + //~^ needless_return } else { return Err(format!("err!")); + //~^ needless_return } } mod issue10049 { fn single() -> u32 { return if true { 1 } else { 2 }; + //~^ needless_return } fn multiple(b1: bool, b2: bool, b3: bool) -> u32 { return if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 }; + //~^ needless_return } } @@ -367,10 +418,12 @@ fn allow_works() -> i32 { fn conjunctive_blocks() -> String { return { "a".to_string() } + "b" + { "c" }; + //~^ needless_return } fn issue12907() -> String { return "".split("").next().unwrap().to_string(); + //~^ needless_return } fn issue13458() { diff --git a/tests/ui/needless_return.stderr b/tests/ui/needless_return.stderr index 8d8b5b9e713d..04c97a41d676 100644 --- a/tests/ui/needless_return.stderr +++ b/tests/ui/needless_return.stderr @@ -13,7 +13,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:33:5 + --> tests/ui/needless_return.rs:34:5 | LL | return true; | ^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:38:5 + --> tests/ui/needless_return.rs:40:5 | LL | return true;;; | ^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:43:5 + --> tests/ui/needless_return.rs:46:5 | LL | return true;; ; ; | ^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:48:9 + --> tests/ui/needless_return.rs:52:9 | LL | return true; | ^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:50:9 + --> tests/ui/needless_return.rs:55:9 | LL | return false; | ^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + false | error: unneeded `return` statement - --> tests/ui/needless_return.rs:56:17 + --> tests/ui/needless_return.rs:62:17 | LL | true => return false, | ^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + true => false, | error: unneeded `return` statement - --> tests/ui/needless_return.rs:58:13 + --> tests/ui/needless_return.rs:65:13 | LL | return true; | ^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:65:9 + --> tests/ui/needless_return.rs:73:9 | LL | return true; | ^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:67:16 + --> tests/ui/needless_return.rs:76:16 | LL | let _ = || return true; | ^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL + let _ = || true; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:71:5 + --> tests/ui/needless_return.rs:81:5 | LL | return the_answer!(); | ^^^^^^^^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL + the_answer!() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:74:21 + --> tests/ui/needless_return.rs:85:21 | LL | fn test_void_fun() { | _____________________^ @@ -148,7 +148,7 @@ LL + fn test_void_fun() { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:79:11 + --> tests/ui/needless_return.rs:91:11 | LL | if b { | ___________^ @@ -163,7 +163,7 @@ LL + if b { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:81:13 + --> tests/ui/needless_return.rs:94:13 | LL | } else { | _____________^ @@ -178,7 +178,7 @@ LL + } else { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:89:14 + --> tests/ui/needless_return.rs:103:14 | LL | _ => return, | ^^^^^^ @@ -190,7 +190,7 @@ LL + _ => (), | error: unneeded `return` statement - --> tests/ui/needless_return.rs:97:24 + --> tests/ui/needless_return.rs:112:24 | LL | let _ = 42; | ________________________^ @@ -205,7 +205,7 @@ LL + let _ = 42; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:100:14 + --> tests/ui/needless_return.rs:116:14 | LL | _ => return, | ^^^^^^ @@ -217,7 +217,7 @@ LL + _ => (), | error: unneeded `return` statement - --> tests/ui/needless_return.rs:113:9 + --> tests/ui/needless_return.rs:130:9 | LL | return String::from("test"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -229,7 +229,7 @@ LL + String::from("test") | error: unneeded `return` statement - --> tests/ui/needless_return.rs:115:9 + --> tests/ui/needless_return.rs:133:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^ @@ -241,7 +241,7 @@ LL + String::new() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:137:32 + --> tests/ui/needless_return.rs:156:32 | LL | bar.unwrap_or_else(|_| return) | ^^^^^^ @@ -253,7 +253,7 @@ LL + bar.unwrap_or_else(|_| {}) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:141:21 + --> tests/ui/needless_return.rs:161:21 | LL | let _ = || { | _____________________^ @@ -268,7 +268,7 @@ LL + let _ = || { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:144:20 + --> tests/ui/needless_return.rs:165:20 | LL | let _ = || return; | ^^^^^^ @@ -280,7 +280,7 @@ LL + let _ = || {}; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:150:32 + --> tests/ui/needless_return.rs:172:32 | LL | res.unwrap_or_else(|_| return Foo) | ^^^^^^^^^^ @@ -292,7 +292,7 @@ LL + res.unwrap_or_else(|_| Foo) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:159:5 + --> tests/ui/needless_return.rs:182:5 | LL | return true; | ^^^^^^^^^^^ @@ -304,7 +304,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:163:5 + --> tests/ui/needless_return.rs:187:5 | LL | return true; | ^^^^^^^^^^^ @@ -316,7 +316,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:168:9 + --> tests/ui/needless_return.rs:193:9 | LL | return true; | ^^^^^^^^^^^ @@ -328,7 +328,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:170:9 + --> tests/ui/needless_return.rs:196:9 | LL | return false; | ^^^^^^^^^^^^ @@ -340,7 +340,7 @@ LL + false | error: unneeded `return` statement - --> tests/ui/needless_return.rs:176:17 + --> tests/ui/needless_return.rs:203:17 | LL | true => return false, | ^^^^^^^^^^^^ @@ -352,7 +352,7 @@ LL + true => false, | error: unneeded `return` statement - --> tests/ui/needless_return.rs:178:13 + --> tests/ui/needless_return.rs:206:13 | LL | return true; | ^^^^^^^^^^^ @@ -364,7 +364,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:185:9 + --> tests/ui/needless_return.rs:214:9 | LL | return true; | ^^^^^^^^^^^ @@ -376,7 +376,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:187:16 + --> tests/ui/needless_return.rs:217:16 | LL | let _ = || return true; | ^^^^^^^^^^^ @@ -388,7 +388,7 @@ LL + let _ = || true; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:191:5 + --> tests/ui/needless_return.rs:222:5 | LL | return the_answer!(); | ^^^^^^^^^^^^^^^^^^^^ @@ -400,7 +400,7 @@ LL + the_answer!() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:194:33 + --> tests/ui/needless_return.rs:226:33 | LL | async fn async_test_void_fun() { | _________________________________^ @@ -415,7 +415,7 @@ LL + async fn async_test_void_fun() { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:199:11 + --> tests/ui/needless_return.rs:232:11 | LL | if b { | ___________^ @@ -430,7 +430,7 @@ LL + if b { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:201:13 + --> tests/ui/needless_return.rs:235:13 | LL | } else { | _____________^ @@ -445,7 +445,7 @@ LL + } else { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:209:14 + --> tests/ui/needless_return.rs:244:14 | LL | _ => return, | ^^^^^^ @@ -457,7 +457,7 @@ LL + _ => (), | error: unneeded `return` statement - --> tests/ui/needless_return.rs:222:9 + --> tests/ui/needless_return.rs:258:9 | LL | return String::from("test"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -469,7 +469,7 @@ LL + String::from("test") | error: unneeded `return` statement - --> tests/ui/needless_return.rs:224:9 + --> tests/ui/needless_return.rs:261:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^ @@ -481,7 +481,7 @@ LL + String::new() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:240:5 + --> tests/ui/needless_return.rs:278:5 | LL | return format!("Hello {}", "world!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -493,7 +493,7 @@ LL + format!("Hello {}", "world!") | error: unneeded `return` statement - --> tests/ui/needless_return.rs:281:9 + --> tests/ui/needless_return.rs:320:9 | LL | return true; | ^^^^^^^^^^^ @@ -501,13 +501,14 @@ LL | return true; help: remove `return` | LL ~ true -LL | } else { -LL | return false; +LL | +... +LL | LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:283:9 + --> tests/ui/needless_return.rs:323:9 | LL | return false; | ^^^^^^^^^^^^ @@ -515,11 +516,12 @@ LL | return false; help: remove `return` | LL ~ false +LL | LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:290:13 + --> tests/ui/needless_return.rs:331:13 | LL | return 10; | ^^^^^^^^^ @@ -527,14 +529,14 @@ LL | return 10; help: remove `return` | LL ~ 10 -LL | }, +LL | ... LL | }, LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:293:13 + --> tests/ui/needless_return.rs:335:13 | LL | return 100; | ^^^^^^^^^^ @@ -542,12 +544,13 @@ LL | return 100; help: remove `return` | LL ~ 100 +LL | LL | }, LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:301:9 + --> tests/ui/needless_return.rs:344:9 | LL | return 0; | ^^^^^^^^ @@ -555,11 +558,12 @@ LL | return 0; help: remove `return` | LL ~ 0 +LL | LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:308:13 + --> tests/ui/needless_return.rs:352:13 | LL | return *(x as *const isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -567,14 +571,15 @@ LL | return *(x as *const isize); help: remove `return` | LL ~ *(x as *const isize) -LL | } else { -LL | return !*(x as *const isize); +LL | +... +LL | LL ~ } LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:310:13 + --> tests/ui/needless_return.rs:355:13 | LL | return !*(x as *const isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -582,29 +587,28 @@ LL | return !*(x as *const isize); help: remove `return` | LL ~ !*(x as *const isize) +LL | LL ~ } LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:317:20 + --> tests/ui/needless_return.rs:363:20 | LL | let _ = 42; | ____________________^ -LL | | LL | | return; | |______________^ | help: remove `return` | LL - let _ = 42; -LL - LL - return; LL + let _ = 42; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:324:20 + --> tests/ui/needless_return.rs:370:20 | LL | let _ = 42; return; | ^^^^^^^ @@ -616,7 +620,7 @@ LL + let _ = 42; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:336:9 + --> tests/ui/needless_return.rs:383:9 | LL | return Ok(format!("ok!")); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -628,7 +632,7 @@ LL + Ok(format!("ok!")) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:338:9 + --> tests/ui/needless_return.rs:386:9 | LL | return Err(format!("err!")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -640,7 +644,7 @@ LL + Err(format!("err!")) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:344:9 + --> tests/ui/needless_return.rs:393:9 | LL | return if true { 1 } else { 2 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -652,7 +656,7 @@ LL + if true { 1 } else { 2 } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:348:9 + --> tests/ui/needless_return.rs:398:9 | LL | return if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -664,7 +668,7 @@ LL + (if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else | error: unneeded `return` statement - --> tests/ui/needless_return.rs:369:5 + --> tests/ui/needless_return.rs:420:5 | LL | return { "a".to_string() } + "b" + { "c" }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -676,7 +680,7 @@ LL + ({ "a".to_string() } + "b" + { "c" }) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:373:5 + --> tests/ui/needless_return.rs:425:5 | LL | return "".split("").next().unwrap().to_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/needless_return_with_question_mark.fixed b/tests/ui/needless_return_with_question_mark.fixed index 9b7da8526631..2c6faf37717d 100644 --- a/tests/ui/needless_return_with_question_mark.fixed +++ b/tests/ui/needless_return_with_question_mark.fixed @@ -27,6 +27,7 @@ fn c() -> Option<()> { fn main() -> Result<(), ()> { Err(())?; + //~^ needless_return_with_question_mark return Ok::<(), ()>(()); Err(())?; Ok::<(), ()>(()); diff --git a/tests/ui/needless_return_with_question_mark.rs b/tests/ui/needless_return_with_question_mark.rs index 68e76d2b6402..b4411fa19561 100644 --- a/tests/ui/needless_return_with_question_mark.rs +++ b/tests/ui/needless_return_with_question_mark.rs @@ -27,6 +27,7 @@ fn c() -> Option<()> { fn main() -> Result<(), ()> { return Err(())?; + //~^ needless_return_with_question_mark return Ok::<(), ()>(()); Err(())?; Ok::<(), ()>(()); diff --git a/tests/ui/needless_return_with_question_mark.stderr b/tests/ui/needless_return_with_question_mark.stderr index 76dd5f953bc6..2af0f46a1ad0 100644 --- a/tests/ui/needless_return_with_question_mark.stderr +++ b/tests/ui/needless_return_with_question_mark.stderr @@ -8,7 +8,7 @@ LL | return Err(())?; = help: to override `-D warnings` add `#[allow(clippy::needless_return_with_question_mark)]` error: unneeded `return` statement with `?` operator - --> tests/ui/needless_return_with_question_mark.rs:69:9 + --> tests/ui/needless_return_with_question_mark.rs:70:9 | LL | return Err(())?; | ^^^^^^^ help: remove it diff --git a/tests/ui/needless_splitn.fixed b/tests/ui/needless_splitn.fixed index efc47533e233..bf5c1717ae53 100644 --- a/tests/ui/needless_splitn.fixed +++ b/tests/ui/needless_splitn.fixed @@ -11,29 +11,41 @@ use itertools::Itertools; fn main() { let str = "key=value=end"; let _ = str.split('=').next(); + //~^ needless_splitn let _ = str.split('=').nth(0); + //~^ needless_splitn let _ = str.splitn(2, '=').nth(1); let (_, _) = str.splitn(2, '=').next_tuple().unwrap(); let (_, _) = str.split('=').next_tuple().unwrap(); + //~^ needless_splitn let _: Vec<&str> = str.splitn(3, '=').collect(); let _ = str.rsplit('=').next(); + //~^ needless_splitn let _ = str.rsplit('=').nth(0); + //~^ needless_splitn let _ = str.rsplitn(2, '=').nth(1); let (_, _) = str.rsplitn(2, '=').next_tuple().unwrap(); let (_, _) = str.rsplit('=').next_tuple().unwrap(); + //~^ needless_splitn let _ = str.split('=').next(); + //~^ needless_splitn let _ = str.split('=').nth(3); + //~^ needless_splitn let _ = str.splitn(5, '=').nth(4); let _ = str.splitn(5, '=').nth(5); } fn _question_mark(s: &str) -> Option<()> { let _ = s.split('=').next()?; + //~^ needless_splitn let _ = s.split('=').nth(0)?; + //~^ needless_splitn let _ = s.rsplit('=').next()?; + //~^ needless_splitn let _ = s.rsplit('=').nth(0)?; + //~^ needless_splitn Some(()) } @@ -42,4 +54,5 @@ fn _question_mark(s: &str) -> Option<()> { fn _test_msrv() { // `manual_split_once` MSRV shouldn't apply to `needless_splitn` let _ = "key=value".split('=').nth(0).unwrap(); + //~^ needless_splitn } diff --git a/tests/ui/needless_splitn.rs b/tests/ui/needless_splitn.rs index a4a3736eea2f..fdfdcb9d5ca8 100644 --- a/tests/ui/needless_splitn.rs +++ b/tests/ui/needless_splitn.rs @@ -11,29 +11,41 @@ use itertools::Itertools; fn main() { let str = "key=value=end"; let _ = str.splitn(2, '=').next(); + //~^ needless_splitn let _ = str.splitn(2, '=').nth(0); + //~^ needless_splitn let _ = str.splitn(2, '=').nth(1); let (_, _) = str.splitn(2, '=').next_tuple().unwrap(); let (_, _) = str.splitn(3, '=').next_tuple().unwrap(); + //~^ needless_splitn let _: Vec<&str> = str.splitn(3, '=').collect(); let _ = str.rsplitn(2, '=').next(); + //~^ needless_splitn let _ = str.rsplitn(2, '=').nth(0); + //~^ needless_splitn let _ = str.rsplitn(2, '=').nth(1); let (_, _) = str.rsplitn(2, '=').next_tuple().unwrap(); let (_, _) = str.rsplitn(3, '=').next_tuple().unwrap(); + //~^ needless_splitn let _ = str.splitn(5, '=').next(); + //~^ needless_splitn let _ = str.splitn(5, '=').nth(3); + //~^ needless_splitn let _ = str.splitn(5, '=').nth(4); let _ = str.splitn(5, '=').nth(5); } fn _question_mark(s: &str) -> Option<()> { let _ = s.splitn(2, '=').next()?; + //~^ needless_splitn let _ = s.splitn(2, '=').nth(0)?; + //~^ needless_splitn let _ = s.rsplitn(2, '=').next()?; + //~^ needless_splitn let _ = s.rsplitn(2, '=').nth(0)?; + //~^ needless_splitn Some(()) } @@ -42,4 +54,5 @@ fn _question_mark(s: &str) -> Option<()> { fn _test_msrv() { // `manual_split_once` MSRV shouldn't apply to `needless_splitn` let _ = "key=value".splitn(2, '=').nth(0).unwrap(); + //~^ needless_splitn } diff --git a/tests/ui/needless_splitn.stderr b/tests/ui/needless_splitn.stderr index ffd82c3fcb13..49387793a122 100644 --- a/tests/ui/needless_splitn.stderr +++ b/tests/ui/needless_splitn.stderr @@ -8,73 +8,73 @@ LL | let _ = str.splitn(2, '=').next(); = help: to override `-D warnings` add `#[allow(clippy::needless_splitn)]` error: unnecessary use of `splitn` - --> tests/ui/needless_splitn.rs:14:13 + --> tests/ui/needless_splitn.rs:15:13 | LL | let _ = str.splitn(2, '=').nth(0); | ^^^^^^^^^^^^^^^^^^ help: try: `str.split('=')` error: unnecessary use of `splitn` - --> tests/ui/needless_splitn.rs:17:18 + --> tests/ui/needless_splitn.rs:19:18 | LL | let (_, _) = str.splitn(3, '=').next_tuple().unwrap(); | ^^^^^^^^^^^^^^^^^^ help: try: `str.split('=')` error: unnecessary use of `rsplitn` - --> tests/ui/needless_splitn.rs:20:13 + --> tests/ui/needless_splitn.rs:23:13 | LL | let _ = str.rsplitn(2, '=').next(); | ^^^^^^^^^^^^^^^^^^^ help: try: `str.rsplit('=')` error: unnecessary use of `rsplitn` - --> tests/ui/needless_splitn.rs:21:13 + --> tests/ui/needless_splitn.rs:25:13 | LL | let _ = str.rsplitn(2, '=').nth(0); | ^^^^^^^^^^^^^^^^^^^ help: try: `str.rsplit('=')` error: unnecessary use of `rsplitn` - --> tests/ui/needless_splitn.rs:24:18 + --> tests/ui/needless_splitn.rs:29:18 | LL | let (_, _) = str.rsplitn(3, '=').next_tuple().unwrap(); | ^^^^^^^^^^^^^^^^^^^ help: try: `str.rsplit('=')` error: unnecessary use of `splitn` - --> tests/ui/needless_splitn.rs:26:13 + --> tests/ui/needless_splitn.rs:32:13 | LL | let _ = str.splitn(5, '=').next(); | ^^^^^^^^^^^^^^^^^^ help: try: `str.split('=')` error: unnecessary use of `splitn` - --> tests/ui/needless_splitn.rs:27:13 + --> tests/ui/needless_splitn.rs:34:13 | LL | let _ = str.splitn(5, '=').nth(3); | ^^^^^^^^^^^^^^^^^^ help: try: `str.split('=')` error: unnecessary use of `splitn` - --> tests/ui/needless_splitn.rs:33:13 + --> tests/ui/needless_splitn.rs:41:13 | LL | let _ = s.splitn(2, '=').next()?; | ^^^^^^^^^^^^^^^^ help: try: `s.split('=')` error: unnecessary use of `splitn` - --> tests/ui/needless_splitn.rs:34:13 + --> tests/ui/needless_splitn.rs:43:13 | LL | let _ = s.splitn(2, '=').nth(0)?; | ^^^^^^^^^^^^^^^^ help: try: `s.split('=')` error: unnecessary use of `rsplitn` - --> tests/ui/needless_splitn.rs:35:13 + --> tests/ui/needless_splitn.rs:45:13 | LL | let _ = s.rsplitn(2, '=').next()?; | ^^^^^^^^^^^^^^^^^ help: try: `s.rsplit('=')` error: unnecessary use of `rsplitn` - --> tests/ui/needless_splitn.rs:36:13 + --> tests/ui/needless_splitn.rs:47:13 | LL | let _ = s.rsplitn(2, '=').nth(0)?; | ^^^^^^^^^^^^^^^^^ help: try: `s.rsplit('=')` error: unnecessary use of `splitn` - --> tests/ui/needless_splitn.rs:44:13 + --> tests/ui/needless_splitn.rs:56:13 | LL | let _ = "key=value".splitn(2, '=').nth(0).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".split('=')` diff --git a/tests/ui/needless_update.rs b/tests/ui/needless_update.rs index 7c59abf07aba..62e349234319 100644 --- a/tests/ui/needless_update.rs +++ b/tests/ui/needless_update.rs @@ -17,8 +17,7 @@ fn main() { S { ..base }; // no error S { a: 1, ..base }; // no error S { a: 1, b: 1, ..base }; - //~^ ERROR: struct update has no effect, all the fields in the struct have already bee - //~| NOTE: `-D clippy::needless-update` implied by `-D warnings` + //~^ needless_update let base = T { x: 0, y: 0 }; T { ..base }; // no error diff --git a/tests/ui/neg_cmp_op_on_partial_ord.rs b/tests/ui/neg_cmp_op_on_partial_ord.rs index c79fd2665260..27b51b428170 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.rs +++ b/tests/ui/neg_cmp_op_on_partial_ord.rs @@ -14,20 +14,19 @@ fn main() { // Not Less but potentially Greater, Equal or Uncomparable. let _not_less = !(a_value < another_value); - //~^ ERROR: the use of negated comparison operators on partially ordered types produce - //~| NOTE: `-D clippy::neg-cmp-op-on-partial-ord` implied by `-D warnings` + //~^ neg_cmp_op_on_partial_ord // Not Less or Equal but potentially Greater or Uncomparable. let _not_less_or_equal = !(a_value <= another_value); - //~^ ERROR: the use of negated comparison operators on partially ordered types produce + //~^ neg_cmp_op_on_partial_ord // Not Greater but potentially Less, Equal or Uncomparable. let _not_greater = !(a_value > another_value); - //~^ ERROR: the use of negated comparison operators on partially ordered types produce + //~^ neg_cmp_op_on_partial_ord // Not Greater or Equal but potentially Less or Uncomparable. let _not_greater_or_equal = !(a_value >= another_value); - //~^ ERROR: the use of negated comparison operators on partially ordered types produce + //~^ neg_cmp_op_on_partial_ord // --- Good --- diff --git a/tests/ui/neg_cmp_op_on_partial_ord.stderr b/tests/ui/neg_cmp_op_on_partial_ord.stderr index d4f7f14f59a3..3c11d5b8826a 100644 --- a/tests/ui/neg_cmp_op_on_partial_ord.stderr +++ b/tests/ui/neg_cmp_op_on_partial_ord.stderr @@ -8,19 +8,19 @@ LL | let _not_less = !(a_value < another_value); = help: to override `-D warnings` add `#[allow(clippy::neg_cmp_op_on_partial_ord)]` error: the use of negated comparison operators on partially ordered types produces code that is hard to read and refactor, please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable - --> tests/ui/neg_cmp_op_on_partial_ord.rs:21:30 + --> tests/ui/neg_cmp_op_on_partial_ord.rs:20:30 | LL | let _not_less_or_equal = !(a_value <= another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the use of negated comparison operators on partially ordered types produces code that is hard to read and refactor, please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable - --> tests/ui/neg_cmp_op_on_partial_ord.rs:25:24 + --> tests/ui/neg_cmp_op_on_partial_ord.rs:24:24 | LL | let _not_greater = !(a_value > another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the use of negated comparison operators on partially ordered types produces code that is hard to read and refactor, please consider using the `partial_cmp` method instead, to make it clear that the two values could be incomparable - --> tests/ui/neg_cmp_op_on_partial_ord.rs:29:33 + --> tests/ui/neg_cmp_op_on_partial_ord.rs:28:33 | LL | let _not_greater_or_equal = !(a_value >= another_value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/neg_multiply.fixed b/tests/ui/neg_multiply.fixed index 52edea73afbb..995470493bfb 100644 --- a/tests/ui/neg_multiply.fixed +++ b/tests/ui/neg_multiply.fixed @@ -26,19 +26,27 @@ fn main() { let x = 0; -x; + //~^ neg_multiply -x; + //~^ neg_multiply 100 + -x; + //~^ neg_multiply -(100 + x); + //~^ neg_multiply -17; + //~^ neg_multiply 0xcafe | -0xff00; + //~^ neg_multiply -(3_usize as i32); + //~^ neg_multiply -(3_usize as i32); + //~^ neg_multiply -1 * -1; // should be ok diff --git a/tests/ui/neg_multiply.rs b/tests/ui/neg_multiply.rs index 23092a35e606..95b94e29517f 100644 --- a/tests/ui/neg_multiply.rs +++ b/tests/ui/neg_multiply.rs @@ -26,19 +26,27 @@ fn main() { let x = 0; x * -1; + //~^ neg_multiply -1 * x; + //~^ neg_multiply 100 + x * -1; + //~^ neg_multiply (100 + x) * -1; + //~^ neg_multiply -1 * 17; + //~^ neg_multiply 0xcafe | 0xff00 * -1; + //~^ neg_multiply 3_usize as i32 * -1; + //~^ neg_multiply (3_usize as i32) * -1; + //~^ neg_multiply -1 * -1; // should be ok diff --git a/tests/ui/neg_multiply.stderr b/tests/ui/neg_multiply.stderr index 13226c7c37b3..9efa5d3ba1f1 100644 --- a/tests/ui/neg_multiply.stderr +++ b/tests/ui/neg_multiply.stderr @@ -8,43 +8,43 @@ LL | x * -1; = help: to override `-D warnings` add `#[allow(clippy::neg_multiply)]` error: this multiplication by -1 can be written more succinctly - --> tests/ui/neg_multiply.rs:30:5 + --> tests/ui/neg_multiply.rs:31:5 | LL | -1 * x; | ^^^^^^ help: consider using: `-x` error: this multiplication by -1 can be written more succinctly - --> tests/ui/neg_multiply.rs:32:11 + --> tests/ui/neg_multiply.rs:34:11 | LL | 100 + x * -1; | ^^^^^^ help: consider using: `-x` error: this multiplication by -1 can be written more succinctly - --> tests/ui/neg_multiply.rs:34:5 + --> tests/ui/neg_multiply.rs:37:5 | LL | (100 + x) * -1; | ^^^^^^^^^^^^^^ help: consider using: `-(100 + x)` error: this multiplication by -1 can be written more succinctly - --> tests/ui/neg_multiply.rs:36:5 + --> tests/ui/neg_multiply.rs:40:5 | LL | -1 * 17; | ^^^^^^^ help: consider using: `-17` error: this multiplication by -1 can be written more succinctly - --> tests/ui/neg_multiply.rs:38:14 + --> tests/ui/neg_multiply.rs:43:14 | LL | 0xcafe | 0xff00 * -1; | ^^^^^^^^^^^ help: consider using: `-0xff00` error: this multiplication by -1 can be written more succinctly - --> tests/ui/neg_multiply.rs:40:5 + --> tests/ui/neg_multiply.rs:46:5 | LL | 3_usize as i32 * -1; | ^^^^^^^^^^^^^^^^^^^ help: consider using: `-(3_usize as i32)` error: this multiplication by -1 can be written more succinctly - --> tests/ui/neg_multiply.rs:41:5 + --> tests/ui/neg_multiply.rs:48:5 | LL | (3_usize as i32) * -1; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `-(3_usize as i32)` diff --git a/tests/ui/never_loop.rs b/tests/ui/never_loop.rs index 93c69209c698..2d8e04c192e4 100644 --- a/tests/ui/never_loop.rs +++ b/tests/ui/never_loop.rs @@ -10,8 +10,8 @@ fn test1() { let mut x = 0; loop { - //~^ ERROR: this loop never actually loops - //~| NOTE: `#[deny(clippy::never_loop)]` on by default + //~^ never_loop + // clippy::never_loop x += 1; if x == 1 { @@ -34,7 +34,8 @@ fn test2() { fn test3() { let mut x = 0; loop { - //~^ ERROR: this loop never actually loops + //~^ never_loop + // never loops x += 1; break; @@ -55,10 +56,12 @@ fn test4() { fn test5() { let i = 0; loop { - //~^ ERROR: this loop never actually loops + //~^ never_loop + // never loops while i == 0 { - //~^ ERROR: this loop never actually loops + //~^ never_loop + // never loops break; } @@ -71,7 +74,8 @@ fn test6() { 'outer: loop { x += 1; loop { - //~^ ERROR: this loop never actually loops + //~^ never_loop + // never loops if x == 5 { break; @@ -108,7 +112,8 @@ fn test8() { fn test9() { let x = Some(1); while let Some(y) = x { - //~^ ERROR: this loop never actually loops + //~^ never_loop + // never loops return; } @@ -116,7 +121,8 @@ fn test9() { fn test10() { for x in 0..10 { - //~^ ERROR: this loop never actually loops + //~^ never_loop + // never loops match x { 1 => break, @@ -165,7 +171,8 @@ pub fn test13() { pub fn test14() { let mut a = true; 'outer: while a { - //~^ ERROR: this loop never actually loops + //~^ never_loop + // never loops while a { if a { @@ -181,7 +188,8 @@ pub fn test14() { pub fn test15() { 'label: loop { while false { - //~^ ERROR: this loop never actually loops + //~^ never_loop + break 'label; } } @@ -233,7 +241,8 @@ pub fn test18() { }; // never loops let _ = loop { - //~^ ERROR: this loop never actually loops + //~^ never_loop + let Some(x) = x else { return; }; @@ -255,12 +264,12 @@ pub fn test19() { pub fn test20() { 'a: loop { - //~^ ERROR: this loop never actually loops + //~^ never_loop + 'b: { break 'b 'c: { break 'a; - //~^ ERROR: sub-expression diverges - //~| NOTE: `-D clippy::diverging-sub-expression` implied by `-D warnings` + //~^ diverging_sub_expression }; } } @@ -292,7 +301,8 @@ pub fn test23() { for _ in 0..10 { 'block: { for _ in 0..20 { - //~^ ERROR: this loop never actually loops + //~^ never_loop + break 'block; } } @@ -376,7 +386,8 @@ pub fn test31(b: bool) { 'a: loop { 'b: { 'c: loop { - //~^ ERROR: this loop never actually loops + //~^ never_loop + if b { break 'c } else { break 'b } } continue 'a; @@ -387,11 +398,13 @@ pub fn test31(b: bool) { pub fn test32() { loop { - //~^ ERROR: this loop never actually loops + //~^ never_loop + panic!("oh no"); } loop { - //~^ ERROR: this loop never actually loops + //~^ never_loop + unimplemented!("not yet"); } loop { diff --git a/tests/ui/never_loop.stderr b/tests/ui/never_loop.stderr index 203e33258225..f6d6d109542b 100644 --- a/tests/ui/never_loop.stderr +++ b/tests/ui/never_loop.stderr @@ -13,64 +13,49 @@ error: this loop never actually loops --> tests/ui/never_loop.rs:36:5 | LL | / loop { -LL | | -LL | | // never loops -LL | | x += 1; +... | LL | | break; LL | | } | |_____^ error: this loop never actually loops - --> tests/ui/never_loop.rs:57:5 + --> tests/ui/never_loop.rs:58:5 | LL | / loop { -LL | | -LL | | // never loops -LL | | while i == 0 { ... | LL | | return; LL | | } | |_____^ error: this loop never actually loops - --> tests/ui/never_loop.rs:60:9 + --> tests/ui/never_loop.rs:62:9 | LL | / while i == 0 { -LL | | -LL | | // never loops -LL | | break; +... | LL | | } | |_________^ error: this loop never actually loops - --> tests/ui/never_loop.rs:73:9 + --> tests/ui/never_loop.rs:76:9 | LL | / loop { -LL | | -LL | | // never loops -LL | | if x == 5 { ... | LL | | continue 'outer; LL | | } | |_________^ error: this loop never actually loops - --> tests/ui/never_loop.rs:110:5 + --> tests/ui/never_loop.rs:114:5 | LL | / while let Some(y) = x { -LL | | -LL | | // never loops -LL | | return; +... | LL | | } | |_____^ error: this loop never actually loops - --> tests/ui/never_loop.rs:118:5 + --> tests/ui/never_loop.rs:123:5 | LL | / for x in 0..10 { -LL | | -LL | | // never loops -LL | | match x { ... | LL | | } | |_____^ @@ -82,52 +67,50 @@ LL + if let Some(x) = (0..10).next() { | error: this loop never actually loops - --> tests/ui/never_loop.rs:167:5 + --> tests/ui/never_loop.rs:173:5 | LL | / 'outer: while a { -LL | | -LL | | // never loops -LL | | while a { ... | LL | | break 'outer; LL | | } | |_____^ error: this loop never actually loops - --> tests/ui/never_loop.rs:183:9 + --> tests/ui/never_loop.rs:190:9 | LL | / while false { LL | | +LL | | LL | | break 'label; LL | | } | |_________^ error: this loop never actually loops - --> tests/ui/never_loop.rs:235:13 + --> tests/ui/never_loop.rs:243:13 | LL | let _ = loop { | _____________^ LL | | +LL | | LL | | let Some(x) = x else { -LL | | return; ... | LL | | break x; LL | | }; | |_____^ error: this loop never actually loops - --> tests/ui/never_loop.rs:257:5 + --> tests/ui/never_loop.rs:266:5 | LL | / 'a: loop { LL | | +LL | | LL | | 'b: { -LL | | break 'b 'c: { ... | LL | | } | |_____^ error: sub-expression diverges - --> tests/ui/never_loop.rs:261:17 + --> tests/ui/never_loop.rs:271:17 | LL | break 'a; | ^^^^^^^^ @@ -136,10 +119,11 @@ LL | break 'a; = help: to override `-D warnings` add `#[allow(clippy::diverging_sub_expression)]` error: this loop never actually loops - --> tests/ui/never_loop.rs:294:13 + --> tests/ui/never_loop.rs:303:13 | LL | / for _ in 0..20 { LL | | +LL | | LL | | break 'block; LL | | } | |_____________^ @@ -151,28 +135,31 @@ LL + if let Some(_) = (0..20).next() { | error: this loop never actually loops - --> tests/ui/never_loop.rs:378:13 + --> tests/ui/never_loop.rs:388:13 | LL | / 'c: loop { LL | | +LL | | LL | | if b { break 'c } else { break 'b } LL | | } | |_____________^ error: this loop never actually loops - --> tests/ui/never_loop.rs:389:5 + --> tests/ui/never_loop.rs:400:5 | LL | / loop { LL | | +LL | | LL | | panic!("oh no"); LL | | } | |_____^ error: this loop never actually loops - --> tests/ui/never_loop.rs:393:5 + --> tests/ui/never_loop.rs:405:5 | LL | / loop { LL | | +LL | | LL | | unimplemented!("not yet"); LL | | } | |_____^ diff --git a/tests/ui/new_ret_no_self.rs b/tests/ui/new_ret_no_self.rs index 175b14d815a2..d61973f09b17 100644 --- a/tests/ui/new_ret_no_self.rs +++ b/tests/ui/new_ret_no_self.rs @@ -48,8 +48,8 @@ impl R for S3 { impl S3 { // should trigger the lint pub fn new(_: String) -> impl R { - //~^ ERROR: methods called `new` usually return `Self` - //~| NOTE: `-D clippy::new-ret-no-self` implied by `-D warnings` + //~^ new_ret_no_self + S3 } } @@ -82,7 +82,8 @@ struct U; impl U { // should trigger lint pub fn new() -> u32 { - //~^ ERROR: methods called `new` usually return `Self` + //~^ new_ret_no_self + unimplemented!(); } } @@ -92,7 +93,8 @@ struct V; impl V { // should trigger lint pub fn new(_: String) -> u32 { - //~^ ERROR: methods called `new` usually return `Self` + //~^ new_ret_no_self + unimplemented!(); } } @@ -129,7 +131,8 @@ struct TupleReturnerBad; impl TupleReturnerBad { // should trigger lint pub fn new() -> (u32, u32) { - //~^ ERROR: methods called `new` usually return `Self` + //~^ new_ret_no_self + unimplemented!(); } } @@ -157,7 +160,8 @@ struct MutPointerReturnerBad; impl MutPointerReturnerBad { // should trigger lint pub fn new() -> *mut V { - //~^ ERROR: methods called `new` usually return `Self` + //~^ new_ret_no_self + unimplemented!(); } } @@ -176,7 +180,8 @@ struct GenericReturnerBad; impl GenericReturnerBad { // should trigger lint pub fn new() -> Option { - //~^ ERROR: methods called `new` usually return `Self` + //~^ new_ret_no_self + unimplemented!(); } } @@ -230,7 +235,7 @@ mod issue5435 { pub trait TraitRet { // should trigger lint as we are in trait definition fn new() -> String; - //~^ ERROR: methods called `new` usually return `Self` + //~^ new_ret_no_self } pub struct StructRet; impl TraitRet for StructRet { @@ -243,7 +248,7 @@ mod issue5435 { pub trait TraitRet2 { // should trigger lint fn new(_: String) -> String; - //~^ ERROR: methods called `new` usually return `Self` + //~^ new_ret_no_self } trait TupleReturnerOk { @@ -279,7 +284,8 @@ mod issue5435 { trait TupleReturnerBad { // should trigger lint fn new() -> (u32, u32) { - //~^ ERROR: methods called `new` usually return `Self` + //~^ new_ret_no_self + unimplemented!(); } } @@ -307,7 +313,8 @@ mod issue5435 { trait MutPointerReturnerBad { // should trigger lint fn new() -> *mut V { - //~^ ERROR: methods called `new` usually return `Self` + //~^ new_ret_no_self + unimplemented!(); } } @@ -378,7 +385,8 @@ mod issue7344 { impl RetImplTraitNoSelf { // should trigger lint fn new(t: T) -> impl Into { - //~^ ERROR: methods called `new` usually return `Self` + //~^ new_ret_no_self + 1 } } @@ -398,7 +406,7 @@ mod issue7344 { impl RetImplTraitNoSelf2 { // should trigger lint fn new(t: T) -> impl Trait2<(), i32> { - //~^ ERROR: methods called `new` usually return `Self` + //~^ new_ret_no_self } } diff --git a/tests/ui/new_ret_no_self.stderr b/tests/ui/new_ret_no_self.stderr index 3597ad65838f..a758c746f918 100644 --- a/tests/ui/new_ret_no_self.stderr +++ b/tests/ui/new_ret_no_self.stderr @@ -16,87 +16,95 @@ error: methods called `new` usually return `Self` | LL | / pub fn new() -> u32 { LL | | +LL | | LL | | unimplemented!(); LL | | } | |_____^ error: methods called `new` usually return `Self` - --> tests/ui/new_ret_no_self.rs:94:5 + --> tests/ui/new_ret_no_self.rs:95:5 | LL | / pub fn new(_: String) -> u32 { LL | | +LL | | LL | | unimplemented!(); LL | | } | |_____^ error: methods called `new` usually return `Self` - --> tests/ui/new_ret_no_self.rs:131:5 + --> tests/ui/new_ret_no_self.rs:133:5 | LL | / pub fn new() -> (u32, u32) { LL | | +LL | | LL | | unimplemented!(); LL | | } | |_____^ error: methods called `new` usually return `Self` - --> tests/ui/new_ret_no_self.rs:159:5 + --> tests/ui/new_ret_no_self.rs:162:5 | LL | / pub fn new() -> *mut V { LL | | -LL | | unimplemented!(); -LL | | } - | |_____^ - -error: methods called `new` usually return `Self` - --> tests/ui/new_ret_no_self.rs:178:5 - | -LL | / pub fn new() -> Option { LL | | LL | | unimplemented!(); LL | | } | |_____^ error: methods called `new` usually return `Self` - --> tests/ui/new_ret_no_self.rs:232:9 + --> tests/ui/new_ret_no_self.rs:182:5 + | +LL | / pub fn new() -> Option { +LL | | +LL | | +LL | | unimplemented!(); +LL | | } + | |_____^ + +error: methods called `new` usually return `Self` + --> tests/ui/new_ret_no_self.rs:237:9 | LL | fn new() -> String; | ^^^^^^^^^^^^^^^^^^^ error: methods called `new` usually return `Self` - --> tests/ui/new_ret_no_self.rs:245:9 + --> tests/ui/new_ret_no_self.rs:250:9 | LL | fn new(_: String) -> String; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: methods called `new` usually return `Self` - --> tests/ui/new_ret_no_self.rs:281:9 + --> tests/ui/new_ret_no_self.rs:286:9 | LL | / fn new() -> (u32, u32) { LL | | -LL | | unimplemented!(); -LL | | } - | |_________^ - -error: methods called `new` usually return `Self` - --> tests/ui/new_ret_no_self.rs:309:9 - | -LL | / fn new() -> *mut V { LL | | LL | | unimplemented!(); LL | | } | |_________^ error: methods called `new` usually return `Self` - --> tests/ui/new_ret_no_self.rs:380:9 + --> tests/ui/new_ret_no_self.rs:315:9 + | +LL | / fn new() -> *mut V { +LL | | +LL | | +LL | | unimplemented!(); +LL | | } + | |_________^ + +error: methods called `new` usually return `Self` + --> tests/ui/new_ret_no_self.rs:387:9 | LL | / fn new(t: T) -> impl Into { LL | | +LL | | LL | | 1 LL | | } | |_________^ error: methods called `new` usually return `Self` - --> tests/ui/new_ret_no_self.rs:400:9 + --> tests/ui/new_ret_no_self.rs:408:9 | LL | / fn new(t: T) -> impl Trait2<(), i32> { LL | | diff --git a/tests/ui/new_ret_no_self_overflow.rs b/tests/ui/new_ret_no_self_overflow.rs index 7bc6fec10ba6..8a85c5662276 100644 --- a/tests/ui/new_ret_no_self_overflow.rs +++ b/tests/ui/new_ret_no_self_overflow.rs @@ -18,6 +18,7 @@ mod issue10041 { impl Bomb2 { pub fn new() -> X { + //~^ ERROR: overflow evaluating the requirement 0i32 } } diff --git a/tests/ui/new_without_default.fixed b/tests/ui/new_without_default.fixed index 5a6a92394a7f..277c335cd885 100644 --- a/tests/ui/new_without_default.fixed +++ b/tests/ui/new_without_default.fixed @@ -17,8 +17,8 @@ impl Default for Foo { impl Foo { pub fn new() -> Foo { - //~^ ERROR: you should consider adding a `Default` implementation for `Foo` - //~| NOTE: `-D clippy::new-without-default` implied by `-D warnings` + //~^ new_without_default + Foo } } @@ -33,7 +33,8 @@ impl Default for Bar { impl Bar { pub fn new() -> Self { - //~^ ERROR: you should consider adding a `Default` implementation for `Bar` + //~^ new_without_default + Bar } } @@ -104,7 +105,8 @@ impl<'c> Default for LtKo<'c> { impl<'c> LtKo<'c> { pub fn new() -> LtKo<'c> { - //~^ ERROR: you should consider adding a `Default` implementation for `LtKo<'c>` + //~^ new_without_default + unimplemented!() } } @@ -143,6 +145,7 @@ impl Default for Const { impl Const { pub const fn new() -> Const { + //~^ new_without_default Const } // While Default is not const, it can still call const functions, so we should lint this } @@ -209,7 +212,8 @@ impl Default for NewNotEqualToDerive { impl NewNotEqualToDerive { // This `new` implementation is not equal to a derived `Default`, so do not suggest deriving. pub fn new() -> Self { - //~^ ERROR: you should consider adding a `Default` implementation for `NewNotEqualToDe + //~^ new_without_default + NewNotEqualToDerive { foo: 1 } } } @@ -224,7 +228,8 @@ impl Default for FooGenerics { impl FooGenerics { pub fn new() -> Self { - //~^ ERROR: you should consider adding a `Default` implementation for `FooGenerics` + //~^ new_without_default + Self(Default::default()) } } @@ -238,7 +243,8 @@ impl Default for BarGenerics { impl BarGenerics { pub fn new() -> Self { - //~^ ERROR: you should consider adding a `Default` implementation for `BarGenerics` + //~^ new_without_default + Self(Default::default()) } } @@ -256,7 +262,8 @@ pub mod issue7220 { impl Foo { pub fn new() -> Self { - //~^ ERROR: you should consider adding a `Default` implementation for `Foo` + //~^ new_without_default + todo!() } } @@ -311,6 +318,7 @@ where K: std::hash::Hash + Eq + PartialEq, { pub fn new() -> Self { + //~^ new_without_default Self { _kv: None } } } diff --git a/tests/ui/new_without_default.rs b/tests/ui/new_without_default.rs index 12ea729253ac..f2844897c93d 100644 --- a/tests/ui/new_without_default.rs +++ b/tests/ui/new_without_default.rs @@ -11,8 +11,8 @@ pub struct Foo; impl Foo { pub fn new() -> Foo { - //~^ ERROR: you should consider adding a `Default` implementation for `Foo` - //~| NOTE: `-D clippy::new-without-default` implied by `-D warnings` + //~^ new_without_default + Foo } } @@ -21,7 +21,8 @@ pub struct Bar; impl Bar { pub fn new() -> Self { - //~^ ERROR: you should consider adding a `Default` implementation for `Bar` + //~^ new_without_default + Bar } } @@ -86,7 +87,8 @@ pub struct LtKo<'a> { impl<'c> LtKo<'c> { pub fn new() -> LtKo<'c> { - //~^ ERROR: you should consider adding a `Default` implementation for `LtKo<'c>` + //~^ new_without_default + unimplemented!() } } @@ -119,6 +121,7 @@ pub struct Const; impl Const { pub const fn new() -> Const { + //~^ new_without_default Const } // While Default is not const, it can still call const functions, so we should lint this } @@ -179,7 +182,8 @@ pub struct NewNotEqualToDerive { impl NewNotEqualToDerive { // This `new` implementation is not equal to a derived `Default`, so do not suggest deriving. pub fn new() -> Self { - //~^ ERROR: you should consider adding a `Default` implementation for `NewNotEqualToDe + //~^ new_without_default + NewNotEqualToDerive { foo: 1 } } } @@ -188,7 +192,8 @@ impl NewNotEqualToDerive { pub struct FooGenerics(std::marker::PhantomData); impl FooGenerics { pub fn new() -> Self { - //~^ ERROR: you should consider adding a `Default` implementation for `FooGenerics` + //~^ new_without_default + Self(Default::default()) } } @@ -196,7 +201,8 @@ impl FooGenerics { pub struct BarGenerics(std::marker::PhantomData); impl BarGenerics { pub fn new() -> Self { - //~^ ERROR: you should consider adding a `Default` implementation for `BarGenerics` + //~^ new_without_default + Self(Default::default()) } } @@ -208,7 +214,8 @@ pub mod issue7220 { impl Foo { pub fn new() -> Self { - //~^ ERROR: you should consider adding a `Default` implementation for `Foo` + //~^ new_without_default + todo!() } } @@ -254,6 +261,7 @@ where K: std::hash::Hash + Eq + PartialEq, { pub fn new() -> Self { + //~^ new_without_default Self { _kv: None } } } diff --git a/tests/ui/new_without_default.stderr b/tests/ui/new_without_default.stderr index 57bf4bd847cc..70a65aba464b 100644 --- a/tests/ui/new_without_default.stderr +++ b/tests/ui/new_without_default.stderr @@ -24,6 +24,7 @@ error: you should consider adding a `Default` implementation for `Bar` | LL | / pub fn new() -> Self { LL | | +LL | | LL | | Bar LL | | } | |_____^ @@ -38,10 +39,11 @@ LL + } | error: you should consider adding a `Default` implementation for `LtKo<'c>` - --> tests/ui/new_without_default.rs:88:5 + --> tests/ui/new_without_default.rs:89:5 | LL | / pub fn new() -> LtKo<'c> { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -56,9 +58,10 @@ LL + } | error: you should consider adding a `Default` implementation for `Const` - --> tests/ui/new_without_default.rs:121:5 + --> tests/ui/new_without_default.rs:123:5 | LL | / pub const fn new() -> Const { +LL | | LL | | Const LL | | } // While Default is not const, it can still call const functions, so we should lint this | |_____^ @@ -73,10 +76,11 @@ LL + } | error: you should consider adding a `Default` implementation for `NewNotEqualToDerive` - --> tests/ui/new_without_default.rs:181:5 + --> tests/ui/new_without_default.rs:184:5 | LL | / pub fn new() -> Self { LL | | +LL | | LL | | NewNotEqualToDerive { foo: 1 } LL | | } | |_____^ @@ -91,10 +95,11 @@ LL + } | error: you should consider adding a `Default` implementation for `FooGenerics` - --> tests/ui/new_without_default.rs:190:5 + --> tests/ui/new_without_default.rs:194:5 | LL | / pub fn new() -> Self { LL | | +LL | | LL | | Self(Default::default()) LL | | } | |_____^ @@ -109,10 +114,11 @@ LL + } | error: you should consider adding a `Default` implementation for `BarGenerics` - --> tests/ui/new_without_default.rs:198:5 + --> tests/ui/new_without_default.rs:203:5 | LL | / pub fn new() -> Self { LL | | +LL | | LL | | Self(Default::default()) LL | | } | |_____^ @@ -127,10 +133,11 @@ LL + } | error: you should consider adding a `Default` implementation for `Foo` - --> tests/ui/new_without_default.rs:210:9 + --> tests/ui/new_without_default.rs:216:9 | LL | / pub fn new() -> Self { LL | | +LL | | LL | | todo!() LL | | } | |_________^ @@ -147,9 +154,10 @@ LL ~ impl Foo { | error: you should consider adding a `Default` implementation for `MyStruct` - --> tests/ui/new_without_default.rs:256:5 + --> tests/ui/new_without_default.rs:263:5 | LL | / pub fn new() -> Self { +LL | | LL | | Self { _kv: None } LL | | } | |_____^ diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs index 0ea911c34348..703c2a3d9847 100644 --- a/tests/ui/no_effect.rs +++ b/tests/ui/no_effect.rs @@ -113,62 +113,88 @@ fn main() { let s = get_struct(); 0; - //~^ ERROR: statement with no effect + //~^ no_effect + Tuple(0); - //~^ ERROR: statement with no effect + //~^ no_effect + Struct { field: 0 }; - //~^ ERROR: statement with no effect + //~^ no_effect + Struct { ..s }; - //~^ ERROR: statement with no effect + //~^ no_effect + Union { a: 0 }; - //~^ ERROR: statement with no effect + //~^ no_effect + Enum::Tuple(0); - //~^ ERROR: statement with no effect + //~^ no_effect + Enum::Struct { field: 0 }; - //~^ ERROR: statement with no effect + //~^ no_effect + 5 + 6; - //~^ ERROR: statement with no effect + //~^ no_effect + *&42; - //~^ ERROR: statement with no effect + //~^ no_effect + &6; - //~^ ERROR: statement with no effect + //~^ no_effect + (5, 6, 7); - //~^ ERROR: statement with no effect + //~^ no_effect + ..; - //~^ ERROR: statement with no effect + //~^ no_effect + 5..; - //~^ ERROR: statement with no effect + //~^ no_effect + ..5; - //~^ ERROR: statement with no effect + //~^ no_effect + 5..6; - //~^ ERROR: statement with no effect + //~^ no_effect + 5..=6; - //~^ ERROR: statement with no effect + //~^ no_effect + [42, 55]; - //~^ ERROR: statement with no effect + //~^ no_effect + [42, 55][1]; - //~^ ERROR: statement with no effect + //~^ no_effect + (42, 55).1; - //~^ ERROR: statement with no effect + //~^ no_effect + [42; 55]; - //~^ ERROR: statement with no effect + //~^ no_effect + [42; 55][13]; - //~^ ERROR: statement with no effect + //~^ no_effect + let mut x = 0; || x += 5; - //~^ ERROR: statement with no effect + //~^ no_effect + let s: String = "foo".into(); FooString { s: s }; - //~^ ERROR: statement with no effect + //~^ no_effect + let _unused = 1; - //~^ ERROR: binding to `_` prefixed variable with no side-effect - //~| NOTE: `-D clippy::no-effect-underscore-binding` implied by `-D warnings` + //~^ no_effect_underscore_binding + let _penguin = || println!("Some helpful closure"); - //~^ ERROR: binding to `_` prefixed variable with no side-effect + //~^ no_effect_underscore_binding + let _duck = Struct { field: 0 }; - //~^ ERROR: binding to `_` prefixed variable with no side-effect + //~^ no_effect_underscore_binding + let _cat = [2, 4, 6, 8][2]; - //~^ ERROR: binding to `_` prefixed variable with no side-effect + //~^ no_effect_underscore_binding + let _issue_12166 = 42; let underscore_variable_above_can_be_used_dont_lint = _issue_12166; diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr index 48ec997d938c..58a9380cbfde 100644 --- a/tests/ui/no_effect.stderr +++ b/tests/ui/no_effect.stderr @@ -8,139 +8,139 @@ LL | 0; = help: to override `-D warnings` add `#[allow(clippy::no_effect)]` error: statement with no effect - --> tests/ui/no_effect.rs:117:5 + --> tests/ui/no_effect.rs:118:5 | LL | Tuple(0); | ^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:119:5 + --> tests/ui/no_effect.rs:121:5 | LL | Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:121:5 + --> tests/ui/no_effect.rs:124:5 | LL | Struct { ..s }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:123:5 + --> tests/ui/no_effect.rs:127:5 | LL | Union { a: 0 }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:125:5 + --> tests/ui/no_effect.rs:130:5 | LL | Enum::Tuple(0); | ^^^^^^^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:127:5 + --> tests/ui/no_effect.rs:133:5 | LL | Enum::Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:129:5 + --> tests/ui/no_effect.rs:136:5 | LL | 5 + 6; | ^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:131:5 + --> tests/ui/no_effect.rs:139:5 | LL | *&42; | ^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:133:5 + --> tests/ui/no_effect.rs:142:5 | LL | &6; | ^^^ error: statement with no effect - --> tests/ui/no_effect.rs:135:5 + --> tests/ui/no_effect.rs:145:5 | LL | (5, 6, 7); | ^^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:137:5 + --> tests/ui/no_effect.rs:148:5 | LL | ..; | ^^^ error: statement with no effect - --> tests/ui/no_effect.rs:139:5 + --> tests/ui/no_effect.rs:151:5 | LL | 5..; | ^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:141:5 + --> tests/ui/no_effect.rs:154:5 | LL | ..5; | ^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:143:5 + --> tests/ui/no_effect.rs:157:5 | LL | 5..6; | ^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:145:5 + --> tests/ui/no_effect.rs:160:5 | LL | 5..=6; | ^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:147:5 + --> tests/ui/no_effect.rs:163:5 | LL | [42, 55]; | ^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:149:5 + --> tests/ui/no_effect.rs:166:5 | LL | [42, 55][1]; | ^^^^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:151:5 + --> tests/ui/no_effect.rs:169:5 | LL | (42, 55).1; | ^^^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:153:5 + --> tests/ui/no_effect.rs:172:5 | LL | [42; 55]; | ^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:155:5 + --> tests/ui/no_effect.rs:175:5 | LL | [42; 55][13]; | ^^^^^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:158:5 + --> tests/ui/no_effect.rs:179:5 | LL | || x += 5; | ^^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:161:5 + --> tests/ui/no_effect.rs:183:5 | LL | FooString { s: s }; | ^^^^^^^^^^^^^^^^^^^ error: binding to `_` prefixed variable with no side-effect - --> tests/ui/no_effect.rs:163:9 + --> tests/ui/no_effect.rs:186:9 | LL | let _unused = 1; | ^^^^^^^ @@ -149,19 +149,19 @@ LL | let _unused = 1; = help: to override `-D warnings` add `#[allow(clippy::no_effect_underscore_binding)]` error: binding to `_` prefixed variable with no side-effect - --> tests/ui/no_effect.rs:166:9 + --> tests/ui/no_effect.rs:189:9 | LL | let _penguin = || println!("Some helpful closure"); | ^^^^^^^^ error: binding to `_` prefixed variable with no side-effect - --> tests/ui/no_effect.rs:168:9 + --> tests/ui/no_effect.rs:192:9 | LL | let _duck = Struct { field: 0 }; | ^^^^^ error: binding to `_` prefixed variable with no side-effect - --> tests/ui/no_effect.rs:170:9 + --> tests/ui/no_effect.rs:195:9 | LL | let _cat = [2, 4, 6, 8][2]; | ^^^^ diff --git a/tests/ui/no_effect_async_fn.rs b/tests/ui/no_effect_async_fn.rs index ef0f3d1df1ac..a036a7e27bef 100644 --- a/tests/ui/no_effect_async_fn.rs +++ b/tests/ui/no_effect_async_fn.rs @@ -11,14 +11,14 @@ impl AsyncTrait for Bar { // Shouldn't lint `binding to `_` prefixed variable with no side-effect` async fn bar(_i: u64) { let _a = 0; - //~^ ERROR: binding to `_` prefixed variable with no side-effect + //~^ no_effect_underscore_binding // Shouldn't lint `binding to `_` prefixed variable with no side-effect` let _b = num(); let _ = async { let _c = 0; - //~^ ERROR: binding to `_` prefixed variable with no side-effect + //~^ no_effect_underscore_binding // Shouldn't lint `binding to `_` prefixed variable with no side-effect` let _d = num(); @@ -30,14 +30,14 @@ impl AsyncTrait for Bar { // Shouldn't lint `binding to `_` prefixed variable with no side-effect` async fn foo(_i: u64) { let _a = 0; - //~^ ERROR: binding to `_` prefixed variable with no side-effect + //~^ no_effect_underscore_binding // Shouldn't lint `binding to `_` prefixed variable with no side-effect` let _b = num(); let _ = async { let _c = 0; - //~^ ERROR: binding to `_` prefixed variable with no side-effect + //~^ no_effect_underscore_binding // Shouldn't lint `binding to `_` prefixed variable with no side-effect` let _d = num(); diff --git a/tests/ui/no_effect_replace.rs b/tests/ui/no_effect_replace.rs index e4fd5caae2a5..245898f50740 100644 --- a/tests/ui/no_effect_replace.rs +++ b/tests/ui/no_effect_replace.rs @@ -2,30 +2,35 @@ fn main() { let _ = "12345".replace('1', "1"); - //~^ ERROR: replacing text with itself - //~| NOTE: `-D clippy::no-effect-replace` implied by `-D warnings` + //~^ no_effect_replace + let _ = "12345".replace("12", "12"); - //~^ ERROR: replacing text with itself + //~^ no_effect_replace + let _ = String::new().replace("12", "12"); - //~^ ERROR: replacing text with itself + //~^ no_effect_replace let _ = "12345".replacen('1', "1", 1); - //~^ ERROR: replacing text with itself + //~^ no_effect_replace + let _ = "12345".replacen("12", "12", 1); - //~^ ERROR: replacing text with itself + //~^ no_effect_replace + let _ = String::new().replacen("12", "12", 1); - //~^ ERROR: replacing text with itself + //~^ no_effect_replace let _ = "12345".replace("12", "22"); let _ = "12345".replacen("12", "22", 1); let mut x = X::default(); let _ = "hello".replace(&x.f(), &x.f()); - //~^ ERROR: replacing text with itself + //~^ no_effect_replace + let _ = "hello".replace(&x.f(), &x.ff()); let _ = "hello".replace(&y(), &y()); - //~^ ERROR: replacing text with itself + //~^ no_effect_replace + let _ = "hello".replace(&y(), &z()); let _ = Replaceme.replace("a", "a"); diff --git a/tests/ui/no_effect_replace.stderr b/tests/ui/no_effect_replace.stderr index ded86c5c5b8d..33d13b1d72e8 100644 --- a/tests/ui/no_effect_replace.stderr +++ b/tests/ui/no_effect_replace.stderr @@ -14,37 +14,37 @@ LL | let _ = "12345".replace("12", "12"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: replacing text with itself - --> tests/ui/no_effect_replace.rs:9:13 + --> tests/ui/no_effect_replace.rs:10:13 | LL | let _ = String::new().replace("12", "12"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: replacing text with itself - --> tests/ui/no_effect_replace.rs:12:13 + --> tests/ui/no_effect_replace.rs:13:13 | LL | let _ = "12345".replacen('1', "1", 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: replacing text with itself - --> tests/ui/no_effect_replace.rs:14:13 + --> tests/ui/no_effect_replace.rs:16:13 | LL | let _ = "12345".replacen("12", "12", 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: replacing text with itself - --> tests/ui/no_effect_replace.rs:16:13 + --> tests/ui/no_effect_replace.rs:19:13 | LL | let _ = String::new().replacen("12", "12", 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: replacing text with itself - --> tests/ui/no_effect_replace.rs:23:13 + --> tests/ui/no_effect_replace.rs:26:13 | LL | let _ = "hello".replace(&x.f(), &x.f()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: replacing text with itself - --> tests/ui/no_effect_replace.rs:27:13 + --> tests/ui/no_effect_replace.rs:31:13 | LL | let _ = "hello".replace(&y(), &y()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/no_effect_return.rs b/tests/ui/no_effect_return.rs index e46c0d73518b..4ba2fe07785d 100644 --- a/tests/ui/no_effect_return.rs +++ b/tests/ui/no_effect_return.rs @@ -7,8 +7,7 @@ use std::ops::ControlFlow; fn a() -> u32 { { 0u32; - //~^ ERROR: statement with no effect - //~| NOTE: `-D clippy::no-effect` implied by `-D warnings` + //~^ no_effect } 0 } @@ -16,7 +15,7 @@ fn a() -> u32 { async fn b() -> u32 { { 0u32; - //~^ ERROR: statement with no effect + //~^ no_effect } 0 } @@ -25,7 +24,7 @@ type C = i32; async fn c() -> C { { 0i32 as C; - //~^ ERROR: statement with no effect + //~^ no_effect } 0 } @@ -34,7 +33,8 @@ fn d() -> u128 { { // not last stmt 0u128; - //~^ ERROR: statement with no effect + //~^ no_effect + println!("lol"); } 0 @@ -44,7 +44,7 @@ fn e() -> u32 { { // mismatched types 0u16; - //~^ ERROR: statement with no effect + //~^ no_effect } 0 } @@ -52,7 +52,7 @@ fn e() -> u32 { fn f() -> [u16; 1] { { [1u16]; - //~^ ERROR: statement with no effect + //~^ no_effect } [1] } @@ -60,7 +60,7 @@ fn f() -> [u16; 1] { fn g() -> ControlFlow<()> { { ControlFlow::Break::<()>(()); - //~^ ERROR: statement with no effect + //~^ no_effect } ControlFlow::Continue(()) } @@ -78,7 +78,7 @@ fn i() -> () { { // does not suggest on function with explicit unit return type (); - //~^ ERROR: statement with no effect + //~^ no_effect } () } @@ -87,7 +87,7 @@ fn j() { { // does not suggest on function without explicit return type (); - //~^ ERROR: statement with no effect + //~^ no_effect } () } diff --git a/tests/ui/no_effect_return.stderr b/tests/ui/no_effect_return.stderr index 3cfe375d034a..e7bf7e4cd4f4 100644 --- a/tests/ui/no_effect_return.stderr +++ b/tests/ui/no_effect_return.stderr @@ -10,7 +10,7 @@ LL | 0u32; = help: to override `-D warnings` add `#[allow(clippy::no_effect)]` error: statement with no effect - --> tests/ui/no_effect_return.rs:18:9 + --> tests/ui/no_effect_return.rs:17:9 | LL | 0u32; | -^^^^ @@ -18,7 +18,7 @@ LL | 0u32; | help: did you mean to return it?: `return` error: statement with no effect - --> tests/ui/no_effect_return.rs:27:9 + --> tests/ui/no_effect_return.rs:26:9 | LL | 0i32 as C; | -^^^^^^^^^ @@ -26,7 +26,7 @@ LL | 0i32 as C; | help: did you mean to return it?: `return` error: statement with no effect - --> tests/ui/no_effect_return.rs:36:9 + --> tests/ui/no_effect_return.rs:35:9 | LL | 0u128; | ^^^^^^ diff --git a/tests/ui/no_mangle_with_rust_abi.rs b/tests/ui/no_mangle_with_rust_abi.rs index 8be149d18637..0d09b3ceecde 100644 --- a/tests/ui/no_mangle_with_rust_abi.rs +++ b/tests/ui/no_mangle_with_rust_abi.rs @@ -4,28 +4,27 @@ #[unsafe(no_mangle)] fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {} -//~^ ERROR: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI -//~| NOTE: `-D clippy::no-mangle-with-rust-abi` implied by `-D warnings` +//~^ no_mangle_with_rust_abi #[unsafe(no_mangle)] pub fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {} -//~^ ERROR: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI +//~^ no_mangle_with_rust_abi /// # Safety /// This function shouldn't be called unless the horsemen are ready #[unsafe(no_mangle)] pub unsafe fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {} -//~^ ERROR: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI +//~^ no_mangle_with_rust_abi /// # Safety /// This function shouldn't be called unless the horsemen are ready #[unsafe(no_mangle)] unsafe fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {} -//~^ ERROR: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI +//~^ no_mangle_with_rust_abi #[unsafe(no_mangle)] fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines( - //~^ ERROR: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI + //~^ no_mangle_with_rust_abi arg_one: u32, arg_two: usize, ) -> u32 { @@ -51,6 +50,7 @@ extern "C" { mod r#fn { #[unsafe(no_mangle)] pub(in super::r#fn) fn with_some_fn_around() {} + //~^ no_mangle_with_rust_abi } fn main() { diff --git a/tests/ui/no_mangle_with_rust_abi.stderr b/tests/ui/no_mangle_with_rust_abi.stderr index a00ebe5e1ac7..871f38e94b63 100644 --- a/tests/ui/no_mangle_with_rust_abi.stderr +++ b/tests/ui/no_mangle_with_rust_abi.stderr @@ -16,7 +16,7 @@ LL | extern "Rust" fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {} | +++++++++++++ error: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI - --> tests/ui/no_mangle_with_rust_abi.rs:11:1 + --> tests/ui/no_mangle_with_rust_abi.rs:10:1 | LL | pub fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -31,7 +31,7 @@ LL | pub extern "Rust" fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {} | +++++++++++++ error: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI - --> tests/ui/no_mangle_with_rust_abi.rs:17:1 + --> tests/ui/no_mangle_with_rust_abi.rs:16:1 | LL | pub unsafe fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -46,7 +46,7 @@ LL | pub unsafe extern "Rust" fn rust_abi_fn_three(arg_one: u32, arg_two: usize) | +++++++++++++ error: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI - --> tests/ui/no_mangle_with_rust_abi.rs:23:1 + --> tests/ui/no_mangle_with_rust_abi.rs:22:1 | LL | unsafe fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL | unsafe extern "Rust" fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {} | +++++++++++++ error: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI - --> tests/ui/no_mangle_with_rust_abi.rs:27:1 + --> tests/ui/no_mangle_with_rust_abi.rs:26:1 | LL | / fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines( LL | | @@ -80,7 +80,7 @@ LL | extern "Rust" fn rust_abi_multiline_function_really_long_name_to_overflow_a | +++++++++++++ error: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI - --> tests/ui/no_mangle_with_rust_abi.rs:53:5 + --> tests/ui/no_mangle_with_rust_abi.rs:52:5 | LL | pub(in super::r#fn) fn with_some_fn_around() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/no_mangle_with_rust_abi_2021.rs b/tests/ui/no_mangle_with_rust_abi_2021.rs index c7c973353480..3d5c70cad2f3 100644 --- a/tests/ui/no_mangle_with_rust_abi_2021.rs +++ b/tests/ui/no_mangle_with_rust_abi_2021.rs @@ -8,28 +8,27 @@ #[no_mangle] fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {} -//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI -//~| NOTE: `-D clippy::no-mangle-with-rust-abi` implied by `-D warnings` +//~^ no_mangle_with_rust_abi #[no_mangle] pub fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {} -//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI +//~^ no_mangle_with_rust_abi /// # Safety /// This function shouldn't be called unless the horsemen are ready #[no_mangle] pub unsafe fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {} -//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI +//~^ no_mangle_with_rust_abi /// # Safety /// This function shouldn't be called unless the horsemen are ready #[no_mangle] unsafe fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {} -//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI +//~^ no_mangle_with_rust_abi #[no_mangle] fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines( - //~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI + //~^ no_mangle_with_rust_abi arg_one: u32, arg_two: usize, ) -> u32 { diff --git a/tests/ui/no_mangle_with_rust_abi_2021.stderr b/tests/ui/no_mangle_with_rust_abi_2021.stderr index 15075be72d0b..abae8fafbeee 100644 --- a/tests/ui/no_mangle_with_rust_abi_2021.stderr +++ b/tests/ui/no_mangle_with_rust_abi_2021.stderr @@ -16,7 +16,7 @@ LL | extern "Rust" fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {} | +++++++++++++ error: `#[no_mangle]` set on a function with the default (`Rust`) ABI - --> tests/ui/no_mangle_with_rust_abi_2021.rs:15:1 + --> tests/ui/no_mangle_with_rust_abi_2021.rs:14:1 | LL | pub fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -31,7 +31,7 @@ LL | pub extern "Rust" fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {} | +++++++++++++ error: `#[no_mangle]` set on a function with the default (`Rust`) ABI - --> tests/ui/no_mangle_with_rust_abi_2021.rs:21:1 + --> tests/ui/no_mangle_with_rust_abi_2021.rs:20:1 | LL | pub unsafe fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -46,7 +46,7 @@ LL | pub unsafe extern "Rust" fn rust_abi_fn_three(arg_one: u32, arg_two: usize) | +++++++++++++ error: `#[no_mangle]` set on a function with the default (`Rust`) ABI - --> tests/ui/no_mangle_with_rust_abi_2021.rs:27:1 + --> tests/ui/no_mangle_with_rust_abi_2021.rs:26:1 | LL | unsafe fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL | unsafe extern "Rust" fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {} | +++++++++++++ error: `#[no_mangle]` set on a function with the default (`Rust`) ABI - --> tests/ui/no_mangle_with_rust_abi_2021.rs:31:1 + --> tests/ui/no_mangle_with_rust_abi_2021.rs:30:1 | LL | / fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines( LL | | diff --git a/tests/ui/non_canonical_clone_impl.rs b/tests/ui/non_canonical_clone_impl.rs index a36c7ed44c24..7d101915517f 100644 --- a/tests/ui/non_canonical_clone_impl.rs +++ b/tests/ui/non_canonical_clone_impl.rs @@ -12,10 +12,12 @@ struct A(u32); impl Clone for A { fn clone(&self) -> Self { + //~^ non_canonical_clone_impl Self(self.0) } fn clone_from(&mut self, source: &Self) { + //~^ non_canonical_clone_impl source.clone(); *self = source.clone(); } @@ -83,10 +85,12 @@ struct F(u32); impl Clone for F { fn clone(&self) -> Self { + //~^ non_canonical_clone_impl Self(self.0) } fn clone_from(&mut self, source: &Self) { + //~^ non_canonical_clone_impl source.clone(); *self = source.clone(); } diff --git a/tests/ui/non_canonical_clone_impl.stderr b/tests/ui/non_canonical_clone_impl.stderr index f7cad58150f7..550098452717 100644 --- a/tests/ui/non_canonical_clone_impl.stderr +++ b/tests/ui/non_canonical_clone_impl.stderr @@ -3,6 +3,7 @@ error: non-canonical implementation of `clone` on a `Copy` type | LL | fn clone(&self) -> Self { | _____________________________^ +LL | | LL | | Self(self.0) LL | | } | |_____^ help: change this to: `{ *self }` @@ -11,27 +12,30 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::non_canonical_clone_impl)]` error: unnecessary implementation of `clone_from` on a `Copy` type - --> tests/ui/non_canonical_clone_impl.rs:18:5 + --> tests/ui/non_canonical_clone_impl.rs:19:5 | LL | / fn clone_from(&mut self, source: &Self) { +LL | | LL | | source.clone(); LL | | *self = source.clone(); LL | | } | |_____^ help: remove it error: non-canonical implementation of `clone` on a `Copy` type - --> tests/ui/non_canonical_clone_impl.rs:85:29 + --> tests/ui/non_canonical_clone_impl.rs:87:29 | LL | fn clone(&self) -> Self { | _____________________________^ +LL | | LL | | Self(self.0) LL | | } | |_____^ help: change this to: `{ *self }` error: unnecessary implementation of `clone_from` on a `Copy` type - --> tests/ui/non_canonical_clone_impl.rs:89:5 + --> tests/ui/non_canonical_clone_impl.rs:92:5 | LL | / fn clone_from(&mut self, source: &Self) { +LL | | LL | | source.clone(); LL | | *self = source.clone(); LL | | } diff --git a/tests/ui/non_canonical_partial_ord_impl.fixed b/tests/ui/non_canonical_partial_ord_impl.fixed index d444a753697f..8774c666db11 100644 --- a/tests/ui/non_canonical_partial_ord_impl.fixed +++ b/tests/ui/non_canonical_partial_ord_impl.fixed @@ -14,6 +14,7 @@ impl Ord for A { } impl PartialOrd for A { + //~^ non_canonical_partial_ord_impl fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } @@ -46,6 +47,7 @@ impl Ord for C { } impl PartialOrd for C { + //~^ non_canonical_partial_ord_impl fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } diff --git a/tests/ui/non_canonical_partial_ord_impl.rs b/tests/ui/non_canonical_partial_ord_impl.rs index dc6c4354604d..568b97c8fff7 100644 --- a/tests/ui/non_canonical_partial_ord_impl.rs +++ b/tests/ui/non_canonical_partial_ord_impl.rs @@ -14,6 +14,7 @@ impl Ord for A { } impl PartialOrd for A { + //~^ non_canonical_partial_ord_impl fn partial_cmp(&self, other: &Self) -> Option { todo!(); } @@ -48,6 +49,7 @@ impl Ord for C { } impl PartialOrd for C { + //~^ non_canonical_partial_ord_impl fn partial_cmp(&self, _: &Self) -> Option { todo!(); } diff --git a/tests/ui/non_canonical_partial_ord_impl.stderr b/tests/ui/non_canonical_partial_ord_impl.stderr index 9f0c2ec43015..86845df4ea90 100644 --- a/tests/ui/non_canonical_partial_ord_impl.stderr +++ b/tests/ui/non_canonical_partial_ord_impl.stderr @@ -2,6 +2,7 @@ error: non-canonical implementation of `partial_cmp` on an `Ord` type --> tests/ui/non_canonical_partial_ord_impl.rs:16:1 | LL | / impl PartialOrd for A { +LL | | LL | | fn partial_cmp(&self, other: &Self) -> Option { | | _____________________________________________________________- LL | || todo!(); @@ -14,9 +15,10 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::non_canonical_partial_ord_impl)]` error: non-canonical implementation of `partial_cmp` on an `Ord` type - --> tests/ui/non_canonical_partial_ord_impl.rs:50:1 + --> tests/ui/non_canonical_partial_ord_impl.rs:51:1 | LL | / impl PartialOrd for C { +LL | | LL | | fn partial_cmp(&self, _: &Self) -> Option { LL | | todo!(); LL | | } diff --git a/tests/ui/non_canonical_partial_ord_impl_fully_qual.rs b/tests/ui/non_canonical_partial_ord_impl_fully_qual.rs index 2f8d5cf30c77..99cd7ebac60c 100644 --- a/tests/ui/non_canonical_partial_ord_impl_fully_qual.rs +++ b/tests/ui/non_canonical_partial_ord_impl_fully_qual.rs @@ -21,6 +21,7 @@ impl cmp::Ord for A { } impl PartialOrd for A { + //~^ non_canonical_partial_ord_impl fn partial_cmp(&self, other: &Self) -> Option { // NOTE: This suggestion is wrong, as `Ord` is not in scope. But this should be fine as it isn't // automatically applied @@ -44,6 +45,7 @@ impl cmp::Ord for B { } impl PartialOrd for B { + //~^ non_canonical_partial_ord_impl fn partial_cmp(&self, other: &Self) -> Option { // This calls `B.cmp`, not `Ord::cmp`! Some(self.cmp(other)) diff --git a/tests/ui/non_canonical_partial_ord_impl_fully_qual.stderr b/tests/ui/non_canonical_partial_ord_impl_fully_qual.stderr index 8dd7face6ef4..392b81dc8d74 100644 --- a/tests/ui/non_canonical_partial_ord_impl_fully_qual.stderr +++ b/tests/ui/non_canonical_partial_ord_impl_fully_qual.stderr @@ -2,6 +2,7 @@ error: non-canonical implementation of `partial_cmp` on an `Ord` type --> tests/ui/non_canonical_partial_ord_impl_fully_qual.rs:23:1 | LL | / impl PartialOrd for A { +LL | | LL | | fn partial_cmp(&self, other: &Self) -> Option { | | _____________________________________________________________- LL | || // NOTE: This suggestion is wrong, as `Ord` is not in scope. But this should be fine as it isn't @@ -16,9 +17,10 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::non_canonical_partial_ord_impl)]` error: non-canonical implementation of `partial_cmp` on an `Ord` type - --> tests/ui/non_canonical_partial_ord_impl_fully_qual.rs:46:1 + --> tests/ui/non_canonical_partial_ord_impl_fully_qual.rs:47:1 | LL | / impl PartialOrd for B { +LL | | LL | | fn partial_cmp(&self, other: &Self) -> Option { | | _____________________________________________________________- LL | || // This calls `B.cmp`, not `Ord::cmp`! diff --git a/tests/ui/non_expressive_names.rs b/tests/ui/non_expressive_names.rs index 987a4775ef07..b772c754f8b7 100644 --- a/tests/ui/non_expressive_names.rs +++ b/tests/ui/non_expressive_names.rs @@ -25,9 +25,12 @@ impl MaybeInst { } fn underscores_and_numbers() { - let _1 = 1; //~ERROR: consider choosing a more descriptive name - let ____1 = 1; //~ERROR: consider choosing a more descriptive name - let __1___2 = 12; //~ERROR: consider choosing a more descriptive name + let _1 = 1; + //~^ just_underscores_and_digits + let ____1 = 1; + //~^ just_underscores_and_digits + let __1___2 = 12; + //~^ just_underscores_and_digits let _1_ok = 1; } @@ -48,9 +51,12 @@ struct Bar; impl Bar { fn bar() { - let _1 = 1; //~ERROR: consider choosing a more descriptive name - let ____1 = 1; //~ERROR: consider choosing a more descriptive name - let __1___2 = 12; //~ERROR: consider choosing a more descriptive name + let _1 = 1; + //~^ just_underscores_and_digits + let ____1 = 1; + //~^ just_underscores_and_digits + let __1___2 = 12; + //~^ just_underscores_and_digits let _1_ok = 1; } } diff --git a/tests/ui/non_expressive_names.stderr b/tests/ui/non_expressive_names.stderr index d9c745f466b7..3bd77a730fe7 100644 --- a/tests/ui/non_expressive_names.stderr +++ b/tests/ui/non_expressive_names.stderr @@ -8,31 +8,31 @@ LL | let _1 = 1; = help: to override `-D warnings` add `#[allow(clippy::just_underscores_and_digits)]` error: consider choosing a more descriptive name - --> tests/ui/non_expressive_names.rs:29:9 + --> tests/ui/non_expressive_names.rs:30:9 | LL | let ____1 = 1; | ^^^^^ error: consider choosing a more descriptive name - --> tests/ui/non_expressive_names.rs:30:9 + --> tests/ui/non_expressive_names.rs:32:9 | LL | let __1___2 = 12; | ^^^^^^^ error: consider choosing a more descriptive name - --> tests/ui/non_expressive_names.rs:51:13 + --> tests/ui/non_expressive_names.rs:54:13 | LL | let _1 = 1; | ^^ error: consider choosing a more descriptive name - --> tests/ui/non_expressive_names.rs:52:13 + --> tests/ui/non_expressive_names.rs:56:13 | LL | let ____1 = 1; | ^^^^^ error: consider choosing a more descriptive name - --> tests/ui/non_expressive_names.rs:53:13 + --> tests/ui/non_expressive_names.rs:58:13 | LL | let __1___2 = 12; | ^^^^^^^ diff --git a/tests/ui/non_minimal_cfg.fixed b/tests/ui/non_minimal_cfg.fixed index 2fcecab452b8..a2b69d0662ee 100644 --- a/tests/ui/non_minimal_cfg.fixed +++ b/tests/ui/non_minimal_cfg.fixed @@ -1,12 +1,16 @@ #![allow(unused)] #[cfg(windows)] +//~^ non_minimal_cfg fn hermit() {} #[cfg(windows)] +//~^ non_minimal_cfg fn wasi() {} #[cfg(all(unix, not(windows)))] +//~^ non_minimal_cfg +//~| non_minimal_cfg fn the_end() {} #[cfg(any())] diff --git a/tests/ui/non_minimal_cfg.rs b/tests/ui/non_minimal_cfg.rs index e3ce11b73336..7178cd189c08 100644 --- a/tests/ui/non_minimal_cfg.rs +++ b/tests/ui/non_minimal_cfg.rs @@ -1,12 +1,16 @@ #![allow(unused)] #[cfg(all(windows))] +//~^ non_minimal_cfg fn hermit() {} #[cfg(any(windows))] +//~^ non_minimal_cfg fn wasi() {} #[cfg(all(any(unix), all(not(windows))))] +//~^ non_minimal_cfg +//~| non_minimal_cfg fn the_end() {} #[cfg(any())] diff --git a/tests/ui/non_minimal_cfg.stderr b/tests/ui/non_minimal_cfg.stderr index 707ff51d430c..3bf306dd89c2 100644 --- a/tests/ui/non_minimal_cfg.stderr +++ b/tests/ui/non_minimal_cfg.stderr @@ -8,19 +8,19 @@ LL | #[cfg(all(windows))] = help: to override `-D warnings` add `#[allow(clippy::non_minimal_cfg)]` error: unneeded sub `cfg` when there is only one condition - --> tests/ui/non_minimal_cfg.rs:6:7 + --> tests/ui/non_minimal_cfg.rs:7:7 | LL | #[cfg(any(windows))] | ^^^^^^^^^^^^ help: try: `windows` error: unneeded sub `cfg` when there is only one condition - --> tests/ui/non_minimal_cfg.rs:9:11 + --> tests/ui/non_minimal_cfg.rs:11:11 | LL | #[cfg(all(any(unix), all(not(windows))))] | ^^^^^^^^^ help: try: `unix` error: unneeded sub `cfg` when there is only one condition - --> tests/ui/non_minimal_cfg.rs:9:22 + --> tests/ui/non_minimal_cfg.rs:11:22 | LL | #[cfg(all(any(unix), all(not(windows))))] | ^^^^^^^^^^^^^^^^^ help: try: `not(windows)` diff --git a/tests/ui/non_minimal_cfg2.rs b/tests/ui/non_minimal_cfg2.rs index f9e3ba4dacda..d073feedb1da 100644 --- a/tests/ui/non_minimal_cfg2.rs +++ b/tests/ui/non_minimal_cfg2.rs @@ -1,3 +1,4 @@ +//@require-annotations-for-level: WARN #![allow(unused)] #[cfg(all())] diff --git a/tests/ui/non_minimal_cfg2.stderr b/tests/ui/non_minimal_cfg2.stderr index 6d86e931edce..169d2989aa13 100644 --- a/tests/ui/non_minimal_cfg2.stderr +++ b/tests/ui/non_minimal_cfg2.stderr @@ -1,5 +1,5 @@ error: unneeded sub `cfg` when there is no condition - --> tests/ui/non_minimal_cfg2.rs:3:7 + --> tests/ui/non_minimal_cfg2.rs:4:7 | LL | #[cfg(all())] | ^^^^^ diff --git a/tests/ui/non_octal_unix_permissions.fixed b/tests/ui/non_octal_unix_permissions.fixed index f68d5e30d27e..83f8991c94f8 100644 --- a/tests/ui/non_octal_unix_permissions.fixed +++ b/tests/ui/non_octal_unix_permissions.fixed @@ -10,11 +10,13 @@ fn main() { // OpenOptionsExt::mode let mut options = OpenOptions::new(); options.mode(0o440); + //~^ non_octal_unix_permissions options.mode(0o400); options.mode(permissions); // PermissionsExt::from_mode let _permissions = Permissions::from_mode(0o647); + //~^ non_octal_unix_permissions let _permissions = Permissions::from_mode(0o000); let _permissions = Permissions::from_mode(permissions); @@ -24,6 +26,7 @@ fn main() { let mut permissions = metadata.permissions(); permissions.set_mode(0o644); + //~^ non_octal_unix_permissions permissions.set_mode(0o704); // no error permissions.set_mode(0b111_000_100); @@ -31,6 +34,7 @@ fn main() { // DirBuilderExt::mode let mut builder = DirBuilder::new(); builder.mode(0o755); + //~^ non_octal_unix_permissions builder.mode(0o406); // no error permissions.set_mode(0b111000100); diff --git a/tests/ui/non_octal_unix_permissions.rs b/tests/ui/non_octal_unix_permissions.rs index 647c3769d2c3..ba1ee10a2787 100644 --- a/tests/ui/non_octal_unix_permissions.rs +++ b/tests/ui/non_octal_unix_permissions.rs @@ -10,11 +10,13 @@ fn main() { // OpenOptionsExt::mode let mut options = OpenOptions::new(); options.mode(440); + //~^ non_octal_unix_permissions options.mode(0o400); options.mode(permissions); // PermissionsExt::from_mode let _permissions = Permissions::from_mode(647); + //~^ non_octal_unix_permissions let _permissions = Permissions::from_mode(0o000); let _permissions = Permissions::from_mode(permissions); @@ -24,6 +26,7 @@ fn main() { let mut permissions = metadata.permissions(); permissions.set_mode(644); + //~^ non_octal_unix_permissions permissions.set_mode(0o704); // no error permissions.set_mode(0b111_000_100); @@ -31,6 +34,7 @@ fn main() { // DirBuilderExt::mode let mut builder = DirBuilder::new(); builder.mode(755); + //~^ non_octal_unix_permissions builder.mode(0o406); // no error permissions.set_mode(0b111000100); diff --git a/tests/ui/non_octal_unix_permissions.stderr b/tests/ui/non_octal_unix_permissions.stderr index 890b308a1dc5..9027617c813a 100644 --- a/tests/ui/non_octal_unix_permissions.stderr +++ b/tests/ui/non_octal_unix_permissions.stderr @@ -8,19 +8,19 @@ LL | options.mode(440); = help: to override `-D warnings` add `#[allow(clippy::non_octal_unix_permissions)]` error: using a non-octal value to set unix file permissions - --> tests/ui/non_octal_unix_permissions.rs:17:47 + --> tests/ui/non_octal_unix_permissions.rs:18:47 | LL | let _permissions = Permissions::from_mode(647); | ^^^ help: consider using an octal literal instead: `0o647` error: using a non-octal value to set unix file permissions - --> tests/ui/non_octal_unix_permissions.rs:26:26 + --> tests/ui/non_octal_unix_permissions.rs:28:26 | LL | permissions.set_mode(644); | ^^^ help: consider using an octal literal instead: `0o644` error: using a non-octal value to set unix file permissions - --> tests/ui/non_octal_unix_permissions.rs:33:18 + --> tests/ui/non_octal_unix_permissions.rs:36:18 | LL | builder.mode(755); | ^^^ help: consider using an octal literal instead: `0o755` diff --git a/tests/ui/non_std_lazy_static/non_std_lazy_static_no_std.rs b/tests/ui/non_std_lazy_static/non_std_lazy_static_no_std.rs index 6208612c6983..1170696b2030 100644 --- a/tests/ui/non_std_lazy_static/non_std_lazy_static_no_std.rs +++ b/tests/ui/non_std_lazy_static/non_std_lazy_static_no_std.rs @@ -1,3 +1,4 @@ +//@ check-pass //@aux-build:once_cell.rs //@aux-build:lazy_static.rs diff --git a/tests/ui/non_std_lazy_static/non_std_lazy_static_other_once_cell.rs b/tests/ui/non_std_lazy_static/non_std_lazy_static_other_once_cell.rs index 8701a4b7729a..f6d4f7250915 100644 --- a/tests/ui/non_std_lazy_static/non_std_lazy_static_other_once_cell.rs +++ b/tests/ui/non_std_lazy_static/non_std_lazy_static_other_once_cell.rs @@ -1,3 +1,4 @@ +//@ check-pass //@aux-build:once_cell.rs #![warn(clippy::non_std_lazy_statics)] diff --git a/tests/ui/non_zero_suggestions.fixed b/tests/ui/non_zero_suggestions.fixed index e67c992fdde0..4573896ecd67 100644 --- a/tests/ui/non_zero_suggestions.fixed +++ b/tests/ui/non_zero_suggestions.fixed @@ -7,19 +7,19 @@ fn main() { let x: u64 = 100; let y = NonZeroU32::new(10).unwrap(); let r1 = x / NonZeroU64::from(y); - //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion + //~^ non_zero_suggestions let r2 = x % NonZeroU64::from(y); - //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion + //~^ non_zero_suggestions // U16 -> U32 let a: u32 = 50; let b = NonZeroU16::new(5).unwrap(); let r3 = a / NonZeroU32::from(b); - //~^ ERROR: consider using `NonZeroU32::from()` for more efficient and type-safe conversion + //~^ non_zero_suggestions let x = NonZeroU64::from(NonZeroU32::new(5).unwrap()); - //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion + //~^ non_zero_suggestions /// Negative test cases (lint should not trigger) // Left hand side expressions should not be triggered @@ -50,7 +50,7 @@ fn main() { // Additional function to test the lint in a different context fn divide_numbers(x: u64, y: NonZeroU32) -> u64 { x / NonZeroU64::from(y) - //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion + //~^ non_zero_suggestions } struct Calculator { @@ -60,6 +60,6 @@ struct Calculator { impl Calculator { fn divide(&self, divisor: NonZeroU32) -> u64 { self.value / NonZeroU64::from(divisor) - //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion + //~^ non_zero_suggestions } } diff --git a/tests/ui/non_zero_suggestions.rs b/tests/ui/non_zero_suggestions.rs index de82371a8f29..3e7081e0c1c0 100644 --- a/tests/ui/non_zero_suggestions.rs +++ b/tests/ui/non_zero_suggestions.rs @@ -7,19 +7,19 @@ fn main() { let x: u64 = 100; let y = NonZeroU32::new(10).unwrap(); let r1 = x / u64::from(y.get()); - //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion + //~^ non_zero_suggestions let r2 = x % u64::from(y.get()); - //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion + //~^ non_zero_suggestions // U16 -> U32 let a: u32 = 50; let b = NonZeroU16::new(5).unwrap(); let r3 = a / u32::from(b.get()); - //~^ ERROR: consider using `NonZeroU32::from()` for more efficient and type-safe conversion + //~^ non_zero_suggestions let x = u64::from(NonZeroU32::new(5).unwrap().get()); - //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion + //~^ non_zero_suggestions /// Negative test cases (lint should not trigger) // Left hand side expressions should not be triggered @@ -50,7 +50,7 @@ fn main() { // Additional function to test the lint in a different context fn divide_numbers(x: u64, y: NonZeroU32) -> u64 { x / u64::from(y.get()) - //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion + //~^ non_zero_suggestions } struct Calculator { @@ -60,6 +60,6 @@ struct Calculator { impl Calculator { fn divide(&self, divisor: NonZeroU32) -> u64 { self.value / u64::from(divisor.get()) - //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion + //~^ non_zero_suggestions } } diff --git a/tests/ui/non_zero_suggestions_unfixable.rs b/tests/ui/non_zero_suggestions_unfixable.rs index 193c710e589f..1224356236c7 100644 --- a/tests/ui/non_zero_suggestions_unfixable.rs +++ b/tests/ui/non_zero_suggestions_unfixable.rs @@ -4,11 +4,12 @@ use std::num::{NonZeroI8, NonZeroI16, NonZeroU8, NonZeroU16, NonZeroU32, NonZero fn main() { let x: u64 = u64::from(NonZeroU32::new(5).unwrap().get()); - //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion + //~^ non_zero_suggestions let n = NonZeroU32::new(20).unwrap(); let y = u64::from(n.get()); - //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion + //~^ non_zero_suggestions + some_fn_that_only_takes_u64(y); let m = NonZeroU32::try_from(1).unwrap(); @@ -17,7 +18,7 @@ fn main() { fn return_non_zero(x: u64, y: NonZeroU32) -> u64 { u64::from(y.get()) - //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion + //~^ non_zero_suggestions } fn some_fn_that_only_takes_u64(_: u64) {} diff --git a/tests/ui/non_zero_suggestions_unfixable.stderr b/tests/ui/non_zero_suggestions_unfixable.stderr index 787179f2a2d6..d2ac983d4f7f 100644 --- a/tests/ui/non_zero_suggestions_unfixable.stderr +++ b/tests/ui/non_zero_suggestions_unfixable.stderr @@ -14,7 +14,7 @@ LL | let y = u64::from(n.get()); | ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(n)` error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion - --> tests/ui/non_zero_suggestions_unfixable.rs:19:5 + --> tests/ui/non_zero_suggestions_unfixable.rs:20:5 | LL | u64::from(y.get()) | ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(y)` diff --git a/tests/ui/nonminimal_bool.rs b/tests/ui/nonminimal_bool.rs index 52b0155a762e..a155ff3508be 100644 --- a/tests/ui/nonminimal_bool.rs +++ b/tests/ui/nonminimal_bool.rs @@ -15,23 +15,28 @@ fn main() { let d: bool = unimplemented!(); let e: bool = unimplemented!(); let _ = !true; - //~^ ERROR: this boolean expression can be simplified - //~| NOTE: `-D clippy::nonminimal-bool` implied by `-D warnings` + //~^ nonminimal_bool + let _ = !false; - //~^ ERROR: this boolean expression can be simplified + //~^ nonminimal_bool + let _ = !!a; - //~^ ERROR: this boolean expression can be simplified + //~^ nonminimal_bool + let _ = false || a; - //~^ ERROR: this boolean expression can be simplified + //~^ nonminimal_bool + // don't lint on cfgs let _ = cfg!(you_shall_not_not_pass) && a; let _ = a || !b || !c || !d || !e; let _ = !(!a && b); - //~^ ERROR: this boolean expression can be simplified + //~^ nonminimal_bool + let _ = !(!a || b); - //~^ ERROR: this boolean expression can be simplified + //~^ nonminimal_bool + let _ = !a && !(b && c); - //~^ ERROR: this boolean expression can be simplified + //~^ nonminimal_bool } fn equality_stuff() { @@ -40,15 +45,19 @@ fn equality_stuff() { let c: i32 = unimplemented!(); let d: i32 = unimplemented!(); let _ = a == b && c == 5 && a == b; - //~^ ERROR: this boolean expression can be simplified + //~^ nonminimal_bool + let _ = a == b || c == 5 || a == b; - //~^ ERROR: this boolean expression can be simplified + //~^ nonminimal_bool + let _ = a == b && c == 5 && b == a; - //~^ ERROR: this boolean expression can be simplified + //~^ nonminimal_bool + let _ = a != b || !(a != b || c == d); - //~^ ERROR: this boolean expression can be simplified + //~^ nonminimal_bool + let _ = a != b && !(a != b && c == d); - //~^ ERROR: this boolean expression can be simplified + //~^ nonminimal_bool } fn issue3847(a: u32, b: u32) -> bool { @@ -79,7 +88,8 @@ fn check_expect() { fn issue9428() { if matches!(true, true) && true { - //~^ ERROR: this boolean expression can be simplified + //~^ nonminimal_bool + println!("foo"); } } @@ -158,19 +168,35 @@ fn issue11932() { fn issue_5794() { let a = 0; - if !(12 == a) {} //~ ERROR: this boolean expression can be simplified - if !(a == 12) {} //~ ERROR: this boolean expression can be simplified - if !(12 != a) {} //~ ERROR: this boolean expression can be simplified - if !(a != 12) {} //~ ERROR: this boolean expression can be simplified + if !(12 == a) {} + //~^ nonminimal_bool + if !(a == 12) {} + //~^ nonminimal_bool + if !(12 != a) {} + //~^ nonminimal_bool + if !(a != 12) {} + //~^ nonminimal_bool let b = true; let c = false; - if !b == true {} //~ ERROR: this boolean expression can be simplified - if !b != true {} //~ ERROR: this boolean expression can be simplified - if true == !b {} //~ ERROR: this boolean expression can be simplified - if true != !b {} //~ ERROR: this boolean expression can be simplified - if !b == !c {} //~ ERROR: this boolean expression can be simplified - if !b != !c {} //~ ERROR: this boolean expression can be simplified + if !b == true {} + //~^ nonminimal_bool + //~| bool_comparison + //~| bool_comparison + if !b != true {} + //~^ nonminimal_bool + //~| bool_comparison + if true == !b {} + //~^ nonminimal_bool + //~| bool_comparison + //~| bool_comparison + if true != !b {} + //~^ nonminimal_bool + //~| bool_comparison + if !b == !c {} + //~^ nonminimal_bool + if !b != !c {} + //~^ nonminimal_bool } fn issue_12371(x: usize) -> bool { @@ -183,3 +209,10 @@ fn issue_12371(x: usize) -> bool { fn many_ops(a: bool, b: bool, c: bool, d: bool, e: bool, f: bool) -> bool { (a && c && f) || (!a && b && !d) || (!b && !c && !e) || (d && e && !f) } + +fn issue14184(a: f32, b: bool) { + if !(a < 2.0 && !b) { + //~^ nonminimal_bool + println!("Hi"); + } +} diff --git a/tests/ui/nonminimal_bool.stderr b/tests/ui/nonminimal_bool.stderr index 56d6eb10ac03..336cce40abf0 100644 --- a/tests/ui/nonminimal_bool.stderr +++ b/tests/ui/nonminimal_bool.stderr @@ -14,37 +14,37 @@ LL | let _ = !false; | ^^^^^^ help: try: `true` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:22:13 + --> tests/ui/nonminimal_bool.rs:23:13 | LL | let _ = !!a; | ^^^ help: try: `a` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:24:13 + --> tests/ui/nonminimal_bool.rs:26:13 | LL | let _ = false || a; | ^^^^^^^^^^ help: try: `a` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:29:13 + --> tests/ui/nonminimal_bool.rs:32:13 | LL | let _ = !(!a && b); | ^^^^^^^^^^ help: try: `a || !b` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:31:13 + --> tests/ui/nonminimal_bool.rs:35:13 | LL | let _ = !(!a || b); | ^^^^^^^^^^ help: try: `a && !b` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:33:13 + --> tests/ui/nonminimal_bool.rs:38:13 | LL | let _ = !a && !(b && c); | ^^^^^^^^^^^^^^^ help: try: `!(a || b && c)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:42:13 + --> tests/ui/nonminimal_bool.rs:47:13 | LL | let _ = a == b && c == 5 && a == b; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -59,7 +59,7 @@ LL + let _ = a == b && c == 5; | error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:44:13 + --> tests/ui/nonminimal_bool.rs:50:13 | LL | let _ = a == b || c == 5 || a == b; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -74,7 +74,7 @@ LL + let _ = a == b || c == 5; | error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:46:13 + --> tests/ui/nonminimal_bool.rs:53:13 | LL | let _ = a == b && c == 5 && b == a; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -89,7 +89,7 @@ LL + let _ = a == b && c == 5; | error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:48:13 + --> tests/ui/nonminimal_bool.rs:56:13 | LL | let _ = a != b || !(a != b || c == d); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -104,7 +104,7 @@ LL + let _ = a != b || c != d; | error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:50:13 + --> tests/ui/nonminimal_bool.rs:59:13 | LL | let _ = a != b && !(a != b && c == d); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -119,43 +119,43 @@ LL + let _ = a != b && c != d; | error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:81:8 + --> tests/ui/nonminimal_bool.rs:90:8 | LL | if matches!(true, true) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(true, true)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:161:8 + --> tests/ui/nonminimal_bool.rs:171:8 | LL | if !(12 == a) {} | ^^^^^^^^^^ help: try: `(12 != a)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:162:8 + --> tests/ui/nonminimal_bool.rs:173:8 | LL | if !(a == 12) {} | ^^^^^^^^^^ help: try: `(a != 12)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:163:8 + --> tests/ui/nonminimal_bool.rs:175:8 | LL | if !(12 != a) {} | ^^^^^^^^^^ help: try: `(12 == a)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:164:8 + --> tests/ui/nonminimal_bool.rs:177:8 | LL | if !(a != 12) {} | ^^^^^^^^^^ help: try: `(a == 12)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:168:8 + --> tests/ui/nonminimal_bool.rs:182:8 | LL | if !b == true {} | ^^^^^^^^^^ help: try: `b != true` error: this comparison might be written more concisely - --> tests/ui/nonminimal_bool.rs:168:8 + --> tests/ui/nonminimal_bool.rs:182:8 | LL | if !b == true {} | ^^^^^^^^^^ help: try simplifying it as shown: `b != true` @@ -164,64 +164,70 @@ LL | if !b == true {} = help: to override `-D warnings` add `#[allow(clippy::bool_comparison)]` error: equality checks against true are unnecessary - --> tests/ui/nonminimal_bool.rs:168:8 + --> tests/ui/nonminimal_bool.rs:182:8 | LL | if !b == true {} | ^^^^^^^^^^ help: try simplifying it as shown: `!b` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:169:8 + --> tests/ui/nonminimal_bool.rs:186:8 | LL | if !b != true {} | ^^^^^^^^^^ help: try: `b == true` error: inequality checks against true can be replaced by a negation - --> tests/ui/nonminimal_bool.rs:169:8 + --> tests/ui/nonminimal_bool.rs:186:8 | LL | if !b != true {} | ^^^^^^^^^^ help: try simplifying it as shown: `!(!b)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:170:8 + --> tests/ui/nonminimal_bool.rs:189:8 | LL | if true == !b {} | ^^^^^^^^^^ help: try: `true != b` error: this comparison might be written more concisely - --> tests/ui/nonminimal_bool.rs:170:8 + --> tests/ui/nonminimal_bool.rs:189:8 | LL | if true == !b {} | ^^^^^^^^^^ help: try simplifying it as shown: `true != b` error: equality checks against true are unnecessary - --> tests/ui/nonminimal_bool.rs:170:8 + --> tests/ui/nonminimal_bool.rs:189:8 | LL | if true == !b {} | ^^^^^^^^^^ help: try simplifying it as shown: `!b` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:171:8 + --> tests/ui/nonminimal_bool.rs:193:8 | LL | if true != !b {} | ^^^^^^^^^^ help: try: `true == b` error: inequality checks against true can be replaced by a negation - --> tests/ui/nonminimal_bool.rs:171:8 + --> tests/ui/nonminimal_bool.rs:193:8 | LL | if true != !b {} | ^^^^^^^^^^ help: try simplifying it as shown: `!(!b)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:172:8 + --> tests/ui/nonminimal_bool.rs:196:8 | LL | if !b == !c {} | ^^^^^^^^ help: try: `b == c` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:173:8 + --> tests/ui/nonminimal_bool.rs:198:8 | LL | if !b != !c {} | ^^^^^^^^ help: try: `b != c` -error: aborting due to 29 previous errors +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool.rs:214:8 + | +LL | if !(a < 2.0 && !b) { + | ^^^^^^^^^^^^^^^^ help: try: `!(a < 2.0) || b` + +error: aborting due to 30 previous errors diff --git a/tests/ui/nonminimal_bool_methods.fixed b/tests/ui/nonminimal_bool_methods.fixed index 65ccaaca8918..c2377491f25b 100644 --- a/tests/ui/nonminimal_bool_methods.fixed +++ b/tests/ui/nonminimal_bool_methods.fixed @@ -6,18 +6,27 @@ fn methods_with_negation() { let b: Result = unimplemented!(); let _ = a.is_some(); let _ = a.is_none(); + //~^ nonminimal_bool let _ = a.is_none(); let _ = a.is_some(); + //~^ nonminimal_bool let _ = b.is_err(); let _ = b.is_ok(); + //~^ nonminimal_bool let _ = b.is_ok(); let _ = b.is_err(); + //~^ nonminimal_bool let c = false; let _ = a.is_none() || c; + //~^ nonminimal_bool let _ = a.is_none() && c; + //~^ nonminimal_bool let _ = !(!c ^ c) || a.is_none(); + //~^ nonminimal_bool let _ = (!c ^ c) || a.is_none(); + //~^ nonminimal_bool let _ = !c ^ c || a.is_none(); + //~^ nonminimal_bool } // Simplified versions of https://github.com/rust-lang/rust-clippy/issues/2638 @@ -90,11 +99,15 @@ fn dont_warn_for_custom_methods_with_negation() { fn warn_for_built_in_methods_with_negation() { let res: Result = Ok(1); if res.is_err() {} + //~^ nonminimal_bool if res.is_ok() {} + //~^ nonminimal_bool let res = Some(1); if res.is_none() {} + //~^ nonminimal_bool if res.is_some() {} + //~^ nonminimal_bool } #[allow(clippy::neg_cmp_op_on_partial_ord)] @@ -110,24 +123,34 @@ fn dont_warn_for_negated_partial_ord_comparison() { fn issue_12625() { let a = 0; let b = 0; - if ((a as u64) < b) {} //~ ERROR: this boolean expression can be simplified - if ((a as u64) < b) {} //~ ERROR: this boolean expression can be simplified - if (a as u64 > b) {} //~ ERROR: this boolean expression can be simplified + if ((a as u64) < b) {} + //~^ nonminimal_bool + if ((a as u64) < b) {} + //~^ nonminimal_bool + if (a as u64 > b) {} + //~^ nonminimal_bool } fn issue_12761() { let a = 0; let b = 0; let c = 0; - if (a < b) as i32 == c {} //~ ERROR: this boolean expression can be simplified - if (a < b) | (a > c) {} //~ ERROR: this boolean expression can be simplified + if (a < b) as i32 == c {} + //~^ nonminimal_bool + if (a < b) | (a > c) {} + //~^ nonminimal_bool + //~| nonminimal_bool let opt: Option = Some(1); let res: Result = Ok(1); - if res.is_err() as i32 == c {} //~ ERROR: this boolean expression can be simplified - if res.is_err() | opt.is_some() {} //~ ERROR: this boolean expression can be simplified + if res.is_err() as i32 == c {} + //~^ nonminimal_bool + if res.is_err() | opt.is_some() {} + //~^ nonminimal_bool + //~| nonminimal_bool fn a(a: bool) -> bool { - (4 <= 3).b() //~ ERROR: this boolean expression can be simplified + (4 <= 3).b() + //~^ nonminimal_bool } trait B { @@ -152,12 +175,18 @@ fn issue_13436() { _ = opt.is_some_and(|x| x == 1000); _ = opt.is_some_and(|x| x != 1000); _ = opt.is_some_and(not_zero); - _ = opt.is_none_or(|x| x >= 1000); //~ ERROR: this boolean expression can be simplified - _ = opt.is_none_or(|x| x > 1000); //~ ERROR: this boolean expression can be simplified - _ = opt.is_none_or(|x| x <= 1000); //~ ERROR: this boolean expression can be simplified - _ = opt.is_none_or(|x| x < 1000); //~ ERROR: this boolean expression can be simplified - _ = opt.is_none_or(|x| x != 1000); //~ ERROR: this boolean expression can be simplified - _ = opt.is_none_or(|x| x == 1000); //~ ERROR: this boolean expression can be simplified + _ = opt.is_none_or(|x| x >= 1000); + //~^ nonminimal_bool + _ = opt.is_none_or(|x| x > 1000); + //~^ nonminimal_bool + _ = opt.is_none_or(|x| x <= 1000); + //~^ nonminimal_bool + _ = opt.is_none_or(|x| x < 1000); + //~^ nonminimal_bool + _ = opt.is_none_or(|x| x != 1000); + //~^ nonminimal_bool + _ = opt.is_none_or(|x| x == 1000); + //~^ nonminimal_bool _ = !opt.is_some_and(not_zero); _ = opt.is_none_or(|x| x < 1000); _ = opt.is_none_or(|x| x <= 1000); @@ -166,33 +195,45 @@ fn issue_13436() { _ = opt.is_none_or(|x| x == 1000); _ = opt.is_none_or(|x| x != 1000); _ = opt.is_none_or(not_zero); - _ = opt.is_some_and(|x| x >= 1000); //~ ERROR: this boolean expression can be simplified - _ = opt.is_some_and(|x| x > 1000); //~ ERROR: this boolean expression can be simplified - _ = opt.is_some_and(|x| x <= 1000); //~ ERROR: this boolean expression can be simplified - _ = opt.is_some_and(|x| x < 1000); //~ ERROR: this boolean expression can be simplified - _ = opt.is_some_and(|x| x != 1000); //~ ERROR: this boolean expression can be simplified - _ = opt.is_some_and(|x| x == 1000); //~ ERROR: this boolean expression can be simplified + _ = opt.is_some_and(|x| x >= 1000); + //~^ nonminimal_bool + _ = opt.is_some_and(|x| x > 1000); + //~^ nonminimal_bool + _ = opt.is_some_and(|x| x <= 1000); + //~^ nonminimal_bool + _ = opt.is_some_and(|x| x < 1000); + //~^ nonminimal_bool + _ = opt.is_some_and(|x| x != 1000); + //~^ nonminimal_bool + _ = opt.is_some_and(|x| x == 1000); + //~^ nonminimal_bool _ = !opt.is_none_or(not_zero); let opt = Some(true); _ = opt.is_some_and(|x| x); _ = opt.is_some_and(|x| !x); _ = !opt.is_some_and(|x| x); - _ = opt.is_none_or(|x| x); //~ ERROR: this boolean expression can be simplified + _ = opt.is_none_or(|x| x); + //~^ nonminimal_bool _ = opt.is_none_or(|x| x); _ = opt.is_none_or(|x| !x); _ = !opt.is_none_or(|x| x); - _ = opt.is_some_and(|x| x); //~ ERROR: this boolean expression can be simplified + _ = opt.is_some_and(|x| x); + //~^ nonminimal_bool let opt: Option> = Some(Ok(123)); _ = opt.is_some_and(|x| x.is_ok()); _ = opt.is_some_and(|x| x.is_err()); _ = opt.is_none_or(|x| x.is_ok()); _ = opt.is_none_or(|x| x.is_err()); - _ = opt.is_none_or(|x| x.is_err()); //~ ERROR: this boolean expression can be simplified - _ = opt.is_none_or(|x| x.is_ok()); //~ ERROR: this boolean expression can be simplified - _ = opt.is_some_and(|x| x.is_err()); //~ ERROR: this boolean expression can be simplified - _ = opt.is_some_and(|x| x.is_ok()); //~ ERROR: this boolean expression can be simplified + _ = opt.is_none_or(|x| x.is_err()); + //~^ nonminimal_bool + _ = opt.is_none_or(|x| x.is_ok()); + //~^ nonminimal_bool + _ = opt.is_some_and(|x| x.is_err()); + //~^ nonminimal_bool + _ = opt.is_some_and(|x| x.is_ok()); + //~^ nonminimal_bool #[clippy::msrv = "1.81"] fn before_stabilization() { diff --git a/tests/ui/nonminimal_bool_methods.rs b/tests/ui/nonminimal_bool_methods.rs index 06db3a1d4a5c..1ae0f0064c6b 100644 --- a/tests/ui/nonminimal_bool_methods.rs +++ b/tests/ui/nonminimal_bool_methods.rs @@ -6,18 +6,27 @@ fn methods_with_negation() { let b: Result = unimplemented!(); let _ = a.is_some(); let _ = !a.is_some(); + //~^ nonminimal_bool let _ = a.is_none(); let _ = !a.is_none(); + //~^ nonminimal_bool let _ = b.is_err(); let _ = !b.is_err(); + //~^ nonminimal_bool let _ = b.is_ok(); let _ = !b.is_ok(); + //~^ nonminimal_bool let c = false; let _ = !(a.is_some() && !c); + //~^ nonminimal_bool let _ = !(a.is_some() || !c); + //~^ nonminimal_bool let _ = !(!c ^ c) || !a.is_some(); + //~^ nonminimal_bool let _ = (!c ^ c) || !a.is_some(); + //~^ nonminimal_bool let _ = !c ^ c || !a.is_some(); + //~^ nonminimal_bool } // Simplified versions of https://github.com/rust-lang/rust-clippy/issues/2638 @@ -90,11 +99,15 @@ fn dont_warn_for_custom_methods_with_negation() { fn warn_for_built_in_methods_with_negation() { let res: Result = Ok(1); if !res.is_ok() {} + //~^ nonminimal_bool if !res.is_err() {} + //~^ nonminimal_bool let res = Some(1); if !res.is_some() {} + //~^ nonminimal_bool if !res.is_none() {} + //~^ nonminimal_bool } #[allow(clippy::neg_cmp_op_on_partial_ord)] @@ -110,24 +123,34 @@ fn dont_warn_for_negated_partial_ord_comparison() { fn issue_12625() { let a = 0; let b = 0; - if !(a as u64 >= b) {} //~ ERROR: this boolean expression can be simplified - if !((a as u64) >= b) {} //~ ERROR: this boolean expression can be simplified - if !(a as u64 <= b) {} //~ ERROR: this boolean expression can be simplified + if !(a as u64 >= b) {} + //~^ nonminimal_bool + if !((a as u64) >= b) {} + //~^ nonminimal_bool + if !(a as u64 <= b) {} + //~^ nonminimal_bool } fn issue_12761() { let a = 0; let b = 0; let c = 0; - if !(a >= b) as i32 == c {} //~ ERROR: this boolean expression can be simplified - if !(a >= b) | !(a <= c) {} //~ ERROR: this boolean expression can be simplified + if !(a >= b) as i32 == c {} + //~^ nonminimal_bool + if !(a >= b) | !(a <= c) {} + //~^ nonminimal_bool + //~| nonminimal_bool let opt: Option = Some(1); let res: Result = Ok(1); - if !res.is_ok() as i32 == c {} //~ ERROR: this boolean expression can be simplified - if !res.is_ok() | !opt.is_none() {} //~ ERROR: this boolean expression can be simplified + if !res.is_ok() as i32 == c {} + //~^ nonminimal_bool + if !res.is_ok() | !opt.is_none() {} + //~^ nonminimal_bool + //~| nonminimal_bool fn a(a: bool) -> bool { - (!(4 > 3)).b() //~ ERROR: this boolean expression can be simplified + (!(4 > 3)).b() + //~^ nonminimal_bool } trait B { @@ -152,12 +175,18 @@ fn issue_13436() { _ = opt.is_some_and(|x| x == 1000); _ = opt.is_some_and(|x| x != 1000); _ = opt.is_some_and(not_zero); - _ = !opt.is_some_and(|x| x < 1000); //~ ERROR: this boolean expression can be simplified - _ = !opt.is_some_and(|x| x <= 1000); //~ ERROR: this boolean expression can be simplified - _ = !opt.is_some_and(|x| x > 1000); //~ ERROR: this boolean expression can be simplified - _ = !opt.is_some_and(|x| x >= 1000); //~ ERROR: this boolean expression can be simplified - _ = !opt.is_some_and(|x| x == 1000); //~ ERROR: this boolean expression can be simplified - _ = !opt.is_some_and(|x| x != 1000); //~ ERROR: this boolean expression can be simplified + _ = !opt.is_some_and(|x| x < 1000); + //~^ nonminimal_bool + _ = !opt.is_some_and(|x| x <= 1000); + //~^ nonminimal_bool + _ = !opt.is_some_and(|x| x > 1000); + //~^ nonminimal_bool + _ = !opt.is_some_and(|x| x >= 1000); + //~^ nonminimal_bool + _ = !opt.is_some_and(|x| x == 1000); + //~^ nonminimal_bool + _ = !opt.is_some_and(|x| x != 1000); + //~^ nonminimal_bool _ = !opt.is_some_and(not_zero); _ = opt.is_none_or(|x| x < 1000); _ = opt.is_none_or(|x| x <= 1000); @@ -166,33 +195,45 @@ fn issue_13436() { _ = opt.is_none_or(|x| x == 1000); _ = opt.is_none_or(|x| x != 1000); _ = opt.is_none_or(not_zero); - _ = !opt.is_none_or(|x| x < 1000); //~ ERROR: this boolean expression can be simplified - _ = !opt.is_none_or(|x| x <= 1000); //~ ERROR: this boolean expression can be simplified - _ = !opt.is_none_or(|x| x > 1000); //~ ERROR: this boolean expression can be simplified - _ = !opt.is_none_or(|x| x >= 1000); //~ ERROR: this boolean expression can be simplified - _ = !opt.is_none_or(|x| x == 1000); //~ ERROR: this boolean expression can be simplified - _ = !opt.is_none_or(|x| x != 1000); //~ ERROR: this boolean expression can be simplified + _ = !opt.is_none_or(|x| x < 1000); + //~^ nonminimal_bool + _ = !opt.is_none_or(|x| x <= 1000); + //~^ nonminimal_bool + _ = !opt.is_none_or(|x| x > 1000); + //~^ nonminimal_bool + _ = !opt.is_none_or(|x| x >= 1000); + //~^ nonminimal_bool + _ = !opt.is_none_or(|x| x == 1000); + //~^ nonminimal_bool + _ = !opt.is_none_or(|x| x != 1000); + //~^ nonminimal_bool _ = !opt.is_none_or(not_zero); let opt = Some(true); _ = opt.is_some_and(|x| x); _ = opt.is_some_and(|x| !x); _ = !opt.is_some_and(|x| x); - _ = !opt.is_some_and(|x| !x); //~ ERROR: this boolean expression can be simplified + _ = !opt.is_some_and(|x| !x); + //~^ nonminimal_bool _ = opt.is_none_or(|x| x); _ = opt.is_none_or(|x| !x); _ = !opt.is_none_or(|x| x); - _ = !opt.is_none_or(|x| !x); //~ ERROR: this boolean expression can be simplified + _ = !opt.is_none_or(|x| !x); + //~^ nonminimal_bool let opt: Option> = Some(Ok(123)); _ = opt.is_some_and(|x| x.is_ok()); _ = opt.is_some_and(|x| x.is_err()); _ = opt.is_none_or(|x| x.is_ok()); _ = opt.is_none_or(|x| x.is_err()); - _ = !opt.is_some_and(|x| x.is_ok()); //~ ERROR: this boolean expression can be simplified - _ = !opt.is_some_and(|x| x.is_err()); //~ ERROR: this boolean expression can be simplified - _ = !opt.is_none_or(|x| x.is_ok()); //~ ERROR: this boolean expression can be simplified - _ = !opt.is_none_or(|x| x.is_err()); //~ ERROR: this boolean expression can be simplified + _ = !opt.is_some_and(|x| x.is_ok()); + //~^ nonminimal_bool + _ = !opt.is_some_and(|x| x.is_err()); + //~^ nonminimal_bool + _ = !opt.is_none_or(|x| x.is_ok()); + //~^ nonminimal_bool + _ = !opt.is_none_or(|x| x.is_err()); + //~^ nonminimal_bool #[clippy::msrv = "1.81"] fn before_stabilization() { diff --git a/tests/ui/nonminimal_bool_methods.stderr b/tests/ui/nonminimal_bool_methods.stderr index 66c50f9ff1e1..b5155b3b1696 100644 --- a/tests/ui/nonminimal_bool_methods.stderr +++ b/tests/ui/nonminimal_bool_methods.stderr @@ -8,241 +8,241 @@ LL | let _ = !a.is_some(); = help: to override `-D warnings` add `#[allow(clippy::nonminimal_bool)]` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:10:13 + --> tests/ui/nonminimal_bool_methods.rs:11:13 | LL | let _ = !a.is_none(); | ^^^^^^^^^^^^ help: try: `a.is_some()` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:12:13 + --> tests/ui/nonminimal_bool_methods.rs:14:13 | LL | let _ = !b.is_err(); | ^^^^^^^^^^^ help: try: `b.is_ok()` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:14:13 + --> tests/ui/nonminimal_bool_methods.rs:17:13 | LL | let _ = !b.is_ok(); | ^^^^^^^^^^ help: try: `b.is_err()` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:16:13 + --> tests/ui/nonminimal_bool_methods.rs:20:13 | LL | let _ = !(a.is_some() && !c); | ^^^^^^^^^^^^^^^^^^^^ help: try: `a.is_none() || c` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:17:13 + --> tests/ui/nonminimal_bool_methods.rs:22:13 | LL | let _ = !(a.is_some() || !c); | ^^^^^^^^^^^^^^^^^^^^ help: try: `a.is_none() && c` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:18:26 + --> tests/ui/nonminimal_bool_methods.rs:24:26 | LL | let _ = !(!c ^ c) || !a.is_some(); | ^^^^^^^^^^^^ help: try: `a.is_none()` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:19:25 + --> tests/ui/nonminimal_bool_methods.rs:26:25 | LL | let _ = (!c ^ c) || !a.is_some(); | ^^^^^^^^^^^^ help: try: `a.is_none()` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:20:23 + --> tests/ui/nonminimal_bool_methods.rs:28:23 | LL | let _ = !c ^ c || !a.is_some(); | ^^^^^^^^^^^^ help: try: `a.is_none()` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:92:8 + --> tests/ui/nonminimal_bool_methods.rs:101:8 | LL | if !res.is_ok() {} | ^^^^^^^^^^^^ help: try: `res.is_err()` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:93:8 + --> tests/ui/nonminimal_bool_methods.rs:103:8 | LL | if !res.is_err() {} | ^^^^^^^^^^^^^ help: try: `res.is_ok()` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:96:8 + --> tests/ui/nonminimal_bool_methods.rs:107:8 | LL | if !res.is_some() {} | ^^^^^^^^^^^^^^ help: try: `res.is_none()` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:97:8 + --> tests/ui/nonminimal_bool_methods.rs:109:8 | LL | if !res.is_none() {} | ^^^^^^^^^^^^^^ help: try: `res.is_some()` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:113:8 + --> tests/ui/nonminimal_bool_methods.rs:126:8 | LL | if !(a as u64 >= b) {} | ^^^^^^^^^^^^^^^^ help: try: `((a as u64) < b)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:114:8 + --> tests/ui/nonminimal_bool_methods.rs:128:8 | LL | if !((a as u64) >= b) {} | ^^^^^^^^^^^^^^^^^^ help: try: `((a as u64) < b)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:115:8 + --> tests/ui/nonminimal_bool_methods.rs:130:8 | LL | if !(a as u64 <= b) {} | ^^^^^^^^^^^^^^^^ help: try: `(a as u64 > b)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:122:8 + --> tests/ui/nonminimal_bool_methods.rs:138:8 | LL | if !(a >= b) as i32 == c {} | ^^^^^^^^^ help: try: `(a < b)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:123:8 + --> tests/ui/nonminimal_bool_methods.rs:140:8 | LL | if !(a >= b) | !(a <= c) {} | ^^^^^^^^^ help: try: `(a < b)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:123:20 + --> tests/ui/nonminimal_bool_methods.rs:140:20 | LL | if !(a >= b) | !(a <= c) {} | ^^^^^^^^^ help: try: `(a > c)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:126:8 + --> tests/ui/nonminimal_bool_methods.rs:145:8 | LL | if !res.is_ok() as i32 == c {} | ^^^^^^^^^^^^ help: try: `res.is_err()` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:127:8 + --> tests/ui/nonminimal_bool_methods.rs:147:8 | LL | if !res.is_ok() | !opt.is_none() {} | ^^^^^^^^^^^^ help: try: `res.is_err()` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:127:23 + --> tests/ui/nonminimal_bool_methods.rs:147:23 | LL | if !res.is_ok() | !opt.is_none() {} | ^^^^^^^^^^^^^^ help: try: `opt.is_some()` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:130:9 + --> tests/ui/nonminimal_bool_methods.rs:152:9 | LL | (!(4 > 3)).b() | ^^^^^^^^^^ help: try: `(4 <= 3)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:155:9 + --> tests/ui/nonminimal_bool_methods.rs:178:9 | LL | _ = !opt.is_some_and(|x| x < 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x >= 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:156:9 + --> tests/ui/nonminimal_bool_methods.rs:180:9 | LL | _ = !opt.is_some_and(|x| x <= 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x > 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:157:9 + --> tests/ui/nonminimal_bool_methods.rs:182:9 | LL | _ = !opt.is_some_and(|x| x > 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x <= 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:158:9 + --> tests/ui/nonminimal_bool_methods.rs:184:9 | LL | _ = !opt.is_some_and(|x| x >= 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x < 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:159:9 + --> tests/ui/nonminimal_bool_methods.rs:186:9 | LL | _ = !opt.is_some_and(|x| x == 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x != 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:160:9 + --> tests/ui/nonminimal_bool_methods.rs:188:9 | LL | _ = !opt.is_some_and(|x| x != 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x == 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:169:9 + --> tests/ui/nonminimal_bool_methods.rs:198:9 | LL | _ = !opt.is_none_or(|x| x < 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x >= 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:170:9 + --> tests/ui/nonminimal_bool_methods.rs:200:9 | LL | _ = !opt.is_none_or(|x| x <= 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x > 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:171:9 + --> tests/ui/nonminimal_bool_methods.rs:202:9 | LL | _ = !opt.is_none_or(|x| x > 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x <= 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:172:9 + --> tests/ui/nonminimal_bool_methods.rs:204:9 | LL | _ = !opt.is_none_or(|x| x >= 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x < 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:173:9 + --> tests/ui/nonminimal_bool_methods.rs:206:9 | LL | _ = !opt.is_none_or(|x| x == 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x != 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:174:9 + --> tests/ui/nonminimal_bool_methods.rs:208:9 | LL | _ = !opt.is_none_or(|x| x != 1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x == 1000)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:181:9 + --> tests/ui/nonminimal_bool_methods.rs:216:9 | LL | _ = !opt.is_some_and(|x| !x); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:185:9 + --> tests/ui/nonminimal_bool_methods.rs:221:9 | LL | _ = !opt.is_none_or(|x| !x); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:192:9 + --> tests/ui/nonminimal_bool_methods.rs:229:9 | LL | _ = !opt.is_some_and(|x| x.is_ok()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x.is_err())` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:193:9 + --> tests/ui/nonminimal_bool_methods.rs:231:9 | LL | _ = !opt.is_some_and(|x| x.is_err()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x.is_ok())` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:194:9 + --> tests/ui/nonminimal_bool_methods.rs:233:9 | LL | _ = !opt.is_none_or(|x| x.is_ok()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x.is_err())` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:195:9 + --> tests/ui/nonminimal_bool_methods.rs:235:9 | LL | _ = !opt.is_none_or(|x| x.is_err()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x.is_ok())` diff --git a/tests/ui/nonminimal_bool_methods_unfixable.rs b/tests/ui/nonminimal_bool_methods_unfixable.rs index 60b8da30a2f1..850eba4851b8 100644 --- a/tests/ui/nonminimal_bool_methods_unfixable.rs +++ b/tests/ui/nonminimal_bool_methods_unfixable.rs @@ -3,7 +3,9 @@ fn issue_13436() { let opt_opt = Some(Some(500)); - _ = !opt_opt.is_some_and(|x| !x.is_some_and(|y| y != 1000)); //~ ERROR: this boolean expression can be simplified + _ = !opt_opt.is_some_and(|x| !x.is_some_and(|y| y != 1000)); + //~^ nonminimal_bool + //~| nonminimal_bool } fn main() {} diff --git a/tests/ui/obfuscated_if_else.fixed b/tests/ui/obfuscated_if_else.fixed index bfe1c5e10cf8..66f5070787b0 100644 --- a/tests/ui/obfuscated_if_else.fixed +++ b/tests/ui/obfuscated_if_else.fixed @@ -1,18 +1,77 @@ #![warn(clippy::obfuscated_if_else)] -#![allow(clippy::unnecessary_lazy_evaluations, clippy::unit_arg, clippy::unused_unit)] +#![allow( + clippy::unnecessary_lazy_evaluations, + clippy::unit_arg, + clippy::unused_unit, + clippy::unwrap_or_default +)] fn main() { if true { "a" } else { "b" }; + //~^ obfuscated_if_else + if true { "a" } else { "b" }; + //~^ obfuscated_if_else let a = 1; if a == 1 { "a" } else { "b" }; + //~^ obfuscated_if_else + if a == 1 { "a" } else { "b" }; + //~^ obfuscated_if_else let partial = (a == 1).then_some("a"); partial.unwrap_or("b"); // not lint let mut a = 0; if true { a += 1 } else { () }; + //~^ obfuscated_if_else + if true { () } else { a += 2 }; + //~^ obfuscated_if_else + + let mut n = 1; + if true { n = 1 } else { n = 2 }; + //~^ obfuscated_if_else + if true { 1 } else { n * 2 }; + //~^ obfuscated_if_else + if true { n += 1 } else { () }; + //~^ obfuscated_if_else + + let _ = if true { 1 } else { n * 2 }; + //~^ obfuscated_if_else + + if true { 1 } else { Default::default() }; + //~^ obfuscated_if_else + + let partial = true.then_some(1); + partial.unwrap_or_else(|| n * 2); // not lint +} + +fn issue11141() { + // Parentheses are required around the left side of a binary expression + let _ = (if true { 40 } else { 17 }) | 2; + //~^ obfuscated_if_else + + // Parentheses are required only for the leftmost expression + let _ = (if true { 30 } else { 17 }) | if true { 2 } else { 3 } | if true { 10 } else { 1 }; + //~^ obfuscated_if_else + //~| obfuscated_if_else + //~| obfuscated_if_else + + // Parentheses are not required around the right side of a binary expression + let _ = 2 | if true { 40 } else { 17 }; + //~^ obfuscated_if_else + + // Parentheses are not required for a cast + let _ = if true { 42 } else { 17 } as u8; + //~^ obfuscated_if_else + + // Parentheses are not required for a deref + let _ = *if true { &42 } else { &17 }; + //~^ obfuscated_if_else + + // Parentheses are not required for a deref followed by a cast + let _ = *if true { &42 } else { &17 } as u8; + //~^ obfuscated_if_else } diff --git a/tests/ui/obfuscated_if_else.rs b/tests/ui/obfuscated_if_else.rs index 0ded2a2ceedf..4efd740eb60b 100644 --- a/tests/ui/obfuscated_if_else.rs +++ b/tests/ui/obfuscated_if_else.rs @@ -1,18 +1,77 @@ #![warn(clippy::obfuscated_if_else)] -#![allow(clippy::unnecessary_lazy_evaluations, clippy::unit_arg, clippy::unused_unit)] +#![allow( + clippy::unnecessary_lazy_evaluations, + clippy::unit_arg, + clippy::unused_unit, + clippy::unwrap_or_default +)] fn main() { true.then_some("a").unwrap_or("b"); + //~^ obfuscated_if_else + true.then(|| "a").unwrap_or("b"); + //~^ obfuscated_if_else let a = 1; (a == 1).then_some("a").unwrap_or("b"); + //~^ obfuscated_if_else + (a == 1).then(|| "a").unwrap_or("b"); + //~^ obfuscated_if_else let partial = (a == 1).then_some("a"); partial.unwrap_or("b"); // not lint let mut a = 0; true.then_some(a += 1).unwrap_or(()); + //~^ obfuscated_if_else + true.then_some(()).unwrap_or(a += 2); + //~^ obfuscated_if_else + + let mut n = 1; + true.then(|| n = 1).unwrap_or_else(|| n = 2); + //~^ obfuscated_if_else + true.then_some(1).unwrap_or_else(|| n * 2); + //~^ obfuscated_if_else + true.then_some(n += 1).unwrap_or_else(|| ()); + //~^ obfuscated_if_else + + let _ = true.then_some(1).unwrap_or_else(|| n * 2); + //~^ obfuscated_if_else + + true.then_some(1).unwrap_or_else(Default::default); + //~^ obfuscated_if_else + + let partial = true.then_some(1); + partial.unwrap_or_else(|| n * 2); // not lint +} + +fn issue11141() { + // Parentheses are required around the left side of a binary expression + let _ = true.then_some(40).unwrap_or(17) | 2; + //~^ obfuscated_if_else + + // Parentheses are required only for the leftmost expression + let _ = true.then_some(30).unwrap_or(17) | true.then_some(2).unwrap_or(3) | true.then_some(10).unwrap_or(1); + //~^ obfuscated_if_else + //~| obfuscated_if_else + //~| obfuscated_if_else + + // Parentheses are not required around the right side of a binary expression + let _ = 2 | true.then_some(40).unwrap_or(17); + //~^ obfuscated_if_else + + // Parentheses are not required for a cast + let _ = true.then_some(42).unwrap_or(17) as u8; + //~^ obfuscated_if_else + + // Parentheses are not required for a deref + let _ = *true.then_some(&42).unwrap_or(&17); + //~^ obfuscated_if_else + + // Parentheses are not required for a deref followed by a cast + let _ = *true.then_some(&42).unwrap_or(&17) as u8; + //~^ obfuscated_if_else } diff --git a/tests/ui/obfuscated_if_else.stderr b/tests/ui/obfuscated_if_else.stderr index 9ce1f475c480..d676c2566957 100644 --- a/tests/ui/obfuscated_if_else.stderr +++ b/tests/ui/obfuscated_if_else.stderr @@ -1,5 +1,5 @@ error: this method chain can be written more clearly with `if .. else ..` - --> tests/ui/obfuscated_if_else.rs:5:5 + --> tests/ui/obfuscated_if_else.rs:10:5 | LL | true.then_some("a").unwrap_or("b"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { "a" } else { "b" }` @@ -8,34 +8,112 @@ LL | true.then_some("a").unwrap_or("b"); = help: to override `-D warnings` add `#[allow(clippy::obfuscated_if_else)]` error: this method chain can be written more clearly with `if .. else ..` - --> tests/ui/obfuscated_if_else.rs:6:5 + --> tests/ui/obfuscated_if_else.rs:13:5 | LL | true.then(|| "a").unwrap_or("b"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { "a" } else { "b" }` error: this method chain can be written more clearly with `if .. else ..` - --> tests/ui/obfuscated_if_else.rs:9:5 + --> tests/ui/obfuscated_if_else.rs:17:5 | LL | (a == 1).then_some("a").unwrap_or("b"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if a == 1 { "a" } else { "b" }` error: this method chain can be written more clearly with `if .. else ..` - --> tests/ui/obfuscated_if_else.rs:10:5 + --> tests/ui/obfuscated_if_else.rs:20:5 | LL | (a == 1).then(|| "a").unwrap_or("b"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if a == 1 { "a" } else { "b" }` error: this method chain can be written more clearly with `if .. else ..` - --> tests/ui/obfuscated_if_else.rs:16:5 + --> tests/ui/obfuscated_if_else.rs:27:5 | LL | true.then_some(a += 1).unwrap_or(()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { a += 1 } else { () }` error: this method chain can be written more clearly with `if .. else ..` - --> tests/ui/obfuscated_if_else.rs:17:5 + --> tests/ui/obfuscated_if_else.rs:30:5 | LL | true.then_some(()).unwrap_or(a += 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { () } else { a += 2 }` -error: aborting due to 6 previous errors +error: this method chain can be written more clearly with `if .. else ..` + --> tests/ui/obfuscated_if_else.rs:34:5 + | +LL | true.then(|| n = 1).unwrap_or_else(|| n = 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { n = 1 } else { n = 2 }` + +error: this method chain can be written more clearly with `if .. else ..` + --> tests/ui/obfuscated_if_else.rs:36:5 + | +LL | true.then_some(1).unwrap_or_else(|| n * 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { 1 } else { n * 2 }` + +error: this method chain can be written more clearly with `if .. else ..` + --> tests/ui/obfuscated_if_else.rs:38:5 + | +LL | true.then_some(n += 1).unwrap_or_else(|| ()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { n += 1 } else { () }` + +error: this method chain can be written more clearly with `if .. else ..` + --> tests/ui/obfuscated_if_else.rs:41:13 + | +LL | let _ = true.then_some(1).unwrap_or_else(|| n * 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { 1 } else { n * 2 }` + +error: this method chain can be written more clearly with `if .. else ..` + --> tests/ui/obfuscated_if_else.rs:44:5 + | +LL | true.then_some(1).unwrap_or_else(Default::default); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { 1 } else { Default::default() }` + +error: this method chain can be written more clearly with `if .. else ..` + --> tests/ui/obfuscated_if_else.rs:53:13 + | +LL | let _ = true.then_some(40).unwrap_or(17) | 2; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(if true { 40 } else { 17 })` + +error: this method chain can be written more clearly with `if .. else ..` + --> tests/ui/obfuscated_if_else.rs:57:13 + | +LL | let _ = true.then_some(30).unwrap_or(17) | true.then_some(2).unwrap_or(3) | true.then_some(10).unwrap_or(1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(if true { 30 } else { 17 })` + +error: this method chain can be written more clearly with `if .. else ..` + --> tests/ui/obfuscated_if_else.rs:57:48 + | +LL | let _ = true.then_some(30).unwrap_or(17) | true.then_some(2).unwrap_or(3) | true.then_some(10).unwrap_or(1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { 2 } else { 3 }` + +error: this method chain can be written more clearly with `if .. else ..` + --> tests/ui/obfuscated_if_else.rs:57:81 + | +LL | let _ = true.then_some(30).unwrap_or(17) | true.then_some(2).unwrap_or(3) | true.then_some(10).unwrap_or(1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { 10 } else { 1 }` + +error: this method chain can be written more clearly with `if .. else ..` + --> tests/ui/obfuscated_if_else.rs:63:17 + | +LL | let _ = 2 | true.then_some(40).unwrap_or(17); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { 40 } else { 17 }` + +error: this method chain can be written more clearly with `if .. else ..` + --> tests/ui/obfuscated_if_else.rs:67:13 + | +LL | let _ = true.then_some(42).unwrap_or(17) as u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { 42 } else { 17 }` + +error: this method chain can be written more clearly with `if .. else ..` + --> tests/ui/obfuscated_if_else.rs:71:14 + | +LL | let _ = *true.then_some(&42).unwrap_or(&17); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { &42 } else { &17 }` + +error: this method chain can be written more clearly with `if .. else ..` + --> tests/ui/obfuscated_if_else.rs:75:14 + | +LL | let _ = *true.then_some(&42).unwrap_or(&17) as u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { &42 } else { &17 }` + +error: aborting due to 19 previous errors diff --git a/tests/ui/octal_escapes.rs b/tests/ui/octal_escapes.rs index f2664e2fa67f..d91d6c1d7bee 100644 --- a/tests/ui/octal_escapes.rs +++ b/tests/ui/octal_escapes.rs @@ -2,20 +2,29 @@ #![warn(clippy::octal_escapes)] fn main() { - let _bad1 = "\033[0m"; //~ octal_escapes - let _bad2 = b"\033[0m"; //~ octal_escapes - let _bad3 = "\\\033[0m"; //~ octal_escapes + let _bad1 = "\033[0m"; + //~^ octal_escapes + let _bad2 = b"\033[0m"; + //~^ octal_escapes + let _bad3 = "\\\033[0m"; + //~^ octal_escapes // maximum 3 digits (\012 is the escape) - let _bad4 = "\01234567"; //~ octal_escapes - let _bad5 = "\0\03"; //~ octal_escapes + let _bad4 = "\01234567"; + //~^ octal_escapes + let _bad5 = "\0\03"; + //~^ octal_escapes let _bad6 = "Text-\055\077-MoreText"; //~^ octal_escapes //~| octal_escapes + let _bad7 = "EvenMoreText-\01\02-ShortEscapes"; //~^ octal_escapes //~| octal_escapes - let _bad8 = "锈\01锈"; //~ octal_escapes - let _bad9 = "锈\011锈"; //~ octal_escapes + + let _bad8 = "锈\01锈"; + //~^ octal_escapes + let _bad9 = "锈\011锈"; + //~^ octal_escapes let _good1 = "\\033[0m"; let _good2 = "\0\\0"; diff --git a/tests/ui/octal_escapes.stderr b/tests/ui/octal_escapes.stderr index 61c781e316ef..5271c13c08bd 100644 --- a/tests/ui/octal_escapes.stderr +++ b/tests/ui/octal_escapes.stderr @@ -18,7 +18,7 @@ LL | let _bad1 = "\x0033[0m"; | ++ error: octal-looking escape in a literal - --> tests/ui/octal_escapes.rs:6:19 + --> tests/ui/octal_escapes.rs:7:19 | LL | let _bad2 = b"\033[0m"; | ^^^^ @@ -34,7 +34,7 @@ LL | let _bad2 = b"\x0033[0m"; | ++ error: octal-looking escape in a literal - --> tests/ui/octal_escapes.rs:7:20 + --> tests/ui/octal_escapes.rs:9:20 | LL | let _bad3 = "\\\033[0m"; | ^^^^ @@ -50,7 +50,7 @@ LL | let _bad3 = "\\\x0033[0m"; | ++ error: octal-looking escape in a literal - --> tests/ui/octal_escapes.rs:9:18 + --> tests/ui/octal_escapes.rs:12:18 | LL | let _bad4 = "\01234567"; | ^^^^ @@ -66,7 +66,7 @@ LL | let _bad4 = "\x001234567"; | ++ error: octal-looking escape in a literal - --> tests/ui/octal_escapes.rs:10:20 + --> tests/ui/octal_escapes.rs:14:20 | LL | let _bad5 = "\0\03"; | ^^^ @@ -81,7 +81,7 @@ LL | let _bad5 = "\0\x0003"; | +++ error: octal-looking escape in a literal - --> tests/ui/octal_escapes.rs:11:23 + --> tests/ui/octal_escapes.rs:16:23 | LL | let _bad6 = "Text-\055\077-MoreText"; | ^^^^ @@ -97,7 +97,7 @@ LL | let _bad6 = "Text-\x0055\077-MoreText"; | ++ error: octal-looking escape in a literal - --> tests/ui/octal_escapes.rs:11:27 + --> tests/ui/octal_escapes.rs:16:27 | LL | let _bad6 = "Text-\055\077-MoreText"; | ^^^^ @@ -113,7 +113,7 @@ LL | let _bad6 = "Text-\055\x0077-MoreText"; | ++ error: octal-looking escape in a literal - --> tests/ui/octal_escapes.rs:14:31 + --> tests/ui/octal_escapes.rs:20:31 | LL | let _bad7 = "EvenMoreText-\01\02-ShortEscapes"; | ^^^ @@ -128,7 +128,7 @@ LL | let _bad7 = "EvenMoreText-\x0001\02-ShortEscapes"; | +++ error: octal-looking escape in a literal - --> tests/ui/octal_escapes.rs:14:34 + --> tests/ui/octal_escapes.rs:20:34 | LL | let _bad7 = "EvenMoreText-\01\02-ShortEscapes"; | ^^^ @@ -143,7 +143,7 @@ LL | let _bad7 = "EvenMoreText-\01\x0002-ShortEscapes"; | +++ error: octal-looking escape in a literal - --> tests/ui/octal_escapes.rs:17:19 + --> tests/ui/octal_escapes.rs:24:19 | LL | let _bad8 = "锈\01锈"; | ^^^ @@ -158,7 +158,7 @@ LL | let _bad8 = "锈\x0001锈"; | +++ error: octal-looking escape in a literal - --> tests/ui/octal_escapes.rs:18:19 + --> tests/ui/octal_escapes.rs:26:19 | LL | let _bad9 = "锈\011锈"; | ^^^^ diff --git a/tests/ui/ok_expect.rs b/tests/ui/ok_expect.rs index c2ad21e22ff8..efb56f242a74 100644 --- a/tests/ui/ok_expect.rs +++ b/tests/ui/ok_expect.rs @@ -14,21 +14,25 @@ fn main() { let _ = res.unwrap(); res.ok().expect("disaster!"); - //~^ ERROR: called `ok().expect()` on a `Result` value + //~^ ok_expect + // the following should not warn, since `expect` isn't implemented unless // the error type implements `Debug` let res2: Result = Ok(0); res2.ok().expect("oh noes!"); let res3: Result> = Ok(0); res3.ok().expect("whoof"); - //~^ ERROR: called `ok().expect()` on a `Result` value + //~^ ok_expect + let res4: Result = Ok(0); res4.ok().expect("argh"); - //~^ ERROR: called `ok().expect()` on a `Result` value + //~^ ok_expect + let res5: io::Result = Ok(0); res5.ok().expect("oops"); - //~^ ERROR: called `ok().expect()` on a `Result` value + //~^ ok_expect + let res6: Result = Ok(0); res6.ok().expect("meh"); - //~^ ERROR: called `ok().expect()` on a `Result` value + //~^ ok_expect } diff --git a/tests/ui/ok_expect.stderr b/tests/ui/ok_expect.stderr index 2fd4f007d06d..a9e3533d8ca1 100644 --- a/tests/ui/ok_expect.stderr +++ b/tests/ui/ok_expect.stderr @@ -9,7 +9,7 @@ LL | res.ok().expect("disaster!"); = help: to override `-D warnings` add `#[allow(clippy::ok_expect)]` error: called `ok().expect()` on a `Result` value - --> tests/ui/ok_expect.rs:23:5 + --> tests/ui/ok_expect.rs:24:5 | LL | res3.ok().expect("whoof"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | res3.ok().expect("whoof"); = help: you can call `expect()` directly on the `Result` error: called `ok().expect()` on a `Result` value - --> tests/ui/ok_expect.rs:26:5 + --> tests/ui/ok_expect.rs:28:5 | LL | res4.ok().expect("argh"); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | res4.ok().expect("argh"); = help: you can call `expect()` directly on the `Result` error: called `ok().expect()` on a `Result` value - --> tests/ui/ok_expect.rs:29:5 + --> tests/ui/ok_expect.rs:32:5 | LL | res5.ok().expect("oops"); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | res5.ok().expect("oops"); = help: you can call `expect()` directly on the `Result` error: called `ok().expect()` on a `Result` value - --> tests/ui/ok_expect.rs:32:5 + --> tests/ui/ok_expect.rs:36:5 | LL | res6.ok().expect("meh"); | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/only_used_in_recursion.rs b/tests/ui/only_used_in_recursion.rs index 169fb790f8c5..7d6075ba9ea4 100644 --- a/tests/ui/only_used_in_recursion.rs +++ b/tests/ui/only_used_in_recursion.rs @@ -9,18 +9,21 @@ fn _simple2(x: u32) -> u32 { } fn _one_unused(flag: u32, a: usize) -> usize { - //~^ ERROR: parameter is only used in recursion + //~^ only_used_in_recursion + if flag == 0 { 0 } else { _one_unused(flag - 1, a) } } fn _two_unused(flag: u32, a: u32, b: i32) -> usize { - //~^ ERROR: parameter is only used in recursion - //~| ERROR: parameter is only used in recursion + //~^ only_used_in_recursion + //~| only_used_in_recursion + if flag == 0 { 0 } else { _two_unused(flag - 1, a, b) } } fn _with_calc(flag: u32, a: i64) -> usize { - //~^ ERROR: parameter is only used in recursion + //~^ only_used_in_recursion + if flag == 0 { 0 } else { @@ -34,8 +37,9 @@ fn _used_with_flag(flag: u32, a: u32) -> usize { } fn _used_with_unused(flag: u32, a: i32, b: i32) -> usize { - //~^ ERROR: parameter is only used in recursion - //~| ERROR: parameter is only used in recursion + //~^ only_used_in_recursion + //~| only_used_in_recursion + if flag == 0 { 0 } else { @@ -44,8 +48,9 @@ fn _used_with_unused(flag: u32, a: i32, b: i32) -> usize { } fn _codependent_unused(flag: u32, a: i32, b: i32) -> usize { - //~^ ERROR: parameter is only used in recursion - //~| ERROR: parameter is only used in recursion + //~^ only_used_in_recursion + //~| only_used_in_recursion + if flag == 0 { 0 } else { @@ -54,7 +59,8 @@ fn _codependent_unused(flag: u32, a: i32, b: i32) -> usize { } fn _not_primitive(flag: u32, b: String) -> usize { - //~^ ERROR: parameter is only used in recursion + //~^ only_used_in_recursion + if flag == 0 { 0 } else { _not_primitive(flag - 1, b) } } @@ -62,13 +68,15 @@ struct A; impl A { fn _method(flag: usize, a: usize) -> usize { - //~^ ERROR: parameter is only used in recursion + //~^ only_used_in_recursion + if flag == 0 { 0 } else { Self::_method(flag - 1, a) } } fn _method_self(&self, flag: usize, a: usize) -> usize { - //~^ ERROR: parameter is only used in recursion - //~| ERROR: parameter is only used in recursion + //~^ only_used_in_recursion + //~| only_used_in_recursion + if flag == 0 { 0 } else { self._method_self(flag - 1, a) } } } @@ -80,12 +88,14 @@ trait B { impl B for A { fn method(flag: u32, a: usize) -> usize { - //~^ ERROR: parameter is only used in recursion + //~^ only_used_in_recursion + if flag == 0 { 0 } else { Self::method(flag - 1, a) } } fn method_self(&self, flag: u32, a: usize) -> usize { - //~^ ERROR: parameter is only used in recursion + //~^ only_used_in_recursion + if flag == 0 { 0 } else { self.method_self(flag - 1, a) } } } @@ -112,12 +122,14 @@ impl B for u32 { trait C { fn method(flag: u32, a: usize) -> usize { - //~^ ERROR: parameter is only used in recursion + //~^ only_used_in_recursion + if flag == 0 { 0 } else { Self::method(flag - 1, a) } } fn method_self(&self, flag: u32, a: usize) -> usize { - //~^ ERROR: parameter is only used in recursion + //~^ only_used_in_recursion + if flag == 0 { 0 } else { self.method_self(flag - 1, a) } } } diff --git a/tests/ui/only_used_in_recursion.stderr b/tests/ui/only_used_in_recursion.stderr index a3aee2697f38..ca08319e1120 100644 --- a/tests/ui/only_used_in_recursion.stderr +++ b/tests/ui/only_used_in_recursion.stderr @@ -5,7 +5,7 @@ LL | fn _one_unused(flag: u32, a: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_a` | note: parameter used here - --> tests/ui/only_used_in_recursion.rs:13:53 + --> tests/ui/only_used_in_recursion.rs:14:53 | LL | if flag == 0 { 0 } else { _one_unused(flag - 1, a) } | ^ @@ -13,181 +13,181 @@ LL | if flag == 0 { 0 } else { _one_unused(flag - 1, a) } = help: to override `-D warnings` add `#[allow(clippy::only_used_in_recursion)]` error: parameter is only used in recursion - --> tests/ui/only_used_in_recursion.rs:16:27 + --> tests/ui/only_used_in_recursion.rs:17:27 | LL | fn _two_unused(flag: u32, a: u32, b: i32) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_a` | note: parameter used here - --> tests/ui/only_used_in_recursion.rs:19:53 + --> tests/ui/only_used_in_recursion.rs:21:53 | LL | if flag == 0 { 0 } else { _two_unused(flag - 1, a, b) } | ^ error: parameter is only used in recursion - --> tests/ui/only_used_in_recursion.rs:16:35 + --> tests/ui/only_used_in_recursion.rs:17:35 | LL | fn _two_unused(flag: u32, a: u32, b: i32) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_b` | note: parameter used here - --> tests/ui/only_used_in_recursion.rs:19:56 + --> tests/ui/only_used_in_recursion.rs:21:56 | LL | if flag == 0 { 0 } else { _two_unused(flag - 1, a, b) } | ^ error: parameter is only used in recursion - --> tests/ui/only_used_in_recursion.rs:22:26 + --> tests/ui/only_used_in_recursion.rs:24:26 | LL | fn _with_calc(flag: u32, a: i64) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_a` | note: parameter used here - --> tests/ui/only_used_in_recursion.rs:27:32 + --> tests/ui/only_used_in_recursion.rs:30:32 | LL | _with_calc(flag - 1, (-a + 10) * 5) | ^ error: parameter is only used in recursion - --> tests/ui/only_used_in_recursion.rs:36:33 + --> tests/ui/only_used_in_recursion.rs:39:33 | LL | fn _used_with_unused(flag: u32, a: i32, b: i32) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_a` | note: parameter used here - --> tests/ui/only_used_in_recursion.rs:42:38 + --> tests/ui/only_used_in_recursion.rs:46:38 | LL | _used_with_unused(flag - 1, -a, a + b) | ^ ^ error: parameter is only used in recursion - --> tests/ui/only_used_in_recursion.rs:36:41 + --> tests/ui/only_used_in_recursion.rs:39:41 | LL | fn _used_with_unused(flag: u32, a: i32, b: i32) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_b` | note: parameter used here - --> tests/ui/only_used_in_recursion.rs:42:45 + --> tests/ui/only_used_in_recursion.rs:46:45 | LL | _used_with_unused(flag - 1, -a, a + b) | ^ error: parameter is only used in recursion - --> tests/ui/only_used_in_recursion.rs:46:35 + --> tests/ui/only_used_in_recursion.rs:50:35 | LL | fn _codependent_unused(flag: u32, a: i32, b: i32) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_a` | note: parameter used here - --> tests/ui/only_used_in_recursion.rs:52:39 + --> tests/ui/only_used_in_recursion.rs:57:39 | LL | _codependent_unused(flag - 1, a * b, a + b) | ^ ^ error: parameter is only used in recursion - --> tests/ui/only_used_in_recursion.rs:46:43 + --> tests/ui/only_used_in_recursion.rs:50:43 | LL | fn _codependent_unused(flag: u32, a: i32, b: i32) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_b` | note: parameter used here - --> tests/ui/only_used_in_recursion.rs:52:43 + --> tests/ui/only_used_in_recursion.rs:57:43 | LL | _codependent_unused(flag - 1, a * b, a + b) | ^ ^ error: parameter is only used in recursion - --> tests/ui/only_used_in_recursion.rs:56:30 + --> tests/ui/only_used_in_recursion.rs:61:30 | LL | fn _not_primitive(flag: u32, b: String) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_b` | note: parameter used here - --> tests/ui/only_used_in_recursion.rs:58:56 + --> tests/ui/only_used_in_recursion.rs:64:56 | LL | if flag == 0 { 0 } else { _not_primitive(flag - 1, b) } | ^ error: parameter is only used in recursion - --> tests/ui/only_used_in_recursion.rs:64:29 + --> tests/ui/only_used_in_recursion.rs:70:29 | LL | fn _method(flag: usize, a: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_a` | note: parameter used here - --> tests/ui/only_used_in_recursion.rs:66:59 + --> tests/ui/only_used_in_recursion.rs:73:59 | LL | if flag == 0 { 0 } else { Self::_method(flag - 1, a) } | ^ error: parameter is only used in recursion - --> tests/ui/only_used_in_recursion.rs:69:22 + --> tests/ui/only_used_in_recursion.rs:76:22 | LL | fn _method_self(&self, flag: usize, a: usize) -> usize { | ^^^^ | note: parameter used here - --> tests/ui/only_used_in_recursion.rs:72:35 + --> tests/ui/only_used_in_recursion.rs:80:35 | LL | if flag == 0 { 0 } else { self._method_self(flag - 1, a) } | ^^^^ error: parameter is only used in recursion - --> tests/ui/only_used_in_recursion.rs:69:41 + --> tests/ui/only_used_in_recursion.rs:76:41 | LL | fn _method_self(&self, flag: usize, a: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_a` | note: parameter used here - --> tests/ui/only_used_in_recursion.rs:72:63 + --> tests/ui/only_used_in_recursion.rs:80:63 | LL | if flag == 0 { 0 } else { self._method_self(flag - 1, a) } | ^ error: parameter is only used in recursion - --> tests/ui/only_used_in_recursion.rs:82:26 + --> tests/ui/only_used_in_recursion.rs:90:26 | LL | fn method(flag: u32, a: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_a` | note: parameter used here - --> tests/ui/only_used_in_recursion.rs:84:58 + --> tests/ui/only_used_in_recursion.rs:93:58 | LL | if flag == 0 { 0 } else { Self::method(flag - 1, a) } | ^ error: parameter is only used in recursion - --> tests/ui/only_used_in_recursion.rs:87:38 + --> tests/ui/only_used_in_recursion.rs:96:38 | LL | fn method_self(&self, flag: u32, a: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_a` | note: parameter used here - --> tests/ui/only_used_in_recursion.rs:89:62 + --> tests/ui/only_used_in_recursion.rs:99:62 | LL | if flag == 0 { 0 } else { self.method_self(flag - 1, a) } | ^ error: parameter is only used in recursion - --> tests/ui/only_used_in_recursion.rs:114:26 + --> tests/ui/only_used_in_recursion.rs:124:26 | LL | fn method(flag: u32, a: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_a` | note: parameter used here - --> tests/ui/only_used_in_recursion.rs:116:58 + --> tests/ui/only_used_in_recursion.rs:127:58 | LL | if flag == 0 { 0 } else { Self::method(flag - 1, a) } | ^ error: parameter is only used in recursion - --> tests/ui/only_used_in_recursion.rs:119:38 + --> tests/ui/only_used_in_recursion.rs:130:38 | LL | fn method_self(&self, flag: u32, a: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_a` | note: parameter used here - --> tests/ui/only_used_in_recursion.rs:121:62 + --> tests/ui/only_used_in_recursion.rs:133:62 | LL | if flag == 0 { 0 } else { self.method_self(flag - 1, a) } | ^ diff --git a/tests/ui/only_used_in_recursion2.rs b/tests/ui/only_used_in_recursion2.rs index 1353ff8816ad..2fe4e7b35d38 100644 --- a/tests/ui/only_used_in_recursion2.rs +++ b/tests/ui/only_used_in_recursion2.rs @@ -1,9 +1,11 @@ #![warn(clippy::only_used_in_recursion)] //@no-rustfix fn _with_inner(flag: u32, a: u32, b: u32) -> usize { - //~^ ERROR: parameter is only used in recursion + //~^ only_used_in_recursion + fn inner(flag: u32, a: u32) -> u32 { - //~^ ERROR: parameter is only used in recursion + //~^ only_used_in_recursion + if flag == 0 { 0 } else { inner(flag, a) } } @@ -12,7 +14,8 @@ fn _with_inner(flag: u32, a: u32, b: u32) -> usize { } fn _with_closure(a: Option, b: u32, f: impl Fn(u32, u32) -> Option) -> u32 { - //~^ ERROR: parameter is only used in recursion + //~^ only_used_in_recursion + if let Some(x) = a.and_then(|x| f(x, x)) { _with_closure(Some(x), b, f) } else { @@ -63,7 +66,8 @@ impl E<()> for () { } fn overwritten_param(flag: u32, mut a: usize) -> usize { - //~^ ERROR: parameter is only used in recursion + //~^ only_used_in_recursion + if flag == 0 { return 0; } else if flag > 5 { @@ -75,7 +79,8 @@ fn overwritten_param(flag: u32, mut a: usize) -> usize { } fn field_direct(flag: u32, mut a: (usize,)) -> usize { - //~^ ERROR: parameter is only used in recursion + //~^ only_used_in_recursion + if flag == 0 { 0 } else { diff --git a/tests/ui/only_used_in_recursion2.stderr b/tests/ui/only_used_in_recursion2.stderr index e39460c7e8f3..a7cd8713cf7a 100644 --- a/tests/ui/only_used_in_recursion2.stderr +++ b/tests/ui/only_used_in_recursion2.stderr @@ -5,7 +5,7 @@ LL | fn _with_inner(flag: u32, a: u32, b: u32) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_b` | note: parameter used here - --> tests/ui/only_used_in_recursion2.rs:11:52 + --> tests/ui/only_used_in_recursion2.rs:13:52 | LL | if flag == 0 { 0 } else { _with_inner(flag, a, b + x) } | ^ @@ -13,49 +13,49 @@ LL | if flag == 0 { 0 } else { _with_inner(flag, a, b + x) } = help: to override `-D warnings` add `#[allow(clippy::only_used_in_recursion)]` error: parameter is only used in recursion - --> tests/ui/only_used_in_recursion2.rs:5:25 + --> tests/ui/only_used_in_recursion2.rs:6:25 | LL | fn inner(flag: u32, a: u32) -> u32 { | ^ help: if this is intentional, prefix it with an underscore: `_a` | note: parameter used here - --> tests/ui/only_used_in_recursion2.rs:7:47 + --> tests/ui/only_used_in_recursion2.rs:9:47 | LL | if flag == 0 { 0 } else { inner(flag, a) } | ^ error: parameter is only used in recursion - --> tests/ui/only_used_in_recursion2.rs:14:34 + --> tests/ui/only_used_in_recursion2.rs:16:34 | LL | fn _with_closure(a: Option, b: u32, f: impl Fn(u32, u32) -> Option) -> u32 { | ^ help: if this is intentional, prefix it with an underscore: `_b` | note: parameter used here - --> tests/ui/only_used_in_recursion2.rs:17:32 + --> tests/ui/only_used_in_recursion2.rs:20:32 | LL | _with_closure(Some(x), b, f) | ^ error: parameter is only used in recursion - --> tests/ui/only_used_in_recursion2.rs:65:37 + --> tests/ui/only_used_in_recursion2.rs:68:37 | LL | fn overwritten_param(flag: u32, mut a: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_a` | note: parameter used here - --> tests/ui/only_used_in_recursion2.rs:74:29 + --> tests/ui/only_used_in_recursion2.rs:78:29 | LL | overwritten_param(flag, a) | ^ error: parameter is only used in recursion - --> tests/ui/only_used_in_recursion2.rs:77:32 + --> tests/ui/only_used_in_recursion2.rs:81:32 | LL | fn field_direct(flag: u32, mut a: (usize,)) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_a` | note: parameter used here - --> tests/ui/only_used_in_recursion2.rs:83:32 + --> tests/ui/only_used_in_recursion2.rs:88:32 | LL | field_direct(flag - 1, a) | ^ diff --git a/tests/ui/op_ref.fixed b/tests/ui/op_ref.fixed index 183dcf4f0863..46a59e419cce 100644 --- a/tests/ui/op_ref.fixed +++ b/tests/ui/op_ref.fixed @@ -9,8 +9,7 @@ fn main() { let unwanted = &tracked_fds - &new_fds; let foo = 5 - 6; - //~^ ERROR: needlessly taken reference of both operands - //~| NOTE: `-D clippy::op-ref` implied by `-D warnings` + //~^ op_ref let bar = String::new(); let bar = "foo" == &bar; @@ -56,7 +55,7 @@ fn main() { let x = Y(1); let y = Y(2); let z = x & y; - //~^ ERROR: taken reference of right operand + //~^ op_ref } #[derive(Clone, Copy)] @@ -90,9 +89,11 @@ impl Mul for A { let two = 2; let three = 3; let _ = one * self; - //~^ ERROR: taken reference of right operand + //~^ op_ref + let _ = two + three; - //~^ ERROR: taken reference of right operand + //~^ op_ref + // Removing the reference would lead to unconditional recursion self * &rhs } diff --git a/tests/ui/op_ref.rs b/tests/ui/op_ref.rs index 6ed4f23d2bd7..e10840ff4b97 100644 --- a/tests/ui/op_ref.rs +++ b/tests/ui/op_ref.rs @@ -9,8 +9,7 @@ fn main() { let unwanted = &tracked_fds - &new_fds; let foo = &5 - &6; - //~^ ERROR: needlessly taken reference of both operands - //~| NOTE: `-D clippy::op-ref` implied by `-D warnings` + //~^ op_ref let bar = String::new(); let bar = "foo" == &bar; @@ -56,7 +55,7 @@ fn main() { let x = Y(1); let y = Y(2); let z = x & &y; - //~^ ERROR: taken reference of right operand + //~^ op_ref } #[derive(Clone, Copy)] @@ -90,9 +89,11 @@ impl Mul for A { let two = 2; let three = 3; let _ = one * &self; - //~^ ERROR: taken reference of right operand + //~^ op_ref + let _ = two + &three; - //~^ ERROR: taken reference of right operand + //~^ op_ref + // Removing the reference would lead to unconditional recursion self * &rhs } diff --git a/tests/ui/op_ref.stderr b/tests/ui/op_ref.stderr index ad002437c0c6..51c2963a9eed 100644 --- a/tests/ui/op_ref.stderr +++ b/tests/ui/op_ref.stderr @@ -13,7 +13,7 @@ LL + let foo = 5 - 6; | error: taken reference of right operand - --> tests/ui/op_ref.rs:58:13 + --> tests/ui/op_ref.rs:57:13 | LL | let z = x & &y; | ^^^^-- @@ -21,7 +21,7 @@ LL | let z = x & &y; | help: use the right value directly: `y` error: taken reference of right operand - --> tests/ui/op_ref.rs:92:17 + --> tests/ui/op_ref.rs:91:17 | LL | let _ = one * &self; | ^^^^^^----- diff --git a/tests/ui/open_options.rs b/tests/ui/open_options.rs index 4acb3780df43..f2f6e6edb4de 100644 --- a/tests/ui/open_options.rs +++ b/tests/ui/open_options.rs @@ -15,28 +15,31 @@ impl OpenOptionsExt for OpenOptions { fn main() { OpenOptions::new().read(true).truncate(true).open("foo.txt"); - //~^ ERROR: file opened with `truncate` and `read` - //~| NOTE: `-D clippy::nonsensical-open-options` implied by `-D warnings` + //~^ nonsensical_open_options + OpenOptions::new().append(true).truncate(true).open("foo.txt"); - //~^ ERROR: file opened with `append` and `truncate` + //~^ nonsensical_open_options OpenOptions::new().read(true).read(false).open("foo.txt"); - //~^ ERROR: the method `read` is called more than once + //~^ nonsensical_open_options + OpenOptions::new() .create(true) .truncate(true) // Ensure we don't trigger suspicious open options by having create without truncate .create(false) - //~^ ERROR: the method `create` is called more than once + //~^ nonsensical_open_options .open("foo.txt"); OpenOptions::new().write(true).write(false).open("foo.txt"); - //~^ ERROR: the method `write` is called more than once + //~^ nonsensical_open_options + OpenOptions::new().append(true).append(false).open("foo.txt"); - //~^ ERROR: the method `append` is called more than once + //~^ nonsensical_open_options + OpenOptions::new().truncate(true).truncate(false).open("foo.txt"); - //~^ ERROR: the method `truncate` is called more than once + //~^ nonsensical_open_options std::fs::File::options().read(true).read(false).open("foo.txt"); - //~^ ERROR: the method `read` is called more than once + //~^ nonsensical_open_options let mut options = std::fs::OpenOptions::new(); options.read(true); diff --git a/tests/ui/open_options.stderr b/tests/ui/open_options.stderr index 19755bce46c8..11b2d55fa058 100644 --- a/tests/ui/open_options.stderr +++ b/tests/ui/open_options.stderr @@ -20,31 +20,31 @@ LL | OpenOptions::new().read(true).read(false).open("foo.txt"); | ^^^^^^^^^^^ error: the method `create` is called more than once - --> tests/ui/open_options.rs:28:10 + --> tests/ui/open_options.rs:29:10 | LL | .create(false) | ^^^^^^^^^^^^^ error: the method `write` is called more than once - --> tests/ui/open_options.rs:31:36 + --> tests/ui/open_options.rs:32:36 | LL | OpenOptions::new().write(true).write(false).open("foo.txt"); | ^^^^^^^^^^^^ error: the method `append` is called more than once - --> tests/ui/open_options.rs:33:37 + --> tests/ui/open_options.rs:35:37 | LL | OpenOptions::new().append(true).append(false).open("foo.txt"); | ^^^^^^^^^^^^^ error: the method `truncate` is called more than once - --> tests/ui/open_options.rs:35:39 + --> tests/ui/open_options.rs:38:39 | LL | OpenOptions::new().truncate(true).truncate(false).open("foo.txt"); | ^^^^^^^^^^^^^^^ error: the method `read` is called more than once - --> tests/ui/open_options.rs:38:41 + --> tests/ui/open_options.rs:41:41 | LL | std::fs::File::options().read(true).read(false).open("foo.txt"); | ^^^^^^^^^^^ diff --git a/tests/ui/open_options_fixable.fixed b/tests/ui/open_options_fixable.fixed index 90a129a9bdff..7f601eec2cf0 100644 --- a/tests/ui/open_options_fixable.fixed +++ b/tests/ui/open_options_fixable.fixed @@ -3,5 +3,5 @@ use std::fs::OpenOptions; #[warn(clippy::suspicious_open_options)] fn main() { OpenOptions::new().create(true).truncate(true).open("foo.txt"); - //~^ ERROR: file opened with `create`, but `truncate` behavior not defined + //~^ suspicious_open_options } diff --git a/tests/ui/open_options_fixable.rs b/tests/ui/open_options_fixable.rs index 3a9e522ba150..5f03528d7a56 100644 --- a/tests/ui/open_options_fixable.rs +++ b/tests/ui/open_options_fixable.rs @@ -3,5 +3,5 @@ use std::fs::OpenOptions; #[warn(clippy::suspicious_open_options)] fn main() { OpenOptions::new().create(true).open("foo.txt"); - //~^ ERROR: file opened with `create`, but `truncate` behavior not defined + //~^ suspicious_open_options } diff --git a/tests/ui/option_as_ref_cloned.fixed b/tests/ui/option_as_ref_cloned.fixed index 394dad219f77..cf21d1c0176e 100644 --- a/tests/ui/option_as_ref_cloned.fixed +++ b/tests/ui/option_as_ref_cloned.fixed @@ -5,10 +5,13 @@ fn main() { let mut x = Some(String::new()); let _: Option = x.clone(); + //~^ option_as_ref_cloned let _: Option = x.clone(); + //~^ option_as_ref_cloned let y = x.as_ref(); let _: Option<&String> = y.clone(); + //~^ option_as_ref_cloned macro_rules! cloned_recv { () => { diff --git a/tests/ui/option_as_ref_cloned.rs b/tests/ui/option_as_ref_cloned.rs index 7243957927b2..354638c4c380 100644 --- a/tests/ui/option_as_ref_cloned.rs +++ b/tests/ui/option_as_ref_cloned.rs @@ -5,10 +5,13 @@ fn main() { let mut x = Some(String::new()); let _: Option = x.as_ref().cloned(); + //~^ option_as_ref_cloned let _: Option = x.as_mut().cloned(); + //~^ option_as_ref_cloned let y = x.as_ref(); let _: Option<&String> = y.as_ref().cloned(); + //~^ option_as_ref_cloned macro_rules! cloned_recv { () => { diff --git a/tests/ui/option_as_ref_cloned.stderr b/tests/ui/option_as_ref_cloned.stderr index 0eda42b91b96..9f650b90d539 100644 --- a/tests/ui/option_as_ref_cloned.stderr +++ b/tests/ui/option_as_ref_cloned.stderr @@ -13,7 +13,7 @@ LL + let _: Option = x.clone(); | error: cloning an `Option<_>` using `.as_mut().cloned()` - --> tests/ui/option_as_ref_cloned.rs:8:31 + --> tests/ui/option_as_ref_cloned.rs:9:31 | LL | let _: Option = x.as_mut().cloned(); | ^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + let _: Option = x.clone(); | error: cloning an `Option<_>` using `.as_ref().cloned()` - --> tests/ui/option_as_ref_cloned.rs:11:32 + --> tests/ui/option_as_ref_cloned.rs:13:32 | LL | let _: Option<&String> = y.as_ref().cloned(); | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/option_as_ref_deref.fixed b/tests/ui/option_as_ref_deref.fixed index c5a959ba566d..9be89b5d484f 100644 --- a/tests/ui/option_as_ref_deref.fixed +++ b/tests/ui/option_as_ref_deref.fixed @@ -9,25 +9,38 @@ fn main() { let mut opt = Some(String::from("123")); let _ = opt.clone().as_deref().map(str::len); + //~^ option_as_ref_deref #[rustfmt::skip] let _ = opt.clone().as_deref() .map(str::len); let _ = opt.as_deref_mut(); + //~^ option_as_ref_deref let _ = opt.as_deref(); + //~^ option_as_ref_deref let _ = opt.as_deref(); + //~^ option_as_ref_deref let _ = opt.as_deref_mut(); + //~^ option_as_ref_deref let _ = opt.as_deref_mut(); + //~^ option_as_ref_deref let _ = Some(CString::new(vec![]).unwrap()).as_deref(); + //~^ option_as_ref_deref let _ = Some(OsString::new()).as_deref(); + //~^ option_as_ref_deref let _ = Some(PathBuf::new()).as_deref(); + //~^ option_as_ref_deref let _ = Some(Vec::<()>::new()).as_deref(); + //~^ option_as_ref_deref let _ = Some(Vec::<()>::new()).as_deref_mut(); + //~^ option_as_ref_deref let _ = opt.as_deref(); + //~^ option_as_ref_deref let _ = opt.clone().as_deref_mut().map(|x| x.len()); + //~^ option_as_ref_deref let vc = vec![String::new()]; let _ = Some(1_usize).as_ref().map(|x| vc[*x].as_str()); // should not be linted @@ -35,10 +48,13 @@ fn main() { let _: Option<&str> = Some(&String::new()).as_ref().map(|x| x.as_str()); // should not be linted let _ = opt.as_deref(); + //~^ option_as_ref_deref let _ = opt.as_deref_mut(); + //~^ option_as_ref_deref // Issue #5927 let _ = opt.as_deref(); + //~^ option_as_ref_deref } #[clippy::msrv = "1.39"] @@ -51,4 +67,5 @@ fn msrv_1_39() { fn msrv_1_40() { let opt = Some(String::from("123")); let _ = opt.as_deref(); + //~^ option_as_ref_deref } diff --git a/tests/ui/option_as_ref_deref.rs b/tests/ui/option_as_ref_deref.rs index 1aeedf211fe2..d6b29e5e61b1 100644 --- a/tests/ui/option_as_ref_deref.rs +++ b/tests/ui/option_as_ref_deref.rs @@ -9,28 +9,42 @@ fn main() { let mut opt = Some(String::from("123")); let _ = opt.clone().as_ref().map(Deref::deref).map(str::len); + //~^ option_as_ref_deref #[rustfmt::skip] let _ = opt.clone() + //~^ option_as_ref_deref .as_ref().map( Deref::deref ) .map(str::len); let _ = opt.as_mut().map(DerefMut::deref_mut); + //~^ option_as_ref_deref let _ = opt.as_ref().map(String::as_str); + //~^ option_as_ref_deref let _ = opt.as_ref().map(|x| x.as_str()); + //~^ option_as_ref_deref let _ = opt.as_mut().map(String::as_mut_str); + //~^ option_as_ref_deref let _ = opt.as_mut().map(|x| x.as_mut_str()); + //~^ option_as_ref_deref let _ = Some(CString::new(vec![]).unwrap()).as_ref().map(CString::as_c_str); + //~^ option_as_ref_deref let _ = Some(OsString::new()).as_ref().map(OsString::as_os_str); + //~^ option_as_ref_deref let _ = Some(PathBuf::new()).as_ref().map(PathBuf::as_path); + //~^ option_as_ref_deref let _ = Some(Vec::<()>::new()).as_ref().map(Vec::as_slice); + //~^ option_as_ref_deref let _ = Some(Vec::<()>::new()).as_mut().map(Vec::as_mut_slice); + //~^ option_as_ref_deref let _ = opt.as_ref().map(|x| x.deref()); + //~^ option_as_ref_deref let _ = opt.clone().as_mut().map(|x| x.deref_mut()).map(|x| x.len()); + //~^ option_as_ref_deref let vc = vec![String::new()]; let _ = Some(1_usize).as_ref().map(|x| vc[*x].as_str()); // should not be linted @@ -38,10 +52,13 @@ fn main() { let _: Option<&str> = Some(&String::new()).as_ref().map(|x| x.as_str()); // should not be linted let _ = opt.as_ref().map(|x| &**x); + //~^ option_as_ref_deref let _ = opt.as_mut().map(|x| &mut **x); + //~^ option_as_ref_deref // Issue #5927 let _ = opt.as_ref().map(std::ops::Deref::deref); + //~^ option_as_ref_deref } #[clippy::msrv = "1.39"] @@ -54,4 +71,5 @@ fn msrv_1_39() { fn msrv_1_40() { let opt = Some(String::from("123")); let _ = opt.as_ref().map(String::as_str); + //~^ option_as_ref_deref } diff --git a/tests/ui/option_as_ref_deref.stderr b/tests/ui/option_as_ref_deref.stderr index 8b7f47a1b9af..ca924aec66dd 100644 --- a/tests/ui/option_as_ref_deref.stderr +++ b/tests/ui/option_as_ref_deref.stderr @@ -8,107 +8,108 @@ LL | let _ = opt.clone().as_ref().map(Deref::deref).map(str::len); = help: to override `-D warnings` add `#[allow(clippy::option_as_ref_deref)]` error: called `.as_ref().map(Deref::deref)` on an `Option` value - --> tests/ui/option_as_ref_deref.rs:14:13 + --> tests/ui/option_as_ref_deref.rs:15:13 | LL | let _ = opt.clone() | _____________^ +LL | | LL | | .as_ref().map( LL | | Deref::deref LL | | ) | |_________^ help: consider using as_deref: `opt.clone().as_deref()` error: called `.as_mut().map(DerefMut::deref_mut)` on an `Option` value - --> tests/ui/option_as_ref_deref.rs:20:13 + --> tests/ui/option_as_ref_deref.rs:22:13 | LL | let _ = opt.as_mut().map(DerefMut::deref_mut); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref_mut: `opt.as_deref_mut()` error: called `.as_ref().map(String::as_str)` on an `Option` value - --> tests/ui/option_as_ref_deref.rs:22:13 + --> tests/ui/option_as_ref_deref.rs:25:13 | LL | let _ = opt.as_ref().map(String::as_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `opt.as_deref()` error: called `.as_ref().map(|x| x.as_str())` on an `Option` value - --> tests/ui/option_as_ref_deref.rs:23:13 + --> tests/ui/option_as_ref_deref.rs:27:13 | LL | let _ = opt.as_ref().map(|x| x.as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `opt.as_deref()` error: called `.as_mut().map(String::as_mut_str)` on an `Option` value - --> tests/ui/option_as_ref_deref.rs:24:13 + --> tests/ui/option_as_ref_deref.rs:29:13 | LL | let _ = opt.as_mut().map(String::as_mut_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref_mut: `opt.as_deref_mut()` error: called `.as_mut().map(|x| x.as_mut_str())` on an `Option` value - --> tests/ui/option_as_ref_deref.rs:25:13 + --> tests/ui/option_as_ref_deref.rs:31:13 | LL | let _ = opt.as_mut().map(|x| x.as_mut_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref_mut: `opt.as_deref_mut()` error: called `.as_ref().map(CString::as_c_str)` on an `Option` value - --> tests/ui/option_as_ref_deref.rs:26:13 + --> tests/ui/option_as_ref_deref.rs:33:13 | LL | let _ = Some(CString::new(vec![]).unwrap()).as_ref().map(CString::as_c_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `Some(CString::new(vec![]).unwrap()).as_deref()` error: called `.as_ref().map(OsString::as_os_str)` on an `Option` value - --> tests/ui/option_as_ref_deref.rs:27:13 + --> tests/ui/option_as_ref_deref.rs:35:13 | LL | let _ = Some(OsString::new()).as_ref().map(OsString::as_os_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `Some(OsString::new()).as_deref()` error: called `.as_ref().map(PathBuf::as_path)` on an `Option` value - --> tests/ui/option_as_ref_deref.rs:28:13 + --> tests/ui/option_as_ref_deref.rs:37:13 | LL | let _ = Some(PathBuf::new()).as_ref().map(PathBuf::as_path); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `Some(PathBuf::new()).as_deref()` error: called `.as_ref().map(Vec::as_slice)` on an `Option` value - --> tests/ui/option_as_ref_deref.rs:29:13 + --> tests/ui/option_as_ref_deref.rs:39:13 | LL | let _ = Some(Vec::<()>::new()).as_ref().map(Vec::as_slice); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `Some(Vec::<()>::new()).as_deref()` error: called `.as_mut().map(Vec::as_mut_slice)` on an `Option` value - --> tests/ui/option_as_ref_deref.rs:30:13 + --> tests/ui/option_as_ref_deref.rs:41:13 | LL | let _ = Some(Vec::<()>::new()).as_mut().map(Vec::as_mut_slice); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref_mut: `Some(Vec::<()>::new()).as_deref_mut()` error: called `.as_ref().map(|x| x.deref())` on an `Option` value - --> tests/ui/option_as_ref_deref.rs:32:13 + --> tests/ui/option_as_ref_deref.rs:44:13 | LL | let _ = opt.as_ref().map(|x| x.deref()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `opt.as_deref()` error: called `.as_mut().map(|x| x.deref_mut())` on an `Option` value - --> tests/ui/option_as_ref_deref.rs:33:13 + --> tests/ui/option_as_ref_deref.rs:46:13 | LL | let _ = opt.clone().as_mut().map(|x| x.deref_mut()).map(|x| x.len()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref_mut: `opt.clone().as_deref_mut()` error: called `.as_ref().map(|x| &**x)` on an `Option` value - --> tests/ui/option_as_ref_deref.rs:40:13 + --> tests/ui/option_as_ref_deref.rs:54:13 | LL | let _ = opt.as_ref().map(|x| &**x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `opt.as_deref()` error: called `.as_mut().map(|x| &mut **x)` on an `Option` value - --> tests/ui/option_as_ref_deref.rs:41:13 + --> tests/ui/option_as_ref_deref.rs:56:13 | LL | let _ = opt.as_mut().map(|x| &mut **x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref_mut: `opt.as_deref_mut()` error: called `.as_ref().map(std::ops::Deref::deref)` on an `Option` value - --> tests/ui/option_as_ref_deref.rs:44:13 + --> tests/ui/option_as_ref_deref.rs:60:13 | LL | let _ = opt.as_ref().map(std::ops::Deref::deref); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `opt.as_deref()` error: called `.as_ref().map(String::as_str)` on an `Option` value - --> tests/ui/option_as_ref_deref.rs:56:13 + --> tests/ui/option_as_ref_deref.rs:73:13 | LL | let _ = opt.as_ref().map(String::as_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `opt.as_deref()` diff --git a/tests/ui/option_env_unwrap.rs b/tests/ui/option_env_unwrap.rs index f8d382340f2f..b8476830efe5 100644 --- a/tests/ui/option_env_unwrap.rs +++ b/tests/ui/option_env_unwrap.rs @@ -8,10 +8,18 @@ use proc_macros::{external, inline_macros}; #[inline_macros] fn main() { let _ = option_env!("PATH").unwrap(); + //~^ option_env_unwrap let _ = option_env!("PATH").expect("environment variable PATH isn't set"); + //~^ option_env_unwrap let _ = option_env!("__Y__do_not_use").unwrap(); // This test only works if you don't have a __Y__do_not_use env variable in your environment. + // + //~^^ option_env_unwrap let _ = inline!(option_env!($"PATH").unwrap()); + //~^ option_env_unwrap let _ = inline!(option_env!($"PATH").expect($"environment variable PATH isn't set")); + //~^ option_env_unwrap let _ = external!(option_env!($"PATH").unwrap()); + //~^ option_env_unwrap let _ = external!(option_env!($"PATH").expect($"environment variable PATH isn't set")); + //~^ option_env_unwrap } diff --git a/tests/ui/option_env_unwrap.stderr b/tests/ui/option_env_unwrap.stderr index 169523269fbb..bbcbfedb7882 100644 --- a/tests/ui/option_env_unwrap.stderr +++ b/tests/ui/option_env_unwrap.stderr @@ -9,7 +9,7 @@ LL | let _ = option_env!("PATH").unwrap(); = help: to override `-D warnings` add `#[allow(clippy::option_env_unwrap)]` error: this will panic at run-time if the environment variable doesn't exist at compile-time - --> tests/ui/option_env_unwrap.rs:11:13 + --> tests/ui/option_env_unwrap.rs:12:13 | LL | let _ = option_env!("PATH").expect("environment variable PATH isn't set"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | let _ = option_env!("PATH").expect("environment variable PATH isn't set = help: consider using the `env!` macro instead error: this will panic at run-time if the environment variable doesn't exist at compile-time - --> tests/ui/option_env_unwrap.rs:12:13 + --> tests/ui/option_env_unwrap.rs:14:13 | LL | let _ = option_env!("__Y__do_not_use").unwrap(); // This test only works if you don't have a __Y__do_not_use env variable in your env... | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | let _ = option_env!("__Y__do_not_use").unwrap(); // This test only work = help: consider using the `env!` macro instead error: this will panic at run-time if the environment variable doesn't exist at compile-time - --> tests/ui/option_env_unwrap.rs:13:21 + --> tests/ui/option_env_unwrap.rs:17:21 | LL | let _ = inline!(option_env!($"PATH").unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,7 +34,7 @@ LL | let _ = inline!(option_env!($"PATH").unwrap()); = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info) error: this will panic at run-time if the environment variable doesn't exist at compile-time - --> tests/ui/option_env_unwrap.rs:14:21 + --> tests/ui/option_env_unwrap.rs:19:21 | LL | let _ = inline!(option_env!($"PATH").expect($"environment variable PATH isn't set")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -43,7 +43,7 @@ LL | let _ = inline!(option_env!($"PATH").expect($"environment variable PATH = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info) error: this will panic at run-time if the environment variable doesn't exist at compile-time - --> tests/ui/option_env_unwrap.rs:15:13 + --> tests/ui/option_env_unwrap.rs:21:13 | LL | let _ = external!(option_env!($"PATH").unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,7 +52,7 @@ LL | let _ = external!(option_env!($"PATH").unwrap()); = note: this error originates in the macro `external` (in Nightly builds, run with -Z macro-backtrace for more info) error: this will panic at run-time if the environment variable doesn't exist at compile-time - --> tests/ui/option_env_unwrap.rs:16:13 + --> tests/ui/option_env_unwrap.rs:23:13 | LL | let _ = external!(option_env!($"PATH").expect($"environment variable PATH isn't set")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/option_filter_map.fixed b/tests/ui/option_filter_map.fixed index b1c3cfa48a44..d390c41af53c 100644 --- a/tests/ui/option_filter_map.fixed +++ b/tests/ui/option_filter_map.fixed @@ -3,18 +3,23 @@ fn main() { let _ = Some(Some(1)).flatten(); - //~^ ERROR: `filter` for `Some` followed by `unwrap` + //~^ option_filter_map + let _ = Some(Some(1)).flatten(); - //~^ ERROR: `filter` for `Some` followed by `unwrap` + //~^ option_filter_map + let _ = Some(1).map(odds_out).flatten(); - //~^ ERROR: `filter` for `Some` followed by `unwrap` + //~^ option_filter_map + let _ = Some(1).map(odds_out).flatten(); - //~^ ERROR: `filter` for `Some` followed by `unwrap` + //~^ option_filter_map let _ = vec![Some(1)].into_iter().flatten(); - //~^ ERROR: `filter` for `Some` followed by `unwrap` + //~^ option_filter_map + let _ = vec![Some(1)].into_iter().flatten(); - //~^ ERROR: `filter` for `Some` followed by `unwrap` + //~^ option_filter_map + let _ = vec![1] .into_iter() .map(odds_out) diff --git a/tests/ui/option_filter_map.rs b/tests/ui/option_filter_map.rs index 2550b9cd2b36..2d3b983a7670 100644 --- a/tests/ui/option_filter_map.rs +++ b/tests/ui/option_filter_map.rs @@ -3,29 +3,34 @@ fn main() { let _ = Some(Some(1)).filter(Option::is_some).map(Option::unwrap); - //~^ ERROR: `filter` for `Some` followed by `unwrap` + //~^ option_filter_map + let _ = Some(Some(1)).filter(|o| o.is_some()).map(|o| o.unwrap()); - //~^ ERROR: `filter` for `Some` followed by `unwrap` + //~^ option_filter_map + let _ = Some(1).map(odds_out).filter(Option::is_some).map(Option::unwrap); - //~^ ERROR: `filter` for `Some` followed by `unwrap` + //~^ option_filter_map + let _ = Some(1).map(odds_out).filter(|o| o.is_some()).map(|o| o.unwrap()); - //~^ ERROR: `filter` for `Some` followed by `unwrap` + //~^ option_filter_map let _ = vec![Some(1)].into_iter().filter(Option::is_some).map(Option::unwrap); - //~^ ERROR: `filter` for `Some` followed by `unwrap` + //~^ option_filter_map + let _ = vec![Some(1)].into_iter().filter(|o| o.is_some()).map(|o| o.unwrap()); - //~^ ERROR: `filter` for `Some` followed by `unwrap` + //~^ option_filter_map + let _ = vec![1] .into_iter() .map(odds_out) .filter(Option::is_some) - //~^ ERROR: `filter` for `Some` followed by `unwrap` + //~^ option_filter_map .map(Option::unwrap); let _ = vec![1] .into_iter() .map(odds_out) .filter(|o| o.is_some()) - //~^ ERROR: `filter` for `Some` followed by `unwrap` + //~^ option_filter_map .map(|o| o.unwrap()); } diff --git a/tests/ui/option_filter_map.stderr b/tests/ui/option_filter_map.stderr index 401ac2b2296d..df3c1f9d47b8 100644 --- a/tests/ui/option_filter_map.stderr +++ b/tests/ui/option_filter_map.stderr @@ -8,37 +8,37 @@ LL | let _ = Some(Some(1)).filter(Option::is_some).map(Option::unwrap); = help: to override `-D warnings` add `#[allow(clippy::option_filter_map)]` error: `filter` for `Some` followed by `unwrap` - --> tests/ui/option_filter_map.rs:7:27 + --> tests/ui/option_filter_map.rs:8:27 | LL | let _ = Some(Some(1)).filter(|o| o.is_some()).map(|o| o.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `Some` followed by `unwrap` - --> tests/ui/option_filter_map.rs:9:35 + --> tests/ui/option_filter_map.rs:11:35 | LL | let _ = Some(1).map(odds_out).filter(Option::is_some).map(Option::unwrap); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `Some` followed by `unwrap` - --> tests/ui/option_filter_map.rs:11:35 + --> tests/ui/option_filter_map.rs:14:35 | LL | let _ = Some(1).map(odds_out).filter(|o| o.is_some()).map(|o| o.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `Some` followed by `unwrap` - --> tests/ui/option_filter_map.rs:14:39 + --> tests/ui/option_filter_map.rs:17:39 | LL | let _ = vec![Some(1)].into_iter().filter(Option::is_some).map(Option::unwrap); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `Some` followed by `unwrap` - --> tests/ui/option_filter_map.rs:16:39 + --> tests/ui/option_filter_map.rs:20:39 | LL | let _ = vec![Some(1)].into_iter().filter(|o| o.is_some()).map(|o| o.unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()` error: `filter` for `Some` followed by `unwrap` - --> tests/ui/option_filter_map.rs:21:10 + --> tests/ui/option_filter_map.rs:26:10 | LL | .filter(Option::is_some) | __________^ @@ -47,7 +47,7 @@ LL | | .map(Option::unwrap); | |____________________________^ help: consider using `flatten` instead: `flatten()` error: `filter` for `Some` followed by `unwrap` - --> tests/ui/option_filter_map.rs:27:10 + --> tests/ui/option_filter_map.rs:32:10 | LL | .filter(|o| o.is_some()) | __________^ diff --git a/tests/ui/option_if_let_else.fixed b/tests/ui/option_if_let_else.fixed index 0ac89bf0d8ea..f5a869cf2831 100644 --- a/tests/ui/option_if_let_else.fixed +++ b/tests/ui/option_if_let_else.fixed @@ -4,6 +4,7 @@ clippy::equatable_if_let, clippy::let_unit_value, clippy::redundant_locals, + clippy::manual_midpoint, clippy::manual_unwrap_or_default, clippy::manual_unwrap_or )] @@ -24,17 +25,23 @@ fn else_if_option(string: Option<&str>) -> Option<(bool, &str)> { fn unop_bad(string: &Option<&str>, mut num: Option) { let _ = string.map_or(0, |s| s.len()); + //~^ option_if_let_else let _ = num.as_ref().map_or(&0, |s| s); + //~^ option_if_let_else let _ = num.as_mut().map_or(&0, |s| { + //~^ option_if_let_else *s += 1; s }); let _ = num.as_ref().map_or(&0, |s| s); + //~^ option_if_let_else let _ = num.map_or(0, |mut s| { + //~^ option_if_let_else s += 1; s }); let _ = num.as_mut().map_or(&0, |s| { + //~^ option_if_let_else *s += 1; s }); @@ -42,6 +49,7 @@ fn unop_bad(string: &Option<&str>, mut num: Option) { fn longer_body(arg: Option) -> u32 { arg.map_or(13, |x| { + //~^ option_if_let_else let y = x * x; y * y }) @@ -98,6 +106,7 @@ fn test_result_impure_else(variable: Result) -> bool { println!("Err"); false }, |binding| { + //~^ option_if_let_else println!("Ok {binding}"); true }) @@ -119,6 +128,7 @@ fn complex_subpat() -> DummyEnum { fn main() { let optional = Some(5); let _ = optional.map_or(5, |x| x + 2); + //~^ option_if_let_else let _ = bad1(None); let _ = else_if_option(None); unop_bad(&None, None); @@ -153,10 +163,12 @@ fn main() { let s = String::new(); // Lint, both branches immutably borrow `s`. let _ = Some(0).map_or(s.len(), |x| s.len() + x); + //~^ option_if_let_else let s = String::new(); // Lint, `Some` branch consumes `s`, but else branch doesn't use `s`. let _ = Some(0).map_or(1, |x| { + //~^ option_if_let_else let s = s; s.len() + x }); @@ -200,6 +212,7 @@ fn main() { let _ = res.map_or(1, |a| a + 1); let _ = res.map_or(1, |a| a + 1); let _ = res.map_or(5, |a| a + 1); + //~^ option_if_let_else } #[allow(dead_code)] @@ -243,6 +256,7 @@ fn issue11429() { let mut _hashmap = opt.as_ref().map_or_else(HashMap::new, |hm| hm.clone()); let mut _hm = opt.as_ref().map_or_else(|| new_map!(), |hm| hm.clone()); + //~^ option_if_let_else } fn issue11893() { diff --git a/tests/ui/option_if_let_else.rs b/tests/ui/option_if_let_else.rs index b4f1b2cd1f7f..d48272e618ac 100644 --- a/tests/ui/option_if_let_else.rs +++ b/tests/ui/option_if_let_else.rs @@ -4,12 +4,14 @@ clippy::equatable_if_let, clippy::let_unit_value, clippy::redundant_locals, + clippy::manual_midpoint, clippy::manual_unwrap_or_default, clippy::manual_unwrap_or )] fn bad1(string: Option<&str>) -> (bool, &str) { if let Some(x) = string { + //~^ option_if_let_else (true, x) } else { (false, "hello") @@ -28,21 +30,27 @@ fn else_if_option(string: Option<&str>) -> Option<(bool, &str)> { fn unop_bad(string: &Option<&str>, mut num: Option) { let _ = if let Some(s) = *string { s.len() } else { 0 }; + //~^ option_if_let_else let _ = if let Some(s) = &num { s } else { &0 }; + //~^ option_if_let_else let _ = if let Some(s) = &mut num { + //~^ option_if_let_else *s += 1; s } else { &0 }; let _ = if let Some(ref s) = num { s } else { &0 }; + //~^ option_if_let_else let _ = if let Some(mut s) = num { + //~^ option_if_let_else s += 1; s } else { 0 }; let _ = if let Some(ref mut s) = num { + //~^ option_if_let_else *s += 1; s } else { @@ -52,6 +60,7 @@ fn unop_bad(string: &Option<&str>, mut num: Option) { fn longer_body(arg: Option) -> u32 { if let Some(x) = arg { + //~^ option_if_let_else let y = x * x; y * y } else { @@ -65,6 +74,7 @@ fn impure_else(arg: Option) { 1 }; let _ = if let Some(x) = arg { + //~^ option_if_let_else x } else { // map_or_else must be suggested @@ -74,6 +84,7 @@ fn impure_else(arg: Option) { fn test_map_or_else(arg: Option) { let _ = if let Some(x) = arg { + //~^ option_if_let_else x * x * x * x } else { let mut y = 1; @@ -107,6 +118,7 @@ fn pattern_to_vec(pattern: &str) -> Vec { .split('/') .flat_map(|s| { if let Some(idx) = s.find('.') { + //~^ option_if_let_else vec![s[..idx].to_string(), s[idx..].to_string()] } else { vec![s.to_string()] @@ -118,6 +130,7 @@ fn pattern_to_vec(pattern: &str) -> Vec { // #10335 fn test_result_impure_else(variable: Result) -> bool { if let Ok(binding) = variable { + //~^ option_if_let_else println!("Ok {binding}"); true } else { @@ -142,6 +155,7 @@ fn complex_subpat() -> DummyEnum { fn main() { let optional = Some(5); let _ = if let Some(x) = optional { x + 2 } else { 5 }; + //~^ option_if_let_else let _ = bad1(None); let _ = else_if_option(None); unop_bad(&None, None); @@ -152,6 +166,7 @@ fn main() { let _ = impure_else(None); let _ = if let Some(x) = Some(0) { + //~^ option_if_let_else loop { if x == 0 { break x; @@ -180,10 +195,12 @@ fn main() { let s = String::new(); // Lint, both branches immutably borrow `s`. let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() }; + //~^ option_if_let_else let s = String::new(); // Lint, `Some` branch consumes `s`, but else branch doesn't use `s`. let _ = if let Some(x) = Some(0) { + //~^ option_if_let_else let s = s; s.len() + x } else { @@ -223,24 +240,29 @@ fn main() { // issue #8492 let _ = match s { + //~^ option_if_let_else Some(string) => string.len(), None => 1, }; let _ = match Some(10) { + //~^ option_if_let_else Some(a) => a + 1, None => 5, }; let res: Result = Ok(5); let _ = match res { + //~^ option_if_let_else Ok(a) => a + 1, _ => 1, }; let _ = match res { + //~^ option_if_let_else Err(_) => 1, Ok(a) => a + 1, }; let _ = if let Ok(a) = res { a + 1 } else { 5 }; + //~^ option_if_let_else } #[allow(dead_code)] @@ -258,6 +280,7 @@ mod issue10729 { pub fn reproduce(initial: &Option) { // 👇 needs `.as_ref()` because initial is an `&Option<_>` let _ = match initial { + //~^ option_if_let_else Some(value) => do_something(value), None => 42, }; @@ -265,6 +288,7 @@ mod issue10729 { pub fn reproduce2(initial: &mut Option) { let _ = match initial { + //~^ option_if_let_else Some(value) => do_something2(value), None => 42, }; @@ -288,12 +312,14 @@ fn issue11429() { let opt: Option> = None; let mut _hashmap = if let Some(hm) = &opt { + //~^ option_if_let_else hm.clone() } else { HashMap::new() }; let mut _hm = if let Some(hm) = &opt { hm.clone() } else { new_map!() }; + //~^ option_if_let_else } fn issue11893() { diff --git a/tests/ui/option_if_let_else.stderr b/tests/ui/option_if_let_else.stderr index 32ff22763234..9eb41f81a539 100644 --- a/tests/ui/option_if_let_else.stderr +++ b/tests/ui/option_if_let_else.stderr @@ -1,7 +1,8 @@ error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:12:5 + --> tests/ui/option_if_let_else.rs:13:5 | LL | / if let Some(x) = string { +LL | | LL | | (true, x) LL | | } else { LL | | (false, "hello") @@ -12,22 +13,23 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::option_if_let_else)]` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:30:13 + --> tests/ui/option_if_let_else.rs:32:13 | LL | let _ = if let Some(s) = *string { s.len() } else { 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `string.map_or(0, |s| s.len())` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:31:13 + --> tests/ui/option_if_let_else.rs:34:13 | LL | let _ = if let Some(s) = &num { s } else { &0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:32:13 + --> tests/ui/option_if_let_else.rs:36:13 | LL | let _ = if let Some(s) = &mut num { | _____________^ +LL | | LL | | *s += 1; LL | | s LL | | } else { @@ -38,22 +40,24 @@ LL | | }; help: try | LL ~ let _ = num.as_mut().map_or(&0, |s| { +LL + LL + *s += 1; LL + s LL ~ }); | error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:38:13 + --> tests/ui/option_if_let_else.rs:43:13 | LL | let _ = if let Some(ref s) = num { s } else { &0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:39:13 + --> tests/ui/option_if_let_else.rs:45:13 | LL | let _ = if let Some(mut s) = num { | _____________^ +LL | | LL | | s += 1; LL | | s LL | | } else { @@ -64,16 +68,18 @@ LL | | }; help: try | LL ~ let _ = num.map_or(0, |mut s| { +LL + LL + s += 1; LL + s LL ~ }); | error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:45:13 + --> tests/ui/option_if_let_else.rs:52:13 | LL | let _ = if let Some(ref mut s) = num { | _____________^ +LL | | LL | | *s += 1; LL | | s LL | | } else { @@ -84,15 +90,17 @@ LL | | }; help: try | LL ~ let _ = num.as_mut().map_or(&0, |s| { +LL + LL + *s += 1; LL + s LL ~ }); | error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:54:5 + --> tests/ui/option_if_let_else.rs:62:5 | LL | / if let Some(x) = arg { +LL | | LL | | let y = x * x; LL | | y * y LL | | } else { @@ -103,30 +111,33 @@ LL | | } help: try | LL ~ arg.map_or(13, |x| { +LL + LL + let y = x * x; LL + y * y LL + }) | -error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:67:13 - | -LL | let _ = if let Some(x) = arg { - | _____________^ -LL | | x -LL | | } else { -... | -LL | | }; - | |_____^ help: try: `arg.map_or_else(side_effect, |x| x)` - error: use Option::map_or_else instead of an if let/else --> tests/ui/option_if_let_else.rs:76:13 | LL | let _ = if let Some(x) = arg { | _____________^ +LL | | +LL | | x +LL | | } else { +LL | | // map_or_else must be suggested +LL | | side_effect() +LL | | }; + | |_____^ help: try: `arg.map_or_else(side_effect, |x| x)` + +error: use Option::map_or_else instead of an if let/else + --> tests/ui/option_if_let_else.rs:86:13 + | +LL | let _ = if let Some(x) = arg { + | _____________^ +LL | | LL | | x * x * x * x LL | | } else { -LL | | let mut y = 1; ... | LL | | y LL | | }; @@ -143,9 +154,10 @@ LL ~ }, |x| x * x * x * x); | error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:109:13 + --> tests/ui/option_if_let_else.rs:120:13 | LL | / if let Some(idx) = s.find('.') { +LL | | LL | | vec![s[..idx].to_string(), s[idx..].to_string()] LL | | } else { LL | | vec![s.to_string()] @@ -153,13 +165,13 @@ LL | | } | |_____________^ help: try: `s.find('.').map_or_else(|| vec![s.to_string()], |idx| vec![s[..idx].to_string(), s[idx..].to_string()])` error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:120:5 + --> tests/ui/option_if_let_else.rs:132:5 | LL | / if let Ok(binding) = variable { +LL | | LL | | println!("Ok {binding}"); LL | | true -LL | | } else { -LL | | println!("Err"); +... | LL | | false LL | | } | |_____^ @@ -170,25 +182,26 @@ LL ~ variable.map_or_else(|_| { LL + println!("Err"); LL + false LL + }, |binding| { +LL + LL + println!("Ok {binding}"); LL + true LL + }) | error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:144:13 + --> tests/ui/option_if_let_else.rs:157:13 | LL | let _ = if let Some(x) = optional { x + 2 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:154:13 + --> tests/ui/option_if_let_else.rs:168:13 | LL | let _ = if let Some(x) = Some(0) { | _____________^ +LL | | LL | | loop { LL | | if x == 0 { -LL | | break x; ... | LL | | 0 LL | | }; @@ -204,16 +217,17 @@ LL ~ }); | error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:182:13 + --> tests/ui/option_if_let_else.rs:197:13 | LL | let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(0).map_or(s.len(), |x| s.len() + x)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:186:13 + --> tests/ui/option_if_let_else.rs:202:13 | LL | let _ = if let Some(x) = Some(0) { | _____________^ +LL | | LL | | let s = s; LL | | s.len() + x LL | | } else { @@ -224,82 +238,90 @@ LL | | }; help: try | LL ~ let _ = Some(0).map_or(1, |x| { +LL + LL + let s = s; LL + s.len() + x LL ~ }); | error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:225:13 + --> tests/ui/option_if_let_else.rs:242:13 | LL | let _ = match s { | _____________^ +LL | | LL | | Some(string) => string.len(), LL | | None => 1, LL | | }; | |_____^ help: try: `s.map_or(1, |string| string.len())` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:229:13 + --> tests/ui/option_if_let_else.rs:247:13 | LL | let _ = match Some(10) { | _____________^ +LL | | LL | | Some(a) => a + 1, LL | | None => 5, LL | | }; | |_____^ help: try: `Some(10).map_or(5, |a| a + 1)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:235:13 + --> tests/ui/option_if_let_else.rs:254:13 | LL | let _ = match res { | _____________^ +LL | | LL | | Ok(a) => a + 1, LL | | _ => 1, LL | | }; | |_____^ help: try: `res.map_or(1, |a| a + 1)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:239:13 + --> tests/ui/option_if_let_else.rs:259:13 | LL | let _ = match res { | _____________^ +LL | | LL | | Err(_) => 1, LL | | Ok(a) => a + 1, LL | | }; | |_____^ help: try: `res.map_or(1, |a| a + 1)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:243:13 + --> tests/ui/option_if_let_else.rs:264:13 | LL | let _ = if let Ok(a) = res { a + 1 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or(5, |a| a + 1)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:260:17 + --> tests/ui/option_if_let_else.rs:282:17 | LL | let _ = match initial { | _________________^ +LL | | LL | | Some(value) => do_something(value), LL | | None => 42, LL | | }; | |_________^ help: try: `initial.as_ref().map_or(42, |value| do_something(value))` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:267:17 + --> tests/ui/option_if_let_else.rs:290:17 | LL | let _ = match initial { | _________________^ +LL | | LL | | Some(value) => do_something2(value), LL | | None => 42, LL | | }; | |_________^ help: try: `initial.as_mut().map_or(42, |value| do_something2(value))` error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:290:24 + --> tests/ui/option_if_let_else.rs:314:24 | LL | let mut _hashmap = if let Some(hm) = &opt { | ________________________^ +LL | | LL | | hm.clone() LL | | } else { LL | | HashMap::new() @@ -307,7 +329,7 @@ LL | | }; | |_____^ help: try: `opt.as_ref().map_or_else(HashMap::new, |hm| hm.clone())` error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:296:19 + --> tests/ui/option_if_let_else.rs:321:19 | LL | let mut _hm = if let Some(hm) = &opt { hm.clone() } else { new_map!() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.as_ref().map_or_else(|| new_map!(), |hm| hm.clone())` diff --git a/tests/ui/option_map_or_err_ok.fixed b/tests/ui/option_map_or_err_ok.fixed deleted file mode 100644 index 131f4b2093e7..000000000000 --- a/tests/ui/option_map_or_err_ok.fixed +++ /dev/null @@ -1,7 +0,0 @@ -#![warn(clippy::option_map_or_err_ok)] - -fn main() { - let x = Some("a"); - let _ = x.ok_or("a"); - //~^ ERROR: called `map_or(Err(_), Ok)` on an `Option` value -} diff --git a/tests/ui/option_map_or_err_ok.rs b/tests/ui/option_map_or_err_ok.rs deleted file mode 100644 index 0f07a592ae5f..000000000000 --- a/tests/ui/option_map_or_err_ok.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![warn(clippy::option_map_or_err_ok)] - -fn main() { - let x = Some("a"); - let _ = x.map_or(Err("a"), Ok); - //~^ ERROR: called `map_or(Err(_), Ok)` on an `Option` value -} diff --git a/tests/ui/option_map_or_err_ok.stderr b/tests/ui/option_map_or_err_ok.stderr deleted file mode 100644 index 1971af80aa8d..000000000000 --- a/tests/ui/option_map_or_err_ok.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: called `map_or(Err(_), Ok)` on an `Option` value - --> tests/ui/option_map_or_err_ok.rs:5:13 - | -LL | let _ = x.map_or(Err("a"), Ok); - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `ok_or`: `x.ok_or("a")` - | - = note: `-D clippy::option-map-or-err-ok` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::option_map_or_err_ok)]` - -error: aborting due to 1 previous error - diff --git a/tests/ui/option_map_or_none.fixed b/tests/ui/option_map_or_none.fixed index 5f0ef34d231c..183bf32e5361 100644 --- a/tests/ui/option_map_or_none.fixed +++ b/tests/ui/option_map_or_none.fixed @@ -8,12 +8,15 @@ fn main() { // Check `OPTION_MAP_OR_NONE`. // Single line case. let _: Option = opt.map(|x| x + 1); + //~^ option_map_or_none // Multi-line case. #[rustfmt::skip] let _: Option = opt.map(|x| x + 1); // function returning `Option` let _: Option = opt.and_then(bar); + //~^ option_map_or_none let _: Option = opt.and_then(|x| { + //~^ option_map_or_none let offset = 0; let height = x; Some(offset + height) @@ -21,4 +24,5 @@ fn main() { // Check `RESULT_MAP_OR_INTO_OPTION`. let _: Option = r.ok(); + //~^ result_map_or_into_option } diff --git a/tests/ui/option_map_or_none.rs b/tests/ui/option_map_or_none.rs index 56b1f61212d0..626f206b2598 100644 --- a/tests/ui/option_map_or_none.rs +++ b/tests/ui/option_map_or_none.rs @@ -8,14 +8,18 @@ fn main() { // Check `OPTION_MAP_OR_NONE`. // Single line case. let _: Option = opt.map_or(None, |x| Some(x + 1)); + //~^ option_map_or_none // Multi-line case. #[rustfmt::skip] let _: Option = opt.map_or(None, |x| { + //~^ option_map_or_none Some(x + 1) }); // function returning `Option` let _: Option = opt.map_or(None, bar); + //~^ option_map_or_none let _: Option = opt.map_or(None, |x| { + //~^ option_map_or_none let offset = 0; let height = x; Some(offset + height) @@ -23,4 +27,5 @@ fn main() { // Check `RESULT_MAP_OR_INTO_OPTION`. let _: Option = r.map_or(None, Some); + //~^ result_map_or_into_option } diff --git a/tests/ui/option_map_or_none.stderr b/tests/ui/option_map_or_none.stderr index cba29861296f..f9290fb99bc1 100644 --- a/tests/ui/option_map_or_none.stderr +++ b/tests/ui/option_map_or_none.stderr @@ -8,25 +8,27 @@ LL | let _: Option = opt.map_or(None, |x| Some(x + 1)); = help: to override `-D warnings` add `#[allow(clippy::option_map_or_none)]` error: called `map_or(None, ..)` on an `Option` value - --> tests/ui/option_map_or_none.rs:13:26 + --> tests/ui/option_map_or_none.rs:14:26 | LL | let _: Option = opt.map_or(None, |x| { | __________________________^ +LL | | LL | | Some(x + 1) LL | | }); | |_________________________^ help: consider using `map`: `opt.map(|x| x + 1)` error: called `map_or(None, ..)` on an `Option` value - --> tests/ui/option_map_or_none.rs:17:26 + --> tests/ui/option_map_or_none.rs:19:26 | LL | let _: Option = opt.map_or(None, bar); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `and_then`: `opt.and_then(bar)` error: called `map_or(None, ..)` on an `Option` value - --> tests/ui/option_map_or_none.rs:18:26 + --> tests/ui/option_map_or_none.rs:21:26 | LL | let _: Option = opt.map_or(None, |x| { | __________________________^ +LL | | LL | | let offset = 0; LL | | let height = x; LL | | Some(offset + height) @@ -36,6 +38,7 @@ LL | | }); help: consider using `and_then` | LL ~ let _: Option = opt.and_then(|x| { +LL + LL + let offset = 0; LL + let height = x; LL + Some(offset + height) @@ -43,7 +46,7 @@ LL ~ }); | error: called `map_or(None, Some)` on a `Result` value - --> tests/ui/option_map_or_none.rs:25:26 + --> tests/ui/option_map_or_none.rs:29:26 | LL | let _: Option = r.map_or(None, Some); | ^^^^^^^^^^^^^^^^^^^^ help: consider using `ok`: `r.ok()` diff --git a/tests/ui/option_map_unit_fn_fixable.fixed b/tests/ui/option_map_unit_fn_fixable.fixed index 5dcc6464ff5f..55c1b8f110ce 100644 --- a/tests/ui/option_map_unit_fn_fixable.fixed +++ b/tests/ui/option_map_unit_fn_fixable.fixed @@ -35,52 +35,71 @@ fn option_map_unit_fn() { let _ : Option<()> = x.field.map(do_nothing); if let Some(x_field) = x.field { do_nothing(x_field) } + //~^ option_map_unit_fn if let Some(x_field) = x.field { do_nothing(x_field) } + //~^ option_map_unit_fn if let Some(x_field) = x.field { diverge(x_field) } + //~^ option_map_unit_fn let captured = 10; if let Some(value) = x.field { do_nothing(value + captured) }; let _ : Option<()> = x.field.map(|value| do_nothing(value + captured)); if let Some(value) = x.field { x.do_option_nothing(value + captured) } + //~^ option_map_unit_fn if let Some(value) = x.field { x.do_option_plus_one(value + captured); } + //~^ option_map_unit_fn if let Some(value) = x.field { do_nothing(value + captured) } + //~^ option_map_unit_fn if let Some(value) = x.field { do_nothing(value + captured) } + //~^ option_map_unit_fn if let Some(value) = x.field { do_nothing(value + captured); } + //~^ option_map_unit_fn if let Some(value) = x.field { do_nothing(value + captured); } + //~^ option_map_unit_fn if let Some(value) = x.field { diverge(value + captured) } + //~^ option_map_unit_fn if let Some(value) = x.field { diverge(value + captured) } + //~^ option_map_unit_fn if let Some(value) = x.field { diverge(value + captured); } + //~^ option_map_unit_fn if let Some(value) = x.field { diverge(value + captured); } + //~^ option_map_unit_fn x.field.map(|value| plus_one(value + captured)); x.field.map(|value| { plus_one(value + captured) }); if let Some(value) = x.field { let y = plus_one(value + captured); } + //~^ option_map_unit_fn if let Some(value) = x.field { plus_one(value + captured); } + //~^ option_map_unit_fn if let Some(value) = x.field { plus_one(value + captured); } + //~^ option_map_unit_fn if let Some(ref value) = x.field { do_nothing(value + captured) } + //~^ option_map_unit_fn if let Some(a) = option() { do_nothing(a) } + //~^ option_map_unit_fn if let Some(value) = option() { println!("{:?}", value) } + //~^ option_map_unit_fn } fn main() {} diff --git a/tests/ui/option_map_unit_fn_fixable.rs b/tests/ui/option_map_unit_fn_fixable.rs index 5489545fe3d9..5ed47e4c60b5 100644 --- a/tests/ui/option_map_unit_fn_fixable.rs +++ b/tests/ui/option_map_unit_fn_fixable.rs @@ -35,52 +35,71 @@ fn option_map_unit_fn() { let _ : Option<()> = x.field.map(do_nothing); x.field.map(do_nothing); + //~^ option_map_unit_fn x.field.map(do_nothing); + //~^ option_map_unit_fn x.field.map(diverge); + //~^ option_map_unit_fn let captured = 10; if let Some(value) = x.field { do_nothing(value + captured) }; let _ : Option<()> = x.field.map(|value| do_nothing(value + captured)); x.field.map(|value| x.do_option_nothing(value + captured)); + //~^ option_map_unit_fn x.field.map(|value| { x.do_option_plus_one(value + captured); }); + //~^ option_map_unit_fn x.field.map(|value| do_nothing(value + captured)); + //~^ option_map_unit_fn x.field.map(|value| { do_nothing(value + captured) }); + //~^ option_map_unit_fn x.field.map(|value| { do_nothing(value + captured); }); + //~^ option_map_unit_fn x.field.map(|value| { { do_nothing(value + captured); } }); + //~^ option_map_unit_fn x.field.map(|value| diverge(value + captured)); + //~^ option_map_unit_fn x.field.map(|value| { diverge(value + captured) }); + //~^ option_map_unit_fn x.field.map(|value| { diverge(value + captured); }); + //~^ option_map_unit_fn x.field.map(|value| { { diverge(value + captured); } }); + //~^ option_map_unit_fn x.field.map(|value| plus_one(value + captured)); x.field.map(|value| { plus_one(value + captured) }); x.field.map(|value| { let y = plus_one(value + captured); }); + //~^ option_map_unit_fn x.field.map(|value| { plus_one(value + captured); }); + //~^ option_map_unit_fn x.field.map(|value| { { plus_one(value + captured); } }); + //~^ option_map_unit_fn x.field.map(|ref value| { do_nothing(value + captured) }); + //~^ option_map_unit_fn option().map(do_nothing); + //~^ option_map_unit_fn option().map(|value| println!("{:?}", value)); + //~^ option_map_unit_fn } fn main() {} diff --git a/tests/ui/option_map_unit_fn_fixable.stderr b/tests/ui/option_map_unit_fn_fixable.stderr index 5fd3dfd071c2..3f7abae34eea 100644 --- a/tests/ui/option_map_unit_fn_fixable.stderr +++ b/tests/ui/option_map_unit_fn_fixable.stderr @@ -10,7 +10,7 @@ LL | x.field.map(do_nothing); = help: to override `-D warnings` add `#[allow(clippy::option_map_unit_fn)]` error: called `map(f)` on an `Option` value where `f` is a function that returns the unit type `()` - --> tests/ui/option_map_unit_fn_fixable.rs:39:5 + --> tests/ui/option_map_unit_fn_fixable.rs:40:5 | LL | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- @@ -18,7 +18,7 @@ LL | x.field.map(do_nothing); | help: try: `if let Some(x_field) = x.field { do_nothing(x_field) }` error: called `map(f)` on an `Option` value where `f` is a function that returns the unit type `()` - --> tests/ui/option_map_unit_fn_fixable.rs:41:5 + --> tests/ui/option_map_unit_fn_fixable.rs:43:5 | LL | x.field.map(diverge); | ^^^^^^^^^^^^^^^^^^^^- @@ -26,7 +26,7 @@ LL | x.field.map(diverge); | help: try: `if let Some(x_field) = x.field { diverge(x_field) }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` - --> tests/ui/option_map_unit_fn_fixable.rs:47:5 + --> tests/ui/option_map_unit_fn_fixable.rs:50:5 | LL | x.field.map(|value| x.do_option_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -34,7 +34,7 @@ LL | x.field.map(|value| x.do_option_nothing(value + captured)); | help: try: `if let Some(value) = x.field { x.do_option_nothing(value + captured) }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` - --> tests/ui/option_map_unit_fn_fixable.rs:49:5 + --> tests/ui/option_map_unit_fn_fixable.rs:53:5 | LL | x.field.map(|value| { x.do_option_plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -42,7 +42,7 @@ LL | x.field.map(|value| { x.do_option_plus_one(value + captured); }); | help: try: `if let Some(value) = x.field { x.do_option_plus_one(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` - --> tests/ui/option_map_unit_fn_fixable.rs:52:5 + --> tests/ui/option_map_unit_fn_fixable.rs:57:5 | LL | x.field.map(|value| do_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -50,7 +50,7 @@ LL | x.field.map(|value| do_nothing(value + captured)); | help: try: `if let Some(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` - --> tests/ui/option_map_unit_fn_fixable.rs:54:5 + --> tests/ui/option_map_unit_fn_fixable.rs:60:5 | LL | x.field.map(|value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -58,7 +58,7 @@ LL | x.field.map(|value| { do_nothing(value + captured) }); | help: try: `if let Some(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` - --> tests/ui/option_map_unit_fn_fixable.rs:56:5 + --> tests/ui/option_map_unit_fn_fixable.rs:63:5 | LL | x.field.map(|value| { do_nothing(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -66,7 +66,7 @@ LL | x.field.map(|value| { do_nothing(value + captured); }); | help: try: `if let Some(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` - --> tests/ui/option_map_unit_fn_fixable.rs:58:5 + --> tests/ui/option_map_unit_fn_fixable.rs:66:5 | LL | x.field.map(|value| { { do_nothing(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -74,7 +74,7 @@ LL | x.field.map(|value| { { do_nothing(value + captured); } }); | help: try: `if let Some(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` - --> tests/ui/option_map_unit_fn_fixable.rs:61:5 + --> tests/ui/option_map_unit_fn_fixable.rs:70:5 | LL | x.field.map(|value| diverge(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -82,7 +82,7 @@ LL | x.field.map(|value| diverge(value + captured)); | help: try: `if let Some(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` - --> tests/ui/option_map_unit_fn_fixable.rs:63:5 + --> tests/ui/option_map_unit_fn_fixable.rs:73:5 | LL | x.field.map(|value| { diverge(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -90,7 +90,7 @@ LL | x.field.map(|value| { diverge(value + captured) }); | help: try: `if let Some(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` - --> tests/ui/option_map_unit_fn_fixable.rs:65:5 + --> tests/ui/option_map_unit_fn_fixable.rs:76:5 | LL | x.field.map(|value| { diverge(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -98,7 +98,7 @@ LL | x.field.map(|value| { diverge(value + captured); }); | help: try: `if let Some(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` - --> tests/ui/option_map_unit_fn_fixable.rs:67:5 + --> tests/ui/option_map_unit_fn_fixable.rs:79:5 | LL | x.field.map(|value| { { diverge(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -106,7 +106,7 @@ LL | x.field.map(|value| { { diverge(value + captured); } }); | help: try: `if let Some(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` - --> tests/ui/option_map_unit_fn_fixable.rs:72:5 + --> tests/ui/option_map_unit_fn_fixable.rs:85:5 | LL | x.field.map(|value| { let y = plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -114,7 +114,7 @@ LL | x.field.map(|value| { let y = plus_one(value + captured); }); | help: try: `if let Some(value) = x.field { let y = plus_one(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` - --> tests/ui/option_map_unit_fn_fixable.rs:74:5 + --> tests/ui/option_map_unit_fn_fixable.rs:88:5 | LL | x.field.map(|value| { plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -122,7 +122,7 @@ LL | x.field.map(|value| { plus_one(value + captured); }); | help: try: `if let Some(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` - --> tests/ui/option_map_unit_fn_fixable.rs:76:5 + --> tests/ui/option_map_unit_fn_fixable.rs:91:5 | LL | x.field.map(|value| { { plus_one(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -130,7 +130,7 @@ LL | x.field.map(|value| { { plus_one(value + captured); } }); | help: try: `if let Some(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` - --> tests/ui/option_map_unit_fn_fixable.rs:79:5 + --> tests/ui/option_map_unit_fn_fixable.rs:95:5 | LL | x.field.map(|ref value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -138,7 +138,7 @@ LL | x.field.map(|ref value| { do_nothing(value + captured) }); | help: try: `if let Some(ref value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an `Option` value where `f` is a function that returns the unit type `()` - --> tests/ui/option_map_unit_fn_fixable.rs:81:5 + --> tests/ui/option_map_unit_fn_fixable.rs:98:5 | LL | option().map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^^- @@ -146,7 +146,7 @@ LL | option().map(do_nothing); | help: try: `if let Some(a) = option() { do_nothing(a) }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()` - --> tests/ui/option_map_unit_fn_fixable.rs:83:5 + --> tests/ui/option_map_unit_fn_fixable.rs:101:5 | LL | option().map(|value| println!("{:?}", value)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- diff --git a/tests/ui/option_map_unit_fn_unfixable.rs b/tests/ui/option_map_unit_fn_unfixable.rs index 20e6c15b18d5..dd2f80fefbee 100644 --- a/tests/ui/option_map_unit_fn_unfixable.rs +++ b/tests/ui/option_map_unit_fn_unfixable.rs @@ -15,8 +15,10 @@ fn plus_one(value: usize) -> usize { fn option_map_unit_fn() { x.field.map(|value| { do_nothing(value); do_nothing(value) }); + //~^ ERROR: cannot find value x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); + //~^ ERROR: cannot find value // Suggestion for the let block should be `{ ... }` as it's too difficult to build a // proper suggestion for these cases @@ -24,7 +26,9 @@ fn option_map_unit_fn() { do_nothing(value); do_nothing(value) }); + //~^^^^ ERROR: cannot find value x.field.map(|value| { do_nothing(value); do_nothing(value); }); + //~^ ERROR: cannot find value // The following should suggest `if let Some(_X) ...` as it's difficult to generate a proper let variable name for them Some(42).map(diverge); diff --git a/tests/ui/option_map_unit_fn_unfixable.stderr b/tests/ui/option_map_unit_fn_unfixable.stderr index 66271036113c..852785014329 100644 --- a/tests/ui/option_map_unit_fn_unfixable.stderr +++ b/tests/ui/option_map_unit_fn_unfixable.stderr @@ -5,19 +5,19 @@ LL | x.field.map(|value| { do_nothing(value); do_nothing(value) }); | ^ not found in this scope error[E0425]: cannot find value `x` in this scope - --> tests/ui/option_map_unit_fn_unfixable.rs:19:5 + --> tests/ui/option_map_unit_fn_unfixable.rs:20:5 | LL | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); | ^ not found in this scope error[E0425]: cannot find value `x` in this scope - --> tests/ui/option_map_unit_fn_unfixable.rs:23:5 + --> tests/ui/option_map_unit_fn_unfixable.rs:25:5 | LL | x.field.map(|value| { | ^ not found in this scope error[E0425]: cannot find value `x` in this scope - --> tests/ui/option_map_unit_fn_unfixable.rs:27:5 + --> tests/ui/option_map_unit_fn_unfixable.rs:30:5 | LL | x.field.map(|value| { do_nothing(value); do_nothing(value); }); | ^ not found in this scope diff --git a/tests/ui/or_fun_call.fixed b/tests/ui/or_fun_call.fixed index 625d654dd396..1794ac57fe5b 100644 --- a/tests/ui/or_fun_call.fixed +++ b/tests/ui/or_fun_call.fixed @@ -50,61 +50,80 @@ fn or_fun_call() { let with_constructor = Some(vec![1]); with_constructor.unwrap_or_else(make); + //~^ or_fun_call let with_new = Some(vec![1]); with_new.unwrap_or_default(); + //~^ unwrap_or_default let with_const_args = Some(vec![1]); with_const_args.unwrap_or_else(|| Vec::with_capacity(12)); + //~^ or_fun_call let with_err: Result<_, ()> = Ok(vec![1]); with_err.unwrap_or_else(|_| make()); + //~^ or_fun_call let with_err_args: Result<_, ()> = Ok(vec![1]); with_err_args.unwrap_or_else(|_| Vec::with_capacity(12)); + //~^ or_fun_call let with_default_trait = Some(1); with_default_trait.unwrap_or_default(); + //~^ unwrap_or_default let with_default_type = Some(1); with_default_type.unwrap_or_default(); + //~^ unwrap_or_default let self_default = None::; self_default.unwrap_or_else(::default); + //~^ or_fun_call let real_default = None::; real_default.unwrap_or_default(); + //~^ unwrap_or_default let with_vec = Some(vec![1]); with_vec.unwrap_or_default(); + //~^ unwrap_or_default let without_default = Some(Foo); without_default.unwrap_or_else(Foo::new); + //~^ or_fun_call let mut map = HashMap::::new(); map.entry(42).or_default(); + //~^ unwrap_or_default let mut map_vec = HashMap::>::new(); map_vec.entry(42).or_default(); + //~^ unwrap_or_default let mut btree = BTreeMap::::new(); btree.entry(42).or_default(); + //~^ unwrap_or_default let mut btree_vec = BTreeMap::>::new(); btree_vec.entry(42).or_default(); + //~^ unwrap_or_default let stringy = Some(String::new()); let _ = stringy.unwrap_or_default(); + //~^ unwrap_or_default let opt = Some(1); let hello = "Hello"; let _ = opt.ok_or_else(|| format!("{} world.", hello)); + //~^ or_fun_call // index let map = HashMap::::new(); let _ = Some(1).unwrap_or_else(|| map[&1]); + //~^ or_fun_call let map = BTreeMap::::new(); let _ = Some(1).unwrap_or_else(|| map[&1]); + //~^ or_fun_call // don't lint index vec let vec = vec![1]; let _ = Some(1).unwrap_or(vec[1]); @@ -129,6 +148,7 @@ fn test_or_with_ctors() { let _ = opt.or(Some(two)); let _ = Some("a".to_string()).or_else(|| Some("b".to_string())); + //~^ or_fun_call let b = "b".to_string(); let _ = Some(Bar("a".to_string(), Duration::from_secs(1))) @@ -168,14 +188,17 @@ mod issue6675 { let s = "test".to_owned(); let s = &s as *const _; None.unwrap_or_else(|| ptr_to_ref(s)); + //~^ or_fun_call } fn bar() { let s = "test".to_owned(); let s = &s as *const _; None.unwrap_or_else(|| unsafe { ptr_to_ref(s) }); + //~^ or_fun_call #[rustfmt::skip] None.unwrap_or_else(|| unsafe { ptr_to_ref(s) }); + //~^ or_fun_call } } @@ -251,7 +274,9 @@ mod issue8993 { fn test_map_or() { let _ = Some(4).map_or_else(g, |v| v); + //~^ or_fun_call let _ = Some(4).map_or_else(g, f); + //~^ or_fun_call let _ = Some(4).map_or(0, f); } } @@ -283,24 +308,31 @@ mod lazy { let with_new = Some(vec![1]); with_new.unwrap_or_default(); + //~^ unwrap_or_default let with_default_trait = Some(1); with_default_trait.unwrap_or_default(); + //~^ unwrap_or_default let with_default_type = Some(1); with_default_type.unwrap_or_default(); + //~^ unwrap_or_default let real_default = None::; real_default.unwrap_or_default(); + //~^ unwrap_or_default let mut map = HashMap::::new(); map.entry(42).or_default(); + //~^ unwrap_or_default let mut btree = BTreeMap::::new(); btree.entry(42).or_default(); + //~^ unwrap_or_default let stringy = Some(String::new()); let _ = stringy.unwrap_or_default(); + //~^ unwrap_or_default // negative tests let self_default = None::; @@ -341,28 +373,36 @@ fn fn_call_in_nested_expr() { } let opt: Option = Some(1); - //~v ERROR: function call inside of `unwrap_or` let _ = opt.unwrap_or_else(f); // suggest `.unwrap_or_else(f)` // - //~v ERROR: function call inside of `unwrap_or` + //~^^ or_fun_call + // + let _ = opt.unwrap_or_else(|| f() + 1); // suggest `.unwrap_or_else(|| f() + 1)` // - //~v ERROR: function call inside of `unwrap_or` + //~^^ or_fun_call + // + let _ = opt.unwrap_or_else(|| { + //~^ or_fun_call let x = f(); x + 1 }); - //~v ERROR: function call inside of `map_or` + let _ = opt.map_or_else(|| f() + 1, |v| v); // suggest `.map_or_else(|| f() + 1, |v| v)` // - //~v ERROR: use of `unwrap_or` to construct default value + //~^^ or_fun_call + // + let _ = opt.unwrap_or_default(); + //~^ unwrap_or_default let opt_foo = Some(Foo { val: String::from("123"), }); - //~v ERROR: function call inside of `unwrap_or` + let _ = opt_foo.unwrap_or_else(|| Foo { val: String::default() }); + //~^ or_fun_call } fn main() {} diff --git a/tests/ui/or_fun_call.rs b/tests/ui/or_fun_call.rs index 5b7d8faec7bf..256db343c057 100644 --- a/tests/ui/or_fun_call.rs +++ b/tests/ui/or_fun_call.rs @@ -50,61 +50,80 @@ fn or_fun_call() { let with_constructor = Some(vec![1]); with_constructor.unwrap_or(make()); + //~^ or_fun_call let with_new = Some(vec![1]); with_new.unwrap_or(Vec::new()); + //~^ unwrap_or_default let with_const_args = Some(vec![1]); with_const_args.unwrap_or(Vec::with_capacity(12)); + //~^ or_fun_call let with_err: Result<_, ()> = Ok(vec![1]); with_err.unwrap_or(make()); + //~^ or_fun_call let with_err_args: Result<_, ()> = Ok(vec![1]); with_err_args.unwrap_or(Vec::with_capacity(12)); + //~^ or_fun_call let with_default_trait = Some(1); with_default_trait.unwrap_or(Default::default()); + //~^ unwrap_or_default let with_default_type = Some(1); with_default_type.unwrap_or(u64::default()); + //~^ unwrap_or_default let self_default = None::; self_default.unwrap_or(::default()); + //~^ or_fun_call let real_default = None::; real_default.unwrap_or(::default()); + //~^ unwrap_or_default let with_vec = Some(vec![1]); with_vec.unwrap_or(vec![]); + //~^ unwrap_or_default let without_default = Some(Foo); without_default.unwrap_or(Foo::new()); + //~^ or_fun_call let mut map = HashMap::::new(); map.entry(42).or_insert(String::new()); + //~^ unwrap_or_default let mut map_vec = HashMap::>::new(); map_vec.entry(42).or_insert(vec![]); + //~^ unwrap_or_default let mut btree = BTreeMap::::new(); btree.entry(42).or_insert(String::new()); + //~^ unwrap_or_default let mut btree_vec = BTreeMap::>::new(); btree_vec.entry(42).or_insert(vec![]); + //~^ unwrap_or_default let stringy = Some(String::new()); let _ = stringy.unwrap_or(String::new()); + //~^ unwrap_or_default let opt = Some(1); let hello = "Hello"; let _ = opt.ok_or(format!("{} world.", hello)); + //~^ or_fun_call // index let map = HashMap::::new(); let _ = Some(1).unwrap_or(map[&1]); + //~^ or_fun_call let map = BTreeMap::::new(); let _ = Some(1).unwrap_or(map[&1]); + //~^ or_fun_call // don't lint index vec let vec = vec![1]; let _ = Some(1).unwrap_or(vec[1]); @@ -129,6 +148,7 @@ fn test_or_with_ctors() { let _ = opt.or(Some(two)); let _ = Some("a".to_string()).or(Some("b".to_string())); + //~^ or_fun_call let b = "b".to_string(); let _ = Some(Bar("a".to_string(), Duration::from_secs(1))) @@ -168,14 +188,17 @@ mod issue6675 { let s = "test".to_owned(); let s = &s as *const _; None.unwrap_or(ptr_to_ref(s)); + //~^ or_fun_call } fn bar() { let s = "test".to_owned(); let s = &s as *const _; None.unwrap_or(unsafe { ptr_to_ref(s) }); + //~^ or_fun_call #[rustfmt::skip] None.unwrap_or( unsafe { ptr_to_ref(s) } ); + //~^ or_fun_call } } @@ -251,7 +274,9 @@ mod issue8993 { fn test_map_or() { let _ = Some(4).map_or(g(), |v| v); + //~^ or_fun_call let _ = Some(4).map_or(g(), f); + //~^ or_fun_call let _ = Some(4).map_or(0, f); } } @@ -283,24 +308,31 @@ mod lazy { let with_new = Some(vec![1]); with_new.unwrap_or_else(Vec::new); + //~^ unwrap_or_default let with_default_trait = Some(1); with_default_trait.unwrap_or_else(Default::default); + //~^ unwrap_or_default let with_default_type = Some(1); with_default_type.unwrap_or_else(u64::default); + //~^ unwrap_or_default let real_default = None::; real_default.unwrap_or_else(::default); + //~^ unwrap_or_default let mut map = HashMap::::new(); map.entry(42).or_insert_with(String::new); + //~^ unwrap_or_default let mut btree = BTreeMap::::new(); btree.entry(42).or_insert_with(String::new); + //~^ unwrap_or_default let stringy = Some(String::new()); let _ = stringy.unwrap_or_else(String::new); + //~^ unwrap_or_default // negative tests let self_default = None::; @@ -341,28 +373,36 @@ fn fn_call_in_nested_expr() { } let opt: Option = Some(1); - //~v ERROR: function call inside of `unwrap_or` let _ = opt.unwrap_or({ f() }); // suggest `.unwrap_or_else(f)` // - //~v ERROR: function call inside of `unwrap_or` + //~^^ or_fun_call + // + let _ = opt.unwrap_or(f() + 1); // suggest `.unwrap_or_else(|| f() + 1)` // - //~v ERROR: function call inside of `unwrap_or` + //~^^ or_fun_call + // + let _ = opt.unwrap_or({ + //~^ or_fun_call let x = f(); x + 1 }); - //~v ERROR: function call inside of `map_or` + let _ = opt.map_or(f() + 1, |v| v); // suggest `.map_or_else(|| f() + 1, |v| v)` // - //~v ERROR: use of `unwrap_or` to construct default value + //~^^ or_fun_call + // + let _ = opt.unwrap_or({ i32::default() }); + //~^ unwrap_or_default let opt_foo = Some(Foo { val: String::from("123"), }); - //~v ERROR: function call inside of `unwrap_or` + let _ = opt_foo.unwrap_or(Foo { val: String::default() }); + //~^ or_fun_call } fn main() {} diff --git a/tests/ui/or_fun_call.stderr b/tests/ui/or_fun_call.stderr index 9f90a830a211..93c87b2f12cd 100644 --- a/tests/ui/or_fun_call.stderr +++ b/tests/ui/or_fun_call.stderr @@ -8,7 +8,7 @@ LL | with_constructor.unwrap_or(make()); = help: to override `-D warnings` add `#[allow(clippy::or_fun_call)]` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:55:14 + --> tests/ui/or_fun_call.rs:56:14 | LL | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` @@ -17,202 +17,203 @@ LL | with_new.unwrap_or(Vec::new()); = help: to override `-D warnings` add `#[allow(clippy::unwrap_or_default)]` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:58:21 + --> tests/ui/or_fun_call.rs:60:21 | LL | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| Vec::with_capacity(12))` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:61:14 + --> tests/ui/or_fun_call.rs:64:14 | LL | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|_| make())` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:64:19 + --> tests/ui/or_fun_call.rs:68:19 | LL | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:67:24 + --> tests/ui/or_fun_call.rs:72:24 | LL | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:70:23 + --> tests/ui/or_fun_call.rs:76:23 | LL | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:73:18 + --> tests/ui/or_fun_call.rs:80:18 | LL | self_default.unwrap_or(::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(::default)` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:76:18 + --> tests/ui/or_fun_call.rs:84:18 | LL | real_default.unwrap_or(::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:79:14 + --> tests/ui/or_fun_call.rs:88:14 | LL | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:82:21 + --> tests/ui/or_fun_call.rs:92:21 | LL | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(Foo::new)` error: use of `or_insert` to construct default value - --> tests/ui/or_fun_call.rs:85:19 + --> tests/ui/or_fun_call.rs:96:19 | LL | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `or_insert` to construct default value - --> tests/ui/or_fun_call.rs:88:23 + --> tests/ui/or_fun_call.rs:100:23 | LL | map_vec.entry(42).or_insert(vec![]); | ^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `or_insert` to construct default value - --> tests/ui/or_fun_call.rs:91:21 + --> tests/ui/or_fun_call.rs:104:21 | LL | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `or_insert` to construct default value - --> tests/ui/or_fun_call.rs:94:25 + --> tests/ui/or_fun_call.rs:108:25 | LL | btree_vec.entry(42).or_insert(vec![]); | ^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:97:21 + --> tests/ui/or_fun_call.rs:112:21 | LL | let _ = stringy.unwrap_or(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: function call inside of `ok_or` - --> tests/ui/or_fun_call.rs:101:17 + --> tests/ui/or_fun_call.rs:117:17 | LL | let _ = opt.ok_or(format!("{} world.", hello)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ok_or_else(|| format!("{} world.", hello))` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:105:21 + --> tests/ui/or_fun_call.rs:122:21 | LL | let _ = Some(1).unwrap_or(map[&1]); | ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| map[&1])` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:107:21 + --> tests/ui/or_fun_call.rs:125:21 | LL | let _ = Some(1).unwrap_or(map[&1]); | ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| map[&1])` error: function call inside of `or` - --> tests/ui/or_fun_call.rs:131:35 + --> tests/ui/or_fun_call.rs:150:35 | LL | let _ = Some("a".to_string()).or(Some("b".to_string())); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_else(|| Some("b".to_string()))` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:170:14 + --> tests/ui/or_fun_call.rs:190:14 | LL | None.unwrap_or(ptr_to_ref(s)); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| ptr_to_ref(s))` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:176:14 + --> tests/ui/or_fun_call.rs:197:14 | LL | None.unwrap_or(unsafe { ptr_to_ref(s) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:178:14 + --> tests/ui/or_fun_call.rs:200:14 | LL | None.unwrap_or( unsafe { ptr_to_ref(s) } ); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })` error: function call inside of `map_or` - --> tests/ui/or_fun_call.rs:253:25 + --> tests/ui/or_fun_call.rs:276:25 | LL | let _ = Some(4).map_or(g(), |v| v); | ^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(g, |v| v)` error: function call inside of `map_or` - --> tests/ui/or_fun_call.rs:254:25 + --> tests/ui/or_fun_call.rs:278:25 | LL | let _ = Some(4).map_or(g(), f); | ^^^^^^^^^^^^^^ help: try: `map_or_else(g, f)` error: use of `unwrap_or_else` to construct default value - --> tests/ui/or_fun_call.rs:285:18 + --> tests/ui/or_fun_call.rs:310:18 | LL | with_new.unwrap_or_else(Vec::new); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or_else` to construct default value - --> tests/ui/or_fun_call.rs:288:28 + --> tests/ui/or_fun_call.rs:314:28 | LL | with_default_trait.unwrap_or_else(Default::default); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or_else` to construct default value - --> tests/ui/or_fun_call.rs:291:27 + --> tests/ui/or_fun_call.rs:318:27 | LL | with_default_type.unwrap_or_else(u64::default); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or_else` to construct default value - --> tests/ui/or_fun_call.rs:294:22 + --> tests/ui/or_fun_call.rs:322:22 | LL | real_default.unwrap_or_else(::default); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `or_insert_with` to construct default value - --> tests/ui/or_fun_call.rs:297:23 + --> tests/ui/or_fun_call.rs:326:23 | LL | map.entry(42).or_insert_with(String::new); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `or_insert_with` to construct default value - --> tests/ui/or_fun_call.rs:300:25 + --> tests/ui/or_fun_call.rs:330:25 | LL | btree.entry(42).or_insert_with(String::new); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `unwrap_or_else` to construct default value - --> tests/ui/or_fun_call.rs:303:25 + --> tests/ui/or_fun_call.rs:334:25 | LL | let _ = stringy.unwrap_or_else(String::new); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:345:17 + --> tests/ui/or_fun_call.rs:376:17 | LL | let _ = opt.unwrap_or({ f() }); // suggest `.unwrap_or_else(f)` | ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(f)` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:348:17 + --> tests/ui/or_fun_call.rs:381:17 | LL | let _ = opt.unwrap_or(f() + 1); // suggest `.unwrap_or_else(|| f() + 1)` | ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| f() + 1)` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:351:17 + --> tests/ui/or_fun_call.rs:386:17 | LL | let _ = opt.unwrap_or({ | _________________^ +LL | | LL | | let x = f(); LL | | x + 1 LL | | }); @@ -221,25 +222,26 @@ LL | | }); help: try | LL ~ let _ = opt.unwrap_or_else(|| { +LL + LL + let x = f(); LL + x + 1 LL ~ }); | error: function call inside of `map_or` - --> tests/ui/or_fun_call.rs:356:17 + --> tests/ui/or_fun_call.rs:392:17 | LL | let _ = opt.map_or(f() + 1, |v| v); // suggest `.map_or_else(|| f() + 1, |v| v)` | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(|| f() + 1, |v| v)` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:359:17 + --> tests/ui/or_fun_call.rs:397:17 | LL | let _ = opt.unwrap_or({ i32::default() }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:365:21 + --> tests/ui/or_fun_call.rs:404:21 | LL | let _ = opt_foo.unwrap_or(Foo { val: String::default() }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| Foo { val: String::default() })` diff --git a/tests/ui/or_then_unwrap.fixed b/tests/ui/or_then_unwrap.fixed index c94478614352..ba9beef57afa 100644 --- a/tests/ui/or_then_unwrap.fixed +++ b/tests/ui/or_then_unwrap.fixed @@ -20,13 +20,19 @@ impl SomeOtherStruct { fn main() { let option: Option<&str> = None; let _ = option.unwrap_or("fallback"); // should trigger lint + // + //~^^ or_then_unwrap let result: Result<&str, &str> = Err("Error"); let _ = result.unwrap_or("fallback"); // should trigger lint + // + //~^^ or_then_unwrap // as part of a method chain let option: Option<&str> = None; let _ = option.map(|v| v).unwrap_or("fallback").to_string().chars(); // should trigger lint + // + //~^^ or_then_unwrap // Not Option/Result let instance = SomeStruct {}; diff --git a/tests/ui/or_then_unwrap.rs b/tests/ui/or_then_unwrap.rs index 10e43e1d1896..fac90249a243 100644 --- a/tests/ui/or_then_unwrap.rs +++ b/tests/ui/or_then_unwrap.rs @@ -20,13 +20,19 @@ impl SomeOtherStruct { fn main() { let option: Option<&str> = None; let _ = option.or(Some("fallback")).unwrap(); // should trigger lint + // + //~^^ or_then_unwrap let result: Result<&str, &str> = Err("Error"); let _ = result.or::<&str>(Ok("fallback")).unwrap(); // should trigger lint + // + //~^^ or_then_unwrap // as part of a method chain let option: Option<&str> = None; let _ = option.map(|v| v).or(Some("fallback")).unwrap().to_string().chars(); // should trigger lint + // + //~^^ or_then_unwrap // Not Option/Result let instance = SomeStruct {}; diff --git a/tests/ui/or_then_unwrap.stderr b/tests/ui/or_then_unwrap.stderr index f454316068f2..1160498c6053 100644 --- a/tests/ui/or_then_unwrap.stderr +++ b/tests/ui/or_then_unwrap.stderr @@ -8,13 +8,13 @@ LL | let _ = option.or(Some("fallback")).unwrap(); // should trigger lint = help: to override `-D warnings` add `#[allow(clippy::or_then_unwrap)]` error: found `.or(Ok(…)).unwrap()` - --> tests/ui/or_then_unwrap.rs:25:20 + --> tests/ui/or_then_unwrap.rs:27:20 | LL | let _ = result.or::<&str>(Ok("fallback")).unwrap(); // should trigger lint | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or("fallback")` error: found `.or(Some(…)).unwrap()` - --> tests/ui/or_then_unwrap.rs:29:31 + --> tests/ui/or_then_unwrap.rs:33:31 | LL | let _ = option.map(|v| v).or(Some("fallback")).unwrap().to_string().chars(); // should trigger lint | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or("fallback")` diff --git a/tests/ui/out_of_bounds_indexing/issue-3102.rs b/tests/ui/out_of_bounds_indexing/issue-3102.rs index 81674653bdd3..e1e0fa02a937 100644 --- a/tests/ui/out_of_bounds_indexing/issue-3102.rs +++ b/tests/ui/out_of_bounds_indexing/issue-3102.rs @@ -7,8 +7,8 @@ fn main() { // issue 3102 let num = 1; &x[num..10]; - //~^ ERROR: range is out of bounds - //~| NOTE: `-D clippy::out-of-bounds-indexing` implied by `-D warnings` + //~^ out_of_bounds_indexing + &x[10..num]; - //~^ ERROR: range is out of bounds + //~^ out_of_bounds_indexing } diff --git a/tests/ui/out_of_bounds_indexing/simple.rs b/tests/ui/out_of_bounds_indexing/simple.rs index c38ca5123816..e613e527eee4 100644 --- a/tests/ui/out_of_bounds_indexing/simple.rs +++ b/tests/ui/out_of_bounds_indexing/simple.rs @@ -5,18 +5,22 @@ fn main() { let x = [1, 2, 3, 4]; &x[..=4]; - //~^ ERROR: range is out of bounds - //~| NOTE: `-D clippy::out-of-bounds-indexing` implied by `-D warnings` + //~^ out_of_bounds_indexing + &x[1..5]; - //~^ ERROR: range is out of bounds + //~^ out_of_bounds_indexing + &x[5..]; - //~^ ERROR: range is out of bounds + //~^ out_of_bounds_indexing + &x[..5]; - //~^ ERROR: range is out of bounds + //~^ out_of_bounds_indexing + &x[5..].iter().map(|x| 2 * x).collect::>(); - //~^ ERROR: range is out of bounds + //~^ out_of_bounds_indexing + &x[0..=4]; - //~^ ERROR: range is out of bounds + //~^ out_of_bounds_indexing &x[4..]; // Ok, should not produce stderr. &x[..4]; // Ok, should not produce stderr. diff --git a/tests/ui/out_of_bounds_indexing/simple.stderr b/tests/ui/out_of_bounds_indexing/simple.stderr index 87d1d574dcb8..f89531733431 100644 --- a/tests/ui/out_of_bounds_indexing/simple.stderr +++ b/tests/ui/out_of_bounds_indexing/simple.stderr @@ -14,25 +14,25 @@ LL | &x[1..5]; | ^ error: range is out of bounds - --> tests/ui/out_of_bounds_indexing/simple.rs:12:8 + --> tests/ui/out_of_bounds_indexing/simple.rs:13:8 | LL | &x[5..]; | ^ error: range is out of bounds - --> tests/ui/out_of_bounds_indexing/simple.rs:14:10 + --> tests/ui/out_of_bounds_indexing/simple.rs:16:10 | LL | &x[..5]; | ^ error: range is out of bounds - --> tests/ui/out_of_bounds_indexing/simple.rs:16:8 + --> tests/ui/out_of_bounds_indexing/simple.rs:19:8 | LL | &x[5..].iter().map(|x| 2 * x).collect::>(); | ^ error: range is out of bounds - --> tests/ui/out_of_bounds_indexing/simple.rs:18:12 + --> tests/ui/out_of_bounds_indexing/simple.rs:22:12 | LL | &x[0..=4]; | ^ diff --git a/tests/ui/overly_complex_bool_expr.fixed b/tests/ui/overly_complex_bool_expr.fixed index b21e91aa3ad4..6818f96725e7 100644 --- a/tests/ui/overly_complex_bool_expr.fixed +++ b/tests/ui/overly_complex_bool_expr.fixed @@ -8,10 +8,12 @@ fn main() { let d: bool = unimplemented!(); let e: bool = unimplemented!(); let _ = a; - //~^ ERROR: this boolean expression contains a logic bug + //~^ overly_complex_bool_expr + let _ = !(a && b); let _ = false; - //~^ ERROR: this boolean expression contains a logic bug + //~^ overly_complex_bool_expr + // don't lint on cfgs let _ = cfg!(you_shall_not_not_pass) && a; let _ = a || !b || !c || !d || !e; @@ -22,11 +24,14 @@ fn equality_stuff() { let a: i32 = unimplemented!(); let b: i32 = unimplemented!(); let _ = false; - //~^ ERROR: this boolean expression contains a logic bug + //~^ overly_complex_bool_expr + let _ = false; - //~^ ERROR: this boolean expression contains a logic bug + //~^ overly_complex_bool_expr + let _ = false; - //~^ ERROR: this boolean expression contains a logic bug + //~^ overly_complex_bool_expr + let _ = a > b && a == b; } diff --git a/tests/ui/overly_complex_bool_expr.rs b/tests/ui/overly_complex_bool_expr.rs index 35ef0a1240a5..f1cd9562a855 100644 --- a/tests/ui/overly_complex_bool_expr.rs +++ b/tests/ui/overly_complex_bool_expr.rs @@ -8,10 +8,12 @@ fn main() { let d: bool = unimplemented!(); let e: bool = unimplemented!(); let _ = a && b || a; - //~^ ERROR: this boolean expression contains a logic bug + //~^ overly_complex_bool_expr + let _ = !(a && b); let _ = false && a; - //~^ ERROR: this boolean expression contains a logic bug + //~^ overly_complex_bool_expr + // don't lint on cfgs let _ = cfg!(you_shall_not_not_pass) && a; let _ = a || !b || !c || !d || !e; @@ -22,11 +24,14 @@ fn equality_stuff() { let a: i32 = unimplemented!(); let b: i32 = unimplemented!(); let _ = a == b && a != b; - //~^ ERROR: this boolean expression contains a logic bug + //~^ overly_complex_bool_expr + let _ = a < b && a >= b; - //~^ ERROR: this boolean expression contains a logic bug + //~^ overly_complex_bool_expr + let _ = a > b && a <= b; - //~^ ERROR: this boolean expression contains a logic bug + //~^ overly_complex_bool_expr + let _ = a > b && a == b; } diff --git a/tests/ui/overly_complex_bool_expr.stderr b/tests/ui/overly_complex_bool_expr.stderr index 5a754236fe4b..42a48a3b5be8 100644 --- a/tests/ui/overly_complex_bool_expr.stderr +++ b/tests/ui/overly_complex_bool_expr.stderr @@ -13,49 +13,49 @@ LL | let _ = a && b || a; = help: to override `-D warnings` add `#[allow(clippy::overly_complex_bool_expr)]` error: this boolean expression contains a logic bug - --> tests/ui/overly_complex_bool_expr.rs:13:13 + --> tests/ui/overly_complex_bool_expr.rs:14:13 | LL | let _ = false && a; | ^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> tests/ui/overly_complex_bool_expr.rs:13:22 + --> tests/ui/overly_complex_bool_expr.rs:14:22 | LL | let _ = false && a; | ^ error: this boolean expression contains a logic bug - --> tests/ui/overly_complex_bool_expr.rs:24:13 + --> tests/ui/overly_complex_bool_expr.rs:26:13 | LL | let _ = a == b && a != b; | ^^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> tests/ui/overly_complex_bool_expr.rs:24:13 + --> tests/ui/overly_complex_bool_expr.rs:26:13 | LL | let _ = a == b && a != b; | ^^^^^^ error: this boolean expression contains a logic bug - --> tests/ui/overly_complex_bool_expr.rs:26:13 + --> tests/ui/overly_complex_bool_expr.rs:29:13 | LL | let _ = a < b && a >= b; | ^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> tests/ui/overly_complex_bool_expr.rs:26:13 + --> tests/ui/overly_complex_bool_expr.rs:29:13 | LL | let _ = a < b && a >= b; | ^^^^^ error: this boolean expression contains a logic bug - --> tests/ui/overly_complex_bool_expr.rs:28:13 + --> tests/ui/overly_complex_bool_expr.rs:32:13 | LL | let _ = a > b && a <= b; | ^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> tests/ui/overly_complex_bool_expr.rs:28:13 + --> tests/ui/overly_complex_bool_expr.rs:32:13 | LL | let _ = a > b && a <= b; | ^^^^^ diff --git a/tests/ui/owned_cow.fixed b/tests/ui/owned_cow.fixed new file mode 100644 index 000000000000..b62e9107a561 --- /dev/null +++ b/tests/ui/owned_cow.fixed @@ -0,0 +1,23 @@ +#![warn(clippy::owned_cow)] + +use std::borrow::Cow; +use std::ffi::{CString, OsString}; +use std::path::PathBuf; + +fn main() { + let x: Cow<'static, str> = Cow::Owned(String::from("Hi!")); + //~^ ERROR: needlessly owned Cow type + let y: Cow<'_, [u8]> = Cow::Owned(vec![]); + //~^ ERROR: needlessly owned Cow type + let z: Cow<'_, [_]> = Cow::Owned(vec![2_i32]); + //~^ ERROR: needlessly owned Cow type + let o: Cow<'_, std::ffi::OsStr> = Cow::Owned(OsString::new()); + //~^ ERROR: needlessly owned Cow type + let c: Cow<'_, std::ffi::CStr> = Cow::Owned(CString::new("").unwrap()); + //~^ ERROR: needlessly owned Cow type + let p: Cow<'_, std::path::Path> = Cow::Owned(PathBuf::new()); + //~^ ERROR: needlessly owned Cow type + + // false positive: borrowed type + let b: Cow<'_, str> = Cow::Borrowed("Hi!"); +} diff --git a/tests/ui/owned_cow.rs b/tests/ui/owned_cow.rs new file mode 100644 index 000000000000..0e0f14711b7f --- /dev/null +++ b/tests/ui/owned_cow.rs @@ -0,0 +1,23 @@ +#![warn(clippy::owned_cow)] + +use std::borrow::Cow; +use std::ffi::{CString, OsString}; +use std::path::PathBuf; + +fn main() { + let x: Cow<'static, String> = Cow::Owned(String::from("Hi!")); + //~^ ERROR: needlessly owned Cow type + let y: Cow<'_, Vec> = Cow::Owned(vec![]); + //~^ ERROR: needlessly owned Cow type + let z: Cow<'_, Vec<_>> = Cow::Owned(vec![2_i32]); + //~^ ERROR: needlessly owned Cow type + let o: Cow<'_, OsString> = Cow::Owned(OsString::new()); + //~^ ERROR: needlessly owned Cow type + let c: Cow<'_, CString> = Cow::Owned(CString::new("").unwrap()); + //~^ ERROR: needlessly owned Cow type + let p: Cow<'_, PathBuf> = Cow::Owned(PathBuf::new()); + //~^ ERROR: needlessly owned Cow type + + // false positive: borrowed type + let b: Cow<'_, str> = Cow::Borrowed("Hi!"); +} diff --git a/tests/ui/owned_cow.stderr b/tests/ui/owned_cow.stderr new file mode 100644 index 000000000000..8985d6db623d --- /dev/null +++ b/tests/ui/owned_cow.stderr @@ -0,0 +1,41 @@ +error: needlessly owned Cow type + --> tests/ui/owned_cow.rs:8:25 + | +LL | let x: Cow<'static, String> = Cow::Owned(String::from("Hi!")); + | ^^^^^^ help: use: `str` + | + = note: `-D clippy::owned-cow` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::owned_cow)]` + +error: needlessly owned Cow type + --> tests/ui/owned_cow.rs:10:20 + | +LL | let y: Cow<'_, Vec> = Cow::Owned(vec![]); + | ^^^^^^^ help: use: `[u8]` + +error: needlessly owned Cow type + --> tests/ui/owned_cow.rs:12:20 + | +LL | let z: Cow<'_, Vec<_>> = Cow::Owned(vec![2_i32]); + | ^^^^^^ help: use: `[_]` + +error: needlessly owned Cow type + --> tests/ui/owned_cow.rs:14:20 + | +LL | let o: Cow<'_, OsString> = Cow::Owned(OsString::new()); + | ^^^^^^^^ help: use: `std::ffi::OsStr` + +error: needlessly owned Cow type + --> tests/ui/owned_cow.rs:16:20 + | +LL | let c: Cow<'_, CString> = Cow::Owned(CString::new("").unwrap()); + | ^^^^^^^ help: use: `std::ffi::CStr` + +error: needlessly owned Cow type + --> tests/ui/owned_cow.rs:18:20 + | +LL | let p: Cow<'_, PathBuf> = Cow::Owned(PathBuf::new()); + | ^^^^^^^ help: use: `std::path::Path` + +error: aborting due to 6 previous errors + diff --git a/tests/ui/panic_in_result_fn.rs b/tests/ui/panic_in_result_fn.rs index e2375aa996f7..005e38db9021 100644 --- a/tests/ui/panic_in_result_fn.rs +++ b/tests/ui/panic_in_result_fn.rs @@ -4,7 +4,7 @@ struct A; impl A { fn result_with_panic() -> Result // should emit lint - //~^ ERROR: used `panic!()` or assertion in a function that returns `Result` + //~^ panic_in_result_fn { panic!("error"); } @@ -51,12 +51,13 @@ impl A { } fn function_result_with_panic() -> Result // should emit lint -//~^ ERROR: used `panic!()` or assertion in a function that returns `Result` +//~^ panic_in_result_fn { panic!("error"); } fn in_closure() -> Result { + //~^ panic_in_result_fn let c = || panic!(); c() } diff --git a/tests/ui/panic_in_result_fn.stderr b/tests/ui/panic_in_result_fn.stderr index 2d49b5ab1b8f..1067f4fac11c 100644 --- a/tests/ui/panic_in_result_fn.stderr +++ b/tests/ui/panic_in_result_fn.stderr @@ -38,6 +38,7 @@ error: used `panic!()` or assertion in a function that returns `Result` --> tests/ui/panic_in_result_fn.rs:59:1 | LL | / fn in_closure() -> Result { +LL | | LL | | let c = || panic!(); LL | | c() LL | | } @@ -45,7 +46,7 @@ LL | | } | = help: `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing note: return Err() instead of panicking - --> tests/ui/panic_in_result_fn.rs:60:16 + --> tests/ui/panic_in_result_fn.rs:61:16 | LL | let c = || panic!(); | ^^^^^^^^ diff --git a/tests/ui/panic_in_result_fn_assertions.rs b/tests/ui/panic_in_result_fn_assertions.rs index 672c4c738339..4e7028241579 100644 --- a/tests/ui/panic_in_result_fn_assertions.rs +++ b/tests/ui/panic_in_result_fn_assertions.rs @@ -5,21 +5,21 @@ struct A; impl A { fn result_with_assert_with_message(x: i32) -> Result // should emit lint - //~^ ERROR: used `panic!()` or assertion in a function that returns `Result` + //~^ panic_in_result_fn { assert!(x == 5, "wrong argument"); Ok(true) } fn result_with_assert_eq(x: i32) -> Result // should emit lint - //~^ ERROR: used `panic!()` or assertion in a function that returns `Result` + //~^ panic_in_result_fn { assert_eq!(x, 5); Ok(true) } fn result_with_assert_ne(x: i32) -> Result // should emit lint - //~^ ERROR: used `panic!()` or assertion in a function that returns `Result` + //~^ panic_in_result_fn { assert_ne!(x, 1); Ok(true) diff --git a/tests/ui/panic_in_result_fn_debug_assertions.rs b/tests/ui/panic_in_result_fn_debug_assertions.rs index df89d8c50246..c4549c6b8412 100644 --- a/tests/ui/panic_in_result_fn_debug_assertions.rs +++ b/tests/ui/panic_in_result_fn_debug_assertions.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::panic_in_result_fn)] #![allow(clippy::uninlined_format_args, clippy::unnecessary_wraps)] diff --git a/tests/ui/panicking_macros.rs b/tests/ui/panicking_macros.rs index 2bbf5792ec4c..65854d7eb4bf 100644 --- a/tests/ui/panicking_macros.rs +++ b/tests/ui/panicking_macros.rs @@ -20,61 +20,72 @@ fn inline_const() { fn panic() { let a = 2; panic!(); - //~^ ERROR: `panic` should not be present in production code - //~| NOTE: `-D clippy::panic` implied by `-D warnings` + //~^ panic + panic!("message"); - //~^ ERROR: `panic` should not be present in production code + //~^ panic + panic!("{} {}", "panic with", "multiple arguments"); - //~^ ERROR: `panic` should not be present in production code + //~^ panic + let b = a + 2; } fn todo() { let a = 2; todo!(); - //~^ ERROR: `todo` should not be present in production code - //~| NOTE: `-D clippy::todo` implied by `-D warnings` + //~^ todo + todo!("message"); - //~^ ERROR: `todo` should not be present in production code + //~^ todo + todo!("{} {}", "panic with", "multiple arguments"); - //~^ ERROR: `todo` should not be present in production code + //~^ todo + let b = a + 2; } fn unimplemented() { let a = 2; unimplemented!(); - //~^ ERROR: `unimplemented` should not be present in production code - //~| NOTE: `-D clippy::unimplemented` implied by `-D warnings` + //~^ unimplemented + unimplemented!("message"); - //~^ ERROR: `unimplemented` should not be present in production code + //~^ unimplemented + unimplemented!("{} {}", "panic with", "multiple arguments"); - //~^ ERROR: `unimplemented` should not be present in production code + //~^ unimplemented + let b = a + 2; } fn unreachable() { let a = 2; unreachable!(); - //~^ ERROR: usage of the `unreachable!` macro - //~| NOTE: `-D clippy::unreachable` implied by `-D warnings` + //~^ unreachable + unreachable!("message"); - //~^ ERROR: usage of the `unreachable!` macro + //~^ unreachable + unreachable!("{} {}", "panic with", "multiple arguments"); - //~^ ERROR: usage of the `unreachable!` macro + //~^ unreachable + let b = a + 2; } fn core_versions() { use core::{panic, todo, unimplemented, unreachable}; panic!(); - //~^ ERROR: `panic` should not be present in production code + //~^ panic + todo!(); - //~^ ERROR: `todo` should not be present in production code + //~^ todo + unimplemented!(); - //~^ ERROR: `unimplemented` should not be present in production code + //~^ unimplemented + unreachable!(); - //~^ ERROR: usage of the `unreachable!` macro + //~^ unreachable } fn assert() { diff --git a/tests/ui/panicking_macros.stderr b/tests/ui/panicking_macros.stderr index 7c0f0a7d3764..03e459e4ec6e 100644 --- a/tests/ui/panicking_macros.stderr +++ b/tests/ui/panicking_macros.stderr @@ -14,13 +14,13 @@ LL | panic!("message"); | ^^^^^^^^^^^^^^^^^ error: `panic` should not be present in production code - --> tests/ui/panicking_macros.rs:27:5 + --> tests/ui/panicking_macros.rs:28:5 | LL | panic!("{} {}", "panic with", "multiple arguments"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `todo` should not be present in production code - --> tests/ui/panicking_macros.rs:34:5 + --> tests/ui/panicking_macros.rs:36:5 | LL | todo!(); | ^^^^^^^ @@ -29,19 +29,19 @@ LL | todo!(); = help: to override `-D warnings` add `#[allow(clippy::todo)]` error: `todo` should not be present in production code - --> tests/ui/panicking_macros.rs:37:5 + --> tests/ui/panicking_macros.rs:39:5 | LL | todo!("message"); | ^^^^^^^^^^^^^^^^ error: `todo` should not be present in production code - --> tests/ui/panicking_macros.rs:39:5 + --> tests/ui/panicking_macros.rs:42:5 | LL | todo!("{} {}", "panic with", "multiple arguments"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `unimplemented` should not be present in production code - --> tests/ui/panicking_macros.rs:46:5 + --> tests/ui/panicking_macros.rs:50:5 | LL | unimplemented!(); | ^^^^^^^^^^^^^^^^ @@ -50,19 +50,19 @@ LL | unimplemented!(); = help: to override `-D warnings` add `#[allow(clippy::unimplemented)]` error: `unimplemented` should not be present in production code - --> tests/ui/panicking_macros.rs:49:5 + --> tests/ui/panicking_macros.rs:53:5 | LL | unimplemented!("message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: `unimplemented` should not be present in production code - --> tests/ui/panicking_macros.rs:51:5 + --> tests/ui/panicking_macros.rs:56:5 | LL | unimplemented!("{} {}", "panic with", "multiple arguments"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: usage of the `unreachable!` macro - --> tests/ui/panicking_macros.rs:58:5 + --> tests/ui/panicking_macros.rs:64:5 | LL | unreachable!(); | ^^^^^^^^^^^^^^ @@ -71,37 +71,37 @@ LL | unreachable!(); = help: to override `-D warnings` add `#[allow(clippy::unreachable)]` error: usage of the `unreachable!` macro - --> tests/ui/panicking_macros.rs:61:5 + --> tests/ui/panicking_macros.rs:67:5 | LL | unreachable!("message"); | ^^^^^^^^^^^^^^^^^^^^^^^ error: usage of the `unreachable!` macro - --> tests/ui/panicking_macros.rs:63:5 + --> tests/ui/panicking_macros.rs:70:5 | LL | unreachable!("{} {}", "panic with", "multiple arguments"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `panic` should not be present in production code - --> tests/ui/panicking_macros.rs:70:5 + --> tests/ui/panicking_macros.rs:78:5 | LL | panic!(); | ^^^^^^^^ error: `todo` should not be present in production code - --> tests/ui/panicking_macros.rs:72:5 + --> tests/ui/panicking_macros.rs:81:5 | LL | todo!(); | ^^^^^^^ error: `unimplemented` should not be present in production code - --> tests/ui/panicking_macros.rs:74:5 + --> tests/ui/panicking_macros.rs:84:5 | LL | unimplemented!(); | ^^^^^^^^^^^^^^^^ error: usage of the `unreachable!` macro - --> tests/ui/panicking_macros.rs:76:5 + --> tests/ui/panicking_macros.rs:87:5 | LL | unreachable!(); | ^^^^^^^^^^^^^^ diff --git a/tests/ui/panicking_overflow_checks.rs b/tests/ui/panicking_overflow_checks.rs index dc2ddeada1e9..29789c949756 100644 --- a/tests/ui/panicking_overflow_checks.rs +++ b/tests/ui/panicking_overflow_checks.rs @@ -2,14 +2,20 @@ #![allow(clippy::needless_if)] fn test(a: u32, b: u32, c: u32) { - if a + b < a {} //~ panicking_overflow_checks - if a > a + b {} //~ panicking_overflow_checks - if a + b < b {} //~ panicking_overflow_checks - if b > a + b {} //~ panicking_overflow_checks + if a + b < a {} + //~^ panicking_overflow_checks + if a > a + b {} + //~^ panicking_overflow_checks + if a + b < b {} + //~^ panicking_overflow_checks + if b > a + b {} + //~^ panicking_overflow_checks if a - b > b {} if b < a - b {} - if a - b > a {} //~ panicking_overflow_checks - if a < a - b {} //~ panicking_overflow_checks + if a - b > a {} + //~^ panicking_overflow_checks + if a < a - b {} + //~^ panicking_overflow_checks if a + b < c {} if c > a + b {} if a - b < c {} diff --git a/tests/ui/panicking_overflow_checks.stderr b/tests/ui/panicking_overflow_checks.stderr index 1fae04578899..3022c9e52b0c 100644 --- a/tests/ui/panicking_overflow_checks.stderr +++ b/tests/ui/panicking_overflow_checks.stderr @@ -8,31 +8,31 @@ LL | if a + b < a {} = help: to override `-D warnings` add `#[allow(clippy::panicking_overflow_checks)]` error: you are trying to use classic C overflow conditions that will fail in Rust - --> tests/ui/panicking_overflow_checks.rs:6:8 + --> tests/ui/panicking_overflow_checks.rs:7:8 | LL | if a > a + b {} | ^^^^^^^^^ error: you are trying to use classic C overflow conditions that will fail in Rust - --> tests/ui/panicking_overflow_checks.rs:7:8 + --> tests/ui/panicking_overflow_checks.rs:9:8 | LL | if a + b < b {} | ^^^^^^^^^ error: you are trying to use classic C overflow conditions that will fail in Rust - --> tests/ui/panicking_overflow_checks.rs:8:8 + --> tests/ui/panicking_overflow_checks.rs:11:8 | LL | if b > a + b {} | ^^^^^^^^^ error: you are trying to use classic C overflow conditions that will fail in Rust - --> tests/ui/panicking_overflow_checks.rs:11:8 + --> tests/ui/panicking_overflow_checks.rs:15:8 | LL | if a - b > a {} | ^^^^^^^^^ error: you are trying to use classic C overflow conditions that will fail in Rust - --> tests/ui/panicking_overflow_checks.rs:12:8 + --> tests/ui/panicking_overflow_checks.rs:17:8 | LL | if a < a - b {} | ^^^^^^^^^ diff --git a/tests/ui/partial_pub_fields.rs b/tests/ui/partial_pub_fields.rs index 316b36c25eac..27f4b2a0b4fc 100644 --- a/tests/ui/partial_pub_fields.rs +++ b/tests/ui/partial_pub_fields.rs @@ -8,23 +8,23 @@ fn main() { pub struct FileSet { files: HashMap, pub paths: HashMap, - //~^ ERROR: mixed usage of pub and non-pub fields + //~^ partial_pub_fields } pub struct Color { pub r: u8, pub g: u8, b: u8, - //~^ ERROR: mixed usage of pub and non-pub fields + //~^ partial_pub_fields } pub struct Point(i32, pub i32); - //~^ ERROR: mixed usage of pub and non-pub fields + //~^ partial_pub_fields pub struct Visibility { r#pub: bool, pub pos: u32, - //~^ ERROR: mixed usage of pub and non-pub fields + //~^ partial_pub_fields } // Don't lint on empty structs; diff --git a/tests/ui/partialeq_ne_impl.rs b/tests/ui/partialeq_ne_impl.rs index 555eeebe1c78..a3b2b68708ba 100644 --- a/tests/ui/partialeq_ne_impl.rs +++ b/tests/ui/partialeq_ne_impl.rs @@ -7,8 +7,8 @@ impl PartialEq for Foo { true } fn ne(&self, _: &Foo) -> bool { - //~^ ERROR: re-implementing `PartialEq::ne` is unnecessary - //~| NOTE: `-D clippy::partialeq-ne-impl` implied by `-D warnings` + //~^ partialeq_ne_impl + false } } diff --git a/tests/ui/partialeq_to_none.fixed b/tests/ui/partialeq_to_none.fixed index 87adbca39484..e700cc56349f 100644 --- a/tests/ui/partialeq_to_none.fixed +++ b/tests/ui/partialeq_to_none.fixed @@ -12,6 +12,7 @@ impl PartialEq> for Foobar { #[allow(dead_code)] fn foo(f: Option) -> &'static str { if f.is_some() { "yay" } else { "nay" } + //~^ partialeq_to_none } fn foobar() -> Option<()> { @@ -42,19 +43,28 @@ fn main() { let x = Some(0); let _ = x.is_none(); + //~^ partialeq_to_none let _ = x.is_some(); + //~^ partialeq_to_none let _ = x.is_none(); + //~^ partialeq_to_none let _ = x.is_some(); + //~^ partialeq_to_none if foobar().is_none() {} + //~^ partialeq_to_none if bar().ok().is_some() {} + //~^ partialeq_to_none let _ = Some(1 + 2).is_some(); + //~^ partialeq_to_none let _ = { Some(0) }.is_none(); + //~^ partialeq_to_none let _ = { + //~^ partialeq_to_none /* This comment runs long */ @@ -65,10 +75,15 @@ fn main() { let _ = Foobar == None; let _ = optref().is_none(); + //~^ partialeq_to_none let _ = optref().is_some(); + //~^ partialeq_to_none let _ = optref().is_none(); + //~^ partialeq_to_none let _ = optref().is_some(); + //~^ partialeq_to_none let x = Box::new(Option::<()>::None); let _ = (*x).is_some(); + //~^ partialeq_to_none } diff --git a/tests/ui/partialeq_to_none.rs b/tests/ui/partialeq_to_none.rs index b623e6a66268..1bae076dd337 100644 --- a/tests/ui/partialeq_to_none.rs +++ b/tests/ui/partialeq_to_none.rs @@ -12,6 +12,7 @@ impl PartialEq> for Foobar { #[allow(dead_code)] fn foo(f: Option) -> &'static str { if f != None { "yay" } else { "nay" } + //~^ partialeq_to_none } fn foobar() -> Option<()> { @@ -42,19 +43,28 @@ fn main() { let x = Some(0); let _ = x == None; + //~^ partialeq_to_none let _ = x != None; + //~^ partialeq_to_none let _ = None == x; + //~^ partialeq_to_none let _ = None != x; + //~^ partialeq_to_none if foobar() == None {} + //~^ partialeq_to_none if bar().ok() != None {} + //~^ partialeq_to_none let _ = Some(1 + 2) != None; + //~^ partialeq_to_none let _ = { Some(0) } == None; + //~^ partialeq_to_none let _ = { + //~^ partialeq_to_none /* This comment runs long */ @@ -65,10 +75,15 @@ fn main() { let _ = Foobar == None; let _ = optref() == &&None; + //~^ partialeq_to_none let _ = &&None != optref(); + //~^ partialeq_to_none let _ = **optref() == None; + //~^ partialeq_to_none let _ = &None != *optref(); + //~^ partialeq_to_none let x = Box::new(Option::<()>::None); let _ = None != *x; + //~^ partialeq_to_none } diff --git a/tests/ui/partialeq_to_none.stderr b/tests/ui/partialeq_to_none.stderr index b588fbf32b60..b09bd7fa0f42 100644 --- a/tests/ui/partialeq_to_none.stderr +++ b/tests/ui/partialeq_to_none.stderr @@ -8,58 +8,59 @@ LL | if f != None { "yay" } else { "nay" } = help: to override `-D warnings` add `#[allow(clippy::partialeq_to_none)]` error: binary comparison to literal `Option::None` - --> tests/ui/partialeq_to_none.rs:44:13 + --> tests/ui/partialeq_to_none.rs:45:13 | LL | let _ = x == None; | ^^^^^^^^^ help: use `Option::is_none()` instead: `x.is_none()` error: binary comparison to literal `Option::None` - --> tests/ui/partialeq_to_none.rs:45:13 + --> tests/ui/partialeq_to_none.rs:47:13 | LL | let _ = x != None; | ^^^^^^^^^ help: use `Option::is_some()` instead: `x.is_some()` error: binary comparison to literal `Option::None` - --> tests/ui/partialeq_to_none.rs:46:13 + --> tests/ui/partialeq_to_none.rs:49:13 | LL | let _ = None == x; | ^^^^^^^^^ help: use `Option::is_none()` instead: `x.is_none()` error: binary comparison to literal `Option::None` - --> tests/ui/partialeq_to_none.rs:47:13 + --> tests/ui/partialeq_to_none.rs:51:13 | LL | let _ = None != x; | ^^^^^^^^^ help: use `Option::is_some()` instead: `x.is_some()` error: binary comparison to literal `Option::None` - --> tests/ui/partialeq_to_none.rs:49:8 + --> tests/ui/partialeq_to_none.rs:54:8 | LL | if foobar() == None {} | ^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `foobar().is_none()` error: binary comparison to literal `Option::None` - --> tests/ui/partialeq_to_none.rs:51:8 + --> tests/ui/partialeq_to_none.rs:57:8 | LL | if bar().ok() != None {} | ^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `bar().ok().is_some()` error: binary comparison to literal `Option::None` - --> tests/ui/partialeq_to_none.rs:53:13 + --> tests/ui/partialeq_to_none.rs:60:13 | LL | let _ = Some(1 + 2) != None; | ^^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `Some(1 + 2).is_some()` error: binary comparison to literal `Option::None` - --> tests/ui/partialeq_to_none.rs:55:13 + --> tests/ui/partialeq_to_none.rs:63:13 | LL | let _ = { Some(0) } == None; | ^^^^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `{ Some(0) }.is_none()` error: binary comparison to literal `Option::None` - --> tests/ui/partialeq_to_none.rs:57:13 + --> tests/ui/partialeq_to_none.rs:66:13 | LL | let _ = { | _____________^ +LL | | LL | | /* LL | | This comment runs long LL | | */ @@ -70,6 +71,7 @@ LL | | } != None; help: use `Option::is_some()` instead | LL ~ let _ = { +LL + LL + /* LL + This comment runs long LL + */ @@ -78,31 +80,31 @@ LL ~ }.is_some(); | error: binary comparison to literal `Option::None` - --> tests/ui/partialeq_to_none.rs:67:13 + --> tests/ui/partialeq_to_none.rs:77:13 | LL | let _ = optref() == &&None; | ^^^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `optref().is_none()` error: binary comparison to literal `Option::None` - --> tests/ui/partialeq_to_none.rs:68:13 + --> tests/ui/partialeq_to_none.rs:79:13 | LL | let _ = &&None != optref(); | ^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `optref().is_some()` error: binary comparison to literal `Option::None` - --> tests/ui/partialeq_to_none.rs:69:13 + --> tests/ui/partialeq_to_none.rs:81:13 | LL | let _ = **optref() == None; | ^^^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `optref().is_none()` error: binary comparison to literal `Option::None` - --> tests/ui/partialeq_to_none.rs:70:13 + --> tests/ui/partialeq_to_none.rs:83:13 | LL | let _ = &None != *optref(); | ^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `optref().is_some()` error: binary comparison to literal `Option::None` - --> tests/ui/partialeq_to_none.rs:73:13 + --> tests/ui/partialeq_to_none.rs:87:13 | LL | let _ = None != *x; | ^^^^^^^^^^ help: use `Option::is_some()` instead: `(*x).is_some()` diff --git a/tests/ui/path_buf_push_overwrite.fixed b/tests/ui/path_buf_push_overwrite.fixed index 1a46d72378f8..5c818bad3d53 100644 --- a/tests/ui/path_buf_push_overwrite.fixed +++ b/tests/ui/path_buf_push_overwrite.fixed @@ -5,4 +5,5 @@ use std::path::PathBuf; fn main() { let mut x = PathBuf::from("/foo"); x.push("bar"); + //~^ path_buf_push_overwrite } diff --git a/tests/ui/path_buf_push_overwrite.rs b/tests/ui/path_buf_push_overwrite.rs index 3e3f84b17a4b..650ae3286a0c 100644 --- a/tests/ui/path_buf_push_overwrite.rs +++ b/tests/ui/path_buf_push_overwrite.rs @@ -5,4 +5,5 @@ use std::path::PathBuf; fn main() { let mut x = PathBuf::from("/foo"); x.push("/bar"); + //~^ path_buf_push_overwrite } diff --git a/tests/ui/path_ends_with_ext.fixed b/tests/ui/path_ends_with_ext.fixed index 49767e242cee..fa4286e11644 100644 --- a/tests/ui/path_ends_with_ext.fixed +++ b/tests/ui/path_ends_with_ext.fixed @@ -9,7 +9,7 @@ macro_rules! arg { fn test(path: &Path) { path.extension().is_some_and(|ext| ext == "md"); - //~^ ERROR: this looks like a failed attempt at checking for the file extension + //~^ path_ends_with_ext // some "extensions" are allowed by default path.ends_with(".git"); @@ -30,7 +30,7 @@ fn test(path: &Path) { #[clippy::msrv = "1.69"] fn under_msv(path: &Path) -> bool { path.extension().map_or(false, |ext| ext == "md") - //~^ ERROR: this looks like a failed attempt at checking for the file extension + //~^ path_ends_with_ext } fn main() {} diff --git a/tests/ui/path_ends_with_ext.rs b/tests/ui/path_ends_with_ext.rs index 2dfd046218af..00d7ede8ef93 100644 --- a/tests/ui/path_ends_with_ext.rs +++ b/tests/ui/path_ends_with_ext.rs @@ -9,7 +9,7 @@ macro_rules! arg { fn test(path: &Path) { path.ends_with(".md"); - //~^ ERROR: this looks like a failed attempt at checking for the file extension + //~^ path_ends_with_ext // some "extensions" are allowed by default path.ends_with(".git"); @@ -30,7 +30,7 @@ fn test(path: &Path) { #[clippy::msrv = "1.69"] fn under_msv(path: &Path) -> bool { path.ends_with(".md") - //~^ ERROR: this looks like a failed attempt at checking for the file extension + //~^ path_ends_with_ext } fn main() {} diff --git a/tests/ui/pathbuf_init_then_push.rs b/tests/ui/pathbuf_init_then_push.rs index 4a7ae00a7352..7b65392e9519 100644 --- a/tests/ui/pathbuf_init_then_push.rs +++ b/tests/ui/pathbuf_init_then_push.rs @@ -3,17 +3,21 @@ use std::path::PathBuf; fn main() { - let mut path_buf = PathBuf::new(); //~ ERROR: calls to `push` immediately after creation + let mut path_buf = PathBuf::new(); + //~^ pathbuf_init_then_push path_buf.push("foo"); - path_buf = PathBuf::from("foo"); //~ ERROR: calls to `push` immediately after creation + path_buf = PathBuf::from("foo"); + //~^ pathbuf_init_then_push path_buf.push("bar"); let bar = "bar"; - path_buf = PathBuf::from("foo"); //~ ERROR: calls to `push` immediately after creation + path_buf = PathBuf::from("foo"); + //~^ pathbuf_init_then_push path_buf.push(bar); - let mut path_buf = PathBuf::from("foo").join("bar"); //~ ERROR: calls to `push` immediately after creation + let mut path_buf = PathBuf::from("foo").join("bar"); + //~^ pathbuf_init_then_push path_buf.push("buz"); let mut x = PathBuf::new(); diff --git a/tests/ui/pathbuf_init_then_push.stderr b/tests/ui/pathbuf_init_then_push.stderr index e7aa291035d2..1aa730a0bea2 100644 --- a/tests/ui/pathbuf_init_then_push.stderr +++ b/tests/ui/pathbuf_init_then_push.stderr @@ -2,6 +2,7 @@ error: calls to `push` immediately after creation --> tests/ui/pathbuf_init_then_push.rs:6:5 | LL | / let mut path_buf = PathBuf::new(); +LL | | LL | | path_buf.push("foo"); | |_________________________^ help: consider using the `.join()`: `let mut path_buf = PathBuf::from("foo");` | @@ -9,23 +10,26 @@ LL | | path_buf.push("foo"); = help: to override `-D warnings` add `#[allow(clippy::pathbuf_init_then_push)]` error: calls to `push` immediately after creation - --> tests/ui/pathbuf_init_then_push.rs:9:5 + --> tests/ui/pathbuf_init_then_push.rs:10:5 | LL | / path_buf = PathBuf::from("foo"); +LL | | LL | | path_buf.push("bar"); | |_________________________^ help: consider using the `.join()`: `path_buf = PathBuf::from("foo").join("bar");` error: calls to `push` immediately after creation - --> tests/ui/pathbuf_init_then_push.rs:13:5 + --> tests/ui/pathbuf_init_then_push.rs:15:5 | LL | / path_buf = PathBuf::from("foo"); +LL | | LL | | path_buf.push(bar); | |_______________________^ help: consider using the `.join()`: `path_buf = PathBuf::from("foo").join(bar);` error: calls to `push` immediately after creation - --> tests/ui/pathbuf_init_then_push.rs:16:5 + --> tests/ui/pathbuf_init_then_push.rs:19:5 | LL | / let mut path_buf = PathBuf::from("foo").join("bar"); +LL | | LL | | path_buf.push("buz"); | |_________________________^ help: consider using the `.join()`: `let mut path_buf = PathBuf::from("foo").join("bar").join("buz");` diff --git a/tests/ui/pattern_type_mismatch/mutability.rs b/tests/ui/pattern_type_mismatch/mutability.rs index 61dee47cb192..bdac3764bf16 100644 --- a/tests/ui/pattern_type_mismatch/mutability.rs +++ b/tests/ui/pattern_type_mismatch/mutability.rs @@ -7,14 +7,14 @@ fn should_lint() { let value = &Some(23); match value { Some(_) => (), - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch _ => (), } let value = &mut Some(23); match value { Some(_) => (), - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch _ => (), } } diff --git a/tests/ui/pattern_type_mismatch/pattern_alternatives.rs b/tests/ui/pattern_type_mismatch/pattern_alternatives.rs index 558d496ae2c0..3c789f570b03 100644 --- a/tests/ui/pattern_type_mismatch/pattern_alternatives.rs +++ b/tests/ui/pattern_type_mismatch/pattern_alternatives.rs @@ -13,11 +13,13 @@ fn alternatives() { // not ok if let Value::B | Value::A(_) = ref_value {} - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch + if let &Value::B | &Value::A(Some(_)) = ref_value {} - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch + if let Value::B | Value::A(Some(_)) = *ref_value {} - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch // ok if let &Value::B | &Value::A(_) = ref_value {} diff --git a/tests/ui/pattern_type_mismatch/pattern_alternatives.stderr b/tests/ui/pattern_type_mismatch/pattern_alternatives.stderr index e1aec2497cd1..763f688ea897 100644 --- a/tests/ui/pattern_type_mismatch/pattern_alternatives.stderr +++ b/tests/ui/pattern_type_mismatch/pattern_alternatives.stderr @@ -9,7 +9,7 @@ LL | if let Value::B | Value::A(_) = ref_value {} = help: to override `-D warnings` add `#[allow(clippy::pattern_type_mismatch)]` error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/pattern_alternatives.rs:17:34 + --> tests/ui/pattern_type_mismatch/pattern_alternatives.rs:18:34 | LL | if let &Value::B | &Value::A(Some(_)) = ref_value {} | ^^^^^^^ @@ -17,7 +17,7 @@ LL | if let &Value::B | &Value::A(Some(_)) = ref_value {} = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/pattern_alternatives.rs:19:32 + --> tests/ui/pattern_type_mismatch/pattern_alternatives.rs:21:32 | LL | if let Value::B | Value::A(Some(_)) = *ref_value {} | ^^^^^^^ diff --git a/tests/ui/pattern_type_mismatch/pattern_structs.rs b/tests/ui/pattern_type_mismatch/pattern_structs.rs index d9b22693f297..7fc53d591a91 100644 --- a/tests/ui/pattern_type_mismatch/pattern_structs.rs +++ b/tests/ui/pattern_type_mismatch/pattern_structs.rs @@ -11,11 +11,13 @@ fn struct_types() { // not ok let Struct { .. } = ref_value; - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch + if let &Struct { ref_inner: Some(_) } = ref_value {} - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch + if let Struct { ref_inner: Some(_) } = *ref_value {} - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch // ok let &Struct { .. } = ref_value; @@ -33,15 +35,19 @@ fn struct_enum_variants() { // not ok if let StructEnum::Var { .. } = ref_value {} - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch + if let StructEnum::Var { inner_ref: Some(_) } = ref_value {} - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch + if let &StructEnum::Var { inner_ref: Some(_) } = ref_value {} - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch + if let StructEnum::Var { inner_ref: Some(_) } = *ref_value {} - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch + if let StructEnum::Empty = ref_value {} - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch // ok if let &StructEnum::Var { .. } = ref_value {} diff --git a/tests/ui/pattern_type_mismatch/pattern_structs.stderr b/tests/ui/pattern_type_mismatch/pattern_structs.stderr index e5d6e9ed6f81..70f7bdc38906 100644 --- a/tests/ui/pattern_type_mismatch/pattern_structs.stderr +++ b/tests/ui/pattern_type_mismatch/pattern_structs.stderr @@ -9,7 +9,7 @@ LL | let Struct { .. } = ref_value; = help: to override `-D warnings` add `#[allow(clippy::pattern_type_mismatch)]` error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/pattern_structs.rs:15:33 + --> tests/ui/pattern_type_mismatch/pattern_structs.rs:16:33 | LL | if let &Struct { ref_inner: Some(_) } = ref_value {} | ^^^^^^^ @@ -17,7 +17,7 @@ LL | if let &Struct { ref_inner: Some(_) } = ref_value {} = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/pattern_structs.rs:17:32 + --> tests/ui/pattern_type_mismatch/pattern_structs.rs:19:32 | LL | if let Struct { ref_inner: Some(_) } = *ref_value {} | ^^^^^^^ @@ -25,7 +25,7 @@ LL | if let Struct { ref_inner: Some(_) } = *ref_value {} = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/pattern_structs.rs:35:12 + --> tests/ui/pattern_type_mismatch/pattern_structs.rs:37:12 | LL | if let StructEnum::Var { .. } = ref_value {} | ^^^^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | if let StructEnum::Var { .. } = ref_value {} = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/pattern_structs.rs:37:12 + --> tests/ui/pattern_type_mismatch/pattern_structs.rs:40:12 | LL | if let StructEnum::Var { inner_ref: Some(_) } = ref_value {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | if let StructEnum::Var { inner_ref: Some(_) } = ref_value {} = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/pattern_structs.rs:39:42 + --> tests/ui/pattern_type_mismatch/pattern_structs.rs:43:42 | LL | if let &StructEnum::Var { inner_ref: Some(_) } = ref_value {} | ^^^^^^^ @@ -49,7 +49,7 @@ LL | if let &StructEnum::Var { inner_ref: Some(_) } = ref_value {} = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/pattern_structs.rs:41:41 + --> tests/ui/pattern_type_mismatch/pattern_structs.rs:46:41 | LL | if let StructEnum::Var { inner_ref: Some(_) } = *ref_value {} | ^^^^^^^ @@ -57,7 +57,7 @@ LL | if let StructEnum::Var { inner_ref: Some(_) } = *ref_value {} = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/pattern_structs.rs:43:12 + --> tests/ui/pattern_type_mismatch/pattern_structs.rs:49:12 | LL | if let StructEnum::Empty = ref_value {} | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/pattern_type_mismatch/pattern_tuples.rs b/tests/ui/pattern_type_mismatch/pattern_tuples.rs index f44e3543c96a..ecd95d9ae2b3 100644 --- a/tests/ui/pattern_type_mismatch/pattern_tuples.rs +++ b/tests/ui/pattern_type_mismatch/pattern_tuples.rs @@ -9,11 +9,13 @@ fn tuple_types() { // not ok let TupleStruct(_) = ref_value; - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch + if let &TupleStruct(Some(_)) = ref_value {} - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch + if let TupleStruct(Some(_)) = *ref_value {} - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch // ok let &TupleStruct(_) = ref_value; @@ -31,13 +33,16 @@ fn tuple_enum_variants() { // not ok if let TupleEnum::Var(_) = ref_value {} - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch + if let &TupleEnum::Var(Some(_)) = ref_value {} - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch + if let TupleEnum::Var(Some(_)) = *ref_value {} - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch + if let TupleEnum::Empty = ref_value {} - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch // ok if let &TupleEnum::Var(_) = ref_value {} @@ -53,11 +58,13 @@ fn plain_tuples() { // not ok let (_a, _b) = ref_value; - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch + if let &(_a, Some(_)) = ref_value {} - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch + if let (_a, Some(_)) = *ref_value {} - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch // ok let &(_a, _b) = ref_value; diff --git a/tests/ui/pattern_type_mismatch/pattern_tuples.stderr b/tests/ui/pattern_type_mismatch/pattern_tuples.stderr index 9ecf12a1d639..d47c5d509c3f 100644 --- a/tests/ui/pattern_type_mismatch/pattern_tuples.stderr +++ b/tests/ui/pattern_type_mismatch/pattern_tuples.stderr @@ -9,7 +9,7 @@ LL | let TupleStruct(_) = ref_value; = help: to override `-D warnings` add `#[allow(clippy::pattern_type_mismatch)]` error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:13:25 + --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:14:25 | LL | if let &TupleStruct(Some(_)) = ref_value {} | ^^^^^^^ @@ -17,7 +17,7 @@ LL | if let &TupleStruct(Some(_)) = ref_value {} = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:15:24 + --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:17:24 | LL | if let TupleStruct(Some(_)) = *ref_value {} | ^^^^^^^ @@ -25,7 +25,7 @@ LL | if let TupleStruct(Some(_)) = *ref_value {} = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:33:12 + --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:35:12 | LL | if let TupleEnum::Var(_) = ref_value {} | ^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | if let TupleEnum::Var(_) = ref_value {} = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:35:28 + --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:38:28 | LL | if let &TupleEnum::Var(Some(_)) = ref_value {} | ^^^^^^^ @@ -41,7 +41,7 @@ LL | if let &TupleEnum::Var(Some(_)) = ref_value {} = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:37:27 + --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:41:27 | LL | if let TupleEnum::Var(Some(_)) = *ref_value {} | ^^^^^^^ @@ -49,7 +49,7 @@ LL | if let TupleEnum::Var(Some(_)) = *ref_value {} = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:39:12 + --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:44:12 | LL | if let TupleEnum::Empty = ref_value {} | ^^^^^^^^^^^^^^^^ @@ -57,7 +57,7 @@ LL | if let TupleEnum::Empty = ref_value {} = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:55:9 + --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:60:9 | LL | let (_a, _b) = ref_value; | ^^^^^^^^ @@ -65,7 +65,7 @@ LL | let (_a, _b) = ref_value; = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:57:18 + --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:63:18 | LL | if let &(_a, Some(_)) = ref_value {} | ^^^^^^^ @@ -73,7 +73,7 @@ LL | if let &(_a, Some(_)) = ref_value {} = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:59:17 + --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:66:17 | LL | if let (_a, Some(_)) = *ref_value {} | ^^^^^^^ diff --git a/tests/ui/pattern_type_mismatch/syntax.rs b/tests/ui/pattern_type_mismatch/syntax.rs index dbc7c3f31061..0bbc26a0c27c 100644 --- a/tests/ui/pattern_type_mismatch/syntax.rs +++ b/tests/ui/pattern_type_mismatch/syntax.rs @@ -9,7 +9,7 @@ fn syntax_match() { // not ok match ref_value { Some(_) => (), - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch None => (), } @@ -29,7 +29,7 @@ fn syntax_if_let() { // not ok if let Some(_) = ref_value {} - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch // ok if let &Some(_) = ref_value {} @@ -41,7 +41,8 @@ fn syntax_while_let() { // not ok while let Some(_) = ref_value { - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch + break; } @@ -60,7 +61,7 @@ fn syntax_for() { // not ok for (_a, _b) in slice.iter() {} - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch // ok for &(_a, _b) in slice.iter() {} @@ -71,7 +72,7 @@ fn syntax_let() { // not ok let (_n, _m) = ref_value; - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch // ok let &(_n, _m) = ref_value; @@ -81,7 +82,7 @@ fn syntax_let() { fn syntax_fn() { // not ok fn foo((_a, _b): &(i32, i32)) {} - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch // ok fn foo_ok_1(&(_a, _b): &(i32, i32)) {} @@ -96,7 +97,7 @@ fn syntax_closure() { // not ok foo(|(_a, _b)| ()); - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch // ok foo(|&(_a, _b)| ()); @@ -113,7 +114,7 @@ fn macro_with_expression() { // not ok matching_macro!(match value { Some(_) => (), - //~^ ERROR: type of pattern does not match the expression type + //~^ pattern_type_mismatch _ => (), }); @@ -134,6 +135,7 @@ fn macro_expansion() { // not ok match $e { Some(_) => (), + //~^ pattern_type_mismatch _ => (), } diff --git a/tests/ui/pattern_type_mismatch/syntax.stderr b/tests/ui/pattern_type_mismatch/syntax.stderr index 9186a01b9c75..3f6b5feb9b07 100644 --- a/tests/ui/pattern_type_mismatch/syntax.stderr +++ b/tests/ui/pattern_type_mismatch/syntax.stderr @@ -25,7 +25,7 @@ LL | while let Some(_) = ref_value { = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/syntax.rs:62:9 + --> tests/ui/pattern_type_mismatch/syntax.rs:63:9 | LL | for (_a, _b) in slice.iter() {} | ^^^^^^^^ @@ -33,7 +33,7 @@ LL | for (_a, _b) in slice.iter() {} = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/syntax.rs:73:9 + --> tests/ui/pattern_type_mismatch/syntax.rs:74:9 | LL | let (_n, _m) = ref_value; | ^^^^^^^^ @@ -41,7 +41,7 @@ LL | let (_n, _m) = ref_value; = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/syntax.rs:83:12 + --> tests/ui/pattern_type_mismatch/syntax.rs:84:12 | LL | fn foo((_a, _b): &(i32, i32)) {} | ^^^^^^^^ @@ -49,7 +49,7 @@ LL | fn foo((_a, _b): &(i32, i32)) {} = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/syntax.rs:98:10 + --> tests/ui/pattern_type_mismatch/syntax.rs:99:10 | LL | foo(|(_a, _b)| ()); | ^^^^^^^^ @@ -57,7 +57,7 @@ LL | foo(|(_a, _b)| ()); = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/syntax.rs:115:9 + --> tests/ui/pattern_type_mismatch/syntax.rs:116:9 | LL | Some(_) => (), | ^^^^^^^ @@ -65,7 +65,7 @@ LL | Some(_) => (), = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/syntax.rs:136:17 + --> tests/ui/pattern_type_mismatch/syntax.rs:137:17 | LL | Some(_) => (), | ^^^^^^^ diff --git a/tests/ui/patterns.fixed b/tests/ui/patterns.fixed index feaec33ac15a..bcb8ecfc38d2 100644 --- a/tests/ui/patterns.fixed +++ b/tests/ui/patterns.fixed @@ -12,6 +12,7 @@ fn main() { match v { Some(x) => (), y => (), + //~^ redundant_pattern } match v { Some(x) => (), @@ -27,6 +28,7 @@ fn main() { // required "ref" left out in suggestion: #5271 match mutv { ref mut x => { + //~^ redundant_pattern x.push(4); println!("vec: {:?}", x); }, @@ -35,6 +37,7 @@ fn main() { match mutv { ref x => println!("vec: {:?}", x), + //~^ redundant_pattern ref y if y == &vec![0] => (), } external! { diff --git a/tests/ui/patterns.rs b/tests/ui/patterns.rs index 53812c7deec3..19639ebd13d6 100644 --- a/tests/ui/patterns.rs +++ b/tests/ui/patterns.rs @@ -12,6 +12,7 @@ fn main() { match v { Some(x) => (), y @ _ => (), + //~^ redundant_pattern } match v { Some(x) => (), @@ -27,6 +28,7 @@ fn main() { // required "ref" left out in suggestion: #5271 match mutv { ref mut x @ _ => { + //~^ redundant_pattern x.push(4); println!("vec: {:?}", x); }, @@ -35,6 +37,7 @@ fn main() { match mutv { ref x @ _ => println!("vec: {:?}", x), + //~^ redundant_pattern ref y if y == &vec![0] => (), } external! { diff --git a/tests/ui/patterns.stderr b/tests/ui/patterns.stderr index fa4cf7f83562..b9950fe181cc 100644 --- a/tests/ui/patterns.stderr +++ b/tests/ui/patterns.stderr @@ -8,13 +8,13 @@ LL | y @ _ => (), = help: to override `-D warnings` add `#[allow(clippy::redundant_pattern)]` error: the `x @ _` pattern can be written as just `x` - --> tests/ui/patterns.rs:29:9 + --> tests/ui/patterns.rs:30:9 | LL | ref mut x @ _ => { | ^^^^^^^^^^^^^ help: try: `ref mut x` error: the `x @ _` pattern can be written as just `x` - --> tests/ui/patterns.rs:37:9 + --> tests/ui/patterns.rs:39:9 | LL | ref x @ _ => println!("vec: {:?}", x), | ^^^^^^^^^ help: try: `ref x` diff --git a/tests/ui/permissions_set_readonly_false.rs b/tests/ui/permissions_set_readonly_false.rs index 5a84a64fd2d1..ccca523da551 100644 --- a/tests/ui/permissions_set_readonly_false.rs +++ b/tests/ui/permissions_set_readonly_false.rs @@ -17,8 +17,8 @@ fn main() { let mut permissions = metadata.permissions(); // lint here permissions.set_readonly(false); - //~^ ERROR: call to `set_readonly` with argument `false` - //~| NOTE: on Unix platforms this results in the file being world writable + //~^ permissions_set_readonly_false + // no lint permissions.set_readonly(true); diff --git a/tests/ui/pointers_in_nomem_asm_block.rs b/tests/ui/pointers_in_nomem_asm_block.rs index b5abcbb3474c..171716be2602 100644 --- a/tests/ui/pointers_in_nomem_asm_block.rs +++ b/tests/ui/pointers_in_nomem_asm_block.rs @@ -9,7 +9,8 @@ unsafe fn nomem_bad(p: &i32) { asm!( "asdf {p1}, {p2}, {p3}", p1 = in(reg) p, - //~^ ERROR: passing pointers to nomem asm block + //~^ pointers_in_nomem_asm_block + p2 = in(reg) p as *const _ as usize, p3 = in(reg) p, options(nomem, nostack, preserves_flags) @@ -24,10 +25,10 @@ unsafe fn nomem_good(p: &i32) { unsafe fn nomem_bad2(p: &mut i32) { asm!("asdf {p}", p = in(reg) p, options(nomem, nostack, preserves_flags)); - //~^ ERROR: passing pointers to nomem asm block + //~^ pointers_in_nomem_asm_block } unsafe fn nomem_fn(p: extern "C" fn()) { asm!("call {p}", p = in(reg) p, options(nomem)); - //~^ ERROR: passing pointers to nomem asm block + //~^ pointers_in_nomem_asm_block } diff --git a/tests/ui/pointers_in_nomem_asm_block.stderr b/tests/ui/pointers_in_nomem_asm_block.stderr index cabeb37344f2..ca24e34f63c0 100644 --- a/tests/ui/pointers_in_nomem_asm_block.stderr +++ b/tests/ui/pointers_in_nomem_asm_block.stderr @@ -13,7 +13,7 @@ LL | p3 = in(reg) p, = help: to override `-D warnings` add `#[allow(clippy::pointers_in_nomem_asm_block)]` error: passing pointers to nomem asm block - --> tests/ui/pointers_in_nomem_asm_block.rs:26:22 + --> tests/ui/pointers_in_nomem_asm_block.rs:27:22 | LL | asm!("asdf {p}", p = in(reg) p, options(nomem, nostack, preserves_flags)); | ^^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | asm!("asdf {p}", p = in(reg) p, options(nomem, nostack, preserves_flags = note: if this is intentional and no pointers are read or written to, consider allowing the lint error: passing pointers to nomem asm block - --> tests/ui/pointers_in_nomem_asm_block.rs:31:22 + --> tests/ui/pointers_in_nomem_asm_block.rs:32:22 | LL | asm!("call {p}", p = in(reg) p, options(nomem)); | ^^^^^^^^^^^^^ diff --git a/tests/ui/precedence.fixed b/tests/ui/precedence.fixed index 52144a18bac0..cbb78bff68bf 100644 --- a/tests/ui/precedence.fixed +++ b/tests/ui/precedence.fixed @@ -14,12 +14,19 @@ macro_rules! trip { fn main() { 1 << (2 + 3); + //~^ precedence (1 + 2) << 3; + //~^ precedence 4 >> (1 + 1); + //~^ precedence (1 + 3) >> 2; + //~^ precedence 1 ^ (1 - 1); + //~^ precedence 3 | (2 - 1); + //~^ precedence 3 & (5 - 2); + //~^ precedence 0x0F00 & 0x00F0 << 4; 0x0F00 & 0xF000 >> 4; 0x0F00 << 1 ^ 3; diff --git a/tests/ui/precedence.rs b/tests/ui/precedence.rs index 9ef5c43833f8..c73a4020e2e5 100644 --- a/tests/ui/precedence.rs +++ b/tests/ui/precedence.rs @@ -14,12 +14,19 @@ macro_rules! trip { fn main() { 1 << 2 + 3; + //~^ precedence 1 + 2 << 3; + //~^ precedence 4 >> 1 + 1; + //~^ precedence 1 + 3 >> 2; + //~^ precedence 1 ^ 1 - 1; + //~^ precedence 3 | 2 - 1; + //~^ precedence 3 & 5 - 2; + //~^ precedence 0x0F00 & 0x00F0 << 4; 0x0F00 & 0xF000 >> 4; 0x0F00 << 1 ^ 3; diff --git a/tests/ui/precedence.stderr b/tests/ui/precedence.stderr index 68ad5cb4829a..50cd8f4b8146 100644 --- a/tests/ui/precedence.stderr +++ b/tests/ui/precedence.stderr @@ -8,37 +8,37 @@ LL | 1 << 2 + 3; = help: to override `-D warnings` add `#[allow(clippy::precedence)]` error: operator precedence might not be obvious - --> tests/ui/precedence.rs:17:5 + --> tests/ui/precedence.rs:18:5 | LL | 1 + 2 << 3; | ^^^^^^^^^^ help: consider parenthesizing your expression: `(1 + 2) << 3` error: operator precedence might not be obvious - --> tests/ui/precedence.rs:18:5 + --> tests/ui/precedence.rs:20:5 | LL | 4 >> 1 + 1; | ^^^^^^^^^^ help: consider parenthesizing your expression: `4 >> (1 + 1)` error: operator precedence might not be obvious - --> tests/ui/precedence.rs:19:5 + --> tests/ui/precedence.rs:22:5 | LL | 1 + 3 >> 2; | ^^^^^^^^^^ help: consider parenthesizing your expression: `(1 + 3) >> 2` error: operator precedence might not be obvious - --> tests/ui/precedence.rs:20:5 + --> tests/ui/precedence.rs:24:5 | LL | 1 ^ 1 - 1; | ^^^^^^^^^ help: consider parenthesizing your expression: `1 ^ (1 - 1)` error: operator precedence might not be obvious - --> tests/ui/precedence.rs:21:5 + --> tests/ui/precedence.rs:26:5 | LL | 3 | 2 - 1; | ^^^^^^^^^ help: consider parenthesizing your expression: `3 | (2 - 1)` error: operator precedence might not be obvious - --> tests/ui/precedence.rs:22:5 + --> tests/ui/precedence.rs:28:5 | LL | 3 & 5 - 2; | ^^^^^^^^^ help: consider parenthesizing your expression: `3 & (5 - 2)` diff --git a/tests/ui/precedence_bits.fixed b/tests/ui/precedence_bits.fixed index 82fea0d14e43..e0ce4a992bb1 100644 --- a/tests/ui/precedence_bits.fixed +++ b/tests/ui/precedence_bits.fixed @@ -26,9 +26,13 @@ fn main() { 3 | 2 - 1; 3 & 5 - 2; 0x0F00 & (0x00F0 << 4); + //~^ precedence_bits 0x0F00 & (0xF000 >> 4); + //~^ precedence_bits (0x0F00 << 1) ^ 3; + //~^ precedence_bits (0x0F00 << 1) | 2; + //~^ precedence_bits let b = 3; trip!(b * 8); diff --git a/tests/ui/precedence_bits.rs b/tests/ui/precedence_bits.rs index 9b353308b6ee..20d17e26c355 100644 --- a/tests/ui/precedence_bits.rs +++ b/tests/ui/precedence_bits.rs @@ -26,9 +26,13 @@ fn main() { 3 | 2 - 1; 3 & 5 - 2; 0x0F00 & 0x00F0 << 4; + //~^ precedence_bits 0x0F00 & 0xF000 >> 4; + //~^ precedence_bits 0x0F00 << 1 ^ 3; + //~^ precedence_bits 0x0F00 << 1 | 2; + //~^ precedence_bits let b = 3; trip!(b * 8); diff --git a/tests/ui/precedence_bits.stderr b/tests/ui/precedence_bits.stderr index f468186b363c..9cbdca8956d6 100644 --- a/tests/ui/precedence_bits.stderr +++ b/tests/ui/precedence_bits.stderr @@ -8,19 +8,19 @@ LL | 0x0F00 & 0x00F0 << 4; = help: to override `-D warnings` add `#[allow(clippy::precedence_bits)]` error: operator precedence might not be obvious - --> tests/ui/precedence_bits.rs:29:5 + --> tests/ui/precedence_bits.rs:30:5 | LL | 0x0F00 & 0xF000 >> 4; | ^^^^^^^^^^^^^^^^^^^^ help: consider parenthesizing your expression: `0x0F00 & (0xF000 >> 4)` error: operator precedence might not be obvious - --> tests/ui/precedence_bits.rs:30:5 + --> tests/ui/precedence_bits.rs:32:5 | LL | 0x0F00 << 1 ^ 3; | ^^^^^^^^^^^^^^^ help: consider parenthesizing your expression: `(0x0F00 << 1) ^ 3` error: operator precedence might not be obvious - --> tests/ui/precedence_bits.rs:31:5 + --> tests/ui/precedence_bits.rs:34:5 | LL | 0x0F00 << 1 | 2; | ^^^^^^^^^^^^^^^ help: consider parenthesizing your expression: `(0x0F00 << 1) | 2` diff --git a/tests/ui/print.rs b/tests/ui/print.rs index 9ac4b51e1afd..ee3d9dc0de03 100644 --- a/tests/ui/print.rs +++ b/tests/ui/print.rs @@ -9,8 +9,7 @@ struct Foo; impl Display for Foo { fn fmt(&self, f: &mut Formatter) -> Result { write!(f, "{:?}", 43.1415) - //~^ ERROR: use of `Debug`-based formatting - //~| NOTE: `-D clippy::use-debug` implied by `-D warnings` + //~^ use_debug } } @@ -23,21 +22,21 @@ impl Debug for Foo { fn main() { println!("Hello"); - //~^ ERROR: use of `println!` - //~| NOTE: `-D clippy::print-stdout` implied by `-D warnings` + //~^ print_stdout + print!("Hello"); - //~^ ERROR: use of `print!` + //~^ print_stdout print!("Hello {}", "World"); - //~^ ERROR: use of `print!` + //~^ print_stdout print!("Hello {:?}", "World"); - //~^ ERROR: use of `print!` - //~| ERROR: use of `Debug`-based formatting + //~^ print_stdout + //~| use_debug print!("Hello {:#?}", "#orld"); - //~^ ERROR: use of `print!` - //~| ERROR: use of `Debug`-based formatting + //~^ print_stdout + //~| use_debug assert_eq!(42, 1337); diff --git a/tests/ui/print.stderr b/tests/ui/print.stderr index a8374241c831..9dd216bd1449 100644 --- a/tests/ui/print.stderr +++ b/tests/ui/print.stderr @@ -8,7 +8,7 @@ LL | write!(f, "{:?}", 43.1415) = help: to override `-D warnings` add `#[allow(clippy::use_debug)]` error: use of `println!` - --> tests/ui/print.rs:25:5 + --> tests/ui/print.rs:24:5 | LL | println!("Hello"); | ^^^^^^^^^^^^^^^^^ @@ -17,37 +17,37 @@ LL | println!("Hello"); = help: to override `-D warnings` add `#[allow(clippy::print_stdout)]` error: use of `print!` - --> tests/ui/print.rs:28:5 + --> tests/ui/print.rs:27:5 | LL | print!("Hello"); | ^^^^^^^^^^^^^^^ error: use of `print!` - --> tests/ui/print.rs:31:5 + --> tests/ui/print.rs:30:5 | LL | print!("Hello {}", "World"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `print!` - --> tests/ui/print.rs:34:5 + --> tests/ui/print.rs:33:5 | LL | print!("Hello {:?}", "World"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `Debug`-based formatting - --> tests/ui/print.rs:34:19 + --> tests/ui/print.rs:33:19 | LL | print!("Hello {:?}", "World"); | ^^^^ error: use of `print!` - --> tests/ui/print.rs:38:5 + --> tests/ui/print.rs:37:5 | LL | print!("Hello {:#?}", "#orld"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `Debug`-based formatting - --> tests/ui/print.rs:38:19 + --> tests/ui/print.rs:37:19 | LL | print!("Hello {:#?}", "#orld"); | ^^^^^ diff --git a/tests/ui/print_in_format_impl.rs b/tests/ui/print_in_format_impl.rs index 261f50832199..8bc704921220 100644 --- a/tests/ui/print_in_format_impl.rs +++ b/tests/ui/print_in_format_impl.rs @@ -18,17 +18,21 @@ impl Debug for Foo { static WORKS_WITH_NESTED_ITEMS: bool = true; print!("{}", 1); - //~^ ERROR: use of `print!` in `Debug` impl - //~| NOTE: `-D clippy::print-in-format-impl` implied by `-D warnings` + //~^ print_in_format_impl + println!("{}", 2); - //~^ ERROR: use of `println!` in `Debug` impl + //~^ print_in_format_impl + eprint!("{}", 3); - //~^ ERROR: use of `eprint!` in `Debug` impl + //~^ print_in_format_impl + eprintln!("{}", 4); - //~^ ERROR: use of `eprintln!` in `Debug` impl + //~^ print_in_format_impl + nested! { println!("nested"); - //~^ ERROR: use of `println!` in `Debug` impl + //~^ print_in_format_impl + }; write!(f, "{}", 5); @@ -42,7 +46,8 @@ impl Debug for Foo { impl Display for Foo { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { print!("Display"); - //~^ ERROR: use of `print!` in `Display` impl + //~^ print_in_format_impl + write!(f, "Display"); Ok(()) @@ -53,7 +58,8 @@ struct UnnamedFormatter; impl Debug for UnnamedFormatter { fn fmt(&self, _: &mut Formatter) -> Result<(), Error> { println!("UnnamedFormatter"); - //~^ ERROR: use of `println!` in `Debug` impl + //~^ print_in_format_impl + Ok(()) } } diff --git a/tests/ui/print_in_format_impl.stderr b/tests/ui/print_in_format_impl.stderr index 3fb6b3f9c911..91d6ce953849 100644 --- a/tests/ui/print_in_format_impl.stderr +++ b/tests/ui/print_in_format_impl.stderr @@ -14,31 +14,31 @@ LL | println!("{}", 2); | ^^^^^^^^^^^^^^^^^ help: replace with: `writeln!(f, ..)` error: use of `eprint!` in `Debug` impl - --> tests/ui/print_in_format_impl.rs:25:9 + --> tests/ui/print_in_format_impl.rs:26:9 | LL | eprint!("{}", 3); | ^^^^^^^^^^^^^^^^ help: replace with: `write!(f, ..)` error: use of `eprintln!` in `Debug` impl - --> tests/ui/print_in_format_impl.rs:27:9 + --> tests/ui/print_in_format_impl.rs:29:9 | LL | eprintln!("{}", 4); | ^^^^^^^^^^^^^^^^^^ help: replace with: `writeln!(f, ..)` error: use of `println!` in `Debug` impl - --> tests/ui/print_in_format_impl.rs:30:13 + --> tests/ui/print_in_format_impl.rs:33:13 | LL | println!("nested"); | ^^^^^^^^^^^^^^^^^^ help: replace with: `writeln!(f, ..)` error: use of `print!` in `Display` impl - --> tests/ui/print_in_format_impl.rs:44:9 + --> tests/ui/print_in_format_impl.rs:48:9 | LL | print!("Display"); | ^^^^^^^^^^^^^^^^^ help: replace with: `write!(f, ..)` error: use of `println!` in `Debug` impl - --> tests/ui/print_in_format_impl.rs:55:9 + --> tests/ui/print_in_format_impl.rs:60:9 | LL | println!("UnnamedFormatter"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `writeln!(..)` diff --git a/tests/ui/print_literal.fixed b/tests/ui/print_literal.fixed index 328e9a9b999f..24c45a4a61b9 100644 --- a/tests/ui/print_literal.fixed +++ b/tests/ui/print_literal.fixed @@ -25,28 +25,32 @@ fn main() { // these should throw warnings print!("Hello world"); - //~^ ERROR: literal with an empty format string - //~| NOTE: `-D clippy::print-literal` implied by `-D warnings` + //~^ print_literal + println!("Hello {} world", world); - //~^ ERROR: literal with an empty format string + //~^ print_literal + println!("Hello world"); - //~^ ERROR: literal with an empty format string + //~^ print_literal + println!("a literal {:.4}", 5); - //~^ ERROR: literal with an empty format string + //~^ print_literal // positional args don't change the fact // that we're using a literal -- this should // throw a warning println!("hello world"); - //~^ ERROR: literal with an empty format string + //~^ print_literal + println!("world hello"); - //~^ ERROR: literal with an empty format string + //~^ print_literal // named args shouldn't change anything either println!("hello world"); - //~^ ERROR: literal with an empty format string + //~^ print_literal + println!("world hello"); - //~^ ERROR: literal with an empty format string + //~^ print_literal // The string literal from `file!()` has a callsite span that isn't marked as coming from an // expansion @@ -54,23 +58,33 @@ fn main() { // Braces in unicode escapes should not be escaped println!("{{}} \x00 \u{ab123} \\\u{ab123} {{:?}}"); + //~^ print_literal println!("\\\u{1234}"); + //~^ print_literal // This does not lint because it would have to suggest unescaping the character println!(r"{}", "\u{ab123}"); // These are not unicode escapes println!("\\u{{ab123}} \\u{{{{"); + //~^ print_literal println!(r"\u{{ab123}} \u{{{{"); + //~^ print_literal println!("\\{{ab123}} \\u{{{{"); + //~^ print_literal println!("\\u{{ab123}}"); + //~^ print_literal println!("\\\\u{{1234}}"); + //~^ print_literal println!("mixed: {{hello}} {world}"); + //~^ print_literal } fn issue_13959() { println!("\""); + //~^ print_literal println!( " + //~^ print_literal foo \\ \\\\ diff --git a/tests/ui/print_literal.rs b/tests/ui/print_literal.rs index 3130d0b6998e..42ae589ca639 100644 --- a/tests/ui/print_literal.rs +++ b/tests/ui/print_literal.rs @@ -25,28 +25,32 @@ fn main() { // these should throw warnings print!("Hello {}", "world"); - //~^ ERROR: literal with an empty format string - //~| NOTE: `-D clippy::print-literal` implied by `-D warnings` + //~^ print_literal + println!("Hello {} {}", world, "world"); - //~^ ERROR: literal with an empty format string + //~^ print_literal + println!("Hello {}", "world"); - //~^ ERROR: literal with an empty format string + //~^ print_literal + println!("{} {:.4}", "a literal", 5); - //~^ ERROR: literal with an empty format string + //~^ print_literal // positional args don't change the fact // that we're using a literal -- this should // throw a warning println!("{0} {1}", "hello", "world"); - //~^ ERROR: literal with an empty format string + //~^ print_literal + println!("{1} {0}", "hello", "world"); - //~^ ERROR: literal with an empty format string + //~^ print_literal // named args shouldn't change anything either println!("{foo} {bar}", foo = "hello", bar = "world"); - //~^ ERROR: literal with an empty format string + //~^ print_literal + println!("{bar} {foo}", foo = "hello", bar = "world"); - //~^ ERROR: literal with an empty format string + //~^ print_literal // The string literal from `file!()` has a callsite span that isn't marked as coming from an // expansion @@ -54,24 +58,34 @@ fn main() { // Braces in unicode escapes should not be escaped println!("{}", "{} \x00 \u{ab123} \\\u{ab123} {:?}"); + //~^ print_literal println!("{}", "\\\u{1234}"); + //~^ print_literal // This does not lint because it would have to suggest unescaping the character println!(r"{}", "\u{ab123}"); // These are not unicode escapes println!("{}", r"\u{ab123} \u{{"); + //~^ print_literal println!(r"{}", r"\u{ab123} \u{{"); + //~^ print_literal println!("{}", r"\{ab123} \u{{"); + //~^ print_literal println!("{}", "\\u{ab123}"); + //~^ print_literal println!("{}", "\\\\u{1234}"); + //~^ print_literal println!("mixed: {} {world}", "{hello}"); + //~^ print_literal } fn issue_13959() { println!("{}", r#"""#); + //~^ print_literal println!( "{}", r#" + //~^ print_literal foo \ \\ diff --git a/tests/ui/print_literal.stderr b/tests/ui/print_literal.stderr index d967b7c24070..da663000686f 100644 --- a/tests/ui/print_literal.stderr +++ b/tests/ui/print_literal.stderr @@ -25,7 +25,7 @@ LL + println!("Hello {} world", world); | error: literal with an empty format string - --> tests/ui/print_literal.rs:32:26 + --> tests/ui/print_literal.rs:33:26 | LL | println!("Hello {}", "world"); | ^^^^^^^ @@ -37,7 +37,7 @@ LL + println!("Hello world"); | error: literal with an empty format string - --> tests/ui/print_literal.rs:34:26 + --> tests/ui/print_literal.rs:36:26 | LL | println!("{} {:.4}", "a literal", 5); | ^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + println!("a literal {:.4}", 5); | error: literal with an empty format string - --> tests/ui/print_literal.rs:40:25 + --> tests/ui/print_literal.rs:42:25 | LL | println!("{0} {1}", "hello", "world"); | ^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + println!("hello world"); | error: literal with an empty format string - --> tests/ui/print_literal.rs:42:25 + --> tests/ui/print_literal.rs:45:25 | LL | println!("{1} {0}", "hello", "world"); | ^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + println!("world hello"); | error: literal with an empty format string - --> tests/ui/print_literal.rs:46:35 + --> tests/ui/print_literal.rs:49:35 | LL | println!("{foo} {bar}", foo = "hello", bar = "world"); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + println!("hello world"); | error: literal with an empty format string - --> tests/ui/print_literal.rs:48:35 + --> tests/ui/print_literal.rs:52:35 | LL | println!("{bar} {foo}", foo = "hello", bar = "world"); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL + println!("world hello"); | error: literal with an empty format string - --> tests/ui/print_literal.rs:56:20 + --> tests/ui/print_literal.rs:60:20 | LL | println!("{}", "{} \x00 \u{ab123} \\\u{ab123} {:?}"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL + println!("{{}} \x00 \u{ab123} \\\u{ab123} {{:?}}"); | error: literal with an empty format string - --> tests/ui/print_literal.rs:57:20 + --> tests/ui/print_literal.rs:62:20 | LL | println!("{}", "\\\u{1234}"); | ^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL + println!("\\\u{1234}"); | error: literal with an empty format string - --> tests/ui/print_literal.rs:61:20 + --> tests/ui/print_literal.rs:67:20 | LL | println!("{}", r"\u{ab123} \u{{"); | ^^^^^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL + println!("\\u{{ab123}} \\u{{{{"); | error: literal with an empty format string - --> tests/ui/print_literal.rs:62:21 + --> tests/ui/print_literal.rs:69:21 | LL | println!(r"{}", r"\u{ab123} \u{{"); | ^^^^^^^^^^^^^^^^^ @@ -145,7 +145,7 @@ LL + println!(r"\u{{ab123}} \u{{{{"); | error: literal with an empty format string - --> tests/ui/print_literal.rs:63:20 + --> tests/ui/print_literal.rs:71:20 | LL | println!("{}", r"\{ab123} \u{{"); | ^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL + println!("\\{{ab123}} \\u{{{{"); | error: literal with an empty format string - --> tests/ui/print_literal.rs:64:20 + --> tests/ui/print_literal.rs:73:20 | LL | println!("{}", "\\u{ab123}"); | ^^^^^^^^^^^^ @@ -169,7 +169,7 @@ LL + println!("\\u{{ab123}}"); | error: literal with an empty format string - --> tests/ui/print_literal.rs:65:20 + --> tests/ui/print_literal.rs:75:20 | LL | println!("{}", "\\\\u{1234}"); | ^^^^^^^^^^^^^ @@ -181,7 +181,7 @@ LL + println!("\\\\u{{1234}}"); | error: literal with an empty format string - --> tests/ui/print_literal.rs:67:35 + --> tests/ui/print_literal.rs:78:35 | LL | println!("mixed: {} {world}", "{hello}"); | ^^^^^^^^^ @@ -193,7 +193,7 @@ LL + println!("mixed: {{hello}} {world}"); | error: literal with an empty format string - --> tests/ui/print_literal.rs:71:20 + --> tests/ui/print_literal.rs:83:20 | LL | println!("{}", r#"""#); | ^^^^^^ @@ -205,12 +205,12 @@ LL + println!("\""); | error: literal with an empty format string - --> tests/ui/print_literal.rs:74:9 + --> tests/ui/print_literal.rs:87:9 | LL | / r#" +LL | | LL | | foo LL | | \ -LL | | \\ ... | LL | | bar LL | | "# @@ -219,6 +219,7 @@ LL | | "# help: try | LL ~ " +LL + LL + foo LL + \\ LL + \\\\ diff --git a/tests/ui/print_stderr.rs b/tests/ui/print_stderr.rs index 109f43ffe25d..a086dfd37758 100644 --- a/tests/ui/print_stderr.rs +++ b/tests/ui/print_stderr.rs @@ -2,10 +2,11 @@ fn main() { eprintln!("Hello"); - //~^ ERROR: use of `eprintln!` - //~| NOTE: `-D clippy::print-stderr` implied by `-D warnings` + //~^ print_stderr + println!("This should not do anything"); eprint!("World"); - //~^ ERROR: use of `eprint!` + //~^ print_stderr + print!("Nor should this"); } diff --git a/tests/ui/print_stdout_build_script.rs b/tests/ui/print_stdout_build_script.rs index 91448cb0faf8..f01b8538ef49 100644 --- a/tests/ui/print_stdout_build_script.rs +++ b/tests/ui/print_stdout_build_script.rs @@ -1,4 +1,5 @@ //@compile-flags: --crate-name=build_script_build +//@ check-pass #![warn(clippy::print_stdout)] diff --git a/tests/ui/print_with_newline.fixed b/tests/ui/print_with_newline.fixed index 7ac6d2870c12..96c5ee4c1e92 100644 --- a/tests/ui/print_with_newline.fixed +++ b/tests/ui/print_with_newline.fixed @@ -5,16 +5,19 @@ fn main() { println!("Hello"); - //~^ ERROR: using `print!()` with a format string that ends in a single newline - //~| NOTE: `-D clippy::print-with-newline` implied by `-D warnings` + //~^ print_with_newline + println!("Hello {}", "world"); - //~^ ERROR: using `print!()` with a format string that ends in a single newline + //~^ print_with_newline + println!("Hello {} {}", "world", "#2"); - //~^ ERROR: using `print!()` with a format string that ends in a single newline + //~^ print_with_newline + println!("{}", 1265); - //~^ ERROR: using `print!()` with a format string that ends in a single newline + //~^ print_with_newline + println!(); - //~^ ERROR: using `print!()` with a format string that ends in a single newline + //~^ print_with_newline // these are all fine print!(""); @@ -37,7 +40,8 @@ fn main() { // #3514 print!("\\n"); println!("\\"); - //~^ ERROR: using `print!()` with a format string that ends in a single newline + //~^ print_with_newline + print!("\\\\n"); // Raw strings @@ -46,11 +50,11 @@ fn main() { // Literal newlines should also fail println!( - //~^ ERROR: using `print!()` with a format string that ends in a single newline + //~^ print_with_newline ); println!( - //~^ ERROR: using `print!()` with a format string that ends in a single newline + //~^ print_with_newline ); @@ -59,7 +63,8 @@ fn main() { print!("foo\r\n"); // should fail println!("\\r"); - //~^ ERROR: using `print!()` with a format string that ends in a single newline + //~^ print_with_newline + print!("foo\rbar\n"); // Ignore expanded format strings diff --git a/tests/ui/print_with_newline.rs b/tests/ui/print_with_newline.rs index 602d1ea3ec0e..60d1e4788308 100644 --- a/tests/ui/print_with_newline.rs +++ b/tests/ui/print_with_newline.rs @@ -5,16 +5,19 @@ fn main() { print!("Hello\n"); - //~^ ERROR: using `print!()` with a format string that ends in a single newline - //~| NOTE: `-D clippy::print-with-newline` implied by `-D warnings` + //~^ print_with_newline + print!("Hello {}\n", "world"); - //~^ ERROR: using `print!()` with a format string that ends in a single newline + //~^ print_with_newline + print!("Hello {} {}\n", "world", "#2"); - //~^ ERROR: using `print!()` with a format string that ends in a single newline + //~^ print_with_newline + print!("{}\n", 1265); - //~^ ERROR: using `print!()` with a format string that ends in a single newline + //~^ print_with_newline + print!("\n"); - //~^ ERROR: using `print!()` with a format string that ends in a single newline + //~^ print_with_newline // these are all fine print!(""); @@ -37,7 +40,8 @@ fn main() { // #3514 print!("\\n"); print!("\\\n"); - //~^ ERROR: using `print!()` with a format string that ends in a single newline + //~^ print_with_newline + print!("\\\\n"); // Raw strings @@ -46,12 +50,12 @@ fn main() { // Literal newlines should also fail print!( - //~^ ERROR: using `print!()` with a format string that ends in a single newline + //~^ print_with_newline " " ); print!( - //~^ ERROR: using `print!()` with a format string that ends in a single newline + //~^ print_with_newline r" " ); @@ -61,7 +65,8 @@ fn main() { print!("foo\r\n"); // should fail print!("\\r\n"); - //~^ ERROR: using `print!()` with a format string that ends in a single newline + //~^ print_with_newline + print!("foo\rbar\n"); // Ignore expanded format strings diff --git a/tests/ui/print_with_newline.stderr b/tests/ui/print_with_newline.stderr index 9b07299e61d3..9ead0fca113b 100644 --- a/tests/ui/print_with_newline.stderr +++ b/tests/ui/print_with_newline.stderr @@ -25,7 +25,7 @@ LL + println!("Hello {}", "world"); | error: using `print!()` with a format string that ends in a single newline - --> tests/ui/print_with_newline.rs:12:5 + --> tests/ui/print_with_newline.rs:13:5 | LL | print!("Hello {} {}\n", "world", "#2"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + println!("Hello {} {}", "world", "#2"); | error: using `print!()` with a format string that ends in a single newline - --> tests/ui/print_with_newline.rs:14:5 + --> tests/ui/print_with_newline.rs:16:5 | LL | print!("{}\n", 1265); | ^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + println!("{}", 1265); | error: using `print!()` with a format string that ends in a single newline - --> tests/ui/print_with_newline.rs:16:5 + --> tests/ui/print_with_newline.rs:19:5 | LL | print!("\n"); | ^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + println!(); | error: using `print!()` with a format string that ends in a single newline - --> tests/ui/print_with_newline.rs:39:5 + --> tests/ui/print_with_newline.rs:42:5 | LL | print!("\\\n"); | ^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + println!("\\"); | error: using `print!()` with a format string that ends in a single newline - --> tests/ui/print_with_newline.rs:48:5 + --> tests/ui/print_with_newline.rs:52:5 | LL | / print!( LL | | @@ -90,7 +90,7 @@ LL ~ | error: using `print!()` with a format string that ends in a single newline - --> tests/ui/print_with_newline.rs:53:5 + --> tests/ui/print_with_newline.rs:57:5 | LL | / print!( LL | | @@ -107,7 +107,7 @@ LL ~ | error: using `print!()` with a format string that ends in a single newline - --> tests/ui/print_with_newline.rs:63:5 + --> tests/ui/print_with_newline.rs:67:5 | LL | print!("\\r\n"); | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/println_empty_string.fixed b/tests/ui/println_empty_string.fixed index 20811fc75323..05e262ec7786 100644 --- a/tests/ui/println_empty_string.fixed +++ b/tests/ui/println_empty_string.fixed @@ -3,15 +3,19 @@ fn main() { println!(); println!(); + //~^ println_empty_string match "a" { _ => println!(), + //~^ println_empty_string } eprintln!(); eprintln!(); + //~^ println_empty_string match "a" { _ => eprintln!(), + //~^ println_empty_string } } diff --git a/tests/ui/println_empty_string.rs b/tests/ui/println_empty_string.rs index 47f7277dce79..028ddb60dbce 100644 --- a/tests/ui/println_empty_string.rs +++ b/tests/ui/println_empty_string.rs @@ -3,15 +3,19 @@ fn main() { println!(); println!(""); + //~^ println_empty_string match "a" { _ => println!(""), + //~^ println_empty_string } eprintln!(); eprintln!(""); + //~^ println_empty_string match "a" { _ => eprintln!(""), + //~^ println_empty_string } } diff --git a/tests/ui/println_empty_string.stderr b/tests/ui/println_empty_string.stderr index 17de05fa25a4..8b997aef9069 100644 --- a/tests/ui/println_empty_string.stderr +++ b/tests/ui/println_empty_string.stderr @@ -10,7 +10,7 @@ LL | println!(""); = help: to override `-D warnings` add `#[allow(clippy::println_empty_string)]` error: empty string literal in `println!` - --> tests/ui/println_empty_string.rs:8:14 + --> tests/ui/println_empty_string.rs:9:14 | LL | _ => println!(""), | ^^^^^^^^^--^ @@ -18,7 +18,7 @@ LL | _ => println!(""), | help: remove the empty string error: empty string literal in `eprintln!` - --> tests/ui/println_empty_string.rs:12:5 + --> tests/ui/println_empty_string.rs:14:5 | LL | eprintln!(""); | ^^^^^^^^^^--^ @@ -26,7 +26,7 @@ LL | eprintln!(""); | help: remove the empty string error: empty string literal in `eprintln!` - --> tests/ui/println_empty_string.rs:15:14 + --> tests/ui/println_empty_string.rs:18:14 | LL | _ => eprintln!(""), | ^^^^^^^^^^--^ diff --git a/tests/ui/ptr_arg.rs b/tests/ui/ptr_arg.rs index e8b42d3b913b..2d77bf06ff94 100644 --- a/tests/ui/ptr_arg.rs +++ b/tests/ui/ptr_arg.rs @@ -11,39 +11,45 @@ use std::borrow::Cow; use std::path::{Path, PathBuf}; fn do_vec(x: &Vec) { - //~^ ERROR: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - //~| NOTE: `-D clippy::ptr-arg` implied by `-D warnings` + //~^ ptr_arg + //Nothing here } fn do_vec_mut(x: &mut Vec) { - //~^ ERROR: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice w + //~^ ptr_arg + //Nothing here } fn do_vec_mut2(x: &mut Vec) { - //~^ ERROR: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice w + //~^ ptr_arg + x.len(); x.is_empty(); } fn do_str(x: &String) { - //~^ ERROR: writing `&String` instead of `&str` involves a new object where a slice will d + //~^ ptr_arg + //Nothing here either } fn do_str_mut(x: &mut String) { - //~^ ERROR: writing `&mut String` instead of `&mut str` involves a new object where a slic + //~^ ptr_arg + //Nothing here either } fn do_path(x: &PathBuf) { - //~^ ERROR: writing `&PathBuf` instead of `&Path` involves a new object where a slice will + //~^ ptr_arg + //Nothing here either } fn do_path_mut(x: &mut PathBuf) { - //~^ ERROR: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a sl + //~^ ptr_arg + //Nothing here either } @@ -52,7 +58,8 @@ fn main() {} trait Foo { type Item; fn do_vec(x: &Vec); - //~^ ERROR: writing `&Vec` instead of `&[_]` involves a new object where a slice will + //~^ ptr_arg + fn do_item(x: &Self::Item); } @@ -66,7 +73,8 @@ impl Foo for Bar { } fn cloned(x: &Vec) -> Vec { - //~^ ERROR: writing `&Vec` instead of `&[_]` involves a new object where a slice will do + //~^ ptr_arg + let e = x.clone(); let f = e.clone(); // OK let g = x; @@ -76,7 +84,8 @@ fn cloned(x: &Vec) -> Vec { } fn str_cloned(x: &String) -> String { - //~^ ERROR: writing `&String` instead of `&str` involves a new object where a slice will d + //~^ ptr_arg + let a = x.clone(); let b = x.clone(); let c = b.clone(); @@ -85,7 +94,8 @@ fn str_cloned(x: &String) -> String { } fn path_cloned(x: &PathBuf) -> PathBuf { - //~^ ERROR: writing `&PathBuf` instead of `&Path` involves a new object where a slice will + //~^ ptr_arg + let a = x.clone(); let b = x.clone(); let c = b.clone(); @@ -94,7 +104,8 @@ fn path_cloned(x: &PathBuf) -> PathBuf { } fn false_positive_capacity(x: &Vec, y: &String) { - //~^ ERROR: writing `&String` instead of `&str` involves a new object where a slice will d + //~^ ptr_arg + let a = x.capacity(); let b = y.clone(); let c = y.as_str(); @@ -109,7 +120,7 @@ fn false_positive_capacity_too(x: &String) -> String { #[allow(dead_code)] fn test_cow_with_ref(c: &Cow<[i32]>) {} -//~^ ERROR: using a reference to `Cow` is not recommended +//~^ ptr_arg fn test_cow(c: Cow<[i32]>) { let _c = c; @@ -139,7 +150,7 @@ mod issue_5644 { } fn some_allowed(#[allow(clippy::ptr_arg)] _v: &Vec, _s: &String) {} - //~^ ERROR: writing `&String` instead of `&str` involves a new object where a slice wi + //~^ ptr_arg struct S; impl S { @@ -169,26 +180,30 @@ mod issue6509 { use std::path::PathBuf; fn foo_vec(vec: &Vec) { - //~^ ERROR: writing `&Vec` instead of `&[_]` involves a new object where a slice will + //~^ ptr_arg + let _ = vec.clone().pop(); let _ = vec.clone().clone(); } fn foo_path(path: &PathBuf) { - //~^ ERROR: writing `&PathBuf` instead of `&Path` involves a new object where a slice + //~^ ptr_arg + let _ = path.clone().pop(); let _ = path.clone().clone(); } fn foo_str(str: &PathBuf) { - //~^ ERROR: writing `&PathBuf` instead of `&Path` involves a new object where a slice + //~^ ptr_arg + let _ = str.clone().pop(); let _ = str.clone().clone(); } } fn mut_vec_slice_methods(v: &mut Vec) { - //~^ ERROR: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice w + //~^ ptr_arg + v.copy_within(1..5, 10); } @@ -251,9 +266,10 @@ fn dyn_trait_ok(a: &mut Vec, b: &mut String, c: &mut PathBuf) { } fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { - //~^ ERROR: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice w - //~| ERROR: writing `&mut String` instead of `&mut str` involves a new object where a slic - //~| ERROR: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a sl + //~^ ptr_arg + //~| ptr_arg + //~| ptr_arg + trait T {} impl T for Vec {} impl T for [U] {} @@ -277,22 +293,26 @@ mod issue_9218 { // This one has an anonymous lifetime so it's not okay fn cow_elided_lifetime<'a>(input: &'a Cow) -> &'a str { - //~^ ERROR: using a reference to `Cow` is not recommended + //~^ ptr_arg + todo!() } // These two's return types don't use 'a so it's not okay fn cow_bad_ret_ty_1<'a>(input: &'a Cow<'a, str>) -> &'static str { - //~^ ERROR: using a reference to `Cow` is not recommended + //~^ ptr_arg + todo!() } fn cow_bad_ret_ty_2<'a, 'b>(input: &'a Cow<'a, str>) -> &'b str { - //~^ ERROR: using a reference to `Cow` is not recommended + //~^ ptr_arg + todo!() } // Inferred to be `&'a str`, afaik. fn cow_good_ret_ty<'a>(input: &'a Cow<'a, str>) -> &str { + //~^ ERROR: elided lifetime has a name todo!() } } @@ -325,8 +345,9 @@ mod issue_13308 { // Other cases that are still ok to lint and ideally shouldn't regress fn good(v1: &String, v2: &String) { - //~^ ERROR: writing `&String` instead of `&str` - //~^^ ERROR: writing `&String` instead of `&str` + //~^ ptr_arg + //~| ptr_arg + h1(v1); h2(String::new(), v2); } diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr index 1a6b3aa1f8d4..741e60cbd749 100644 --- a/tests/ui/ptr_arg.stderr +++ b/tests/ui/ptr_arg.stderr @@ -1,5 +1,5 @@ error: elided lifetime has a name - --> tests/ui/ptr_arg.rs:295:56 + --> tests/ui/ptr_arg.rs:314:56 | LL | fn cow_good_ret_ty<'a>(input: &'a Cow<'a, str>) -> &str { | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` @@ -23,43 +23,43 @@ LL | fn do_vec_mut(x: &mut Vec) { | ^^^^^^^^^^^^^ help: change this to: `&mut [i64]` error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:24:19 + --> tests/ui/ptr_arg.rs:25:19 | LL | fn do_vec_mut2(x: &mut Vec) { | ^^^^^^^^^^^^^ help: change this to: `&mut [i64]` error: writing `&String` instead of `&str` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:30:14 + --> tests/ui/ptr_arg.rs:32:14 | LL | fn do_str(x: &String) { | ^^^^^^^ help: change this to: `&str` error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:35:18 + --> tests/ui/ptr_arg.rs:38:18 | LL | fn do_str_mut(x: &mut String) { | ^^^^^^^^^^^ help: change this to: `&mut str` error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:40:15 + --> tests/ui/ptr_arg.rs:44:15 | LL | fn do_path(x: &PathBuf) { | ^^^^^^^^ help: change this to: `&Path` error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:45:19 + --> tests/ui/ptr_arg.rs:50:19 | LL | fn do_path_mut(x: &mut PathBuf) { | ^^^^^^^^^^^^ help: change this to: `&mut Path` error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:54:18 + --> tests/ui/ptr_arg.rs:60:18 | LL | fn do_vec(x: &Vec); | ^^^^^^^^^ help: change this to: `&[i64]` error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:68:14 + --> tests/ui/ptr_arg.rs:75:14 | LL | fn cloned(x: &Vec) -> Vec { | ^^^^^^^^ @@ -68,6 +68,7 @@ help: change this to | LL ~ fn cloned(x: &[u8]) -> Vec { LL | +LL | LL ~ let e = x.to_owned(); LL | let f = e.clone(); // OK LL | let g = x; @@ -77,7 +78,7 @@ LL ~ x.to_owned() | error: writing `&String` instead of `&str` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:78:18 + --> tests/ui/ptr_arg.rs:86:18 | LL | fn str_cloned(x: &String) -> String { | ^^^^^^^ @@ -86,6 +87,7 @@ help: change this to | LL ~ fn str_cloned(x: &str) -> String { LL | +LL | LL ~ let a = x.to_owned(); LL ~ let b = x.to_owned(); LL | let c = b.clone(); @@ -94,7 +96,7 @@ LL ~ x.to_owned() | error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:87:19 + --> tests/ui/ptr_arg.rs:96:19 | LL | fn path_cloned(x: &PathBuf) -> PathBuf { | ^^^^^^^^ @@ -103,6 +105,7 @@ help: change this to | LL ~ fn path_cloned(x: &Path) -> PathBuf { LL | +LL | LL ~ let a = x.to_path_buf(); LL ~ let b = x.to_path_buf(); LL | let c = b.clone(); @@ -111,7 +114,7 @@ LL ~ x.to_path_buf() | error: writing `&String` instead of `&str` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:96:44 + --> tests/ui/ptr_arg.rs:106:44 | LL | fn false_positive_capacity(x: &Vec, y: &String) { | ^^^^^^^ @@ -120,25 +123,26 @@ help: change this to | LL ~ fn false_positive_capacity(x: &Vec, y: &str) { LL | +LL | LL | let a = x.capacity(); LL ~ let b = y.to_owned(); LL ~ let c = y; | error: using a reference to `Cow` is not recommended - --> tests/ui/ptr_arg.rs:111:25 + --> tests/ui/ptr_arg.rs:122:25 | LL | fn test_cow_with_ref(c: &Cow<[i32]>) {} | ^^^^^^^^^^^ help: change this to: `&[i32]` error: writing `&String` instead of `&str` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:141:66 + --> tests/ui/ptr_arg.rs:152:66 | LL | fn some_allowed(#[allow(clippy::ptr_arg)] _v: &Vec, _s: &String) {} | ^^^^^^^ help: change this to: `&str` error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:171:21 + --> tests/ui/ptr_arg.rs:182:21 | LL | fn foo_vec(vec: &Vec) { | ^^^^^^^^ @@ -147,12 +151,13 @@ help: change this to | LL ~ fn foo_vec(vec: &[u8]) { LL | +LL | LL ~ let _ = vec.to_owned().pop(); LL ~ let _ = vec.to_owned().clone(); | error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:177:23 + --> tests/ui/ptr_arg.rs:189:23 | LL | fn foo_path(path: &PathBuf) { | ^^^^^^^^ @@ -161,12 +166,13 @@ help: change this to | LL ~ fn foo_path(path: &Path) { LL | +LL | LL ~ let _ = path.to_path_buf().pop(); LL ~ let _ = path.to_path_buf().clone(); | error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:183:21 + --> tests/ui/ptr_arg.rs:196:21 | LL | fn foo_str(str: &PathBuf) { | ^^^^^^^^ @@ -175,60 +181,61 @@ help: change this to | LL ~ fn foo_str(str: &Path) { LL | +LL | LL ~ let _ = str.to_path_buf().pop(); LL ~ let _ = str.to_path_buf().clone(); | error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:190:29 + --> tests/ui/ptr_arg.rs:204:29 | LL | fn mut_vec_slice_methods(v: &mut Vec) { | ^^^^^^^^^^^^^ help: change this to: `&mut [u32]` error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:253:17 + --> tests/ui/ptr_arg.rs:268:17 | LL | fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { | ^^^^^^^^^^^^^ help: change this to: `&mut [u32]` error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:253:35 + --> tests/ui/ptr_arg.rs:268:35 | LL | fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { | ^^^^^^^^^^^ help: change this to: `&mut str` error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:253:51 + --> tests/ui/ptr_arg.rs:268:51 | LL | fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { | ^^^^^^^^^^^^ help: change this to: `&mut Path` error: using a reference to `Cow` is not recommended - --> tests/ui/ptr_arg.rs:279:39 + --> tests/ui/ptr_arg.rs:295:39 | LL | fn cow_elided_lifetime<'a>(input: &'a Cow) -> &'a str { | ^^^^^^^^^^^^ help: change this to: `&str` error: using a reference to `Cow` is not recommended - --> tests/ui/ptr_arg.rs:285:36 + --> tests/ui/ptr_arg.rs:302:36 | LL | fn cow_bad_ret_ty_1<'a>(input: &'a Cow<'a, str>) -> &'static str { | ^^^^^^^^^^^^^^^^ help: change this to: `&str` error: using a reference to `Cow` is not recommended - --> tests/ui/ptr_arg.rs:289:40 + --> tests/ui/ptr_arg.rs:307:40 | LL | fn cow_bad_ret_ty_2<'a, 'b>(input: &'a Cow<'a, str>) -> &'b str { | ^^^^^^^^^^^^^^^^ help: change this to: `&str` error: writing `&String` instead of `&str` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:327:17 + --> tests/ui/ptr_arg.rs:347:17 | LL | fn good(v1: &String, v2: &String) { | ^^^^^^^ help: change this to: `&str` error: writing `&String` instead of `&str` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:327:30 + --> tests/ui/ptr_arg.rs:347:30 | LL | fn good(v1: &String, v2: &String) { | ^^^^^^^ help: change this to: `&str` diff --git a/tests/ui/ptr_as_ptr.fixed b/tests/ui/ptr_as_ptr.fixed index fa15c323540f..2033f31c1eec 100644 --- a/tests/ui/ptr_as_ptr.fixed +++ b/tests/ui/ptr_as_ptr.fixed @@ -16,6 +16,7 @@ mod issue_11278_b { pub fn f(o: &mut super::issue_11278_a::T) -> super::issue_11278_a::T { // Retain `super` *unsafe { Box::from_raw(Box::into_raw(Box::new(o)).cast::>()) } + //~^ ptr_as_ptr } } @@ -25,12 +26,15 @@ fn main() { let mut_ptr: *mut u32 = &mut 42_u32; let _ = ptr.cast::(); + //~^ ptr_as_ptr let _ = mut_ptr.cast::(); + //~^ ptr_as_ptr // Make sure the lint can handle the difference in their operator precedences. unsafe { let ptr_ptr: *const *const u32 = &ptr; let _ = (*ptr_ptr).cast::(); + //~^ ptr_as_ptr } // Changes in mutability. Do not lint this. @@ -44,10 +48,13 @@ fn main() { // Ensure the lint doesn't produce unnecessary turbofish for inferred types. let _: *const i32 = ptr.cast(); + //~^ ptr_as_ptr let _: *mut i32 = mut_ptr.cast(); + //~^ ptr_as_ptr // Make sure the lint is triggered inside a macro let _ = inline!($ptr.cast::()); + //~^ ptr_as_ptr // Do not lint inside macros from external crates let _ = external!($ptr as *const i32); @@ -69,7 +76,9 @@ fn _msrv_1_38() { let mut_ptr: *mut u32 = &mut 42_u32; let _ = ptr.cast::(); + //~^ ptr_as_ptr let _ = mut_ptr.cast::(); + //~^ ptr_as_ptr } #[allow(clippy::unnecessary_cast)] @@ -77,37 +86,45 @@ mod null { fn use_path_mut() -> *mut u32 { use std::ptr; ptr::null_mut::() + //~^ ptr_as_ptr } fn full_path_mut() -> *mut u32 { std::ptr::null_mut::() + //~^ ptr_as_ptr } fn core_path_mut() -> *mut u32 { use core::ptr; ptr::null_mut::() + //~^ ptr_as_ptr } fn full_core_path_mut() -> *mut u32 { core::ptr::null_mut::() + //~^ ptr_as_ptr } fn use_path() -> *const u32 { use std::ptr; ptr::null::() + //~^ ptr_as_ptr } fn full_path() -> *const u32 { std::ptr::null::() + //~^ ptr_as_ptr } fn core_path() -> *const u32 { use core::ptr; ptr::null::() + //~^ ptr_as_ptr } fn full_core_path() -> *const u32 { core::ptr::null::() + //~^ ptr_as_ptr } } @@ -115,37 +132,45 @@ mod null_ptr_infer { fn use_path_mut() -> *mut u32 { use std::ptr; ptr::null_mut() + //~^ ptr_as_ptr } fn full_path_mut() -> *mut u32 { std::ptr::null_mut() + //~^ ptr_as_ptr } fn core_path_mut() -> *mut u32 { use core::ptr; ptr::null_mut() + //~^ ptr_as_ptr } fn full_core_path_mut() -> *mut u32 { core::ptr::null_mut() + //~^ ptr_as_ptr } fn use_path() -> *const u32 { use std::ptr; ptr::null() + //~^ ptr_as_ptr } fn full_path() -> *const u32 { std::ptr::null() + //~^ ptr_as_ptr } fn core_path() -> *const u32 { use core::ptr; ptr::null() + //~^ ptr_as_ptr } fn full_core_path() -> *const u32 { core::ptr::null() + //~^ ptr_as_ptr } } @@ -153,36 +178,44 @@ mod null_entire_infer { fn use_path_mut() -> *mut u32 { use std::ptr; ptr::null_mut() + //~^ ptr_as_ptr } fn full_path_mut() -> *mut u32 { std::ptr::null_mut() + //~^ ptr_as_ptr } fn core_path_mut() -> *mut u32 { use core::ptr; ptr::null_mut() + //~^ ptr_as_ptr } fn full_core_path_mut() -> *mut u32 { core::ptr::null_mut() + //~^ ptr_as_ptr } fn use_path() -> *const u32 { use std::ptr; ptr::null() + //~^ ptr_as_ptr } fn full_path() -> *const u32 { std::ptr::null() + //~^ ptr_as_ptr } fn core_path() -> *const u32 { use core::ptr; ptr::null() + //~^ ptr_as_ptr } fn full_core_path() -> *const u32 { core::ptr::null() + //~^ ptr_as_ptr } } diff --git a/tests/ui/ptr_as_ptr.rs b/tests/ui/ptr_as_ptr.rs index 7ab52e63da55..224d09b0eb6e 100644 --- a/tests/ui/ptr_as_ptr.rs +++ b/tests/ui/ptr_as_ptr.rs @@ -16,6 +16,7 @@ mod issue_11278_b { pub fn f(o: &mut super::issue_11278_a::T) -> super::issue_11278_a::T { // Retain `super` *unsafe { Box::from_raw(Box::into_raw(Box::new(o)) as *mut super::issue_11278_a::T) } + //~^ ptr_as_ptr } } @@ -25,12 +26,15 @@ fn main() { let mut_ptr: *mut u32 = &mut 42_u32; let _ = ptr as *const i32; + //~^ ptr_as_ptr let _ = mut_ptr as *mut i32; + //~^ ptr_as_ptr // Make sure the lint can handle the difference in their operator precedences. unsafe { let ptr_ptr: *const *const u32 = &ptr; let _ = *ptr_ptr as *const i32; + //~^ ptr_as_ptr } // Changes in mutability. Do not lint this. @@ -44,10 +48,13 @@ fn main() { // Ensure the lint doesn't produce unnecessary turbofish for inferred types. let _: *const i32 = ptr as *const _; + //~^ ptr_as_ptr let _: *mut i32 = mut_ptr as _; + //~^ ptr_as_ptr // Make sure the lint is triggered inside a macro let _ = inline!($ptr as *const i32); + //~^ ptr_as_ptr // Do not lint inside macros from external crates let _ = external!($ptr as *const i32); @@ -69,7 +76,9 @@ fn _msrv_1_38() { let mut_ptr: *mut u32 = &mut 42_u32; let _ = ptr as *const i32; + //~^ ptr_as_ptr let _ = mut_ptr as *mut i32; + //~^ ptr_as_ptr } #[allow(clippy::unnecessary_cast)] @@ -77,37 +86,45 @@ mod null { fn use_path_mut() -> *mut u32 { use std::ptr; ptr::null_mut() as *mut u32 + //~^ ptr_as_ptr } fn full_path_mut() -> *mut u32 { std::ptr::null_mut() as *mut u32 + //~^ ptr_as_ptr } fn core_path_mut() -> *mut u32 { use core::ptr; ptr::null_mut() as *mut u32 + //~^ ptr_as_ptr } fn full_core_path_mut() -> *mut u32 { core::ptr::null_mut() as *mut u32 + //~^ ptr_as_ptr } fn use_path() -> *const u32 { use std::ptr; ptr::null() as *const u32 + //~^ ptr_as_ptr } fn full_path() -> *const u32 { std::ptr::null() as *const u32 + //~^ ptr_as_ptr } fn core_path() -> *const u32 { use core::ptr; ptr::null() as *const u32 + //~^ ptr_as_ptr } fn full_core_path() -> *const u32 { core::ptr::null() as *const u32 + //~^ ptr_as_ptr } } @@ -115,37 +132,45 @@ mod null_ptr_infer { fn use_path_mut() -> *mut u32 { use std::ptr; ptr::null_mut() as *mut _ + //~^ ptr_as_ptr } fn full_path_mut() -> *mut u32 { std::ptr::null_mut() as *mut _ + //~^ ptr_as_ptr } fn core_path_mut() -> *mut u32 { use core::ptr; ptr::null_mut() as *mut _ + //~^ ptr_as_ptr } fn full_core_path_mut() -> *mut u32 { core::ptr::null_mut() as *mut _ + //~^ ptr_as_ptr } fn use_path() -> *const u32 { use std::ptr; ptr::null() as *const _ + //~^ ptr_as_ptr } fn full_path() -> *const u32 { std::ptr::null() as *const _ + //~^ ptr_as_ptr } fn core_path() -> *const u32 { use core::ptr; ptr::null() as *const _ + //~^ ptr_as_ptr } fn full_core_path() -> *const u32 { core::ptr::null() as *const _ + //~^ ptr_as_ptr } } @@ -153,36 +178,44 @@ mod null_entire_infer { fn use_path_mut() -> *mut u32 { use std::ptr; ptr::null_mut() as _ + //~^ ptr_as_ptr } fn full_path_mut() -> *mut u32 { std::ptr::null_mut() as _ + //~^ ptr_as_ptr } fn core_path_mut() -> *mut u32 { use core::ptr; ptr::null_mut() as _ + //~^ ptr_as_ptr } fn full_core_path_mut() -> *mut u32 { core::ptr::null_mut() as _ + //~^ ptr_as_ptr } fn use_path() -> *const u32 { use std::ptr; ptr::null() as _ + //~^ ptr_as_ptr } fn full_path() -> *const u32 { std::ptr::null() as _ + //~^ ptr_as_ptr } fn core_path() -> *const u32 { use core::ptr; ptr::null() as _ + //~^ ptr_as_ptr } fn full_core_path() -> *const u32 { core::ptr::null() as _ + //~^ ptr_as_ptr } } diff --git a/tests/ui/ptr_as_ptr.stderr b/tests/ui/ptr_as_ptr.stderr index 18462620b0a3..66dae8e0135e 100644 --- a/tests/ui/ptr_as_ptr.stderr +++ b/tests/ui/ptr_as_ptr.stderr @@ -8,37 +8,37 @@ LL | *unsafe { Box::from_raw(Box::into_raw(Box::new(o)) as *mut super::i = help: to override `-D warnings` add `#[allow(clippy::ptr_as_ptr)]` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:27:13 + --> tests/ui/ptr_as_ptr.rs:28:13 | LL | let _ = ptr as *const i32; | ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:28:13 + --> tests/ui/ptr_as_ptr.rs:30:13 | LL | let _ = mut_ptr as *mut i32; | ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:33:17 + --> tests/ui/ptr_as_ptr.rs:36:17 | LL | let _ = *ptr_ptr as *const i32; | ^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `(*ptr_ptr).cast::()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:46:25 + --> tests/ui/ptr_as_ptr.rs:50:25 | LL | let _: *const i32 = ptr as *const _; | ^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:47:23 + --> tests/ui/ptr_as_ptr.rs:52:23 | LL | let _: *mut i32 = mut_ptr as _; | ^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:50:21 + --> tests/ui/ptr_as_ptr.rs:56:21 | LL | let _ = inline!($ptr as *const i32); | ^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `$ptr.cast::()` @@ -46,29 +46,17 @@ LL | let _ = inline!($ptr as *const i32); = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info) error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:71:13 + --> tests/ui/ptr_as_ptr.rs:78:13 | LL | let _ = ptr as *const i32; | ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:72:13 + --> tests/ui/ptr_as_ptr.rs:80:13 | LL | let _ = mut_ptr as *mut i32; | ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::()` -error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:79:9 - | -LL | ptr::null_mut() as *mut u32 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut::()` - -error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:83:9 - | -LL | std::ptr::null_mut() as *mut u32 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut::()` - error: `as` casting between raw pointers without changing their constness --> tests/ui/ptr_as_ptr.rs:88:9 | @@ -76,127 +64,139 @@ LL | ptr::null_mut() as *mut u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut::()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:92:9 + --> tests/ui/ptr_as_ptr.rs:93:9 + | +LL | std::ptr::null_mut() as *mut u32 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut::()` + +error: `as` casting between raw pointers without changing their constness + --> tests/ui/ptr_as_ptr.rs:99:9 + | +LL | ptr::null_mut() as *mut u32 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut::()` + +error: `as` casting between raw pointers without changing their constness + --> tests/ui/ptr_as_ptr.rs:104:9 | LL | core::ptr::null_mut() as *mut u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut::()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:97:9 + --> tests/ui/ptr_as_ptr.rs:110:9 | LL | ptr::null() as *const u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null::()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:101:9 + --> tests/ui/ptr_as_ptr.rs:115:9 | LL | std::ptr::null() as *const u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null::()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:106:9 + --> tests/ui/ptr_as_ptr.rs:121:9 | LL | ptr::null() as *const u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null::()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:110:9 + --> tests/ui/ptr_as_ptr.rs:126:9 | LL | core::ptr::null() as *const u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null::()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:117:9 + --> tests/ui/ptr_as_ptr.rs:134:9 | LL | ptr::null_mut() as *mut _ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:121:9 + --> tests/ui/ptr_as_ptr.rs:139:9 | LL | std::ptr::null_mut() as *mut _ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:126:9 + --> tests/ui/ptr_as_ptr.rs:145:9 | LL | ptr::null_mut() as *mut _ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:130:9 + --> tests/ui/ptr_as_ptr.rs:150:9 | LL | core::ptr::null_mut() as *mut _ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:135:9 + --> tests/ui/ptr_as_ptr.rs:156:9 | LL | ptr::null() as *const _ | ^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:139:9 + --> tests/ui/ptr_as_ptr.rs:161:9 | LL | std::ptr::null() as *const _ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:144:9 + --> tests/ui/ptr_as_ptr.rs:167:9 | LL | ptr::null() as *const _ | ^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:148:9 + --> tests/ui/ptr_as_ptr.rs:172:9 | LL | core::ptr::null() as *const _ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:155:9 + --> tests/ui/ptr_as_ptr.rs:180:9 | LL | ptr::null_mut() as _ | ^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:159:9 + --> tests/ui/ptr_as_ptr.rs:185:9 | LL | std::ptr::null_mut() as _ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:164:9 + --> tests/ui/ptr_as_ptr.rs:191:9 | LL | ptr::null_mut() as _ | ^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:168:9 + --> tests/ui/ptr_as_ptr.rs:196:9 | LL | core::ptr::null_mut() as _ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:173:9 + --> tests/ui/ptr_as_ptr.rs:202:9 | LL | ptr::null() as _ | ^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:177:9 + --> tests/ui/ptr_as_ptr.rs:207:9 | LL | std::ptr::null() as _ | ^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:182:9 + --> tests/ui/ptr_as_ptr.rs:213:9 | LL | ptr::null() as _ | ^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:186:9 + --> tests/ui/ptr_as_ptr.rs:218:9 | LL | core::ptr::null() as _ | ^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null()` diff --git a/tests/ui/ptr_cast_constness.fixed b/tests/ui/ptr_cast_constness.fixed index 9a5272c7adc3..6dded72d3e19 100644 --- a/tests/ui/ptr_cast_constness.fixed +++ b/tests/ui/ptr_cast_constness.fixed @@ -13,7 +13,9 @@ use proc_macros::{external, inline_macros}; unsafe fn ptr_to_ref(p: *const T, om: *mut U) { let _: &mut T = std::mem::transmute(p.cast_mut()); + //~^ ptr_cast_constness let _ = &mut *p.cast_mut(); + //~^ ptr_cast_constness let _: &T = &*(om as *const T); } @@ -29,10 +31,13 @@ fn main() { unsafe { let ptr_ptr: *const *const u32 = &ptr; let _ = (*ptr_ptr).cast_mut(); + //~^ ptr_cast_constness } let _ = ptr.cast_mut(); + //~^ ptr_cast_constness let _ = mut_ptr.cast_const(); + //~^ ptr_cast_constness // Lint this, since pointer::cast_mut and pointer::cast_const have ?Sized let ptr_of_array: *const [u32; 4] = &[1, 2, 3, 4]; @@ -66,20 +71,28 @@ fn _msrv_1_65() { let mut_ptr: *mut u32 = &mut 42_u32; let _ = ptr.cast_mut(); + //~^ ptr_cast_constness let _ = mut_ptr.cast_const(); + //~^ ptr_cast_constness } #[inline_macros] fn null_pointers() { use std::ptr; let _ = std::ptr::null_mut::(); + //~^ ptr_cast_constness let _ = std::ptr::null::(); + //~^ ptr_cast_constness let _ = std::ptr::null_mut::(); + //~^ ptr_cast_constness let _ = std::ptr::null::(); + //~^ ptr_cast_constness // Make sure the lint is triggered inside a macro let _ = inline!(std::ptr::null_mut::()); + //~^ ptr_cast_constness let _ = inline!(std::ptr::null_mut::()); + //~^ ptr_cast_constness // Do not lint inside macros from external crates let _ = external!(ptr::null::() as *mut u32); diff --git a/tests/ui/ptr_cast_constness.rs b/tests/ui/ptr_cast_constness.rs index 43ab5f5ba7cc..e9629f5290ec 100644 --- a/tests/ui/ptr_cast_constness.rs +++ b/tests/ui/ptr_cast_constness.rs @@ -13,7 +13,9 @@ use proc_macros::{external, inline_macros}; unsafe fn ptr_to_ref(p: *const T, om: *mut U) { let _: &mut T = std::mem::transmute(p as *mut T); + //~^ ptr_cast_constness let _ = &mut *(p as *mut T); + //~^ ptr_cast_constness let _: &T = &*(om as *const T); } @@ -29,10 +31,13 @@ fn main() { unsafe { let ptr_ptr: *const *const u32 = &ptr; let _ = *ptr_ptr as *mut u32; + //~^ ptr_cast_constness } let _ = ptr as *mut u32; + //~^ ptr_cast_constness let _ = mut_ptr as *const u32; + //~^ ptr_cast_constness // Lint this, since pointer::cast_mut and pointer::cast_const have ?Sized let ptr_of_array: *const [u32; 4] = &[1, 2, 3, 4]; @@ -66,20 +71,28 @@ fn _msrv_1_65() { let mut_ptr: *mut u32 = &mut 42_u32; let _ = ptr as *mut u32; + //~^ ptr_cast_constness let _ = mut_ptr as *const u32; + //~^ ptr_cast_constness } #[inline_macros] fn null_pointers() { use std::ptr; let _ = ptr::null::() as *mut String; + //~^ ptr_cast_constness let _ = ptr::null_mut::() as *const u32; + //~^ ptr_cast_constness let _ = ptr::null::().cast_mut(); + //~^ ptr_cast_constness let _ = ptr::null_mut::().cast_const(); + //~^ ptr_cast_constness // Make sure the lint is triggered inside a macro let _ = inline!(ptr::null::() as *mut u32); + //~^ ptr_cast_constness let _ = inline!(ptr::null::().cast_mut()); + //~^ ptr_cast_constness // Do not lint inside macros from external crates let _ = external!(ptr::null::() as *mut u32); diff --git a/tests/ui/ptr_cast_constness.stderr b/tests/ui/ptr_cast_constness.stderr index a693793a4ae9..1eeeef747013 100644 --- a/tests/ui/ptr_cast_constness.stderr +++ b/tests/ui/ptr_cast_constness.stderr @@ -8,67 +8,67 @@ LL | let _: &mut T = std::mem::transmute(p as *mut T); = help: to override `-D warnings` add `#[allow(clippy::ptr_cast_constness)]` error: `as` casting between raw pointers while changing only its constness - --> tests/ui/ptr_cast_constness.rs:16:19 + --> tests/ui/ptr_cast_constness.rs:17:19 | LL | let _ = &mut *(p as *mut T); | ^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `p.cast_mut()` error: `as` casting between raw pointers while changing only its constness - --> tests/ui/ptr_cast_constness.rs:31:17 + --> tests/ui/ptr_cast_constness.rs:33:17 | LL | let _ = *ptr_ptr as *mut u32; | ^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `(*ptr_ptr).cast_mut()` error: `as` casting between raw pointers while changing only its constness - --> tests/ui/ptr_cast_constness.rs:34:13 + --> tests/ui/ptr_cast_constness.rs:37:13 | LL | let _ = ptr as *mut u32; | ^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `ptr.cast_mut()` error: `as` casting between raw pointers while changing only its constness - --> tests/ui/ptr_cast_constness.rs:35:13 + --> tests/ui/ptr_cast_constness.rs:39:13 | LL | let _ = mut_ptr as *const u32; | ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()` error: `as` casting between raw pointers while changing only its constness - --> tests/ui/ptr_cast_constness.rs:68:13 + --> tests/ui/ptr_cast_constness.rs:73:13 | LL | let _ = ptr as *mut u32; | ^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `ptr.cast_mut()` error: `as` casting between raw pointers while changing only its constness - --> tests/ui/ptr_cast_constness.rs:69:13 + --> tests/ui/ptr_cast_constness.rs:75:13 | LL | let _ = mut_ptr as *const u32; | ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()` error: `as` casting to make a const null pointer into a mutable null pointer - --> tests/ui/ptr_cast_constness.rs:75:13 + --> tests/ui/ptr_cast_constness.rs:82:13 | LL | let _ = ptr::null::() as *mut String; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::()` error: `as` casting to make a mutable null pointer into a const null pointer - --> tests/ui/ptr_cast_constness.rs:76:13 + --> tests/ui/ptr_cast_constness.rs:84:13 | LL | let _ = ptr::null_mut::() as *const u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null()` directly instead: `std::ptr::null::()` error: changing constness of a null pointer - --> tests/ui/ptr_cast_constness.rs:77:13 + --> tests/ui/ptr_cast_constness.rs:86:13 | LL | let _ = ptr::null::().cast_mut(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::()` error: changing constness of a null pointer - --> tests/ui/ptr_cast_constness.rs:78:13 + --> tests/ui/ptr_cast_constness.rs:88:13 | LL | let _ = ptr::null_mut::().cast_const(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null()` directly instead: `std::ptr::null::()` error: `as` casting to make a const null pointer into a mutable null pointer - --> tests/ui/ptr_cast_constness.rs:81:21 + --> tests/ui/ptr_cast_constness.rs:92:21 | LL | let _ = inline!(ptr::null::() as *mut u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::()` @@ -76,7 +76,7 @@ LL | let _ = inline!(ptr::null::() as *mut u32); = note: this error originates in the macro `__inline_mac_fn_null_pointers` (in Nightly builds, run with -Z macro-backtrace for more info) error: changing constness of a null pointer - --> tests/ui/ptr_cast_constness.rs:82:21 + --> tests/ui/ptr_cast_constness.rs:94:21 | LL | let _ = inline!(ptr::null::().cast_mut()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::()` diff --git a/tests/ui/ptr_eq.fixed b/tests/ui/ptr_eq.fixed index 3ae6df18c0a0..1ccd2c2237de 100644 --- a/tests/ui/ptr_eq.fixed +++ b/tests/ui/ptr_eq.fixed @@ -17,7 +17,9 @@ fn main() { let b = &[1, 2, 3]; let _ = std::ptr::eq(a, b); + //~^ ptr_eq let _ = std::ptr::eq(a, b); + //~^ ptr_eq let _ = a.as_ptr() == b as *const _; let _ = a.as_ptr() == b.as_ptr(); diff --git a/tests/ui/ptr_eq.rs b/tests/ui/ptr_eq.rs index 440d5d94a831..0bc58a57fa53 100644 --- a/tests/ui/ptr_eq.rs +++ b/tests/ui/ptr_eq.rs @@ -17,7 +17,9 @@ fn main() { let b = &[1, 2, 3]; let _ = a as *const _ as usize == b as *const _ as usize; + //~^ ptr_eq let _ = a as *const _ == b as *const _; + //~^ ptr_eq let _ = a.as_ptr() == b as *const _; let _ = a.as_ptr() == b.as_ptr(); diff --git a/tests/ui/ptr_eq.stderr b/tests/ui/ptr_eq.stderr index bf8c2b5c08fb..8e8b34f26ff7 100644 --- a/tests/ui/ptr_eq.stderr +++ b/tests/ui/ptr_eq.stderr @@ -8,7 +8,7 @@ LL | let _ = a as *const _ as usize == b as *const _ as usize; = help: to override `-D warnings` add `#[allow(clippy::ptr_eq)]` error: use `std::ptr::eq` when comparing raw pointers - --> tests/ui/ptr_eq.rs:20:13 + --> tests/ui/ptr_eq.rs:21:13 | LL | let _ = a as *const _ == b as *const _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a, b)` diff --git a/tests/ui/ptr_eq_no_std.fixed b/tests/ui/ptr_eq_no_std.fixed index 97c8c394c03d..b3e82fae38f3 100644 --- a/tests/ui/ptr_eq_no_std.fixed +++ b/tests/ui/ptr_eq_no_std.fixed @@ -29,7 +29,9 @@ fn main() { let b = &[1, 2, 3]; let _ = core::ptr::eq(a, b); + //~^ ptr_eq let _ = core::ptr::eq(a, b); + //~^ ptr_eq let _ = a.as_ptr() == b as *const _; let _ = a.as_ptr() == b.as_ptr(); diff --git a/tests/ui/ptr_eq_no_std.rs b/tests/ui/ptr_eq_no_std.rs index a7ba9b4d8174..ba78f5ee5f84 100644 --- a/tests/ui/ptr_eq_no_std.rs +++ b/tests/ui/ptr_eq_no_std.rs @@ -29,7 +29,9 @@ fn main() { let b = &[1, 2, 3]; let _ = a as *const _ as usize == b as *const _ as usize; + //~^ ptr_eq let _ = a as *const _ == b as *const _; + //~^ ptr_eq let _ = a.as_ptr() == b as *const _; let _ = a.as_ptr() == b.as_ptr(); diff --git a/tests/ui/ptr_eq_no_std.stderr b/tests/ui/ptr_eq_no_std.stderr index 0463b75b720b..8c7b1ff76661 100644 --- a/tests/ui/ptr_eq_no_std.stderr +++ b/tests/ui/ptr_eq_no_std.stderr @@ -8,7 +8,7 @@ LL | let _ = a as *const _ as usize == b as *const _ as usize; = help: to override `-D warnings` add `#[allow(clippy::ptr_eq)]` error: use `core::ptr::eq` when comparing raw pointers - --> tests/ui/ptr_eq_no_std.rs:32:13 + --> tests/ui/ptr_eq_no_std.rs:33:13 | LL | let _ = a as *const _ == b as *const _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a, b)` diff --git a/tests/ui/ptr_offset_with_cast.fixed b/tests/ui/ptr_offset_with_cast.fixed index 929512be63d4..4fe9dcf46c35 100644 --- a/tests/ui/ptr_offset_with_cast.fixed +++ b/tests/ui/ptr_offset_with_cast.fixed @@ -10,10 +10,12 @@ fn main() { unsafe { let _ = ptr.add(offset_usize); + //~^ ptr_offset_with_cast let _ = ptr.offset(offset_isize as isize); let _ = ptr.offset(offset_u8 as isize); let _ = ptr.wrapping_add(offset_usize); + //~^ ptr_offset_with_cast let _ = ptr.wrapping_offset(offset_isize as isize); let _ = ptr.wrapping_offset(offset_u8 as isize); } diff --git a/tests/ui/ptr_offset_with_cast.rs b/tests/ui/ptr_offset_with_cast.rs index 146bc27765ad..a1fb892733d3 100644 --- a/tests/ui/ptr_offset_with_cast.rs +++ b/tests/ui/ptr_offset_with_cast.rs @@ -10,10 +10,12 @@ fn main() { unsafe { let _ = ptr.offset(offset_usize as isize); + //~^ ptr_offset_with_cast let _ = ptr.offset(offset_isize as isize); let _ = ptr.offset(offset_u8 as isize); let _ = ptr.wrapping_offset(offset_usize as isize); + //~^ ptr_offset_with_cast let _ = ptr.wrapping_offset(offset_isize as isize); let _ = ptr.wrapping_offset(offset_u8 as isize); } diff --git a/tests/ui/ptr_offset_with_cast.stderr b/tests/ui/ptr_offset_with_cast.stderr index 87ff10adc946..dcd5e027d182 100644 --- a/tests/ui/ptr_offset_with_cast.stderr +++ b/tests/ui/ptr_offset_with_cast.stderr @@ -8,7 +8,7 @@ LL | let _ = ptr.offset(offset_usize as isize); = help: to override `-D warnings` add `#[allow(clippy::ptr_offset_with_cast)]` error: use of `wrapping_offset` with a `usize` casted to an `isize` - --> tests/ui/ptr_offset_with_cast.rs:16:17 + --> tests/ui/ptr_offset_with_cast.rs:17:17 | LL | let _ = ptr.wrapping_offset(offset_usize as isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr.wrapping_add(offset_usize)` diff --git a/tests/ui/pub_use.rs b/tests/ui/pub_use.rs index aef947e406a6..be4d1b2a964b 100644 --- a/tests/ui/pub_use.rs +++ b/tests/ui/pub_use.rs @@ -8,7 +8,7 @@ pub mod outer { } // should be linted pub use inner::Test; - //~^ ERROR: using `pub use` + //~^ pub_use } // should not be linted diff --git a/tests/ui/pub_with_shorthand.fixed b/tests/ui/pub_with_shorthand.fixed index 028209de0666..4036de8bbc0a 100644 --- a/tests/ui/pub_with_shorthand.fixed +++ b/tests/ui/pub_with_shorthand.fixed @@ -11,14 +11,18 @@ extern crate proc_macros; pub(in self) fn a() {} +//~^ pub_with_shorthand pub(in self) fn b() {} pub fn c() {} mod a { pub(in super) fn d() {} pub(in super) fn e() {} + //~^ pub_with_shorthand pub(in self) fn f() {} + //~^ pub_with_shorthand pub(in crate) fn k() {} + //~^ pub_with_shorthand pub(in crate) fn m() {} mod b { pub(in crate::a) fn l() {} diff --git a/tests/ui/pub_with_shorthand.rs b/tests/ui/pub_with_shorthand.rs index 8578e3e0c434..fac4ba990447 100644 --- a/tests/ui/pub_with_shorthand.rs +++ b/tests/ui/pub_with_shorthand.rs @@ -11,14 +11,18 @@ extern crate proc_macros; pub(self) fn a() {} +//~^ pub_with_shorthand pub(in self) fn b() {} pub fn c() {} mod a { pub(in super) fn d() {} pub(super) fn e() {} + //~^ pub_with_shorthand pub(self) fn f() {} + //~^ pub_with_shorthand pub(crate) fn k() {} + //~^ pub_with_shorthand pub(in crate) fn m() {} mod b { pub(in crate::a) fn l() {} diff --git a/tests/ui/pub_with_shorthand.stderr b/tests/ui/pub_with_shorthand.stderr index 8978244c4c04..00a3fc28ecb6 100644 --- a/tests/ui/pub_with_shorthand.stderr +++ b/tests/ui/pub_with_shorthand.stderr @@ -8,19 +8,19 @@ LL | pub(self) fn a() {} = help: to override `-D warnings` add `#[allow(clippy::pub_with_shorthand)]` error: usage of `pub` without `in` - --> tests/ui/pub_with_shorthand.rs:19:5 + --> tests/ui/pub_with_shorthand.rs:20:5 | LL | pub(super) fn e() {} | ^^^^^^^^^^ help: add it: `pub(in super)` error: usage of `pub` without `in` - --> tests/ui/pub_with_shorthand.rs:20:5 + --> tests/ui/pub_with_shorthand.rs:22:5 | LL | pub(self) fn f() {} | ^^^^^^^^^ help: add it: `pub(in self)` error: usage of `pub` without `in` - --> tests/ui/pub_with_shorthand.rs:21:5 + --> tests/ui/pub_with_shorthand.rs:24:5 | LL | pub(crate) fn k() {} | ^^^^^^^^^^ help: add it: `pub(in crate)` diff --git a/tests/ui/pub_without_shorthand.fixed b/tests/ui/pub_without_shorthand.fixed index 715e86c17645..fbe3326400cb 100644 --- a/tests/ui/pub_without_shorthand.fixed +++ b/tests/ui/pub_without_shorthand.fixed @@ -12,14 +12,17 @@ extern crate proc_macros; pub(self) fn a() {} pub(self) fn b() {} +//~^ pub_without_shorthand pub fn c() {} mod a { pub(super) fn d() {} + //~^ pub_without_shorthand pub(super) fn e() {} pub(self) fn f() {} pub(crate) fn k() {} pub(crate) fn m() {} + //~^ pub_without_shorthand mod b { pub(in crate::a) fn l() {} } diff --git a/tests/ui/pub_without_shorthand.rs b/tests/ui/pub_without_shorthand.rs index ed2fd6f0f617..fb756096c9d9 100644 --- a/tests/ui/pub_without_shorthand.rs +++ b/tests/ui/pub_without_shorthand.rs @@ -12,14 +12,17 @@ extern crate proc_macros; pub(self) fn a() {} pub(in self) fn b() {} +//~^ pub_without_shorthand pub fn c() {} mod a { pub(in super) fn d() {} + //~^ pub_without_shorthand pub(super) fn e() {} pub(self) fn f() {} pub(crate) fn k() {} pub(in crate) fn m() {} + //~^ pub_without_shorthand mod b { pub(in crate::a) fn l() {} } diff --git a/tests/ui/pub_without_shorthand.stderr b/tests/ui/pub_without_shorthand.stderr index e37c731732ba..c823af6432de 100644 --- a/tests/ui/pub_without_shorthand.stderr +++ b/tests/ui/pub_without_shorthand.stderr @@ -8,13 +8,13 @@ LL | pub(in self) fn b() {} = help: to override `-D warnings` add `#[allow(clippy::pub_without_shorthand)]` error: usage of `pub` with `in` - --> tests/ui/pub_without_shorthand.rs:18:5 + --> tests/ui/pub_without_shorthand.rs:19:5 | LL | pub(in super) fn d() {} | ^^^^^^^^^^^^^ help: remove it: `pub(super)` error: usage of `pub` with `in` - --> tests/ui/pub_without_shorthand.rs:22:5 + --> tests/ui/pub_without_shorthand.rs:24:5 | LL | pub(in crate) fn m() {} | ^^^^^^^^^^^^^ help: remove it: `pub(crate)` diff --git a/tests/ui/question_mark.fixed b/tests/ui/question_mark.fixed index b6e148e9f772..8dfef3202be9 100644 --- a/tests/ui/question_mark.fixed +++ b/tests/ui/question_mark.fixed @@ -141,6 +141,7 @@ fn func_returning_result() -> Result { fn result_func(x: Result) -> Result { let _ = x?; + //~^ question_mark x?; @@ -371,5 +372,6 @@ fn issue12412(foo: &Foo, bar: &Bar) -> Option<()> { }; // lint let v = bar.foo.owned.clone()?; + //~^^^ question_mark Some(()) } diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs index 48dc9eb0a626..fffaa803f39c 100644 --- a/tests/ui/question_mark.rs +++ b/tests/ui/question_mark.rs @@ -5,6 +5,7 @@ fn some_func(a: Option) -> Option { if a.is_none() { + //~^ question_mark return None; } @@ -50,20 +51,24 @@ impl CopyStruct { #[rustfmt::skip] pub fn func(&self) -> Option { if (self.opt).is_none() { + //~^ question_mark return None; } if self.opt.is_none() { + //~^ question_mark return None } let _ = if self.opt.is_none() { + //~^ question_mark return None; } else { self.opt }; let _ = if let Some(x) = self.opt { + //~^ question_mark x } else { return None; @@ -81,6 +86,7 @@ pub struct MoveStruct { impl MoveStruct { pub fn ref_func(&self) -> Option> { if self.opt.is_none() { + //~^ question_mark return None; } @@ -89,6 +95,7 @@ impl MoveStruct { pub fn mov_func_reuse(self) -> Option> { if self.opt.is_none() { + //~^ question_mark return None; } @@ -97,6 +104,7 @@ impl MoveStruct { pub fn mov_func_no_use(self) -> Option> { if self.opt.is_none() { + //~^ question_mark return None; } Some(Vec::new()) @@ -104,6 +112,7 @@ impl MoveStruct { pub fn if_let_ref_func(self) -> Option> { let v: &Vec<_> = if let Some(ref v) = self.opt { + //~^ question_mark v } else { return None; @@ -114,6 +123,7 @@ impl MoveStruct { pub fn if_let_mov_func(self) -> Option> { let v = if let Some(v) = self.opt { + //~^ question_mark v } else { return None; @@ -135,10 +145,12 @@ fn func() -> Option { } if f().is_none() { + //~^ question_mark return None; } let _val = match f() { + //~^ question_mark Some(val) => val, None => return None, }; @@ -149,11 +161,13 @@ fn func() -> Option { }; match f() { + //~^ question_mark Some(val) => val, None => return None, }; match opt_none!() { + //~^ question_mark Some(x) => x, None => return None, }; @@ -180,17 +194,21 @@ fn func_returning_result() -> Result { fn result_func(x: Result) -> Result { let _ = if let Ok(x) = x { x } else { return x }; + //~^ question_mark if x.is_err() { + //~^ question_mark return x; } let _val = match func_returning_result() { + //~^ question_mark Ok(val) => val, Err(err) => return Err(err), }; match func_returning_result() { + //~^ question_mark Ok(val) => val, Err(err) => return Err(err), }; @@ -282,6 +300,7 @@ fn do_something() {} fn err_immediate_return() -> Result { if let Err(err) = func_returning_result() { + //~^ question_mark return Err(err); } Ok(1) @@ -289,6 +308,7 @@ fn err_immediate_return() -> Result { fn err_immediate_return_and_do_something() -> Result { if let Err(err) = func_returning_result() { + //~^ question_mark return Err(err); } do_something(); @@ -366,6 +386,7 @@ fn issue6828_nested_body() -> Option { try { fn f2(a: Option) -> Option { if a.is_none() { + //~^ question_mark return None; // do lint here, the outer `try` is not relevant here // https://github.com/rust-lang/rust-clippy/pull/11001#issuecomment-1610636867 @@ -428,5 +449,6 @@ fn issue12412(foo: &Foo, bar: &Bar) -> Option<()> { let Some(v) = bar.foo.owned.clone() else { return None; }; + //~^^^ question_mark Some(()) } diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr index 06a8bd0de349..c4db0fbc3022 100644 --- a/tests/ui/question_mark.stderr +++ b/tests/ui/question_mark.stderr @@ -2,6 +2,7 @@ error: this block may be rewritten with the `?` operator --> tests/ui/question_mark.rs:7:5 | LL | / if a.is_none() { +LL | | LL | | return None; LL | | } | |_____^ help: replace it with: `a?;` @@ -10,26 +11,29 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::question_mark)]` error: this block may be rewritten with the `?` operator - --> tests/ui/question_mark.rs:52:9 + --> tests/ui/question_mark.rs:53:9 | LL | / if (self.opt).is_none() { +LL | | LL | | return None; LL | | } | |_________^ help: replace it with: `(self.opt)?;` error: this block may be rewritten with the `?` operator - --> tests/ui/question_mark.rs:56:9 + --> tests/ui/question_mark.rs:58:9 | LL | / if self.opt.is_none() { +LL | | LL | | return None LL | | } | |_________^ help: replace it with: `self.opt?;` error: this block may be rewritten with the `?` operator - --> tests/ui/question_mark.rs:60:17 + --> tests/ui/question_mark.rs:63:17 | LL | let _ = if self.opt.is_none() { | _________________^ +LL | | LL | | return None; LL | | } else { LL | | self.opt @@ -37,10 +41,11 @@ LL | | }; | |_________^ help: replace it with: `Some(self.opt?)` error: this block may be rewritten with the `?` operator - --> tests/ui/question_mark.rs:66:17 + --> tests/ui/question_mark.rs:70:17 | LL | let _ = if let Some(x) = self.opt { | _________________^ +LL | | LL | | x LL | | } else { LL | | return None; @@ -48,34 +53,38 @@ LL | | }; | |_________^ help: replace it with: `self.opt?` error: this block may be rewritten with the `?` operator - --> tests/ui/question_mark.rs:83:9 + --> tests/ui/question_mark.rs:88:9 | LL | / if self.opt.is_none() { +LL | | LL | | return None; LL | | } | |_________^ help: replace it with: `self.opt.as_ref()?;` error: this block may be rewritten with the `?` operator - --> tests/ui/question_mark.rs:91:9 + --> tests/ui/question_mark.rs:97:9 | LL | / if self.opt.is_none() { +LL | | LL | | return None; LL | | } | |_________^ help: replace it with: `self.opt.as_ref()?;` error: this block may be rewritten with the `?` operator - --> tests/ui/question_mark.rs:99:9 + --> tests/ui/question_mark.rs:106:9 | LL | / if self.opt.is_none() { +LL | | LL | | return None; LL | | } | |_________^ help: replace it with: `self.opt.as_ref()?;` error: this block may be rewritten with the `?` operator - --> tests/ui/question_mark.rs:106:26 + --> tests/ui/question_mark.rs:114:26 | LL | let v: &Vec<_> = if let Some(ref v) = self.opt { | __________________________^ +LL | | LL | | v LL | | } else { LL | | return None; @@ -83,10 +92,11 @@ LL | | }; | |_________^ help: replace it with: `self.opt.as_ref()?` error: this block may be rewritten with the `?` operator - --> tests/ui/question_mark.rs:116:17 + --> tests/ui/question_mark.rs:125:17 | LL | let v = if let Some(v) = self.opt { | _________________^ +LL | | LL | | v LL | | } else { LL | | return None; @@ -94,101 +104,111 @@ LL | | }; | |_________^ help: replace it with: `self.opt?` error: this block may be rewritten with the `?` operator - --> tests/ui/question_mark.rs:137:5 + --> tests/ui/question_mark.rs:147:5 | LL | / if f().is_none() { +LL | | LL | | return None; LL | | } | |_____^ help: replace it with: `f()?;` error: this `match` expression can be replaced with `?` - --> tests/ui/question_mark.rs:141:16 + --> tests/ui/question_mark.rs:152:16 | LL | let _val = match f() { | ________________^ +LL | | LL | | Some(val) => val, LL | | None => return None, LL | | }; | |_____^ help: try instead: `f()?` error: this `match` expression can be replaced with `?` - --> tests/ui/question_mark.rs:151:5 + --> tests/ui/question_mark.rs:163:5 | LL | / match f() { +LL | | LL | | Some(val) => val, LL | | None => return None, LL | | }; | |_____^ help: try instead: `f()?` error: this `match` expression can be replaced with `?` - --> tests/ui/question_mark.rs:156:5 + --> tests/ui/question_mark.rs:169:5 | LL | / match opt_none!() { +LL | | LL | | Some(x) => x, LL | | None => return None, LL | | }; | |_____^ help: try instead: `opt_none!()?` error: this block may be rewritten with the `?` operator - --> tests/ui/question_mark.rs:182:13 + --> tests/ui/question_mark.rs:196:13 | LL | let _ = if let Ok(x) = x { x } else { return x }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x?` error: this block may be rewritten with the `?` operator - --> tests/ui/question_mark.rs:184:5 + --> tests/ui/question_mark.rs:199:5 | LL | / if x.is_err() { +LL | | LL | | return x; LL | | } | |_____^ help: replace it with: `x?;` error: this `match` expression can be replaced with `?` - --> tests/ui/question_mark.rs:188:16 + --> tests/ui/question_mark.rs:204:16 | LL | let _val = match func_returning_result() { | ________________^ +LL | | LL | | Ok(val) => val, LL | | Err(err) => return Err(err), LL | | }; | |_____^ help: try instead: `func_returning_result()?` error: this `match` expression can be replaced with `?` - --> tests/ui/question_mark.rs:193:5 + --> tests/ui/question_mark.rs:210:5 | LL | / match func_returning_result() { +LL | | LL | | Ok(val) => val, LL | | Err(err) => return Err(err), LL | | }; | |_____^ help: try instead: `func_returning_result()?` error: this block may be rewritten with the `?` operator - --> tests/ui/question_mark.rs:284:5 + --> tests/ui/question_mark.rs:302:5 | LL | / if let Err(err) = func_returning_result() { +LL | | LL | | return Err(err); LL | | } | |_____^ help: replace it with: `func_returning_result()?;` error: this block may be rewritten with the `?` operator - --> tests/ui/question_mark.rs:291:5 + --> tests/ui/question_mark.rs:310:5 | LL | / if let Err(err) = func_returning_result() { +LL | | LL | | return Err(err); LL | | } | |_____^ help: replace it with: `func_returning_result()?;` error: this block may be rewritten with the `?` operator - --> tests/ui/question_mark.rs:368:13 + --> tests/ui/question_mark.rs:388:13 | LL | / if a.is_none() { +LL | | LL | | return None; ... | LL | | } | |_____________^ help: replace it with: `a?;` error: this `let...else` may be rewritten with the `?` operator - --> tests/ui/question_mark.rs:428:5 + --> tests/ui/question_mark.rs:449:5 | LL | / let Some(v) = bar.foo.owned.clone() else { LL | | return None; diff --git a/tests/ui/question_mark_used.rs b/tests/ui/question_mark_used.rs index 715d7fab8eed..9e204d1e9f3c 100644 --- a/tests/ui/question_mark_used.rs +++ b/tests/ui/question_mark_used.rs @@ -9,7 +9,8 @@ fn other_function() -> Option { fn my_function() -> Option { other_function()?; - //~^ ERROR: question mark operator was used + //~^ question_mark_used + None } diff --git a/tests/ui/range.fixed b/tests/ui/range.fixed new file mode 100644 index 000000000000..0e951d88091b --- /dev/null +++ b/tests/ui/range.fixed @@ -0,0 +1,19 @@ +#![allow(clippy::useless_vec)] +#[warn(clippy::range_zip_with_len)] +fn main() { + let v1 = vec![1, 2, 3]; + let v2 = vec![4, 5]; + let _x = v1.iter().enumerate(); + //~^ range_zip_with_len + + let _y = v1.iter().zip(0..v2.len()); // No error +} + +#[allow(unused)] +fn no_panic_with_fake_range_types() { + struct Range { + foo: i32, + } + + let _ = Range { foo: 0 }; +} diff --git a/tests/ui/range.rs b/tests/ui/range.rs index 9541812b0691..534380164743 100644 --- a/tests/ui/range.rs +++ b/tests/ui/range.rs @@ -4,8 +4,8 @@ fn main() { let v1 = vec![1, 2, 3]; let v2 = vec![4, 5]; let _x = v1.iter().zip(0..v1.len()); - //~^ ERROR: it is more idiomatic to use `v1.iter().enumerate()` - //~| NOTE: `-D clippy::range-zip-with-len` implied by `-D warnings` + //~^ range_zip_with_len + let _y = v1.iter().zip(0..v2.len()); // No error } diff --git a/tests/ui/range.stderr b/tests/ui/range.stderr index 8c71a209700e..798ce1842d8b 100644 --- a/tests/ui/range.stderr +++ b/tests/ui/range.stderr @@ -1,8 +1,8 @@ -error: it is more idiomatic to use `v1.iter().enumerate()` +error: using `.zip()` with a range and `.len()` --> tests/ui/range.rs:6:14 | LL | let _x = v1.iter().zip(0..v1.len()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `v1.iter().enumerate()` | = note: `-D clippy::range-zip-with-len` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::range_zip_with_len)]` diff --git a/tests/ui/range_contains.fixed b/tests/ui/range_contains.fixed index ed248df374d1..19d6165e9820 100644 --- a/tests/ui/range_contains.fixed +++ b/tests/ui/range_contains.fixed @@ -11,23 +11,35 @@ fn main() { // order shouldn't matter (8..12).contains(&x); + //~^ manual_range_contains (21..42).contains(&x); + //~^ manual_range_contains (1..100).contains(&x); + //~^ manual_range_contains // also with inclusive ranges (9..=99).contains(&x); + //~^ manual_range_contains (1..=33).contains(&x); + //~^ manual_range_contains (1..=999).contains(&x); + //~^ manual_range_contains // and the outside !(8..12).contains(&x); + //~^ manual_range_contains !(21..42).contains(&x); + //~^ manual_range_contains !(1..100).contains(&x); + //~^ manual_range_contains // also with the outside of inclusive ranges !(9..=99).contains(&x); + //~^ manual_range_contains !(1..=33).contains(&x); + //~^ manual_range_contains !(1..=999).contains(&x); + //~^ manual_range_contains // not a range.contains x > 8 && x < 12; // lower bound not inclusive @@ -43,18 +55,26 @@ fn main() { // Fix #6315 let y = 3.; (0. ..1.).contains(&y); + //~^ manual_range_contains !(0. ..=1.).contains(&y); + //~^ manual_range_contains // handle negatives #8721 (-10..=10).contains(&x); + //~^ manual_range_contains x >= 10 && x <= -10; (-3. ..=3.).contains(&y); + //~^ manual_range_contains y >= 3. && y <= -3.; // Fix #8745 let z = 42; (0..=10).contains(&x) && (0..=10).contains(&z); + //~^ manual_range_contains + //~| manual_range_contains !(0..10).contains(&x) || !(0..10).contains(&z); + //~^ manual_range_contains + //~| manual_range_contains // Make sure operators in parens don't give a breaking suggestion ((x % 2 == 0) || (x < 0)) || (x >= 10); } @@ -74,4 +94,5 @@ fn msrv_1_34() { fn msrv_1_35() { let x = 5; (8..35).contains(&x); + //~^ manual_range_contains } diff --git a/tests/ui/range_contains.rs b/tests/ui/range_contains.rs index c3188ec6d92b..80bf40806697 100644 --- a/tests/ui/range_contains.rs +++ b/tests/ui/range_contains.rs @@ -11,23 +11,35 @@ fn main() { // order shouldn't matter x >= 8 && x < 12; + //~^ manual_range_contains x < 42 && x >= 21; + //~^ manual_range_contains 100 > x && 1 <= x; + //~^ manual_range_contains // also with inclusive ranges x >= 9 && x <= 99; + //~^ manual_range_contains x <= 33 && x >= 1; + //~^ manual_range_contains 999 >= x && 1 <= x; + //~^ manual_range_contains // and the outside x < 8 || x >= 12; + //~^ manual_range_contains x >= 42 || x < 21; + //~^ manual_range_contains 100 <= x || 1 > x; + //~^ manual_range_contains // also with the outside of inclusive ranges x < 9 || x > 99; + //~^ manual_range_contains x > 33 || x < 1; + //~^ manual_range_contains 999 < x || 1 > x; + //~^ manual_range_contains // not a range.contains x > 8 && x < 12; // lower bound not inclusive @@ -43,18 +55,26 @@ fn main() { // Fix #6315 let y = 3.; y >= 0. && y < 1.; + //~^ manual_range_contains y < 0. || y > 1.; + //~^ manual_range_contains // handle negatives #8721 x >= -10 && x <= 10; + //~^ manual_range_contains x >= 10 && x <= -10; y >= -3. && y <= 3.; + //~^ manual_range_contains y >= 3. && y <= -3.; // Fix #8745 let z = 42; (x >= 0) && (x <= 10) && (z >= 0) && (z <= 10); + //~^ manual_range_contains + //~| manual_range_contains (x < 0) || (x >= 10) || (z < 0) || (z >= 10); + //~^ manual_range_contains + //~| manual_range_contains // Make sure operators in parens don't give a breaking suggestion ((x % 2 == 0) || (x < 0)) || (x >= 10); } @@ -74,4 +94,5 @@ fn msrv_1_34() { fn msrv_1_35() { let x = 5; x >= 8 && x < 35; + //~^ manual_range_contains } diff --git a/tests/ui/range_contains.stderr b/tests/ui/range_contains.stderr index 58ed1292ac7c..67bd5aad093d 100644 --- a/tests/ui/range_contains.stderr +++ b/tests/ui/range_contains.stderr @@ -8,121 +8,121 @@ LL | x >= 8 && x < 12; = help: to override `-D warnings` add `#[allow(clippy::manual_range_contains)]` error: manual `Range::contains` implementation - --> tests/ui/range_contains.rs:14:5 + --> tests/ui/range_contains.rs:15:5 | LL | x < 42 && x >= 21; | ^^^^^^^^^^^^^^^^^ help: use: `(21..42).contains(&x)` error: manual `Range::contains` implementation - --> tests/ui/range_contains.rs:15:5 + --> tests/ui/range_contains.rs:17:5 | LL | 100 > x && 1 <= x; | ^^^^^^^^^^^^^^^^^ help: use: `(1..100).contains(&x)` error: manual `RangeInclusive::contains` implementation - --> tests/ui/range_contains.rs:18:5 + --> tests/ui/range_contains.rs:21:5 | LL | x >= 9 && x <= 99; | ^^^^^^^^^^^^^^^^^ help: use: `(9..=99).contains(&x)` error: manual `RangeInclusive::contains` implementation - --> tests/ui/range_contains.rs:19:5 + --> tests/ui/range_contains.rs:23:5 | LL | x <= 33 && x >= 1; | ^^^^^^^^^^^^^^^^^ help: use: `(1..=33).contains(&x)` error: manual `RangeInclusive::contains` implementation - --> tests/ui/range_contains.rs:20:5 + --> tests/ui/range_contains.rs:25:5 | LL | 999 >= x && 1 <= x; | ^^^^^^^^^^^^^^^^^^ help: use: `(1..=999).contains(&x)` error: manual `!Range::contains` implementation - --> tests/ui/range_contains.rs:23:5 + --> tests/ui/range_contains.rs:29:5 | LL | x < 8 || x >= 12; | ^^^^^^^^^^^^^^^^ help: use: `!(8..12).contains(&x)` error: manual `!Range::contains` implementation - --> tests/ui/range_contains.rs:24:5 + --> tests/ui/range_contains.rs:31:5 | LL | x >= 42 || x < 21; | ^^^^^^^^^^^^^^^^^ help: use: `!(21..42).contains(&x)` error: manual `!Range::contains` implementation - --> tests/ui/range_contains.rs:25:5 + --> tests/ui/range_contains.rs:33:5 | LL | 100 <= x || 1 > x; | ^^^^^^^^^^^^^^^^^ help: use: `!(1..100).contains(&x)` error: manual `!RangeInclusive::contains` implementation - --> tests/ui/range_contains.rs:28:5 + --> tests/ui/range_contains.rs:37:5 | LL | x < 9 || x > 99; | ^^^^^^^^^^^^^^^ help: use: `!(9..=99).contains(&x)` error: manual `!RangeInclusive::contains` implementation - --> tests/ui/range_contains.rs:29:5 + --> tests/ui/range_contains.rs:39:5 | LL | x > 33 || x < 1; | ^^^^^^^^^^^^^^^ help: use: `!(1..=33).contains(&x)` error: manual `!RangeInclusive::contains` implementation - --> tests/ui/range_contains.rs:30:5 + --> tests/ui/range_contains.rs:41:5 | LL | 999 < x || 1 > x; | ^^^^^^^^^^^^^^^^ help: use: `!(1..=999).contains(&x)` error: manual `Range::contains` implementation - --> tests/ui/range_contains.rs:45:5 + --> tests/ui/range_contains.rs:57:5 | LL | y >= 0. && y < 1.; | ^^^^^^^^^^^^^^^^^ help: use: `(0. ..1.).contains(&y)` error: manual `!RangeInclusive::contains` implementation - --> tests/ui/range_contains.rs:46:5 + --> tests/ui/range_contains.rs:59:5 | LL | y < 0. || y > 1.; | ^^^^^^^^^^^^^^^^ help: use: `!(0. ..=1.).contains(&y)` error: manual `RangeInclusive::contains` implementation - --> tests/ui/range_contains.rs:49:5 + --> tests/ui/range_contains.rs:63:5 | LL | x >= -10 && x <= 10; | ^^^^^^^^^^^^^^^^^^^ help: use: `(-10..=10).contains(&x)` error: manual `RangeInclusive::contains` implementation - --> tests/ui/range_contains.rs:51:5 + --> tests/ui/range_contains.rs:66:5 | LL | y >= -3. && y <= 3.; | ^^^^^^^^^^^^^^^^^^^ help: use: `(-3. ..=3.).contains(&y)` error: manual `RangeInclusive::contains` implementation - --> tests/ui/range_contains.rs:56:30 + --> tests/ui/range_contains.rs:72:30 | LL | (x >= 0) && (x <= 10) && (z >= 0) && (z <= 10); | ^^^^^^^^^^^^^^^^^^^^^ help: use: `(0..=10).contains(&z)` error: manual `RangeInclusive::contains` implementation - --> tests/ui/range_contains.rs:56:5 + --> tests/ui/range_contains.rs:72:5 | LL | (x >= 0) && (x <= 10) && (z >= 0) && (z <= 10); | ^^^^^^^^^^^^^^^^^^^^^ help: use: `(0..=10).contains(&x)` error: manual `!Range::contains` implementation - --> tests/ui/range_contains.rs:57:29 + --> tests/ui/range_contains.rs:75:29 | LL | (x < 0) || (x >= 10) || (z < 0) || (z >= 10); | ^^^^^^^^^^^^^^^^^^^^ help: use: `!(0..10).contains(&z)` error: manual `!Range::contains` implementation - --> tests/ui/range_contains.rs:57:5 + --> tests/ui/range_contains.rs:75:5 | LL | (x < 0) || (x >= 10) || (z < 0) || (z >= 10); | ^^^^^^^^^^^^^^^^^^^^ help: use: `!(0..10).contains(&x)` error: manual `Range::contains` implementation - --> tests/ui/range_contains.rs:76:5 + --> tests/ui/range_contains.rs:96:5 | LL | x >= 8 && x < 35; | ^^^^^^^^^^^^^^^^ help: use: `(8..35).contains(&x)` diff --git a/tests/ui/range_plus_minus_one.fixed b/tests/ui/range_plus_minus_one.fixed index e701dde86933..ee716ef3a6a0 100644 --- a/tests/ui/range_plus_minus_one.fixed +++ b/tests/ui/range_plus_minus_one.fixed @@ -27,29 +27,38 @@ fn main() { for _ in 0..=2 {} for _ in 0..=3 {} + //~^ range_plus_one for _ in 0..=3 + 1 {} for _ in 0..=5 {} + //~^ range_plus_one for _ in 0..=1 + 5 {} for _ in 1..=1 {} + //~^ range_plus_one for _ in 1..=1 + 1 {} for _ in 0..13 + 13 {} for _ in 0..=13 - 7 {} for _ in 0..=f() {} + //~^ range_plus_one for _ in 0..=(1 + f()) {} let _ = ..11 - 1; let _ = ..11; + //~^ range_minus_one let _ = ..11; + //~^ range_minus_one let _ = (1..=11); + //~^ range_plus_one let _ = ((f() + 1)..=f()); + //~^ range_plus_one const ONE: usize = 1; // integer consts are linted, too for _ in 1..=ONE {} + //~^ range_plus_one let mut vec: Vec<()> = std::vec::Vec::new(); vec.drain(..); diff --git a/tests/ui/range_plus_minus_one.rs b/tests/ui/range_plus_minus_one.rs index 7057fa8e3f0d..f2d5ae2c1506 100644 --- a/tests/ui/range_plus_minus_one.rs +++ b/tests/ui/range_plus_minus_one.rs @@ -27,29 +27,38 @@ fn main() { for _ in 0..=2 {} for _ in 0..3 + 1 {} + //~^ range_plus_one for _ in 0..=3 + 1 {} for _ in 0..1 + 5 {} + //~^ range_plus_one for _ in 0..=1 + 5 {} for _ in 1..1 + 1 {} + //~^ range_plus_one for _ in 1..=1 + 1 {} for _ in 0..13 + 13 {} for _ in 0..=13 - 7 {} for _ in 0..(1 + f()) {} + //~^ range_plus_one for _ in 0..=(1 + f()) {} let _ = ..11 - 1; let _ = ..=11 - 1; + //~^ range_minus_one let _ = ..=(11 - 1); + //~^ range_minus_one let _ = (1..11 + 1); + //~^ range_plus_one let _ = (f() + 1)..(f() + 1); + //~^ range_plus_one const ONE: usize = 1; // integer consts are linted, too for _ in 1..ONE + ONE {} + //~^ range_plus_one let mut vec: Vec<()> = std::vec::Vec::new(); vec.drain(..); diff --git a/tests/ui/range_plus_minus_one.stderr b/tests/ui/range_plus_minus_one.stderr index 0b1883bc5ff2..9b23a8b8c0b4 100644 --- a/tests/ui/range_plus_minus_one.stderr +++ b/tests/ui/range_plus_minus_one.stderr @@ -8,25 +8,25 @@ LL | for _ in 0..3 + 1 {} = help: to override `-D warnings` add `#[allow(clippy::range_plus_one)]` error: an inclusive range would be more readable - --> tests/ui/range_plus_minus_one.rs:32:14 + --> tests/ui/range_plus_minus_one.rs:33:14 | LL | for _ in 0..1 + 5 {} | ^^^^^^^^ help: use: `0..=5` error: an inclusive range would be more readable - --> tests/ui/range_plus_minus_one.rs:35:14 + --> tests/ui/range_plus_minus_one.rs:37:14 | LL | for _ in 1..1 + 1 {} | ^^^^^^^^ help: use: `1..=1` error: an inclusive range would be more readable - --> tests/ui/range_plus_minus_one.rs:41:14 + --> tests/ui/range_plus_minus_one.rs:44:14 | LL | for _ in 0..(1 + f()) {} | ^^^^^^^^^^^^ help: use: `0..=f()` error: an exclusive range would be more readable - --> tests/ui/range_plus_minus_one.rs:45:13 + --> tests/ui/range_plus_minus_one.rs:49:13 | LL | let _ = ..=11 - 1; | ^^^^^^^^^ help: use: `..11` @@ -35,25 +35,25 @@ LL | let _ = ..=11 - 1; = help: to override `-D warnings` add `#[allow(clippy::range_minus_one)]` error: an exclusive range would be more readable - --> tests/ui/range_plus_minus_one.rs:46:13 + --> tests/ui/range_plus_minus_one.rs:51:13 | LL | let _ = ..=(11 - 1); | ^^^^^^^^^^^ help: use: `..11` error: an inclusive range would be more readable - --> tests/ui/range_plus_minus_one.rs:47:13 + --> tests/ui/range_plus_minus_one.rs:53:13 | LL | let _ = (1..11 + 1); | ^^^^^^^^^^^ help: use: `(1..=11)` error: an inclusive range would be more readable - --> tests/ui/range_plus_minus_one.rs:48:13 + --> tests/ui/range_plus_minus_one.rs:55:13 | LL | let _ = (f() + 1)..(f() + 1); | ^^^^^^^^^^^^^^^^^^^^ help: use: `((f() + 1)..=f())` error: an inclusive range would be more readable - --> tests/ui/range_plus_minus_one.rs:52:14 + --> tests/ui/range_plus_minus_one.rs:60:14 | LL | for _ in 1..ONE + ONE {} | ^^^^^^^^^^^^ help: use: `1..=ONE` diff --git a/tests/ui/rc_buffer.fixed b/tests/ui/rc_buffer.fixed index 35ac95a76a91..c71a4072b962 100644 --- a/tests/ui/rc_buffer.fixed +++ b/tests/ui/rc_buffer.fixed @@ -9,18 +9,26 @@ use std::rc::Rc; struct S { // triggers lint bad1: Rc, + //~^ rc_buffer bad2: Rc, + //~^ rc_buffer bad3: Rc<[u8]>, + //~^ rc_buffer bad4: Rc, + //~^ rc_buffer // does not trigger lint good1: Rc>, } // triggers lint fn func_bad1(_: Rc) {} +//~^ rc_buffer fn func_bad2(_: Rc) {} +//~^ rc_buffer fn func_bad3(_: Rc<[u8]>) {} +//~^ rc_buffer fn func_bad4(_: Rc) {} +//~^ rc_buffer // does not trigger lint fn func_good1(_: Rc>) {} diff --git a/tests/ui/rc_buffer.rs b/tests/ui/rc_buffer.rs index e78fb5a6d9d8..686c2644da17 100644 --- a/tests/ui/rc_buffer.rs +++ b/tests/ui/rc_buffer.rs @@ -9,18 +9,26 @@ use std::rc::Rc; struct S { // triggers lint bad1: Rc, + //~^ rc_buffer bad2: Rc, + //~^ rc_buffer bad3: Rc>, + //~^ rc_buffer bad4: Rc, + //~^ rc_buffer // does not trigger lint good1: Rc>, } // triggers lint fn func_bad1(_: Rc) {} +//~^ rc_buffer fn func_bad2(_: Rc) {} +//~^ rc_buffer fn func_bad3(_: Rc>) {} +//~^ rc_buffer fn func_bad4(_: Rc) {} +//~^ rc_buffer // does not trigger lint fn func_good1(_: Rc>) {} diff --git a/tests/ui/rc_buffer.stderr b/tests/ui/rc_buffer.stderr index 922f09288bf3..7500523ab4ac 100644 --- a/tests/ui/rc_buffer.stderr +++ b/tests/ui/rc_buffer.stderr @@ -8,43 +8,43 @@ LL | bad1: Rc, = help: to override `-D warnings` add `#[allow(clippy::rc_buffer)]` error: usage of `Rc` when T is a buffer type - --> tests/ui/rc_buffer.rs:12:11 + --> tests/ui/rc_buffer.rs:13:11 | LL | bad2: Rc, | ^^^^^^^^^^^ help: try: `Rc` error: usage of `Rc` when T is a buffer type - --> tests/ui/rc_buffer.rs:13:11 + --> tests/ui/rc_buffer.rs:15:11 | LL | bad3: Rc>, | ^^^^^^^^^^^ help: try: `Rc<[u8]>` error: usage of `Rc` when T is a buffer type - --> tests/ui/rc_buffer.rs:14:11 + --> tests/ui/rc_buffer.rs:17:11 | LL | bad4: Rc, | ^^^^^^^^^^^^ help: try: `Rc` error: usage of `Rc` when T is a buffer type - --> tests/ui/rc_buffer.rs:20:17 + --> tests/ui/rc_buffer.rs:24:17 | LL | fn func_bad1(_: Rc) {} | ^^^^^^^^^^ help: try: `Rc` error: usage of `Rc` when T is a buffer type - --> tests/ui/rc_buffer.rs:21:17 + --> tests/ui/rc_buffer.rs:26:17 | LL | fn func_bad2(_: Rc) {} | ^^^^^^^^^^^ help: try: `Rc` error: usage of `Rc` when T is a buffer type - --> tests/ui/rc_buffer.rs:22:17 + --> tests/ui/rc_buffer.rs:28:17 | LL | fn func_bad3(_: Rc>) {} | ^^^^^^^^^^^ help: try: `Rc<[u8]>` error: usage of `Rc` when T is a buffer type - --> tests/ui/rc_buffer.rs:23:17 + --> tests/ui/rc_buffer.rs:30:17 | LL | fn func_bad4(_: Rc) {} | ^^^^^^^^^^^^ help: try: `Rc` diff --git a/tests/ui/rc_buffer_arc.fixed b/tests/ui/rc_buffer_arc.fixed index 0d01c7c476f7..27059e3f2e1f 100644 --- a/tests/ui/rc_buffer_arc.fixed +++ b/tests/ui/rc_buffer_arc.fixed @@ -8,18 +8,26 @@ use std::sync::{Arc, Mutex}; struct S { // triggers lint bad1: Arc, + //~^ rc_buffer bad2: Arc, + //~^ rc_buffer bad3: Arc<[u8]>, + //~^ rc_buffer bad4: Arc, + //~^ rc_buffer // does not trigger lint good1: Arc>, } // triggers lint fn func_bad1(_: Arc) {} +//~^ rc_buffer fn func_bad2(_: Arc) {} +//~^ rc_buffer fn func_bad3(_: Arc<[u8]>) {} +//~^ rc_buffer fn func_bad4(_: Arc) {} +//~^ rc_buffer // does not trigger lint fn func_good1(_: Arc>) {} diff --git a/tests/ui/rc_buffer_arc.rs b/tests/ui/rc_buffer_arc.rs index 61ab16dc1829..5261eae2f26a 100644 --- a/tests/ui/rc_buffer_arc.rs +++ b/tests/ui/rc_buffer_arc.rs @@ -8,18 +8,26 @@ use std::sync::{Arc, Mutex}; struct S { // triggers lint bad1: Arc, + //~^ rc_buffer bad2: Arc, + //~^ rc_buffer bad3: Arc>, + //~^ rc_buffer bad4: Arc, + //~^ rc_buffer // does not trigger lint good1: Arc>, } // triggers lint fn func_bad1(_: Arc) {} +//~^ rc_buffer fn func_bad2(_: Arc) {} +//~^ rc_buffer fn func_bad3(_: Arc>) {} +//~^ rc_buffer fn func_bad4(_: Arc) {} +//~^ rc_buffer // does not trigger lint fn func_good1(_: Arc>) {} diff --git a/tests/ui/rc_buffer_arc.stderr b/tests/ui/rc_buffer_arc.stderr index 5ef5da2f67f8..786715463232 100644 --- a/tests/ui/rc_buffer_arc.stderr +++ b/tests/ui/rc_buffer_arc.stderr @@ -8,43 +8,43 @@ LL | bad1: Arc, = help: to override `-D warnings` add `#[allow(clippy::rc_buffer)]` error: usage of `Arc` when T is a buffer type - --> tests/ui/rc_buffer_arc.rs:11:11 + --> tests/ui/rc_buffer_arc.rs:12:11 | LL | bad2: Arc, | ^^^^^^^^^^^^ help: try: `Arc` error: usage of `Arc` when T is a buffer type - --> tests/ui/rc_buffer_arc.rs:12:11 + --> tests/ui/rc_buffer_arc.rs:14:11 | LL | bad3: Arc>, | ^^^^^^^^^^^^ help: try: `Arc<[u8]>` error: usage of `Arc` when T is a buffer type - --> tests/ui/rc_buffer_arc.rs:13:11 + --> tests/ui/rc_buffer_arc.rs:16:11 | LL | bad4: Arc, | ^^^^^^^^^^^^^ help: try: `Arc` error: usage of `Arc` when T is a buffer type - --> tests/ui/rc_buffer_arc.rs:19:17 + --> tests/ui/rc_buffer_arc.rs:23:17 | LL | fn func_bad1(_: Arc) {} | ^^^^^^^^^^^ help: try: `Arc` error: usage of `Arc` when T is a buffer type - --> tests/ui/rc_buffer_arc.rs:20:17 + --> tests/ui/rc_buffer_arc.rs:25:17 | LL | fn func_bad2(_: Arc) {} | ^^^^^^^^^^^^ help: try: `Arc` error: usage of `Arc` when T is a buffer type - --> tests/ui/rc_buffer_arc.rs:21:17 + --> tests/ui/rc_buffer_arc.rs:27:17 | LL | fn func_bad3(_: Arc>) {} | ^^^^^^^^^^^^ help: try: `Arc<[u8]>` error: usage of `Arc` when T is a buffer type - --> tests/ui/rc_buffer_arc.rs:22:17 + --> tests/ui/rc_buffer_arc.rs:29:17 | LL | fn func_bad4(_: Arc) {} | ^^^^^^^^^^^^^ help: try: `Arc` diff --git a/tests/ui/rc_buffer_redefined_string.rs b/tests/ui/rc_buffer_redefined_string.rs index 5d31a848cf72..49a8ba3e2efb 100644 --- a/tests/ui/rc_buffer_redefined_string.rs +++ b/tests/ui/rc_buffer_redefined_string.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::rc_buffer)] use std::rc::Rc; diff --git a/tests/ui/rc_clone_in_vec_init/arc.rs b/tests/ui/rc_clone_in_vec_init/arc.rs index 1c9e9aa7ef47..ad5d131f34bc 100644 --- a/tests/ui/rc_clone_in_vec_init/arc.rs +++ b/tests/ui/rc_clone_in_vec_init/arc.rs @@ -7,8 +7,7 @@ fn main() {} fn should_warn_simple_case() { let v = vec![Arc::new("x".to_string()); 2]; - //~^ ERROR: initializing a reference-counted pointer in `vec![elem; len]` - //~| NOTE: each element will point to the same `Arc` instance + //~^ rc_clone_in_vec_init } fn should_warn_simple_case_with_big_indentation() { @@ -17,16 +16,16 @@ fn should_warn_simple_case_with_big_indentation() { dbg!(k); if true { let v = vec![Arc::new("x".to_string()); 2]; - //~^ ERROR: initializing a reference-counted pointer in `vec![elem; len]` - //~| NOTE: each element will point to the same `Arc` instance + //~^ rc_clone_in_vec_init } } } fn should_warn_complex_case() { let v = vec![ - //~^ ERROR: initializing a reference-counted pointer in `vec![elem; len]` - //~| NOTE: each element will point to the same `Arc` instance + //~^ rc_clone_in_vec_init + + std::sync::Arc::new(Mutex::new({ let x = 1; dbg!(x); @@ -36,8 +35,9 @@ fn should_warn_complex_case() { ]; let v1 = vec![ - //~^ ERROR: initializing a reference-counted pointer in `vec![elem; len]` - //~| NOTE: each element will point to the same `Arc` instance + //~^ rc_clone_in_vec_init + + Arc::new(Mutex::new({ let x = 1; dbg!(x); diff --git a/tests/ui/rc_clone_in_vec_init/arc.stderr b/tests/ui/rc_clone_in_vec_init/arc.stderr index 1078a97542f2..598d3c0ae577 100644 --- a/tests/ui/rc_clone_in_vec_init/arc.stderr +++ b/tests/ui/rc_clone_in_vec_init/arc.stderr @@ -24,7 +24,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> tests/ui/rc_clone_in_vec_init/arc.rs:19:21 + --> tests/ui/rc_clone_in_vec_init/arc.rs:18:21 | LL | let v = vec![Arc::new("x".to_string()); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -47,13 +47,10 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> tests/ui/rc_clone_in_vec_init/arc.rs:27:13 + --> tests/ui/rc_clone_in_vec_init/arc.rs:25:13 | LL | let v = vec![ | _____________^ -LL | | -LL | | -LL | | std::sync::Arc::new(Mutex::new({ ... | LL | | 2 LL | | ]; @@ -77,13 +74,10 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> tests/ui/rc_clone_in_vec_init/arc.rs:38:14 + --> tests/ui/rc_clone_in_vec_init/arc.rs:37:14 | LL | let v1 = vec![ | ______________^ -LL | | -LL | | -LL | | Arc::new(Mutex::new({ ... | LL | | 2 LL | | ]; diff --git a/tests/ui/rc_clone_in_vec_init/rc.rs b/tests/ui/rc_clone_in_vec_init/rc.rs index 01cc433cbdae..d5af17c29e1d 100644 --- a/tests/ui/rc_clone_in_vec_init/rc.rs +++ b/tests/ui/rc_clone_in_vec_init/rc.rs @@ -8,8 +8,7 @@ fn main() {} fn should_warn_simple_case() { let v = vec![Rc::new("x".to_string()); 2]; - //~^ ERROR: initializing a reference-counted pointer in `vec![elem; len]` - //~| NOTE: each element will point to the same `Rc` instance + //~^ rc_clone_in_vec_init } fn should_warn_simple_case_with_big_indentation() { @@ -18,16 +17,16 @@ fn should_warn_simple_case_with_big_indentation() { dbg!(k); if true { let v = vec![Rc::new("x".to_string()); 2]; - //~^ ERROR: initializing a reference-counted pointer in `vec![elem; len]` - //~| NOTE: each element will point to the same `Rc` instance + //~^ rc_clone_in_vec_init } } } fn should_warn_complex_case() { let v = vec![ - //~^ ERROR: initializing a reference-counted pointer in `vec![elem; len]` - //~| NOTE: each element will point to the same `Rc` instance + //~^ rc_clone_in_vec_init + + std::rc::Rc::new(Mutex::new({ let x = 1; dbg!(x); @@ -37,8 +36,9 @@ fn should_warn_complex_case() { ]; let v1 = vec![ - //~^ ERROR: initializing a reference-counted pointer in `vec![elem; len]` - //~| NOTE: each element will point to the same `Rc` instance + //~^ rc_clone_in_vec_init + + Rc::new(Mutex::new({ let x = 1; dbg!(x); diff --git a/tests/ui/rc_clone_in_vec_init/rc.stderr b/tests/ui/rc_clone_in_vec_init/rc.stderr index 702266d62d2c..60d7f33ada9c 100644 --- a/tests/ui/rc_clone_in_vec_init/rc.stderr +++ b/tests/ui/rc_clone_in_vec_init/rc.stderr @@ -24,7 +24,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> tests/ui/rc_clone_in_vec_init/rc.rs:20:21 + --> tests/ui/rc_clone_in_vec_init/rc.rs:19:21 | LL | let v = vec![Rc::new("x".to_string()); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -47,13 +47,10 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> tests/ui/rc_clone_in_vec_init/rc.rs:28:13 + --> tests/ui/rc_clone_in_vec_init/rc.rs:26:13 | LL | let v = vec![ | _____________^ -LL | | -LL | | -LL | | std::rc::Rc::new(Mutex::new({ ... | LL | | 2 LL | | ]; @@ -77,13 +74,10 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> tests/ui/rc_clone_in_vec_init/rc.rs:39:14 + --> tests/ui/rc_clone_in_vec_init/rc.rs:38:14 | LL | let v1 = vec![ | ______________^ -LL | | -LL | | -LL | | Rc::new(Mutex::new({ ... | LL | | 2 LL | | ]; diff --git a/tests/ui/rc_clone_in_vec_init/weak.rs b/tests/ui/rc_clone_in_vec_init/weak.rs index fd2895d40458..add09b6ba859 100644 --- a/tests/ui/rc_clone_in_vec_init/weak.rs +++ b/tests/ui/rc_clone_in_vec_init/weak.rs @@ -8,18 +8,16 @@ fn main() {} fn should_warn_simple_case() { let v = vec![SyncWeak::::new(); 2]; - //~^ ERROR: initializing a reference-counted pointer in `vec![elem; len]` - //~| NOTE: each element will point to the same `Weak` instance + //~^ rc_clone_in_vec_init + let v2 = vec![UnSyncWeak::::new(); 2]; - //~^ ERROR: initializing a reference-counted pointer in `vec![elem; len]` - //~| NOTE: each element will point to the same `Weak` instance + //~^ rc_clone_in_vec_init let v = vec![Rc::downgrade(&Rc::new("x".to_string())); 2]; - //~^ ERROR: initializing a reference-counted pointer in `vec![elem; len]` - //~| NOTE: each element will point to the same `Weak` instance + //~^ rc_clone_in_vec_init + let v = vec![Arc::downgrade(&Arc::new("x".to_string())); 2]; - //~^ ERROR: initializing a reference-counted pointer in `vec![elem; len]` - //~| NOTE: each element will point to the same `Weak` instance + //~^ rc_clone_in_vec_init } fn should_warn_simple_case_with_big_indentation() { @@ -28,19 +26,19 @@ fn should_warn_simple_case_with_big_indentation() { dbg!(k); if true { let v = vec![Arc::downgrade(&Arc::new("x".to_string())); 2]; - //~^ ERROR: initializing a reference-counted pointer in `vec![elem; len]` - //~| NOTE: each element will point to the same `Weak` instance + //~^ rc_clone_in_vec_init + let v2 = vec![Rc::downgrade(&Rc::new("x".to_string())); 2]; - //~^ ERROR: initializing a reference-counted pointer in `vec![elem; len]` - //~| NOTE: each element will point to the same `Weak` instance + //~^ rc_clone_in_vec_init } } } fn should_warn_complex_case() { let v = vec![ - //~^ ERROR: initializing a reference-counted pointer in `vec![elem; len]` - //~| NOTE: each element will point to the same `Weak` instance + //~^ rc_clone_in_vec_init + + Arc::downgrade(&Arc::new(Mutex::new({ let x = 1; dbg!(x); @@ -50,8 +48,9 @@ fn should_warn_complex_case() { ]; let v1 = vec![ - //~^ ERROR: initializing a reference-counted pointer in `vec![elem; len]` - //~| NOTE: each element will point to the same `Weak` instance + //~^ rc_clone_in_vec_init + + Rc::downgrade(&Rc::new(Mutex::new({ let x = 1; dbg!(x); diff --git a/tests/ui/rc_clone_in_vec_init/weak.stderr b/tests/ui/rc_clone_in_vec_init/weak.stderr index 68ca2a7eb848..8bd018ab586c 100644 --- a/tests/ui/rc_clone_in_vec_init/weak.stderr +++ b/tests/ui/rc_clone_in_vec_init/weak.stderr @@ -47,7 +47,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> tests/ui/rc_clone_in_vec_init/weak.rs:17:13 + --> tests/ui/rc_clone_in_vec_init/weak.rs:16:13 | LL | let v = vec![Rc::downgrade(&Rc::new("x".to_string())); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -70,7 +70,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> tests/ui/rc_clone_in_vec_init/weak.rs:20:13 + --> tests/ui/rc_clone_in_vec_init/weak.rs:19:13 | LL | let v = vec![Arc::downgrade(&Arc::new("x".to_string())); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -93,7 +93,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> tests/ui/rc_clone_in_vec_init/weak.rs:30:21 + --> tests/ui/rc_clone_in_vec_init/weak.rs:28:21 | LL | let v = vec![Arc::downgrade(&Arc::new("x".to_string())); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -116,7 +116,7 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> tests/ui/rc_clone_in_vec_init/weak.rs:33:22 + --> tests/ui/rc_clone_in_vec_init/weak.rs:31:22 | LL | let v2 = vec![Rc::downgrade(&Rc::new("x".to_string())); 2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -139,13 +139,10 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> tests/ui/rc_clone_in_vec_init/weak.rs:41:13 + --> tests/ui/rc_clone_in_vec_init/weak.rs:38:13 | LL | let v = vec![ | _____________^ -LL | | -LL | | -LL | | Arc::downgrade(&Arc::new(Mutex::new({ ... | LL | | 2 LL | | ]; @@ -169,13 +166,10 @@ LL ~ }; | error: initializing a reference-counted pointer in `vec![elem; len]` - --> tests/ui/rc_clone_in_vec_init/weak.rs:52:14 + --> tests/ui/rc_clone_in_vec_init/weak.rs:50:14 | LL | let v1 = vec![ | ______________^ -LL | | -LL | | -LL | | Rc::downgrade(&Rc::new(Mutex::new({ ... | LL | | 2 LL | | ]; diff --git a/tests/ui/rc_mutex.rs b/tests/ui/rc_mutex.rs index 40adb3ddce95..c8700e13b11e 100644 --- a/tests/ui/rc_mutex.rs +++ b/tests/ui/rc_mutex.rs @@ -6,7 +6,7 @@ use std::sync::Mutex; pub struct MyStructWithPrivItem { foo: Rc>, - //~^ ERROR: usage of `Rc>` + //~^ rc_mutex } pub struct MyStructWithPubItem { @@ -25,11 +25,13 @@ pub enum MyEnum { // All of these test should be trigger the lint because they are not // part of the public api fn test1(foo: Rc>) {} -//~^ ERROR: usage of `Rc>` +//~^ rc_mutex + fn test2(foo: Rc>) {} -//~^ ERROR: usage of `Rc>` +//~^ rc_mutex + fn test3(foo: Rc>>) {} -//~^ ERROR: usage of `Rc>` +//~^ rc_mutex // All of these test should be allowed because they are part of the // public api and `avoid_breaking_exported_api` is `false` by default. diff --git a/tests/ui/rc_mutex.stderr b/tests/ui/rc_mutex.stderr index 9aa18336df00..5b589cfa309a 100644 --- a/tests/ui/rc_mutex.stderr +++ b/tests/ui/rc_mutex.stderr @@ -17,7 +17,7 @@ LL | fn test1(foo: Rc>) {} = help: consider using `Rc>` or `Arc>` instead error: usage of `Rc>` - --> tests/ui/rc_mutex.rs:29:15 + --> tests/ui/rc_mutex.rs:30:15 | LL | fn test2(foo: Rc>) {} | ^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | fn test2(foo: Rc>) {} = help: consider using `Rc>` or `Arc>` instead error: usage of `Rc>` - --> tests/ui/rc_mutex.rs:31:15 + --> tests/ui/rc_mutex.rs:33:15 | LL | fn test3(foo: Rc>>) {} | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/read_line_without_trim.fixed b/tests/ui/read_line_without_trim.fixed index 523ad5552747..e7f208e78d20 100644 --- a/tests/ui/read_line_without_trim.fixed +++ b/tests/ui/read_line_without_trim.fixed @@ -10,22 +10,27 @@ fn main() { let mut input = String::new(); std::io::stdin().read_line(&mut input).unwrap(); let _x: i32 = input.trim_end().parse().unwrap(); + //~^ read_line_without_trim let mut input = String::new(); std::io::stdin().read_line(&mut input).unwrap(); let _x = input.trim_end().parse::().unwrap(); + //~^ read_line_without_trim let mut input = String::new(); std::io::stdin().read_line(&mut input).unwrap(); let _x = input.trim_end().parse::().unwrap(); + //~^ read_line_without_trim let mut input = String::new(); std::io::stdin().read_line(&mut input).unwrap(); let _x = input.trim_end().parse::().unwrap(); + //~^ read_line_without_trim let mut input = String::new(); std::io::stdin().read_line(&mut input).unwrap(); let _x = input.trim_end().parse::().unwrap(); + //~^ read_line_without_trim let mut input = String::new(); std::io::stdin().read_line(&mut input).unwrap(); @@ -36,12 +41,14 @@ fn main() { let mut input = String::new(); std::io::stdin().read_line(&mut input).unwrap(); if input.trim_end() == "foo" { + //~^ read_line_without_trim println!("This will never ever execute!"); } let mut input = String::new(); std::io::stdin().read_line(&mut input).unwrap(); if input.trim_end().ends_with("foo") { + //~^ read_line_without_trim println!("Neither will this"); } } diff --git a/tests/ui/read_line_without_trim.rs b/tests/ui/read_line_without_trim.rs index e31ff0cde61d..6664278b5a87 100644 --- a/tests/ui/read_line_without_trim.rs +++ b/tests/ui/read_line_without_trim.rs @@ -10,22 +10,27 @@ fn main() { let mut input = String::new(); std::io::stdin().read_line(&mut input).unwrap(); let _x: i32 = input.parse().unwrap(); + //~^ read_line_without_trim let mut input = String::new(); std::io::stdin().read_line(&mut input).unwrap(); let _x = input.parse::().unwrap(); + //~^ read_line_without_trim let mut input = String::new(); std::io::stdin().read_line(&mut input).unwrap(); let _x = input.parse::().unwrap(); + //~^ read_line_without_trim let mut input = String::new(); std::io::stdin().read_line(&mut input).unwrap(); let _x = input.parse::().unwrap(); + //~^ read_line_without_trim let mut input = String::new(); std::io::stdin().read_line(&mut input).unwrap(); let _x = input.parse::().unwrap(); + //~^ read_line_without_trim let mut input = String::new(); std::io::stdin().read_line(&mut input).unwrap(); @@ -36,12 +41,14 @@ fn main() { let mut input = String::new(); std::io::stdin().read_line(&mut input).unwrap(); if input == "foo" { + //~^ read_line_without_trim println!("This will never ever execute!"); } let mut input = String::new(); std::io::stdin().read_line(&mut input).unwrap(); if input.ends_with("foo") { + //~^ read_line_without_trim println!("Neither will this"); } } diff --git a/tests/ui/read_line_without_trim.stderr b/tests/ui/read_line_without_trim.stderr index b54229f762a3..5e5618111432 100644 --- a/tests/ui/read_line_without_trim.stderr +++ b/tests/ui/read_line_without_trim.stderr @@ -15,7 +15,7 @@ LL | std::io::stdin().read_line(&mut input).unwrap(); = help: to override `-D warnings` add `#[allow(clippy::read_line_without_trim)]` error: calling `.parse()` on a string without trimming the trailing newline character - --> tests/ui/read_line_without_trim.rs:16:20 + --> tests/ui/read_line_without_trim.rs:17:20 | LL | let _x = input.parse::().unwrap(); | ----- ^^^^^^^^^^^^^^ @@ -23,13 +23,13 @@ LL | let _x = input.parse::().unwrap(); | help: try: `input.trim_end()` | note: call to `.read_line()` here, which leaves a trailing newline character in the buffer, which in turn will cause the checking to always fail - --> tests/ui/read_line_without_trim.rs:15:5 + --> tests/ui/read_line_without_trim.rs:16:5 | LL | std::io::stdin().read_line(&mut input).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: calling `.parse()` on a string without trimming the trailing newline character - --> tests/ui/read_line_without_trim.rs:20:20 + --> tests/ui/read_line_without_trim.rs:22:20 | LL | let _x = input.parse::().unwrap(); | ----- ^^^^^^^^^^^^^^ @@ -37,13 +37,13 @@ LL | let _x = input.parse::().unwrap(); | help: try: `input.trim_end()` | note: call to `.read_line()` here, which leaves a trailing newline character in the buffer, which in turn will cause the checking to always fail - --> tests/ui/read_line_without_trim.rs:19:5 + --> tests/ui/read_line_without_trim.rs:21:5 | LL | std::io::stdin().read_line(&mut input).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: calling `.parse()` on a string without trimming the trailing newline character - --> tests/ui/read_line_without_trim.rs:24:20 + --> tests/ui/read_line_without_trim.rs:27:20 | LL | let _x = input.parse::().unwrap(); | ----- ^^^^^^^^^^^^^^ @@ -51,13 +51,13 @@ LL | let _x = input.parse::().unwrap(); | help: try: `input.trim_end()` | note: call to `.read_line()` here, which leaves a trailing newline character in the buffer, which in turn will cause the checking to always fail - --> tests/ui/read_line_without_trim.rs:23:5 + --> tests/ui/read_line_without_trim.rs:26:5 | LL | std::io::stdin().read_line(&mut input).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: calling `.parse()` on a string without trimming the trailing newline character - --> tests/ui/read_line_without_trim.rs:28:20 + --> tests/ui/read_line_without_trim.rs:32:20 | LL | let _x = input.parse::().unwrap(); | ----- ^^^^^^^^^^^^^^^ @@ -65,13 +65,13 @@ LL | let _x = input.parse::().unwrap(); | help: try: `input.trim_end()` | note: call to `.read_line()` here, which leaves a trailing newline character in the buffer, which in turn will cause the checking to always fail - --> tests/ui/read_line_without_trim.rs:27:5 + --> tests/ui/read_line_without_trim.rs:31:5 | LL | std::io::stdin().read_line(&mut input).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: comparing a string literal without trimming the trailing newline character - --> tests/ui/read_line_without_trim.rs:38:8 + --> tests/ui/read_line_without_trim.rs:43:8 | LL | if input == "foo" { | -----^^^^^^^^^ @@ -79,13 +79,13 @@ LL | if input == "foo" { | help: try: `input.trim_end()` | note: call to `.read_line()` here, which leaves a trailing newline character in the buffer, which in turn will cause the comparison to always fail - --> tests/ui/read_line_without_trim.rs:37:5 + --> tests/ui/read_line_without_trim.rs:42:5 | LL | std::io::stdin().read_line(&mut input).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: checking the end of a string without trimming the trailing newline character - --> tests/ui/read_line_without_trim.rs:44:8 + --> tests/ui/read_line_without_trim.rs:50:8 | LL | if input.ends_with("foo") { | -----^^^^^^^^^^^^^^^^^ @@ -93,7 +93,7 @@ LL | if input.ends_with("foo") { | help: try: `input.trim_end()` | note: call to `.read_line()` here, which leaves a trailing newline character in the buffer, which in turn will cause the parsing to always fail - --> tests/ui/read_line_without_trim.rs:43:5 + --> tests/ui/read_line_without_trim.rs:49:5 | LL | std::io::stdin().read_line(&mut input).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/read_zero_byte_vec.rs b/tests/ui/read_zero_byte_vec.rs index 68acf4334699..938d61b68607 100644 --- a/tests/ui/read_zero_byte_vec.rs +++ b/tests/ui/read_zero_byte_vec.rs @@ -8,6 +8,7 @@ use std::fs::File; use std::io; use std::io::prelude::*; //@no-rustfix +//@require-annotations-for-level: WARN extern crate futures; use futures::io::{AsyncRead, AsyncReadExt}; use tokio::io::{AsyncRead as TokioAsyncRead, AsyncReadExt as _, AsyncWrite as TokioAsyncWrite, AsyncWriteExt as _}; diff --git a/tests/ui/read_zero_byte_vec.stderr b/tests/ui/read_zero_byte_vec.stderr index e2356f1cb56b..8f255bc87ab8 100644 --- a/tests/ui/read_zero_byte_vec.stderr +++ b/tests/ui/read_zero_byte_vec.stderr @@ -1,5 +1,5 @@ error: reading zero byte data to `Vec` - --> tests/ui/read_zero_byte_vec.rs:21:5 + --> tests/ui/read_zero_byte_vec.rs:22:5 | LL | f.read_exact(&mut data).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `data.resize(20, 0); f.read_exact(&mut data)` @@ -8,61 +8,61 @@ LL | f.read_exact(&mut data).unwrap(); = help: to override `-D warnings` add `#[allow(clippy::read_zero_byte_vec)]` error: reading zero byte data to `Vec` - --> tests/ui/read_zero_byte_vec.rs:27:5 + --> tests/ui/read_zero_byte_vec.rs:28:5 | LL | f.read_exact(&mut data2)?; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `data2.resize(cap, 0); f.read_exact(&mut data2)` error: reading zero byte data to `Vec` - --> tests/ui/read_zero_byte_vec.rs:32:5 + --> tests/ui/read_zero_byte_vec.rs:33:5 | LL | f.read_exact(&mut data3)?; | ^^^^^^^^^^^^^^^^^^^^^^^^ error: reading zero byte data to `Vec` - --> tests/ui/read_zero_byte_vec.rs:37:13 + --> tests/ui/read_zero_byte_vec.rs:38:13 | LL | let _ = f.read(&mut data4)?; | ^^^^^^^^^^^^^^^^^^ error: reading zero byte data to `Vec` - --> tests/ui/read_zero_byte_vec.rs:43:9 + --> tests/ui/read_zero_byte_vec.rs:44:9 | LL | f.read(&mut data5) | ^^^^^^^^^^^^^^^^^^ error: reading zero byte data to `Vec` - --> tests/ui/read_zero_byte_vec.rs:50:9 + --> tests/ui/read_zero_byte_vec.rs:51:9 | LL | f.read(&mut data6) | ^^^^^^^^^^^^^^^^^^ error: reading zero byte data to `Vec` - --> tests/ui/read_zero_byte_vec.rs:84:9 + --> tests/ui/read_zero_byte_vec.rs:85:9 | LL | f.read(&mut v)?; | ^^^^^^^^^^^^^^ error: reading zero byte data to `Vec` - --> tests/ui/read_zero_byte_vec.rs:94:5 + --> tests/ui/read_zero_byte_vec.rs:95:5 | LL | r.read(&mut data).await.unwrap(); | ^^^^^^^^^^^^^^^^^ error: reading zero byte data to `Vec` - --> tests/ui/read_zero_byte_vec.rs:99:5 + --> tests/ui/read_zero_byte_vec.rs:100:5 | LL | r.read_exact(&mut data2).await.unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: reading zero byte data to `Vec` - --> tests/ui/read_zero_byte_vec.rs:106:5 + --> tests/ui/read_zero_byte_vec.rs:107:5 | LL | r.read(&mut data).await.unwrap(); | ^^^^^^^^^^^^^^^^^ error: reading zero byte data to `Vec` - --> tests/ui/read_zero_byte_vec.rs:111:5 + --> tests/ui/read_zero_byte_vec.rs:112:5 | LL | r.read_exact(&mut data2).await.unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/readonly_write_lock.fixed b/tests/ui/readonly_write_lock.fixed index 4db13482ac78..0cb91247232b 100644 --- a/tests/ui/readonly_write_lock.fixed +++ b/tests/ui/readonly_write_lock.fixed @@ -14,14 +14,15 @@ fn main() { { let writer = lock.read().unwrap(); - //~^ ERROR: this write lock is used only for reading - //~| NOTE: `-D clippy::readonly-write-lock` implied by `-D warnings` + //~^ readonly_write_lock + dbg!(&writer); } { let writer = lock.read().unwrap(); - //~^ ERROR: this write lock is used only for reading + //~^ readonly_write_lock + accept_i32(*writer); } diff --git a/tests/ui/readonly_write_lock.rs b/tests/ui/readonly_write_lock.rs index 66ba1b2d6969..843755fe792c 100644 --- a/tests/ui/readonly_write_lock.rs +++ b/tests/ui/readonly_write_lock.rs @@ -14,14 +14,15 @@ fn main() { { let writer = lock.write().unwrap(); - //~^ ERROR: this write lock is used only for reading - //~| NOTE: `-D clippy::readonly-write-lock` implied by `-D warnings` + //~^ readonly_write_lock + dbg!(&writer); } { let writer = lock.write().unwrap(); - //~^ ERROR: this write lock is used only for reading + //~^ readonly_write_lock + accept_i32(*writer); } diff --git a/tests/ui/recursive_format_impl.rs b/tests/ui/recursive_format_impl.rs index b3eafc6dad7a..9f46fef62354 100644 --- a/tests/ui/recursive_format_impl.rs +++ b/tests/ui/recursive_format_impl.rs @@ -29,8 +29,7 @@ impl B for A { impl fmt::Display for A { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.to_string()) - //~^ ERROR: using `self.to_string` in `fmt::Display` implementation will cause inf - //~| NOTE: `-D clippy::recursive-format-impl` implied by `-D warnings` + //~^ recursive_format_impl } } @@ -75,7 +74,7 @@ struct G; impl std::fmt::Display for G { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self) - //~^ ERROR: using `self` as `Display` in `impl Display` will cause infinite recurs + //~^ recursive_format_impl } } @@ -85,14 +84,14 @@ struct H; impl std::fmt::Display for H { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", &self) - //~^ ERROR: using `self` as `Display` in `impl Display` will cause infinite recurs + //~^ recursive_format_impl } } impl std::fmt::Debug for H { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{:?}", &self) - //~^ ERROR: using `self` as `Debug` in `impl Debug` will cause infinite recursion + //~^ recursive_format_impl } } @@ -102,7 +101,7 @@ struct H2; impl std::fmt::Display for H2 { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", &&&self) - //~^ ERROR: using `self` as `Display` in `impl Display` will cause infinite recurs + //~^ recursive_format_impl } } @@ -177,14 +176,14 @@ impl std::ops::Deref for J { impl std::fmt::Display for J { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}", &*self) - //~^ ERROR: using `self` as `Display` in `impl Display` will cause infinite recurs + //~^ recursive_format_impl } } impl std::fmt::Debug for J { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{:?}", &*self) - //~^ ERROR: using `self` as `Debug` in `impl Debug` will cause infinite recursion + //~^ recursive_format_impl } } @@ -201,7 +200,7 @@ impl std::ops::Deref for J2 { impl std::fmt::Display for J2 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}", *self) - //~^ ERROR: using `self` as `Display` in `impl Display` will cause infinite recurs + //~^ recursive_format_impl } } @@ -218,7 +217,7 @@ impl std::ops::Deref for J3 { impl std::fmt::Display for J3 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}", **&&*self) - //~^ ERROR: using `self` as `Display` in `impl Display` will cause infinite recurs + //~^ recursive_format_impl } } @@ -235,7 +234,7 @@ impl std::ops::Deref for J4 { impl std::fmt::Display for J4 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}", &&**&&*self) - //~^ ERROR: using `self` as `Display` in `impl Display` will cause infinite recurs + //~^ recursive_format_impl } } diff --git a/tests/ui/recursive_format_impl.stderr b/tests/ui/recursive_format_impl.stderr index f80aff01eb53..31960c7193b4 100644 --- a/tests/ui/recursive_format_impl.stderr +++ b/tests/ui/recursive_format_impl.stderr @@ -8,7 +8,7 @@ LL | write!(f, "{}", self.to_string()) = help: to override `-D warnings` add `#[allow(clippy::recursive_format_impl)]` error: using `self` as `Display` in `impl Display` will cause infinite recursion - --> tests/ui/recursive_format_impl.rs:77:9 + --> tests/ui/recursive_format_impl.rs:76:9 | LL | write!(f, "{}", self) | ^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | write!(f, "{}", self) = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Display` in `impl Display` will cause infinite recursion - --> tests/ui/recursive_format_impl.rs:87:9 + --> tests/ui/recursive_format_impl.rs:86:9 | LL | write!(f, "{}", &self) | ^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | write!(f, "{}", &self) = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Debug` in `impl Debug` will cause infinite recursion - --> tests/ui/recursive_format_impl.rs:94:9 + --> tests/ui/recursive_format_impl.rs:93:9 | LL | write!(f, "{:?}", &self) | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | write!(f, "{:?}", &self) = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Display` in `impl Display` will cause infinite recursion - --> tests/ui/recursive_format_impl.rs:104:9 + --> tests/ui/recursive_format_impl.rs:103:9 | LL | write!(f, "{}", &&&self) | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | write!(f, "{}", &&&self) = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Display` in `impl Display` will cause infinite recursion - --> tests/ui/recursive_format_impl.rs:179:9 + --> tests/ui/recursive_format_impl.rs:178:9 | LL | write!(f, "{}", &*self) | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -48,7 +48,7 @@ LL | write!(f, "{}", &*self) = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Debug` in `impl Debug` will cause infinite recursion - --> tests/ui/recursive_format_impl.rs:186:9 + --> tests/ui/recursive_format_impl.rs:185:9 | LL | write!(f, "{:?}", &*self) | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | write!(f, "{:?}", &*self) = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Display` in `impl Display` will cause infinite recursion - --> tests/ui/recursive_format_impl.rs:203:9 + --> tests/ui/recursive_format_impl.rs:202:9 | LL | write!(f, "{}", *self) | ^^^^^^^^^^^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | write!(f, "{}", *self) = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Display` in `impl Display` will cause infinite recursion - --> tests/ui/recursive_format_impl.rs:220:9 + --> tests/ui/recursive_format_impl.rs:219:9 | LL | write!(f, "{}", **&&*self) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -72,7 +72,7 @@ LL | write!(f, "{}", **&&*self) = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Display` in `impl Display` will cause infinite recursion - --> tests/ui/recursive_format_impl.rs:237:9 + --> tests/ui/recursive_format_impl.rs:236:9 | LL | write!(f, "{}", &&**&&*self) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/redundant_allocation.rs b/tests/ui/redundant_allocation.rs index e70f8e71fae8..0562f7dcc761 100644 --- a/tests/ui/redundant_allocation.rs +++ b/tests/ui/redundant_allocation.rs @@ -14,24 +14,21 @@ mod outer_box { use std::sync::Arc; pub fn box_test6(foo: Box>) {} - //~^ ERROR: usage of `Box>` - //~| NOTE: `Rc` is already on the heap, `Box>` makes an extra allocation + //~^ redundant_allocation pub fn box_test7(foo: Box>) {} - //~^ ERROR: usage of `Box>` - //~| NOTE: `Arc` is already on the heap, `Box>` makes an extra allocation + //~^ redundant_allocation pub fn box_test8() -> Box>> { - //~^ ERROR: usage of `Box>>` - //~| NOTE: `Rc>` is already on the heap, `Box>>` makes an e + //~^ redundant_allocation + unimplemented!(); } pub fn box_test9(foo: Box>) -> Box>> { - //~^ ERROR: usage of `Box>` - //~| NOTE: `Arc` is already on the heap, `Box>` makes an extra allocation - //~| ERROR: usage of `Box>>` - //~| NOTE: `Arc>` is already on the heap, `Box>>` makes an extra a + //~^ redundant_allocation + //~| redundant_allocation + unimplemented!(); } } @@ -43,24 +40,21 @@ mod outer_rc { use std::sync::Arc; pub fn rc_test5(a: Rc>) {} - //~^ ERROR: usage of `Rc>` - //~| NOTE: `Box` is already on the heap, `Rc>` makes an extra allocati + //~^ redundant_allocation pub fn rc_test7(a: Rc>) {} - //~^ ERROR: usage of `Rc>` - //~| NOTE: `Arc` is already on the heap, `Rc>` makes an extra allocati + //~^ redundant_allocation pub fn rc_test8() -> Rc>> { - //~^ ERROR: usage of `Rc>>` - //~| NOTE: `Box>` is already on the heap, `Rc>>` makes an + //~^ redundant_allocation + unimplemented!(); } pub fn rc_test9(foo: Rc>) -> Rc>> { - //~^ ERROR: usage of `Rc>` - //~| NOTE: `Arc` is already on the heap, `Rc>` makes an extra allocation - //~| ERROR: usage of `Rc>>` - //~| NOTE: `Arc>` is already on the heap, `Rc>>` makes an extra al + //~^ redundant_allocation + //~| redundant_allocation + unimplemented!(); } } @@ -72,24 +66,21 @@ mod outer_arc { use std::sync::Arc; pub fn arc_test5(a: Arc>) {} - //~^ ERROR: usage of `Arc>` - //~| NOTE: `Box` is already on the heap, `Arc>` makes an extra allocat + //~^ redundant_allocation pub fn arc_test6(a: Arc>) {} - //~^ ERROR: usage of `Arc>` - //~| NOTE: `Rc` is already on the heap, `Arc>` makes an extra allocatio + //~^ redundant_allocation pub fn arc_test8() -> Arc>> { - //~^ ERROR: usage of `Arc>>` - //~| NOTE: `Box>` is already on the heap, `Arc>>` makes an + //~^ redundant_allocation + unimplemented!(); } pub fn arc_test9(foo: Arc>) -> Arc>> { - //~^ ERROR: usage of `Arc>` - //~| NOTE: `Rc` is already on the heap, `Arc>` makes an extra allocation - //~| ERROR: usage of `Arc>>` - //~| NOTE: `Rc>` is already on the heap, `Arc>>` makes an extra all + //~^ redundant_allocation + //~| redundant_allocation + unimplemented!(); } } @@ -112,8 +103,7 @@ mod box_dyn { pub fn test_rc(_: Rc>) {} pub fn test_arc(_: Arc>) {} pub fn test_rc_box(_: Rc>>) {} - //~^ ERROR: usage of `Rc>>` - //~| NOTE: `Box>` is already on the heap, `Rc>>` makes an ex + //~^ redundant_allocation } // https://github.com/rust-lang/rust-clippy/issues/8604 @@ -146,17 +136,16 @@ mod box_fat_ptr { pub fn test_box_custom(_: Box>) {} pub fn test_rc_box_str(_: Rc>>) {} - //~^ ERROR: usage of `Rc>>` - //~| NOTE: `Box>` is already on the heap, `Rc>>` makes an extra + //~^ redundant_allocation + pub fn test_rc_box_slice(_: Rc>>) {} - //~^ ERROR: usage of `Rc>>` - //~| NOTE: `Box>` is already on the heap, `Rc>>` makes a + //~^ redundant_allocation + pub fn test_rc_box_path(_: Rc>>) {} - //~^ ERROR: usage of `Rc>>` - //~| NOTE: `Box>` is already on the heap, `Rc>>` makes an extr + //~^ redundant_allocation + pub fn test_rc_box_custom(_: Rc>>) {} - //~^ ERROR: usage of `Rc>>` - //~| NOTE: `Box>` is already on the heap, `Rc>>` makes + //~^ redundant_allocation } // https://github.com/rust-lang/rust-clippy/issues/11417 diff --git a/tests/ui/redundant_allocation.stderr b/tests/ui/redundant_allocation.stderr index 8a043013e07a..44d30f95d7bc 100644 --- a/tests/ui/redundant_allocation.stderr +++ b/tests/ui/redundant_allocation.stderr @@ -10,7 +10,7 @@ LL | pub fn box_test6(foo: Box>) {} = help: to override `-D warnings` add `#[allow(clippy::redundant_allocation)]` error: usage of `Box>` - --> tests/ui/redundant_allocation.rs:20:30 + --> tests/ui/redundant_allocation.rs:19:30 | LL | pub fn box_test7(foo: Box>) {} | ^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | pub fn box_test7(foo: Box>) {} = help: consider using just `Box` or `Arc` error: usage of `Box>>` - --> tests/ui/redundant_allocation.rs:24:27 + --> tests/ui/redundant_allocation.rs:22:27 | LL | pub fn box_test8() -> Box>> { | ^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | pub fn box_test8() -> Box>> { = help: consider using just `Box>` or `Rc>` error: usage of `Box>` - --> tests/ui/redundant_allocation.rs:30:30 + --> tests/ui/redundant_allocation.rs:28:30 | LL | pub fn box_test9(foo: Box>) -> Box>> { | ^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL | pub fn box_test9(foo: Box>) -> Box>> { = help: consider using just `Box` or `Arc` error: usage of `Box>>` - --> tests/ui/redundant_allocation.rs:30:46 + --> tests/ui/redundant_allocation.rs:28:46 | LL | pub fn box_test9(foo: Box>) -> Box>> { | ^^^^^^^^^^^^^^^^^ @@ -46,7 +46,7 @@ LL | pub fn box_test9(foo: Box>) -> Box>> { = help: consider using just `Box>` or `Arc>` error: usage of `Rc>` - --> tests/ui/redundant_allocation.rs:45:24 + --> tests/ui/redundant_allocation.rs:42:24 | LL | pub fn rc_test5(a: Rc>) {} | ^^^^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | pub fn rc_test5(a: Rc>) {} = help: consider using just `Rc` or `Box` error: usage of `Rc>` - --> tests/ui/redundant_allocation.rs:49:24 + --> tests/ui/redundant_allocation.rs:45:24 | LL | pub fn rc_test7(a: Rc>) {} | ^^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | pub fn rc_test7(a: Rc>) {} = help: consider using just `Rc` or `Arc` error: usage of `Rc>>` - --> tests/ui/redundant_allocation.rs:53:26 + --> tests/ui/redundant_allocation.rs:48:26 | LL | pub fn rc_test8() -> Rc>> { | ^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | pub fn rc_test8() -> Rc>> { = help: consider using just `Rc>` or `Box>` error: usage of `Rc>` - --> tests/ui/redundant_allocation.rs:59:29 + --> tests/ui/redundant_allocation.rs:54:29 | LL | pub fn rc_test9(foo: Rc>) -> Rc>> { | ^^^^^^^^^^ @@ -82,7 +82,7 @@ LL | pub fn rc_test9(foo: Rc>) -> Rc>> { = help: consider using just `Rc` or `Arc` error: usage of `Rc>>` - --> tests/ui/redundant_allocation.rs:59:44 + --> tests/ui/redundant_allocation.rs:54:44 | LL | pub fn rc_test9(foo: Rc>) -> Rc>> { | ^^^^^^^^^^^^^^^^ @@ -91,7 +91,7 @@ LL | pub fn rc_test9(foo: Rc>) -> Rc>> { = help: consider using just `Rc>` or `Arc>` error: usage of `Arc>` - --> tests/ui/redundant_allocation.rs:74:25 + --> tests/ui/redundant_allocation.rs:68:25 | LL | pub fn arc_test5(a: Arc>) {} | ^^^^^^^^^^^^^^ @@ -100,7 +100,7 @@ LL | pub fn arc_test5(a: Arc>) {} = help: consider using just `Arc` or `Box` error: usage of `Arc>` - --> tests/ui/redundant_allocation.rs:78:25 + --> tests/ui/redundant_allocation.rs:71:25 | LL | pub fn arc_test6(a: Arc>) {} | ^^^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL | pub fn arc_test6(a: Arc>) {} = help: consider using just `Arc` or `Rc` error: usage of `Arc>>` - --> tests/ui/redundant_allocation.rs:82:27 + --> tests/ui/redundant_allocation.rs:74:27 | LL | pub fn arc_test8() -> Arc>> { | ^^^^^^^^^^^^^^^^^^^^^ @@ -118,7 +118,7 @@ LL | pub fn arc_test8() -> Arc>> { = help: consider using just `Arc>` or `Box>` error: usage of `Arc>` - --> tests/ui/redundant_allocation.rs:88:30 + --> tests/ui/redundant_allocation.rs:80:30 | LL | pub fn arc_test9(foo: Arc>) -> Arc>> { | ^^^^^^^^^^ @@ -127,7 +127,7 @@ LL | pub fn arc_test9(foo: Arc>) -> Arc>> { = help: consider using just `Arc` or `Rc` error: usage of `Arc>>` - --> tests/ui/redundant_allocation.rs:88:45 + --> tests/ui/redundant_allocation.rs:80:45 | LL | pub fn arc_test9(foo: Arc>) -> Arc>> { | ^^^^^^^^^^^^^^^^ @@ -136,7 +136,7 @@ LL | pub fn arc_test9(foo: Arc>) -> Arc>> { = help: consider using just `Arc>` or `Rc>` error: usage of `Rc>>` - --> tests/ui/redundant_allocation.rs:114:27 + --> tests/ui/redundant_allocation.rs:105:27 | LL | pub fn test_rc_box(_: Rc>>) {} | ^^^^^^^^^^^^^^^^^^^ @@ -145,7 +145,7 @@ LL | pub fn test_rc_box(_: Rc>>) {} = help: consider using just `Rc>` or `Box>` error: usage of `Rc>>` - --> tests/ui/redundant_allocation.rs:148:31 + --> tests/ui/redundant_allocation.rs:138:31 | LL | pub fn test_rc_box_str(_: Rc>>) {} | ^^^^^^^^^^^^^^^^^ @@ -154,7 +154,7 @@ LL | pub fn test_rc_box_str(_: Rc>>) {} = help: consider using just `Rc>` or `Box>` error: usage of `Rc>>` - --> tests/ui/redundant_allocation.rs:151:33 + --> tests/ui/redundant_allocation.rs:141:33 | LL | pub fn test_rc_box_slice(_: Rc>>) {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -163,7 +163,7 @@ LL | pub fn test_rc_box_slice(_: Rc>>) {} = help: consider using just `Rc>` or `Box>` error: usage of `Rc>>` - --> tests/ui/redundant_allocation.rs:154:32 + --> tests/ui/redundant_allocation.rs:144:32 | LL | pub fn test_rc_box_path(_: Rc>>) {} | ^^^^^^^^^^^^^^^^^^ @@ -172,7 +172,7 @@ LL | pub fn test_rc_box_path(_: Rc>>) {} = help: consider using just `Rc>` or `Box>` error: usage of `Rc>>` - --> tests/ui/redundant_allocation.rs:157:34 + --> tests/ui/redundant_allocation.rs:147:34 | LL | pub fn test_rc_box_custom(_: Rc>>) {} | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/redundant_allocation_fixable.fixed b/tests/ui/redundant_allocation_fixable.fixed index 61c989c67a1a..7773ba11f973 100644 --- a/tests/ui/redundant_allocation_fixable.fixed +++ b/tests/ui/redundant_allocation_fixable.fixed @@ -21,14 +21,18 @@ mod outer_box { use std::sync::Arc; pub fn box_test1(foo: &T) {} + //~^ redundant_allocation pub fn box_test2(foo: &MyStruct) {} + //~^ redundant_allocation pub fn box_test3(foo: &MyEnum) {} + //~^ redundant_allocation pub fn box_test4_neg(foo: Box>) {} pub fn box_test5(foo: Box) {} + //~^ redundant_allocation } mod outer_rc { @@ -38,14 +42,18 @@ mod outer_rc { use std::sync::Arc; pub fn rc_test1(foo: &T) {} + //~^ redundant_allocation pub fn rc_test2(foo: &MyStruct) {} + //~^ redundant_allocation pub fn rc_test3(foo: &MyEnum) {} + //~^ redundant_allocation pub fn rc_test4_neg(foo: Rc>) {} pub fn rc_test6(a: Rc) {} + //~^ redundant_allocation } mod outer_arc { @@ -55,14 +63,18 @@ mod outer_arc { use std::sync::Arc; pub fn arc_test1(foo: &T) {} + //~^ redundant_allocation pub fn arc_test2(foo: &MyStruct) {} + //~^ redundant_allocation pub fn arc_test3(foo: &MyEnum) {} + //~^ redundant_allocation pub fn arc_test4_neg(foo: Arc>) {} pub fn arc_test7(a: Arc) {} + //~^ redundant_allocation } fn main() {} diff --git a/tests/ui/redundant_allocation_fixable.rs b/tests/ui/redundant_allocation_fixable.rs index 3ad1e9a978df..fb86ed2b3cfd 100644 --- a/tests/ui/redundant_allocation_fixable.rs +++ b/tests/ui/redundant_allocation_fixable.rs @@ -21,14 +21,18 @@ mod outer_box { use std::sync::Arc; pub fn box_test1(foo: Box<&T>) {} + //~^ redundant_allocation pub fn box_test2(foo: Box<&MyStruct>) {} + //~^ redundant_allocation pub fn box_test3(foo: Box<&MyEnum>) {} + //~^ redundant_allocation pub fn box_test4_neg(foo: Box>) {} pub fn box_test5(foo: Box>) {} + //~^ redundant_allocation } mod outer_rc { @@ -38,14 +42,18 @@ mod outer_rc { use std::sync::Arc; pub fn rc_test1(foo: Rc<&T>) {} + //~^ redundant_allocation pub fn rc_test2(foo: Rc<&MyStruct>) {} + //~^ redundant_allocation pub fn rc_test3(foo: Rc<&MyEnum>) {} + //~^ redundant_allocation pub fn rc_test4_neg(foo: Rc>) {} pub fn rc_test6(a: Rc>) {} + //~^ redundant_allocation } mod outer_arc { @@ -55,14 +63,18 @@ mod outer_arc { use std::sync::Arc; pub fn arc_test1(foo: Arc<&T>) {} + //~^ redundant_allocation pub fn arc_test2(foo: Arc<&MyStruct>) {} + //~^ redundant_allocation pub fn arc_test3(foo: Arc<&MyEnum>) {} + //~^ redundant_allocation pub fn arc_test4_neg(foo: Arc>) {} pub fn arc_test7(a: Arc>) {} + //~^ redundant_allocation } fn main() {} diff --git a/tests/ui/redundant_allocation_fixable.stderr b/tests/ui/redundant_allocation_fixable.stderr index 34a1a21bdadc..ed8282cc82ce 100644 --- a/tests/ui/redundant_allocation_fixable.stderr +++ b/tests/ui/redundant_allocation_fixable.stderr @@ -9,7 +9,7 @@ LL | pub fn box_test1(foo: Box<&T>) {} = help: to override `-D warnings` add `#[allow(clippy::redundant_allocation)]` error: usage of `Box<&MyStruct>` - --> tests/ui/redundant_allocation_fixable.rs:25:27 + --> tests/ui/redundant_allocation_fixable.rs:26:27 | LL | pub fn box_test2(foo: Box<&MyStruct>) {} | ^^^^^^^^^^^^^^ help: try: `&MyStruct` @@ -17,7 +17,7 @@ LL | pub fn box_test2(foo: Box<&MyStruct>) {} = note: `&MyStruct` is already a pointer, `Box<&MyStruct>` allocates a pointer on the heap error: usage of `Box<&MyEnum>` - --> tests/ui/redundant_allocation_fixable.rs:27:27 + --> tests/ui/redundant_allocation_fixable.rs:29:27 | LL | pub fn box_test3(foo: Box<&MyEnum>) {} | ^^^^^^^^^^^^ help: try: `&MyEnum` @@ -25,7 +25,7 @@ LL | pub fn box_test3(foo: Box<&MyEnum>) {} = note: `&MyEnum` is already a pointer, `Box<&MyEnum>` allocates a pointer on the heap error: usage of `Box>` - --> tests/ui/redundant_allocation_fixable.rs:31:30 + --> tests/ui/redundant_allocation_fixable.rs:34:30 | LL | pub fn box_test5(foo: Box>) {} | ^^^^^^^^^^^ help: try: `Box` @@ -33,7 +33,7 @@ LL | pub fn box_test5(foo: Box>) {} = note: `Box` is already on the heap, `Box>` makes an extra allocation error: usage of `Rc<&T>` - --> tests/ui/redundant_allocation_fixable.rs:40:29 + --> tests/ui/redundant_allocation_fixable.rs:44:29 | LL | pub fn rc_test1(foo: Rc<&T>) {} | ^^^^^^ help: try: `&T` @@ -41,7 +41,7 @@ LL | pub fn rc_test1(foo: Rc<&T>) {} = note: `&T` is already a pointer, `Rc<&T>` allocates a pointer on the heap error: usage of `Rc<&MyStruct>` - --> tests/ui/redundant_allocation_fixable.rs:42:26 + --> tests/ui/redundant_allocation_fixable.rs:47:26 | LL | pub fn rc_test2(foo: Rc<&MyStruct>) {} | ^^^^^^^^^^^^^ help: try: `&MyStruct` @@ -49,7 +49,7 @@ LL | pub fn rc_test2(foo: Rc<&MyStruct>) {} = note: `&MyStruct` is already a pointer, `Rc<&MyStruct>` allocates a pointer on the heap error: usage of `Rc<&MyEnum>` - --> tests/ui/redundant_allocation_fixable.rs:44:26 + --> tests/ui/redundant_allocation_fixable.rs:50:26 | LL | pub fn rc_test3(foo: Rc<&MyEnum>) {} | ^^^^^^^^^^^ help: try: `&MyEnum` @@ -57,7 +57,7 @@ LL | pub fn rc_test3(foo: Rc<&MyEnum>) {} = note: `&MyEnum` is already a pointer, `Rc<&MyEnum>` allocates a pointer on the heap error: usage of `Rc>` - --> tests/ui/redundant_allocation_fixable.rs:48:24 + --> tests/ui/redundant_allocation_fixable.rs:55:24 | LL | pub fn rc_test6(a: Rc>) {} | ^^^^^^^^^^^^ help: try: `Rc` @@ -65,7 +65,7 @@ LL | pub fn rc_test6(a: Rc>) {} = note: `Rc` is already on the heap, `Rc>` makes an extra allocation error: usage of `Arc<&T>` - --> tests/ui/redundant_allocation_fixable.rs:57:30 + --> tests/ui/redundant_allocation_fixable.rs:65:30 | LL | pub fn arc_test1(foo: Arc<&T>) {} | ^^^^^^^ help: try: `&T` @@ -73,7 +73,7 @@ LL | pub fn arc_test1(foo: Arc<&T>) {} = note: `&T` is already a pointer, `Arc<&T>` allocates a pointer on the heap error: usage of `Arc<&MyStruct>` - --> tests/ui/redundant_allocation_fixable.rs:59:27 + --> tests/ui/redundant_allocation_fixable.rs:68:27 | LL | pub fn arc_test2(foo: Arc<&MyStruct>) {} | ^^^^^^^^^^^^^^ help: try: `&MyStruct` @@ -81,7 +81,7 @@ LL | pub fn arc_test2(foo: Arc<&MyStruct>) {} = note: `&MyStruct` is already a pointer, `Arc<&MyStruct>` allocates a pointer on the heap error: usage of `Arc<&MyEnum>` - --> tests/ui/redundant_allocation_fixable.rs:61:27 + --> tests/ui/redundant_allocation_fixable.rs:71:27 | LL | pub fn arc_test3(foo: Arc<&MyEnum>) {} | ^^^^^^^^^^^^ help: try: `&MyEnum` @@ -89,7 +89,7 @@ LL | pub fn arc_test3(foo: Arc<&MyEnum>) {} = note: `&MyEnum` is already a pointer, `Arc<&MyEnum>` allocates a pointer on the heap error: usage of `Arc>` - --> tests/ui/redundant_allocation_fixable.rs:65:25 + --> tests/ui/redundant_allocation_fixable.rs:76:25 | LL | pub fn arc_test7(a: Arc>) {} | ^^^^^^^^^^^^^^ help: try: `Arc` diff --git a/tests/ui/redundant_as_str.fixed b/tests/ui/redundant_as_str.fixed index 708a1cc91506..4c5f7893d42e 100644 --- a/tests/ui/redundant_as_str.fixed +++ b/tests/ui/redundant_as_str.fixed @@ -6,7 +6,9 @@ fn main() { // These methods are redundant and the `as_str` can be removed let _redundant = string.as_bytes(); + //~^ redundant_as_str let _redundant = string.is_empty(); + //~^ redundant_as_str // These methods don't use `as_str` when they are redundant let _no_as_str = string.as_bytes(); diff --git a/tests/ui/redundant_as_str.rs b/tests/ui/redundant_as_str.rs index 257af591ceff..e3baec754595 100644 --- a/tests/ui/redundant_as_str.rs +++ b/tests/ui/redundant_as_str.rs @@ -6,7 +6,9 @@ fn main() { // These methods are redundant and the `as_str` can be removed let _redundant = string.as_str().as_bytes(); + //~^ redundant_as_str let _redundant = string.as_str().is_empty(); + //~^ redundant_as_str // These methods don't use `as_str` when they are redundant let _no_as_str = string.as_bytes(); diff --git a/tests/ui/redundant_as_str.stderr b/tests/ui/redundant_as_str.stderr index f5379d701db8..fc99c008220e 100644 --- a/tests/ui/redundant_as_str.stderr +++ b/tests/ui/redundant_as_str.stderr @@ -8,7 +8,7 @@ LL | let _redundant = string.as_str().as_bytes(); = help: to override `-D warnings` add `#[allow(clippy::redundant_as_str)]` error: this `as_str` is redundant and can be removed as the method immediately following exists on `String` too - --> tests/ui/redundant_as_str.rs:9:29 + --> tests/ui/redundant_as_str.rs:10:29 | LL | let _redundant = string.as_str().is_empty(); | ^^^^^^^^^^^^^^^^^ help: try: `is_empty` diff --git a/tests/ui/redundant_async_block.fixed b/tests/ui/redundant_async_block.fixed index a1875c1c06e1..2f14f27e7056 100644 --- a/tests/ui/redundant_async_block.fixed +++ b/tests/ui/redundant_async_block.fixed @@ -11,6 +11,7 @@ async fn func2() -> String { let s = String::from("some string"); let f = async { (*s).to_owned() }; let x = f; + //~^ redundant_async_block x.await } @@ -18,13 +19,16 @@ fn main() { let fut1 = async { 17 }; // Lint let fut2 = fut1; + //~^ redundant_async_block let fut1 = async { 25 }; // Lint let fut2 = fut1; + //~^ redundant_async_block // Lint let fut = async { 42 }; + //~^ redundant_async_block // Do not lint: not a single expression let fut = async { @@ -41,6 +45,7 @@ fn capture_local() -> impl Future { let fut = async { 17 }; // Lint fut + //~^ redundant_async_block } fn capture_local_closure(s: &str) -> impl Future { @@ -54,11 +59,13 @@ fn capture_arg(s: &str) -> impl Future { let fut = async move { s }; // Lint fut + //~^ redundant_async_block } fn capture_future_arg(f: impl Future) -> impl Future { // Lint f + //~^ redundant_async_block } fn capture_func_result(f: FN) -> impl Future @@ -82,6 +89,7 @@ where { // Lint async { f().await + 1 } + //~^ redundant_async_block } #[derive(Debug, Clone)] @@ -145,6 +153,7 @@ fn all_from_macro() -> impl Future { () => { // Lint async { 42 } + //~^ redundant_async_block }; } mac!() @@ -165,6 +174,7 @@ fn safe_parts_from_macro() -> impl Future { ($e: expr) => { // Lint async { $e } + //~^ redundant_async_block }; } mac!(42) diff --git a/tests/ui/redundant_async_block.rs b/tests/ui/redundant_async_block.rs index bb43403a043e..f5fe26b19cc8 100644 --- a/tests/ui/redundant_async_block.rs +++ b/tests/ui/redundant_async_block.rs @@ -11,6 +11,7 @@ async fn func2() -> String { let s = String::from("some string"); let f = async { (*s).to_owned() }; let x = async { f.await }; + //~^ redundant_async_block x.await } @@ -18,13 +19,16 @@ fn main() { let fut1 = async { 17 }; // Lint let fut2 = async { fut1.await }; + //~^ redundant_async_block let fut1 = async { 25 }; // Lint let fut2 = async move { fut1.await }; + //~^ redundant_async_block // Lint let fut = async { async { 42 }.await }; + //~^ redundant_async_block // Do not lint: not a single expression let fut = async { @@ -41,6 +45,7 @@ fn capture_local() -> impl Future { let fut = async { 17 }; // Lint async move { fut.await } + //~^ redundant_async_block } fn capture_local_closure(s: &str) -> impl Future { @@ -54,11 +59,13 @@ fn capture_arg(s: &str) -> impl Future { let fut = async move { s }; // Lint async move { fut.await } + //~^ redundant_async_block } fn capture_future_arg(f: impl Future) -> impl Future { // Lint async { f.await } + //~^ redundant_async_block } fn capture_func_result(f: FN) -> impl Future @@ -82,6 +89,7 @@ where { // Lint async { async { f().await + 1 }.await } + //~^ redundant_async_block } #[derive(Debug, Clone)] @@ -145,6 +153,7 @@ fn all_from_macro() -> impl Future { () => { // Lint async { async { 42 }.await } + //~^ redundant_async_block }; } mac!() @@ -165,6 +174,7 @@ fn safe_parts_from_macro() -> impl Future { ($e: expr) => { // Lint async { async { $e }.await } + //~^ redundant_async_block }; } mac!(42) diff --git a/tests/ui/redundant_async_block.stderr b/tests/ui/redundant_async_block.stderr index c6a5e2f28ada..386f00a25c2f 100644 --- a/tests/ui/redundant_async_block.stderr +++ b/tests/ui/redundant_async_block.stderr @@ -8,31 +8,25 @@ LL | let x = async { f.await }; = help: to override `-D warnings` add `#[allow(clippy::redundant_async_block)]` error: this async expression only awaits a single future - --> tests/ui/redundant_async_block.rs:20:16 + --> tests/ui/redundant_async_block.rs:21:16 | LL | let fut2 = async { fut1.await }; | ^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `fut1` error: this async expression only awaits a single future - --> tests/ui/redundant_async_block.rs:24:16 + --> tests/ui/redundant_async_block.rs:26:16 | LL | let fut2 = async move { fut1.await }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `fut1` error: this async expression only awaits a single future - --> tests/ui/redundant_async_block.rs:27:15 + --> tests/ui/redundant_async_block.rs:30:15 | LL | let fut = async { async { 42 }.await }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `async { 42 }` error: this async expression only awaits a single future - --> tests/ui/redundant_async_block.rs:43:5 - | -LL | async move { fut.await } - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `fut` - -error: this async expression only awaits a single future - --> tests/ui/redundant_async_block.rs:56:5 + --> tests/ui/redundant_async_block.rs:47:5 | LL | async move { fut.await } | ^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `fut` @@ -40,17 +34,23 @@ LL | async move { fut.await } error: this async expression only awaits a single future --> tests/ui/redundant_async_block.rs:61:5 | +LL | async move { fut.await } + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `fut` + +error: this async expression only awaits a single future + --> tests/ui/redundant_async_block.rs:67:5 + | LL | async { f.await } | ^^^^^^^^^^^^^^^^^ help: you can reduce it to: `f` error: this async expression only awaits a single future - --> tests/ui/redundant_async_block.rs:84:5 + --> tests/ui/redundant_async_block.rs:91:5 | LL | async { async { f().await + 1 }.await } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `async { f().await + 1 }` error: this async expression only awaits a single future - --> tests/ui/redundant_async_block.rs:147:13 + --> tests/ui/redundant_async_block.rs:155:13 | LL | async { async { 42 }.await } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `async { 42 }` @@ -61,7 +61,7 @@ LL | mac!() = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: this async expression only awaits a single future - --> tests/ui/redundant_async_block.rs:167:13 + --> tests/ui/redundant_async_block.rs:176:13 | LL | async { async { $e }.await } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `async { $e }` diff --git a/tests/ui/redundant_at_rest_pattern.fixed b/tests/ui/redundant_at_rest_pattern.fixed index a7997637372e..908b9051b7ef 100644 --- a/tests/ui/redundant_at_rest_pattern.fixed +++ b/tests/ui/redundant_at_rest_pattern.fixed @@ -7,13 +7,19 @@ extern crate proc_macros; fn main() { if let a = [()] {} + //~^ redundant_at_rest_pattern if let ref a = [()] {} + //~^ redundant_at_rest_pattern if let mut a = [()] {} + //~^ redundant_at_rest_pattern if let ref mut a = [()] {} + //~^ redundant_at_rest_pattern let v = vec![()]; if let a = &*v {} + //~^ redundant_at_rest_pattern let s = &[()]; if let a = s {} + //~^ redundant_at_rest_pattern // Don't lint if let [..] = &*v {} if let [a] = &*v {} diff --git a/tests/ui/redundant_at_rest_pattern.rs b/tests/ui/redundant_at_rest_pattern.rs index f103d1f1a179..0f19459773a9 100644 --- a/tests/ui/redundant_at_rest_pattern.rs +++ b/tests/ui/redundant_at_rest_pattern.rs @@ -7,13 +7,19 @@ extern crate proc_macros; fn main() { if let [a @ ..] = [()] {} + //~^ redundant_at_rest_pattern if let [ref a @ ..] = [()] {} + //~^ redundant_at_rest_pattern if let [mut a @ ..] = [()] {} + //~^ redundant_at_rest_pattern if let [ref mut a @ ..] = [()] {} + //~^ redundant_at_rest_pattern let v = vec![()]; if let [a @ ..] = &*v {} + //~^ redundant_at_rest_pattern let s = &[()]; if let [a @ ..] = s {} + //~^ redundant_at_rest_pattern // Don't lint if let [..] = &*v {} if let [a] = &*v {} diff --git a/tests/ui/redundant_at_rest_pattern.stderr b/tests/ui/redundant_at_rest_pattern.stderr index 012ba550ca11..3a6f6cf6500a 100644 --- a/tests/ui/redundant_at_rest_pattern.stderr +++ b/tests/ui/redundant_at_rest_pattern.stderr @@ -8,31 +8,31 @@ LL | if let [a @ ..] = [()] {} = help: to override `-D warnings` add `#[allow(clippy::redundant_at_rest_pattern)]` error: using a rest pattern to bind an entire slice to a local - --> tests/ui/redundant_at_rest_pattern.rs:10:12 + --> tests/ui/redundant_at_rest_pattern.rs:11:12 | LL | if let [ref a @ ..] = [()] {} | ^^^^^^^^^^^^ help: this is better represented with just the binding: `ref a` error: using a rest pattern to bind an entire slice to a local - --> tests/ui/redundant_at_rest_pattern.rs:11:12 + --> tests/ui/redundant_at_rest_pattern.rs:13:12 | LL | if let [mut a @ ..] = [()] {} | ^^^^^^^^^^^^ help: this is better represented with just the binding: `mut a` error: using a rest pattern to bind an entire slice to a local - --> tests/ui/redundant_at_rest_pattern.rs:12:12 + --> tests/ui/redundant_at_rest_pattern.rs:15:12 | LL | if let [ref mut a @ ..] = [()] {} | ^^^^^^^^^^^^^^^^ help: this is better represented with just the binding: `ref mut a` error: using a rest pattern to bind an entire slice to a local - --> tests/ui/redundant_at_rest_pattern.rs:14:12 + --> tests/ui/redundant_at_rest_pattern.rs:18:12 | LL | if let [a @ ..] = &*v {} | ^^^^^^^^ help: this is better represented with just the binding: `a` error: using a rest pattern to bind an entire slice to a local - --> tests/ui/redundant_at_rest_pattern.rs:16:12 + --> tests/ui/redundant_at_rest_pattern.rs:21:12 | LL | if let [a @ ..] = s {} | ^^^^^^^^ help: this is better represented with just the binding: `a` diff --git a/tests/ui/redundant_clone.fixed b/tests/ui/redundant_clone.fixed index 1d04cca9b9ed..23c00b34a00a 100644 --- a/tests/ui/redundant_clone.fixed +++ b/tests/ui/redundant_clone.fixed @@ -13,23 +13,31 @@ use std::path::Path; fn main() { let _s = ["lorem", "ipsum"].join(" "); + //~^ redundant_clone let s = String::from("foo"); let _s = s; + //~^ redundant_clone let s = String::from("foo"); let _s = s; + //~^ redundant_clone let s = String::from("foo"); let _s = s; + //~^ redundant_clone let _s = Path::new("/a/b/").join("c"); + //~^ redundant_clone let _s = Path::new("/a/b/").join("c"); + //~^ redundant_clone let _s = OsString::new(); + //~^ redundant_clone let _s = OsString::new(); + //~^ redundant_clone // Check that lint level works #[allow(clippy::redundant_clone)] @@ -41,6 +49,7 @@ fn main() { let tup = (String::from("foo"),); let _t = tup.0; + //~^ redundant_clone let tup_ref = &(String::from("foo"),); let _s = tup_ref.0.clone(); // this `.clone()` cannot be removed @@ -73,6 +82,7 @@ fn main() { struct Alpha; fn with_branch(a: Alpha, b: bool) -> (Alpha, Alpha) { if b { (a.clone(), a) } else { (Alpha, a) } + //~^ redundant_clone } fn cannot_double_move(a: Alpha) -> (Alpha, Alpha) { @@ -130,7 +140,9 @@ fn borrower_propagation() { } let _s = s; + //~^ redundant_clone let _t = t; + //~^ redundant_clone #[derive(Clone)] struct Foo { @@ -141,6 +153,7 @@ fn borrower_propagation() { let f = Foo { x: 123 }; let _x = Some(f.x); let _f = f; + //~^ redundant_clone } { @@ -153,6 +166,7 @@ fn borrower_propagation() { fn not_consumed() { let x = std::path::PathBuf::from("home"); let y = x.join("matthias"); + //~^ redundant_clone // join() creates a new owned PathBuf, does not take a &mut to x variable, thus the .clone() is // redundant. (It also does not consume the PathBuf) @@ -207,6 +221,7 @@ fn clone_then_move_cloned() { let x = Alpha; // ok, data is moved while the clone is in use. foo(&x, move || { + //~^ redundant_clone let _ = x; }); diff --git a/tests/ui/redundant_clone.rs b/tests/ui/redundant_clone.rs index 738744fec98f..f9fe8ba0236d 100644 --- a/tests/ui/redundant_clone.rs +++ b/tests/ui/redundant_clone.rs @@ -13,23 +13,31 @@ use std::path::Path; fn main() { let _s = ["lorem", "ipsum"].join(" ").to_string(); + //~^ redundant_clone let s = String::from("foo"); let _s = s.clone(); + //~^ redundant_clone let s = String::from("foo"); let _s = s.to_string(); + //~^ redundant_clone let s = String::from("foo"); let _s = s.to_owned(); + //~^ redundant_clone let _s = Path::new("/a/b/").join("c").to_owned(); + //~^ redundant_clone let _s = Path::new("/a/b/").join("c").to_path_buf(); + //~^ redundant_clone let _s = OsString::new().to_owned(); + //~^ redundant_clone let _s = OsString::new().to_os_string(); + //~^ redundant_clone // Check that lint level works #[allow(clippy::redundant_clone)] @@ -41,6 +49,7 @@ fn main() { let tup = (String::from("foo"),); let _t = tup.0.clone(); + //~^ redundant_clone let tup_ref = &(String::from("foo"),); let _s = tup_ref.0.clone(); // this `.clone()` cannot be removed @@ -73,6 +82,7 @@ fn main() { struct Alpha; fn with_branch(a: Alpha, b: bool) -> (Alpha, Alpha) { if b { (a.clone(), a.clone()) } else { (Alpha, a) } + //~^ redundant_clone } fn cannot_double_move(a: Alpha) -> (Alpha, Alpha) { @@ -130,7 +140,9 @@ fn borrower_propagation() { } let _s = s.clone(); + //~^ redundant_clone let _t = t.clone(); + //~^ redundant_clone #[derive(Clone)] struct Foo { @@ -141,6 +153,7 @@ fn borrower_propagation() { let f = Foo { x: 123 }; let _x = Some(f.x); let _f = f.clone(); + //~^ redundant_clone } { @@ -153,6 +166,7 @@ fn borrower_propagation() { fn not_consumed() { let x = std::path::PathBuf::from("home"); let y = x.clone().join("matthias"); + //~^ redundant_clone // join() creates a new owned PathBuf, does not take a &mut to x variable, thus the .clone() is // redundant. (It also does not consume the PathBuf) @@ -207,6 +221,7 @@ fn clone_then_move_cloned() { let x = Alpha; // ok, data is moved while the clone is in use. foo(&x.clone(), move || { + //~^ redundant_clone let _ = x; }); diff --git a/tests/ui/redundant_clone.stderr b/tests/ui/redundant_clone.stderr index 3c37288f5507..5be081f0f2f8 100644 --- a/tests/ui/redundant_clone.stderr +++ b/tests/ui/redundant_clone.stderr @@ -13,169 +13,169 @@ LL | let _s = ["lorem", "ipsum"].join(" ").to_string(); = help: to override `-D warnings` add `#[allow(clippy::redundant_clone)]` error: redundant clone - --> tests/ui/redundant_clone.rs:18:15 + --> tests/ui/redundant_clone.rs:19:15 | LL | let _s = s.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:18:14 + --> tests/ui/redundant_clone.rs:19:14 | LL | let _s = s.clone(); | ^ error: redundant clone - --> tests/ui/redundant_clone.rs:21:15 + --> tests/ui/redundant_clone.rs:23:15 | LL | let _s = s.to_string(); | ^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:21:14 + --> tests/ui/redundant_clone.rs:23:14 | LL | let _s = s.to_string(); | ^ error: redundant clone - --> tests/ui/redundant_clone.rs:24:15 + --> tests/ui/redundant_clone.rs:27:15 | LL | let _s = s.to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:24:14 + --> tests/ui/redundant_clone.rs:27:14 | LL | let _s = s.to_owned(); | ^ error: redundant clone - --> tests/ui/redundant_clone.rs:26:42 + --> tests/ui/redundant_clone.rs:30:42 | LL | let _s = Path::new("/a/b/").join("c").to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:26:14 + --> tests/ui/redundant_clone.rs:30:14 | LL | let _s = Path::new("/a/b/").join("c").to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> tests/ui/redundant_clone.rs:28:42 + --> tests/ui/redundant_clone.rs:33:42 | LL | let _s = Path::new("/a/b/").join("c").to_path_buf(); | ^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:28:14 + --> tests/ui/redundant_clone.rs:33:14 | LL | let _s = Path::new("/a/b/").join("c").to_path_buf(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> tests/ui/redundant_clone.rs:30:29 + --> tests/ui/redundant_clone.rs:36:29 | LL | let _s = OsString::new().to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:30:14 + --> tests/ui/redundant_clone.rs:36:14 | LL | let _s = OsString::new().to_owned(); | ^^^^^^^^^^^^^^^ error: redundant clone - --> tests/ui/redundant_clone.rs:32:29 + --> tests/ui/redundant_clone.rs:39:29 | LL | let _s = OsString::new().to_os_string(); | ^^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:32:14 + --> tests/ui/redundant_clone.rs:39:14 | LL | let _s = OsString::new().to_os_string(); | ^^^^^^^^^^^^^^^ error: redundant clone - --> tests/ui/redundant_clone.rs:43:19 + --> tests/ui/redundant_clone.rs:51:19 | LL | let _t = tup.0.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:43:14 + --> tests/ui/redundant_clone.rs:51:14 | LL | let _t = tup.0.clone(); | ^^^^^ error: redundant clone - --> tests/ui/redundant_clone.rs:75:25 + --> tests/ui/redundant_clone.rs:84:25 | LL | if b { (a.clone(), a.clone()) } else { (Alpha, a) } | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:75:24 + --> tests/ui/redundant_clone.rs:84:24 | LL | if b { (a.clone(), a.clone()) } else { (Alpha, a) } | ^ error: redundant clone - --> tests/ui/redundant_clone.rs:132:15 + --> tests/ui/redundant_clone.rs:142:15 | LL | let _s = s.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:132:14 + --> tests/ui/redundant_clone.rs:142:14 | LL | let _s = s.clone(); | ^ error: redundant clone - --> tests/ui/redundant_clone.rs:133:15 + --> tests/ui/redundant_clone.rs:144:15 | LL | let _t = t.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:133:14 + --> tests/ui/redundant_clone.rs:144:14 | LL | let _t = t.clone(); | ^ error: redundant clone - --> tests/ui/redundant_clone.rs:143:19 + --> tests/ui/redundant_clone.rs:155:19 | LL | let _f = f.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:143:18 + --> tests/ui/redundant_clone.rs:155:18 | LL | let _f = f.clone(); | ^ error: redundant clone - --> tests/ui/redundant_clone.rs:155:14 + --> tests/ui/redundant_clone.rs:168:14 | LL | let y = x.clone().join("matthias"); | ^^^^^^^^ help: remove this | note: cloned value is neither consumed nor mutated - --> tests/ui/redundant_clone.rs:155:13 + --> tests/ui/redundant_clone.rs:168:13 | LL | let y = x.clone().join("matthias"); | ^^^^^^^^^ error: redundant clone - --> tests/ui/redundant_clone.rs:209:11 + --> tests/ui/redundant_clone.rs:223:11 | LL | foo(&x.clone(), move || { | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:209:10 + --> tests/ui/redundant_clone.rs:223:10 | LL | foo(&x.clone(), move || { | ^ diff --git a/tests/ui/redundant_closure_call_early.rs b/tests/ui/redundant_closure_call_early.rs index 6f9c9fd52224..722f7c03909f 100644 --- a/tests/ui/redundant_closure_call_early.rs +++ b/tests/ui/redundant_closure_call_early.rs @@ -7,12 +7,11 @@ fn main() { // lint here let mut k = (|m| m + 1)(i); - //~^ ERROR: try not to call a closure in the expression where it is declared - //~| NOTE: `-D clippy::redundant-closure-call` implied by `-D warnings` + //~^ redundant_closure_call // lint here k = (|a, b| a * b)(1, 5); - //~^ ERROR: try not to call a closure in the expression where it is declared + //~^ redundant_closure_call // don't lint these #[allow(clippy::needless_return)] diff --git a/tests/ui/redundant_closure_call_early.stderr b/tests/ui/redundant_closure_call_early.stderr index 038144a5d613..1dd24baf9dae 100644 --- a/tests/ui/redundant_closure_call_early.stderr +++ b/tests/ui/redundant_closure_call_early.stderr @@ -8,7 +8,7 @@ LL | let mut k = (|m| m + 1)(i); = help: to override `-D warnings` add `#[allow(clippy::redundant_closure_call)]` error: try not to call a closure in the expression where it is declared - --> tests/ui/redundant_closure_call_early.rs:14:9 + --> tests/ui/redundant_closure_call_early.rs:13:9 | LL | k = (|a, b| a * b)(1, 5); | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/redundant_closure_call_fixable.fixed b/tests/ui/redundant_closure_call_fixable.fixed index 9138a8bacfe1..099c118e64e3 100644 --- a/tests/ui/redundant_closure_call_fixable.fixed +++ b/tests/ui/redundant_closure_call_fixable.fixed @@ -13,17 +13,21 @@ async fn something_else() -> u32 { fn main() { let a = 42; + //~^ redundant_closure_call let b = async { + //~^ redundant_closure_call let x = something().await; let y = something_else().await; x * y }; let c = { + //~^ redundant_closure_call let x = 21; let y = 2; x * y }; let d = async { something().await }; + //~^ redundant_closure_call macro_rules! m { () => { @@ -33,14 +37,17 @@ fn main() { macro_rules! m2 { () => { m!() + //~^ redundant_closure_call }; } m2!(); + //~^ redundant_closure_call issue9956(); } fn issue9956() { assert_eq!(43, 42); + //~^ redundant_closure_call // ... and some more interesting cases I've found while implementing the fix @@ -50,13 +57,16 @@ fn issue9956() { // immediately calling it inside of a macro dbg!(42); + //~^ redundant_closure_call // immediately calling only one closure, so we can't remove the other ones let a = (|| || 123); + //~^ redundant_closure_call dbg!(a()()); // nested async closures let a = async { 1 }; + //~^ redundant_closure_call let h = async { a.await }; // macro expansion tests @@ -66,8 +76,10 @@ fn issue9956() { }; } let a = 1; + //~^ redundant_closure_call assert_eq!(a, 1); let a = 123; + //~^ redundant_closure_call assert_eq!(a, 123); // chaining calls, but not closures @@ -81,11 +93,14 @@ fn issue9956() { } fn foo(_: i32, _: i32) {} bar()(42, 5); + //~^ redundant_closure_call foo(42, 5); + //~^ redundant_closure_call } async fn issue11357() { async {}.await; + //~^ redundant_closure_call } mod issue11707 { @@ -95,11 +110,13 @@ mod issue11707 { fn demo() { spawn_on(async move {}); + //~^ redundant_closure_call } } fn avoid_double_parens() { std::convert::identity(13_i32 + 36_i32).leading_zeros(); + //~^ redundant_closure_call } fn fp_11274() { diff --git a/tests/ui/redundant_closure_call_fixable.rs b/tests/ui/redundant_closure_call_fixable.rs index ede6fa27778b..da5dd7ef263b 100644 --- a/tests/ui/redundant_closure_call_fixable.rs +++ b/tests/ui/redundant_closure_call_fixable.rs @@ -13,17 +13,21 @@ async fn something_else() -> u32 { fn main() { let a = (|| 42)(); + //~^ redundant_closure_call let b = (async || { + //~^ redundant_closure_call let x = something().await; let y = something_else().await; x * y })(); let c = (|| { + //~^ redundant_closure_call let x = 21; let y = 2; x * y })(); let d = (async || something().await)(); + //~^ redundant_closure_call macro_rules! m { () => { @@ -33,14 +37,17 @@ fn main() { macro_rules! m2 { () => { (|| m!())() + //~^ redundant_closure_call }; } m2!(); + //~^ redundant_closure_call issue9956(); } fn issue9956() { assert_eq!((|| || 43)()(), 42); + //~^ redundant_closure_call // ... and some more interesting cases I've found while implementing the fix @@ -50,13 +57,16 @@ fn issue9956() { // immediately calling it inside of a macro dbg!((|| 42)()); + //~^ redundant_closure_call // immediately calling only one closure, so we can't remove the other ones let a = (|| || || 123)(); + //~^ redundant_closure_call dbg!(a()()); // nested async closures let a = (|| || || || async || 1)()()()()(); + //~^ redundant_closure_call let h = async { a.await }; // macro expansion tests @@ -66,8 +76,10 @@ fn issue9956() { }; } let a = (|| echo!(|| echo!(|| 1)))()()(); + //~^ redundant_closure_call assert_eq!(a, 1); let a = (|| echo!((|| 123)))()(); + //~^ redundant_closure_call assert_eq!(a, 123); // chaining calls, but not closures @@ -81,11 +93,14 @@ fn issue9956() { } fn foo(_: i32, _: i32) {} bar()((|| || 42)()(), 5); + //~^ redundant_closure_call foo((|| || 42)()(), 5); + //~^ redundant_closure_call } async fn issue11357() { (|| async {})().await; + //~^ redundant_closure_call } mod issue11707 { @@ -95,11 +110,13 @@ mod issue11707 { fn demo() { spawn_on((|| async move {})()); + //~^ redundant_closure_call } } fn avoid_double_parens() { std::convert::identity((|| 13_i32 + 36_i32)()).leading_zeros(); + //~^ redundant_closure_call } fn fp_11274() { diff --git a/tests/ui/redundant_closure_call_fixable.stderr b/tests/ui/redundant_closure_call_fixable.stderr index 8e0d37df96b8..2c35aafbe310 100644 --- a/tests/ui/redundant_closure_call_fixable.stderr +++ b/tests/ui/redundant_closure_call_fixable.stderr @@ -8,10 +8,11 @@ LL | let a = (|| 42)(); = help: to override `-D warnings` add `#[allow(clippy::redundant_closure_call)]` error: try not to call a closure in the expression where it is declared - --> tests/ui/redundant_closure_call_fixable.rs:16:13 + --> tests/ui/redundant_closure_call_fixable.rs:17:13 | LL | let b = (async || { | _____________^ +LL | | LL | | let x = something().await; LL | | let y = something_else().await; LL | | x * y @@ -21,6 +22,7 @@ LL | | })(); help: try doing something like | LL ~ let b = async { +LL + LL + let x = something().await; LL + let y = something_else().await; LL + x * y @@ -28,10 +30,11 @@ LL ~ }; | error: try not to call a closure in the expression where it is declared - --> tests/ui/redundant_closure_call_fixable.rs:21:13 + --> tests/ui/redundant_closure_call_fixable.rs:23:13 | LL | let c = (|| { | _____________^ +LL | | LL | | let x = 21; LL | | let y = 2; LL | | x * y @@ -41,6 +44,7 @@ LL | | })(); help: try doing something like | LL ~ let c = { +LL + LL + let x = 21; LL + let y = 2; LL + x * y @@ -48,13 +52,13 @@ LL ~ }; | error: try not to call a closure in the expression where it is declared - --> tests/ui/redundant_closure_call_fixable.rs:26:13 + --> tests/ui/redundant_closure_call_fixable.rs:29:13 | LL | let d = (async || something().await)(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `async { something().await }` error: try not to call a closure in the expression where it is declared - --> tests/ui/redundant_closure_call_fixable.rs:35:13 + --> tests/ui/redundant_closure_call_fixable.rs:39:13 | LL | (|| m!())() | ^^^^^^^^^^^ help: try doing something like: `m!()` @@ -65,7 +69,7 @@ LL | m2!(); = note: this error originates in the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info) error: try not to call a closure in the expression where it is declared - --> tests/ui/redundant_closure_call_fixable.rs:30:13 + --> tests/ui/redundant_closure_call_fixable.rs:34:13 | LL | (|| 0)() | ^^^^^^^^ help: try doing something like: `0` @@ -76,67 +80,67 @@ LL | m2!(); = note: this error originates in the macro `m` which comes from the expansion of the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info) error: try not to call a closure in the expression where it is declared - --> tests/ui/redundant_closure_call_fixable.rs:43:16 + --> tests/ui/redundant_closure_call_fixable.rs:49:16 | LL | assert_eq!((|| || 43)()(), 42); | ^^^^^^^^^^^^^^ help: try doing something like: `43` error: try not to call a closure in the expression where it is declared - --> tests/ui/redundant_closure_call_fixable.rs:52:10 + --> tests/ui/redundant_closure_call_fixable.rs:59:10 | LL | dbg!((|| 42)()); | ^^^^^^^^^ help: try doing something like: `42` error: try not to call a closure in the expression where it is declared - --> tests/ui/redundant_closure_call_fixable.rs:55:13 + --> tests/ui/redundant_closure_call_fixable.rs:63:13 | LL | let a = (|| || || 123)(); | ^^^^^^^^^^^^^^^^ help: try doing something like: `(|| || 123)` error: try not to call a closure in the expression where it is declared - --> tests/ui/redundant_closure_call_fixable.rs:59:13 + --> tests/ui/redundant_closure_call_fixable.rs:68:13 | LL | let a = (|| || || || async || 1)()()()()(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `async { 1 }` error: try not to call a closure in the expression where it is declared - --> tests/ui/redundant_closure_call_fixable.rs:68:13 + --> tests/ui/redundant_closure_call_fixable.rs:78:13 | LL | let a = (|| echo!(|| echo!(|| 1)))()()(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `1` error: try not to call a closure in the expression where it is declared - --> tests/ui/redundant_closure_call_fixable.rs:70:13 + --> tests/ui/redundant_closure_call_fixable.rs:81:13 | LL | let a = (|| echo!((|| 123)))()(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `123` error: try not to call a closure in the expression where it is declared - --> tests/ui/redundant_closure_call_fixable.rs:83:11 + --> tests/ui/redundant_closure_call_fixable.rs:95:11 | LL | bar()((|| || 42)()(), 5); | ^^^^^^^^^^^^^^ help: try doing something like: `42` error: try not to call a closure in the expression where it is declared - --> tests/ui/redundant_closure_call_fixable.rs:84:9 + --> tests/ui/redundant_closure_call_fixable.rs:97:9 | LL | foo((|| || 42)()(), 5); | ^^^^^^^^^^^^^^ help: try doing something like: `42` error: try not to call a closure in the expression where it is declared - --> tests/ui/redundant_closure_call_fixable.rs:88:5 + --> tests/ui/redundant_closure_call_fixable.rs:102:5 | LL | (|| async {})().await; | ^^^^^^^^^^^^^^^ help: try doing something like: `async {}` error: try not to call a closure in the expression where it is declared - --> tests/ui/redundant_closure_call_fixable.rs:97:18 + --> tests/ui/redundant_closure_call_fixable.rs:112:18 | LL | spawn_on((|| async move {})()); | ^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `async move {}` error: try not to call a closure in the expression where it is declared - --> tests/ui/redundant_closure_call_fixable.rs:102:28 + --> tests/ui/redundant_closure_call_fixable.rs:118:28 | LL | std::convert::identity((|| 13_i32 + 36_i32)()).leading_zeros(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `13_i32 + 36_i32` diff --git a/tests/ui/redundant_closure_call_late.rs b/tests/ui/redundant_closure_call_late.rs index dc369c3bc092..fd997b1b5fa7 100644 --- a/tests/ui/redundant_closure_call_late.rs +++ b/tests/ui/redundant_closure_call_late.rs @@ -14,16 +14,16 @@ fn main() { // lint here let redun_closure = || 1; i = redun_closure(); - //~^ ERROR: closure called just once immediately after it was declared - //~| NOTE: `-D clippy::redundant-closure-call` implied by `-D warnings` + //~^ redundant_closure_call // shadowed closures are supported, lint here let shadowed_closure = || 1; i = shadowed_closure(); - //~^ ERROR: closure called just once immediately after it was declared + //~^ redundant_closure_call + let shadowed_closure = || 2; i = shadowed_closure(); - //~^ ERROR: closure called just once immediately after it was declared + //~^ redundant_closure_call // don't lint here let shadowed_closure = || 2; diff --git a/tests/ui/redundant_closure_call_late.stderr b/tests/ui/redundant_closure_call_late.stderr index 023e766a5d2b..ce2a21c23872 100644 --- a/tests/ui/redundant_closure_call_late.stderr +++ b/tests/ui/redundant_closure_call_late.stderr @@ -8,7 +8,7 @@ LL | i = redun_closure(); = help: to override `-D warnings` add `#[allow(clippy::redundant_closure_call)]` error: closure called just once immediately after it was declared - --> tests/ui/redundant_closure_call_late.rs:22:5 + --> tests/ui/redundant_closure_call_late.rs:21:5 | LL | i = shadowed_closure(); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/redundant_else.fixed b/tests/ui/redundant_else.fixed index 47aa79302d2c..8a3279f50180 100644 --- a/tests/ui/redundant_else.fixed +++ b/tests/ui/redundant_else.fixed @@ -8,14 +8,16 @@ fn main() { println!("Love your neighbor;"); break; } - //~^ ERROR: redundant else block + //~^ redundant_else + println!("yet don't pull down your hedge."); // continue if foo() { println!("He that lies down with Dogs,"); continue; } - //~^ ERROR: redundant else block + //~^ redundant_else + println!("shall rise up with fleas."); // match block if foo() { @@ -24,7 +26,8 @@ fn main() { _ => return, } } - //~^ ERROR: redundant else block + //~^ redundant_else + println!("You may delay, but time will not."); } // else if @@ -33,14 +36,16 @@ fn main() { } else if foo() { return; } - //~^ ERROR: redundant else block + //~^ redundant_else + println!("A fat kitchen makes a lean will."); // let binding outside of block let _ = { if foo() { return; } - //~^ ERROR: redundant else block + //~^ redundant_else + 1 }; // else if with let binding outside of block @@ -50,7 +55,8 @@ fn main() { } else if foo() { return; } - //~^ ERROR: redundant else block + //~^ redundant_else + 2 }; // inside if let @@ -59,7 +65,8 @@ fn main() { if foo() { return; } - //~^ ERROR: redundant else block + //~^ redundant_else + 1 } else { 1 diff --git a/tests/ui/redundant_else.rs b/tests/ui/redundant_else.rs index 8bcf2ce5233d..78abf4247a56 100644 --- a/tests/ui/redundant_else.rs +++ b/tests/ui/redundant_else.rs @@ -8,7 +8,8 @@ fn main() { println!("Love your neighbor;"); break; } else { - //~^ ERROR: redundant else block + //~^ redundant_else + println!("yet don't pull down your hedge."); } // continue @@ -16,7 +17,8 @@ fn main() { println!("He that lies down with Dogs,"); continue; } else { - //~^ ERROR: redundant else block + //~^ redundant_else + println!("shall rise up with fleas."); } // match block @@ -26,7 +28,8 @@ fn main() { _ => return, } } else { - //~^ ERROR: redundant else block + //~^ redundant_else + println!("You may delay, but time will not."); } } @@ -36,7 +39,8 @@ fn main() { } else if foo() { return; } else { - //~^ ERROR: redundant else block + //~^ redundant_else + println!("A fat kitchen makes a lean will."); } // let binding outside of block @@ -44,7 +48,8 @@ fn main() { if foo() { return; } else { - //~^ ERROR: redundant else block + //~^ redundant_else + 1 } }; @@ -55,7 +60,8 @@ fn main() { } else if foo() { return; } else { - //~^ ERROR: redundant else block + //~^ redundant_else + 2 } }; @@ -65,7 +71,8 @@ fn main() { if foo() { return; } else { - //~^ ERROR: redundant else block + //~^ redundant_else + 1 } } else { diff --git a/tests/ui/redundant_else.stderr b/tests/ui/redundant_else.stderr index ecc16f7cda5e..0902c97af0dd 100644 --- a/tests/ui/redundant_else.stderr +++ b/tests/ui/redundant_else.stderr @@ -4,6 +4,7 @@ error: redundant else block LL | } else { | __________^ LL | | +LL | | LL | | println!("yet don't pull down your hedge."); LL | | } | |_________^ @@ -14,15 +15,17 @@ help: remove the `else` block and move the contents out | LL ~ } LL + +LL + LL + println!("yet don't pull down your hedge."); | error: redundant else block - --> tests/ui/redundant_else.rs:18:10 + --> tests/ui/redundant_else.rs:19:10 | LL | } else { | __________^ LL | | +LL | | LL | | println!("shall rise up with fleas."); LL | | } | |_________^ @@ -31,15 +34,17 @@ help: remove the `else` block and move the contents out | LL ~ } LL + +LL + LL + println!("shall rise up with fleas."); | error: redundant else block - --> tests/ui/redundant_else.rs:28:10 + --> tests/ui/redundant_else.rs:30:10 | LL | } else { | __________^ LL | | +LL | | LL | | println!("You may delay, but time will not."); LL | | } | |_________^ @@ -48,15 +53,17 @@ help: remove the `else` block and move the contents out | LL ~ } LL + +LL + LL + println!("You may delay, but time will not."); | error: redundant else block - --> tests/ui/redundant_else.rs:38:6 + --> tests/ui/redundant_else.rs:41:6 | LL | } else { | ______^ LL | | +LL | | LL | | println!("A fat kitchen makes a lean will."); LL | | } | |_____^ @@ -65,15 +72,17 @@ help: remove the `else` block and move the contents out | LL ~ } LL + +LL + LL + println!("A fat kitchen makes a lean will."); | error: redundant else block - --> tests/ui/redundant_else.rs:46:10 + --> tests/ui/redundant_else.rs:50:10 | LL | } else { | __________^ LL | | +LL | | LL | | 1 LL | | } | |_________^ @@ -82,15 +91,17 @@ help: remove the `else` block and move the contents out | LL ~ } LL + +LL + LL + 1 | error: redundant else block - --> tests/ui/redundant_else.rs:57:10 + --> tests/ui/redundant_else.rs:62:10 | LL | } else { | __________^ LL | | +LL | | LL | | 2 LL | | } | |_________^ @@ -99,15 +110,17 @@ help: remove the `else` block and move the contents out | LL ~ } LL + +LL + LL + 2 | error: redundant else block - --> tests/ui/redundant_else.rs:67:10 + --> tests/ui/redundant_else.rs:73:10 | LL | } else { | __________^ LL | | +LL | | LL | | 1 LL | | } | |_________^ @@ -116,6 +129,7 @@ help: remove the `else` block and move the contents out | LL ~ } LL + +LL + LL + 1 | diff --git a/tests/ui/redundant_field_names.fixed b/tests/ui/redundant_field_names.fixed index 72fc4cb7333e..4c922030eb66 100644 --- a/tests/ui/redundant_field_names.fixed +++ b/tests/ui/redundant_field_names.fixed @@ -31,8 +31,9 @@ fn main() { let me = Person { gender, + //~^ redundant_field_names age, - + //~^ redundant_field_names name, //should be ok buzz: fizz, //should be ok foo: foo::BAR, //should be ok @@ -53,10 +54,15 @@ fn main() { // hand-written Range family structs are linted let _ = RangeFrom { start }; + //~^ redundant_field_names let _ = RangeTo { end }; + //~^ redundant_field_names let _ = Range { start, end }; + //~^ redundant_field_names + //~| redundant_field_names let _ = RangeInclusive::new(start, end); let _ = RangeToInclusive { end }; + //~^ redundant_field_names external! { let v = 1; @@ -69,6 +75,7 @@ fn main() { macro_rules! internal { ($i:ident) => { let _ = S { v }; + //~^ redundant_field_names let _ = S { $i: v }; let _ = S { v: $i }; let _ = S { $i: $i }; @@ -97,4 +104,5 @@ fn msrv_1_16() { fn msrv_1_17() { let start = 0; let _ = RangeFrom { start }; + //~^ redundant_field_names } diff --git a/tests/ui/redundant_field_names.rs b/tests/ui/redundant_field_names.rs index 2617d7e72837..7d03e269cf25 100644 --- a/tests/ui/redundant_field_names.rs +++ b/tests/ui/redundant_field_names.rs @@ -31,8 +31,9 @@ fn main() { let me = Person { gender: gender, + //~^ redundant_field_names age: age, - + //~^ redundant_field_names name, //should be ok buzz: fizz, //should be ok foo: foo::BAR, //should be ok @@ -53,10 +54,15 @@ fn main() { // hand-written Range family structs are linted let _ = RangeFrom { start: start }; + //~^ redundant_field_names let _ = RangeTo { end: end }; + //~^ redundant_field_names let _ = Range { start: start, end: end }; + //~^ redundant_field_names + //~| redundant_field_names let _ = RangeInclusive::new(start, end); let _ = RangeToInclusive { end: end }; + //~^ redundant_field_names external! { let v = 1; @@ -69,6 +75,7 @@ fn main() { macro_rules! internal { ($i:ident) => { let _ = S { v: v }; + //~^ redundant_field_names let _ = S { $i: v }; let _ = S { v: $i }; let _ = S { $i: $i }; @@ -97,4 +104,5 @@ fn msrv_1_16() { fn msrv_1_17() { let start = 0; let _ = RangeFrom { start: start }; + //~^ redundant_field_names } diff --git a/tests/ui/redundant_field_names.stderr b/tests/ui/redundant_field_names.stderr index 38c021fdba37..5554c28b7cff 100644 --- a/tests/ui/redundant_field_names.stderr +++ b/tests/ui/redundant_field_names.stderr @@ -8,43 +8,43 @@ LL | gender: gender, = help: to override `-D warnings` add `#[allow(clippy::redundant_field_names)]` error: redundant field names in struct initialization - --> tests/ui/redundant_field_names.rs:34:9 + --> tests/ui/redundant_field_names.rs:35:9 | LL | age: age, | ^^^^^^^^ help: replace it with: `age` error: redundant field names in struct initialization - --> tests/ui/redundant_field_names.rs:55:25 + --> tests/ui/redundant_field_names.rs:56:25 | LL | let _ = RangeFrom { start: start }; | ^^^^^^^^^^^^ help: replace it with: `start` error: redundant field names in struct initialization - --> tests/ui/redundant_field_names.rs:56:23 + --> tests/ui/redundant_field_names.rs:58:23 | LL | let _ = RangeTo { end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization - --> tests/ui/redundant_field_names.rs:57:21 + --> tests/ui/redundant_field_names.rs:60:21 | LL | let _ = Range { start: start, end: end }; | ^^^^^^^^^^^^ help: replace it with: `start` error: redundant field names in struct initialization - --> tests/ui/redundant_field_names.rs:57:35 + --> tests/ui/redundant_field_names.rs:60:35 | LL | let _ = Range { start: start, end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization - --> tests/ui/redundant_field_names.rs:59:32 + --> tests/ui/redundant_field_names.rs:64:32 | LL | let _ = RangeToInclusive { end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization - --> tests/ui/redundant_field_names.rs:71:25 + --> tests/ui/redundant_field_names.rs:77:25 | LL | let _ = S { v: v }; | ^^^^ help: replace it with: `v` @@ -55,7 +55,7 @@ LL | internal!(v); = note: this error originates in the macro `internal` (in Nightly builds, run with -Z macro-backtrace for more info) error: redundant field names in struct initialization - --> tests/ui/redundant_field_names.rs:99:25 + --> tests/ui/redundant_field_names.rs:106:25 | LL | let _ = RangeFrom { start: start }; | ^^^^^^^^^^^^ help: replace it with: `start` diff --git a/tests/ui/redundant_guards.fixed b/tests/ui/redundant_guards.fixed index ff7b233f004e..9dd9d341db2e 100644 --- a/tests/ui/redundant_guards.fixed +++ b/tests/ui/redundant_guards.fixed @@ -20,12 +20,14 @@ struct FloatWrapper(f32); fn issue11304() { match 0.1 { 0.0 => todo!(), + //~^ redundant_guards // Pattern matching NAN is illegal x if x == f64::NAN => todo!(), _ => todo!(), } match FloatWrapper(0.1) { FloatWrapper(0.0) => todo!(), + //~^ redundant_guards _ => todo!(), } } @@ -41,19 +43,25 @@ fn main() { let c = C(1, 2); match c { C(x, 1) => .., + //~^ redundant_guards _ => todo!(), }; let x = Some(Some(1)); match x { Some(Some(1)) if true => .., + //~^ redundant_guards Some(Some(1)) => { + //~^ redundant_guards println!("a"); .. }, Some(Some(1)) => .., + //~^ redundant_guards Some(Some(2)) => .., + //~^ redundant_guards Some(Some(2)) => .., + //~^ redundant_guards // Don't lint, since x is used in the body Some(x) if let Some(1) = x => { x; @@ -79,6 +87,7 @@ fn main() { let b = B { e: Some(A(0)) }; match b { B { e: Some(A(2)) } => .., + //~^ redundant_guards _ => todo!(), }; // Do not lint, since we cannot represent this as a pattern (at least, without a conversion) @@ -116,6 +125,7 @@ fn i() { // Do not lint E::A(x) | E::B(x) | E::C(x) if x == "from an or pattern" => {}, E::A("not from an or pattern") => {}, + //~^ redundant_guards _ => {}, }; } @@ -123,6 +133,7 @@ fn i() { fn h(v: Option) { match v { Some(0) => .., + //~^ redundant_guards _ => .., }; } @@ -130,7 +141,9 @@ fn h(v: Option) { fn negative_literal(i: i32) { match i { -1 => {}, + //~^ redundant_guards 1 => {}, + //~^ redundant_guards _ => {}, } } @@ -193,9 +206,13 @@ mod issue11465 { let c = Some(1); match c { Some(1) => {}, + //~^ redundant_guards Some(1) => {}, + //~^ redundant_guards Some(2) => {}, + //~^ redundant_guards Some(3) => {}, + //~^ redundant_guards _ => {}, }; @@ -216,9 +233,13 @@ mod issue11465 { B { ref b, .. } if b == "bar" => {}, B { ref b, .. } if "bar" == b => {}, B { c: 1, .. } => {}, + //~^ redundant_guards B { c: 1, .. } => {}, + //~^ redundant_guards B { c: 1, .. } => {}, + //~^ redundant_guards B { c: 1, .. } => {}, + //~^ redundant_guards _ => {}, } } @@ -229,6 +250,7 @@ fn issue11807() { match Some(Some("")) { Some(Some("")) => {}, + //~^ redundant_guards _ => {}, } @@ -240,11 +262,13 @@ fn issue11807() { match Some(Some(&[] as &[i32])) { Some(Some([])) => {}, + //~^ redundant_guards _ => {}, } match Some(Some([] as [i32; 0])) { Some(Some([])) => {}, + //~^ redundant_guards _ => {}, } @@ -256,21 +280,25 @@ fn issue11807() { match Some(Some(&[] as &[i32])) { Some(Some([..])) => {}, + //~^ redundant_guards _ => {}, } match Some(Some(&[] as &[i32])) { Some(Some([1, ..])) => {}, + //~^ redundant_guards _ => {}, } match Some(Some(&[] as &[i32])) { Some(Some([1, 2, ..])) => {}, + //~^ redundant_guards _ => {}, } match Some(Some(&[] as &[i32])) { Some(Some([.., 1, 2])) => {}, + //~^ redundant_guards _ => {}, } diff --git a/tests/ui/redundant_guards.rs b/tests/ui/redundant_guards.rs index b4d4ef5b170d..e9950d3bbd1d 100644 --- a/tests/ui/redundant_guards.rs +++ b/tests/ui/redundant_guards.rs @@ -20,12 +20,14 @@ struct FloatWrapper(f32); fn issue11304() { match 0.1 { x if x == 0.0 => todo!(), + //~^ redundant_guards // Pattern matching NAN is illegal x if x == f64::NAN => todo!(), _ => todo!(), } match FloatWrapper(0.1) { x if x == FloatWrapper(0.0) => todo!(), + //~^ redundant_guards _ => todo!(), } } @@ -41,19 +43,25 @@ fn main() { let c = C(1, 2); match c { C(x, y) if let 1 = y => .., + //~^ redundant_guards _ => todo!(), }; let x = Some(Some(1)); match x { Some(x) if matches!(x, Some(1) if true) => .., + //~^ redundant_guards Some(x) if matches!(x, Some(1)) => { + //~^ redundant_guards println!("a"); .. }, Some(x) if let Some(1) = x => .., + //~^ redundant_guards Some(x) if x == Some(2) => .., + //~^ redundant_guards Some(x) if Some(2) == x => .., + //~^ redundant_guards // Don't lint, since x is used in the body Some(x) if let Some(1) = x => { x; @@ -79,6 +87,7 @@ fn main() { let b = B { e: Some(A(0)) }; match b { B { e } if matches!(e, Some(A(2))) => .., + //~^ redundant_guards _ => todo!(), }; // Do not lint, since we cannot represent this as a pattern (at least, without a conversion) @@ -116,6 +125,7 @@ fn i() { // Do not lint E::A(x) | E::B(x) | E::C(x) if x == "from an or pattern" => {}, E::A(y) if y == "not from an or pattern" => {}, + //~^ redundant_guards _ => {}, }; } @@ -123,6 +133,7 @@ fn i() { fn h(v: Option) { match v { x if matches!(x, Some(0)) => .., + //~^ redundant_guards _ => .., }; } @@ -130,7 +141,9 @@ fn h(v: Option) { fn negative_literal(i: i32) { match i { i if i == -1 => {}, + //~^ redundant_guards i if i == 1 => {}, + //~^ redundant_guards _ => {}, } } @@ -193,9 +206,13 @@ mod issue11465 { let c = Some(1); match c { Some(ref x) if x == &1 => {}, + //~^ redundant_guards Some(ref x) if &1 == x => {}, + //~^ redundant_guards Some(ref x) if let &2 = x => {}, + //~^ redundant_guards Some(ref x) if matches!(x, &3) => {}, + //~^ redundant_guards _ => {}, }; @@ -216,9 +233,13 @@ mod issue11465 { B { ref b, .. } if b == "bar" => {}, B { ref b, .. } if "bar" == b => {}, B { ref c, .. } if c == &1 => {}, + //~^ redundant_guards B { ref c, .. } if &1 == c => {}, + //~^ redundant_guards B { ref c, .. } if let &1 = c => {}, + //~^ redundant_guards B { ref c, .. } if matches!(c, &1) => {}, + //~^ redundant_guards _ => {}, } } @@ -229,6 +250,7 @@ fn issue11807() { match Some(Some("")) { Some(Some(x)) if x.is_empty() => {}, + //~^ redundant_guards _ => {}, } @@ -240,11 +262,13 @@ fn issue11807() { match Some(Some(&[] as &[i32])) { Some(Some(x)) if x.is_empty() => {}, + //~^ redundant_guards _ => {}, } match Some(Some([] as [i32; 0])) { Some(Some(x)) if x.is_empty() => {}, + //~^ redundant_guards _ => {}, } @@ -256,21 +280,25 @@ fn issue11807() { match Some(Some(&[] as &[i32])) { Some(Some(x)) if x.starts_with(&[]) => {}, + //~^ redundant_guards _ => {}, } match Some(Some(&[] as &[i32])) { Some(Some(x)) if x.starts_with(&[1]) => {}, + //~^ redundant_guards _ => {}, } match Some(Some(&[] as &[i32])) { Some(Some(x)) if x.starts_with(&[1, 2]) => {}, + //~^ redundant_guards _ => {}, } match Some(Some(&[] as &[i32])) { Some(Some(x)) if x.ends_with(&[1, 2]) => {}, + //~^ redundant_guards _ => {}, } diff --git a/tests/ui/redundant_guards.stderr b/tests/ui/redundant_guards.stderr index a10cd5c2f481..cb7b9b119e20 100644 --- a/tests/ui/redundant_guards.stderr +++ b/tests/ui/redundant_guards.stderr @@ -13,7 +13,7 @@ LL + 0.0 => todo!(), | error: redundant guard - --> tests/ui/redundant_guards.rs:28:14 + --> tests/ui/redundant_guards.rs:29:14 | LL | x if x == FloatWrapper(0.0) => todo!(), | ^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + FloatWrapper(0.0) => todo!(), | error: redundant guard - --> tests/ui/redundant_guards.rs:43:20 + --> tests/ui/redundant_guards.rs:45:20 | LL | C(x, y) if let 1 = y => .., | ^^^^^^^^^ @@ -37,7 +37,7 @@ LL + C(x, 1) => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:49:20 + --> tests/ui/redundant_guards.rs:52:20 | LL | Some(x) if matches!(x, Some(1) if true) => .., | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + Some(Some(1)) if true => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:50:20 + --> tests/ui/redundant_guards.rs:54:20 | LL | Some(x) if matches!(x, Some(1)) => { | ^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + Some(Some(1)) => { | error: redundant guard - --> tests/ui/redundant_guards.rs:54:20 + --> tests/ui/redundant_guards.rs:59:20 | LL | Some(x) if let Some(1) = x => .., | ^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + Some(Some(1)) => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:55:20 + --> tests/ui/redundant_guards.rs:61:20 | LL | Some(x) if x == Some(2) => .., | ^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + Some(Some(2)) => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:56:20 + --> tests/ui/redundant_guards.rs:63:20 | LL | Some(x) if Some(2) == x => .., | ^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL + Some(Some(2)) => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:81:20 + --> tests/ui/redundant_guards.rs:89:20 | LL | B { e } if matches!(e, Some(A(2))) => .., | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL + B { e: Some(A(2)) } => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:118:20 + --> tests/ui/redundant_guards.rs:127:20 | LL | E::A(y) if y == "not from an or pattern" => {}, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL + E::A("not from an or pattern") => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:125:14 + --> tests/ui/redundant_guards.rs:135:14 | LL | x if matches!(x, Some(0)) => .., | ^^^^^^^^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL + Some(0) => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:132:14 + --> tests/ui/redundant_guards.rs:143:14 | LL | i if i == -1 => {}, | ^^^^^^^ @@ -145,7 +145,7 @@ LL + -1 => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:133:14 + --> tests/ui/redundant_guards.rs:145:14 | LL | i if i == 1 => {}, | ^^^^^^ @@ -157,7 +157,7 @@ LL + 1 => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:195:28 + --> tests/ui/redundant_guards.rs:208:28 | LL | Some(ref x) if x == &1 => {}, | ^^^^^^^ @@ -169,7 +169,7 @@ LL + Some(1) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:196:28 + --> tests/ui/redundant_guards.rs:210:28 | LL | Some(ref x) if &1 == x => {}, | ^^^^^^^ @@ -181,7 +181,7 @@ LL + Some(1) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:197:28 + --> tests/ui/redundant_guards.rs:212:28 | LL | Some(ref x) if let &2 = x => {}, | ^^^^^^^^^^ @@ -193,7 +193,7 @@ LL + Some(2) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:198:28 + --> tests/ui/redundant_guards.rs:214:28 | LL | Some(ref x) if matches!(x, &3) => {}, | ^^^^^^^^^^^^^^^ @@ -205,7 +205,7 @@ LL + Some(3) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:218:32 + --> tests/ui/redundant_guards.rs:235:32 | LL | B { ref c, .. } if c == &1 => {}, | ^^^^^^^ @@ -217,7 +217,7 @@ LL + B { c: 1, .. } => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:219:32 + --> tests/ui/redundant_guards.rs:237:32 | LL | B { ref c, .. } if &1 == c => {}, | ^^^^^^^ @@ -229,7 +229,7 @@ LL + B { c: 1, .. } => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:220:32 + --> tests/ui/redundant_guards.rs:239:32 | LL | B { ref c, .. } if let &1 = c => {}, | ^^^^^^^^^^ @@ -241,7 +241,7 @@ LL + B { c: 1, .. } => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:221:32 + --> tests/ui/redundant_guards.rs:241:32 | LL | B { ref c, .. } if matches!(c, &1) => {}, | ^^^^^^^^^^^^^^^ @@ -253,7 +253,7 @@ LL + B { c: 1, .. } => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:231:26 + --> tests/ui/redundant_guards.rs:252:26 | LL | Some(Some(x)) if x.is_empty() => {}, | ^^^^^^^^^^^^ @@ -265,7 +265,7 @@ LL + Some(Some("")) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:242:26 + --> tests/ui/redundant_guards.rs:264:26 | LL | Some(Some(x)) if x.is_empty() => {}, | ^^^^^^^^^^^^ @@ -277,7 +277,7 @@ LL + Some(Some([])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:247:26 + --> tests/ui/redundant_guards.rs:270:26 | LL | Some(Some(x)) if x.is_empty() => {}, | ^^^^^^^^^^^^ @@ -289,7 +289,7 @@ LL + Some(Some([])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:258:26 + --> tests/ui/redundant_guards.rs:282:26 | LL | Some(Some(x)) if x.starts_with(&[]) => {}, | ^^^^^^^^^^^^^^^^^^ @@ -301,7 +301,7 @@ LL + Some(Some([..])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:263:26 + --> tests/ui/redundant_guards.rs:288:26 | LL | Some(Some(x)) if x.starts_with(&[1]) => {}, | ^^^^^^^^^^^^^^^^^^^ @@ -313,7 +313,7 @@ LL + Some(Some([1, ..])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:268:26 + --> tests/ui/redundant_guards.rs:294:26 | LL | Some(Some(x)) if x.starts_with(&[1, 2]) => {}, | ^^^^^^^^^^^^^^^^^^^^^^ @@ -325,7 +325,7 @@ LL + Some(Some([1, 2, ..])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:273:26 + --> tests/ui/redundant_guards.rs:300:26 | LL | Some(Some(x)) if x.ends_with(&[1, 2]) => {}, | ^^^^^^^^^^^^^^^^^^^^ @@ -337,7 +337,7 @@ LL + Some(Some([.., 1, 2])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:295:18 + --> tests/ui/redundant_guards.rs:323:18 | LL | y if y.is_empty() => {}, | ^^^^^^^^^^^^ @@ -349,7 +349,7 @@ LL + "" => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:314:22 + --> tests/ui/redundant_guards.rs:342:22 | LL | y if y.is_empty() => {}, | ^^^^^^^^^^^^ diff --git a/tests/ui/redundant_locals.rs b/tests/ui/redundant_locals.rs index 3e7695106a7f..b66532dd22ee 100644 --- a/tests/ui/redundant_locals.rs +++ b/tests/ui/redundant_locals.rs @@ -11,11 +11,13 @@ fn main() {} fn immutable() { let x = 1; let x = x; + //~^ redundant_locals } fn mutable() { let mut x = 1; let mut x = x; + //~^ redundant_locals } fn upgraded_mutability() { @@ -46,27 +48,35 @@ fn coercion(par: &mut i32) { fn parameter(x: i32) { let x = x; + //~^ redundant_locals } fn many() { let x = 1; let x = x; + //~^ redundant_locals let x = x; + //~^ redundant_locals let x = x; + //~^ redundant_locals let x = x; + //~^ redundant_locals } fn interleaved() { let a = 1; let b = 2; let a = a; + //~^ redundant_locals let b = b; + //~^ redundant_locals } fn block() { { let x = 1; let x = x; + //~^ redundant_locals } } @@ -74,9 +84,11 @@ fn closure() { || { let x = 1; let x = x; + //~^ redundant_locals }; |x: i32| { let x = x; + //~^ redundant_locals }; } @@ -96,6 +108,7 @@ fn inconsequential_drop_order() { { let x = x; + //~^ redundant_locals } } @@ -151,6 +164,7 @@ fn without_drop() { let a = WithoutDrop(1); let b = WithoutDrop(2); let a = a; + //~^ redundant_locals } fn drop_inner() { diff --git a/tests/ui/redundant_locals.stderr b/tests/ui/redundant_locals.stderr index 541b988eefe9..ae3631cdf15f 100644 --- a/tests/ui/redundant_locals.stderr +++ b/tests/ui/redundant_locals.stderr @@ -13,65 +13,29 @@ LL | let x = 1; = help: to override `-D warnings` add `#[allow(clippy::redundant_locals)]` error: redundant redefinition of a binding `x` - --> tests/ui/redundant_locals.rs:18:5 + --> tests/ui/redundant_locals.rs:19:5 | LL | let mut x = x; | ^^^^^^^^^^^^^^ | help: `x` is initially defined here - --> tests/ui/redundant_locals.rs:17:9 + --> tests/ui/redundant_locals.rs:18:9 | LL | let mut x = 1; | ^^^^^ error: redundant redefinition of a binding `x` - --> tests/ui/redundant_locals.rs:48:5 + --> tests/ui/redundant_locals.rs:50:5 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> tests/ui/redundant_locals.rs:47:14 + --> tests/ui/redundant_locals.rs:49:14 | LL | fn parameter(x: i32) { | ^ -error: redundant redefinition of a binding `x` - --> tests/ui/redundant_locals.rs:53:5 - | -LL | let x = x; - | ^^^^^^^^^^ - | -help: `x` is initially defined here - --> tests/ui/redundant_locals.rs:52:9 - | -LL | let x = 1; - | ^ - -error: redundant redefinition of a binding `x` - --> tests/ui/redundant_locals.rs:54:5 - | -LL | let x = x; - | ^^^^^^^^^^ - | -help: `x` is initially defined here - --> tests/ui/redundant_locals.rs:53:9 - | -LL | let x = x; - | ^ - -error: redundant redefinition of a binding `x` - --> tests/ui/redundant_locals.rs:55:5 - | -LL | let x = x; - | ^^^^^^^^^^ - | -help: `x` is initially defined here - --> tests/ui/redundant_locals.rs:54:9 - | -LL | let x = x; - | ^ - error: redundant redefinition of a binding `x` --> tests/ui/redundant_locals.rs:56:5 | @@ -81,89 +45,125 @@ LL | let x = x; help: `x` is initially defined here --> tests/ui/redundant_locals.rs:55:9 | +LL | let x = 1; + | ^ + +error: redundant redefinition of a binding `x` + --> tests/ui/redundant_locals.rs:58:5 + | +LL | let x = x; + | ^^^^^^^^^^ + | +help: `x` is initially defined here + --> tests/ui/redundant_locals.rs:56:9 + | +LL | let x = x; + | ^ + +error: redundant redefinition of a binding `x` + --> tests/ui/redundant_locals.rs:60:5 + | +LL | let x = x; + | ^^^^^^^^^^ + | +help: `x` is initially defined here + --> tests/ui/redundant_locals.rs:58:9 + | +LL | let x = x; + | ^ + +error: redundant redefinition of a binding `x` + --> tests/ui/redundant_locals.rs:62:5 + | +LL | let x = x; + | ^^^^^^^^^^ + | +help: `x` is initially defined here + --> tests/ui/redundant_locals.rs:60:9 + | LL | let x = x; | ^ error: redundant redefinition of a binding `a` - --> tests/ui/redundant_locals.rs:62:5 + --> tests/ui/redundant_locals.rs:69:5 | LL | let a = a; | ^^^^^^^^^^ | help: `a` is initially defined here - --> tests/ui/redundant_locals.rs:60:9 + --> tests/ui/redundant_locals.rs:67:9 | LL | let a = 1; | ^ error: redundant redefinition of a binding `b` - --> tests/ui/redundant_locals.rs:63:5 + --> tests/ui/redundant_locals.rs:71:5 | LL | let b = b; | ^^^^^^^^^^ | help: `b` is initially defined here - --> tests/ui/redundant_locals.rs:61:9 + --> tests/ui/redundant_locals.rs:68:9 | LL | let b = 2; | ^ error: redundant redefinition of a binding `x` - --> tests/ui/redundant_locals.rs:69:9 + --> tests/ui/redundant_locals.rs:78:9 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> tests/ui/redundant_locals.rs:68:13 + --> tests/ui/redundant_locals.rs:77:13 | LL | let x = 1; | ^ error: redundant redefinition of a binding `x` - --> tests/ui/redundant_locals.rs:76:9 + --> tests/ui/redundant_locals.rs:86:9 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> tests/ui/redundant_locals.rs:75:13 + --> tests/ui/redundant_locals.rs:85:13 | LL | let x = 1; | ^ error: redundant redefinition of a binding `x` - --> tests/ui/redundant_locals.rs:79:9 + --> tests/ui/redundant_locals.rs:90:9 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> tests/ui/redundant_locals.rs:78:6 + --> tests/ui/redundant_locals.rs:89:6 | LL | |x: i32| { | ^ error: redundant redefinition of a binding `x` - --> tests/ui/redundant_locals.rs:98:9 + --> tests/ui/redundant_locals.rs:110:9 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> tests/ui/redundant_locals.rs:95:9 + --> tests/ui/redundant_locals.rs:107:9 | LL | let x = 1; | ^ error: redundant redefinition of a binding `a` - --> tests/ui/redundant_locals.rs:153:5 + --> tests/ui/redundant_locals.rs:166:5 | LL | let a = a; | ^^^^^^^^^^ | help: `a` is initially defined here - --> tests/ui/redundant_locals.rs:151:9 + --> tests/ui/redundant_locals.rs:164:9 | LL | let a = WithoutDrop(1); | ^ diff --git a/tests/ui/redundant_pattern_matching_drop_order.fixed b/tests/ui/redundant_pattern_matching_drop_order.fixed index 148eaa4b33a6..1141b5db3ebf 100644 --- a/tests/ui/redundant_pattern_matching_drop_order.fixed +++ b/tests/ui/redundant_pattern_matching_drop_order.fixed @@ -13,49 +13,71 @@ fn main() { // Result if m.lock().is_ok() {} + //~^ redundant_pattern_matching if Err::<(), _>(m.lock().unwrap().0).is_err() {} + //~^ redundant_pattern_matching { if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok() {} + //~^ redundant_pattern_matching } if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok() { + //~^ redundant_pattern_matching } else { } if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok() {} + //~^ redundant_pattern_matching if Err::, _>(()).is_err() {} + //~^ redundant_pattern_matching if Ok::<_, ()>(String::new()).is_ok() {} + //~^ redundant_pattern_matching if Err::<(), _>((String::new(), ())).is_err() {} + //~^ redundant_pattern_matching // Option if Some(m.lock()).is_some() {} + //~^ redundant_pattern_matching if Some(m.lock().unwrap().0).is_some() {} + //~^ redundant_pattern_matching { if None::>.is_none() {} + //~^ redundant_pattern_matching } if None::>.is_none() { + //~^ redundant_pattern_matching } else { } if None::>.is_none() {} + //~^ redundant_pattern_matching if Some(String::new()).is_some() {} + //~^ redundant_pattern_matching if Some((String::new(), ())).is_some() {} + //~^ redundant_pattern_matching // Poll if Ready(m.lock()).is_ready() {} + //~^ redundant_pattern_matching if Ready(m.lock().unwrap().0).is_ready() {} + //~^ redundant_pattern_matching { if Pending::>.is_pending() {} + //~^ redundant_pattern_matching } if Pending::>.is_pending() { + //~^ redundant_pattern_matching } else { } if Pending::>.is_pending() {} + //~^ redundant_pattern_matching if Ready(String::new()).is_ready() {} + //~^ redundant_pattern_matching if Ready((String::new(), ())).is_ready() {} + //~^ redundant_pattern_matching } diff --git a/tests/ui/redundant_pattern_matching_drop_order.rs b/tests/ui/redundant_pattern_matching_drop_order.rs index 5bc06f3cc529..f60ddf468309 100644 --- a/tests/ui/redundant_pattern_matching_drop_order.rs +++ b/tests/ui/redundant_pattern_matching_drop_order.rs @@ -13,49 +13,71 @@ fn main() { // Result if let Ok(_) = m.lock() {} + //~^ redundant_pattern_matching if let Err(_) = Err::<(), _>(m.lock().unwrap().0) {} + //~^ redundant_pattern_matching { if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {} + //~^ redundant_pattern_matching } if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) { + //~^ redundant_pattern_matching } else { } if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {} + //~^ redundant_pattern_matching if let Err(_) = Err::, _>(()) {} + //~^ redundant_pattern_matching if let Ok(_) = Ok::<_, ()>(String::new()) {} + //~^ redundant_pattern_matching if let Err(_) = Err::<(), _>((String::new(), ())) {} + //~^ redundant_pattern_matching // Option if let Some(_) = Some(m.lock()) {} + //~^ redundant_pattern_matching if let Some(_) = Some(m.lock().unwrap().0) {} + //~^ redundant_pattern_matching { if let None = None::> {} + //~^ redundant_pattern_matching } if let None = None::> { + //~^ redundant_pattern_matching } else { } if let None = None::> {} + //~^ redundant_pattern_matching if let Some(_) = Some(String::new()) {} + //~^ redundant_pattern_matching if let Some(_) = Some((String::new(), ())) {} + //~^ redundant_pattern_matching // Poll if let Ready(_) = Ready(m.lock()) {} + //~^ redundant_pattern_matching if let Ready(_) = Ready(m.lock().unwrap().0) {} + //~^ redundant_pattern_matching { if let Pending = Pending::> {} + //~^ redundant_pattern_matching } if let Pending = Pending::> { + //~^ redundant_pattern_matching } else { } if let Pending = Pending::> {} + //~^ redundant_pattern_matching if let Ready(_) = Ready(String::new()) {} + //~^ redundant_pattern_matching if let Ready(_) = Ready((String::new(), ())) {} + //~^ redundant_pattern_matching } diff --git a/tests/ui/redundant_pattern_matching_drop_order.stderr b/tests/ui/redundant_pattern_matching_drop_order.stderr index 1a99cb9fc32b..74462f022f70 100644 --- a/tests/ui/redundant_pattern_matching_drop_order.stderr +++ b/tests/ui/redundant_pattern_matching_drop_order.stderr @@ -10,7 +10,7 @@ LL | if let Ok(_) = m.lock() {} = help: to override `-D warnings` add `#[allow(clippy::redundant_pattern_matching)]` error: redundant pattern matching, consider using `is_err()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:16:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:17:12 | LL | if let Err(_) = Err::<(), _>(m.lock().unwrap().0) {} | -------^^^^^^------------------------------------ help: try: `if Err::<(), _>(m.lock().unwrap().0).is_err()` @@ -19,7 +19,7 @@ LL | if let Err(_) = Err::<(), _>(m.lock().unwrap().0) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_ok()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:19:16 + --> tests/ui/redundant_pattern_matching_drop_order.rs:21:16 | LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {} | -------^^^^^----------------------------------------- help: try: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()` @@ -28,7 +28,7 @@ LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_ok()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:21:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:24:12 | LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) { | -------^^^^^----------------------------------------- help: try: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()` @@ -37,31 +37,31 @@ LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) { = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_ok()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:24:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:28:12 | LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {} | -------^^^^^----------------------------------------- help: try: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:25:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:30:12 | LL | if let Err(_) = Err::, _>(()) {} | -------^^^^^^------------------------------------------ help: try: `if Err::, _>(()).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:27:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:33:12 | LL | if let Ok(_) = Ok::<_, ()>(String::new()) {} | -------^^^^^----------------------------- help: try: `if Ok::<_, ()>(String::new()).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:28:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:35:12 | LL | if let Err(_) = Err::<(), _>((String::new(), ())) {} | -------^^^^^^------------------------------------ help: try: `if Err::<(), _>((String::new(), ())).is_err()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:31:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:39:12 | LL | if let Some(_) = Some(m.lock()) {} | -------^^^^^^^----------------- help: try: `if Some(m.lock()).is_some()` @@ -70,7 +70,7 @@ LL | if let Some(_) = Some(m.lock()) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:32:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:41:12 | LL | if let Some(_) = Some(m.lock().unwrap().0) {} | -------^^^^^^^---------------------------- help: try: `if Some(m.lock().unwrap().0).is_some()` @@ -79,7 +79,7 @@ LL | if let Some(_) = Some(m.lock().unwrap().0) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:35:16 + --> tests/ui/redundant_pattern_matching_drop_order.rs:45:16 | LL | if let None = None::> {} | -------^^^^------------------------------------ help: try: `if None::>.is_none()` @@ -88,7 +88,7 @@ LL | if let None = None::> {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:37:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:48:12 | LL | if let None = None::> { | -------^^^^------------------------------------ help: try: `if None::>.is_none()` @@ -97,25 +97,25 @@ LL | if let None = None::> { = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:41:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:53:12 | LL | if let None = None::> {} | -------^^^^------------------------------------ help: try: `if None::>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:43:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:56:12 | LL | if let Some(_) = Some(String::new()) {} | -------^^^^^^^---------------------- help: try: `if Some(String::new()).is_some()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:44:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:58:12 | LL | if let Some(_) = Some((String::new(), ())) {} | -------^^^^^^^---------------------------- help: try: `if Some((String::new(), ())).is_some()` error: redundant pattern matching, consider using `is_ready()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:47:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:62:12 | LL | if let Ready(_) = Ready(m.lock()) {} | -------^^^^^^^^------------------ help: try: `if Ready(m.lock()).is_ready()` @@ -124,7 +124,7 @@ LL | if let Ready(_) = Ready(m.lock()) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_ready()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:48:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:64:12 | LL | if let Ready(_) = Ready(m.lock().unwrap().0) {} | -------^^^^^^^^----------------------------- help: try: `if Ready(m.lock().unwrap().0).is_ready()` @@ -133,7 +133,7 @@ LL | if let Ready(_) = Ready(m.lock().unwrap().0) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_pending()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:51:16 + --> tests/ui/redundant_pattern_matching_drop_order.rs:68:16 | LL | if let Pending = Pending::> {} | -------^^^^^^^--------------------------------------- help: try: `if Pending::>.is_pending()` @@ -142,7 +142,7 @@ LL | if let Pending = Pending::> {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_pending()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:53:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:71:12 | LL | if let Pending = Pending::> { | -------^^^^^^^--------------------------------------- help: try: `if Pending::>.is_pending()` @@ -151,19 +151,19 @@ LL | if let Pending = Pending::> { = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_pending()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:57:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:76:12 | LL | if let Pending = Pending::> {} | -------^^^^^^^--------------------------------------- help: try: `if Pending::>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:59:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:79:12 | LL | if let Ready(_) = Ready(String::new()) {} | -------^^^^^^^^----------------------- help: try: `if Ready(String::new()).is_ready()` error: redundant pattern matching, consider using `is_ready()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:60:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:81:12 | LL | if let Ready(_) = Ready((String::new(), ())) {} | -------^^^^^^^^----------------------------- help: try: `if Ready((String::new(), ())).is_ready()` diff --git a/tests/ui/redundant_pattern_matching_if_let_true.fixed b/tests/ui/redundant_pattern_matching_if_let_true.fixed index 6d9106789340..980455da2ee7 100644 --- a/tests/ui/redundant_pattern_matching_if_let_true.fixed +++ b/tests/ui/redundant_pattern_matching_if_let_true.fixed @@ -20,18 +20,25 @@ fn main() { let mut k = 5; if k > 1 {} + //~^ redundant_pattern_matching if !(k > 5) {} + //~^ redundant_pattern_matching if k > 1 {} + //~^ redundant_pattern_matching if let (true, true) = (k > 1, k > 2) {} while k > 1 { + //~^ redundant_pattern_matching k += 1; } while condition!() { + //~^ redundant_pattern_matching k += 1; } k > 5; + //~^ redundant_pattern_matching !(k > 5); + //~^ redundant_pattern_matching // Whole loop is from a macro expansion, don't lint: lettrue!(if); lettrue!(while); diff --git a/tests/ui/redundant_pattern_matching_if_let_true.rs b/tests/ui/redundant_pattern_matching_if_let_true.rs index a82e673982a3..9cb0fe2e65f6 100644 --- a/tests/ui/redundant_pattern_matching_if_let_true.rs +++ b/tests/ui/redundant_pattern_matching_if_let_true.rs @@ -20,18 +20,25 @@ fn main() { let mut k = 5; if let true = k > 1 {} + //~^ redundant_pattern_matching if let false = k > 5 {} + //~^ redundant_pattern_matching if let (true) = k > 1 {} + //~^ redundant_pattern_matching if let (true, true) = (k > 1, k > 2) {} while let true = k > 1 { + //~^ redundant_pattern_matching k += 1; } while let true = condition!() { + //~^ redundant_pattern_matching k += 1; } matches!(k > 5, true); + //~^ redundant_pattern_matching matches!(k > 5, false); + //~^ redundant_pattern_matching // Whole loop is from a macro expansion, don't lint: lettrue!(if); lettrue!(while); diff --git a/tests/ui/redundant_pattern_matching_if_let_true.stderr b/tests/ui/redundant_pattern_matching_if_let_true.stderr index 43d5cd07cec7..db8646270609 100644 --- a/tests/ui/redundant_pattern_matching_if_let_true.stderr +++ b/tests/ui/redundant_pattern_matching_if_let_true.stderr @@ -8,37 +8,37 @@ LL | if let true = k > 1 {} = help: to override `-D warnings` add `#[allow(clippy::redundant_pattern_matching)]` error: using `if let` to pattern match a bool - --> tests/ui/redundant_pattern_matching_if_let_true.rs:23:8 + --> tests/ui/redundant_pattern_matching_if_let_true.rs:24:8 | LL | if let false = k > 5 {} | ^^^^^^^^^^^^^^^^^ help: consider using the condition directly: `!(k > 5)` error: using `if let` to pattern match a bool - --> tests/ui/redundant_pattern_matching_if_let_true.rs:24:8 + --> tests/ui/redundant_pattern_matching_if_let_true.rs:26:8 | LL | if let (true) = k > 1 {} | ^^^^^^^^^^^^^^^^^^ help: consider using the condition directly: `k > 1` error: using `if let` to pattern match a bool - --> tests/ui/redundant_pattern_matching_if_let_true.rs:26:11 + --> tests/ui/redundant_pattern_matching_if_let_true.rs:29:11 | LL | while let true = k > 1 { | ^^^^^^^^^^^^^^^^ help: consider using the condition directly: `k > 1` error: using `if let` to pattern match a bool - --> tests/ui/redundant_pattern_matching_if_let_true.rs:29:11 + --> tests/ui/redundant_pattern_matching_if_let_true.rs:33:11 | LL | while let true = condition!() { | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using the condition directly: `condition!()` error: using `matches!` to pattern match a bool - --> tests/ui/redundant_pattern_matching_if_let_true.rs:33:5 + --> tests/ui/redundant_pattern_matching_if_let_true.rs:38:5 | LL | matches!(k > 5, true); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using the condition directly: `k > 5` error: using `matches!` to pattern match a bool - --> tests/ui/redundant_pattern_matching_if_let_true.rs:34:5 + --> tests/ui/redundant_pattern_matching_if_let_true.rs:40:5 | LL | matches!(k > 5, false); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using the condition directly: `!(k > 5)` diff --git a/tests/ui/redundant_pattern_matching_ipaddr.fixed b/tests/ui/redundant_pattern_matching_ipaddr.fixed index 429d33118a58..549c97d9534a 100644 --- a/tests/ui/redundant_pattern_matching_ipaddr.fixed +++ b/tests/ui/redundant_pattern_matching_ipaddr.fixed @@ -13,20 +13,27 @@ use std::net::{Ipv4Addr, Ipv6Addr}; fn main() { let ipaddr: IpAddr = V4(Ipv4Addr::LOCALHOST); if ipaddr.is_ipv4() {} + //~^ redundant_pattern_matching if V4(Ipv4Addr::LOCALHOST).is_ipv4() {} + //~^ redundant_pattern_matching if V6(Ipv6Addr::LOCALHOST).is_ipv6() {} + //~^ redundant_pattern_matching // Issue 6459 if V4(Ipv4Addr::LOCALHOST).is_ipv4() {} + //~^ redundant_pattern_matching // Issue 6459 if V6(Ipv6Addr::LOCALHOST).is_ipv6() {} + //~^ redundant_pattern_matching while V4(Ipv4Addr::LOCALHOST).is_ipv4() {} + //~^ redundant_pattern_matching while V6(Ipv6Addr::LOCALHOST).is_ipv6() {} + //~^ redundant_pattern_matching if V4(Ipv4Addr::LOCALHOST).is_ipv4() {} @@ -45,6 +52,7 @@ fn main() { V6(Ipv6Addr::LOCALHOST).is_ipv4(); let _ = if V4(Ipv4Addr::LOCALHOST).is_ipv4() { + //~^ redundant_pattern_matching true } else { false @@ -53,8 +61,10 @@ fn main() { ipaddr_const(); let _ = if gen_ipaddr().is_ipv4() { + //~^ redundant_pattern_matching 1 } else if gen_ipaddr().is_ipv6() { + //~^ redundant_pattern_matching 2 } else { 3 @@ -67,12 +77,16 @@ fn gen_ipaddr() -> IpAddr { const fn ipaddr_const() { if V4(Ipv4Addr::LOCALHOST).is_ipv4() {} + //~^ redundant_pattern_matching if V6(Ipv6Addr::LOCALHOST).is_ipv6() {} + //~^ redundant_pattern_matching while V4(Ipv4Addr::LOCALHOST).is_ipv4() {} + //~^ redundant_pattern_matching while V6(Ipv6Addr::LOCALHOST).is_ipv6() {} + //~^ redundant_pattern_matching V4(Ipv4Addr::LOCALHOST).is_ipv4(); diff --git a/tests/ui/redundant_pattern_matching_ipaddr.rs b/tests/ui/redundant_pattern_matching_ipaddr.rs index e7136b72c20c..decb1396d56d 100644 --- a/tests/ui/redundant_pattern_matching_ipaddr.rs +++ b/tests/ui/redundant_pattern_matching_ipaddr.rs @@ -13,20 +13,27 @@ use std::net::{Ipv4Addr, Ipv6Addr}; fn main() { let ipaddr: IpAddr = V4(Ipv4Addr::LOCALHOST); if let V4(_) = &ipaddr {} + //~^ redundant_pattern_matching if let V4(_) = V4(Ipv4Addr::LOCALHOST) {} + //~^ redundant_pattern_matching if let V6(_) = V6(Ipv6Addr::LOCALHOST) {} + //~^ redundant_pattern_matching // Issue 6459 if matches!(V4(Ipv4Addr::LOCALHOST), V4(_)) {} + //~^ redundant_pattern_matching // Issue 6459 if matches!(V6(Ipv6Addr::LOCALHOST), V6(_)) {} + //~^ redundant_pattern_matching while let V4(_) = V4(Ipv4Addr::LOCALHOST) {} + //~^ redundant_pattern_matching while let V6(_) = V6(Ipv6Addr::LOCALHOST) {} + //~^ redundant_pattern_matching if V4(Ipv4Addr::LOCALHOST).is_ipv4() {} @@ -37,26 +44,31 @@ fn main() { } match V4(Ipv4Addr::LOCALHOST) { + //~^ redundant_pattern_matching V4(_) => true, V6(_) => false, }; match V4(Ipv4Addr::LOCALHOST) { + //~^ redundant_pattern_matching V4(_) => false, V6(_) => true, }; match V6(Ipv6Addr::LOCALHOST) { + //~^ redundant_pattern_matching V4(_) => false, V6(_) => true, }; match V6(Ipv6Addr::LOCALHOST) { + //~^ redundant_pattern_matching V4(_) => true, V6(_) => false, }; let _ = if let V4(_) = V4(Ipv4Addr::LOCALHOST) { + //~^ redundant_pattern_matching true } else { false @@ -65,8 +77,10 @@ fn main() { ipaddr_const(); let _ = if let V4(_) = gen_ipaddr() { + //~^ redundant_pattern_matching 1 } else if let V6(_) = gen_ipaddr() { + //~^ redundant_pattern_matching 2 } else { 3 @@ -79,19 +93,25 @@ fn gen_ipaddr() -> IpAddr { const fn ipaddr_const() { if let V4(_) = V4(Ipv4Addr::LOCALHOST) {} + //~^ redundant_pattern_matching if let V6(_) = V6(Ipv6Addr::LOCALHOST) {} + //~^ redundant_pattern_matching while let V4(_) = V4(Ipv4Addr::LOCALHOST) {} + //~^ redundant_pattern_matching while let V6(_) = V6(Ipv6Addr::LOCALHOST) {} + //~^ redundant_pattern_matching match V4(Ipv4Addr::LOCALHOST) { + //~^ redundant_pattern_matching V4(_) => true, V6(_) => false, }; match V6(Ipv6Addr::LOCALHOST) { + //~^ redundant_pattern_matching V4(_) => false, V6(_) => true, }; diff --git a/tests/ui/redundant_pattern_matching_ipaddr.stderr b/tests/ui/redundant_pattern_matching_ipaddr.stderr index a4930ad839f9..66d2cecdc0c9 100644 --- a/tests/ui/redundant_pattern_matching_ipaddr.stderr +++ b/tests/ui/redundant_pattern_matching_ipaddr.stderr @@ -8,132 +8,138 @@ LL | if let V4(_) = &ipaddr {} = help: to override `-D warnings` add `#[allow(clippy::redundant_pattern_matching)]` error: redundant pattern matching, consider using `is_ipv4()` - --> tests/ui/redundant_pattern_matching_ipaddr.rs:17:12 + --> tests/ui/redundant_pattern_matching_ipaddr.rs:18:12 | LL | if let V4(_) = V4(Ipv4Addr::LOCALHOST) {} | -------^^^^^-------------------------- help: try: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> tests/ui/redundant_pattern_matching_ipaddr.rs:19:12 + --> tests/ui/redundant_pattern_matching_ipaddr.rs:21:12 | LL | if let V6(_) = V6(Ipv6Addr::LOCALHOST) {} | -------^^^^^-------------------------- help: try: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> tests/ui/redundant_pattern_matching_ipaddr.rs:22:8 + --> tests/ui/redundant_pattern_matching_ipaddr.rs:25:8 | LL | if matches!(V4(Ipv4Addr::LOCALHOST), V4(_)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> tests/ui/redundant_pattern_matching_ipaddr.rs:25:8 + --> tests/ui/redundant_pattern_matching_ipaddr.rs:29:8 | LL | if matches!(V6(Ipv6Addr::LOCALHOST), V6(_)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> tests/ui/redundant_pattern_matching_ipaddr.rs:27:15 + --> tests/ui/redundant_pattern_matching_ipaddr.rs:32:15 | LL | while let V4(_) = V4(Ipv4Addr::LOCALHOST) {} | ----------^^^^^-------------------------- help: try: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> tests/ui/redundant_pattern_matching_ipaddr.rs:29:15 + --> tests/ui/redundant_pattern_matching_ipaddr.rs:35:15 | LL | while let V6(_) = V6(Ipv6Addr::LOCALHOST) {} | ----------^^^^^-------------------------- help: try: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> tests/ui/redundant_pattern_matching_ipaddr.rs:39:5 + --> tests/ui/redundant_pattern_matching_ipaddr.rs:46:5 | LL | / match V4(Ipv4Addr::LOCALHOST) { +LL | | LL | | V4(_) => true, LL | | V6(_) => false, LL | | }; | |_____^ help: try: `V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> tests/ui/redundant_pattern_matching_ipaddr.rs:44:5 + --> tests/ui/redundant_pattern_matching_ipaddr.rs:52:5 | LL | / match V4(Ipv4Addr::LOCALHOST) { +LL | | LL | | V4(_) => false, LL | | V6(_) => true, LL | | }; | |_____^ help: try: `V4(Ipv4Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv6()` - --> tests/ui/redundant_pattern_matching_ipaddr.rs:49:5 + --> tests/ui/redundant_pattern_matching_ipaddr.rs:58:5 | LL | / match V6(Ipv6Addr::LOCALHOST) { +LL | | LL | | V4(_) => false, LL | | V6(_) => true, LL | | }; | |_____^ help: try: `V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> tests/ui/redundant_pattern_matching_ipaddr.rs:54:5 + --> tests/ui/redundant_pattern_matching_ipaddr.rs:64:5 | LL | / match V6(Ipv6Addr::LOCALHOST) { +LL | | LL | | V4(_) => true, LL | | V6(_) => false, LL | | }; | |_____^ help: try: `V6(Ipv6Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv4()` - --> tests/ui/redundant_pattern_matching_ipaddr.rs:59:20 + --> tests/ui/redundant_pattern_matching_ipaddr.rs:70:20 | LL | let _ = if let V4(_) = V4(Ipv4Addr::LOCALHOST) { | -------^^^^^-------------------------- help: try: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv4()` - --> tests/ui/redundant_pattern_matching_ipaddr.rs:67:20 + --> tests/ui/redundant_pattern_matching_ipaddr.rs:79:20 | LL | let _ = if let V4(_) = gen_ipaddr() { | -------^^^^^--------------- help: try: `if gen_ipaddr().is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> tests/ui/redundant_pattern_matching_ipaddr.rs:69:19 + --> tests/ui/redundant_pattern_matching_ipaddr.rs:82:19 | LL | } else if let V6(_) = gen_ipaddr() { | -------^^^^^--------------- help: try: `if gen_ipaddr().is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> tests/ui/redundant_pattern_matching_ipaddr.rs:81:12 + --> tests/ui/redundant_pattern_matching_ipaddr.rs:95:12 | LL | if let V4(_) = V4(Ipv4Addr::LOCALHOST) {} | -------^^^^^-------------------------- help: try: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> tests/ui/redundant_pattern_matching_ipaddr.rs:83:12 + --> tests/ui/redundant_pattern_matching_ipaddr.rs:98:12 | LL | if let V6(_) = V6(Ipv6Addr::LOCALHOST) {} | -------^^^^^-------------------------- help: try: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> tests/ui/redundant_pattern_matching_ipaddr.rs:85:15 + --> tests/ui/redundant_pattern_matching_ipaddr.rs:101:15 | LL | while let V4(_) = V4(Ipv4Addr::LOCALHOST) {} | ----------^^^^^-------------------------- help: try: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> tests/ui/redundant_pattern_matching_ipaddr.rs:87:15 + --> tests/ui/redundant_pattern_matching_ipaddr.rs:104:15 | LL | while let V6(_) = V6(Ipv6Addr::LOCALHOST) {} | ----------^^^^^-------------------------- help: try: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()` error: redundant pattern matching, consider using `is_ipv4()` - --> tests/ui/redundant_pattern_matching_ipaddr.rs:89:5 + --> tests/ui/redundant_pattern_matching_ipaddr.rs:107:5 | LL | / match V4(Ipv4Addr::LOCALHOST) { +LL | | LL | | V4(_) => true, LL | | V6(_) => false, LL | | }; | |_____^ help: try: `V4(Ipv4Addr::LOCALHOST).is_ipv4()` error: redundant pattern matching, consider using `is_ipv6()` - --> tests/ui/redundant_pattern_matching_ipaddr.rs:94:5 + --> tests/ui/redundant_pattern_matching_ipaddr.rs:113:5 | LL | / match V6(Ipv6Addr::LOCALHOST) { +LL | | LL | | V4(_) => false, LL | | V6(_) => true, LL | | }; diff --git a/tests/ui/redundant_pattern_matching_option.fixed b/tests/ui/redundant_pattern_matching_option.fixed index c7e0cd2610f0..5585006dc362 100644 --- a/tests/ui/redundant_pattern_matching_option.fixed +++ b/tests/ui/redundant_pattern_matching_option.fixed @@ -12,10 +12,13 @@ fn issue_11174(boolean: bool, maybe_some: Option) -> bool { maybe_some.is_none() && (!boolean) + //~^ redundant_pattern_matching } fn issue_11174_edge_cases(boolean: bool, boolean2: bool, maybe_some: Option) { let _ = maybe_some.is_none() && (boolean || boolean2); // guard needs parentheses + // + //~^^ redundant_pattern_matching let _ = match maybe_some { // can't use `matches!` here // because `expr` metavars in macros don't allow let exprs @@ -30,23 +33,30 @@ fn issue_11174_edge_cases(boolean: bool, boolean2: bool, maybe_some: Option.is_none() {} + //~^ redundant_pattern_matching if Some(42).is_some() {} + //~^ redundant_pattern_matching if Some(42).is_some() { + //~^ redundant_pattern_matching foo(); } else { bar(); } while Some(42).is_some() {} + //~^ redundant_pattern_matching while Some(42).is_none() {} + //~^ redundant_pattern_matching while None::<()>.is_none() {} + //~^ redundant_pattern_matching let mut v = vec![1, 2, 3]; while v.pop().is_some() { + //~^ redundant_pattern_matching foo(); } @@ -62,20 +72,24 @@ fn main() { let opt = Some(false); let _ = if opt.is_some() { true } else { false }; + //~^ redundant_pattern_matching issue6067(); issue10726(); issue10803(); let _ = if gen_opt().is_some() { + //~^ redundant_pattern_matching 1 } else if gen_opt().is_none() { + //~^ redundant_pattern_matching 2 } else { 3 }; if gen_opt().is_some() {} + //~^ redundant_pattern_matching } fn gen_opt() -> Option<()> { @@ -91,12 +105,16 @@ fn bar() {} // so the following should be linted. const fn issue6067() { if Some(42).is_some() {} + //~^ redundant_pattern_matching if None::<()>.is_none() {} + //~^ redundant_pattern_matching while Some(42).is_some() {} + //~^ redundant_pattern_matching while None::<()>.is_none() {} + //~^ redundant_pattern_matching Some(42).is_some(); @@ -106,7 +124,9 @@ const fn issue6067() { #[allow(clippy::deref_addrof, dead_code, clippy::needless_borrow)] fn issue7921() { if (&None::<()>).is_none() {} + //~^ redundant_pattern_matching if (&None::<()>).is_none() {} + //~^ redundant_pattern_matching } fn issue10726() { @@ -131,8 +151,10 @@ fn issue10803() { let x = Some(42); let _ = x.is_some(); + //~^ redundant_pattern_matching let _ = x.is_none(); + //~^ redundant_pattern_matching // Don't lint let _ = matches!(x, Some(16)); @@ -143,5 +165,6 @@ fn issue13902() { let p = &raw const x; unsafe { let _ = (*p).is_none(); + //~^ redundant_pattern_matching } } diff --git a/tests/ui/redundant_pattern_matching_option.rs b/tests/ui/redundant_pattern_matching_option.rs index 6d9a9f7f9428..581a432f38e1 100644 --- a/tests/ui/redundant_pattern_matching_option.rs +++ b/tests/ui/redundant_pattern_matching_option.rs @@ -12,10 +12,13 @@ fn issue_11174(boolean: bool, maybe_some: Option) -> bool { matches!(maybe_some, None if !boolean) + //~^ redundant_pattern_matching } fn issue_11174_edge_cases(boolean: bool, boolean2: bool, maybe_some: Option) { let _ = matches!(maybe_some, None if boolean || boolean2); // guard needs parentheses + // + //~^^ redundant_pattern_matching let _ = match maybe_some { // can't use `matches!` here // because `expr` metavars in macros don't allow let exprs @@ -30,23 +33,30 @@ fn issue_11174_edge_cases(boolean: bool, boolean2: bool, maybe_some: Option {} + //~^ redundant_pattern_matching if let Some(_) = Some(42) {} + //~^ redundant_pattern_matching if let Some(_) = Some(42) { + //~^ redundant_pattern_matching foo(); } else { bar(); } while let Some(_) = Some(42) {} + //~^ redundant_pattern_matching while let None = Some(42) {} + //~^ redundant_pattern_matching while let None = None::<()> {} + //~^ redundant_pattern_matching let mut v = vec![1, 2, 3]; while let Some(_) = v.pop() { + //~^ redundant_pattern_matching foo(); } @@ -55,36 +65,43 @@ fn main() { if Some(42).is_some() {} match Some(42) { + //~^ redundant_pattern_matching Some(_) => true, None => false, }; match None::<()> { + //~^ redundant_pattern_matching Some(_) => false, None => true, }; let _ = match None::<()> { + //~^ redundant_pattern_matching Some(_) => false, None => true, }; let opt = Some(false); let _ = if let Some(_) = opt { true } else { false }; + //~^ redundant_pattern_matching issue6067(); issue10726(); issue10803(); let _ = if let Some(_) = gen_opt() { + //~^ redundant_pattern_matching 1 } else if let None = gen_opt() { + //~^ redundant_pattern_matching 2 } else { 3 }; if let Some(..) = gen_opt() {} + //~^ redundant_pattern_matching } fn gen_opt() -> Option<()> { @@ -100,19 +117,25 @@ fn bar() {} // so the following should be linted. const fn issue6067() { if let Some(_) = Some(42) {} + //~^ redundant_pattern_matching if let None = None::<()> {} + //~^ redundant_pattern_matching while let Some(_) = Some(42) {} + //~^ redundant_pattern_matching while let None = None::<()> {} + //~^ redundant_pattern_matching match Some(42) { + //~^ redundant_pattern_matching Some(_) => true, None => false, }; match None::<()> { + //~^ redundant_pattern_matching Some(_) => false, None => true, }; @@ -121,28 +144,34 @@ const fn issue6067() { #[allow(clippy::deref_addrof, dead_code, clippy::needless_borrow)] fn issue7921() { if let None = *(&None::<()>) {} + //~^ redundant_pattern_matching if let None = *&None::<()> {} + //~^ redundant_pattern_matching } fn issue10726() { let x = Some(42); match x { + //~^ redundant_pattern_matching Some(_) => true, _ => false, }; match x { + //~^ redundant_pattern_matching None => true, _ => false, }; match x { + //~^ redundant_pattern_matching Some(_) => false, _ => true, }; match x { + //~^ redundant_pattern_matching None => false, _ => true, }; @@ -158,8 +187,10 @@ fn issue10803() { let x = Some(42); let _ = matches!(x, Some(_)); + //~^ redundant_pattern_matching let _ = matches!(x, None); + //~^ redundant_pattern_matching // Don't lint let _ = matches!(x, Some(16)); @@ -170,5 +201,6 @@ fn issue13902() { let p = &raw const x; unsafe { let _ = matches!(*p, None); + //~^ redundant_pattern_matching } } diff --git a/tests/ui/redundant_pattern_matching_option.stderr b/tests/ui/redundant_pattern_matching_option.stderr index 34d80f5ca782..681602567d2f 100644 --- a/tests/ui/redundant_pattern_matching_option.stderr +++ b/tests/ui/redundant_pattern_matching_option.stderr @@ -8,209 +8,218 @@ LL | matches!(maybe_some, None if !boolean) = help: to override `-D warnings` add `#[allow(clippy::redundant_pattern_matching)]` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:18:13 + --> tests/ui/redundant_pattern_matching_option.rs:19:13 | LL | let _ = matches!(maybe_some, None if boolean || boolean2); // guard needs parentheses | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `maybe_some.is_none() && (boolean || boolean2)` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:32:12 + --> tests/ui/redundant_pattern_matching_option.rs:35:12 | LL | if let None = None::<()> {} | -------^^^^------------- help: try: `if None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:34:12 + --> tests/ui/redundant_pattern_matching_option.rs:38:12 | LL | if let Some(_) = Some(42) {} | -------^^^^^^^----------- help: try: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:36:12 + --> tests/ui/redundant_pattern_matching_option.rs:41:12 | LL | if let Some(_) = Some(42) { | -------^^^^^^^----------- help: try: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:42:15 + --> tests/ui/redundant_pattern_matching_option.rs:48:15 | LL | while let Some(_) = Some(42) {} | ----------^^^^^^^----------- help: try: `while Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:44:15 + --> tests/ui/redundant_pattern_matching_option.rs:51:15 | LL | while let None = Some(42) {} | ----------^^^^----------- help: try: `while Some(42).is_none()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:46:15 + --> tests/ui/redundant_pattern_matching_option.rs:54:15 | LL | while let None = None::<()> {} | ----------^^^^------------- help: try: `while None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:49:15 + --> tests/ui/redundant_pattern_matching_option.rs:58:15 | LL | while let Some(_) = v.pop() { | ----------^^^^^^^---------- help: try: `while v.pop().is_some()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:57:5 + --> tests/ui/redundant_pattern_matching_option.rs:67:5 | LL | / match Some(42) { +LL | | LL | | Some(_) => true, LL | | None => false, LL | | }; | |_____^ help: try: `Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:62:5 + --> tests/ui/redundant_pattern_matching_option.rs:73:5 | LL | / match None::<()> { +LL | | LL | | Some(_) => false, LL | | None => true, LL | | }; | |_____^ help: try: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:67:13 + --> tests/ui/redundant_pattern_matching_option.rs:79:13 | LL | let _ = match None::<()> { | _____________^ +LL | | LL | | Some(_) => false, LL | | None => true, LL | | }; | |_____^ help: try: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:73:20 + --> tests/ui/redundant_pattern_matching_option.rs:86:20 | LL | let _ = if let Some(_) = opt { true } else { false }; | -------^^^^^^^------ help: try: `if opt.is_some()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:79:20 + --> tests/ui/redundant_pattern_matching_option.rs:93:20 | LL | let _ = if let Some(_) = gen_opt() { | -------^^^^^^^------------ help: try: `if gen_opt().is_some()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:81:19 + --> tests/ui/redundant_pattern_matching_option.rs:96:19 | LL | } else if let None = gen_opt() { | -------^^^^------------ help: try: `if gen_opt().is_none()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:87:12 + --> tests/ui/redundant_pattern_matching_option.rs:103:12 | LL | if let Some(..) = gen_opt() {} | -------^^^^^^^^------------ help: try: `if gen_opt().is_some()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:102:12 + --> tests/ui/redundant_pattern_matching_option.rs:119:12 | LL | if let Some(_) = Some(42) {} | -------^^^^^^^----------- help: try: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:104:12 + --> tests/ui/redundant_pattern_matching_option.rs:122:12 | LL | if let None = None::<()> {} | -------^^^^------------- help: try: `if None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:106:15 + --> tests/ui/redundant_pattern_matching_option.rs:125:15 | LL | while let Some(_) = Some(42) {} | ----------^^^^^^^----------- help: try: `while Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:108:15 + --> tests/ui/redundant_pattern_matching_option.rs:128:15 | LL | while let None = None::<()> {} | ----------^^^^------------- help: try: `while None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:110:5 + --> tests/ui/redundant_pattern_matching_option.rs:131:5 | LL | / match Some(42) { +LL | | LL | | Some(_) => true, LL | | None => false, LL | | }; | |_____^ help: try: `Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:115:5 + --> tests/ui/redundant_pattern_matching_option.rs:137:5 | LL | / match None::<()> { +LL | | LL | | Some(_) => false, LL | | None => true, LL | | }; | |_____^ help: try: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:123:12 + --> tests/ui/redundant_pattern_matching_option.rs:146:12 | LL | if let None = *(&None::<()>) {} | -------^^^^----------------- help: try: `if (&None::<()>).is_none()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:124:12 + --> tests/ui/redundant_pattern_matching_option.rs:148:12 | LL | if let None = *&None::<()> {} | -------^^^^--------------- help: try: `if (&None::<()>).is_none()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:130:5 + --> tests/ui/redundant_pattern_matching_option.rs:155:5 | LL | / match x { +LL | | LL | | Some(_) => true, LL | | _ => false, LL | | }; | |_____^ help: try: `x.is_some()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:135:5 + --> tests/ui/redundant_pattern_matching_option.rs:161:5 | LL | / match x { +LL | | LL | | None => true, LL | | _ => false, LL | | }; | |_____^ help: try: `x.is_none()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:140:5 + --> tests/ui/redundant_pattern_matching_option.rs:167:5 | LL | / match x { +LL | | LL | | Some(_) => false, LL | | _ => true, LL | | }; | |_____^ help: try: `x.is_none()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:145:5 + --> tests/ui/redundant_pattern_matching_option.rs:173:5 | LL | / match x { +LL | | LL | | None => false, LL | | _ => true, LL | | }; | |_____^ help: try: `x.is_some()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_option.rs:160:13 + --> tests/ui/redundant_pattern_matching_option.rs:189:13 | LL | let _ = matches!(x, Some(_)); | ^^^^^^^^^^^^^^^^^^^^ help: try: `x.is_some()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:162:13 + --> tests/ui/redundant_pattern_matching_option.rs:192:13 | LL | let _ = matches!(x, None); | ^^^^^^^^^^^^^^^^^ help: try: `x.is_none()` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_option.rs:172:17 + --> tests/ui/redundant_pattern_matching_option.rs:203:17 | LL | let _ = matches!(*p, None); | ^^^^^^^^^^^^^^^^^^ help: try: `(*p).is_none()` diff --git a/tests/ui/redundant_pattern_matching_poll.fixed b/tests/ui/redundant_pattern_matching_poll.fixed index 08d83f87e4c3..c8e18e8676f2 100644 --- a/tests/ui/redundant_pattern_matching_poll.fixed +++ b/tests/ui/redundant_pattern_matching_poll.fixed @@ -13,10 +13,13 @@ use std::task::Poll::{self, Pending, Ready}; fn main() { if Pending::<()>.is_pending() {} + //~^ redundant_pattern_matching if Ready(42).is_ready() {} + //~^ redundant_pattern_matching if Ready(42).is_ready() { + //~^ redundant_pattern_matching foo(); } else { bar(); @@ -24,15 +27,20 @@ fn main() { // Issue 6459 if Ready(42).is_ready() {} + //~^ redundant_pattern_matching // Issue 6459 if Pending::<()>.is_pending() {} + //~^ redundant_pattern_matching while Ready(42).is_ready() {} + //~^ redundant_pattern_matching while Ready(42).is_pending() {} + //~^ redundant_pattern_matching while Pending::<()>.is_pending() {} + //~^ redundant_pattern_matching if Pending::.is_pending() {} @@ -46,12 +54,15 @@ fn main() { let poll = Ready(false); let _ = if poll.is_ready() { true } else { false }; + //~^ redundant_pattern_matching poll_const(); let _ = if gen_poll().is_ready() { + //~^ redundant_pattern_matching 1 } else if gen_poll().is_pending() { + //~^ redundant_pattern_matching 2 } else { 3 @@ -68,12 +79,16 @@ fn bar() {} const fn poll_const() { if Ready(42).is_ready() {} + //~^ redundant_pattern_matching if Pending::<()>.is_pending() {} + //~^ redundant_pattern_matching while Ready(42).is_ready() {} + //~^ redundant_pattern_matching while Pending::<()>.is_pending() {} + //~^ redundant_pattern_matching Ready(42).is_ready(); diff --git a/tests/ui/redundant_pattern_matching_poll.rs b/tests/ui/redundant_pattern_matching_poll.rs index 7bc2b3be4d34..727503d21a54 100644 --- a/tests/ui/redundant_pattern_matching_poll.rs +++ b/tests/ui/redundant_pattern_matching_poll.rs @@ -13,10 +13,13 @@ use std::task::Poll::{self, Pending, Ready}; fn main() { if let Pending = Pending::<()> {} + //~^ redundant_pattern_matching if let Ready(_) = Ready(42) {} + //~^ redundant_pattern_matching if let Ready(_) = Ready(42) { + //~^ redundant_pattern_matching foo(); } else { bar(); @@ -24,43 +27,54 @@ fn main() { // Issue 6459 if matches!(Ready(42), Ready(_)) {} + //~^ redundant_pattern_matching // Issue 6459 if matches!(Pending::<()>, Pending) {} + //~^ redundant_pattern_matching while let Ready(_) = Ready(42) {} + //~^ redundant_pattern_matching while let Pending = Ready(42) {} + //~^ redundant_pattern_matching while let Pending = Pending::<()> {} + //~^ redundant_pattern_matching if Pending::.is_pending() {} if Ready(42).is_ready() {} match Ready(42) { + //~^ redundant_pattern_matching Ready(_) => true, Pending => false, }; match Pending::<()> { + //~^ redundant_pattern_matching Ready(_) => false, Pending => true, }; let _ = match Pending::<()> { + //~^ redundant_pattern_matching Ready(_) => false, Pending => true, }; let poll = Ready(false); let _ = if let Ready(_) = poll { true } else { false }; + //~^ redundant_pattern_matching poll_const(); let _ = if let Ready(_) = gen_poll() { + //~^ redundant_pattern_matching 1 } else if let Pending = gen_poll() { + //~^ redundant_pattern_matching 2 } else { 3 @@ -77,19 +91,25 @@ fn bar() {} const fn poll_const() { if let Ready(_) = Ready(42) {} + //~^ redundant_pattern_matching if let Pending = Pending::<()> {} + //~^ redundant_pattern_matching while let Ready(_) = Ready(42) {} + //~^ redundant_pattern_matching while let Pending = Pending::<()> {} + //~^ redundant_pattern_matching match Ready(42) { + //~^ redundant_pattern_matching Ready(_) => true, Pending => false, }; match Pending::<()> { + //~^ redundant_pattern_matching Ready(_) => false, Pending => true, }; diff --git a/tests/ui/redundant_pattern_matching_poll.stderr b/tests/ui/redundant_pattern_matching_poll.stderr index 2b0f087fb993..5f659184f7b3 100644 --- a/tests/ui/redundant_pattern_matching_poll.stderr +++ b/tests/ui/redundant_pattern_matching_poll.stderr @@ -8,130 +8,135 @@ LL | if let Pending = Pending::<()> {} = help: to override `-D warnings` add `#[allow(clippy::redundant_pattern_matching)]` error: redundant pattern matching, consider using `is_ready()` - --> tests/ui/redundant_pattern_matching_poll.rs:17:12 + --> tests/ui/redundant_pattern_matching_poll.rs:18:12 | LL | if let Ready(_) = Ready(42) {} | -------^^^^^^^^------------ help: try: `if Ready(42).is_ready()` error: redundant pattern matching, consider using `is_ready()` - --> tests/ui/redundant_pattern_matching_poll.rs:19:12 + --> tests/ui/redundant_pattern_matching_poll.rs:21:12 | LL | if let Ready(_) = Ready(42) { | -------^^^^^^^^------------ help: try: `if Ready(42).is_ready()` error: redundant pattern matching, consider using `is_ready()` - --> tests/ui/redundant_pattern_matching_poll.rs:26:8 + --> tests/ui/redundant_pattern_matching_poll.rs:29:8 | LL | if matches!(Ready(42), Ready(_)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> tests/ui/redundant_pattern_matching_poll.rs:29:8 + --> tests/ui/redundant_pattern_matching_poll.rs:33:8 | LL | if matches!(Pending::<()>, Pending) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> tests/ui/redundant_pattern_matching_poll.rs:31:15 + --> tests/ui/redundant_pattern_matching_poll.rs:36:15 | LL | while let Ready(_) = Ready(42) {} | ----------^^^^^^^^------------ help: try: `while Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> tests/ui/redundant_pattern_matching_poll.rs:33:15 + --> tests/ui/redundant_pattern_matching_poll.rs:39:15 | LL | while let Pending = Ready(42) {} | ----------^^^^^^^------------ help: try: `while Ready(42).is_pending()` error: redundant pattern matching, consider using `is_pending()` - --> tests/ui/redundant_pattern_matching_poll.rs:35:15 + --> tests/ui/redundant_pattern_matching_poll.rs:42:15 | LL | while let Pending = Pending::<()> {} | ----------^^^^^^^---------------- help: try: `while Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> tests/ui/redundant_pattern_matching_poll.rs:41:5 + --> tests/ui/redundant_pattern_matching_poll.rs:49:5 | LL | / match Ready(42) { +LL | | LL | | Ready(_) => true, LL | | Pending => false, LL | | }; | |_____^ help: try: `Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> tests/ui/redundant_pattern_matching_poll.rs:46:5 + --> tests/ui/redundant_pattern_matching_poll.rs:55:5 | LL | / match Pending::<()> { +LL | | LL | | Ready(_) => false, LL | | Pending => true, LL | | }; | |_____^ help: try: `Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_pending()` - --> tests/ui/redundant_pattern_matching_poll.rs:51:13 + --> tests/ui/redundant_pattern_matching_poll.rs:61:13 | LL | let _ = match Pending::<()> { | _____________^ +LL | | LL | | Ready(_) => false, LL | | Pending => true, LL | | }; | |_____^ help: try: `Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> tests/ui/redundant_pattern_matching_poll.rs:57:20 + --> tests/ui/redundant_pattern_matching_poll.rs:68:20 | LL | let _ = if let Ready(_) = poll { true } else { false }; | -------^^^^^^^^------- help: try: `if poll.is_ready()` error: redundant pattern matching, consider using `is_ready()` - --> tests/ui/redundant_pattern_matching_poll.rs:61:20 + --> tests/ui/redundant_pattern_matching_poll.rs:73:20 | LL | let _ = if let Ready(_) = gen_poll() { | -------^^^^^^^^------------- help: try: `if gen_poll().is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> tests/ui/redundant_pattern_matching_poll.rs:63:19 + --> tests/ui/redundant_pattern_matching_poll.rs:76:19 | LL | } else if let Pending = gen_poll() { | -------^^^^^^^------------- help: try: `if gen_poll().is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> tests/ui/redundant_pattern_matching_poll.rs:79:12 + --> tests/ui/redundant_pattern_matching_poll.rs:93:12 | LL | if let Ready(_) = Ready(42) {} | -------^^^^^^^^------------ help: try: `if Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> tests/ui/redundant_pattern_matching_poll.rs:81:12 + --> tests/ui/redundant_pattern_matching_poll.rs:96:12 | LL | if let Pending = Pending::<()> {} | -------^^^^^^^---------------- help: try: `if Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> tests/ui/redundant_pattern_matching_poll.rs:83:15 + --> tests/ui/redundant_pattern_matching_poll.rs:99:15 | LL | while let Ready(_) = Ready(42) {} | ----------^^^^^^^^------------ help: try: `while Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> tests/ui/redundant_pattern_matching_poll.rs:85:15 + --> tests/ui/redundant_pattern_matching_poll.rs:102:15 | LL | while let Pending = Pending::<()> {} | ----------^^^^^^^---------------- help: try: `while Pending::<()>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> tests/ui/redundant_pattern_matching_poll.rs:87:5 + --> tests/ui/redundant_pattern_matching_poll.rs:105:5 | LL | / match Ready(42) { +LL | | LL | | Ready(_) => true, LL | | Pending => false, LL | | }; | |_____^ help: try: `Ready(42).is_ready()` error: redundant pattern matching, consider using `is_pending()` - --> tests/ui/redundant_pattern_matching_poll.rs:92:5 + --> tests/ui/redundant_pattern_matching_poll.rs:111:5 | LL | / match Pending::<()> { +LL | | LL | | Ready(_) => false, LL | | Pending => true, LL | | }; diff --git a/tests/ui/redundant_pattern_matching_result.fixed b/tests/ui/redundant_pattern_matching_result.fixed index 9571aaee7424..115879608314 100644 --- a/tests/ui/redundant_pattern_matching_result.fixed +++ b/tests/ui/redundant_pattern_matching_result.fixed @@ -13,14 +13,19 @@ fn main() { let result: Result = Err(5); if result.is_ok() {} + //~^ redundant_pattern_matching if Ok::(42).is_ok() {} + //~^ redundant_pattern_matching if Err::(42).is_err() {} + //~^ redundant_pattern_matching while Ok::(10).is_ok() {} + //~^ redundant_pattern_matching while Ok::(10).is_err() {} + //~^ redundant_pattern_matching if Ok::(42).is_ok() {} @@ -39,6 +44,7 @@ fn main() { Err::(42).is_ok(); let _ = if Ok::(4).is_ok() { true } else { false }; + //~^ redundant_pattern_matching issue5504(); issue6067(); @@ -47,8 +53,10 @@ fn main() { issue10803(); let _ = if gen_res().is_ok() { + //~^ redundant_pattern_matching 1 } else if gen_res().is_err() { + //~^ redundant_pattern_matching 2 } else { 3 @@ -72,14 +80,18 @@ fn issue5504() { fn try_result_opt() -> Result { while r#try!(result_opt()).is_some() {} + //~^ redundant_pattern_matching if r#try!(result_opt()).is_some() {} + //~^ redundant_pattern_matching Ok(42) } try_result_opt(); if m!().is_some() {} + //~^ redundant_pattern_matching while m!().is_some() {} + //~^ redundant_pattern_matching } fn issue6065() { @@ -98,12 +110,16 @@ fn issue6065() { // so the following should be linted. const fn issue6067() { if Ok::(42).is_ok() {} + //~^ redundant_pattern_matching if Err::(42).is_err() {} + //~^ redundant_pattern_matching while Ok::(10).is_ok() {} + //~^ redundant_pattern_matching while Ok::(10).is_err() {} + //~^ redundant_pattern_matching Ok::(42).is_ok(); @@ -139,8 +155,10 @@ fn issue10803() { let x: Result = Ok(42); let _ = x.is_ok(); + //~^ redundant_pattern_matching let _ = x.is_err(); + //~^ redundant_pattern_matching // Don't lint let _ = matches!(x, Ok(16)); diff --git a/tests/ui/redundant_pattern_matching_result.rs b/tests/ui/redundant_pattern_matching_result.rs index 4fc65aa70b54..35f8f91b3152 100644 --- a/tests/ui/redundant_pattern_matching_result.rs +++ b/tests/ui/redundant_pattern_matching_result.rs @@ -13,14 +13,19 @@ fn main() { let result: Result = Err(5); if let Ok(_) = &result {} + //~^ redundant_pattern_matching if let Ok(_) = Ok::(42) {} + //~^ redundant_pattern_matching if let Err(_) = Err::(42) {} + //~^ redundant_pattern_matching while let Ok(_) = Ok::(10) {} + //~^ redundant_pattern_matching while let Err(_) = Ok::(10) {} + //~^ redundant_pattern_matching if Ok::(42).is_ok() {} @@ -31,26 +36,31 @@ fn main() { } match Ok::(42) { + //~^ redundant_pattern_matching Ok(_) => true, Err(_) => false, }; match Ok::(42) { + //~^ redundant_pattern_matching Ok(_) => false, Err(_) => true, }; match Err::(42) { + //~^ redundant_pattern_matching Ok(_) => false, Err(_) => true, }; match Err::(42) { + //~^ redundant_pattern_matching Ok(_) => true, Err(_) => false, }; let _ = if let Ok(_) = Ok::(4) { true } else { false }; + //~^ redundant_pattern_matching issue5504(); issue6067(); @@ -59,8 +69,10 @@ fn main() { issue10803(); let _ = if let Ok(_) = gen_res() { + //~^ redundant_pattern_matching 1 } else if let Err(_) = gen_res() { + //~^ redundant_pattern_matching 2 } else { 3 @@ -84,14 +96,18 @@ fn issue5504() { fn try_result_opt() -> Result { while let Some(_) = r#try!(result_opt()) {} + //~^ redundant_pattern_matching if let Some(_) = r#try!(result_opt()) {} + //~^ redundant_pattern_matching Ok(42) } try_result_opt(); if let Some(_) = m!() {} + //~^ redundant_pattern_matching while let Some(_) = m!() {} + //~^ redundant_pattern_matching } fn issue6065() { @@ -110,19 +126,25 @@ fn issue6065() { // so the following should be linted. const fn issue6067() { if let Ok(_) = Ok::(42) {} + //~^ redundant_pattern_matching if let Err(_) = Err::(42) {} + //~^ redundant_pattern_matching while let Ok(_) = Ok::(10) {} + //~^ redundant_pattern_matching while let Err(_) = Ok::(10) {} + //~^ redundant_pattern_matching match Ok::(42) { + //~^ redundant_pattern_matching Ok(_) => true, Err(_) => false, }; match Err::(42) { + //~^ redundant_pattern_matching Ok(_) => false, Err(_) => true, }; @@ -133,21 +155,25 @@ fn issue10726() { let x: Result = Ok(42); match x { + //~^ redundant_pattern_matching Ok(_) => true, _ => false, }; match x { + //~^ redundant_pattern_matching Ok(_) => false, _ => true, }; match x { + //~^ redundant_pattern_matching Err(_) => true, _ => false, }; match x { + //~^ redundant_pattern_matching Err(_) => false, _ => true, }; @@ -169,8 +195,10 @@ fn issue10803() { let x: Result = Ok(42); let _ = matches!(x, Ok(_)); + //~^ redundant_pattern_matching let _ = matches!(x, Err(_)); + //~^ redundant_pattern_matching // Don't lint let _ = matches!(x, Ok(16)); diff --git a/tests/ui/redundant_pattern_matching_result.stderr b/tests/ui/redundant_pattern_matching_result.stderr index 991e6225ecb6..4f78b95356c2 100644 --- a/tests/ui/redundant_pattern_matching_result.stderr +++ b/tests/ui/redundant_pattern_matching_result.stderr @@ -8,193 +8,203 @@ LL | if let Ok(_) = &result {} = help: to override `-D warnings` add `#[allow(clippy::redundant_pattern_matching)]` error: redundant pattern matching, consider using `is_ok()` - --> tests/ui/redundant_pattern_matching_result.rs:17:12 + --> tests/ui/redundant_pattern_matching_result.rs:18:12 | LL | if let Ok(_) = Ok::(42) {} | -------^^^^^--------------------- help: try: `if Ok::(42).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> tests/ui/redundant_pattern_matching_result.rs:19:12 + --> tests/ui/redundant_pattern_matching_result.rs:21:12 | LL | if let Err(_) = Err::(42) {} | -------^^^^^^---------------------- help: try: `if Err::(42).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> tests/ui/redundant_pattern_matching_result.rs:21:15 + --> tests/ui/redundant_pattern_matching_result.rs:24:15 | LL | while let Ok(_) = Ok::(10) {} | ----------^^^^^--------------------- help: try: `while Ok::(10).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> tests/ui/redundant_pattern_matching_result.rs:23:15 + --> tests/ui/redundant_pattern_matching_result.rs:27:15 | LL | while let Err(_) = Ok::(10) {} | ----------^^^^^^--------------------- help: try: `while Ok::(10).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> tests/ui/redundant_pattern_matching_result.rs:33:5 + --> tests/ui/redundant_pattern_matching_result.rs:38:5 | LL | / match Ok::(42) { +LL | | LL | | Ok(_) => true, LL | | Err(_) => false, LL | | }; | |_____^ help: try: `Ok::(42).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> tests/ui/redundant_pattern_matching_result.rs:38:5 + --> tests/ui/redundant_pattern_matching_result.rs:44:5 | LL | / match Ok::(42) { +LL | | LL | | Ok(_) => false, LL | | Err(_) => true, LL | | }; | |_____^ help: try: `Ok::(42).is_err()` error: redundant pattern matching, consider using `is_err()` - --> tests/ui/redundant_pattern_matching_result.rs:43:5 + --> tests/ui/redundant_pattern_matching_result.rs:50:5 | LL | / match Err::(42) { +LL | | LL | | Ok(_) => false, LL | | Err(_) => true, LL | | }; | |_____^ help: try: `Err::(42).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> tests/ui/redundant_pattern_matching_result.rs:48:5 + --> tests/ui/redundant_pattern_matching_result.rs:56:5 | LL | / match Err::(42) { +LL | | LL | | Ok(_) => true, LL | | Err(_) => false, LL | | }; | |_____^ help: try: `Err::(42).is_ok()` error: redundant pattern matching, consider using `is_ok()` - --> tests/ui/redundant_pattern_matching_result.rs:53:20 + --> tests/ui/redundant_pattern_matching_result.rs:62:20 | LL | let _ = if let Ok(_) = Ok::(4) { true } else { false }; | -------^^^^^--------------------- help: try: `if Ok::(4).is_ok()` error: redundant pattern matching, consider using `is_ok()` - --> tests/ui/redundant_pattern_matching_result.rs:61:20 + --> tests/ui/redundant_pattern_matching_result.rs:71:20 | LL | let _ = if let Ok(_) = gen_res() { | -------^^^^^------------ help: try: `if gen_res().is_ok()` error: redundant pattern matching, consider using `is_err()` - --> tests/ui/redundant_pattern_matching_result.rs:63:19 + --> tests/ui/redundant_pattern_matching_result.rs:74:19 | LL | } else if let Err(_) = gen_res() { | -------^^^^^^------------ help: try: `if gen_res().is_err()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_result.rs:86:19 + --> tests/ui/redundant_pattern_matching_result.rs:98:19 | LL | while let Some(_) = r#try!(result_opt()) {} | ----------^^^^^^^----------------------- help: try: `while r#try!(result_opt()).is_some()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_result.rs:87:16 + --> tests/ui/redundant_pattern_matching_result.rs:100:16 | LL | if let Some(_) = r#try!(result_opt()) {} | -------^^^^^^^----------------------- help: try: `if r#try!(result_opt()).is_some()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_result.rs:93:12 + --> tests/ui/redundant_pattern_matching_result.rs:107:12 | LL | if let Some(_) = m!() {} | -------^^^^^^^------- help: try: `if m!().is_some()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_result.rs:94:15 + --> tests/ui/redundant_pattern_matching_result.rs:109:15 | LL | while let Some(_) = m!() {} | ----------^^^^^^^------- help: try: `while m!().is_some()` error: redundant pattern matching, consider using `is_ok()` - --> tests/ui/redundant_pattern_matching_result.rs:112:12 + --> tests/ui/redundant_pattern_matching_result.rs:128:12 | LL | if let Ok(_) = Ok::(42) {} | -------^^^^^--------------------- help: try: `if Ok::(42).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> tests/ui/redundant_pattern_matching_result.rs:114:12 + --> tests/ui/redundant_pattern_matching_result.rs:131:12 | LL | if let Err(_) = Err::(42) {} | -------^^^^^^---------------------- help: try: `if Err::(42).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> tests/ui/redundant_pattern_matching_result.rs:116:15 + --> tests/ui/redundant_pattern_matching_result.rs:134:15 | LL | while let Ok(_) = Ok::(10) {} | ----------^^^^^--------------------- help: try: `while Ok::(10).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> tests/ui/redundant_pattern_matching_result.rs:118:15 + --> tests/ui/redundant_pattern_matching_result.rs:137:15 | LL | while let Err(_) = Ok::(10) {} | ----------^^^^^^--------------------- help: try: `while Ok::(10).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> tests/ui/redundant_pattern_matching_result.rs:120:5 + --> tests/ui/redundant_pattern_matching_result.rs:140:5 | LL | / match Ok::(42) { +LL | | LL | | Ok(_) => true, LL | | Err(_) => false, LL | | }; | |_____^ help: try: `Ok::(42).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> tests/ui/redundant_pattern_matching_result.rs:125:5 + --> tests/ui/redundant_pattern_matching_result.rs:146:5 | LL | / match Err::(42) { +LL | | LL | | Ok(_) => false, LL | | Err(_) => true, LL | | }; | |_____^ help: try: `Err::(42).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> tests/ui/redundant_pattern_matching_result.rs:135:5 + --> tests/ui/redundant_pattern_matching_result.rs:157:5 | LL | / match x { +LL | | LL | | Ok(_) => true, LL | | _ => false, LL | | }; | |_____^ help: try: `x.is_ok()` error: redundant pattern matching, consider using `is_err()` - --> tests/ui/redundant_pattern_matching_result.rs:140:5 + --> tests/ui/redundant_pattern_matching_result.rs:163:5 | LL | / match x { +LL | | LL | | Ok(_) => false, LL | | _ => true, LL | | }; | |_____^ help: try: `x.is_err()` error: redundant pattern matching, consider using `is_err()` - --> tests/ui/redundant_pattern_matching_result.rs:145:5 + --> tests/ui/redundant_pattern_matching_result.rs:169:5 | LL | / match x { +LL | | LL | | Err(_) => true, LL | | _ => false, LL | | }; | |_____^ help: try: `x.is_err()` error: redundant pattern matching, consider using `is_ok()` - --> tests/ui/redundant_pattern_matching_result.rs:150:5 + --> tests/ui/redundant_pattern_matching_result.rs:175:5 | LL | / match x { +LL | | LL | | Err(_) => false, LL | | _ => true, LL | | }; | |_____^ help: try: `x.is_ok()` error: redundant pattern matching, consider using `is_ok()` - --> tests/ui/redundant_pattern_matching_result.rs:171:13 + --> tests/ui/redundant_pattern_matching_result.rs:197:13 | LL | let _ = matches!(x, Ok(_)); | ^^^^^^^^^^^^^^^^^^ help: try: `x.is_ok()` error: redundant pattern matching, consider using `is_err()` - --> tests/ui/redundant_pattern_matching_result.rs:173:13 + --> tests/ui/redundant_pattern_matching_result.rs:200:13 | LL | let _ = matches!(x, Err(_)); | ^^^^^^^^^^^^^^^^^^^ help: try: `x.is_err()` diff --git a/tests/ui/redundant_pub_crate.fixed b/tests/ui/redundant_pub_crate.fixed index 8882a4d50a5f..a6450123f4c9 100644 --- a/tests/ui/redundant_pub_crate.fixed +++ b/tests/ui/redundant_pub_crate.fixed @@ -5,24 +5,33 @@ mod m1 { fn f() {} pub fn g() {} // private due to m1 + // + //~^^ redundant_pub_crate pub fn h() {} mod m1_1 { fn f() {} pub fn g() {} // private due to m1_1 and m1 + // + //~^^ redundant_pub_crate pub fn h() {} } pub mod m1_2 { + //~^ redundant_pub_crate //:^ private due to m1 fn f() {} pub fn g() {} // private due to m1_2 and m1 + // + //~^^ redundant_pub_crate pub fn h() {} } pub mod m1_3 { fn f() {} pub fn g() {} // private due to m1 + // + //~^^ redundant_pub_crate pub fn h() {} } } @@ -30,24 +39,33 @@ mod m1 { pub(crate) mod m2 { fn f() {} pub fn g() {} // already crate visible due to m2 + // + //~^^ redundant_pub_crate pub fn h() {} mod m2_1 { fn f() {} pub fn g() {} // private due to m2_1 + // + //~^^ redundant_pub_crate pub fn h() {} } pub mod m2_2 { + //~^ redundant_pub_crate //:^ already crate visible due to m2 fn f() {} pub fn g() {} // already crate visible due to m2_2 and m2 + // + //~^^ redundant_pub_crate pub fn h() {} } pub mod m2_3 { fn f() {} pub fn g() {} // already crate visible due to m2 + // + //~^^ redundant_pub_crate pub fn h() {} } } @@ -60,6 +78,8 @@ pub mod m3 { mod m3_1 { fn f() {} pub fn g() {} // private due to m3_1 + // + //~^^ redundant_pub_crate pub fn h() {} } @@ -67,6 +87,8 @@ pub mod m3 { //:^ ok fn f() {} pub fn g() {} // already crate visible due to m3_2 + // + //~^^ redundant_pub_crate pub fn h() {} } @@ -80,18 +102,25 @@ pub mod m3 { mod m4 { fn f() {} pub fn g() {} // private: not re-exported by `pub use m4::*` + // + //~^^ redundant_pub_crate pub fn h() {} mod m4_1 { fn f() {} pub fn g() {} // private due to m4_1 + // + //~^^ redundant_pub_crate pub fn h() {} } pub mod m4_2 { + //~^ redundant_pub_crate //:^ private: not re-exported by `pub use m4::*` fn f() {} pub fn g() {} // private due to m4_2 + // + //~^^ redundant_pub_crate pub fn h() {} } diff --git a/tests/ui/redundant_pub_crate.rs b/tests/ui/redundant_pub_crate.rs index 5c8cab9be161..7415d34d50cc 100644 --- a/tests/ui/redundant_pub_crate.rs +++ b/tests/ui/redundant_pub_crate.rs @@ -5,24 +5,33 @@ mod m1 { fn f() {} pub(crate) fn g() {} // private due to m1 + // + //~^^ redundant_pub_crate pub fn h() {} mod m1_1 { fn f() {} pub(crate) fn g() {} // private due to m1_1 and m1 + // + //~^^ redundant_pub_crate pub fn h() {} } pub(crate) mod m1_2 { + //~^ redundant_pub_crate //:^ private due to m1 fn f() {} pub(crate) fn g() {} // private due to m1_2 and m1 + // + //~^^ redundant_pub_crate pub fn h() {} } pub mod m1_3 { fn f() {} pub(crate) fn g() {} // private due to m1 + // + //~^^ redundant_pub_crate pub fn h() {} } } @@ -30,24 +39,33 @@ mod m1 { pub(crate) mod m2 { fn f() {} pub(crate) fn g() {} // already crate visible due to m2 + // + //~^^ redundant_pub_crate pub fn h() {} mod m2_1 { fn f() {} pub(crate) fn g() {} // private due to m2_1 + // + //~^^ redundant_pub_crate pub fn h() {} } pub(crate) mod m2_2 { + //~^ redundant_pub_crate //:^ already crate visible due to m2 fn f() {} pub(crate) fn g() {} // already crate visible due to m2_2 and m2 + // + //~^^ redundant_pub_crate pub fn h() {} } pub mod m2_3 { fn f() {} pub(crate) fn g() {} // already crate visible due to m2 + // + //~^^ redundant_pub_crate pub fn h() {} } } @@ -60,6 +78,8 @@ pub mod m3 { mod m3_1 { fn f() {} pub(crate) fn g() {} // private due to m3_1 + // + //~^^ redundant_pub_crate pub fn h() {} } @@ -67,6 +87,8 @@ pub mod m3 { //:^ ok fn f() {} pub(crate) fn g() {} // already crate visible due to m3_2 + // + //~^^ redundant_pub_crate pub fn h() {} } @@ -80,18 +102,25 @@ pub mod m3 { mod m4 { fn f() {} pub(crate) fn g() {} // private: not re-exported by `pub use m4::*` + // + //~^^ redundant_pub_crate pub fn h() {} mod m4_1 { fn f() {} pub(crate) fn g() {} // private due to m4_1 + // + //~^^ redundant_pub_crate pub fn h() {} } pub(crate) mod m4_2 { + //~^ redundant_pub_crate //:^ private: not re-exported by `pub use m4::*` fn f() {} pub(crate) fn g() {} // private due to m4_2 + // + //~^^ redundant_pub_crate pub fn h() {} } diff --git a/tests/ui/redundant_pub_crate.stderr b/tests/ui/redundant_pub_crate.stderr index 699e19b1abcf..95909ea8b066 100644 --- a/tests/ui/redundant_pub_crate.stderr +++ b/tests/ui/redundant_pub_crate.stderr @@ -10,7 +10,7 @@ LL | pub(crate) fn g() {} // private due to m1 = help: to override `-D warnings` add `#[allow(clippy::redundant_pub_crate)]` error: pub(crate) function inside private module - --> tests/ui/redundant_pub_crate.rs:12:9 + --> tests/ui/redundant_pub_crate.rs:14:9 | LL | pub(crate) fn g() {} // private due to m1_1 and m1 | ----------^^^^^ @@ -18,7 +18,7 @@ LL | pub(crate) fn g() {} // private due to m1_1 and m1 | help: consider using: `pub` error: pub(crate) module inside private module - --> tests/ui/redundant_pub_crate.rs:16:5 + --> tests/ui/redundant_pub_crate.rs:20:5 | LL | pub(crate) mod m1_2 { | ----------^^^^^^^^^ @@ -26,7 +26,7 @@ LL | pub(crate) mod m1_2 { | help: consider using: `pub` error: pub(crate) function inside private module - --> tests/ui/redundant_pub_crate.rs:19:9 + --> tests/ui/redundant_pub_crate.rs:24:9 | LL | pub(crate) fn g() {} // private due to m1_2 and m1 | ----------^^^^^ @@ -34,7 +34,7 @@ LL | pub(crate) fn g() {} // private due to m1_2 and m1 | help: consider using: `pub` error: pub(crate) function inside private module - --> tests/ui/redundant_pub_crate.rs:25:9 + --> tests/ui/redundant_pub_crate.rs:32:9 | LL | pub(crate) fn g() {} // private due to m1 | ----------^^^^^ @@ -42,7 +42,7 @@ LL | pub(crate) fn g() {} // private due to m1 | help: consider using: `pub` error: pub(crate) function inside private module - --> tests/ui/redundant_pub_crate.rs:32:5 + --> tests/ui/redundant_pub_crate.rs:41:5 | LL | pub(crate) fn g() {} // already crate visible due to m2 | ----------^^^^^ @@ -50,7 +50,7 @@ LL | pub(crate) fn g() {} // already crate visible due to m2 | help: consider using: `pub` error: pub(crate) function inside private module - --> tests/ui/redundant_pub_crate.rs:37:9 + --> tests/ui/redundant_pub_crate.rs:48:9 | LL | pub(crate) fn g() {} // private due to m2_1 | ----------^^^^^ @@ -58,7 +58,7 @@ LL | pub(crate) fn g() {} // private due to m2_1 | help: consider using: `pub` error: pub(crate) module inside private module - --> tests/ui/redundant_pub_crate.rs:41:5 + --> tests/ui/redundant_pub_crate.rs:54:5 | LL | pub(crate) mod m2_2 { | ----------^^^^^^^^^ @@ -66,7 +66,7 @@ LL | pub(crate) mod m2_2 { | help: consider using: `pub` error: pub(crate) function inside private module - --> tests/ui/redundant_pub_crate.rs:44:9 + --> tests/ui/redundant_pub_crate.rs:58:9 | LL | pub(crate) fn g() {} // already crate visible due to m2_2 and m2 | ----------^^^^^ @@ -74,7 +74,7 @@ LL | pub(crate) fn g() {} // already crate visible due to m2_2 and m2 | help: consider using: `pub` error: pub(crate) function inside private module - --> tests/ui/redundant_pub_crate.rs:50:9 + --> tests/ui/redundant_pub_crate.rs:66:9 | LL | pub(crate) fn g() {} // already crate visible due to m2 | ----------^^^^^ @@ -82,7 +82,7 @@ LL | pub(crate) fn g() {} // already crate visible due to m2 | help: consider using: `pub` error: pub(crate) function inside private module - --> tests/ui/redundant_pub_crate.rs:62:9 + --> tests/ui/redundant_pub_crate.rs:80:9 | LL | pub(crate) fn g() {} // private due to m3_1 | ----------^^^^^ @@ -90,7 +90,7 @@ LL | pub(crate) fn g() {} // private due to m3_1 | help: consider using: `pub` error: pub(crate) function inside private module - --> tests/ui/redundant_pub_crate.rs:69:9 + --> tests/ui/redundant_pub_crate.rs:89:9 | LL | pub(crate) fn g() {} // already crate visible due to m3_2 | ----------^^^^^ @@ -98,7 +98,7 @@ LL | pub(crate) fn g() {} // already crate visible due to m3_2 | help: consider using: `pub` error: pub(crate) function inside private module - --> tests/ui/redundant_pub_crate.rs:82:5 + --> tests/ui/redundant_pub_crate.rs:104:5 | LL | pub(crate) fn g() {} // private: not re-exported by `pub use m4::*` | ----------^^^^^ @@ -106,7 +106,7 @@ LL | pub(crate) fn g() {} // private: not re-exported by `pub use m4::*` | help: consider using: `pub` error: pub(crate) function inside private module - --> tests/ui/redundant_pub_crate.rs:87:9 + --> tests/ui/redundant_pub_crate.rs:111:9 | LL | pub(crate) fn g() {} // private due to m4_1 | ----------^^^^^ @@ -114,7 +114,7 @@ LL | pub(crate) fn g() {} // private due to m4_1 | help: consider using: `pub` error: pub(crate) module inside private module - --> tests/ui/redundant_pub_crate.rs:91:5 + --> tests/ui/redundant_pub_crate.rs:117:5 | LL | pub(crate) mod m4_2 { | ----------^^^^^^^^^ @@ -122,7 +122,7 @@ LL | pub(crate) mod m4_2 { | help: consider using: `pub` error: pub(crate) function inside private module - --> tests/ui/redundant_pub_crate.rs:94:9 + --> tests/ui/redundant_pub_crate.rs:121:9 | LL | pub(crate) fn g() {} // private due to m4_2 | ----------^^^^^ diff --git a/tests/ui/redundant_slicing.fixed b/tests/ui/redundant_slicing.fixed index a4c035ba8407..385a5d97cf1a 100644 --- a/tests/ui/redundant_slicing.fixed +++ b/tests/ui/redundant_slicing.fixed @@ -6,10 +6,14 @@ use std::io::Read; fn main() { let slice: &[u32] = &[0]; let _ = slice; // Redundant slice + // + //~^^ redundant_slicing let v = vec![0]; let _ = &v[..]; // Ok, results in `&[_]` let _ = (&*v); // Outer borrow is redundant + // + //~^^ redundant_slicing static S: &[u8] = &[0, 1, 2]; let _ = &mut &S[..]; // Ok, re-borrows slice @@ -27,6 +31,7 @@ fn main() { }; } let _ = slice; + //~^ redundant_slicing macro_rules! m2 { ($e:expr) => { diff --git a/tests/ui/redundant_slicing.rs b/tests/ui/redundant_slicing.rs index 67fe702acf54..04f181da250d 100644 --- a/tests/ui/redundant_slicing.rs +++ b/tests/ui/redundant_slicing.rs @@ -6,10 +6,14 @@ use std::io::Read; fn main() { let slice: &[u32] = &[0]; let _ = &slice[..]; // Redundant slice + // + //~^^ redundant_slicing let v = vec![0]; let _ = &v[..]; // Ok, results in `&[_]` let _ = &(&*v)[..]; // Outer borrow is redundant + // + //~^^ redundant_slicing static S: &[u8] = &[0, 1, 2]; let _ = &mut &S[..]; // Ok, re-borrows slice @@ -27,6 +31,7 @@ fn main() { }; } let _ = &m!(slice)[..]; + //~^ redundant_slicing macro_rules! m2 { ($e:expr) => { diff --git a/tests/ui/redundant_slicing.stderr b/tests/ui/redundant_slicing.stderr index 269a597b3226..964111bccf88 100644 --- a/tests/ui/redundant_slicing.stderr +++ b/tests/ui/redundant_slicing.stderr @@ -8,13 +8,13 @@ LL | let _ = &slice[..]; // Redundant slice = help: to override `-D warnings` add `#[allow(clippy::redundant_slicing)]` error: redundant slicing of the whole range - --> tests/ui/redundant_slicing.rs:12:13 + --> tests/ui/redundant_slicing.rs:14:13 | LL | let _ = &(&*v)[..]; // Outer borrow is redundant | ^^^^^^^^^^ help: use the original value instead: `(&*v)` error: redundant slicing of the whole range - --> tests/ui/redundant_slicing.rs:29:13 + --> tests/ui/redundant_slicing.rs:33:13 | LL | let _ = &m!(slice)[..]; | ^^^^^^^^^^^^^^ help: use the original value instead: `slice` diff --git a/tests/ui/redundant_static_lifetimes.fixed b/tests/ui/redundant_static_lifetimes.fixed index 3d1c78bd12d9..86c6ca17eb20 100644 --- a/tests/ui/redundant_static_lifetimes.fixed +++ b/tests/ui/redundant_static_lifetimes.fixed @@ -6,40 +6,57 @@ struct Foo; const VAR_ONE: &str = "Test constant #1"; // ERROR: Consider removing 'static. +//~^ redundant_static_lifetimes const VAR_TWO: &str = "Test constant #2"; // This line should not raise a warning. const VAR_THREE: &[&str] = &["one", "two"]; // ERROR: Consider removing 'static +//~^ redundant_static_lifetimes const VAR_FOUR: (&str, (&str, &str), &str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static +//~^ redundant_static_lifetimes +//~| redundant_static_lifetimes const VAR_SIX: &u8 = &5; +//~^ redundant_static_lifetimes const VAR_HEIGHT: &Foo = &Foo {}; +//~^ redundant_static_lifetimes const VAR_SLICE: &[u8] = b"Test constant #1"; // ERROR: Consider removing 'static. +//~^ redundant_static_lifetimes const VAR_TUPLE: &(u8, u8) = &(1, 2); // ERROR: Consider removing 'static. +//~^ redundant_static_lifetimes const VAR_ARRAY: &[u8; 1] = b"T"; // ERROR: Consider removing 'static. +//~^ redundant_static_lifetimes static STATIC_VAR_ONE: &str = "Test static #1"; // ERROR: Consider removing 'static. +//~^ redundant_static_lifetimes static STATIC_VAR_TWO: &str = "Test static #2"; // This line should not raise a warning. static STATIC_VAR_THREE: &[&str] = &["one", "two"]; // ERROR: Consider removing 'static +//~^ redundant_static_lifetimes static STATIC_VAR_SIX: &u8 = &5; +//~^ redundant_static_lifetimes static STATIC_VAR_HEIGHT: &Foo = &Foo {}; +//~^ redundant_static_lifetimes static STATIC_VAR_SLICE: &[u8] = b"Test static #3"; // ERROR: Consider removing 'static. +//~^ redundant_static_lifetimes static STATIC_VAR_TUPLE: &(u8, u8) = &(1, 2); // ERROR: Consider removing 'static. +//~^ redundant_static_lifetimes static STATIC_VAR_ARRAY: &[u8; 1] = b"T"; // ERROR: Consider removing 'static. +//~^ redundant_static_lifetimes static mut STATIC_MUT_SLICE: &mut [u32] = &mut [0]; +//~^ redundant_static_lifetimes fn main() { let false_positive: &'static str = "test"; @@ -69,4 +86,5 @@ fn msrv_1_16() { #[clippy::msrv = "1.17"] fn msrv_1_17() { static V: &u8 = &17; + //~^ redundant_static_lifetimes } diff --git a/tests/ui/redundant_static_lifetimes.rs b/tests/ui/redundant_static_lifetimes.rs index 5932f14b8d9a..6fefe6c232d2 100644 --- a/tests/ui/redundant_static_lifetimes.rs +++ b/tests/ui/redundant_static_lifetimes.rs @@ -6,40 +6,57 @@ struct Foo; const VAR_ONE: &'static str = "Test constant #1"; // ERROR: Consider removing 'static. +//~^ redundant_static_lifetimes const VAR_TWO: &str = "Test constant #2"; // This line should not raise a warning. const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR: Consider removing 'static +//~^ redundant_static_lifetimes const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static +//~^ redundant_static_lifetimes +//~| redundant_static_lifetimes const VAR_SIX: &'static u8 = &5; +//~^ redundant_static_lifetimes const VAR_HEIGHT: &'static Foo = &Foo {}; +//~^ redundant_static_lifetimes const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR: Consider removing 'static. +//~^ redundant_static_lifetimes const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR: Consider removing 'static. +//~^ redundant_static_lifetimes const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR: Consider removing 'static. +//~^ redundant_static_lifetimes static STATIC_VAR_ONE: &'static str = "Test static #1"; // ERROR: Consider removing 'static. +//~^ redundant_static_lifetimes static STATIC_VAR_TWO: &str = "Test static #2"; // This line should not raise a warning. static STATIC_VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR: Consider removing 'static +//~^ redundant_static_lifetimes static STATIC_VAR_SIX: &'static u8 = &5; +//~^ redundant_static_lifetimes static STATIC_VAR_HEIGHT: &'static Foo = &Foo {}; +//~^ redundant_static_lifetimes static STATIC_VAR_SLICE: &'static [u8] = b"Test static #3"; // ERROR: Consider removing 'static. +//~^ redundant_static_lifetimes static STATIC_VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR: Consider removing 'static. +//~^ redundant_static_lifetimes static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR: Consider removing 'static. +//~^ redundant_static_lifetimes static mut STATIC_MUT_SLICE: &'static mut [u32] = &mut [0]; +//~^ redundant_static_lifetimes fn main() { let false_positive: &'static str = "test"; @@ -69,4 +86,5 @@ fn msrv_1_16() { #[clippy::msrv = "1.17"] fn msrv_1_17() { static V: &'static u8 = &17; + //~^ redundant_static_lifetimes } diff --git a/tests/ui/redundant_static_lifetimes.stderr b/tests/ui/redundant_static_lifetimes.stderr index 48871eba2dc7..955882703955 100644 --- a/tests/ui/redundant_static_lifetimes.stderr +++ b/tests/ui/redundant_static_lifetimes.stderr @@ -8,103 +8,103 @@ LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR: Consider removi = help: to override `-D warnings` add `#[allow(clippy::redundant_static_lifetimes)]` error: constants have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:12:21 + --> tests/ui/redundant_static_lifetimes.rs:13:21 | LL | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: constants have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:14:32 + --> tests/ui/redundant_static_lifetimes.rs:16:32 | LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: constants have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:14:47 + --> tests/ui/redundant_static_lifetimes.rs:16:47 | LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: constants have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:16:17 + --> tests/ui/redundant_static_lifetimes.rs:20:17 | LL | const VAR_SIX: &'static u8 = &5; | -^^^^^^^--- help: consider removing `'static`: `&u8` error: constants have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:18:20 + --> tests/ui/redundant_static_lifetimes.rs:23:20 | LL | const VAR_HEIGHT: &'static Foo = &Foo {}; | -^^^^^^^---- help: consider removing `'static`: `&Foo` error: constants have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:20:19 + --> tests/ui/redundant_static_lifetimes.rs:26:19 | LL | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR: Consider removing 'static. | -^^^^^^^----- help: consider removing `'static`: `&[u8]` error: constants have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:22:19 + --> tests/ui/redundant_static_lifetimes.rs:29:19 | LL | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR: Consider removing 'static. | -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)` error: constants have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:24:19 + --> tests/ui/redundant_static_lifetimes.rs:32:19 | LL | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR: Consider removing 'static. | -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:26:25 + --> tests/ui/redundant_static_lifetimes.rs:35:25 | LL | static STATIC_VAR_ONE: &'static str = "Test static #1"; // ERROR: Consider removing 'static. | -^^^^^^^---- help: consider removing `'static`: `&str` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:30:29 + --> tests/ui/redundant_static_lifetimes.rs:40:29 | LL | static STATIC_VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:32:25 + --> tests/ui/redundant_static_lifetimes.rs:43:25 | LL | static STATIC_VAR_SIX: &'static u8 = &5; | -^^^^^^^--- help: consider removing `'static`: `&u8` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:34:28 + --> tests/ui/redundant_static_lifetimes.rs:46:28 | LL | static STATIC_VAR_HEIGHT: &'static Foo = &Foo {}; | -^^^^^^^---- help: consider removing `'static`: `&Foo` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:36:27 + --> tests/ui/redundant_static_lifetimes.rs:49:27 | LL | static STATIC_VAR_SLICE: &'static [u8] = b"Test static #3"; // ERROR: Consider removing 'static. | -^^^^^^^----- help: consider removing `'static`: `&[u8]` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:38:27 + --> tests/ui/redundant_static_lifetimes.rs:52:27 | LL | static STATIC_VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR: Consider removing 'static. | -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:40:27 + --> tests/ui/redundant_static_lifetimes.rs:55:27 | LL | static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR: Consider removing 'static. | -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:42:31 + --> tests/ui/redundant_static_lifetimes.rs:58:31 | LL | static mut STATIC_MUT_SLICE: &'static mut [u32] = &mut [0]; | -^^^^^^^---------- help: consider removing `'static`: `&mut [u32]` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:71:16 + --> tests/ui/redundant_static_lifetimes.rs:88:16 | LL | static V: &'static u8 = &17; | -^^^^^^^--- help: consider removing `'static`: `&u8` diff --git a/tests/ui/redundant_static_lifetimes_multiple.rs b/tests/ui/redundant_static_lifetimes_multiple.rs index bfcab420b1f4..8cb6e4491842 100644 --- a/tests/ui/redundant_static_lifetimes_multiple.rs +++ b/tests/ui/redundant_static_lifetimes_multiple.rs @@ -2,24 +2,23 @@ // these are rustfixable, but run-rustfix tests cannot handle them const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR: Consider removing 'static -//~^ ERROR: constants have by default a `'static` lifetime -//~| NOTE: `-D clippy::redundant-static-lifetimes` implied by `-D warnings` -//~| ERROR: constants have by default a `'static` lifetime +//~^ redundant_static_lifetimes +//~| redundant_static_lifetimes const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; -//~^ ERROR: constants have by default a `'static` lifetime -//~| ERROR: constants have by default a `'static` lifetime +//~^ redundant_static_lifetimes +//~| redundant_static_lifetimes static STATIC_VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static -//~^ ERROR: statics have by default a `'static` lifetime -//~| ERROR: statics have by default a `'static` lifetime +//~^ redundant_static_lifetimes +//~| redundant_static_lifetimes static STATIC_VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR: Consider removing 'static -//~^ ERROR: statics have by default a `'static` lifetime -//~| ERROR: statics have by default a `'static` lifetime +//~^ redundant_static_lifetimes +//~| redundant_static_lifetimes static STATIC_VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; -//~^ ERROR: statics have by default a `'static` lifetime -//~| ERROR: statics have by default a `'static` lifetime +//~^ redundant_static_lifetimes +//~| redundant_static_lifetimes fn main() {} diff --git a/tests/ui/redundant_static_lifetimes_multiple.stderr b/tests/ui/redundant_static_lifetimes_multiple.stderr index 330703d9eff1..aed16204f1c2 100644 --- a/tests/ui/redundant_static_lifetimes_multiple.stderr +++ b/tests/ui/redundant_static_lifetimes_multiple.stderr @@ -14,49 +14,49 @@ LL | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; | -^^^^^^^---- help: consider removing `'static`: `&str` error: constants have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes_multiple.rs:9:29 + --> tests/ui/redundant_static_lifetimes_multiple.rs:8:29 | LL | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; | -^^^^^^^--------------- help: consider removing `'static`: `&[&'static str]` error: constants have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes_multiple.rs:9:39 + --> tests/ui/redundant_static_lifetimes_multiple.rs:8:39 | LL | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; | -^^^^^^^---- help: consider removing `'static`: `&str` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes_multiple.rs:13:40 + --> tests/ui/redundant_static_lifetimes_multiple.rs:12:40 | LL | static STATIC_VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes_multiple.rs:13:55 + --> tests/ui/redundant_static_lifetimes_multiple.rs:12:55 | LL | static STATIC_VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes_multiple.rs:17:26 + --> tests/ui/redundant_static_lifetimes_multiple.rs:16:26 | LL | static STATIC_VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR: Consider removing 'static | -^^^^^^^------------------ help: consider removing `'static`: `&[&[&'static str]]` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes_multiple.rs:17:38 + --> tests/ui/redundant_static_lifetimes_multiple.rs:16:38 | LL | static STATIC_VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes_multiple.rs:21:37 + --> tests/ui/redundant_static_lifetimes_multiple.rs:20:37 | LL | static STATIC_VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; | -^^^^^^^--------------- help: consider removing `'static`: `&[&'static str]` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes_multiple.rs:21:47 + --> tests/ui/redundant_static_lifetimes_multiple.rs:20:47 | LL | static STATIC_VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; | -^^^^^^^---- help: consider removing `'static`: `&str` diff --git a/tests/ui/redundant_type_annotations.rs b/tests/ui/redundant_type_annotations.rs index dc9b073ffba8..55c19d194a49 100644 --- a/tests/ui/redundant_type_annotations.rs +++ b/tests/ui/redundant_type_annotations.rs @@ -79,12 +79,13 @@ impl Pie { // Everything here should be lint let v: u32 = self.return_an_int(); - //~^ ERROR: redundant type annotation - //~| NOTE: `-D clippy::redundant-type-annotations` implied by `-D warnings` + //~^ redundant_type_annotations + let v: &u32 = self.return_a_ref(); - //~^ ERROR: redundant type annotation + //~^ redundant_type_annotations + let v: &Slice = self.return_a_ref_to_struct(); - //~^ ERROR: redundant type annotation + //~^ redundant_type_annotations } } @@ -157,50 +158,50 @@ fn test_functions() { // Everything here should be lint let _return: String = return_a_string(); - //~^ ERROR: redundant type annotation + //~^ redundant_type_annotations let _return: Pie = return_a_struct(); - //~^ ERROR: redundant type annotation + //~^ redundant_type_annotations let _return: Pizza = return_an_enum(); - //~^ ERROR: redundant type annotation + //~^ redundant_type_annotations let _return: u32 = return_an_int(); - //~^ ERROR: redundant type annotation + //~^ redundant_type_annotations let _return: String = String::new(); - //~^ ERROR: redundant type annotation + //~^ redundant_type_annotations let new_pie: Pie = Pie::new(); - //~^ ERROR: redundant type annotation + //~^ redundant_type_annotations let _return: u32 = new_pie.return_an_int(); - //~^ ERROR: redundant type annotation + //~^ redundant_type_annotations let _return: u32 = Pie::associated_return_an_int(); - //~^ ERROR: redundant type annotation + //~^ redundant_type_annotations let _return: String = Pie::associated_return_a_string(); - //~^ ERROR: redundant type annotation + //~^ redundant_type_annotations } fn test_simple_types() { // Everything here should be lint let _var: u32 = u32::MAX; - //~^ ERROR: redundant type annotation + //~^ redundant_type_annotations let _var: u32 = 5_u32; - //~^ ERROR: redundant type annotation + //~^ redundant_type_annotations let _var: &str = "test"; - //~^ ERROR: redundant type annotation + //~^ redundant_type_annotations let _var: &[u8; 4] = b"test"; - //~^ ERROR: redundant type annotation + //~^ redundant_type_annotations let _var: bool = false; - //~^ ERROR: redundant type annotation + //~^ redundant_type_annotations } fn issue12212() { diff --git a/tests/ui/redundant_type_annotations.stderr b/tests/ui/redundant_type_annotations.stderr index 4768f4d3c57c..d2f04cc4768e 100644 --- a/tests/ui/redundant_type_annotations.stderr +++ b/tests/ui/redundant_type_annotations.stderr @@ -14,91 +14,91 @@ LL | let v: &u32 = self.return_a_ref(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> tests/ui/redundant_type_annotations.rs:86:9 + --> tests/ui/redundant_type_annotations.rs:87:9 | LL | let v: &Slice = self.return_a_ref_to_struct(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> tests/ui/redundant_type_annotations.rs:159:5 + --> tests/ui/redundant_type_annotations.rs:160:5 | LL | let _return: String = return_a_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> tests/ui/redundant_type_annotations.rs:162:5 + --> tests/ui/redundant_type_annotations.rs:163:5 | LL | let _return: Pie = return_a_struct(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> tests/ui/redundant_type_annotations.rs:165:5 + --> tests/ui/redundant_type_annotations.rs:166:5 | LL | let _return: Pizza = return_an_enum(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> tests/ui/redundant_type_annotations.rs:168:5 + --> tests/ui/redundant_type_annotations.rs:169:5 | LL | let _return: u32 = return_an_int(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> tests/ui/redundant_type_annotations.rs:171:5 + --> tests/ui/redundant_type_annotations.rs:172:5 | LL | let _return: String = String::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> tests/ui/redundant_type_annotations.rs:174:5 + --> tests/ui/redundant_type_annotations.rs:175:5 | LL | let new_pie: Pie = Pie::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> tests/ui/redundant_type_annotations.rs:177:5 + --> tests/ui/redundant_type_annotations.rs:178:5 | LL | let _return: u32 = new_pie.return_an_int(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> tests/ui/redundant_type_annotations.rs:180:5 + --> tests/ui/redundant_type_annotations.rs:181:5 | LL | let _return: u32 = Pie::associated_return_an_int(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> tests/ui/redundant_type_annotations.rs:183:5 + --> tests/ui/redundant_type_annotations.rs:184:5 | LL | let _return: String = Pie::associated_return_a_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> tests/ui/redundant_type_annotations.rs:190:5 + --> tests/ui/redundant_type_annotations.rs:191:5 | LL | let _var: u32 = u32::MAX; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> tests/ui/redundant_type_annotations.rs:193:5 + --> tests/ui/redundant_type_annotations.rs:194:5 | LL | let _var: u32 = 5_u32; | ^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> tests/ui/redundant_type_annotations.rs:196:5 + --> tests/ui/redundant_type_annotations.rs:197:5 | LL | let _var: &str = "test"; | ^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> tests/ui/redundant_type_annotations.rs:199:5 + --> tests/ui/redundant_type_annotations.rs:200:5 | LL | let _var: &[u8; 4] = b"test"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation - --> tests/ui/redundant_type_annotations.rs:202:5 + --> tests/ui/redundant_type_annotations.rs:203:5 | LL | let _var: bool = false; | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/ref_as_ptr.fixed b/tests/ui/ref_as_ptr.fixed index 6048267092f1..ce144508581e 100644 --- a/tests/ui/ref_as_ptr.fixed +++ b/tests/ui/ref_as_ptr.fixed @@ -5,53 +5,86 @@ fn f(_: T) {} fn main() { f(std::ptr::from_ref(&1u8)); + //~^ ref_as_ptr f(std::ptr::from_ref::(&2u32)); + //~^ ref_as_ptr f(std::ptr::from_ref::(&3.0f64)); + //~^ ref_as_ptr f(std::ptr::from_ref(&4) as *const f32); + //~^ ref_as_ptr f(std::ptr::from_ref::(&5.0f32) as *const u32); + //~^ ref_as_ptr f(std::ptr::from_ref(&mut 6u8)); + //~^ ref_as_ptr f(std::ptr::from_ref::(&mut 7u32)); + //~^ ref_as_ptr f(std::ptr::from_ref::(&mut 8.0f64)); + //~^ ref_as_ptr f(std::ptr::from_ref(&mut 9) as *const f32); + //~^ ref_as_ptr f(std::ptr::from_ref::(&mut 10.0f32) as *const u32); + //~^ ref_as_ptr f(std::ptr::from_mut(&mut 11u8)); + //~^ ref_as_ptr f(std::ptr::from_mut::(&mut 12u32)); + //~^ ref_as_ptr f(std::ptr::from_mut::(&mut 13.0f64)); + //~^ ref_as_ptr f(std::ptr::from_mut(&mut 14) as *const f32); + //~^ ref_as_ptr f(std::ptr::from_mut::(&mut 15.0f32) as *const u32); + //~^ ref_as_ptr f(std::ptr::from_ref(&1u8)); + //~^ ref_as_ptr f(std::ptr::from_ref::(&2u32)); + //~^ ref_as_ptr f(std::ptr::from_ref::(&3.0f64)); + //~^ ref_as_ptr f(std::ptr::from_ref(&4) as *const f32); + //~^ ref_as_ptr f(std::ptr::from_ref::(&5.0f32) as *const u32); + //~^ ref_as_ptr let val = 1; f(std::ptr::from_ref(&val)); + //~^ ref_as_ptr f(std::ptr::from_ref::(&val)); + //~^ ref_as_ptr f(std::ptr::from_ref(&val) as *const f32); + //~^ ref_as_ptr f(std::ptr::from_ref::(&val) as *const f64); + //~^ ref_as_ptr let mut val: u8 = 2; f(std::ptr::from_mut::(&mut val)); + //~^ ref_as_ptr f(std::ptr::from_mut(&mut val)); + //~^ ref_as_ptr f(std::ptr::from_ref::(&mut val)); + //~^ ref_as_ptr f(std::ptr::from_ref(&mut val)); + //~^ ref_as_ptr f(std::ptr::from_ref::(&mut val) as *const f64); + //~^ ref_as_ptr f::<*const Option>(std::ptr::from_ref(&mut val) as *const _); + //~^ ref_as_ptr f(std::ptr::from_ref::<[usize; 7]>(&std::array::from_fn(|i| i * i))); + //~^ ref_as_ptr f(std::ptr::from_ref::<[usize; 8]>(&mut std::array::from_fn(|i| i * i))); + //~^ ref_as_ptr f(std::ptr::from_mut::<[usize; 9]>(&mut std::array::from_fn(|i| i * i))); + //~^ ref_as_ptr let _ = &String::new() as *const _; let _ = &mut String::new() as *mut _; @@ -74,17 +107,23 @@ fn _msrv_1_76() { let mut_val = &mut 42_i32; f(std::ptr::from_ref::(val)); + //~^ ref_as_ptr f(std::ptr::from_mut::(mut_val)); + //~^ ref_as_ptr } fn foo(val: &[u8]) { f(std::ptr::from_ref(val)); + //~^ ref_as_ptr f(std::ptr::from_ref::<[u8]>(val)); + //~^ ref_as_ptr } fn bar(val: &mut str) { f(std::ptr::from_mut(val)); + //~^ ref_as_ptr f(std::ptr::from_mut::(val)); + //~^ ref_as_ptr } struct X<'a>(&'a i32); @@ -92,10 +131,12 @@ struct X<'a>(&'a i32); impl<'a> X<'a> { fn foo(&self) -> *const i64 { std::ptr::from_ref(self.0) as *const _ + //~^ ref_as_ptr } fn bar(&mut self) -> *const i64 { std::ptr::from_ref(self.0) as *const _ + //~^ ref_as_ptr } } @@ -104,13 +145,16 @@ struct Y<'a>(&'a mut i32); impl<'a> Y<'a> { fn foo(&self) -> *const i64 { std::ptr::from_ref(self.0) as *const _ + //~^ ref_as_ptr } fn bar(&mut self) -> *const i64 { std::ptr::from_ref(self.0) as *const _ + //~^ ref_as_ptr } fn baz(&mut self) -> *const i64 { std::ptr::from_mut(self.0) as *mut _ + //~^ ref_as_ptr } } diff --git a/tests/ui/ref_as_ptr.rs b/tests/ui/ref_as_ptr.rs index 7f1d59b856e4..acdff2c2ba29 100644 --- a/tests/ui/ref_as_ptr.rs +++ b/tests/ui/ref_as_ptr.rs @@ -5,53 +5,86 @@ fn f(_: T) {} fn main() { f(&1u8 as *const _); + //~^ ref_as_ptr f(&2u32 as *const u32); + //~^ ref_as_ptr f(&3.0f64 as *const f64); + //~^ ref_as_ptr f(&4 as *const _ as *const f32); + //~^ ref_as_ptr f(&5.0f32 as *const f32 as *const u32); + //~^ ref_as_ptr f(&mut 6u8 as *const _); + //~^ ref_as_ptr f(&mut 7u32 as *const u32); + //~^ ref_as_ptr f(&mut 8.0f64 as *const f64); + //~^ ref_as_ptr f(&mut 9 as *const _ as *const f32); + //~^ ref_as_ptr f(&mut 10.0f32 as *const f32 as *const u32); + //~^ ref_as_ptr f(&mut 11u8 as *mut _); + //~^ ref_as_ptr f(&mut 12u32 as *mut u32); + //~^ ref_as_ptr f(&mut 13.0f64 as *mut f64); + //~^ ref_as_ptr f(&mut 14 as *mut _ as *const f32); + //~^ ref_as_ptr f(&mut 15.0f32 as *mut f32 as *const u32); + //~^ ref_as_ptr f(&1u8 as *const _); + //~^ ref_as_ptr f(&2u32 as *const u32); + //~^ ref_as_ptr f(&3.0f64 as *const f64); + //~^ ref_as_ptr f(&4 as *const _ as *const f32); + //~^ ref_as_ptr f(&5.0f32 as *const f32 as *const u32); + //~^ ref_as_ptr let val = 1; f(&val as *const _); + //~^ ref_as_ptr f(&val as *const i32); + //~^ ref_as_ptr f(&val as *const _ as *const f32); + //~^ ref_as_ptr f(&val as *const i32 as *const f64); + //~^ ref_as_ptr let mut val: u8 = 2; f(&mut val as *mut u8); + //~^ ref_as_ptr f(&mut val as *mut _); + //~^ ref_as_ptr f(&mut val as *const u8); + //~^ ref_as_ptr f(&mut val as *const _); + //~^ ref_as_ptr f(&mut val as *const u8 as *const f64); + //~^ ref_as_ptr f::<*const Option>(&mut val as *const _ as *const _); + //~^ ref_as_ptr f(&std::array::from_fn(|i| i * i) as *const [usize; 7]); + //~^ ref_as_ptr f(&mut std::array::from_fn(|i| i * i) as *const [usize; 8]); + //~^ ref_as_ptr f(&mut std::array::from_fn(|i| i * i) as *mut [usize; 9]); + //~^ ref_as_ptr let _ = &String::new() as *const _; let _ = &mut String::new() as *mut _; @@ -74,17 +107,23 @@ fn _msrv_1_76() { let mut_val = &mut 42_i32; f(val as *const i32); + //~^ ref_as_ptr f(mut_val as *mut i32); + //~^ ref_as_ptr } fn foo(val: &[u8]) { f(val as *const _); + //~^ ref_as_ptr f(val as *const [u8]); + //~^ ref_as_ptr } fn bar(val: &mut str) { f(val as *mut _); + //~^ ref_as_ptr f(val as *mut str); + //~^ ref_as_ptr } struct X<'a>(&'a i32); @@ -92,10 +131,12 @@ struct X<'a>(&'a i32); impl<'a> X<'a> { fn foo(&self) -> *const i64 { self.0 as *const _ as *const _ + //~^ ref_as_ptr } fn bar(&mut self) -> *const i64 { self.0 as *const _ as *const _ + //~^ ref_as_ptr } } @@ -104,13 +145,16 @@ struct Y<'a>(&'a mut i32); impl<'a> Y<'a> { fn foo(&self) -> *const i64 { self.0 as *const _ as *const _ + //~^ ref_as_ptr } fn bar(&mut self) -> *const i64 { self.0 as *const _ as *const _ + //~^ ref_as_ptr } fn baz(&mut self) -> *const i64 { self.0 as *mut _ as *mut _ + //~^ ref_as_ptr } } diff --git a/tests/ui/ref_as_ptr.stderr b/tests/ui/ref_as_ptr.stderr index c5e9af38aea0..79db29e596bd 100644 --- a/tests/ui/ref_as_ptr.stderr +++ b/tests/ui/ref_as_ptr.stderr @@ -8,259 +8,259 @@ LL | f(&1u8 as *const _); = help: to override `-D warnings` add `#[allow(clippy::ref_as_ptr)]` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:8:7 + --> tests/ui/ref_as_ptr.rs:9:7 | LL | f(&2u32 as *const u32); | ^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::(&2u32)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:9:7 + --> tests/ui/ref_as_ptr.rs:11:7 | LL | f(&3.0f64 as *const f64); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::(&3.0f64)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:11:7 + --> tests/ui/ref_as_ptr.rs:14:7 | LL | f(&4 as *const _ as *const f32); | ^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&4)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:12:7 + --> tests/ui/ref_as_ptr.rs:16:7 | LL | f(&5.0f32 as *const f32 as *const u32); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::(&5.0f32)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:14:7 + --> tests/ui/ref_as_ptr.rs:19:7 | LL | f(&mut 6u8 as *const _); | ^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&mut 6u8)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:15:7 + --> tests/ui/ref_as_ptr.rs:21:7 | LL | f(&mut 7u32 as *const u32); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::(&mut 7u32)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:16:7 + --> tests/ui/ref_as_ptr.rs:23:7 | LL | f(&mut 8.0f64 as *const f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::(&mut 8.0f64)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:18:7 + --> tests/ui/ref_as_ptr.rs:26:7 | LL | f(&mut 9 as *const _ as *const f32); | ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&mut 9)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:19:7 + --> tests/ui/ref_as_ptr.rs:28:7 | LL | f(&mut 10.0f32 as *const f32 as *const u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::(&mut 10.0f32)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:21:7 + --> tests/ui/ref_as_ptr.rs:31:7 | LL | f(&mut 11u8 as *mut _); | ^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut(&mut 11u8)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:22:7 + --> tests/ui/ref_as_ptr.rs:33:7 | LL | f(&mut 12u32 as *mut u32); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut::(&mut 12u32)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:23:7 + --> tests/ui/ref_as_ptr.rs:35:7 | LL | f(&mut 13.0f64 as *mut f64); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut::(&mut 13.0f64)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:25:7 + --> tests/ui/ref_as_ptr.rs:38:7 | LL | f(&mut 14 as *mut _ as *const f32); | ^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut(&mut 14)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:26:7 + --> tests/ui/ref_as_ptr.rs:40:7 | LL | f(&mut 15.0f32 as *mut f32 as *const u32); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut::(&mut 15.0f32)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:28:7 + --> tests/ui/ref_as_ptr.rs:43:7 | LL | f(&1u8 as *const _); | ^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&1u8)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:29:7 + --> tests/ui/ref_as_ptr.rs:45:7 | LL | f(&2u32 as *const u32); | ^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::(&2u32)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:30:7 + --> tests/ui/ref_as_ptr.rs:47:7 | LL | f(&3.0f64 as *const f64); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::(&3.0f64)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:32:7 + --> tests/ui/ref_as_ptr.rs:50:7 | LL | f(&4 as *const _ as *const f32); | ^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&4)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:33:7 + --> tests/ui/ref_as_ptr.rs:52:7 | LL | f(&5.0f32 as *const f32 as *const u32); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::(&5.0f32)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:36:7 + --> tests/ui/ref_as_ptr.rs:56:7 | LL | f(&val as *const _); | ^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&val)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:37:7 + --> tests/ui/ref_as_ptr.rs:58:7 | LL | f(&val as *const i32); | ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::(&val)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:39:7 + --> tests/ui/ref_as_ptr.rs:61:7 | LL | f(&val as *const _ as *const f32); | ^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&val)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:40:7 + --> tests/ui/ref_as_ptr.rs:63:7 | LL | f(&val as *const i32 as *const f64); | ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::(&val)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:43:7 + --> tests/ui/ref_as_ptr.rs:67:7 | LL | f(&mut val as *mut u8); | ^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut::(&mut val)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:44:7 + --> tests/ui/ref_as_ptr.rs:69:7 | LL | f(&mut val as *mut _); | ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut(&mut val)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:46:7 + --> tests/ui/ref_as_ptr.rs:72:7 | LL | f(&mut val as *const u8); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::(&mut val)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:47:7 + --> tests/ui/ref_as_ptr.rs:74:7 | LL | f(&mut val as *const _); | ^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&mut val)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:49:7 + --> tests/ui/ref_as_ptr.rs:77:7 | LL | f(&mut val as *const u8 as *const f64); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::(&mut val)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:50:28 + --> tests/ui/ref_as_ptr.rs:79:28 | LL | f::<*const Option>(&mut val as *const _ as *const _); | ^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&mut val)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:52:7 + --> tests/ui/ref_as_ptr.rs:82:7 | LL | f(&std::array::from_fn(|i| i * i) as *const [usize; 7]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<[usize; 7]>(&std::array::from_fn(|i| i * i))` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:53:7 + --> tests/ui/ref_as_ptr.rs:84:7 | LL | f(&mut std::array::from_fn(|i| i * i) as *const [usize; 8]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<[usize; 8]>(&mut std::array::from_fn(|i| i * i))` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:54:7 + --> tests/ui/ref_as_ptr.rs:86:7 | LL | f(&mut std::array::from_fn(|i| i * i) as *mut [usize; 9]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut::<[usize; 9]>(&mut std::array::from_fn(|i| i * i))` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:76:7 + --> tests/ui/ref_as_ptr.rs:109:7 | LL | f(val as *const i32); | ^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::(val)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:77:7 + --> tests/ui/ref_as_ptr.rs:111:7 | LL | f(mut_val as *mut i32); | ^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut::(mut_val)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:81:7 + --> tests/ui/ref_as_ptr.rs:116:7 | LL | f(val as *const _); | ^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(val)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:82:7 + --> tests/ui/ref_as_ptr.rs:118:7 | LL | f(val as *const [u8]); | ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<[u8]>(val)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:86:7 + --> tests/ui/ref_as_ptr.rs:123:7 | LL | f(val as *mut _); | ^^^^^^^^^^^^^ help: try: `std::ptr::from_mut(val)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:87:7 + --> tests/ui/ref_as_ptr.rs:125:7 | LL | f(val as *mut str); | ^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut::(val)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:94:9 + --> tests/ui/ref_as_ptr.rs:133:9 | LL | self.0 as *const _ as *const _ | ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(self.0)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:98:9 + --> tests/ui/ref_as_ptr.rs:138:9 | LL | self.0 as *const _ as *const _ | ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(self.0)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:106:9 + --> tests/ui/ref_as_ptr.rs:147:9 | LL | self.0 as *const _ as *const _ | ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(self.0)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:110:9 + --> tests/ui/ref_as_ptr.rs:152:9 | LL | self.0 as *const _ as *const _ | ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(self.0)` error: reference as raw pointer - --> tests/ui/ref_as_ptr.rs:114:9 + --> tests/ui/ref_as_ptr.rs:157:9 | LL | self.0 as *mut _ as *mut _ | ^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut(self.0)` diff --git a/tests/ui/ref_binding_to_reference.rs b/tests/ui/ref_binding_to_reference.rs index 001ed3119490..365fd8edea78 100644 --- a/tests/ui/ref_binding_to_reference.rs +++ b/tests/ui/ref_binding_to_reference.rs @@ -28,15 +28,15 @@ fn main() { // Err, reference to a &String let _: &&String = match Some(&x) { Some(ref x) => x, - //~^ ERROR: this pattern creates a reference to a reference - //~| NOTE: `-D clippy::ref-binding-to-reference` implied by `-D warnings` + //~^ ref_binding_to_reference None => return, }; // Err, reference to a &String let _: &&String = match Some(&x) { Some(ref x) => { - //~^ ERROR: this pattern creates a reference to a reference + //~^ ref_binding_to_reference + f1(x); f1(*x); x @@ -47,20 +47,22 @@ fn main() { // Err, reference to a &String match Some(&x) { Some(ref x) => m2!(x), - //~^ ERROR: this pattern creates a reference to a reference + //~^ ref_binding_to_reference None => return, } // Err, reference to a &String let _ = |&ref x: &&String| { - //~^ ERROR: this pattern creates a reference to a reference + //~^ ref_binding_to_reference + let _: &&String = x; }; } // Err, reference to a &String fn f2<'a>(&ref x: &&'a String) -> &'a String { - //~^ ERROR: this pattern creates a reference to a reference + //~^ ref_binding_to_reference + let _: &&String = x; *x } @@ -68,7 +70,8 @@ fn f2<'a>(&ref x: &&'a String) -> &'a String { trait T1 { // Err, reference to a &String fn f(&ref x: &&String) { - //~^ ERROR: this pattern creates a reference to a reference + //~^ ref_binding_to_reference + let _: &&String = x; } } @@ -77,7 +80,8 @@ struct S; impl T1 for S { // Err, reference to a &String fn f(&ref x: &&String) { - //~^ ERROR: this pattern creates a reference to a reference + //~^ ref_binding_to_reference + let _: &&String = x; } } diff --git a/tests/ui/ref_binding_to_reference.stderr b/tests/ui/ref_binding_to_reference.stderr index 233416351a0a..c1adfab12bcb 100644 --- a/tests/ui/ref_binding_to_reference.stderr +++ b/tests/ui/ref_binding_to_reference.stderr @@ -13,7 +13,7 @@ LL + Some(x) => &x, | error: this pattern creates a reference to a reference - --> tests/ui/ref_binding_to_reference.rs:38:14 + --> tests/ui/ref_binding_to_reference.rs:37:14 | LL | Some(ref x) => { | ^^^^^ @@ -22,6 +22,7 @@ help: try | LL ~ Some(x) => { LL | +LL | LL | f1(x); LL ~ f1(x); LL ~ &x @@ -49,11 +50,12 @@ help: try | LL ~ let _ = |&x: &&String| { LL | +LL | LL ~ let _: &&String = &x; | error: this pattern creates a reference to a reference - --> tests/ui/ref_binding_to_reference.rs:62:12 + --> tests/ui/ref_binding_to_reference.rs:63:12 | LL | fn f2<'a>(&ref x: &&'a String) -> &'a String { | ^^^^^ @@ -62,12 +64,13 @@ help: try | LL ~ fn f2<'a>(&x: &&'a String) -> &'a String { LL | +LL | LL ~ let _: &&String = &x; LL ~ x | error: this pattern creates a reference to a reference - --> tests/ui/ref_binding_to_reference.rs:70:11 + --> tests/ui/ref_binding_to_reference.rs:72:11 | LL | fn f(&ref x: &&String) { | ^^^^^ @@ -76,11 +79,12 @@ help: try | LL ~ fn f(&x: &&String) { LL | +LL | LL ~ let _: &&String = &x; | error: this pattern creates a reference to a reference - --> tests/ui/ref_binding_to_reference.rs:79:11 + --> tests/ui/ref_binding_to_reference.rs:82:11 | LL | fn f(&ref x: &&String) { | ^^^^^ @@ -89,6 +93,7 @@ help: try | LL ~ fn f(&x: &&String) { LL | +LL | LL ~ let _: &&String = &x; | diff --git a/tests/ui/ref_option/ref_option.all.fixed b/tests/ui/ref_option/ref_option.all.fixed index 47781a97c983..4159e916f199 100644 --- a/tests/ui/ref_option/ref_option.all.fixed +++ b/tests/ui/ref_option/ref_option.all.fixed @@ -6,42 +6,59 @@ #![warn(clippy::ref_option)] fn opt_u8(a: Option<&u8>) {} +//~^ ref_option fn opt_gen(a: Option<&T>) {} +//~^ ref_option fn opt_string(a: std::option::Option<&String>) {} +//~^ ref_option fn ret_string<'a>(p: &'a str) -> Option<&'a u8> { + //~^ ref_option panic!() } fn ret_string_static() -> Option<&'static u8> { + //~^ ref_option panic!() } fn mult_string(a: Option<&String>, b: Option<&Vec>) {} +//~^ ref_option fn ret_box<'a>() -> Option<&'a Box> { + //~^ ref_option panic!() } pub fn pub_opt_string(a: Option<&String>) {} +//~[all]^ ref_option pub fn pub_mult_string(a: Option<&String>, b: Option<&Vec>) {} +//~[all]^ ref_option pub trait PubTrait { fn pub_trait_opt(&self, a: Option<&Vec>); + //~[all]^ ref_option fn pub_trait_ret(&self) -> Option<&Vec>; + //~[all]^ ref_option } trait PrivateTrait { fn trait_opt(&self, a: Option<&String>); + //~^ ref_option fn trait_ret(&self) -> Option<&String>; + //~^ ref_option } pub struct PubStruct; impl PubStruct { pub fn pub_opt_params(&self, a: Option<&()>) {} + //~[all]^ ref_option pub fn pub_opt_ret(&self) -> Option<&String> { + //~[all]^ ref_option panic!() } fn private_opt_params(&self, a: Option<&()>) {} + //~^ ref_option fn private_opt_ret(&self) -> Option<&String> { + //~^ ref_option panic!() } } diff --git a/tests/ui/ref_option/ref_option.all.stderr b/tests/ui/ref_option/ref_option.all.stderr index fd30628bdd81..bd43c28336eb 100644 --- a/tests/ui/ref_option/ref_option.all.stderr +++ b/tests/ui/ref_option/ref_option.all.stderr @@ -10,7 +10,7 @@ LL | fn opt_u8(a: &Option) {} = help: to override `-D warnings` add `#[allow(clippy::ref_option)]` error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:9:1 + --> tests/ui/ref_option/ref_option.rs:10:1 | LL | fn opt_gen(a: &Option) {} | ^^^^^^^^^^^^^^^^^----------^^^^ @@ -18,7 +18,7 @@ LL | fn opt_gen(a: &Option) {} | help: change this to: `Option<&T>` error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:10:1 + --> tests/ui/ref_option/ref_option.rs:12:1 | LL | fn opt_string(a: &std::option::Option) {} | ^^^^^^^^^^^^^^^^^----------------------------^^^^ @@ -26,29 +26,31 @@ LL | fn opt_string(a: &std::option::Option) {} | help: change this to: `std::option::Option<&String>` error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:11:1 + --> tests/ui/ref_option/ref_option.rs:14:1 | LL | fn ret_string<'a>(p: &'a str) -> &'a Option { | ^ -------------- help: change this to: `Option<&'a u8>` | _| | | +LL | | LL | | panic!() LL | | } | |_^ error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:14:1 + --> tests/ui/ref_option/ref_option.rs:18:1 | LL | fn ret_string_static() -> &'static Option { | ^ ------------------- help: change this to: `Option<&'static u8>` | _| | | +LL | | LL | | panic!() LL | | } | |_^ error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:17:1 + --> tests/ui/ref_option/ref_option.rs:22:1 | LL | fn mult_string(a: &Option, b: &Option>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,18 +62,19 @@ LL + fn mult_string(a: Option<&String>, b: Option<&Vec>) {} | error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:18:1 + --> tests/ui/ref_option/ref_option.rs:24:1 | LL | fn ret_box<'a>() -> &'a Option> { | ^ ------------------- help: change this to: `Option<&'a Box>` | _| | | +LL | | LL | | panic!() LL | | } | |_^ error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:22:1 + --> tests/ui/ref_option/ref_option.rs:29:1 | LL | pub fn pub_opt_string(a: &Option) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^ @@ -79,7 +82,7 @@ LL | pub fn pub_opt_string(a: &Option) {} | help: change this to: `Option<&String>` error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:23:1 + --> tests/ui/ref_option/ref_option.rs:31:1 | LL | pub fn pub_mult_string(a: &Option, b: &Option>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -91,7 +94,7 @@ LL + pub fn pub_mult_string(a: Option<&String>, b: Option<&Vec>) {} | error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:26:5 + --> tests/ui/ref_option/ref_option.rs:35:5 | LL | fn pub_trait_opt(&self, a: &Option>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------^^ @@ -99,7 +102,7 @@ LL | fn pub_trait_opt(&self, a: &Option>); | help: change this to: `Option<&Vec>` error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:27:5 + --> tests/ui/ref_option/ref_option.rs:37:5 | LL | fn pub_trait_ret(&self) -> &Option>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------^ @@ -107,7 +110,7 @@ LL | fn pub_trait_ret(&self) -> &Option>; | help: change this to: `Option<&Vec>` error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:31:5 + --> tests/ui/ref_option/ref_option.rs:42:5 | LL | fn trait_opt(&self, a: &Option); | ^^^^^^^^^^^^^^^^^^^^^^^---------------^^ @@ -115,7 +118,7 @@ LL | fn trait_opt(&self, a: &Option); | help: change this to: `Option<&String>` error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:32:5 + --> tests/ui/ref_option/ref_option.rs:44:5 | LL | fn trait_ret(&self) -> &Option; | ^^^^^^^^^^^^^^^^^^^^^^^---------------^ @@ -123,7 +126,7 @@ LL | fn trait_ret(&self) -> &Option; | help: change this to: `Option<&String>` error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:38:5 + --> tests/ui/ref_option/ref_option.rs:51:5 | LL | pub fn pub_opt_params(&self, a: &Option<()>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^ @@ -131,18 +134,19 @@ LL | pub fn pub_opt_params(&self, a: &Option<()>) {} | help: change this to: `Option<&()>` error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:39:5 + --> tests/ui/ref_option/ref_option.rs:53:5 | LL | pub fn pub_opt_ret(&self) -> &Option { | ^ --------------- help: change this to: `Option<&String>` | _____| | | +LL | | LL | | panic!() LL | | } | |_____^ error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:43:5 + --> tests/ui/ref_option/ref_option.rs:58:5 | LL | fn private_opt_params(&self, a: &Option<()>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^ @@ -150,12 +154,13 @@ LL | fn private_opt_params(&self, a: &Option<()>) {} | help: change this to: `Option<&()>` error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:44:5 + --> tests/ui/ref_option/ref_option.rs:60:5 | LL | fn private_opt_ret(&self) -> &Option { | ^ --------------- help: change this to: `Option<&String>` | _____| | | +LL | | LL | | panic!() LL | | } | |_____^ diff --git a/tests/ui/ref_option/ref_option.private.fixed b/tests/ui/ref_option/ref_option.private.fixed index 8c42556e9b0d..3b158befb926 100644 --- a/tests/ui/ref_option/ref_option.private.fixed +++ b/tests/ui/ref_option/ref_option.private.fixed @@ -6,42 +6,59 @@ #![warn(clippy::ref_option)] fn opt_u8(a: Option<&u8>) {} +//~^ ref_option fn opt_gen(a: Option<&T>) {} +//~^ ref_option fn opt_string(a: std::option::Option<&String>) {} +//~^ ref_option fn ret_string<'a>(p: &'a str) -> Option<&'a u8> { + //~^ ref_option panic!() } fn ret_string_static() -> Option<&'static u8> { + //~^ ref_option panic!() } fn mult_string(a: Option<&String>, b: Option<&Vec>) {} +//~^ ref_option fn ret_box<'a>() -> Option<&'a Box> { + //~^ ref_option panic!() } pub fn pub_opt_string(a: &Option) {} +//~[all]^ ref_option pub fn pub_mult_string(a: &Option, b: &Option>) {} +//~[all]^ ref_option pub trait PubTrait { fn pub_trait_opt(&self, a: &Option>); + //~[all]^ ref_option fn pub_trait_ret(&self) -> &Option>; + //~[all]^ ref_option } trait PrivateTrait { fn trait_opt(&self, a: Option<&String>); + //~^ ref_option fn trait_ret(&self) -> Option<&String>; + //~^ ref_option } pub struct PubStruct; impl PubStruct { pub fn pub_opt_params(&self, a: &Option<()>) {} + //~[all]^ ref_option pub fn pub_opt_ret(&self) -> &Option { + //~[all]^ ref_option panic!() } fn private_opt_params(&self, a: Option<&()>) {} + //~^ ref_option fn private_opt_ret(&self) -> Option<&String> { + //~^ ref_option panic!() } } diff --git a/tests/ui/ref_option/ref_option.private.stderr b/tests/ui/ref_option/ref_option.private.stderr index d3428f1891f3..88c65e429d87 100644 --- a/tests/ui/ref_option/ref_option.private.stderr +++ b/tests/ui/ref_option/ref_option.private.stderr @@ -10,7 +10,7 @@ LL | fn opt_u8(a: &Option) {} = help: to override `-D warnings` add `#[allow(clippy::ref_option)]` error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:9:1 + --> tests/ui/ref_option/ref_option.rs:10:1 | LL | fn opt_gen(a: &Option) {} | ^^^^^^^^^^^^^^^^^----------^^^^ @@ -18,7 +18,7 @@ LL | fn opt_gen(a: &Option) {} | help: change this to: `Option<&T>` error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:10:1 + --> tests/ui/ref_option/ref_option.rs:12:1 | LL | fn opt_string(a: &std::option::Option) {} | ^^^^^^^^^^^^^^^^^----------------------------^^^^ @@ -26,29 +26,31 @@ LL | fn opt_string(a: &std::option::Option) {} | help: change this to: `std::option::Option<&String>` error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:11:1 + --> tests/ui/ref_option/ref_option.rs:14:1 | LL | fn ret_string<'a>(p: &'a str) -> &'a Option { | ^ -------------- help: change this to: `Option<&'a u8>` | _| | | +LL | | LL | | panic!() LL | | } | |_^ error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:14:1 + --> tests/ui/ref_option/ref_option.rs:18:1 | LL | fn ret_string_static() -> &'static Option { | ^ ------------------- help: change this to: `Option<&'static u8>` | _| | | +LL | | LL | | panic!() LL | | } | |_^ error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:17:1 + --> tests/ui/ref_option/ref_option.rs:22:1 | LL | fn mult_string(a: &Option, b: &Option>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,18 +62,19 @@ LL + fn mult_string(a: Option<&String>, b: Option<&Vec>) {} | error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:18:1 + --> tests/ui/ref_option/ref_option.rs:24:1 | LL | fn ret_box<'a>() -> &'a Option> { | ^ ------------------- help: change this to: `Option<&'a Box>` | _| | | +LL | | LL | | panic!() LL | | } | |_^ error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:31:5 + --> tests/ui/ref_option/ref_option.rs:42:5 | LL | fn trait_opt(&self, a: &Option); | ^^^^^^^^^^^^^^^^^^^^^^^---------------^^ @@ -79,7 +82,7 @@ LL | fn trait_opt(&self, a: &Option); | help: change this to: `Option<&String>` error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:32:5 + --> tests/ui/ref_option/ref_option.rs:44:5 | LL | fn trait_ret(&self) -> &Option; | ^^^^^^^^^^^^^^^^^^^^^^^---------------^ @@ -87,7 +90,7 @@ LL | fn trait_ret(&self) -> &Option; | help: change this to: `Option<&String>` error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:43:5 + --> tests/ui/ref_option/ref_option.rs:58:5 | LL | fn private_opt_params(&self, a: &Option<()>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^ @@ -95,12 +98,13 @@ LL | fn private_opt_params(&self, a: &Option<()>) {} | help: change this to: `Option<&()>` error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option.rs:44:5 + --> tests/ui/ref_option/ref_option.rs:60:5 | LL | fn private_opt_ret(&self) -> &Option { | ^ --------------- help: change this to: `Option<&String>` | _____| | | +LL | | LL | | panic!() LL | | } | |_____^ diff --git a/tests/ui/ref_option/ref_option.rs b/tests/ui/ref_option/ref_option.rs index 05251bcf12cd..35cd94174f8b 100644 --- a/tests/ui/ref_option/ref_option.rs +++ b/tests/ui/ref_option/ref_option.rs @@ -6,42 +6,59 @@ #![warn(clippy::ref_option)] fn opt_u8(a: &Option) {} +//~^ ref_option fn opt_gen(a: &Option) {} +//~^ ref_option fn opt_string(a: &std::option::Option) {} +//~^ ref_option fn ret_string<'a>(p: &'a str) -> &'a Option { + //~^ ref_option panic!() } fn ret_string_static() -> &'static Option { + //~^ ref_option panic!() } fn mult_string(a: &Option, b: &Option>) {} +//~^ ref_option fn ret_box<'a>() -> &'a Option> { + //~^ ref_option panic!() } pub fn pub_opt_string(a: &Option) {} +//~[all]^ ref_option pub fn pub_mult_string(a: &Option, b: &Option>) {} +//~[all]^ ref_option pub trait PubTrait { fn pub_trait_opt(&self, a: &Option>); + //~[all]^ ref_option fn pub_trait_ret(&self) -> &Option>; + //~[all]^ ref_option } trait PrivateTrait { fn trait_opt(&self, a: &Option); + //~^ ref_option fn trait_ret(&self) -> &Option; + //~^ ref_option } pub struct PubStruct; impl PubStruct { pub fn pub_opt_params(&self, a: &Option<()>) {} + //~[all]^ ref_option pub fn pub_opt_ret(&self) -> &Option { + //~[all]^ ref_option panic!() } fn private_opt_params(&self, a: &Option<()>) {} + //~^ ref_option fn private_opt_ret(&self) -> &Option { + //~^ ref_option panic!() } } diff --git a/tests/ui/ref_option/ref_option_traits.all.stderr b/tests/ui/ref_option/ref_option_traits.all.stderr index a9967168c12e..030a9a28ec68 100644 --- a/tests/ui/ref_option/ref_option_traits.all.stderr +++ b/tests/ui/ref_option/ref_option_traits.all.stderr @@ -10,7 +10,7 @@ LL | fn pub_trait_opt(&self, a: &Option>); = help: to override `-D warnings` add `#[allow(clippy::ref_option)]` error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option_traits.rs:11:5 + --> tests/ui/ref_option/ref_option_traits.rs:12:5 | LL | fn pub_trait_ret(&self) -> &Option>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------^ @@ -18,7 +18,7 @@ LL | fn pub_trait_ret(&self) -> &Option>; | help: change this to: `Option<&Vec>` error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option_traits.rs:15:5 + --> tests/ui/ref_option/ref_option_traits.rs:17:5 | LL | fn trait_opt(&self, a: &Option); | ^^^^^^^^^^^^^^^^^^^^^^^---------------^^ @@ -26,7 +26,7 @@ LL | fn trait_opt(&self, a: &Option); | help: change this to: `Option<&String>` error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option_traits.rs:16:5 + --> tests/ui/ref_option/ref_option_traits.rs:19:5 | LL | fn trait_ret(&self) -> &Option; | ^^^^^^^^^^^^^^^^^^^^^^^---------------^ diff --git a/tests/ui/ref_option/ref_option_traits.private.stderr b/tests/ui/ref_option/ref_option_traits.private.stderr index 36d0833af8a2..2837ee80fb2e 100644 --- a/tests/ui/ref_option/ref_option_traits.private.stderr +++ b/tests/ui/ref_option/ref_option_traits.private.stderr @@ -1,5 +1,5 @@ error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option_traits.rs:15:5 + --> tests/ui/ref_option/ref_option_traits.rs:17:5 | LL | fn trait_opt(&self, a: &Option); | ^^^^^^^^^^^^^^^^^^^^^^^---------------^^ @@ -10,7 +10,7 @@ LL | fn trait_opt(&self, a: &Option); = help: to override `-D warnings` add `#[allow(clippy::ref_option)]` error: it is more idiomatic to use `Option<&T>` instead of `&Option` - --> tests/ui/ref_option/ref_option_traits.rs:16:5 + --> tests/ui/ref_option/ref_option_traits.rs:19:5 | LL | fn trait_ret(&self) -> &Option; | ^^^^^^^^^^^^^^^^^^^^^^^---------------^ diff --git a/tests/ui/ref_option/ref_option_traits.rs b/tests/ui/ref_option/ref_option_traits.rs index 5d5f113c83db..811da2eb4d50 100644 --- a/tests/ui/ref_option/ref_option_traits.rs +++ b/tests/ui/ref_option/ref_option_traits.rs @@ -8,12 +8,16 @@ pub trait PubTrait { fn pub_trait_opt(&self, a: &Option>); + //~[all]^ ref_option fn pub_trait_ret(&self) -> &Option>; + //~[all]^ ref_option } trait PrivateTrait { fn trait_opt(&self, a: &Option); + //~^ ref_option fn trait_ret(&self) -> &Option; + //~^ ref_option } pub struct PubStruct; diff --git a/tests/ui/ref_option_ref.rs b/tests/ui/ref_option_ref.rs index 44001c45e99a..9632611f7df4 100644 --- a/tests/ui/ref_option_ref.rs +++ b/tests/ui/ref_option_ref.rs @@ -8,37 +8,39 @@ static THRESHOLD: i32 = 10; static REF_THRESHOLD: &Option<&i32> = &Some(&THRESHOLD); -//~^ ERROR: since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Opt -//~| NOTE: `-D clippy::ref-option-ref` implied by `-D warnings` +//~^ ref_option_ref + const CONST_THRESHOLD: &i32 = &10; const REF_CONST: &Option<&i32> = &Some(CONST_THRESHOLD); -//~^ ERROR: since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Opt +//~^ ref_option_ref type RefOptRefU32<'a> = &'a Option<&'a u32>; -//~^ ERROR: since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Opt +//~^ ref_option_ref + type RefOptRef<'a, T> = &'a Option<&'a T>; -//~^ ERROR: since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Opt +//~^ ref_option_ref fn foo(data: &Option<&u32>) {} -//~^ ERROR: since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Opt +//~^ ref_option_ref fn bar(data: &u32) -> &Option<&u32> { - //~^ ERROR: since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Opt + //~^ ref_option_ref + &None } struct StructRef<'a> { data: &'a Option<&'a u32>, - //~^ ERROR: since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to + //~^ ref_option_ref } struct StructTupleRef<'a>(u32, &'a Option<&'a u32>); -//~^ ERROR: since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Opt +//~^ ref_option_ref enum EnumRef<'a> { Variant1(u32), Variant2(&'a Option<&'a u32>), - //~^ ERROR: since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to + //~^ ref_option_ref } trait RefOptTrait { @@ -48,14 +50,14 @@ trait RefOptTrait { impl RefOptTrait for u32 { type A = &'static Option<&'static Self>; - //~^ ERROR: since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to + //~^ ref_option_ref fn foo(&self, _: Self::A) {} } fn main() { let x: &Option<&u32> = &None; - //~^ ERROR: since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to + //~^ ref_option_ref } fn issue9682(arg: &Option<&mut String>) { diff --git a/tests/ui/ref_option_ref.stderr b/tests/ui/ref_option_ref.stderr index 1cb64e1182a5..25064a61ee88 100644 --- a/tests/ui/ref_option_ref.stderr +++ b/tests/ui/ref_option_ref.stderr @@ -20,49 +20,49 @@ LL | type RefOptRefU32<'a> = &'a Option<&'a u32>; | ^^^^^^^^^^^^^^^^^^^ help: try: `Option<&'a u32>` error: since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Option<&T>` - --> tests/ui/ref_option_ref.rs:19:25 + --> tests/ui/ref_option_ref.rs:20:25 | LL | type RefOptRef<'a, T> = &'a Option<&'a T>; | ^^^^^^^^^^^^^^^^^ help: try: `Option<&'a T>` error: since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Option<&T>` - --> tests/ui/ref_option_ref.rs:22:14 + --> tests/ui/ref_option_ref.rs:23:14 | LL | fn foo(data: &Option<&u32>) {} | ^^^^^^^^^^^^^ help: try: `Option<&u32>` error: since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Option<&T>` - --> tests/ui/ref_option_ref.rs:25:23 + --> tests/ui/ref_option_ref.rs:26:23 | LL | fn bar(data: &u32) -> &Option<&u32> { | ^^^^^^^^^^^^^ help: try: `Option<&u32>` error: since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Option<&T>` - --> tests/ui/ref_option_ref.rs:31:11 + --> tests/ui/ref_option_ref.rs:33:11 | LL | data: &'a Option<&'a u32>, | ^^^^^^^^^^^^^^^^^^^ help: try: `Option<&'a u32>` error: since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Option<&T>` - --> tests/ui/ref_option_ref.rs:35:32 + --> tests/ui/ref_option_ref.rs:37:32 | LL | struct StructTupleRef<'a>(u32, &'a Option<&'a u32>); | ^^^^^^^^^^^^^^^^^^^ help: try: `Option<&'a u32>` error: since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Option<&T>` - --> tests/ui/ref_option_ref.rs:40:14 + --> tests/ui/ref_option_ref.rs:42:14 | LL | Variant2(&'a Option<&'a u32>), | ^^^^^^^^^^^^^^^^^^^ help: try: `Option<&'a u32>` error: since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Option<&T>` - --> tests/ui/ref_option_ref.rs:50:14 + --> tests/ui/ref_option_ref.rs:52:14 | LL | type A = &'static Option<&'static Self>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Option<&'static Self>` error: since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Option<&T>` - --> tests/ui/ref_option_ref.rs:57:12 + --> tests/ui/ref_option_ref.rs:59:12 | LL | let x: &Option<&u32> = &None; | ^^^^^^^^^^^^^ help: try: `Option<&u32>` diff --git a/tests/ui/ref_patterns.rs b/tests/ui/ref_patterns.rs index acd42ec89b62..2905af13ccb6 100644 --- a/tests/ui/ref_patterns.rs +++ b/tests/ui/ref_patterns.rs @@ -6,17 +6,17 @@ fn use_in_pattern() { match opt { None => {}, Some(ref opt) => {}, - //~^ ERROR: usage of ref pattern + //~^ ref_patterns } } fn use_in_binding() { let x = 5; let ref y = x; - //~^ ERROR: usage of ref pattern + //~^ ref_patterns } fn use_in_parameter(ref x: i32) {} -//~^ ERROR: usage of ref pattern +//~^ ref_patterns fn main() {} diff --git a/tests/ui/regex.rs b/tests/ui/regex.rs index f607a2d50c6d..c63d549b7553 100644 --- a/tests/ui/regex.rs +++ b/tests/ui/regex.rs @@ -1,3 +1,4 @@ +//@require-annotations-for-level: WARN #![allow( unused, clippy::needless_raw_strings, @@ -27,11 +28,14 @@ fn syntax_error() { //~^ ERROR: regex syntax error: invalid character class range, the start must be <= th let some_regex = Regex::new(OPENING_PAREN); + //~^ invalid_regex let binary_pipe_in_wrong_position = BRegex::new("|"); //~^ ERROR: trivial regex let some_binary_regex = BRegex::new(OPENING_PAREN); + //~^ invalid_regex let some_binary_regex_builder = BRegexBuilder::new(OPENING_PAREN); + //~^ invalid_regex let closing_paren = ")"; let not_linted = Regex::new(closing_paren); @@ -44,7 +48,9 @@ fn syntax_error() { ]); let set_error = RegexSet::new(&[OPENING_PAREN, r"[a-z]+\.(com|org|net)"]); + //~^ invalid_regex let bset_error = BRegexSet::new(&[OPENING_PAREN, r"[a-z]+\.(com|org|net)"]); + //~^ invalid_regex // These following three cases are considering valid since regex-1.8.0 let raw_string_error = Regex::new(r"[...\/...]"); @@ -52,6 +58,7 @@ fn syntax_error() { let _ = Regex::new(r"(?hi)").unwrap(); let escaped_string_span = Regex::new("\\b\\c"); + //~^ invalid_regex let aux_span = Regex::new("(?ixi)"); //~^ ERROR: regex syntax error: duplicate flag diff --git a/tests/ui/regex.stderr b/tests/ui/regex.stderr index 18dd538c68b4..aaec3bc14200 100644 --- a/tests/ui/regex.stderr +++ b/tests/ui/regex.stderr @@ -1,5 +1,5 @@ error: trivial regex - --> tests/ui/regex.rs:19:45 + --> tests/ui/regex.rs:20:45 | LL | let pipe_in_wrong_position = Regex::new("|"); | ^^^ @@ -9,7 +9,7 @@ LL | let pipe_in_wrong_position = Regex::new("|"); = help: to override `-D warnings` add `#[allow(clippy::trivial_regex)]` error: trivial regex - --> tests/ui/regex.rs:21:60 + --> tests/ui/regex.rs:22:60 | LL | let pipe_in_wrong_position_builder = RegexBuilder::new("|"); | ^^^ @@ -17,7 +17,7 @@ LL | let pipe_in_wrong_position_builder = RegexBuilder::new("|"); = help: the regex is unlikely to be useful as it is error: regex syntax error: invalid character class range, the start must be <= the end - --> tests/ui/regex.rs:23:42 + --> tests/ui/regex.rs:24:42 | LL | let wrong_char_ranice = Regex::new("[z-a]"); | ^^^ @@ -26,7 +26,7 @@ LL | let wrong_char_ranice = Regex::new("[z-a]"); = help: to override `-D warnings` add `#[allow(clippy::invalid_regex)]` error: regex syntax error: invalid character class range, the start must be <= the end - --> tests/ui/regex.rs:26:37 + --> tests/ui/regex.rs:27:37 | LL | let some_unicode = Regex::new("[é-è]"); | ^^^ @@ -35,13 +35,13 @@ error: regex parse error: ( ^ error: unclosed group - --> tests/ui/regex.rs:29:33 + --> tests/ui/regex.rs:30:33 | LL | let some_regex = Regex::new(OPENING_PAREN); | ^^^^^^^^^^^^^ error: trivial regex - --> tests/ui/regex.rs:31:53 + --> tests/ui/regex.rs:33:53 | LL | let binary_pipe_in_wrong_position = BRegex::new("|"); | ^^^ @@ -52,7 +52,7 @@ error: regex parse error: ( ^ error: unclosed group - --> tests/ui/regex.rs:33:41 + --> tests/ui/regex.rs:35:41 | LL | let some_binary_regex = BRegex::new(OPENING_PAREN); | ^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ error: regex parse error: ( ^ error: unclosed group - --> tests/ui/regex.rs:34:56 + --> tests/ui/regex.rs:37:56 | LL | let some_binary_regex_builder = BRegexBuilder::new(OPENING_PAREN); | ^^^^^^^^^^^^^ @@ -70,7 +70,7 @@ error: regex parse error: ( ^ error: unclosed group - --> tests/ui/regex.rs:46:37 + --> tests/ui/regex.rs:50:37 | LL | let set_error = RegexSet::new(&[OPENING_PAREN, r"[a-z]+\.(com|org|net)"]); | ^^^^^^^^^^^^^ @@ -79,7 +79,7 @@ error: regex parse error: ( ^ error: unclosed group - --> tests/ui/regex.rs:47:39 + --> tests/ui/regex.rs:52:39 | LL | let bset_error = BRegexSet::new(&[OPENING_PAREN, r"[a-z]+\.(com|org|net)"]); | ^^^^^^^^^^^^^ @@ -88,7 +88,7 @@ error: regex parse error: \b\c ^^ error: unrecognized escape sequence - --> tests/ui/regex.rs:54:42 + --> tests/ui/regex.rs:60:42 | LL | let escaped_string_span = Regex::new("\\b\\c"); | ^^^^^^^^ @@ -96,19 +96,19 @@ LL | let escaped_string_span = Regex::new("\\b\\c"); = help: consider using a raw string literal: `r".."` error: regex syntax error: duplicate flag - --> tests/ui/regex.rs:56:34 + --> tests/ui/regex.rs:63:34 | LL | let aux_span = Regex::new("(?ixi)"); | ^ ^ error: regex syntax error: pattern can match invalid UTF-8 - --> tests/ui/regex.rs:62:53 + --> tests/ui/regex.rs:69:53 | LL | let invalid_utf8_should_lint = Regex::new("(?-u)."); | ^ error: trivial regex - --> tests/ui/regex.rs:67:33 + --> tests/ui/regex.rs:74:33 | LL | let trivial_eq = Regex::new("^foobar$"); | ^^^^^^^^^^ @@ -116,7 +116,7 @@ LL | let trivial_eq = Regex::new("^foobar$"); = help: consider using `==` on `str`s error: trivial regex - --> tests/ui/regex.rs:70:48 + --> tests/ui/regex.rs:77:48 | LL | let trivial_eq_builder = RegexBuilder::new("^foobar$"); | ^^^^^^^^^^ @@ -124,7 +124,7 @@ LL | let trivial_eq_builder = RegexBuilder::new("^foobar$"); = help: consider using `==` on `str`s error: trivial regex - --> tests/ui/regex.rs:73:42 + --> tests/ui/regex.rs:80:42 | LL | let trivial_starts_with = Regex::new("^foobar"); | ^^^^^^^^^ @@ -132,7 +132,7 @@ LL | let trivial_starts_with = Regex::new("^foobar"); = help: consider using `str::starts_with` error: trivial regex - --> tests/ui/regex.rs:76:40 + --> tests/ui/regex.rs:83:40 | LL | let trivial_ends_with = Regex::new("foobar$"); | ^^^^^^^^^ @@ -140,7 +140,7 @@ LL | let trivial_ends_with = Regex::new("foobar$"); = help: consider using `str::ends_with` error: trivial regex - --> tests/ui/regex.rs:79:39 + --> tests/ui/regex.rs:86:39 | LL | let trivial_contains = Regex::new("foobar"); | ^^^^^^^^ @@ -148,7 +148,7 @@ LL | let trivial_contains = Regex::new("foobar"); = help: consider using `str::contains` error: trivial regex - --> tests/ui/regex.rs:82:39 + --> tests/ui/regex.rs:89:39 | LL | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); | ^^^^^^^^^^^^^^^^ @@ -156,7 +156,7 @@ LL | let trivial_contains = Regex::new(NOT_A_REAL_REGEX); = help: consider using `str::contains` error: trivial regex - --> tests/ui/regex.rs:85:40 + --> tests/ui/regex.rs:92:40 | LL | let trivial_backslash = Regex::new("a\\.b"); | ^^^^^^^ @@ -164,7 +164,7 @@ LL | let trivial_backslash = Regex::new("a\\.b"); = help: consider using `str::contains` error: trivial regex - --> tests/ui/regex.rs:89:36 + --> tests/ui/regex.rs:96:36 | LL | let trivial_empty = Regex::new(""); | ^^ @@ -172,7 +172,7 @@ LL | let trivial_empty = Regex::new(""); = help: the regex is unlikely to be useful as it is error: trivial regex - --> tests/ui/regex.rs:92:36 + --> tests/ui/regex.rs:99:36 | LL | let trivial_empty = Regex::new("^"); | ^^^ @@ -180,7 +180,7 @@ LL | let trivial_empty = Regex::new("^"); = help: the regex is unlikely to be useful as it is error: trivial regex - --> tests/ui/regex.rs:95:36 + --> tests/ui/regex.rs:102:36 | LL | let trivial_empty = Regex::new("^$"); | ^^^^ @@ -188,7 +188,7 @@ LL | let trivial_empty = Regex::new("^$"); = help: consider using `str::is_empty` error: trivial regex - --> tests/ui/regex.rs:98:44 + --> tests/ui/regex.rs:105:44 | LL | let binary_trivial_empty = BRegex::new("^$"); | ^^^^ @@ -196,13 +196,13 @@ LL | let binary_trivial_empty = BRegex::new("^$"); = help: consider using `str::is_empty` error: compiling a regex in a loop - --> tests/ui/regex.rs:125:21 + --> tests/ui/regex.rs:132:21 | LL | let regex = Regex::new("a.b"); | ^^^^^^^^^^ | help: move the regex construction outside this loop - --> tests/ui/regex.rs:122:5 + --> tests/ui/regex.rs:129:5 | LL | loop { | ^^^^ @@ -210,37 +210,37 @@ LL | loop { = help: to override `-D warnings` add `#[allow(clippy::regex_creation_in_loops)]` error: compiling a regex in a loop - --> tests/ui/regex.rs:127:21 + --> tests/ui/regex.rs:134:21 | LL | let regex = BRegex::new("a.b"); | ^^^^^^^^^^^ | help: move the regex construction outside this loop - --> tests/ui/regex.rs:122:5 + --> tests/ui/regex.rs:129:5 | LL | loop { | ^^^^ error: compiling a regex in a loop - --> tests/ui/regex.rs:133:25 + --> tests/ui/regex.rs:140:25 | LL | let regex = Regex::new("a.b"); | ^^^^^^^^^^ | help: move the regex construction outside this loop - --> tests/ui/regex.rs:122:5 + --> tests/ui/regex.rs:129:5 | LL | loop { | ^^^^ error: compiling a regex in a loop - --> tests/ui/regex.rs:138:32 + --> tests/ui/regex.rs:145:32 | LL | let nested_regex = Regex::new("a.b"); | ^^^^^^^^^^ | help: move the regex construction outside this loop - --> tests/ui/regex.rs:137:9 + --> tests/ui/regex.rs:144:9 | LL | for _ in 0..10 { | ^^^^^^^^^^^^^^ diff --git a/tests/ui/renamed_builtin_attr.fixed b/tests/ui/renamed_builtin_attr.fixed index aebf8712dd92..1ad7d8702bc0 100644 --- a/tests/ui/renamed_builtin_attr.fixed +++ b/tests/ui/renamed_builtin_attr.fixed @@ -1,4 +1,5 @@ //@compile-flags: -Zdeduplicate-diagnostics=yes #[clippy::cognitive_complexity = "1"] +//~^ ERROR: usage of deprecated attribute fn main() {} diff --git a/tests/ui/renamed_builtin_attr.rs b/tests/ui/renamed_builtin_attr.rs index 6c18151195f5..0fb43b7f4901 100644 --- a/tests/ui/renamed_builtin_attr.rs +++ b/tests/ui/renamed_builtin_attr.rs @@ -1,4 +1,5 @@ //@compile-flags: -Zdeduplicate-diagnostics=yes #[clippy::cyclomatic_complexity = "1"] +//~^ ERROR: usage of deprecated attribute fn main() {} diff --git a/tests/ui/repeat_once.fixed b/tests/ui/repeat_once.fixed index 72e97350a0c8..e739e176f0ac 100644 --- a/tests/ui/repeat_once.fixed +++ b/tests/ui/repeat_once.fixed @@ -7,9 +7,15 @@ fn main() { let slice = [1; 5]; let a = [1; 5].to_vec(); + //~^ repeat_once let b = slice.to_vec(); + //~^ repeat_once let c = "hello".to_string(); + //~^ repeat_once let d = "hi".to_string(); + //~^ repeat_once let e = s.to_string(); + //~^ repeat_once let f = string.clone(); + //~^ repeat_once } diff --git a/tests/ui/repeat_once.rs b/tests/ui/repeat_once.rs index 7557c4d0bd41..89ab94bbaee8 100644 --- a/tests/ui/repeat_once.rs +++ b/tests/ui/repeat_once.rs @@ -7,9 +7,15 @@ fn main() { let slice = [1; 5]; let a = [1; 5].repeat(1); + //~^ repeat_once let b = slice.repeat(1); + //~^ repeat_once let c = "hello".repeat(N); + //~^ repeat_once let d = "hi".repeat(1); + //~^ repeat_once let e = s.repeat(1); + //~^ repeat_once let f = string.repeat(1); + //~^ repeat_once } diff --git a/tests/ui/repeat_once.stderr b/tests/ui/repeat_once.stderr index 6996dc5eee7d..3db7a3568f8e 100644 --- a/tests/ui/repeat_once.stderr +++ b/tests/ui/repeat_once.stderr @@ -8,31 +8,31 @@ LL | let a = [1; 5].repeat(1); = help: to override `-D warnings` add `#[allow(clippy::repeat_once)]` error: calling `repeat(1)` on slice - --> tests/ui/repeat_once.rs:10:13 + --> tests/ui/repeat_once.rs:11:13 | LL | let b = slice.repeat(1); | ^^^^^^^^^^^^^^^ help: consider using `.to_vec()` instead: `slice.to_vec()` error: calling `repeat(1)` on str - --> tests/ui/repeat_once.rs:11:13 + --> tests/ui/repeat_once.rs:13:13 | LL | let c = "hello".repeat(N); | ^^^^^^^^^^^^^^^^^ help: consider using `.to_string()` instead: `"hello".to_string()` error: calling `repeat(1)` on str - --> tests/ui/repeat_once.rs:12:13 + --> tests/ui/repeat_once.rs:15:13 | LL | let d = "hi".repeat(1); | ^^^^^^^^^^^^^^ help: consider using `.to_string()` instead: `"hi".to_string()` error: calling `repeat(1)` on str - --> tests/ui/repeat_once.rs:13:13 + --> tests/ui/repeat_once.rs:17:13 | LL | let e = s.repeat(1); | ^^^^^^^^^^^ help: consider using `.to_string()` instead: `s.to_string()` error: calling `repeat(1)` on a string literal - --> tests/ui/repeat_once.rs:14:13 + --> tests/ui/repeat_once.rs:19:13 | LL | let f = string.repeat(1); | ^^^^^^^^^^^^^^^^ help: consider using `.clone()` instead: `string.clone()` diff --git a/tests/ui/repeat_vec_with_capacity.fixed b/tests/ui/repeat_vec_with_capacity.fixed index f72b61b5f6cd..8a3b0b4f193f 100644 --- a/tests/ui/repeat_vec_with_capacity.fixed +++ b/tests/ui/repeat_vec_with_capacity.fixed @@ -4,13 +4,13 @@ fn main() { { (0..123).map(|_| Vec::<()>::with_capacity(42)).collect::>(); - //~^ ERROR: repeating `Vec::with_capacity` using `vec![x; n]`, which does not retain capacity + //~^ repeat_vec_with_capacity } { let n = 123; (0..n).map(|_| Vec::<()>::with_capacity(42)).collect::>(); - //~^ ERROR: repeating `Vec::with_capacity` using `vec![x; n]`, which does not retain capacity + //~^ repeat_vec_with_capacity } { @@ -25,7 +25,7 @@ fn main() { { std::iter::repeat_with(|| Vec::<()>::with_capacity(42)); - //~^ ERROR: repeating `Vec::with_capacity` using `iter::repeat`, which does not retain capacity + //~^ repeat_vec_with_capacity } { @@ -37,3 +37,8 @@ fn main() { from_macro!(Vec::<()>::with_capacity(42)); } } + +#[clippy::msrv = "1.27.0"] +fn msrv_check() { + std::iter::repeat(Vec::<()>::with_capacity(42)); +} diff --git a/tests/ui/repeat_vec_with_capacity.rs b/tests/ui/repeat_vec_with_capacity.rs index c0cc81f78436..011202d84757 100644 --- a/tests/ui/repeat_vec_with_capacity.rs +++ b/tests/ui/repeat_vec_with_capacity.rs @@ -4,13 +4,13 @@ fn main() { { vec![Vec::<()>::with_capacity(42); 123]; - //~^ ERROR: repeating `Vec::with_capacity` using `vec![x; n]`, which does not retain capacity + //~^ repeat_vec_with_capacity } { let n = 123; vec![Vec::<()>::with_capacity(42); n]; - //~^ ERROR: repeating `Vec::with_capacity` using `vec![x; n]`, which does not retain capacity + //~^ repeat_vec_with_capacity } { @@ -25,7 +25,7 @@ fn main() { { std::iter::repeat(Vec::<()>::with_capacity(42)); - //~^ ERROR: repeating `Vec::with_capacity` using `iter::repeat`, which does not retain capacity + //~^ repeat_vec_with_capacity } { @@ -37,3 +37,8 @@ fn main() { from_macro!(Vec::<()>::with_capacity(42)); } } + +#[clippy::msrv = "1.27.0"] +fn msrv_check() { + std::iter::repeat(Vec::<()>::with_capacity(42)); +} diff --git a/tests/ui/repeat_vec_with_capacity_nostd.fixed b/tests/ui/repeat_vec_with_capacity_nostd.fixed index ef316f1def41..dcff18723b6c 100644 --- a/tests/ui/repeat_vec_with_capacity_nostd.fixed +++ b/tests/ui/repeat_vec_with_capacity_nostd.fixed @@ -7,4 +7,5 @@ use alloc::vec::Vec; fn nostd() { let _: Vec> = core::iter::repeat_with(|| Vec::with_capacity(42)).take(123).collect(); + //~^ repeat_vec_with_capacity } diff --git a/tests/ui/repeat_vec_with_capacity_nostd.rs b/tests/ui/repeat_vec_with_capacity_nostd.rs index 83b418a56674..84cc78de35ec 100644 --- a/tests/ui/repeat_vec_with_capacity_nostd.rs +++ b/tests/ui/repeat_vec_with_capacity_nostd.rs @@ -7,4 +7,5 @@ use alloc::vec::Vec; fn nostd() { let _: Vec> = iter::repeat(Vec::with_capacity(42)).take(123).collect(); + //~^ repeat_vec_with_capacity } diff --git a/tests/ui/repl_uninit.rs b/tests/ui/repl_uninit.rs index 01bdf79e6422..e9469d4c5e2f 100644 --- a/tests/ui/repl_uninit.rs +++ b/tests/ui/repl_uninit.rs @@ -13,22 +13,24 @@ fn main() { // the following is UB if `might_panic` panics unsafe { let taken_v = mem::replace(&mut v, mem::uninitialized()); - //~^ ERROR: replacing with `mem::uninitialized()` - //~| NOTE: `-D clippy::mem-replace-with-uninit` implied by `-D warnings` + //~^ mem_replace_with_uninit + let new_v = might_panic(taken_v); std::mem::forget(mem::replace(&mut v, new_v)); } unsafe { let taken_v = mem::replace(&mut v, mem::MaybeUninit::uninit().assume_init()); - //~^ ERROR: replacing with `mem::MaybeUninit::uninit().assume_init()` + //~^ mem_replace_with_uninit + let new_v = might_panic(taken_v); std::mem::forget(mem::replace(&mut v, new_v)); } unsafe { let taken_v = mem::replace(&mut v, mem::zeroed()); - //~^ ERROR: replacing with `mem::zeroed()` + //~^ mem_replace_with_uninit + let new_v = might_panic(taken_v); std::mem::forget(mem::replace(&mut v, new_v)); } @@ -41,6 +43,7 @@ fn main() { // this is still not OK, because uninit let taken_u = unsafe { mem::replace(uref, mem::uninitialized()) }; - //~^ ERROR: replacing with `mem::uninitialized()` + //~^ mem_replace_with_uninit + *uref = taken_u + 1; } diff --git a/tests/ui/repl_uninit.stderr b/tests/ui/repl_uninit.stderr index 645c4a16a07e..08b0b265942d 100644 --- a/tests/ui/repl_uninit.stderr +++ b/tests/ui/repl_uninit.stderr @@ -14,7 +14,7 @@ LL | let taken_v = mem::replace(&mut v, mem::MaybeUninit::uninit().assum | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::ptr::read(&mut v)` error: replacing with `mem::zeroed()` - --> tests/ui/repl_uninit.rs:30:23 + --> tests/ui/repl_uninit.rs:31:23 | LL | let taken_v = mem::replace(&mut v, mem::zeroed()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | let taken_v = mem::replace(&mut v, mem::zeroed()); = help: consider using a default value or the `take_mut` crate instead error: replacing with `mem::uninitialized()` - --> tests/ui/repl_uninit.rs:43:28 + --> tests/ui/repl_uninit.rs:45:28 | LL | let taken_u = unsafe { mem::replace(uref, mem::uninitialized()) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::ptr::read(uref)` diff --git a/tests/ui/repr_packed_without_abi.rs b/tests/ui/repr_packed_without_abi.rs index 16b5ededee99..c5f1852e98b8 100644 --- a/tests/ui/repr_packed_without_abi.rs +++ b/tests/ui/repr_packed_without_abi.rs @@ -2,12 +2,14 @@ #[repr(packed)] struct NetworkPacketHeader { + //~^ repr_packed_without_abi header_length: u8, header_version: u16, } #[repr(packed)] union Foo { + //~^ repr_packed_without_abi a: u8, b: u16, } diff --git a/tests/ui/repr_packed_without_abi.stderr b/tests/ui/repr_packed_without_abi.stderr index 4f7acd00db3d..d1078b3e8e48 100644 --- a/tests/ui/repr_packed_without_abi.stderr +++ b/tests/ui/repr_packed_without_abi.stderr @@ -4,6 +4,7 @@ error: item uses `packed` representation without ABI-qualification LL | #[repr(packed)] | ------ `packed` representation set here LL | / struct NetworkPacketHeader { +LL | | LL | | header_length: u8, LL | | header_version: u16, LL | | } @@ -18,11 +19,12 @@ LL | #![deny(clippy::repr_packed_without_abi)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: item uses `packed` representation without ABI-qualification - --> tests/ui/repr_packed_without_abi.rs:10:1 + --> tests/ui/repr_packed_without_abi.rs:11:1 | LL | #[repr(packed)] | ------ `packed` representation set here LL | / union Foo { +LL | | LL | | a: u8, LL | | b: u16, LL | | } diff --git a/tests/ui/reserve_after_initialization.rs b/tests/ui/reserve_after_initialization.rs index b57a8e162c53..7f79dac46536 100644 --- a/tests/ui/reserve_after_initialization.rs +++ b/tests/ui/reserve_after_initialization.rs @@ -8,6 +8,7 @@ use proc_macros::{external, with_span}; // Should lint fn standard() { let mut v1: Vec = vec![]; + //~^ reserve_after_initialization v1.reserve(10); } @@ -15,6 +16,7 @@ fn standard() { fn capacity_as_expr() { let capacity = 10; let mut v2: Vec = vec![]; + //~^ reserve_after_initialization v2.reserve(capacity); } @@ -33,6 +35,7 @@ fn called_with_capacity() { fn assign_expression() { let mut v5: Vec = Vec::new(); v5 = Vec::new(); + //~^ reserve_after_initialization v5.reserve(10); } diff --git a/tests/ui/reserve_after_initialization.stderr b/tests/ui/reserve_after_initialization.stderr index b6dbebb3f14c..e79b59a35d41 100644 --- a/tests/ui/reserve_after_initialization.stderr +++ b/tests/ui/reserve_after_initialization.stderr @@ -2,6 +2,7 @@ error: call to `reserve` immediately after creation --> tests/ui/reserve_after_initialization.rs:10:5 | LL | / let mut v1: Vec = vec![]; +LL | | LL | | v1.reserve(10); | |___________________^ help: consider using `Vec::with_capacity(/* Space hint */)`: `let mut v1: Vec = Vec::with_capacity(10);` | @@ -9,16 +10,18 @@ LL | | v1.reserve(10); = help: to override `-D warnings` add `#[allow(clippy::reserve_after_initialization)]` error: call to `reserve` immediately after creation - --> tests/ui/reserve_after_initialization.rs:17:5 + --> tests/ui/reserve_after_initialization.rs:18:5 | LL | / let mut v2: Vec = vec![]; +LL | | LL | | v2.reserve(capacity); | |_________________________^ help: consider using `Vec::with_capacity(/* Space hint */)`: `let mut v2: Vec = Vec::with_capacity(capacity);` error: call to `reserve` immediately after creation - --> tests/ui/reserve_after_initialization.rs:35:5 + --> tests/ui/reserve_after_initialization.rs:37:5 | LL | / v5 = Vec::new(); +LL | | LL | | v5.reserve(10); | |___________________^ help: consider using `Vec::with_capacity(/* Space hint */)`: `v5 = Vec::with_capacity(10);` diff --git a/tests/ui/rest_pat_in_fully_bound_structs.rs b/tests/ui/rest_pat_in_fully_bound_structs.rs index 51fe346d0926..bede01688972 100644 --- a/tests/ui/rest_pat_in_fully_bound_structs.rs +++ b/tests/ui/rest_pat_in_fully_bound_structs.rs @@ -21,16 +21,16 @@ fn main() { match a_struct { A { a: 5, b: 42, c: "", .. } => {}, // Lint - //~^ ERROR: unnecessary use of `..` pattern in struct binding. All fields were alr + //~^ rest_pat_in_fully_bound_structs A { a: 0, b: 0, c: "", .. } => {}, // Lint - //~^ ERROR: unnecessary use of `..` pattern in struct binding. All fields were alr + //~^ rest_pat_in_fully_bound_structs _ => {}, } match a_struct { A { a: 5, b: 42, .. } => {}, A { a: 0, b: 0, c: "", .. } => {}, // Lint - //~^ ERROR: unnecessary use of `..` pattern in struct binding. All fields were alr + //~^ rest_pat_in_fully_bound_structs _ => {}, } diff --git a/tests/ui/result_filter_map.rs b/tests/ui/result_filter_map.rs index bfe47ffcf380..ebd9c4288e3b 100644 --- a/tests/ui/result_filter_map.rs +++ b/tests/ui/result_filter_map.rs @@ -11,25 +11,25 @@ fn main() { let _ = vec![Ok(1) as Result] .into_iter() .filter(Result::is_ok) - //~^ ERROR: `filter` for `Ok` followed by `unwrap` + //~^ result_filter_map .map(Result::unwrap); let _ = vec![Ok(1) as Result] .into_iter() .filter(|o| o.is_ok()) - //~^ ERROR: `filter` for `Ok` followed by `unwrap` + //~^ result_filter_map .map(|o| o.unwrap()); let _ = vec![1] .into_iter() .map(odds_out) .filter(Result::is_ok) - //~^ ERROR: `filter` for `Ok` followed by `unwrap` + //~^ result_filter_map .map(Result::unwrap); let _ = vec![1] .into_iter() .map(odds_out) .filter(|o| o.is_ok()) - //~^ ERROR: `filter` for `Ok` followed by `unwrap` + //~^ result_filter_map .map(|o| o.unwrap()); } diff --git a/tests/ui/result_large_err.rs b/tests/ui/result_large_err.rs index 9c39f023da2d..fa57b3f553fc 100644 --- a/tests/ui/result_large_err.rs +++ b/tests/ui/result_large_err.rs @@ -8,7 +8,8 @@ pub fn small_err() -> Result<(), u128> { } pub fn large_err() -> Result<(), [u8; 512]> { - //~^ ERROR: the `Err`-variant returned from this function is very large + //~^ result_large_err + Ok(()) } @@ -20,19 +21,22 @@ pub struct FullyDefinedLargeError { impl FullyDefinedLargeError { pub fn ret() -> Result<(), Self> { - //~^ ERROR: the `Err`-variant returned from this function is very large + //~^ result_large_err + Ok(()) } } pub fn struct_error() -> Result<(), FullyDefinedLargeError> { - //~^ ERROR: the `Err`-variant returned from this function is very large + //~^ result_large_err + Ok(()) } type Fdlr = std::result::Result; pub fn large_err_via_type_alias(x: T) -> Fdlr { - //~^ ERROR: the `Err`-variant returned from this function is very large + //~^ result_large_err + Ok(x) } @@ -41,7 +45,8 @@ pub fn param_small_error() -> Result<(), (R, u128)> { } pub fn param_large_error() -> Result<(), (u128, R, FullyDefinedLargeError)> { - //~^ ERROR: the `Err`-variant returned from this function is very large + //~^ result_large_err + Ok(()) } @@ -53,7 +58,8 @@ pub enum LargeErrorVariants { impl LargeErrorVariants<()> { pub fn large_enum_error() -> Result<(), Self> { - //~^ ERROR: the `Err`-variant returned from this function is very large + //~^ result_large_err + Ok(()) } } @@ -66,14 +72,16 @@ enum MultipleLargeVariants { impl MultipleLargeVariants { fn large_enum_error() -> Result<(), Self> { - //~^ ERROR: the `Err`-variant returned from this function is very large + //~^ result_large_err + Ok(()) } } trait TraitForcesLargeError { fn large_error() -> Result<(), [u8; 512]> { - //~^ ERROR: the `Err`-variant returned from this function is very large + //~^ result_large_err + Ok(()) } } @@ -93,7 +101,8 @@ pub union FullyDefinedUnionError { } pub fn large_union_err() -> Result<(), FullyDefinedUnionError> { - //~^ ERROR: the `Err`-variant returned from this function is very large + //~^ result_large_err + Ok(()) } @@ -103,7 +112,8 @@ pub union UnionError { } pub fn param_large_union() -> Result<(), UnionError> { - //~^ ERROR: the `Err`-variant returned from this function is very large + //~^ result_large_err + Ok(()) } @@ -113,12 +123,14 @@ pub struct ArrayError { } pub fn array_error_subst() -> Result<(), ArrayError> { - //~^ ERROR: the `Err`-variant returned from this function is very large + //~^ result_large_err + Ok(()) } pub fn array_error() -> Result<(), ArrayError<(i32, T), U>> { - //~^ ERROR: the `Err`-variant returned from this function is very large + //~^ result_large_err + Ok(()) } diff --git a/tests/ui/result_large_err.stderr b/tests/ui/result_large_err.stderr index 1dff3f9efe81..72fbc3f58961 100644 --- a/tests/ui/result_large_err.stderr +++ b/tests/ui/result_large_err.stderr @@ -9,7 +9,7 @@ LL | pub fn large_err() -> Result<(), [u8; 512]> { = help: to override `-D warnings` add `#[allow(clippy::result_large_err)]` error: the `Err`-variant returned from this function is very large - --> tests/ui/result_large_err.rs:22:21 + --> tests/ui/result_large_err.rs:23:21 | LL | pub fn ret() -> Result<(), Self> { | ^^^^^^^^^^^^^^^^ the `Err`-variant is at least 240 bytes @@ -17,7 +17,7 @@ LL | pub fn ret() -> Result<(), Self> { = help: try reducing the size of `FullyDefinedLargeError`, for example by boxing large elements or replacing it with `Box` error: the `Err`-variant returned from this function is very large - --> tests/ui/result_large_err.rs:28:26 + --> tests/ui/result_large_err.rs:30:26 | LL | pub fn struct_error() -> Result<(), FullyDefinedLargeError> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 240 bytes @@ -25,7 +25,7 @@ LL | pub fn struct_error() -> Result<(), FullyDefinedLargeError> { = help: try reducing the size of `FullyDefinedLargeError`, for example by boxing large elements or replacing it with `Box` error: the `Err`-variant returned from this function is very large - --> tests/ui/result_large_err.rs:34:45 + --> tests/ui/result_large_err.rs:37:45 | LL | pub fn large_err_via_type_alias(x: T) -> Fdlr { | ^^^^^^^ the `Err`-variant is at least 240 bytes @@ -33,7 +33,7 @@ LL | pub fn large_err_via_type_alias(x: T) -> Fdlr { = help: try reducing the size of `FullyDefinedLargeError`, for example by boxing large elements or replacing it with `Box` error: the `Err`-variant returned from this function is very large - --> tests/ui/result_large_err.rs:43:34 + --> tests/ui/result_large_err.rs:47:34 | LL | pub fn param_large_error() -> Result<(), (u128, R, FullyDefinedLargeError)> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 256 bytes @@ -41,7 +41,7 @@ LL | pub fn param_large_error() -> Result<(), (u128, R, FullyDefinedLargeErro = help: try reducing the size of `(u128, R, FullyDefinedLargeError)`, for example by boxing large elements or replacing it with `Box<(u128, R, FullyDefinedLargeError)>` error: the `Err`-variant returned from this function is very large - --> tests/ui/result_large_err.rs:55:34 + --> tests/ui/result_large_err.rs:60:34 | LL | _Omg([u8; 512]), | --------------- the largest variant contains at least 512 bytes @@ -52,7 +52,7 @@ LL | pub fn large_enum_error() -> Result<(), Self> { = help: try reducing the size of `LargeErrorVariants<()>`, for example by boxing large elements or replacing it with `Box>` error: the `Err`-variant returned from this function is very large - --> tests/ui/result_large_err.rs:68:30 + --> tests/ui/result_large_err.rs:74:30 | LL | _Biggest([u8; 1024]), | -------------------- the largest variant contains at least 1024 bytes @@ -65,7 +65,7 @@ LL | fn large_enum_error() -> Result<(), Self> { = help: try reducing the size of `MultipleLargeVariants`, for example by boxing large elements or replacing it with `Box` error: the `Err`-variant returned from this function is very large - --> tests/ui/result_large_err.rs:75:25 + --> tests/ui/result_large_err.rs:82:25 | LL | fn large_error() -> Result<(), [u8; 512]> { | ^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes @@ -73,7 +73,7 @@ LL | fn large_error() -> Result<(), [u8; 512]> { = help: try reducing the size of `[u8; 512]`, for example by boxing large elements or replacing it with `Box<[u8; 512]>` error: the `Err`-variant returned from this function is very large - --> tests/ui/result_large_err.rs:95:29 + --> tests/ui/result_large_err.rs:103:29 | LL | pub fn large_union_err() -> Result<(), FullyDefinedUnionError> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes @@ -81,7 +81,7 @@ LL | pub fn large_union_err() -> Result<(), FullyDefinedUnionError> { = help: try reducing the size of `FullyDefinedUnionError`, for example by boxing large elements or replacing it with `Box` error: the `Err`-variant returned from this function is very large - --> tests/ui/result_large_err.rs:105:40 + --> tests/ui/result_large_err.rs:114:40 | LL | pub fn param_large_union() -> Result<(), UnionError> { | ^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes @@ -89,7 +89,7 @@ LL | pub fn param_large_union() -> Result<(), UnionError> { = help: try reducing the size of `UnionError`, for example by boxing large elements or replacing it with `Box>` error: the `Err`-variant returned from this function is very large - --> tests/ui/result_large_err.rs:115:34 + --> tests/ui/result_large_err.rs:125:34 | LL | pub fn array_error_subst() -> Result<(), ArrayError> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 128 bytes @@ -97,7 +97,7 @@ LL | pub fn array_error_subst() -> Result<(), ArrayError> { = help: try reducing the size of `ArrayError`, for example by boxing large elements or replacing it with `Box>` error: the `Err`-variant returned from this function is very large - --> tests/ui/result_large_err.rs:120:31 + --> tests/ui/result_large_err.rs:131:31 | LL | pub fn array_error() -> Result<(), ArrayError<(i32, T), U>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 128 bytes diff --git a/tests/ui/result_map_or_into_option.fixed b/tests/ui/result_map_or_into_option.fixed index cf42b24b2dda..4cf218b84642 100644 --- a/tests/ui/result_map_or_into_option.fixed +++ b/tests/ui/result_map_or_into_option.fixed @@ -3,12 +3,14 @@ fn main() { let opt: Result = Ok(1); let _ = opt.ok(); - //~^ ERROR: called `map_or(None, Some)` on a `Result` value + //~^ result_map_or_into_option + let _ = opt.ok(); - //~^ ERROR: called `map_or_else(|_| None, Some)` on a `Result` value + //~^ result_map_or_into_option + #[rustfmt::skip] let _ = opt.ok(); - //~^ ERROR: called `map_or_else(|_| None, Some)` on a `Result` value + //~^ result_map_or_into_option let rewrap = |s: u32| -> Option { Some(s) }; diff --git a/tests/ui/result_map_or_into_option.rs b/tests/ui/result_map_or_into_option.rs index cdb45d6b82a0..9a0bde8569e8 100644 --- a/tests/ui/result_map_or_into_option.rs +++ b/tests/ui/result_map_or_into_option.rs @@ -3,12 +3,14 @@ fn main() { let opt: Result = Ok(1); let _ = opt.map_or(None, Some); - //~^ ERROR: called `map_or(None, Some)` on a `Result` value + //~^ result_map_or_into_option + let _ = opt.map_or_else(|_| None, Some); - //~^ ERROR: called `map_or_else(|_| None, Some)` on a `Result` value + //~^ result_map_or_into_option + #[rustfmt::skip] let _ = opt.map_or_else(|_| { None }, Some); - //~^ ERROR: called `map_or_else(|_| None, Some)` on a `Result` value + //~^ result_map_or_into_option let rewrap = |s: u32| -> Option { Some(s) }; diff --git a/tests/ui/result_map_or_into_option.stderr b/tests/ui/result_map_or_into_option.stderr index 4cb510d77a06..f9058d35e6c6 100644 --- a/tests/ui/result_map_or_into_option.stderr +++ b/tests/ui/result_map_or_into_option.stderr @@ -8,13 +8,13 @@ LL | let _ = opt.map_or(None, Some); = help: to override `-D warnings` add `#[allow(clippy::result_map_or_into_option)]` error: called `map_or_else(|_| None, Some)` on a `Result` value - --> tests/ui/result_map_or_into_option.rs:7:13 + --> tests/ui/result_map_or_into_option.rs:8:13 | LL | let _ = opt.map_or_else(|_| None, Some); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `ok`: `opt.ok()` error: called `map_or_else(|_| None, Some)` on a `Result` value - --> tests/ui/result_map_or_into_option.rs:10:13 + --> tests/ui/result_map_or_into_option.rs:12:13 | LL | let _ = opt.map_or_else(|_| { None }, Some); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `ok`: `opt.ok()` diff --git a/tests/ui/result_map_unit_fn_fixable.fixed b/tests/ui/result_map_unit_fn_fixable.fixed index 3890f916b606..6bee013c3f47 100644 --- a/tests/ui/result_map_unit_fn_fixable.fixed +++ b/tests/ui/result_map_unit_fn_fixable.fixed @@ -32,50 +32,68 @@ fn result_map_unit_fn() { let _: Result<(), usize> = x.field.map(do_nothing); if let Ok(x_field) = x.field { do_nothing(x_field) } + //~^ result_map_unit_fn if let Ok(x_field) = x.field { do_nothing(x_field) } + //~^ result_map_unit_fn if let Ok(x_field) = x.field { diverge(x_field) } + //~^ result_map_unit_fn let captured = 10; if let Ok(value) = x.field { do_nothing(value + captured) }; let _: Result<(), usize> = x.field.map(|value| do_nothing(value + captured)); if let Ok(value) = x.field { x.do_result_nothing(value + captured) } + //~^ result_map_unit_fn if let Ok(value) = x.field { x.do_result_plus_one(value + captured); } + //~^ result_map_unit_fn if let Ok(value) = x.field { do_nothing(value + captured) } + //~^ result_map_unit_fn if let Ok(value) = x.field { do_nothing(value + captured) } + //~^ result_map_unit_fn if let Ok(value) = x.field { do_nothing(value + captured); } + //~^ result_map_unit_fn if let Ok(value) = x.field { do_nothing(value + captured); } + //~^ result_map_unit_fn if let Ok(value) = x.field { diverge(value + captured) } + //~^ result_map_unit_fn if let Ok(value) = x.field { diverge(value + captured) } + //~^ result_map_unit_fn if let Ok(value) = x.field { diverge(value + captured); } + //~^ result_map_unit_fn if let Ok(value) = x.field { diverge(value + captured); } + //~^ result_map_unit_fn x.field.map(|value| plus_one(value + captured)); x.field.map(|value| { plus_one(value + captured) }); if let Ok(value) = x.field { let y = plus_one(value + captured); } + //~^ result_map_unit_fn if let Ok(value) = x.field { plus_one(value + captured); } + //~^ result_map_unit_fn if let Ok(value) = x.field { plus_one(value + captured); } + //~^ result_map_unit_fn if let Ok(ref value) = x.field { do_nothing(value + captured) } + //~^ result_map_unit_fn if let Ok(value) = x.field { println!("{:?}", value) } + //~^ result_map_unit_fn } fn main() {} diff --git a/tests/ui/result_map_unit_fn_fixable.rs b/tests/ui/result_map_unit_fn_fixable.rs index c3f5aca7bfbe..a206cfe6842f 100644 --- a/tests/ui/result_map_unit_fn_fixable.rs +++ b/tests/ui/result_map_unit_fn_fixable.rs @@ -32,50 +32,68 @@ fn result_map_unit_fn() { let _: Result<(), usize> = x.field.map(do_nothing); x.field.map(do_nothing); + //~^ result_map_unit_fn x.field.map(do_nothing); + //~^ result_map_unit_fn x.field.map(diverge); + //~^ result_map_unit_fn let captured = 10; if let Ok(value) = x.field { do_nothing(value + captured) }; let _: Result<(), usize> = x.field.map(|value| do_nothing(value + captured)); x.field.map(|value| x.do_result_nothing(value + captured)); + //~^ result_map_unit_fn x.field.map(|value| { x.do_result_plus_one(value + captured); }); + //~^ result_map_unit_fn x.field.map(|value| do_nothing(value + captured)); + //~^ result_map_unit_fn x.field.map(|value| { do_nothing(value + captured) }); + //~^ result_map_unit_fn x.field.map(|value| { do_nothing(value + captured); }); + //~^ result_map_unit_fn x.field.map(|value| { { do_nothing(value + captured); } }); + //~^ result_map_unit_fn x.field.map(|value| diverge(value + captured)); + //~^ result_map_unit_fn x.field.map(|value| { diverge(value + captured) }); + //~^ result_map_unit_fn x.field.map(|value| { diverge(value + captured); }); + //~^ result_map_unit_fn x.field.map(|value| { { diverge(value + captured); } }); + //~^ result_map_unit_fn x.field.map(|value| plus_one(value + captured)); x.field.map(|value| { plus_one(value + captured) }); x.field.map(|value| { let y = plus_one(value + captured); }); + //~^ result_map_unit_fn x.field.map(|value| { plus_one(value + captured); }); + //~^ result_map_unit_fn x.field.map(|value| { { plus_one(value + captured); } }); + //~^ result_map_unit_fn x.field.map(|ref value| { do_nothing(value + captured) }); + //~^ result_map_unit_fn x.field.map(|value| println!("{:?}", value)); + //~^ result_map_unit_fn } fn main() {} diff --git a/tests/ui/result_map_unit_fn_fixable.stderr b/tests/ui/result_map_unit_fn_fixable.stderr index 4f3bc2e95449..eca844e06cc0 100644 --- a/tests/ui/result_map_unit_fn_fixable.stderr +++ b/tests/ui/result_map_unit_fn_fixable.stderr @@ -10,7 +10,7 @@ LL | x.field.map(do_nothing); = help: to override `-D warnings` add `#[allow(clippy::result_map_unit_fn)]` error: called `map(f)` on an `Result` value where `f` is a function that returns the unit type `()` - --> tests/ui/result_map_unit_fn_fixable.rs:36:5 + --> tests/ui/result_map_unit_fn_fixable.rs:37:5 | LL | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- @@ -18,7 +18,7 @@ LL | x.field.map(do_nothing); | help: try: `if let Ok(x_field) = x.field { do_nothing(x_field) }` error: called `map(f)` on an `Result` value where `f` is a function that returns the unit type `()` - --> tests/ui/result_map_unit_fn_fixable.rs:38:5 + --> tests/ui/result_map_unit_fn_fixable.rs:40:5 | LL | x.field.map(diverge); | ^^^^^^^^^^^^^^^^^^^^- @@ -26,7 +26,7 @@ LL | x.field.map(diverge); | help: try: `if let Ok(x_field) = x.field { diverge(x_field) }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` - --> tests/ui/result_map_unit_fn_fixable.rs:44:5 + --> tests/ui/result_map_unit_fn_fixable.rs:47:5 | LL | x.field.map(|value| x.do_result_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -34,7 +34,7 @@ LL | x.field.map(|value| x.do_result_nothing(value + captured)); | help: try: `if let Ok(value) = x.field { x.do_result_nothing(value + captured) }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` - --> tests/ui/result_map_unit_fn_fixable.rs:46:5 + --> tests/ui/result_map_unit_fn_fixable.rs:50:5 | LL | x.field.map(|value| { x.do_result_plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -42,7 +42,7 @@ LL | x.field.map(|value| { x.do_result_plus_one(value + captured); }); | help: try: `if let Ok(value) = x.field { x.do_result_plus_one(value + captured); }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` - --> tests/ui/result_map_unit_fn_fixable.rs:49:5 + --> tests/ui/result_map_unit_fn_fixable.rs:54:5 | LL | x.field.map(|value| do_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -50,7 +50,7 @@ LL | x.field.map(|value| do_nothing(value + captured)); | help: try: `if let Ok(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` - --> tests/ui/result_map_unit_fn_fixable.rs:51:5 + --> tests/ui/result_map_unit_fn_fixable.rs:57:5 | LL | x.field.map(|value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -58,7 +58,7 @@ LL | x.field.map(|value| { do_nothing(value + captured) }); | help: try: `if let Ok(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` - --> tests/ui/result_map_unit_fn_fixable.rs:53:5 + --> tests/ui/result_map_unit_fn_fixable.rs:60:5 | LL | x.field.map(|value| { do_nothing(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -66,7 +66,7 @@ LL | x.field.map(|value| { do_nothing(value + captured); }); | help: try: `if let Ok(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` - --> tests/ui/result_map_unit_fn_fixable.rs:55:5 + --> tests/ui/result_map_unit_fn_fixable.rs:63:5 | LL | x.field.map(|value| { { do_nothing(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -74,7 +74,7 @@ LL | x.field.map(|value| { { do_nothing(value + captured); } }); | help: try: `if let Ok(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` - --> tests/ui/result_map_unit_fn_fixable.rs:58:5 + --> tests/ui/result_map_unit_fn_fixable.rs:67:5 | LL | x.field.map(|value| diverge(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -82,7 +82,7 @@ LL | x.field.map(|value| diverge(value + captured)); | help: try: `if let Ok(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` - --> tests/ui/result_map_unit_fn_fixable.rs:60:5 + --> tests/ui/result_map_unit_fn_fixable.rs:70:5 | LL | x.field.map(|value| { diverge(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -90,7 +90,7 @@ LL | x.field.map(|value| { diverge(value + captured) }); | help: try: `if let Ok(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` - --> tests/ui/result_map_unit_fn_fixable.rs:62:5 + --> tests/ui/result_map_unit_fn_fixable.rs:73:5 | LL | x.field.map(|value| { diverge(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -98,7 +98,7 @@ LL | x.field.map(|value| { diverge(value + captured); }); | help: try: `if let Ok(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` - --> tests/ui/result_map_unit_fn_fixable.rs:64:5 + --> tests/ui/result_map_unit_fn_fixable.rs:76:5 | LL | x.field.map(|value| { { diverge(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -106,7 +106,7 @@ LL | x.field.map(|value| { { diverge(value + captured); } }); | help: try: `if let Ok(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` - --> tests/ui/result_map_unit_fn_fixable.rs:69:5 + --> tests/ui/result_map_unit_fn_fixable.rs:82:5 | LL | x.field.map(|value| { let y = plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -114,7 +114,7 @@ LL | x.field.map(|value| { let y = plus_one(value + captured); }); | help: try: `if let Ok(value) = x.field { let y = plus_one(value + captured); }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` - --> tests/ui/result_map_unit_fn_fixable.rs:71:5 + --> tests/ui/result_map_unit_fn_fixable.rs:85:5 | LL | x.field.map(|value| { plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -122,7 +122,7 @@ LL | x.field.map(|value| { plus_one(value + captured); }); | help: try: `if let Ok(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` - --> tests/ui/result_map_unit_fn_fixable.rs:73:5 + --> tests/ui/result_map_unit_fn_fixable.rs:88:5 | LL | x.field.map(|value| { { plus_one(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -130,7 +130,7 @@ LL | x.field.map(|value| { { plus_one(value + captured); } }); | help: try: `if let Ok(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` - --> tests/ui/result_map_unit_fn_fixable.rs:76:5 + --> tests/ui/result_map_unit_fn_fixable.rs:92:5 | LL | x.field.map(|ref value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -138,7 +138,7 @@ LL | x.field.map(|ref value| { do_nothing(value + captured) }); | help: try: `if let Ok(ref value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` - --> tests/ui/result_map_unit_fn_fixable.rs:78:5 + --> tests/ui/result_map_unit_fn_fixable.rs:95:5 | LL | x.field.map(|value| println!("{:?}", value)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- diff --git a/tests/ui/result_map_unit_fn_unfixable.rs b/tests/ui/result_map_unit_fn_unfixable.rs index 62798b6d3d6f..fe3d8ece39f4 100644 --- a/tests/ui/result_map_unit_fn_unfixable.rs +++ b/tests/ui/result_map_unit_fn_unfixable.rs @@ -21,33 +21,39 @@ fn result_map_unit_fn() { let x = HasResult { field: Ok(10) }; x.field.map(|value| { do_nothing(value); do_nothing(value) }); - //~^ ERROR: called `map(f)` on an `Result` value where `f` is a closure that returns t - //~| NOTE: `-D clippy::result-map-unit-fn` implied by `-D warnings` + //~^ result_map_unit_fn + + x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); - //~^ ERROR: called `map(f)` on an `Result` value where `f` is a closure that returns t + //~^ result_map_unit_fn + // Suggestion for the let block should be `{ ... }` as it's too difficult to build a // proper suggestion for these cases x.field.map(|value| { - //~^ ERROR: called `map(f)` on an `Result` value where `f` is a closure that returns t + //~^ result_map_unit_fn + do_nothing(value); do_nothing(value) }); x.field.map(|value| { do_nothing(value); do_nothing(value); }); - //~^ ERROR: called `map(f)` on an `Result` value where `f` is a closure that returns t + //~^ result_map_unit_fn + // The following should suggest `if let Ok(_X) ...` as it's difficult to generate a proper let variable name for them let res: Result = Ok(42).map(diverge); "12".parse::().map(diverge); - //~^ ERROR: called `map(f)` on an `Result` value where `f` is a function that returns + //~^ result_map_unit_fn + let res: Result<(), usize> = Ok(plus_one(1)).map(do_nothing); // Should suggest `if let Ok(_y) ...` to not override the existing foo variable let y: Result = Ok(42); y.map(do_nothing); - //~^ ERROR: called `map(f)` on an `Result` value where `f` is a function that returns + //~^ result_map_unit_fn + } fn main() {} diff --git a/tests/ui/result_map_unit_fn_unfixable.stderr b/tests/ui/result_map_unit_fn_unfixable.stderr index d69c86c70e29..a6e38d808afa 100644 --- a/tests/ui/result_map_unit_fn_unfixable.stderr +++ b/tests/ui/result_map_unit_fn_unfixable.stderr @@ -10,7 +10,7 @@ LL | x.field.map(|value| { do_nothing(value); do_nothing(value) }); = help: to override `-D warnings` add `#[allow(clippy::result_map_unit_fn)]` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` - --> tests/ui/result_map_unit_fn_unfixable.rs:27:5 + --> tests/ui/result_map_unit_fn_unfixable.rs:28:5 | LL | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -18,10 +18,11 @@ LL | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) | help: try: `if let Ok(value) = x.field { ... }` error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` - --> tests/ui/result_map_unit_fn_unfixable.rs:32:5 + --> tests/ui/result_map_unit_fn_unfixable.rs:34:5 | LL | // x.field.map(|value| { LL | || +LL | || LL | || do_nothing(value); LL | || do_nothing(value) LL | || }); @@ -30,7 +31,7 @@ LL | || }); | error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` - --> tests/ui/result_map_unit_fn_unfixable.rs:37:5 + --> tests/ui/result_map_unit_fn_unfixable.rs:40:5 | LL | x.field.map(|value| { do_nothing(value); do_nothing(value); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -38,7 +39,7 @@ LL | x.field.map(|value| { do_nothing(value); do_nothing(value); }); | help: try: `if let Ok(value) = x.field { ... }` error: called `map(f)` on an `Result` value where `f` is a function that returns the unit type `()` - --> tests/ui/result_map_unit_fn_unfixable.rs:42:5 + --> tests/ui/result_map_unit_fn_unfixable.rs:46:5 | LL | "12".parse::().map(diverge); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -46,7 +47,7 @@ LL | "12".parse::().map(diverge); | help: try: `if let Ok(a) = "12".parse::() { diverge(a) }` error: called `map(f)` on an `Result` value where `f` is a function that returns the unit type `()` - --> tests/ui/result_map_unit_fn_unfixable.rs:49:5 + --> tests/ui/result_map_unit_fn_unfixable.rs:54:5 | LL | y.map(do_nothing); | ^^^^^^^^^^^^^^^^^- diff --git a/tests/ui/result_unit_error.rs b/tests/ui/result_unit_error.rs index f3159f2e9515..ddbe0eb556c8 100644 --- a/tests/ui/result_unit_error.rs +++ b/tests/ui/result_unit_error.rs @@ -1,7 +1,8 @@ #![warn(clippy::result_unit_err)] pub fn returns_unit_error() -> Result { - //~^ ERROR: this returns a `Result<_, ()>` + //~^ result_unit_err + Err(()) } @@ -11,10 +12,11 @@ fn private_unit_errors() -> Result { pub trait HasUnitError { fn get_that_error(&self) -> Result; - //~^ ERROR: this returns a `Result<_, ()>` + //~^ result_unit_err fn get_this_one_too(&self) -> Result { - //~^ ERROR: this returns a `Result<_, ()>` + //~^ result_unit_err + Err(()) } } @@ -33,7 +35,8 @@ pub struct UnitErrorHolder; impl UnitErrorHolder { pub fn unit_error(&self) -> Result { - //~^ ERROR: this returns a `Result<_, ()>` + //~^ result_unit_err + Ok(0) } } @@ -43,7 +46,8 @@ pub mod issue_6546 { type ResInv = Result; pub fn should_lint() -> ResInv<(), usize> { - //~^ ERROR: this returns a `Result<_, ()>` + //~^ result_unit_err + Ok(0) } diff --git a/tests/ui/result_unit_error.stderr b/tests/ui/result_unit_error.stderr index e869a3159775..d6c0924d8868 100644 --- a/tests/ui/result_unit_error.stderr +++ b/tests/ui/result_unit_error.stderr @@ -9,7 +9,7 @@ LL | pub fn returns_unit_error() -> Result { = help: to override `-D warnings` add `#[allow(clippy::result_unit_err)]` error: this returns a `Result<_, ()>` - --> tests/ui/result_unit_error.rs:13:5 + --> tests/ui/result_unit_error.rs:14:5 | LL | fn get_that_error(&self) -> Result; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | fn get_that_error(&self) -> Result; = help: use a custom `Error` type instead error: this returns a `Result<_, ()>` - --> tests/ui/result_unit_error.rs:16:5 + --> tests/ui/result_unit_error.rs:17:5 | LL | fn get_this_one_too(&self) -> Result { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | fn get_this_one_too(&self) -> Result { = help: use a custom `Error` type instead error: this returns a `Result<_, ()>` - --> tests/ui/result_unit_error.rs:35:5 + --> tests/ui/result_unit_error.rs:37:5 | LL | pub fn unit_error(&self) -> Result { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | pub fn unit_error(&self) -> Result { = help: use a custom `Error` type instead error: this returns a `Result<_, ()>` - --> tests/ui/result_unit_error.rs:45:5 + --> tests/ui/result_unit_error.rs:48:5 | LL | pub fn should_lint() -> ResInv<(), usize> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/result_unit_error_no_std.rs b/tests/ui/result_unit_error_no_std.rs index c9f4996c3689..8a1849b8490a 100644 --- a/tests/ui/result_unit_error_no_std.rs +++ b/tests/ui/result_unit_error_no_std.rs @@ -10,6 +10,7 @@ pub fn returns_unit_error_no_lint() -> Result { #[clippy::msrv = "1.81"] pub fn returns_unit_error_lint() -> Result { + //~^ result_unit_err Err(()) } diff --git a/tests/ui/return_and_then.fixed b/tests/ui/return_and_then.fixed index 9736a51ac868..74efa14eeec8 100644 --- a/tests/ui/return_and_then.fixed +++ b/tests/ui/return_and_then.fixed @@ -3,6 +3,7 @@ fn main() { fn test_opt_block(opt: Option) -> Option { let n = opt?; + //~^ return_and_then let mut ret = n + 1; ret += n; if n > 1 { Some(ret) } else { None } @@ -11,32 +12,38 @@ fn main() { fn test_opt_func(opt: Option) -> Option { let n = opt?; test_opt_block(Some(n)) + //~^ return_and_then } fn test_call_chain() -> Option { let n = gen_option(1)?; test_opt_block(Some(n)) + //~^ return_and_then } fn test_res_block(opt: Result) -> Result { let n = opt?; if n > 1 { Ok(n + 1) } else { Err(n) } + //~^ return_and_then } fn test_res_func(opt: Result) -> Result { let n = opt?; test_res_block(Ok(n)) + //~^ return_and_then } fn test_ref_only() -> Option { // ref: empty string let x = Some("")?; if x.len() > 2 { Some(3) } else { None } + //~^ return_and_then } fn test_tmp_only() -> Option { // unused temporary: vec![1, 2, 4] let x = Some(match (vec![1, 2, 3], vec![1, 2, 4]) { + //~^ return_and_then (a, _) if a.len() > 1 => a, (_, b) => b, })?; diff --git a/tests/ui/return_and_then.rs b/tests/ui/return_and_then.rs index 8bcbdfc3a632..188dc57e588c 100644 --- a/tests/ui/return_and_then.rs +++ b/tests/ui/return_and_then.rs @@ -3,6 +3,7 @@ fn main() { fn test_opt_block(opt: Option) -> Option { opt.and_then(|n| { + //~^ return_and_then let mut ret = n + 1; ret += n; if n > 1 { Some(ret) } else { None } @@ -11,28 +12,34 @@ fn main() { fn test_opt_func(opt: Option) -> Option { opt.and_then(|n| test_opt_block(Some(n))) + //~^ return_and_then } fn test_call_chain() -> Option { gen_option(1).and_then(|n| test_opt_block(Some(n))) + //~^ return_and_then } fn test_res_block(opt: Result) -> Result { opt.and_then(|n| if n > 1 { Ok(n + 1) } else { Err(n) }) + //~^ return_and_then } fn test_res_func(opt: Result) -> Result { opt.and_then(|n| test_res_block(Ok(n))) + //~^ return_and_then } fn test_ref_only() -> Option { // ref: empty string Some("").and_then(|x| if x.len() > 2 { Some(3) } else { None }) + //~^ return_and_then } fn test_tmp_only() -> Option { // unused temporary: vec![1, 2, 4] Some(match (vec![1, 2, 3], vec![1, 2, 4]) { + //~^ return_and_then (a, _) if a.len() > 1 => a, (_, b) => b, }) diff --git a/tests/ui/return_and_then.stderr b/tests/ui/return_and_then.stderr index b2e8bf2ca45a..cc611c3dba67 100644 --- a/tests/ui/return_and_then.stderr +++ b/tests/ui/return_and_then.stderr @@ -2,6 +2,7 @@ error: use the question mark operator instead of an `and_then` call --> tests/ui/return_and_then.rs:5:9 | LL | / opt.and_then(|n| { +LL | | LL | | let mut ret = n + 1; LL | | ret += n; LL | | if n > 1 { Some(ret) } else { None } @@ -13,13 +14,14 @@ LL | | }) help: try | LL ~ let n = opt?; +LL + LL + let mut ret = n + 1; LL + ret += n; LL + if n > 1 { Some(ret) } else { None } | error: use the question mark operator instead of an `and_then` call - --> tests/ui/return_and_then.rs:13:9 + --> tests/ui/return_and_then.rs:14:9 | LL | opt.and_then(|n| test_opt_block(Some(n))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -31,7 +33,7 @@ LL + test_opt_block(Some(n)) | error: use the question mark operator instead of an `and_then` call - --> tests/ui/return_and_then.rs:17:9 + --> tests/ui/return_and_then.rs:19:9 | LL | gen_option(1).and_then(|n| test_opt_block(Some(n))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -43,7 +45,7 @@ LL + test_opt_block(Some(n)) | error: use the question mark operator instead of an `and_then` call - --> tests/ui/return_and_then.rs:21:9 + --> tests/ui/return_and_then.rs:24:9 | LL | opt.and_then(|n| if n > 1 { Ok(n + 1) } else { Err(n) }) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -55,7 +57,7 @@ LL + if n > 1 { Ok(n + 1) } else { Err(n) } | error: use the question mark operator instead of an `and_then` call - --> tests/ui/return_and_then.rs:25:9 + --> tests/ui/return_and_then.rs:29:9 | LL | opt.and_then(|n| test_res_block(Ok(n))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -67,7 +69,7 @@ LL + test_res_block(Ok(n)) | error: use the question mark operator instead of an `and_then` call - --> tests/ui/return_and_then.rs:30:9 + --> tests/ui/return_and_then.rs:35:9 | LL | Some("").and_then(|x| if x.len() > 2 { Some(3) } else { None }) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -79,9 +81,10 @@ LL + if x.len() > 2 { Some(3) } else { None } | error: use the question mark operator instead of an `and_then` call - --> tests/ui/return_and_then.rs:35:9 + --> tests/ui/return_and_then.rs:41:9 | LL | / Some(match (vec![1, 2, 3], vec![1, 2, 4]) { +LL | | LL | | (a, _) if a.len() > 1 => a, LL | | (_, b) => b, LL | | }) @@ -91,6 +94,7 @@ LL | | .and_then(|x| if x.len() > 2 { Some(3) } else { None }) help: try | LL ~ let x = Some(match (vec![1, 2, 3], vec![1, 2, 4]) { +LL + LL + (a, _) if a.len() > 1 => a, LL + (_, b) => b, LL + })?; diff --git a/tests/ui/return_self_not_must_use.rs b/tests/ui/return_self_not_must_use.rs index ec6f0feb8e65..83965662d15e 100644 --- a/tests/ui/return_self_not_must_use.rs +++ b/tests/ui/return_self_not_must_use.rs @@ -6,7 +6,8 @@ pub struct Bar; pub trait Whatever { fn what(&self) -> Self; - //~^ ERROR: missing `#[must_use]` attribute on a method returning `Self` + //~^ return_self_not_must_use + // There should be no warning here! (returns a reference) fn what2(&self) -> &Self; } @@ -17,11 +18,13 @@ impl Bar { Self } pub fn foo(&self) -> Self { - //~^ ERROR: missing `#[must_use]` attribute on a method returning `Self` + //~^ return_self_not_must_use + Self } pub fn bar(self) -> Self { - //~^ ERROR: missing `#[must_use]` attribute on a method returning `Self` + //~^ return_self_not_must_use + self } // There should be no warning here! (private method) diff --git a/tests/ui/return_self_not_must_use.stderr b/tests/ui/return_self_not_must_use.stderr index 01f826b94a80..3e6a28f32920 100644 --- a/tests/ui/return_self_not_must_use.stderr +++ b/tests/ui/return_self_not_must_use.stderr @@ -9,10 +9,11 @@ LL | fn what(&self) -> Self; = help: to override `-D warnings` add `#[allow(clippy::return_self_not_must_use)]` error: missing `#[must_use]` attribute on a method returning `Self` - --> tests/ui/return_self_not_must_use.rs:19:5 + --> tests/ui/return_self_not_must_use.rs:20:5 | LL | / pub fn foo(&self) -> Self { LL | | +LL | | LL | | Self LL | | } | |_____^ @@ -20,10 +21,11 @@ LL | | } = help: consider adding the `#[must_use]` attribute to the method or directly to the `Self` type error: missing `#[must_use]` attribute on a method returning `Self` - --> tests/ui/return_self_not_must_use.rs:23:5 + --> tests/ui/return_self_not_must_use.rs:25:5 | LL | / pub fn bar(self) -> Self { LL | | +LL | | LL | | self LL | | } | |_____^ diff --git a/tests/ui/reversed_empty_ranges_fixable.fixed b/tests/ui/reversed_empty_ranges_fixable.fixed index c8bf1b35085d..ba5059bbaa37 100644 --- a/tests/ui/reversed_empty_ranges_fixable.fixed +++ b/tests/ui/reversed_empty_ranges_fixable.fixed @@ -7,10 +7,14 @@ fn main() { // These should be linted: (21..=42).rev().for_each(|x| println!("{}", x)); + //~^ reversed_empty_ranges let _ = (21..ANSWER).rev().filter(|x| x % 2 == 0).take(10).collect::>(); + //~^ reversed_empty_ranges for _ in (-42..=-21).rev() {} + //~^ reversed_empty_ranges for _ in (21u32..42u32).rev() {} + //~^ reversed_empty_ranges // These should be ignored as they are not empty ranges: diff --git a/tests/ui/reversed_empty_ranges_fixable.rs b/tests/ui/reversed_empty_ranges_fixable.rs index 6733c096420b..4068bc393066 100644 --- a/tests/ui/reversed_empty_ranges_fixable.rs +++ b/tests/ui/reversed_empty_ranges_fixable.rs @@ -7,10 +7,14 @@ fn main() { // These should be linted: (42..=21).for_each(|x| println!("{}", x)); + //~^ reversed_empty_ranges let _ = (ANSWER..21).filter(|x| x % 2 == 0).take(10).collect::>(); + //~^ reversed_empty_ranges for _ in -21..=-42 {} + //~^ reversed_empty_ranges for _ in 42u32..21u32 {} + //~^ reversed_empty_ranges // These should be ignored as they are not empty ranges: diff --git a/tests/ui/reversed_empty_ranges_fixable.stderr b/tests/ui/reversed_empty_ranges_fixable.stderr index 24cb959c96af..3fadc4c169f1 100644 --- a/tests/ui/reversed_empty_ranges_fixable.stderr +++ b/tests/ui/reversed_empty_ranges_fixable.stderr @@ -13,7 +13,7 @@ LL + (21..=42).rev().for_each(|x| println!("{}", x)); | error: this range is empty so it will yield no values - --> tests/ui/reversed_empty_ranges_fixable.rs:10:13 + --> tests/ui/reversed_empty_ranges_fixable.rs:11:13 | LL | let _ = (ANSWER..21).filter(|x| x % 2 == 0).take(10).collect::>(); | ^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + let _ = (21..ANSWER).rev().filter(|x| x % 2 == 0).take(10).collect:: tests/ui/reversed_empty_ranges_fixable.rs:12:14 + --> tests/ui/reversed_empty_ranges_fixable.rs:14:14 | LL | for _ in -21..=-42 {} | ^^^^^^^^^ @@ -37,7 +37,7 @@ LL + for _ in (-42..=-21).rev() {} | error: this range is empty so it will yield no values - --> tests/ui/reversed_empty_ranges_fixable.rs:13:14 + --> tests/ui/reversed_empty_ranges_fixable.rs:16:14 | LL | for _ in 42u32..21u32 {} | ^^^^^^^^^^^^ diff --git a/tests/ui/reversed_empty_ranges_loops_fixable.fixed b/tests/ui/reversed_empty_ranges_loops_fixable.fixed index df5f2c441f41..55080da8a137 100644 --- a/tests/ui/reversed_empty_ranges_loops_fixable.fixed +++ b/tests/ui/reversed_empty_ranges_loops_fixable.fixed @@ -5,14 +5,17 @@ fn main() { const MAX_LEN: usize = 42; for i in (0..10).rev() { + //~^ reversed_empty_ranges println!("{}", i); } for i in (0..=10).rev() { + //~^ reversed_empty_ranges println!("{}", i); } for i in (0..MAX_LEN).rev() { + //~^ reversed_empty_ranges println!("{}", i); } @@ -32,15 +35,18 @@ fn main() { } for i in (0..10).rev().map(|x| x * 2) { + //~^ reversed_empty_ranges println!("{}", i); } // testing that the empty range lint folds constants for i in (5 + 4..10).rev() { + //~^ reversed_empty_ranges println!("{}", i); } for i in ((3 - 1)..(5 + 2)).rev() { + //~^ reversed_empty_ranges println!("{}", i); } diff --git a/tests/ui/reversed_empty_ranges_loops_fixable.rs b/tests/ui/reversed_empty_ranges_loops_fixable.rs index 92481be6cfc9..e51557bc2796 100644 --- a/tests/ui/reversed_empty_ranges_loops_fixable.rs +++ b/tests/ui/reversed_empty_ranges_loops_fixable.rs @@ -5,14 +5,17 @@ fn main() { const MAX_LEN: usize = 42; for i in 10..0 { + //~^ reversed_empty_ranges println!("{}", i); } for i in 10..=0 { + //~^ reversed_empty_ranges println!("{}", i); } for i in MAX_LEN..0 { + //~^ reversed_empty_ranges println!("{}", i); } @@ -32,15 +35,18 @@ fn main() { } for i in (10..0).map(|x| x * 2) { + //~^ reversed_empty_ranges println!("{}", i); } // testing that the empty range lint folds constants for i in 10..5 + 4 { + //~^ reversed_empty_ranges println!("{}", i); } for i in (5 + 2)..(3 - 1) { + //~^ reversed_empty_ranges println!("{}", i); } diff --git a/tests/ui/reversed_empty_ranges_loops_fixable.stderr b/tests/ui/reversed_empty_ranges_loops_fixable.stderr index 3e9ccb653fe7..eadd9d3675e1 100644 --- a/tests/ui/reversed_empty_ranges_loops_fixable.stderr +++ b/tests/ui/reversed_empty_ranges_loops_fixable.stderr @@ -13,7 +13,7 @@ LL + for i in (0..10).rev() { | error: this range is empty so it will yield no values - --> tests/ui/reversed_empty_ranges_loops_fixable.rs:11:14 + --> tests/ui/reversed_empty_ranges_loops_fixable.rs:12:14 | LL | for i in 10..=0 { | ^^^^^^ @@ -25,7 +25,7 @@ LL + for i in (0..=10).rev() { | error: this range is empty so it will yield no values - --> tests/ui/reversed_empty_ranges_loops_fixable.rs:15:14 + --> tests/ui/reversed_empty_ranges_loops_fixable.rs:17:14 | LL | for i in MAX_LEN..0 { | ^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + for i in (0..MAX_LEN).rev() { | error: this range is empty so it will yield no values - --> tests/ui/reversed_empty_ranges_loops_fixable.rs:34:14 + --> tests/ui/reversed_empty_ranges_loops_fixable.rs:37:14 | LL | for i in (10..0).map(|x| x * 2) { | ^^^^^^^ @@ -49,7 +49,7 @@ LL + for i in (0..10).rev().map(|x| x * 2) { | error: this range is empty so it will yield no values - --> tests/ui/reversed_empty_ranges_loops_fixable.rs:39:14 + --> tests/ui/reversed_empty_ranges_loops_fixable.rs:43:14 | LL | for i in 10..5 + 4 { | ^^^^^^^^^ @@ -61,7 +61,7 @@ LL + for i in (5 + 4..10).rev() { | error: this range is empty so it will yield no values - --> tests/ui/reversed_empty_ranges_loops_fixable.rs:43:14 + --> tests/ui/reversed_empty_ranges_loops_fixable.rs:48:14 | LL | for i in (5 + 2)..(3 - 1) { | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/reversed_empty_ranges_loops_unfixable.rs b/tests/ui/reversed_empty_ranges_loops_unfixable.rs index cd1701dd4bf2..00aa20d25bda 100644 --- a/tests/ui/reversed_empty_ranges_loops_unfixable.rs +++ b/tests/ui/reversed_empty_ranges_loops_unfixable.rs @@ -3,13 +3,14 @@ fn main() { for i in 5..5 { - //~^ ERROR: this range is empty so it will yield no values - //~| NOTE: `-D clippy::reversed-empty-ranges` implied by `-D warnings` + //~^ reversed_empty_ranges + println!("{}", i); } for i in (5 + 2)..(8 - 1) { - //~^ ERROR: this range is empty so it will yield no values + //~^ reversed_empty_ranges + println!("{}", i); } } diff --git a/tests/ui/reversed_empty_ranges_unfixable.rs b/tests/ui/reversed_empty_ranges_unfixable.rs index 16c1121ae069..7bf434544378 100644 --- a/tests/ui/reversed_empty_ranges_unfixable.rs +++ b/tests/ui/reversed_empty_ranges_unfixable.rs @@ -6,13 +6,13 @@ const SOME_NUM: usize = 3; fn main() { let arr = [1, 2, 3, 4, 5]; let _ = &arr[3usize..=1usize]; - //~^ ERROR: this range is reversed and using it to index a slice will panic at run-tim - //~| NOTE: `-D clippy::reversed-empty-ranges` implied by `-D warnings` + //~^ reversed_empty_ranges + let _ = &arr[SOME_NUM..1]; - //~^ ERROR: this range is reversed and using it to index a slice will panic at run-tim + //~^ reversed_empty_ranges for _ in ANSWER..ANSWER {} - //~^ ERROR: this range is empty so it will yield no values + //~^ reversed_empty_ranges // Should not be linted, see issue #5689 let _ = (42 + 10..42 + 10).map(|x| x / 2).find(|&x| x == 21); diff --git a/tests/ui/same_functions_in_if_condition.rs b/tests/ui/same_functions_in_if_condition.rs index a207e4221355..b7ed3aab0043 100644 --- a/tests/ui/same_functions_in_if_condition.rs +++ b/tests/ui/same_functions_in_if_condition.rs @@ -37,33 +37,33 @@ fn ifs_same_cond_fn() { if function() { } else if function() { - //~^ ERROR: `if` has the same function call as a previous `if` + //~^ same_functions_in_if_condition } if fn_arg(a) { } else if fn_arg(a) { - //~^ ERROR: `if` has the same function call as a previous `if` + //~^ same_functions_in_if_condition } if obj.method() { } else if obj.method() { - //~^ ERROR: `if` has the same function call as a previous `if` + //~^ same_functions_in_if_condition } if obj.method_arg(a) { } else if obj.method_arg(a) { - //~^ ERROR: `if` has the same function call as a previous `if` + //~^ same_functions_in_if_condition } let mut v = vec![1]; if v.pop().is_none() { } else if v.pop().is_none() { - //~^ ERROR: `if` has the same function call as a previous `if` + //~^ same_functions_in_if_condition } if v.len() == 42 { } else if v.len() == 42 { - //~^ ERROR: `if` has the same function call as a previous `if` + //~^ same_functions_in_if_condition } if v.len() == 1 { diff --git a/tests/ui/same_item_push.rs b/tests/ui/same_item_push.rs index 87fd59ad3179..a08e8872a932 100644 --- a/tests/ui/same_item_push.rs +++ b/tests/ui/same_item_push.rs @@ -21,33 +21,33 @@ fn main() { let item = 2; for _ in 5..=20 { vec.push(item); - //~^ ERROR: it looks like the same item is being pushed into this `Vec` + //~^ same_item_push } let mut vec: Vec = Vec::new(); for _ in 0..15 { let item = 2; vec.push(item); - //~^ ERROR: it looks like the same item is being pushed into this `Vec` + //~^ same_item_push } let mut vec: Vec = Vec::new(); for _ in 0..15 { vec.push(13); - //~^ ERROR: it looks like the same item is being pushed into this `Vec` + //~^ same_item_push } let mut vec = Vec::new(); for _ in 0..20 { vec.push(VALUE); - //~^ ERROR: it looks like the same item is being pushed into this `Vec` + //~^ same_item_push } let mut vec = Vec::new(); let item = VALUE; for _ in 0..20 { vec.push(item); - //~^ ERROR: it looks like the same item is being pushed into this `Vec` + //~^ same_item_push } #[clippy::msrv = "1.81"] @@ -56,7 +56,7 @@ fn main() { let item = VALUE; for _ in 0..20 { vec.push(item); - //~^ ERROR: it looks like the same item is being pushed into this `Vec` + //~^ same_item_push } } diff --git a/tests/ui/same_name_method.rs b/tests/ui/same_name_method.rs index ba876c2b5a3f..43c664b1505f 100644 --- a/tests/ui/same_name_method.rs +++ b/tests/ui/same_name_method.rs @@ -18,7 +18,7 @@ mod should_lint { impl S { fn foo() {} - //~^ ERROR: method's name is the same as an existing method in a trait + //~^ same_name_method } impl T1 for S { @@ -33,7 +33,7 @@ mod should_lint { impl S { fn clone() {} - //~^ ERROR: method's name is the same as an existing method in a trait + //~^ same_name_method } } @@ -44,7 +44,7 @@ mod should_lint { impl S { fn foo() {} - //~^ ERROR: method's name is the same as an existing method in a trait + //~^ same_name_method } impl T1 for S { @@ -59,7 +59,7 @@ mod should_lint { impl S { fn foo() {} - //~^ ERROR: method's name is the same as an existing method in a trait + //~^ same_name_method } impl T1 for S {} @@ -72,8 +72,8 @@ mod should_lint { impl S { fn foo() {} - //~^ ERROR: method's name is the same as an existing method in a trait - //~| ERROR: method's name is the same as an existing method in a trait + //~^ same_name_method + //~| same_name_method } impl T1 for S {} diff --git a/tests/ui/search_is_some.rs b/tests/ui/search_is_some.rs index 9a9aaba56adc..4143b8bfba58 100644 --- a/tests/ui/search_is_some.rs +++ b/tests/ui/search_is_some.rs @@ -14,18 +14,21 @@ fn main() { // Check `find().is_some()`, multi-line case. let _ = v.iter().find(|&x| { + //~^ search_is_some *x < 0 } ).is_some(); // Check `position().is_some()`, multi-line case. let _ = v.iter().position(|&x| { + //~^ search_is_some x < 0 } ).is_some(); // Check `rposition().is_some()`, multi-line case. let _ = v.iter().rposition(|&x| { + //~^ search_is_some x < 0 } ).is_some(); @@ -41,6 +44,7 @@ fn main() { let some_closure = |x: &u32| *x == 0; let _ = (0..1).find(some_closure).is_some(); + //~^ search_is_some } #[rustfmt::skip] @@ -51,18 +55,21 @@ fn is_none() { // Check `find().is_none()`, multi-line case. let _ = v.iter().find(|&x| { + //~^ search_is_some *x < 0 } ).is_none(); // Check `position().is_none()`, multi-line case. let _ = v.iter().position(|&x| { + //~^ search_is_some x < 0 } ).is_none(); // Check `rposition().is_none()`, multi-line case. let _ = v.iter().rposition(|&x| { + //~^ search_is_some x < 0 } ).is_none(); @@ -78,4 +85,5 @@ fn is_none() { let some_closure = |x: &u32| *x == 0; let _ = (0..1).find(some_closure).is_none(); + //~^ search_is_some } diff --git a/tests/ui/search_is_some.stderr b/tests/ui/search_is_some.stderr index b5ef55341770..d9a43c8915e8 100644 --- a/tests/ui/search_is_some.stderr +++ b/tests/ui/search_is_some.stderr @@ -3,6 +3,7 @@ error: called `is_some()` after searching an `Iterator` with `find` | LL | let _ = v.iter().find(|&x| { | _____________^ +LL | | LL | | *x < 0 LL | | } LL | | ).is_some(); @@ -13,10 +14,11 @@ LL | | ).is_some(); = help: to override `-D warnings` add `#[allow(clippy::search_is_some)]` error: called `is_some()` after searching an `Iterator` with `position` - --> tests/ui/search_is_some.rs:22:13 + --> tests/ui/search_is_some.rs:23:13 | LL | let _ = v.iter().position(|&x| { | _____________^ +LL | | LL | | x < 0 LL | | } LL | | ).is_some(); @@ -25,10 +27,11 @@ LL | | ).is_some(); = help: this is more succinctly expressed by calling `any()` error: called `is_some()` after searching an `Iterator` with `rposition` - --> tests/ui/search_is_some.rs:28:13 + --> tests/ui/search_is_some.rs:30:13 | LL | let _ = v.iter().rposition(|&x| { | _____________^ +LL | | LL | | x < 0 LL | | } LL | | ).is_some(); @@ -37,16 +40,17 @@ LL | | ).is_some(); = help: this is more succinctly expressed by calling `any()` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some.rs:43:20 + --> tests/ui/search_is_some.rs:46:20 | LL | let _ = (0..1).find(some_closure).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(some_closure)` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some.rs:53:13 + --> tests/ui/search_is_some.rs:57:13 | LL | let _ = v.iter().find(|&x| { | _____________^ +LL | | LL | | *x < 0 LL | | } LL | | ).is_none(); @@ -55,10 +59,11 @@ LL | | ).is_none(); = help: this is more succinctly expressed by calling `any()` with negation error: called `is_none()` after searching an `Iterator` with `position` - --> tests/ui/search_is_some.rs:59:13 + --> tests/ui/search_is_some.rs:64:13 | LL | let _ = v.iter().position(|&x| { | _____________^ +LL | | LL | | x < 0 LL | | } LL | | ).is_none(); @@ -67,10 +72,11 @@ LL | | ).is_none(); = help: this is more succinctly expressed by calling `any()` with negation error: called `is_none()` after searching an `Iterator` with `rposition` - --> tests/ui/search_is_some.rs:65:13 + --> tests/ui/search_is_some.rs:71:13 | LL | let _ = v.iter().rposition(|&x| { | _____________^ +LL | | LL | | x < 0 LL | | } LL | | ).is_none(); @@ -79,7 +85,7 @@ LL | | ).is_none(); = help: this is more succinctly expressed by calling `any()` with negation error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some.rs:80:13 + --> tests/ui/search_is_some.rs:87:13 | LL | let _ = (0..1).find(some_closure).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!(0..1).any(some_closure)` diff --git a/tests/ui/search_is_some_fixable_none.fixed b/tests/ui/search_is_some_fixable_none.fixed index 86a937b4dae1..847e5140d3e6 100644 --- a/tests/ui/search_is_some_fixable_none.fixed +++ b/tests/ui/search_is_some_fixable_none.fixed @@ -1,4 +1,4 @@ -#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec)] +#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec, clippy::manual_contains)] #![warn(clippy::search_is_some)] fn main() { @@ -7,36 +7,56 @@ fn main() { // Check `find().is_none()`, single-line case. let _ = !v.iter().any(|x| *x < 0); + //~^ search_is_some let _ = !(0..1).any(|x| **y == x); // one dereference less + // + //~^^ search_is_some let _ = !(0..1).any(|x| x == 0); + //~^ search_is_some let _ = !v.iter().any(|x| *x == 0); + //~^ search_is_some let _ = !(4..5).any(|x| x == 1 || x == 3 || x == 5); + //~^ search_is_some let _ = !(1..3).any(|x| [1, 2, 3].contains(&x)); + //~^ search_is_some let _ = !(1..3).any(|x| x == 0 || [1, 2, 3].contains(&x)); + //~^ search_is_some let _ = !(1..3).any(|x| [1, 2, 3].contains(&x) || x == 0); + //~^ search_is_some let _ = !(1..3).any(|x| [1, 2, 3].contains(&x) || x == 0 || [4, 5, 6].contains(&x) || x == -1); // Check `position().is_none()`, single-line case. let _ = !v.iter().any(|&x| x < 0); + //~^ search_is_some // Check `rposition().is_none()`, single-line case. let _ = !v.iter().any(|&x| x < 0); + //~^ search_is_some let s1 = String::from("hello world"); let s2 = String::from("world"); // caller of `find()` is a `&`static str` let _ = !"hello world".contains("world"); + //~^ search_is_some let _ = !"hello world".contains(&s2); + //~^ search_is_some let _ = !"hello world".contains(&s2[2..]); + //~^ search_is_some // caller of `find()` is a `String` let _ = !s1.contains("world"); + //~^ search_is_some let _ = !s1.contains(&s2); + //~^ search_is_some let _ = !s1.contains(&s2[2..]); + //~^ search_is_some // caller of `find()` is slice of `String` let _ = !s1[2..].contains("world"); + //~^ search_is_some let _ = !s1[2..].contains(&s2); + //~^ search_is_some let _ = !s1[2..].contains(&s2[2..]); + //~^ search_is_some } #[allow(clippy::clone_on_copy, clippy::map_clone)] @@ -53,6 +73,7 @@ mod issue7392 { .hand .iter() .filter(|c| !filter_hand.iter().any(|cc| c == &cc)) + //~^ search_is_some .map(|c| c.clone()) .collect::>(); } @@ -69,6 +90,7 @@ mod issue7392 { .hand .iter() .filter(|(c, _)| !filter_hand.iter().any(|cc| c == cc)) + //~^ search_is_some .map(|c| c.clone()) .collect::>(); } @@ -80,21 +102,25 @@ mod issue7392 { } let vfoo = vec![Foo { foo: 1, bar: 2 }]; let _ = !vfoo.iter().any(|v| v.foo == 1 && v.bar == 2); + //~^ search_is_some let vfoo = vec![(42, Foo { foo: 1, bar: 2 })]; let _ = !vfoo + //~^ search_is_some .iter().any(|(i, v)| *i == 42 && v.foo == 1 && v.bar == 2); } fn index_projection() { let vfoo = vec![[0, 1, 2, 3]]; let _ = !vfoo.iter().any(|a| a[0] == 42); + //~^ search_is_some } #[allow(clippy::match_like_matches_macro)] fn slice_projection() { let vfoo = vec![[0, 1, 2, 3, 0, 1, 2, 3]]; let _ = !vfoo.iter().any(|sub| sub[1..4].len() == 3); + //~^ search_is_some } fn please(x: &u32) -> bool { @@ -113,16 +139,22 @@ mod issue7392 { let x = 19; let ppx: &u32 = &x; let _ = ![ppx].iter().any(|ppp_x: &&u32| please(ppp_x)); + //~^ search_is_some let _ = ![String::from("Hey hey")].iter().any(|s| s.len() == 2); + //~^ search_is_some let v = vec![3, 2, 1, 0]; let _ = !v.iter().any(|x| deref_enough(*x)); + //~^ search_is_some let _ = !v.iter().any(|x: &u32| deref_enough(*x)); + //~^ search_is_some #[allow(clippy::redundant_closure)] let _ = !v.iter().any(|x| arg_no_deref(&x)); + //~^ search_is_some #[allow(clippy::redundant_closure)] let _ = !v.iter().any(|x: &u32| arg_no_deref(&x)); + //~^ search_is_some } fn field_index_projection() { @@ -143,6 +175,7 @@ mod issue7392 { }, }]; let _ = !vfoo + //~^ search_is_some .iter().any(|v| v.inner_double.bar[0][0] == 2 && v.inner.bar[0] == 2); } @@ -157,11 +190,13 @@ mod issue7392 { inner: vec![Foo { bar: 0 }], }]; let _ = !vfoo.iter().any(|v| v.inner[0].bar == 2); + //~^ search_is_some } fn double_deref_index_projection() { let vfoo = vec![&&[0, 1, 2, 3]]; let _ = !vfoo.iter().any(|x| (**x)[0] == 9); + //~^ search_is_some } fn method_call_by_ref() { @@ -175,11 +210,14 @@ mod issue7392 { } let vfoo = vec![Foo { bar: 1 }]; let _ = !vfoo.iter().any(|v| v.by_ref(&v.bar)); + //~^ search_is_some } fn ref_bindings() { let _ = ![&(&1, 2), &(&3, 4), &(&5, 4)].iter().any(|(&x, y)| x == *y); + //~^ search_is_some let _ = ![&(&1, 2), &(&3, 4), &(&5, 4)].iter().any(|(&x, y)| x == *y); + //~^ search_is_some } fn test_string_1(s: &str) -> bool { @@ -199,7 +237,9 @@ mod issue7392 { let lst = &[String::from("Hello"), String::from("world")]; let v: Vec<&[String]> = vec![lst]; let _ = !v.iter().any(|s| s[0].is_empty()); + //~^ search_is_some let _ = !v.iter().any(|s| test_string_1(&s[0])); + //~^ search_is_some // Field projections struct FieldProjection<'a> { @@ -209,8 +249,11 @@ mod issue7392 { let instance = FieldProjection { field: &field }; let v = vec![instance]; let _ = !v.iter().any(|fp| fp.field.is_power_of_two()); + //~^ search_is_some let _ = !v.iter().any(|fp| test_u32_1(fp.field)); + //~^ search_is_some let _ = !v.iter().any(|fp| test_u32_2(*fp.field)); + //~^ search_is_some } } @@ -227,39 +270,51 @@ mod issue_11910 { fn test_normal_for_iter() { let v = vec![3, 2, 1, 0, -1, -2, -3]; let _ = !v.iter().any(|x| *x == 42); + //~^ search_is_some Foo.bar(!v.iter().any(|x| *x == 42)); + //~^ search_is_some } fn test_then_for_iter() { let v = vec![3, 2, 1, 0, -1, -2, -3]; (!v.iter().any(|x| *x == 42)).then(computations); + //~^ search_is_some } fn test_then_some_for_iter() { let v = vec![3, 2, 1, 0, -1, -2, -3]; (!v.iter().any(|x| *x == 42)).then_some(0); + //~^ search_is_some } fn test_normal_for_str() { let s = "hello"; let _ = !s.contains("world"); + //~^ search_is_some Foo.bar(!s.contains("world")); + //~^ search_is_some let s = String::from("hello"); let _ = !s.contains("world"); + //~^ search_is_some Foo.bar(!s.contains("world")); + //~^ search_is_some } fn test_then_for_str() { let s = "hello"; let _ = (!s.contains("world")).then(computations); + //~^ search_is_some let s = String::from("hello"); let _ = (!s.contains("world")).then(computations); + //~^ search_is_some } fn test_then_some_for_str() { let s = "hello"; let _ = (!s.contains("world")).then_some(0); + //~^ search_is_some let s = String::from("hello"); let _ = (!s.contains("world")).then_some(0); + //~^ search_is_some } } diff --git a/tests/ui/search_is_some_fixable_none.rs b/tests/ui/search_is_some_fixable_none.rs index c0103a015097..e976d12600cc 100644 --- a/tests/ui/search_is_some_fixable_none.rs +++ b/tests/ui/search_is_some_fixable_none.rs @@ -1,4 +1,4 @@ -#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec)] +#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec, clippy::manual_contains)] #![warn(clippy::search_is_some)] fn main() { @@ -7,38 +7,59 @@ fn main() { // Check `find().is_none()`, single-line case. let _ = v.iter().find(|&x| *x < 0).is_none(); + //~^ search_is_some let _ = (0..1).find(|x| **y == *x).is_none(); // one dereference less + // + //~^^ search_is_some let _ = (0..1).find(|x| *x == 0).is_none(); + //~^ search_is_some let _ = v.iter().find(|x| **x == 0).is_none(); + //~^ search_is_some let _ = (4..5).find(|x| *x == 1 || *x == 3 || *x == 5).is_none(); + //~^ search_is_some let _ = (1..3).find(|x| [1, 2, 3].contains(x)).is_none(); + //~^ search_is_some let _ = (1..3).find(|x| *x == 0 || [1, 2, 3].contains(x)).is_none(); + //~^ search_is_some let _ = (1..3).find(|x| [1, 2, 3].contains(x) || *x == 0).is_none(); + //~^ search_is_some let _ = (1..3) + //~^ search_is_some .find(|x| [1, 2, 3].contains(x) || *x == 0 || [4, 5, 6].contains(x) || *x == -1) .is_none(); // Check `position().is_none()`, single-line case. let _ = v.iter().position(|&x| x < 0).is_none(); + //~^ search_is_some // Check `rposition().is_none()`, single-line case. let _ = v.iter().rposition(|&x| x < 0).is_none(); + //~^ search_is_some let s1 = String::from("hello world"); let s2 = String::from("world"); // caller of `find()` is a `&`static str` let _ = "hello world".find("world").is_none(); + //~^ search_is_some let _ = "hello world".find(&s2).is_none(); + //~^ search_is_some let _ = "hello world".find(&s2[2..]).is_none(); + //~^ search_is_some // caller of `find()` is a `String` let _ = s1.find("world").is_none(); + //~^ search_is_some let _ = s1.find(&s2).is_none(); + //~^ search_is_some let _ = s1.find(&s2[2..]).is_none(); + //~^ search_is_some // caller of `find()` is slice of `String` let _ = s1[2..].find("world").is_none(); + //~^ search_is_some let _ = s1[2..].find(&s2).is_none(); + //~^ search_is_some let _ = s1[2..].find(&s2[2..]).is_none(); + //~^ search_is_some } #[allow(clippy::clone_on_copy, clippy::map_clone)] @@ -55,6 +76,7 @@ mod issue7392 { .hand .iter() .filter(|c| filter_hand.iter().find(|cc| c == cc).is_none()) + //~^ search_is_some .map(|c| c.clone()) .collect::>(); } @@ -71,6 +93,7 @@ mod issue7392 { .hand .iter() .filter(|(c, _)| filter_hand.iter().find(|cc| c == *cc).is_none()) + //~^ search_is_some .map(|c| c.clone()) .collect::>(); } @@ -82,9 +105,11 @@ mod issue7392 { } let vfoo = vec![Foo { foo: 1, bar: 2 }]; let _ = vfoo.iter().find(|v| v.foo == 1 && v.bar == 2).is_none(); + //~^ search_is_some let vfoo = vec![(42, Foo { foo: 1, bar: 2 })]; let _ = vfoo + //~^ search_is_some .iter() .find(|(i, v)| *i == 42 && v.foo == 1 && v.bar == 2) .is_none(); @@ -93,12 +118,14 @@ mod issue7392 { fn index_projection() { let vfoo = vec![[0, 1, 2, 3]]; let _ = vfoo.iter().find(|a| a[0] == 42).is_none(); + //~^ search_is_some } #[allow(clippy::match_like_matches_macro)] fn slice_projection() { let vfoo = vec![[0, 1, 2, 3, 0, 1, 2, 3]]; let _ = vfoo.iter().find(|sub| sub[1..4].len() == 3).is_none(); + //~^ search_is_some } fn please(x: &u32) -> bool { @@ -117,16 +144,22 @@ mod issue7392 { let x = 19; let ppx: &u32 = &x; let _ = [ppx].iter().find(|ppp_x: &&&u32| please(**ppp_x)).is_none(); + //~^ search_is_some let _ = [String::from("Hey hey")].iter().find(|s| s.len() == 2).is_none(); + //~^ search_is_some let v = vec![3, 2, 1, 0]; let _ = v.iter().find(|x| deref_enough(**x)).is_none(); + //~^ search_is_some let _ = v.iter().find(|x: &&u32| deref_enough(**x)).is_none(); + //~^ search_is_some #[allow(clippy::redundant_closure)] let _ = v.iter().find(|x| arg_no_deref(x)).is_none(); + //~^ search_is_some #[allow(clippy::redundant_closure)] let _ = v.iter().find(|x: &&u32| arg_no_deref(x)).is_none(); + //~^ search_is_some } fn field_index_projection() { @@ -147,6 +180,7 @@ mod issue7392 { }, }]; let _ = vfoo + //~^ search_is_some .iter() .find(|v| v.inner_double.bar[0][0] == 2 && v.inner.bar[0] == 2) .is_none(); @@ -163,11 +197,13 @@ mod issue7392 { inner: vec![Foo { bar: 0 }], }]; let _ = vfoo.iter().find(|v| v.inner[0].bar == 2).is_none(); + //~^ search_is_some } fn double_deref_index_projection() { let vfoo = vec![&&[0, 1, 2, 3]]; let _ = vfoo.iter().find(|x| (**x)[0] == 9).is_none(); + //~^ search_is_some } fn method_call_by_ref() { @@ -181,11 +217,14 @@ mod issue7392 { } let vfoo = vec![Foo { bar: 1 }]; let _ = vfoo.iter().find(|v| v.by_ref(&v.bar)).is_none(); + //~^ search_is_some } fn ref_bindings() { let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|(&x, y)| x == *y).is_none(); + //~^ search_is_some let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|&(&x, y)| x == *y).is_none(); + //~^ search_is_some } fn test_string_1(s: &str) -> bool { @@ -205,7 +244,9 @@ mod issue7392 { let lst = &[String::from("Hello"), String::from("world")]; let v: Vec<&[String]> = vec![lst]; let _ = v.iter().find(|s| s[0].is_empty()).is_none(); + //~^ search_is_some let _ = v.iter().find(|s| test_string_1(&s[0])).is_none(); + //~^ search_is_some // Field projections struct FieldProjection<'a> { @@ -215,8 +256,11 @@ mod issue7392 { let instance = FieldProjection { field: &field }; let v = vec![instance]; let _ = v.iter().find(|fp| fp.field.is_power_of_two()).is_none(); + //~^ search_is_some let _ = v.iter().find(|fp| test_u32_1(fp.field)).is_none(); + //~^ search_is_some let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_none(); + //~^ search_is_some } } @@ -233,39 +277,51 @@ mod issue_11910 { fn test_normal_for_iter() { let v = vec![3, 2, 1, 0, -1, -2, -3]; let _ = v.iter().find(|x| **x == 42).is_none(); + //~^ search_is_some Foo.bar(v.iter().find(|x| **x == 42).is_none()); + //~^ search_is_some } fn test_then_for_iter() { let v = vec![3, 2, 1, 0, -1, -2, -3]; v.iter().find(|x| **x == 42).is_none().then(computations); + //~^ search_is_some } fn test_then_some_for_iter() { let v = vec![3, 2, 1, 0, -1, -2, -3]; v.iter().find(|x| **x == 42).is_none().then_some(0); + //~^ search_is_some } fn test_normal_for_str() { let s = "hello"; let _ = s.find("world").is_none(); + //~^ search_is_some Foo.bar(s.find("world").is_none()); + //~^ search_is_some let s = String::from("hello"); let _ = s.find("world").is_none(); + //~^ search_is_some Foo.bar(s.find("world").is_none()); + //~^ search_is_some } fn test_then_for_str() { let s = "hello"; let _ = s.find("world").is_none().then(computations); + //~^ search_is_some let s = String::from("hello"); let _ = s.find("world").is_none().then(computations); + //~^ search_is_some } fn test_then_some_for_str() { let s = "hello"; let _ = s.find("world").is_none().then_some(0); + //~^ search_is_some let s = String::from("hello"); let _ = s.find("world").is_none().then_some(0); + //~^ search_is_some } } diff --git a/tests/ui/search_is_some_fixable_none.stderr b/tests/ui/search_is_some_fixable_none.stderr index 2c858b9fb10e..ccc17025222d 100644 --- a/tests/ui/search_is_some_fixable_none.stderr +++ b/tests/ui/search_is_some_fixable_none.stderr @@ -8,145 +8,147 @@ LL | let _ = v.iter().find(|&x| *x < 0).is_none(); = help: to override `-D warnings` add `#[allow(clippy::search_is_some)]` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:10:13 + --> tests/ui/search_is_some_fixable_none.rs:11:13 | LL | let _ = (0..1).find(|x| **y == *x).is_none(); // one dereference less | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!(0..1).any(|x| **y == x)` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:11:13 + --> tests/ui/search_is_some_fixable_none.rs:14:13 | LL | let _ = (0..1).find(|x| *x == 0).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!(0..1).any(|x| x == 0)` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:12:13 + --> tests/ui/search_is_some_fixable_none.rs:16:13 | LL | let _ = v.iter().find(|x| **x == 0).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|x| *x == 0)` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:13:13 + --> tests/ui/search_is_some_fixable_none.rs:18:13 | LL | let _ = (4..5).find(|x| *x == 1 || *x == 3 || *x == 5).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!(4..5).any(|x| x == 1 || x == 3 || x == 5)` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:14:13 + --> tests/ui/search_is_some_fixable_none.rs:20:13 | LL | let _ = (1..3).find(|x| [1, 2, 3].contains(x)).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!(1..3).any(|x| [1, 2, 3].contains(&x))` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:15:13 + --> tests/ui/search_is_some_fixable_none.rs:22:13 | LL | let _ = (1..3).find(|x| *x == 0 || [1, 2, 3].contains(x)).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!(1..3).any(|x| x == 0 || [1, 2, 3].contains(&x))` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:16:13 + --> tests/ui/search_is_some_fixable_none.rs:24:13 | LL | let _ = (1..3).find(|x| [1, 2, 3].contains(x) || *x == 0).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!(1..3).any(|x| [1, 2, 3].contains(&x) || x == 0)` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:17:13 + --> tests/ui/search_is_some_fixable_none.rs:26:13 | LL | let _ = (1..3) | _____________^ +LL | | LL | | .find(|x| [1, 2, 3].contains(x) || *x == 0 || [4, 5, 6].contains(x) || *x == -1) LL | | .is_none(); | |__________________^ help: consider using: `!(1..3).any(|x| [1, 2, 3].contains(&x) || x == 0 || [4, 5, 6].contains(&x) || x == -1)` error: called `is_none()` after searching an `Iterator` with `position` - --> tests/ui/search_is_some_fixable_none.rs:22:13 + --> tests/ui/search_is_some_fixable_none.rs:32:13 | LL | let _ = v.iter().position(|&x| x < 0).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|&x| x < 0)` error: called `is_none()` after searching an `Iterator` with `rposition` - --> tests/ui/search_is_some_fixable_none.rs:25:13 + --> tests/ui/search_is_some_fixable_none.rs:36:13 | LL | let _ = v.iter().rposition(|&x| x < 0).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|&x| x < 0)` error: called `is_none()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_none.rs:31:13 + --> tests/ui/search_is_some_fixable_none.rs:43:13 | LL | let _ = "hello world".find("world").is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!"hello world".contains("world")` error: called `is_none()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_none.rs:32:13 + --> tests/ui/search_is_some_fixable_none.rs:45:13 | LL | let _ = "hello world".find(&s2).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!"hello world".contains(&s2)` error: called `is_none()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_none.rs:33:13 + --> tests/ui/search_is_some_fixable_none.rs:47:13 | LL | let _ = "hello world".find(&s2[2..]).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!"hello world".contains(&s2[2..])` error: called `is_none()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_none.rs:35:13 + --> tests/ui/search_is_some_fixable_none.rs:50:13 | LL | let _ = s1.find("world").is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s1.contains("world")` error: called `is_none()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_none.rs:36:13 + --> tests/ui/search_is_some_fixable_none.rs:52:13 | LL | let _ = s1.find(&s2).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s1.contains(&s2)` error: called `is_none()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_none.rs:37:13 + --> tests/ui/search_is_some_fixable_none.rs:54:13 | LL | let _ = s1.find(&s2[2..]).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s1.contains(&s2[2..])` error: called `is_none()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_none.rs:39:13 + --> tests/ui/search_is_some_fixable_none.rs:57:13 | LL | let _ = s1[2..].find("world").is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s1[2..].contains("world")` error: called `is_none()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_none.rs:40:13 + --> tests/ui/search_is_some_fixable_none.rs:59:13 | LL | let _ = s1[2..].find(&s2).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s1[2..].contains(&s2)` error: called `is_none()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_none.rs:41:13 + --> tests/ui/search_is_some_fixable_none.rs:61:13 | LL | let _ = s1[2..].find(&s2[2..]).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s1[2..].contains(&s2[2..])` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:57:25 + --> tests/ui/search_is_some_fixable_none.rs:78:25 | LL | .filter(|c| filter_hand.iter().find(|cc| c == cc).is_none()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!filter_hand.iter().any(|cc| c == &cc)` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:73:30 + --> tests/ui/search_is_some_fixable_none.rs:95:30 | LL | .filter(|(c, _)| filter_hand.iter().find(|cc| c == *cc).is_none()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!filter_hand.iter().any(|cc| c == cc)` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:84:17 + --> tests/ui/search_is_some_fixable_none.rs:107:17 | LL | let _ = vfoo.iter().find(|v| v.foo == 1 && v.bar == 2).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!vfoo.iter().any(|v| v.foo == 1 && v.bar == 2)` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:87:17 + --> tests/ui/search_is_some_fixable_none.rs:111:17 | LL | let _ = vfoo | _________________^ +LL | | LL | | .iter() LL | | .find(|(i, v)| *i == 42 && v.foo == 1 && v.bar == 2) LL | | .is_none(); @@ -155,62 +157,64 @@ LL | | .is_none(); help: consider using | LL ~ let _ = !vfoo +LL + LL ~ .iter().any(|(i, v)| *i == 42 && v.foo == 1 && v.bar == 2); | error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:95:17 + --> tests/ui/search_is_some_fixable_none.rs:120:17 | LL | let _ = vfoo.iter().find(|a| a[0] == 42).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!vfoo.iter().any(|a| a[0] == 42)` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:101:17 + --> tests/ui/search_is_some_fixable_none.rs:127:17 | LL | let _ = vfoo.iter().find(|sub| sub[1..4].len() == 3).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!vfoo.iter().any(|sub| sub[1..4].len() == 3)` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:119:17 + --> tests/ui/search_is_some_fixable_none.rs:146:17 | LL | let _ = [ppx].iter().find(|ppp_x: &&&u32| please(**ppp_x)).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `![ppx].iter().any(|ppp_x: &&u32| please(ppp_x))` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:120:17 + --> tests/ui/search_is_some_fixable_none.rs:148:17 | LL | let _ = [String::from("Hey hey")].iter().find(|s| s.len() == 2).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `![String::from("Hey hey")].iter().any(|s| s.len() == 2)` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:123:17 + --> tests/ui/search_is_some_fixable_none.rs:152:17 | LL | let _ = v.iter().find(|x| deref_enough(**x)).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|x| deref_enough(*x))` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:124:17 + --> tests/ui/search_is_some_fixable_none.rs:154:17 | LL | let _ = v.iter().find(|x: &&u32| deref_enough(**x)).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|x: &u32| deref_enough(*x))` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:127:17 + --> tests/ui/search_is_some_fixable_none.rs:158:17 | LL | let _ = v.iter().find(|x| arg_no_deref(x)).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|x| arg_no_deref(&x))` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:129:17 + --> tests/ui/search_is_some_fixable_none.rs:161:17 | LL | let _ = v.iter().find(|x: &&u32| arg_no_deref(x)).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|x: &u32| arg_no_deref(&x))` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:149:17 + --> tests/ui/search_is_some_fixable_none.rs:182:17 | LL | let _ = vfoo | _________________^ +LL | | LL | | .iter() LL | | .find(|v| v.inner_double.bar[0][0] == 2 && v.inner.bar[0] == 2) LL | | .is_none(); @@ -219,137 +223,138 @@ LL | | .is_none(); help: consider using | LL ~ let _ = !vfoo +LL + LL ~ .iter().any(|v| v.inner_double.bar[0][0] == 2 && v.inner.bar[0] == 2); | error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:165:17 + --> tests/ui/search_is_some_fixable_none.rs:199:17 | LL | let _ = vfoo.iter().find(|v| v.inner[0].bar == 2).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!vfoo.iter().any(|v| v.inner[0].bar == 2)` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:170:17 + --> tests/ui/search_is_some_fixable_none.rs:205:17 | LL | let _ = vfoo.iter().find(|x| (**x)[0] == 9).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!vfoo.iter().any(|x| (**x)[0] == 9)` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:183:17 + --> tests/ui/search_is_some_fixable_none.rs:219:17 | LL | let _ = vfoo.iter().find(|v| v.by_ref(&v.bar)).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!vfoo.iter().any(|v| v.by_ref(&v.bar))` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:187:17 + --> tests/ui/search_is_some_fixable_none.rs:224:17 | LL | let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|(&x, y)| x == *y).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `![&(&1, 2), &(&3, 4), &(&5, 4)].iter().any(|(&x, y)| x == *y)` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:188:17 + --> tests/ui/search_is_some_fixable_none.rs:226:17 | LL | let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|&(&x, y)| x == *y).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `![&(&1, 2), &(&3, 4), &(&5, 4)].iter().any(|(&x, y)| x == *y)` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:207:17 + --> tests/ui/search_is_some_fixable_none.rs:246:17 | LL | let _ = v.iter().find(|s| s[0].is_empty()).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|s| s[0].is_empty())` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:208:17 + --> tests/ui/search_is_some_fixable_none.rs:248:17 | LL | let _ = v.iter().find(|s| test_string_1(&s[0])).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|s| test_string_1(&s[0]))` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:217:17 + --> tests/ui/search_is_some_fixable_none.rs:258:17 | LL | let _ = v.iter().find(|fp| fp.field.is_power_of_two()).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|fp| fp.field.is_power_of_two())` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:218:17 + --> tests/ui/search_is_some_fixable_none.rs:260:17 | LL | let _ = v.iter().find(|fp| test_u32_1(fp.field)).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|fp| test_u32_1(fp.field))` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:219:17 + --> tests/ui/search_is_some_fixable_none.rs:262:17 | LL | let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|fp| test_u32_2(*fp.field))` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:235:17 + --> tests/ui/search_is_some_fixable_none.rs:279:17 | LL | let _ = v.iter().find(|x| **x == 42).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|x| *x == 42)` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:236:17 + --> tests/ui/search_is_some_fixable_none.rs:281:17 | LL | Foo.bar(v.iter().find(|x| **x == 42).is_none()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|x| *x == 42)` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:241:9 + --> tests/ui/search_is_some_fixable_none.rs:287:9 | LL | v.iter().find(|x| **x == 42).is_none().then(computations); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!v.iter().any(|x| *x == 42))` error: called `is_none()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_none.rs:246:9 + --> tests/ui/search_is_some_fixable_none.rs:293:9 | LL | v.iter().find(|x| **x == 42).is_none().then_some(0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!v.iter().any(|x| *x == 42))` error: called `is_none()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_none.rs:251:17 + --> tests/ui/search_is_some_fixable_none.rs:299:17 | LL | let _ = s.find("world").is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s.contains("world")` error: called `is_none()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_none.rs:252:17 + --> tests/ui/search_is_some_fixable_none.rs:301:17 | LL | Foo.bar(s.find("world").is_none()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s.contains("world")` error: called `is_none()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_none.rs:254:17 + --> tests/ui/search_is_some_fixable_none.rs:304:17 | LL | let _ = s.find("world").is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s.contains("world")` error: called `is_none()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_none.rs:255:17 + --> tests/ui/search_is_some_fixable_none.rs:306:17 | LL | Foo.bar(s.find("world").is_none()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s.contains("world")` error: called `is_none()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_none.rs:260:17 + --> tests/ui/search_is_some_fixable_none.rs:312:17 | LL | let _ = s.find("world").is_none().then(computations); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!s.contains("world"))` error: called `is_none()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_none.rs:262:17 + --> tests/ui/search_is_some_fixable_none.rs:315:17 | LL | let _ = s.find("world").is_none().then(computations); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!s.contains("world"))` error: called `is_none()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_none.rs:267:17 + --> tests/ui/search_is_some_fixable_none.rs:321:17 | LL | let _ = s.find("world").is_none().then_some(0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!s.contains("world"))` error: called `is_none()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_none.rs:269:17 + --> tests/ui/search_is_some_fixable_none.rs:324:17 | LL | let _ = s.find("world").is_none().then_some(0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!s.contains("world"))` diff --git a/tests/ui/search_is_some_fixable_some.fixed b/tests/ui/search_is_some_fixable_some.fixed index ae3cbc3c4da2..05e88b8528f1 100644 --- a/tests/ui/search_is_some_fixable_some.fixed +++ b/tests/ui/search_is_some_fixable_some.fixed @@ -1,4 +1,4 @@ -#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec)] +#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec, clippy::manual_contains)] #![warn(clippy::search_is_some)] fn main() { @@ -7,36 +7,56 @@ fn main() { // Check `find().is_some()`, single-line case. let _ = v.iter().any(|x| *x < 0); + //~^ search_is_some let _ = (0..1).any(|x| **y == x); // one dereference less + // + //~^^ search_is_some let _ = (0..1).any(|x| x == 0); + //~^ search_is_some let _ = v.iter().any(|x| *x == 0); + //~^ search_is_some let _ = (4..5).any(|x| x == 1 || x == 3 || x == 5); + //~^ search_is_some let _ = (1..3).any(|x| [1, 2, 3].contains(&x)); + //~^ search_is_some let _ = (1..3).any(|x| x == 0 || [1, 2, 3].contains(&x)); + //~^ search_is_some let _ = (1..3).any(|x| [1, 2, 3].contains(&x) || x == 0); + //~^ search_is_some let _ = (1..3) .any(|x| [1, 2, 3].contains(&x) || x == 0 || [4, 5, 6].contains(&x) || x == -1); // Check `position().is_some()`, single-line case. let _ = v.iter().any(|&x| x < 0); + //~^ search_is_some // Check `rposition().is_some()`, single-line case. let _ = v.iter().any(|&x| x < 0); + //~^ search_is_some let s1 = String::from("hello world"); let s2 = String::from("world"); // caller of `find()` is a `&`static str` let _ = "hello world".contains("world"); + //~^ search_is_some let _ = "hello world".contains(&s2); + //~^ search_is_some let _ = "hello world".contains(&s2[2..]); + //~^ search_is_some // caller of `find()` is a `String` let _ = s1.contains("world"); + //~^ search_is_some let _ = s1.contains(&s2); + //~^ search_is_some let _ = s1.contains(&s2[2..]); + //~^ search_is_some // caller of `find()` is slice of `String` let _ = s1[2..].contains("world"); + //~^ search_is_some let _ = s1[2..].contains(&s2); + //~^ search_is_some let _ = s1[2..].contains(&s2[2..]); + //~^ search_is_some } #[allow(clippy::clone_on_copy, clippy::map_clone)] @@ -53,6 +73,7 @@ mod issue7392 { .hand .iter() .filter(|c| filter_hand.iter().any(|cc| c == &cc)) + //~^ search_is_some .map(|c| c.clone()) .collect::>(); } @@ -69,6 +90,7 @@ mod issue7392 { .hand .iter() .filter(|(c, _)| filter_hand.iter().any(|cc| c == cc)) + //~^ search_is_some .map(|c| c.clone()) .collect::>(); } @@ -80,6 +102,7 @@ mod issue7392 { } let vfoo = vec![Foo { foo: 1, bar: 2 }]; let _ = vfoo.iter().any(|v| v.foo == 1 && v.bar == 2); + //~^ search_is_some let vfoo = vec![(42, Foo { foo: 1, bar: 2 })]; let _ = vfoo @@ -90,12 +113,14 @@ mod issue7392 { fn index_projection() { let vfoo = vec![[0, 1, 2, 3]]; let _ = vfoo.iter().any(|a| a[0] == 42); + //~^ search_is_some } #[allow(clippy::match_like_matches_macro)] fn slice_projection() { let vfoo = vec![[0, 1, 2, 3, 0, 1, 2, 3]]; let _ = vfoo.iter().any(|sub| sub[1..4].len() == 3); + //~^ search_is_some } fn please(x: &u32) -> bool { @@ -114,16 +139,22 @@ mod issue7392 { let x = 19; let ppx: &u32 = &x; let _ = [ppx].iter().any(|ppp_x: &&u32| please(ppp_x)); + //~^ search_is_some let _ = [String::from("Hey hey")].iter().any(|s| s.len() == 2); + //~^ search_is_some let v = vec![3, 2, 1, 0]; let _ = v.iter().any(|x| deref_enough(*x)); + //~^ search_is_some let _ = v.iter().any(|x: &u32| deref_enough(*x)); + //~^ search_is_some #[allow(clippy::redundant_closure)] let _ = v.iter().any(|x| arg_no_deref(&x)); + //~^ search_is_some #[allow(clippy::redundant_closure)] let _ = v.iter().any(|x: &u32| arg_no_deref(&x)); + //~^ search_is_some } fn field_index_projection() { @@ -159,11 +190,13 @@ mod issue7392 { inner: vec![Foo { bar: 0 }], }]; let _ = vfoo.iter().any(|v| v.inner[0].bar == 2); + //~^ search_is_some } fn double_deref_index_projection() { let vfoo = vec![&&[0, 1, 2, 3]]; let _ = vfoo.iter().any(|x| (**x)[0] == 9); + //~^ search_is_some } fn method_call_by_ref() { @@ -177,11 +210,14 @@ mod issue7392 { } let vfoo = vec![Foo { bar: 1 }]; let _ = vfoo.iter().any(|v| v.by_ref(&v.bar)); + //~^ search_is_some } fn ref_bindings() { let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().any(|(&x, y)| x == *y); + //~^ search_is_some let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().any(|(&x, y)| x == *y); + //~^ search_is_some } fn test_string_1(s: &str) -> bool { @@ -201,7 +237,9 @@ mod issue7392 { let lst = &[String::from("Hello"), String::from("world")]; let v: Vec<&[String]> = vec![lst]; let _ = v.iter().any(|s| s[0].is_empty()); + //~^ search_is_some let _ = v.iter().any(|s| test_string_1(&s[0])); + //~^ search_is_some // Field projections struct FieldProjection<'a> { @@ -211,8 +249,11 @@ mod issue7392 { let instance = FieldProjection { field: &field }; let v = vec![instance]; let _ = v.iter().any(|fp| fp.field.is_power_of_two()); + //~^ search_is_some let _ = v.iter().any(|fp| test_u32_1(fp.field)); + //~^ search_is_some let _ = v.iter().any(|fp| test_u32_2(*fp.field)); + //~^ search_is_some } } @@ -228,6 +269,7 @@ mod issue9120 { fn wrapper bool>(v: Vec, func: T) -> bool { #[allow(clippy::redundant_closure)] v.iter().any(|x: &u32| func(&x)) + //~^ search_is_some } fn do_tests() { @@ -237,11 +279,14 @@ mod issue9120 { #[allow(clippy::redundant_closure)] let _ = v.iter().any(|x: &u32| arg_no_deref_impl(&x)); + //~^ search_is_some #[allow(clippy::redundant_closure)] let _ = v.iter().any(|x: &u32| arg_no_deref_dyn(&x)); + //~^ search_is_some #[allow(clippy::redundant_closure)] let _ = v.iter().any(|x: &u32| (*arg_no_deref_dyn)(&x)); + //~^ search_is_some } } diff --git a/tests/ui/search_is_some_fixable_some.rs b/tests/ui/search_is_some_fixable_some.rs index 19a44803fd54..caab816f2436 100644 --- a/tests/ui/search_is_some_fixable_some.rs +++ b/tests/ui/search_is_some_fixable_some.rs @@ -1,4 +1,4 @@ -#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec)] +#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec, clippy::manual_contains)] #![warn(clippy::search_is_some)] fn main() { @@ -7,37 +7,58 @@ fn main() { // Check `find().is_some()`, single-line case. let _ = v.iter().find(|&x| *x < 0).is_some(); + //~^ search_is_some let _ = (0..1).find(|x| **y == *x).is_some(); // one dereference less + // + //~^^ search_is_some let _ = (0..1).find(|x| *x == 0).is_some(); + //~^ search_is_some let _ = v.iter().find(|x| **x == 0).is_some(); + //~^ search_is_some let _ = (4..5).find(|x| *x == 1 || *x == 3 || *x == 5).is_some(); + //~^ search_is_some let _ = (1..3).find(|x| [1, 2, 3].contains(x)).is_some(); + //~^ search_is_some let _ = (1..3).find(|x| *x == 0 || [1, 2, 3].contains(x)).is_some(); + //~^ search_is_some let _ = (1..3).find(|x| [1, 2, 3].contains(x) || *x == 0).is_some(); + //~^ search_is_some let _ = (1..3) .find(|x| [1, 2, 3].contains(x) || *x == 0 || [4, 5, 6].contains(x) || *x == -1) + //~^ search_is_some .is_some(); // Check `position().is_some()`, single-line case. let _ = v.iter().position(|&x| x < 0).is_some(); + //~^ search_is_some // Check `rposition().is_some()`, single-line case. let _ = v.iter().rposition(|&x| x < 0).is_some(); + //~^ search_is_some let s1 = String::from("hello world"); let s2 = String::from("world"); // caller of `find()` is a `&`static str` let _ = "hello world".find("world").is_some(); + //~^ search_is_some let _ = "hello world".find(&s2).is_some(); + //~^ search_is_some let _ = "hello world".find(&s2[2..]).is_some(); + //~^ search_is_some // caller of `find()` is a `String` let _ = s1.find("world").is_some(); + //~^ search_is_some let _ = s1.find(&s2).is_some(); + //~^ search_is_some let _ = s1.find(&s2[2..]).is_some(); + //~^ search_is_some // caller of `find()` is slice of `String` let _ = s1[2..].find("world").is_some(); + //~^ search_is_some let _ = s1[2..].find(&s2).is_some(); + //~^ search_is_some let _ = s1[2..].find(&s2[2..]).is_some(); + //~^ search_is_some } #[allow(clippy::clone_on_copy, clippy::map_clone)] @@ -54,6 +75,7 @@ mod issue7392 { .hand .iter() .filter(|c| filter_hand.iter().find(|cc| c == cc).is_some()) + //~^ search_is_some .map(|c| c.clone()) .collect::>(); } @@ -70,6 +92,7 @@ mod issue7392 { .hand .iter() .filter(|(c, _)| filter_hand.iter().find(|cc| c == *cc).is_some()) + //~^ search_is_some .map(|c| c.clone()) .collect::>(); } @@ -81,23 +104,27 @@ mod issue7392 { } let vfoo = vec![Foo { foo: 1, bar: 2 }]; let _ = vfoo.iter().find(|v| v.foo == 1 && v.bar == 2).is_some(); + //~^ search_is_some let vfoo = vec![(42, Foo { foo: 1, bar: 2 })]; let _ = vfoo .iter() .find(|(i, v)| *i == 42 && v.foo == 1 && v.bar == 2) + //~^ search_is_some .is_some(); } fn index_projection() { let vfoo = vec![[0, 1, 2, 3]]; let _ = vfoo.iter().find(|a| a[0] == 42).is_some(); + //~^ search_is_some } #[allow(clippy::match_like_matches_macro)] fn slice_projection() { let vfoo = vec![[0, 1, 2, 3, 0, 1, 2, 3]]; let _ = vfoo.iter().find(|sub| sub[1..4].len() == 3).is_some(); + //~^ search_is_some } fn please(x: &u32) -> bool { @@ -116,16 +143,22 @@ mod issue7392 { let x = 19; let ppx: &u32 = &x; let _ = [ppx].iter().find(|ppp_x: &&&u32| please(**ppp_x)).is_some(); + //~^ search_is_some let _ = [String::from("Hey hey")].iter().find(|s| s.len() == 2).is_some(); + //~^ search_is_some let v = vec![3, 2, 1, 0]; let _ = v.iter().find(|x| deref_enough(**x)).is_some(); + //~^ search_is_some let _ = v.iter().find(|x: &&u32| deref_enough(**x)).is_some(); + //~^ search_is_some #[allow(clippy::redundant_closure)] let _ = v.iter().find(|x| arg_no_deref(x)).is_some(); + //~^ search_is_some #[allow(clippy::redundant_closure)] let _ = v.iter().find(|x: &&u32| arg_no_deref(x)).is_some(); + //~^ search_is_some } fn field_index_projection() { @@ -148,6 +181,7 @@ mod issue7392 { let _ = vfoo .iter() .find(|v| v.inner_double.bar[0][0] == 2 && v.inner.bar[0] == 2) + //~^ search_is_some .is_some(); } @@ -162,11 +196,13 @@ mod issue7392 { inner: vec![Foo { bar: 0 }], }]; let _ = vfoo.iter().find(|v| v.inner[0].bar == 2).is_some(); + //~^ search_is_some } fn double_deref_index_projection() { let vfoo = vec![&&[0, 1, 2, 3]]; let _ = vfoo.iter().find(|x| (**x)[0] == 9).is_some(); + //~^ search_is_some } fn method_call_by_ref() { @@ -180,11 +216,14 @@ mod issue7392 { } let vfoo = vec![Foo { bar: 1 }]; let _ = vfoo.iter().find(|v| v.by_ref(&v.bar)).is_some(); + //~^ search_is_some } fn ref_bindings() { let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|(&x, y)| x == *y).is_some(); + //~^ search_is_some let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|&(&x, y)| x == *y).is_some(); + //~^ search_is_some } fn test_string_1(s: &str) -> bool { @@ -204,7 +243,9 @@ mod issue7392 { let lst = &[String::from("Hello"), String::from("world")]; let v: Vec<&[String]> = vec![lst]; let _ = v.iter().find(|s| s[0].is_empty()).is_some(); + //~^ search_is_some let _ = v.iter().find(|s| test_string_1(&s[0])).is_some(); + //~^ search_is_some // Field projections struct FieldProjection<'a> { @@ -214,8 +255,11 @@ mod issue7392 { let instance = FieldProjection { field: &field }; let v = vec![instance]; let _ = v.iter().find(|fp| fp.field.is_power_of_two()).is_some(); + //~^ search_is_some let _ = v.iter().find(|fp| test_u32_1(fp.field)).is_some(); + //~^ search_is_some let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_some(); + //~^ search_is_some } } @@ -231,6 +275,7 @@ mod issue9120 { fn wrapper bool>(v: Vec, func: T) -> bool { #[allow(clippy::redundant_closure)] v.iter().find(|x: &&u32| func(x)).is_some() + //~^ search_is_some } fn do_tests() { @@ -240,11 +285,14 @@ mod issue9120 { #[allow(clippy::redundant_closure)] let _ = v.iter().find(|x: &&u32| arg_no_deref_impl(x)).is_some(); + //~^ search_is_some #[allow(clippy::redundant_closure)] let _ = v.iter().find(|x: &&u32| arg_no_deref_dyn(x)).is_some(); + //~^ search_is_some #[allow(clippy::redundant_closure)] let _ = v.iter().find(|x: &&u32| (*arg_no_deref_dyn)(x)).is_some(); + //~^ search_is_some } } diff --git a/tests/ui/search_is_some_fixable_some.stderr b/tests/ui/search_is_some_fixable_some.stderr index af1de7f82f80..af719b78831a 100644 --- a/tests/ui/search_is_some_fixable_some.stderr +++ b/tests/ui/search_is_some_fixable_some.stderr @@ -8,283 +8,286 @@ LL | let _ = v.iter().find(|&x| *x < 0).is_some(); = help: to override `-D warnings` add `#[allow(clippy::search_is_some)]` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:10:20 + --> tests/ui/search_is_some_fixable_some.rs:11:20 | LL | let _ = (0..1).find(|x| **y == *x).is_some(); // one dereference less | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x| **y == x)` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:11:20 + --> tests/ui/search_is_some_fixable_some.rs:14:20 | LL | let _ = (0..1).find(|x| *x == 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x| x == 0)` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:12:22 + --> tests/ui/search_is_some_fixable_some.rs:16:22 | LL | let _ = v.iter().find(|x| **x == 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x| *x == 0)` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:13:20 + --> tests/ui/search_is_some_fixable_some.rs:18:20 | LL | let _ = (4..5).find(|x| *x == 1 || *x == 3 || *x == 5).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x| x == 1 || x == 3 || x == 5)` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:14:20 + --> tests/ui/search_is_some_fixable_some.rs:20:20 | LL | let _ = (1..3).find(|x| [1, 2, 3].contains(x)).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x| [1, 2, 3].contains(&x))` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:15:20 + --> tests/ui/search_is_some_fixable_some.rs:22:20 | LL | let _ = (1..3).find(|x| *x == 0 || [1, 2, 3].contains(x)).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x| x == 0 || [1, 2, 3].contains(&x))` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:16:20 + --> tests/ui/search_is_some_fixable_some.rs:24:20 | LL | let _ = (1..3).find(|x| [1, 2, 3].contains(x) || *x == 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x| [1, 2, 3].contains(&x) || x == 0)` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:18:10 + --> tests/ui/search_is_some_fixable_some.rs:27:10 | LL | .find(|x| [1, 2, 3].contains(x) || *x == 0 || [4, 5, 6].contains(x) || *x == -1) | __________^ +LL | | LL | | .is_some(); | |__________________^ help: consider using: `any(|x| [1, 2, 3].contains(&x) || x == 0 || [4, 5, 6].contains(&x) || x == -1)` error: called `is_some()` after searching an `Iterator` with `position` - --> tests/ui/search_is_some_fixable_some.rs:22:22 + --> tests/ui/search_is_some_fixable_some.rs:32:22 | LL | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with `rposition` - --> tests/ui/search_is_some_fixable_some.rs:25:22 + --> tests/ui/search_is_some_fixable_some.rs:36:22 | LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|&x| x < 0)` error: called `is_some()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_some.rs:30:27 + --> tests/ui/search_is_some_fixable_some.rs:42:27 | LL | let _ = "hello world".find("world").is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `contains("world")` error: called `is_some()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_some.rs:31:27 + --> tests/ui/search_is_some_fixable_some.rs:44:27 | LL | let _ = "hello world".find(&s2).is_some(); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `contains(&s2)` error: called `is_some()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_some.rs:32:27 + --> tests/ui/search_is_some_fixable_some.rs:46:27 | LL | let _ = "hello world".find(&s2[2..]).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `contains(&s2[2..])` error: called `is_some()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_some.rs:34:16 + --> tests/ui/search_is_some_fixable_some.rs:49:16 | LL | let _ = s1.find("world").is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `contains("world")` error: called `is_some()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_some.rs:35:16 + --> tests/ui/search_is_some_fixable_some.rs:51:16 | LL | let _ = s1.find(&s2).is_some(); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `contains(&s2)` error: called `is_some()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_some.rs:36:16 + --> tests/ui/search_is_some_fixable_some.rs:53:16 | LL | let _ = s1.find(&s2[2..]).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `contains(&s2[2..])` error: called `is_some()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_some.rs:38:21 + --> tests/ui/search_is_some_fixable_some.rs:56:21 | LL | let _ = s1[2..].find("world").is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `contains("world")` error: called `is_some()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_some.rs:39:21 + --> tests/ui/search_is_some_fixable_some.rs:58:21 | LL | let _ = s1[2..].find(&s2).is_some(); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `contains(&s2)` error: called `is_some()` after calling `find()` on a string - --> tests/ui/search_is_some_fixable_some.rs:40:21 + --> tests/ui/search_is_some_fixable_some.rs:60:21 | LL | let _ = s1[2..].find(&s2[2..]).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `contains(&s2[2..])` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:56:44 + --> tests/ui/search_is_some_fixable_some.rs:77:44 | LL | .filter(|c| filter_hand.iter().find(|cc| c == cc).is_some()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|cc| c == &cc)` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:72:49 + --> tests/ui/search_is_some_fixable_some.rs:94:49 | LL | .filter(|(c, _)| filter_hand.iter().find(|cc| c == *cc).is_some()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|cc| c == cc)` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:83:29 + --> tests/ui/search_is_some_fixable_some.rs:106:29 | LL | let _ = vfoo.iter().find(|v| v.foo == 1 && v.bar == 2).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|v| v.foo == 1 && v.bar == 2)` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:88:14 + --> tests/ui/search_is_some_fixable_some.rs:112:14 | LL | .find(|(i, v)| *i == 42 && v.foo == 1 && v.bar == 2) | ______________^ +LL | | LL | | .is_some(); | |______________________^ help: consider using: `any(|(i, v)| *i == 42 && v.foo == 1 && v.bar == 2)` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:94:29 + --> tests/ui/search_is_some_fixable_some.rs:119:29 | LL | let _ = vfoo.iter().find(|a| a[0] == 42).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|a| a[0] == 42)` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:100:29 + --> tests/ui/search_is_some_fixable_some.rs:126:29 | LL | let _ = vfoo.iter().find(|sub| sub[1..4].len() == 3).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|sub| sub[1..4].len() == 3)` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:118:30 + --> tests/ui/search_is_some_fixable_some.rs:145:30 | LL | let _ = [ppx].iter().find(|ppp_x: &&&u32| please(**ppp_x)).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|ppp_x: &&u32| please(ppp_x))` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:119:50 + --> tests/ui/search_is_some_fixable_some.rs:147:50 | LL | let _ = [String::from("Hey hey")].iter().find(|s| s.len() == 2).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|s| s.len() == 2)` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:122:26 + --> tests/ui/search_is_some_fixable_some.rs:151:26 | LL | let _ = v.iter().find(|x| deref_enough(**x)).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x| deref_enough(*x))` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:123:26 + --> tests/ui/search_is_some_fixable_some.rs:153:26 | LL | let _ = v.iter().find(|x: &&u32| deref_enough(**x)).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x: &u32| deref_enough(*x))` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:126:26 + --> tests/ui/search_is_some_fixable_some.rs:157:26 | LL | let _ = v.iter().find(|x| arg_no_deref(x)).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x| arg_no_deref(&x))` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:128:26 + --> tests/ui/search_is_some_fixable_some.rs:160:26 | LL | let _ = v.iter().find(|x: &&u32| arg_no_deref(x)).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x: &u32| arg_no_deref(&x))` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:150:14 + --> tests/ui/search_is_some_fixable_some.rs:183:14 | LL | .find(|v| v.inner_double.bar[0][0] == 2 && v.inner.bar[0] == 2) | ______________^ +LL | | LL | | .is_some(); | |______________________^ help: consider using: `any(|v| v.inner_double.bar[0][0] == 2 && v.inner.bar[0] == 2)` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:164:29 + --> tests/ui/search_is_some_fixable_some.rs:198:29 | LL | let _ = vfoo.iter().find(|v| v.inner[0].bar == 2).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|v| v.inner[0].bar == 2)` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:169:29 + --> tests/ui/search_is_some_fixable_some.rs:204:29 | LL | let _ = vfoo.iter().find(|x| (**x)[0] == 9).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x| (**x)[0] == 9)` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:182:29 + --> tests/ui/search_is_some_fixable_some.rs:218:29 | LL | let _ = vfoo.iter().find(|v| v.by_ref(&v.bar)).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|v| v.by_ref(&v.bar))` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:186:55 + --> tests/ui/search_is_some_fixable_some.rs:223:55 | LL | let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|(&x, y)| x == *y).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|(&x, y)| x == *y)` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:187:55 + --> tests/ui/search_is_some_fixable_some.rs:225:55 | LL | let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|&(&x, y)| x == *y).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|(&x, y)| x == *y)` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:206:26 + --> tests/ui/search_is_some_fixable_some.rs:245:26 | LL | let _ = v.iter().find(|s| s[0].is_empty()).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|s| s[0].is_empty())` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:207:26 + --> tests/ui/search_is_some_fixable_some.rs:247:26 | LL | let _ = v.iter().find(|s| test_string_1(&s[0])).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|s| test_string_1(&s[0]))` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:216:26 + --> tests/ui/search_is_some_fixable_some.rs:257:26 | LL | let _ = v.iter().find(|fp| fp.field.is_power_of_two()).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|fp| fp.field.is_power_of_two())` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:217:26 + --> tests/ui/search_is_some_fixable_some.rs:259:26 | LL | let _ = v.iter().find(|fp| test_u32_1(fp.field)).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|fp| test_u32_1(fp.field))` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:218:26 + --> tests/ui/search_is_some_fixable_some.rs:261:26 | LL | let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|fp| test_u32_2(*fp.field))` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:233:18 + --> tests/ui/search_is_some_fixable_some.rs:277:18 | LL | v.iter().find(|x: &&u32| func(x)).is_some() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x: &u32| func(&x))` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:242:26 + --> tests/ui/search_is_some_fixable_some.rs:287:26 | LL | let _ = v.iter().find(|x: &&u32| arg_no_deref_impl(x)).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x: &u32| arg_no_deref_impl(&x))` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:245:26 + --> tests/ui/search_is_some_fixable_some.rs:291:26 | LL | let _ = v.iter().find(|x: &&u32| arg_no_deref_dyn(x)).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x: &u32| arg_no_deref_dyn(&x))` error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:248:26 + --> tests/ui/search_is_some_fixable_some.rs:295:26 | LL | let _ = v.iter().find(|x: &&u32| (*arg_no_deref_dyn)(x)).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x: &u32| (*arg_no_deref_dyn)(&x))` diff --git a/tests/ui/seek_from_current.fixed b/tests/ui/seek_from_current.fixed index 543f0c681393..08eb15fe4e78 100644 --- a/tests/ui/seek_from_current.fixed +++ b/tests/ui/seek_from_current.fixed @@ -17,6 +17,7 @@ fn _msrv_1_51() -> io::Result<()> { let mut f = File::create("foo.txt")?; f.write_all(b"Hi!")?; f.stream_position()?; + //~^ seek_from_current f.seek(SeekFrom::Current(1))?; Ok(()) } diff --git a/tests/ui/seek_from_current.rs b/tests/ui/seek_from_current.rs index 4ed877f8ec21..1974fd60dec7 100644 --- a/tests/ui/seek_from_current.rs +++ b/tests/ui/seek_from_current.rs @@ -17,6 +17,7 @@ fn _msrv_1_51() -> io::Result<()> { let mut f = File::create("foo.txt")?; f.write_all(b"Hi!")?; f.seek(SeekFrom::Current(0))?; + //~^ seek_from_current f.seek(SeekFrom::Current(1))?; Ok(()) } diff --git a/tests/ui/seek_to_start_instead_of_rewind.fixed b/tests/ui/seek_to_start_instead_of_rewind.fixed index 8859a68320f0..87747eafc443 100644 --- a/tests/ui/seek_to_start_instead_of_rewind.fixed +++ b/tests/ui/seek_to_start_instead_of_rewind.fixed @@ -50,11 +50,13 @@ fn seek_to_start_false_trait_bound(t: &mut T) { // This should trigger clippy warning fn seek_to_start(t: &mut T) { t.rewind(); + //~^ seek_to_start_instead_of_rewind } // This should trigger clippy warning fn owned_seek_to_start(mut t: T) { t.rewind(); + //~^ seek_to_start_instead_of_rewind } // This should NOT trigger clippy warning because @@ -134,6 +136,7 @@ fn msrv_1_55() { write!(f, "{hello}").unwrap(); f.rewind(); + //~^ seek_to_start_instead_of_rewind let mut buf = String::new(); f.read_to_string(&mut buf).unwrap(); diff --git a/tests/ui/seek_to_start_instead_of_rewind.rs b/tests/ui/seek_to_start_instead_of_rewind.rs index 7b72efb34ff8..e824a9b1ec31 100644 --- a/tests/ui/seek_to_start_instead_of_rewind.rs +++ b/tests/ui/seek_to_start_instead_of_rewind.rs @@ -50,11 +50,13 @@ fn seek_to_start_false_trait_bound(t: &mut T) { // This should trigger clippy warning fn seek_to_start(t: &mut T) { t.seek(SeekFrom::Start(0)); + //~^ seek_to_start_instead_of_rewind } // This should trigger clippy warning fn owned_seek_to_start(mut t: T) { t.seek(SeekFrom::Start(0)); + //~^ seek_to_start_instead_of_rewind } // This should NOT trigger clippy warning because @@ -134,6 +136,7 @@ fn msrv_1_55() { write!(f, "{hello}").unwrap(); f.seek(SeekFrom::Start(0)); + //~^ seek_to_start_instead_of_rewind let mut buf = String::new(); f.read_to_string(&mut buf).unwrap(); diff --git a/tests/ui/seek_to_start_instead_of_rewind.stderr b/tests/ui/seek_to_start_instead_of_rewind.stderr index 2c3c45820e10..6c6575cc02f5 100644 --- a/tests/ui/seek_to_start_instead_of_rewind.stderr +++ b/tests/ui/seek_to_start_instead_of_rewind.stderr @@ -8,13 +8,13 @@ LL | t.seek(SeekFrom::Start(0)); = help: to override `-D warnings` add `#[allow(clippy::seek_to_start_instead_of_rewind)]` error: used `seek` to go to the start of the stream - --> tests/ui/seek_to_start_instead_of_rewind.rs:57:7 + --> tests/ui/seek_to_start_instead_of_rewind.rs:58:7 | LL | t.seek(SeekFrom::Start(0)); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `rewind()` error: used `seek` to go to the start of the stream - --> tests/ui/seek_to_start_instead_of_rewind.rs:136:7 + --> tests/ui/seek_to_start_instead_of_rewind.rs:138:7 | LL | f.seek(SeekFrom::Start(0)); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `rewind()` diff --git a/tests/ui/self_assignment.rs b/tests/ui/self_assignment.rs index 213bca6c4515..6e82b42cf6d7 100644 --- a/tests/ui/self_assignment.rs +++ b/tests/ui/self_assignment.rs @@ -11,30 +11,38 @@ pub struct S<'a> { pub fn positives(mut a: usize, b: &mut u32, mut s: S) { a = a; - //~^ ERROR: self-assignment of `a` to `a` - //~| NOTE: `-D clippy::self-assignment` implied by `-D warnings` + //~^ self_assignment + *b = *b; - //~^ ERROR: self-assignment of `*b` to `*b` + //~^ self_assignment + s = s; - //~^ ERROR: self-assignment of `s` to `s` + //~^ self_assignment + s.a = s.a; - //~^ ERROR: self-assignment of `s.a` to `s.a` + //~^ self_assignment + s.b[9] = s.b[5 + 4]; - //~^ ERROR: self-assignment of `s.b[5 + 4]` to `s.b[9]` + //~^ self_assignment + s.c[0][1] = s.c[0][1]; - //~^ ERROR: self-assignment of `s.c[0][1]` to `s.c[0][1]` + //~^ self_assignment + s.b[a] = s.b[a]; - //~^ ERROR: self-assignment of `s.b[a]` to `s.b[a]` + //~^ self_assignment + *s.e = *s.e; - //~^ ERROR: self-assignment of `*s.e` to `*s.e` + //~^ self_assignment + s.b[a + 10] = s.b[10 + a]; - //~^ ERROR: self-assignment of `s.b[10 + a]` to `s.b[a + 10]` + //~^ self_assignment let mut t = (0, 1); t.1 = t.1; - //~^ ERROR: self-assignment of `t.1` to `t.1` + //~^ self_assignment + t.0 = (t.0); - //~^ ERROR: self-assignment of `(t.0)` to `t.0` + //~^ self_assignment } pub fn negatives_not_equal(mut a: usize, b: &mut usize, mut s: S) { diff --git a/tests/ui/self_assignment.stderr b/tests/ui/self_assignment.stderr index e92414163d4c..e9a2164187ce 100644 --- a/tests/ui/self_assignment.stderr +++ b/tests/ui/self_assignment.stderr @@ -14,55 +14,55 @@ LL | *b = *b; | ^^^^^^^ error: self-assignment of `s` to `s` - --> tests/ui/self_assignment.rs:18:5 + --> tests/ui/self_assignment.rs:19:5 | LL | s = s; | ^^^^^ error: self-assignment of `s.a` to `s.a` - --> tests/ui/self_assignment.rs:20:5 + --> tests/ui/self_assignment.rs:22:5 | LL | s.a = s.a; | ^^^^^^^^^ error: self-assignment of `s.b[5 + 4]` to `s.b[9]` - --> tests/ui/self_assignment.rs:22:5 + --> tests/ui/self_assignment.rs:25:5 | LL | s.b[9] = s.b[5 + 4]; | ^^^^^^^^^^^^^^^^^^^ error: self-assignment of `s.c[0][1]` to `s.c[0][1]` - --> tests/ui/self_assignment.rs:24:5 + --> tests/ui/self_assignment.rs:28:5 | LL | s.c[0][1] = s.c[0][1]; | ^^^^^^^^^^^^^^^^^^^^^ error: self-assignment of `s.b[a]` to `s.b[a]` - --> tests/ui/self_assignment.rs:26:5 + --> tests/ui/self_assignment.rs:31:5 | LL | s.b[a] = s.b[a]; | ^^^^^^^^^^^^^^^ error: self-assignment of `*s.e` to `*s.e` - --> tests/ui/self_assignment.rs:28:5 + --> tests/ui/self_assignment.rs:34:5 | LL | *s.e = *s.e; | ^^^^^^^^^^^ error: self-assignment of `s.b[10 + a]` to `s.b[a + 10]` - --> tests/ui/self_assignment.rs:30:5 + --> tests/ui/self_assignment.rs:37:5 | LL | s.b[a + 10] = s.b[10 + a]; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: self-assignment of `t.1` to `t.1` - --> tests/ui/self_assignment.rs:34:5 + --> tests/ui/self_assignment.rs:41:5 | LL | t.1 = t.1; | ^^^^^^^^^ error: self-assignment of `(t.0)` to `t.0` - --> tests/ui/self_assignment.rs:36:5 + --> tests/ui/self_assignment.rs:44:5 | LL | t.0 = (t.0); | ^^^^^^^^^^^ diff --git a/tests/ui/self_named_constructors.rs b/tests/ui/self_named_constructors.rs index dc326b399481..8b6453e0d1d7 100644 --- a/tests/ui/self_named_constructors.rs +++ b/tests/ui/self_named_constructors.rs @@ -5,8 +5,8 @@ struct ShouldNotSpawn; impl ShouldSpawn { pub fn should_spawn() -> ShouldSpawn { - //~^ ERROR: constructor `should_spawn` has the same name as the type - //~| NOTE: `-D clippy::self-named-constructors` implied by `-D warnings` + //~^ self_named_constructors + ShouldSpawn } diff --git a/tests/ui/semicolon_if_nothing_returned.fixed b/tests/ui/semicolon_if_nothing_returned.fixed index 6c8c835d0e0e..3de14e9d2595 100644 --- a/tests/ui/semicolon_if_nothing_returned.fixed +++ b/tests/ui/semicolon_if_nothing_returned.fixed @@ -16,21 +16,25 @@ fn get_unit() {} // the functions below trigger the lint fn main() { println!("Hello"); + //~^ semicolon_if_nothing_returned } fn hello() { get_unit(); + //~^ semicolon_if_nothing_returned } fn basic101(x: i32) { let y: i32; y = x + 1; + //~^ semicolon_if_nothing_returned } #[rustfmt::skip] fn closure_error() { let _d = || { hello(); + //~^ semicolon_if_nothing_returned }; } @@ -42,6 +46,7 @@ fn unsafe_checks_error() { let mut s = MaybeUninit::::uninit(); let _d = || unsafe { ptr::drop_in_place(s.as_mut_ptr()); + //~^ semicolon_if_nothing_returned }; } diff --git a/tests/ui/semicolon_if_nothing_returned.rs b/tests/ui/semicolon_if_nothing_returned.rs index 2c2e4c024190..304f43fb457c 100644 --- a/tests/ui/semicolon_if_nothing_returned.rs +++ b/tests/ui/semicolon_if_nothing_returned.rs @@ -16,21 +16,25 @@ fn get_unit() {} // the functions below trigger the lint fn main() { println!("Hello") + //~^ semicolon_if_nothing_returned } fn hello() { get_unit() + //~^ semicolon_if_nothing_returned } fn basic101(x: i32) { let y: i32; y = x + 1 + //~^ semicolon_if_nothing_returned } #[rustfmt::skip] fn closure_error() { let _d = || { hello() + //~^ semicolon_if_nothing_returned }; } @@ -42,6 +46,7 @@ fn unsafe_checks_error() { let mut s = MaybeUninit::::uninit(); let _d = || unsafe { ptr::drop_in_place(s.as_mut_ptr()) + //~^ semicolon_if_nothing_returned }; } diff --git a/tests/ui/semicolon_if_nothing_returned.stderr b/tests/ui/semicolon_if_nothing_returned.stderr index 69e434b142cf..d7d117e05bdf 100644 --- a/tests/ui/semicolon_if_nothing_returned.stderr +++ b/tests/ui/semicolon_if_nothing_returned.stderr @@ -8,25 +8,25 @@ LL | println!("Hello") = help: to override `-D warnings` add `#[allow(clippy::semicolon_if_nothing_returned)]` error: consider adding a `;` to the last statement for consistent formatting - --> tests/ui/semicolon_if_nothing_returned.rs:22:5 + --> tests/ui/semicolon_if_nothing_returned.rs:23:5 | LL | get_unit() | ^^^^^^^^^^ help: add a `;` here: `get_unit();` error: consider adding a `;` to the last statement for consistent formatting - --> tests/ui/semicolon_if_nothing_returned.rs:27:5 + --> tests/ui/semicolon_if_nothing_returned.rs:29:5 | LL | y = x + 1 | ^^^^^^^^^ help: add a `;` here: `y = x + 1;` error: consider adding a `;` to the last statement for consistent formatting - --> tests/ui/semicolon_if_nothing_returned.rs:33:9 + --> tests/ui/semicolon_if_nothing_returned.rs:36:9 | LL | hello() | ^^^^^^^ help: add a `;` here: `hello();` error: consider adding a `;` to the last statement for consistent formatting - --> tests/ui/semicolon_if_nothing_returned.rs:44:9 + --> tests/ui/semicolon_if_nothing_returned.rs:48:9 | LL | ptr::drop_in_place(s.as_mut_ptr()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add a `;` here: `ptr::drop_in_place(s.as_mut_ptr());` diff --git a/tests/ui/semicolon_inside_block.fixed b/tests/ui/semicolon_inside_block.fixed index 21681e71589e..7eb53e733ad5 100644 --- a/tests/ui/semicolon_inside_block.fixed +++ b/tests/ui/semicolon_inside_block.fixed @@ -36,7 +36,9 @@ fn main() { } { unit_fn_block(); } + //~^ semicolon_inside_block unsafe { unit_fn_block(); } + //~^ semicolon_inside_block { unit_fn_block(); } unsafe { unit_fn_block(); } @@ -45,6 +47,7 @@ fn main() { unsafe { unit_fn_block(); }; { + //~^ semicolon_inside_block unit_fn_block(); unit_fn_block(); } @@ -58,6 +61,7 @@ fn main() { }; { m!(()); } + //~^ semicolon_inside_block { m!(()); } { m!(()); }; m!(0); diff --git a/tests/ui/semicolon_inside_block.rs b/tests/ui/semicolon_inside_block.rs index 3a81661cd16f..9fa5b117194d 100644 --- a/tests/ui/semicolon_inside_block.rs +++ b/tests/ui/semicolon_inside_block.rs @@ -36,7 +36,9 @@ fn main() { } { unit_fn_block() }; + //~^ semicolon_inside_block unsafe { unit_fn_block() }; + //~^ semicolon_inside_block { unit_fn_block(); } unsafe { unit_fn_block(); } @@ -45,6 +47,7 @@ fn main() { unsafe { unit_fn_block(); }; { + //~^ semicolon_inside_block unit_fn_block(); unit_fn_block() }; @@ -58,6 +61,7 @@ fn main() { }; { m!(()) }; + //~^ semicolon_inside_block { m!(()); } { m!(()); }; m!(0); diff --git a/tests/ui/semicolon_inside_block.stderr b/tests/ui/semicolon_inside_block.stderr index d32fb681d3b9..23433f4e7ef9 100644 --- a/tests/ui/semicolon_inside_block.stderr +++ b/tests/ui/semicolon_inside_block.stderr @@ -13,7 +13,7 @@ LL + { unit_fn_block(); } | error: consider moving the `;` inside the block for consistent formatting - --> tests/ui/semicolon_inside_block.rs:39:5 + --> tests/ui/semicolon_inside_block.rs:40:5 | LL | unsafe { unit_fn_block() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,9 +25,10 @@ LL + unsafe { unit_fn_block(); } | error: consider moving the `;` inside the block for consistent formatting - --> tests/ui/semicolon_inside_block.rs:47:5 + --> tests/ui/semicolon_inside_block.rs:49:5 | LL | / { +LL | | LL | | unit_fn_block(); LL | | unit_fn_block() LL | | }; @@ -40,7 +41,7 @@ LL ~ } | error: consider moving the `;` inside the block for consistent formatting - --> tests/ui/semicolon_inside_block.rs:60:5 + --> tests/ui/semicolon_inside_block.rs:63:5 | LL | { m!(()) }; | ^^^^^^^^^^^ diff --git a/tests/ui/semicolon_outside_block.fixed b/tests/ui/semicolon_outside_block.fixed index ac7e86631cae..52fae9a3aff1 100644 --- a/tests/ui/semicolon_outside_block.fixed +++ b/tests/ui/semicolon_outside_block.fixed @@ -39,7 +39,9 @@ fn main() { unsafe { unit_fn_block() }; { unit_fn_block() }; + //~^ semicolon_outside_block unsafe { unit_fn_block() }; + //~^ semicolon_outside_block { unit_fn_block(); }; unsafe { unit_fn_block(); }; @@ -49,6 +51,7 @@ fn main() { unit_fn_block() }; { + //~^ semicolon_outside_block unit_fn_block(); unit_fn_block() }; @@ -59,6 +62,7 @@ fn main() { { m!(()) }; { m!(()) }; + //~^ semicolon_outside_block { m!(()); }; m!(0); m!(1); @@ -81,10 +85,12 @@ fn main() { { unit_fn_block(); }; unsafe { + //~^ semicolon_outside_block std::arch::asm!("") }; { + //~^ semicolon_outside_block line!() }; diff --git a/tests/ui/semicolon_outside_block.rs b/tests/ui/semicolon_outside_block.rs index 68f25339e322..5975e66fbb81 100644 --- a/tests/ui/semicolon_outside_block.rs +++ b/tests/ui/semicolon_outside_block.rs @@ -39,7 +39,9 @@ fn main() { unsafe { unit_fn_block() }; { unit_fn_block(); } + //~^ semicolon_outside_block unsafe { unit_fn_block(); } + //~^ semicolon_outside_block { unit_fn_block(); }; unsafe { unit_fn_block(); }; @@ -49,6 +51,7 @@ fn main() { unit_fn_block() }; { + //~^ semicolon_outside_block unit_fn_block(); unit_fn_block(); } @@ -59,6 +62,7 @@ fn main() { { m!(()) }; { m!(()); } + //~^ semicolon_outside_block { m!(()); }; m!(0); m!(1); @@ -81,10 +85,12 @@ fn main() { { unit_fn_block(); }; unsafe { + //~^ semicolon_outside_block std::arch::asm!(""); } { + //~^ semicolon_outside_block line!(); } diff --git a/tests/ui/semicolon_outside_block.stderr b/tests/ui/semicolon_outside_block.stderr index ff8c00048f63..18d6dc697f2e 100644 --- a/tests/ui/semicolon_outside_block.stderr +++ b/tests/ui/semicolon_outside_block.stderr @@ -13,7 +13,7 @@ LL + { unit_fn_block() }; | error: consider moving the `;` outside the block for consistent formatting - --> tests/ui/semicolon_outside_block.rs:42:5 + --> tests/ui/semicolon_outside_block.rs:43:5 | LL | unsafe { unit_fn_block(); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,9 +25,10 @@ LL + unsafe { unit_fn_block() }; | error: consider moving the `;` outside the block for consistent formatting - --> tests/ui/semicolon_outside_block.rs:51:5 + --> tests/ui/semicolon_outside_block.rs:53:5 | LL | / { +LL | | LL | | unit_fn_block(); LL | | unit_fn_block(); LL | | } @@ -40,7 +41,7 @@ LL ~ }; | error: consider moving the `;` outside the block for consistent formatting - --> tests/ui/semicolon_outside_block.rs:61:5 + --> tests/ui/semicolon_outside_block.rs:64:5 | LL | { m!(()); } | ^^^^^^^^^^^ @@ -52,9 +53,10 @@ LL + { m!(()) }; | error: consider moving the `;` outside the block for consistent formatting - --> tests/ui/semicolon_outside_block.rs:83:5 + --> tests/ui/semicolon_outside_block.rs:87:5 | LL | / unsafe { +LL | | LL | | std::arch::asm!(""); LL | | } | |_____^ @@ -66,9 +68,10 @@ LL ~ }; | error: consider moving the `;` outside the block for consistent formatting - --> tests/ui/semicolon_outside_block.rs:87:5 + --> tests/ui/semicolon_outside_block.rs:92:5 | LL | / { +LL | | LL | | line!(); LL | | } | |_____^ diff --git a/tests/ui/serde.rs b/tests/ui/serde.rs index af8b10f3e6ae..8ab1144e5700 100644 --- a/tests/ui/serde.rs +++ b/tests/ui/serde.rs @@ -37,8 +37,7 @@ impl<'de> serde::de::Visitor<'de> for B { } fn visit_string(self, _v: String) -> Result - //~^ ERROR: you should not implement `visit_string` without also implementing `visit_s - //~| NOTE: `-D clippy::serde-api-misuse` implied by `-D warnings` + //~^ serde_api_misuse where E: serde::de::Error, { diff --git a/tests/ui/serde.stderr b/tests/ui/serde.stderr index f71d41d58aae..eb6b7c6b0c36 100644 --- a/tests/ui/serde.stderr +++ b/tests/ui/serde.stderr @@ -3,9 +3,9 @@ error: you should not implement `visit_string` without also implementing `visit_ | LL | / fn visit_string(self, _v: String) -> Result LL | | -LL | | LL | | where -... | +LL | | E: serde::de::Error, +LL | | { LL | | unimplemented!() LL | | } | |_____^ diff --git a/tests/ui/set_contains_or_insert.rs b/tests/ui/set_contains_or_insert.rs index d3a3e1c878b3..575cfda139a4 100644 --- a/tests/ui/set_contains_or_insert.rs +++ b/tests/ui/set_contains_or_insert.rs @@ -10,35 +10,42 @@ fn should_warn_hashset() { let value = 5; if !set.contains(&value) { + //~^ set_contains_or_insert set.insert(value); println!("Just a comment"); } if set.contains(&value) { + //~^ set_contains_or_insert set.insert(value); println!("Just a comment"); } if !set.contains(&value) { + //~^ set_contains_or_insert set.insert(value); } if !!set.contains(&value) { + //~^ set_contains_or_insert set.insert(value); println!("Just a comment"); } if (&set).contains(&value) { + //~^ set_contains_or_insert set.insert(value); } let borrow_value = &6; if !set.contains(borrow_value) { + //~^ set_contains_or_insert set.insert(*borrow_value); } let borrow_set = &mut set; if !borrow_set.contains(&value) { + //~^ set_contains_or_insert borrow_set.insert(value); } } @@ -77,35 +84,42 @@ fn should_warn_btreeset() { let value = 5; if !set.contains(&value) { + //~^ set_contains_or_insert set.insert(value); println!("Just a comment"); } if set.contains(&value) { + //~^ set_contains_or_insert set.insert(value); println!("Just a comment"); } if !set.contains(&value) { + //~^ set_contains_or_insert set.insert(value); } if !!set.contains(&value) { + //~^ set_contains_or_insert set.insert(value); println!("Just a comment"); } if (&set).contains(&value) { + //~^ set_contains_or_insert set.insert(value); } let borrow_value = &6; if !set.contains(borrow_value) { + //~^ set_contains_or_insert set.insert(*borrow_value); } let borrow_set = &mut set; if !borrow_set.contains(&value) { + //~^ set_contains_or_insert borrow_set.insert(value); } } diff --git a/tests/ui/set_contains_or_insert.stderr b/tests/ui/set_contains_or_insert.stderr index 14ad63005448..3152b1136458 100644 --- a/tests/ui/set_contains_or_insert.stderr +++ b/tests/ui/set_contains_or_insert.stderr @@ -3,6 +3,7 @@ error: usage of `HashSet::insert` after `HashSet::contains` | LL | if !set.contains(&value) { | ^^^^^^^^^^^^^^^^ +LL | LL | set.insert(value); | ^^^^^^^^^^^^^ | @@ -10,106 +11,119 @@ LL | set.insert(value); = help: to override `-D warnings` add `#[allow(clippy::set_contains_or_insert)]` error: usage of `HashSet::insert` after `HashSet::contains` - --> tests/ui/set_contains_or_insert.rs:17:12 + --> tests/ui/set_contains_or_insert.rs:18:12 | LL | if set.contains(&value) { | ^^^^^^^^^^^^^^^^ +LL | LL | set.insert(value); | ^^^^^^^^^^^^^ error: usage of `HashSet::insert` after `HashSet::contains` - --> tests/ui/set_contains_or_insert.rs:22:13 + --> tests/ui/set_contains_or_insert.rs:24:13 | LL | if !set.contains(&value) { | ^^^^^^^^^^^^^^^^ +LL | LL | set.insert(value); | ^^^^^^^^^^^^^ error: usage of `HashSet::insert` after `HashSet::contains` - --> tests/ui/set_contains_or_insert.rs:26:14 + --> tests/ui/set_contains_or_insert.rs:29:14 | LL | if !!set.contains(&value) { | ^^^^^^^^^^^^^^^^ +LL | LL | set.insert(value); | ^^^^^^^^^^^^^ error: usage of `HashSet::insert` after `HashSet::contains` - --> tests/ui/set_contains_or_insert.rs:31:15 + --> tests/ui/set_contains_or_insert.rs:35:15 | LL | if (&set).contains(&value) { | ^^^^^^^^^^^^^^^^ +LL | LL | set.insert(value); | ^^^^^^^^^^^^^ error: usage of `HashSet::insert` after `HashSet::contains` - --> tests/ui/set_contains_or_insert.rs:36:13 + --> tests/ui/set_contains_or_insert.rs:41:13 | LL | if !set.contains(borrow_value) { | ^^^^^^^^^^^^^^^^^^^^^^ +LL | LL | set.insert(*borrow_value); | ^^^^^^^^^^^^^^^^^^^^^ error: usage of `HashSet::insert` after `HashSet::contains` - --> tests/ui/set_contains_or_insert.rs:41:20 + --> tests/ui/set_contains_or_insert.rs:47:20 | LL | if !borrow_set.contains(&value) { | ^^^^^^^^^^^^^^^^ +LL | LL | borrow_set.insert(value); | ^^^^^^^^^^^^^ error: usage of `BTreeSet::insert` after `BTreeSet::contains` - --> tests/ui/set_contains_or_insert.rs:79:13 + --> tests/ui/set_contains_or_insert.rs:86:13 | LL | if !set.contains(&value) { | ^^^^^^^^^^^^^^^^ +LL | LL | set.insert(value); | ^^^^^^^^^^^^^ error: usage of `BTreeSet::insert` after `BTreeSet::contains` - --> tests/ui/set_contains_or_insert.rs:84:12 + --> tests/ui/set_contains_or_insert.rs:92:12 | LL | if set.contains(&value) { | ^^^^^^^^^^^^^^^^ +LL | LL | set.insert(value); | ^^^^^^^^^^^^^ error: usage of `BTreeSet::insert` after `BTreeSet::contains` - --> tests/ui/set_contains_or_insert.rs:89:13 + --> tests/ui/set_contains_or_insert.rs:98:13 | LL | if !set.contains(&value) { | ^^^^^^^^^^^^^^^^ +LL | LL | set.insert(value); | ^^^^^^^^^^^^^ error: usage of `BTreeSet::insert` after `BTreeSet::contains` - --> tests/ui/set_contains_or_insert.rs:93:14 + --> tests/ui/set_contains_or_insert.rs:103:14 | LL | if !!set.contains(&value) { | ^^^^^^^^^^^^^^^^ +LL | LL | set.insert(value); | ^^^^^^^^^^^^^ error: usage of `BTreeSet::insert` after `BTreeSet::contains` - --> tests/ui/set_contains_or_insert.rs:98:15 + --> tests/ui/set_contains_or_insert.rs:109:15 | LL | if (&set).contains(&value) { | ^^^^^^^^^^^^^^^^ +LL | LL | set.insert(value); | ^^^^^^^^^^^^^ error: usage of `BTreeSet::insert` after `BTreeSet::contains` - --> tests/ui/set_contains_or_insert.rs:103:13 + --> tests/ui/set_contains_or_insert.rs:115:13 | LL | if !set.contains(borrow_value) { | ^^^^^^^^^^^^^^^^^^^^^^ +LL | LL | set.insert(*borrow_value); | ^^^^^^^^^^^^^^^^^^^^^ error: usage of `BTreeSet::insert` after `BTreeSet::contains` - --> tests/ui/set_contains_or_insert.rs:108:20 + --> tests/ui/set_contains_or_insert.rs:121:20 | LL | if !borrow_set.contains(&value) { | ^^^^^^^^^^^^^^^^ +LL | LL | borrow_set.insert(value); | ^^^^^^^^^^^^^ diff --git a/tests/ui/shadow.rs b/tests/ui/shadow.rs index 31944f5ef1b1..7d503a1cf6c1 100644 --- a/tests/ui/shadow.rs +++ b/tests/ui/shadow.rs @@ -22,22 +22,34 @@ macro_rules! reuse { fn shadow_same() { let x = 1; let x = x; + //~^ shadow_same let mut x = &x; + //~^ shadow_same let x = &mut x; + //~^ shadow_same let x = *x; + //~^ shadow_same } fn shadow_reuse() -> Option<()> { let x = ([[0]], ()); let x = x.0; + //~^ shadow_reuse let x = x[0]; + //~^ shadow_reuse let [x] = x; + //~^ shadow_reuse let x = Some(x); + //~^ shadow_reuse let x = foo(x); + //~^ shadow_reuse let x = || x; + //~^ shadow_reuse let x = Some(1).map(|_| x)?; + //~^ shadow_reuse let y = 1; let y = match y { + //~^ shadow_reuse 1 => 2, _ => 3, }; @@ -53,27 +65,36 @@ fn shadow_reuse_macro() { fn shadow_unrelated() { let x = 1; let x = 2; + //~^ shadow_unrelated } fn syntax() { fn f(x: u32) { let x = 1; + //~^ shadow_unrelated } let x = 1; match Some(1) { Some(1) => {}, Some(x) => { + //~^ shadow_unrelated let x = 1; + //~^ shadow_unrelated }, _ => {}, } if let Some(x) = Some(1) {} + //~^ shadow_unrelated while let Some(x) = Some(1) {} + //~^ shadow_unrelated let _ = |[x]: [u32; 1]| { + //~^ shadow_unrelated let x = 1; + //~^ shadow_unrelated }; let y = Some(1); if let Some(y) = y {} + //~^ shadow_reuse } fn negative() { @@ -110,12 +131,14 @@ pub async fn foo1(_a: i32) {} pub async fn foo2(_a: i32, _b: i64) { let _b = _a; + //~^ shadow_unrelated } fn ice_8748() { let _ = [0; { let x = 1; if let Some(x) = Some(1) { x } else { 1 } + //~^ shadow_unrelated }]; } @@ -126,10 +149,12 @@ fn shadow_closure() { #[allow(clippy::shadow_reuse)] let y = x.map(|x| x + 1); let z = x.map(|x| x + 1); + //~^ shadow_reuse let a: Vec> = [100u8, 120, 140] .iter() .map(|i| i.checked_mul(2)) .map(|i| i.map(|i| i - 10)) + //~^ shadow_reuse .collect(); } @@ -139,6 +164,7 @@ struct Issue13795 { fn issue13795(value: Issue13795) { let Issue13795 { value, .. } = value; + //~^ shadow_same } fn main() {} diff --git a/tests/ui/shadow.stderr b/tests/ui/shadow.stderr index c8c524b3a2f5..649f843575a7 100644 --- a/tests/ui/shadow.stderr +++ b/tests/ui/shadow.stderr @@ -13,7 +13,7 @@ LL | let x = 1; = help: to override `-D warnings` add `#[allow(clippy::shadow_same)]` error: `mut x` is shadowed by itself in `&x` - --> tests/ui/shadow.rs:25:13 + --> tests/ui/shadow.rs:26:13 | LL | let mut x = &x; | ^ @@ -25,37 +25,37 @@ LL | let x = x; | ^ error: `x` is shadowed by itself in `&mut x` - --> tests/ui/shadow.rs:26:9 + --> tests/ui/shadow.rs:28:9 | LL | let x = &mut x; | ^ | note: previous binding is here - --> tests/ui/shadow.rs:25:9 + --> tests/ui/shadow.rs:26:9 | LL | let mut x = &x; | ^^^^^ error: `x` is shadowed by itself in `*x` - --> tests/ui/shadow.rs:27:9 + --> tests/ui/shadow.rs:30:9 | LL | let x = *x; | ^ | note: previous binding is here - --> tests/ui/shadow.rs:26:9 + --> tests/ui/shadow.rs:28:9 | LL | let x = &mut x; | ^ error: `x` is shadowed - --> tests/ui/shadow.rs:32:9 + --> tests/ui/shadow.rs:36:9 | LL | let x = x.0; | ^ | note: previous binding is here - --> tests/ui/shadow.rs:31:9 + --> tests/ui/shadow.rs:35:9 | LL | let x = ([[0]], ()); | ^ @@ -63,175 +63,103 @@ LL | let x = ([[0]], ()); = help: to override `-D warnings` add `#[allow(clippy::shadow_reuse)]` error: `x` is shadowed - --> tests/ui/shadow.rs:33:9 + --> tests/ui/shadow.rs:38:9 | LL | let x = x[0]; | ^ | note: previous binding is here - --> tests/ui/shadow.rs:32:9 + --> tests/ui/shadow.rs:36:9 | LL | let x = x.0; | ^ error: `x` is shadowed - --> tests/ui/shadow.rs:34:10 + --> tests/ui/shadow.rs:40:10 | LL | let [x] = x; | ^ | note: previous binding is here - --> tests/ui/shadow.rs:33:9 + --> tests/ui/shadow.rs:38:9 | LL | let x = x[0]; | ^ error: `x` is shadowed - --> tests/ui/shadow.rs:35:9 + --> tests/ui/shadow.rs:42:9 | LL | let x = Some(x); | ^ | note: previous binding is here - --> tests/ui/shadow.rs:34:10 + --> tests/ui/shadow.rs:40:10 | LL | let [x] = x; | ^ error: `x` is shadowed - --> tests/ui/shadow.rs:36:9 + --> tests/ui/shadow.rs:44:9 | LL | let x = foo(x); | ^ | note: previous binding is here - --> tests/ui/shadow.rs:35:9 + --> tests/ui/shadow.rs:42:9 | LL | let x = Some(x); | ^ error: `x` is shadowed - --> tests/ui/shadow.rs:37:9 + --> tests/ui/shadow.rs:46:9 | LL | let x = || x; | ^ | note: previous binding is here - --> tests/ui/shadow.rs:36:9 + --> tests/ui/shadow.rs:44:9 | LL | let x = foo(x); | ^ error: `x` is shadowed - --> tests/ui/shadow.rs:38:9 + --> tests/ui/shadow.rs:48:9 | LL | let x = Some(1).map(|_| x)?; | ^ | note: previous binding is here - --> tests/ui/shadow.rs:37:9 + --> tests/ui/shadow.rs:46:9 | LL | let x = || x; | ^ error: `y` is shadowed - --> tests/ui/shadow.rs:40:9 + --> tests/ui/shadow.rs:51:9 | LL | let y = match y { | ^ | note: previous binding is here - --> tests/ui/shadow.rs:39:9 + --> tests/ui/shadow.rs:50:9 | LL | let y = 1; | ^ error: `x` shadows a previous, unrelated binding - --> tests/ui/shadow.rs:55:9 + --> tests/ui/shadow.rs:67:9 | LL | let x = 2; | ^ | note: previous binding is here - --> tests/ui/shadow.rs:54:9 + --> tests/ui/shadow.rs:66:9 | LL | let x = 1; | ^ = note: `-D clippy::shadow-unrelated` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::shadow_unrelated)]` -error: `x` shadows a previous, unrelated binding - --> tests/ui/shadow.rs:60:13 - | -LL | let x = 1; - | ^ - | -note: previous binding is here - --> tests/ui/shadow.rs:59:10 - | -LL | fn f(x: u32) { - | ^ - -error: `x` shadows a previous, unrelated binding - --> tests/ui/shadow.rs:65:14 - | -LL | Some(x) => { - | ^ - | -note: previous binding is here - --> tests/ui/shadow.rs:62:9 - | -LL | let x = 1; - | ^ - -error: `x` shadows a previous, unrelated binding - --> tests/ui/shadow.rs:66:17 - | -LL | let x = 1; - | ^ - | -note: previous binding is here - --> tests/ui/shadow.rs:65:14 - | -LL | Some(x) => { - | ^ - -error: `x` shadows a previous, unrelated binding - --> tests/ui/shadow.rs:70:17 - | -LL | if let Some(x) = Some(1) {} - | ^ - | -note: previous binding is here - --> tests/ui/shadow.rs:62:9 - | -LL | let x = 1; - | ^ - -error: `x` shadows a previous, unrelated binding - --> tests/ui/shadow.rs:71:20 - | -LL | while let Some(x) = Some(1) {} - | ^ - | -note: previous binding is here - --> tests/ui/shadow.rs:62:9 - | -LL | let x = 1; - | ^ - -error: `x` shadows a previous, unrelated binding - --> tests/ui/shadow.rs:72:15 - | -LL | let _ = |[x]: [u32; 1]| { - | ^ - | -note: previous binding is here - --> tests/ui/shadow.rs:62:9 - | -LL | let x = 1; - | ^ - error: `x` shadows a previous, unrelated binding --> tests/ui/shadow.rs:73:13 | @@ -239,79 +167,151 @@ LL | let x = 1; | ^ | note: previous binding is here - --> tests/ui/shadow.rs:72:15 + --> tests/ui/shadow.rs:72:10 + | +LL | fn f(x: u32) { + | ^ + +error: `x` shadows a previous, unrelated binding + --> tests/ui/shadow.rs:79:14 + | +LL | Some(x) => { + | ^ + | +note: previous binding is here + --> tests/ui/shadow.rs:76:9 + | +LL | let x = 1; + | ^ + +error: `x` shadows a previous, unrelated binding + --> tests/ui/shadow.rs:81:17 + | +LL | let x = 1; + | ^ + | +note: previous binding is here + --> tests/ui/shadow.rs:79:14 + | +LL | Some(x) => { + | ^ + +error: `x` shadows a previous, unrelated binding + --> tests/ui/shadow.rs:86:17 + | +LL | if let Some(x) = Some(1) {} + | ^ + | +note: previous binding is here + --> tests/ui/shadow.rs:76:9 + | +LL | let x = 1; + | ^ + +error: `x` shadows a previous, unrelated binding + --> tests/ui/shadow.rs:88:20 + | +LL | while let Some(x) = Some(1) {} + | ^ + | +note: previous binding is here + --> tests/ui/shadow.rs:76:9 + | +LL | let x = 1; + | ^ + +error: `x` shadows a previous, unrelated binding + --> tests/ui/shadow.rs:90:15 + | +LL | let _ = |[x]: [u32; 1]| { + | ^ + | +note: previous binding is here + --> tests/ui/shadow.rs:76:9 + | +LL | let x = 1; + | ^ + +error: `x` shadows a previous, unrelated binding + --> tests/ui/shadow.rs:92:13 + | +LL | let x = 1; + | ^ + | +note: previous binding is here + --> tests/ui/shadow.rs:90:15 | LL | let _ = |[x]: [u32; 1]| { | ^ error: `y` is shadowed - --> tests/ui/shadow.rs:76:17 + --> tests/ui/shadow.rs:96:17 | LL | if let Some(y) = y {} | ^ | note: previous binding is here - --> tests/ui/shadow.rs:75:9 + --> tests/ui/shadow.rs:95:9 | LL | let y = Some(1); | ^ error: `_b` shadows a previous, unrelated binding - --> tests/ui/shadow.rs:112:9 + --> tests/ui/shadow.rs:133:9 | LL | let _b = _a; | ^^ | note: previous binding is here - --> tests/ui/shadow.rs:111:28 + --> tests/ui/shadow.rs:132:28 | LL | pub async fn foo2(_a: i32, _b: i64) { | ^^ error: `x` shadows a previous, unrelated binding - --> tests/ui/shadow.rs:118:21 + --> tests/ui/shadow.rs:140:21 | LL | if let Some(x) = Some(1) { x } else { 1 } | ^ | note: previous binding is here - --> tests/ui/shadow.rs:117:13 + --> tests/ui/shadow.rs:139:13 | LL | let x = 1; | ^ error: `x` is shadowed - --> tests/ui/shadow.rs:128:20 + --> tests/ui/shadow.rs:151:20 | LL | let z = x.map(|x| x + 1); | ^ | note: previous binding is here - --> tests/ui/shadow.rs:125:9 + --> tests/ui/shadow.rs:148:9 | LL | let x = Some(1); | ^ error: `i` is shadowed - --> tests/ui/shadow.rs:132:25 + --> tests/ui/shadow.rs:156:25 | LL | .map(|i| i.map(|i| i - 10)) | ^ | note: previous binding is here - --> tests/ui/shadow.rs:132:15 + --> tests/ui/shadow.rs:156:15 | LL | .map(|i| i.map(|i| i - 10)) | ^ error: `value` is shadowed by itself in `value` - --> tests/ui/shadow.rs:141:22 + --> tests/ui/shadow.rs:166:22 | LL | let Issue13795 { value, .. } = value; | ^^^^^ | note: previous binding is here - --> tests/ui/shadow.rs:140:15 + --> tests/ui/shadow.rs:165:15 | LL | fn issue13795(value: Issue13795) { | ^^^^^ diff --git a/tests/ui/short_circuit_statement.fixed b/tests/ui/short_circuit_statement.fixed index a2bf07ac6052..133d296e259c 100644 --- a/tests/ui/short_circuit_statement.fixed +++ b/tests/ui/short_circuit_statement.fixed @@ -3,15 +3,19 @@ fn main() { if f() { g(); } - //~^ ERROR: boolean short circuit operator in statement + //~^ short_circuit_statement + if !f() { g(); } - //~^ ERROR: boolean short circuit operator in statement + //~^ short_circuit_statement + if 1 != 2 { g(); } - //~^ ERROR: boolean short circuit operator in statement + //~^ short_circuit_statement + if f() || g() { H * 2; } - //~^ ERROR: boolean short circuit operator in statement + //~^ short_circuit_statement + if !(f() || g()) { H * 2; } - //~^ ERROR: boolean short circuit operator in statement + //~^ short_circuit_statement macro_rules! mac { ($f:ident or $g:ident) => { @@ -26,9 +30,10 @@ fn main() { } if mac!() { mac!(); } - //~^ ERROR: boolean short circuit operator in statement + //~^ short_circuit_statement + if !mac!() { mac!(); } - //~^ ERROR: boolean short circuit operator in statement + //~^ short_circuit_statement // Do not lint if the expression comes from a macro mac!(); diff --git a/tests/ui/short_circuit_statement.rs b/tests/ui/short_circuit_statement.rs index bdba546ad8f6..4275ae64fdd6 100644 --- a/tests/ui/short_circuit_statement.rs +++ b/tests/ui/short_circuit_statement.rs @@ -3,15 +3,19 @@ fn main() { f() && g(); - //~^ ERROR: boolean short circuit operator in statement + //~^ short_circuit_statement + f() || g(); - //~^ ERROR: boolean short circuit operator in statement + //~^ short_circuit_statement + 1 == 2 || g(); - //~^ ERROR: boolean short circuit operator in statement + //~^ short_circuit_statement + (f() || g()) && (H * 2); - //~^ ERROR: boolean short circuit operator in statement + //~^ short_circuit_statement + (f() || g()) || (H * 2); - //~^ ERROR: boolean short circuit operator in statement + //~^ short_circuit_statement macro_rules! mac { ($f:ident or $g:ident) => { @@ -26,9 +30,10 @@ fn main() { } mac!() && mac!(); - //~^ ERROR: boolean short circuit operator in statement + //~^ short_circuit_statement + mac!() || mac!(); - //~^ ERROR: boolean short circuit operator in statement + //~^ short_circuit_statement // Do not lint if the expression comes from a macro mac!(); diff --git a/tests/ui/short_circuit_statement.stderr b/tests/ui/short_circuit_statement.stderr index ecf6676405b4..acd28d41a33a 100644 --- a/tests/ui/short_circuit_statement.stderr +++ b/tests/ui/short_circuit_statement.stderr @@ -8,37 +8,37 @@ LL | f() && g(); = help: to override `-D warnings` add `#[allow(clippy::short_circuit_statement)]` error: boolean short circuit operator in statement may be clearer using an explicit test - --> tests/ui/short_circuit_statement.rs:7:5 + --> tests/ui/short_circuit_statement.rs:8:5 | LL | f() || g(); | ^^^^^^^^^^^ help: replace it with: `if !f() { g(); }` error: boolean short circuit operator in statement may be clearer using an explicit test - --> tests/ui/short_circuit_statement.rs:9:5 + --> tests/ui/short_circuit_statement.rs:11:5 | LL | 1 == 2 || g(); | ^^^^^^^^^^^^^^ help: replace it with: `if 1 != 2 { g(); }` error: boolean short circuit operator in statement may be clearer using an explicit test - --> tests/ui/short_circuit_statement.rs:11:5 + --> tests/ui/short_circuit_statement.rs:14:5 | LL | (f() || g()) && (H * 2); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `if f() || g() { H * 2; }` error: boolean short circuit operator in statement may be clearer using an explicit test - --> tests/ui/short_circuit_statement.rs:13:5 + --> tests/ui/short_circuit_statement.rs:17:5 | LL | (f() || g()) || (H * 2); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `if !(f() || g()) { H * 2; }` error: boolean short circuit operator in statement may be clearer using an explicit test - --> tests/ui/short_circuit_statement.rs:28:5 + --> tests/ui/short_circuit_statement.rs:32:5 | LL | mac!() && mac!(); | ^^^^^^^^^^^^^^^^^ help: replace it with: `if mac!() { mac!(); }` error: boolean short circuit operator in statement may be clearer using an explicit test - --> tests/ui/short_circuit_statement.rs:30:5 + --> tests/ui/short_circuit_statement.rs:35:5 | LL | mac!() || mac!(); | ^^^^^^^^^^^^^^^^^ help: replace it with: `if !mac!() { mac!(); }` diff --git a/tests/ui/should_impl_trait/corner_cases.rs b/tests/ui/should_impl_trait/corner_cases.rs index 50999c6f2198..4ec0f02d6645 100644 --- a/tests/ui/should_impl_trait/corner_cases.rs +++ b/tests/ui/should_impl_trait/corner_cases.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::all, clippy::pedantic)] #![allow( clippy::missing_errors_doc, diff --git a/tests/ui/should_impl_trait/method_list_1.rs b/tests/ui/should_impl_trait/method_list_1.rs index 85eed3f06f64..87b3a7d2fa0c 100644 --- a/tests/ui/should_impl_trait/method_list_1.rs +++ b/tests/ui/should_impl_trait/method_list_1.rs @@ -23,77 +23,92 @@ impl T { // trait method list part 1, should lint all // ***************************************** pub fn add(self, other: T) -> T { - //~^ ERROR: method `add` can be confused for the standard trait method `std::ops::Add: + //~^ should_implement_trait + unimplemented!() } pub fn as_mut(&mut self) -> &mut T { - //~^ ERROR: method `as_mut` can be confused for the standard trait method `std::conver + //~^ should_implement_trait + unimplemented!() } pub fn as_ref(&self) -> &T { - //~^ ERROR: method `as_ref` can be confused for the standard trait method `std::conver + //~^ should_implement_trait + unimplemented!() } pub fn bitand(self, rhs: T) -> T { - //~^ ERROR: method `bitand` can be confused for the standard trait method `std::ops::B + //~^ should_implement_trait + unimplemented!() } pub fn bitor(self, rhs: Self) -> Self { - //~^ ERROR: method `bitor` can be confused for the standard trait method `std::ops::Bi + //~^ should_implement_trait + unimplemented!() } pub fn bitxor(self, rhs: Self) -> Self { - //~^ ERROR: method `bitxor` can be confused for the standard trait method `std::ops::B + //~^ should_implement_trait + unimplemented!() } pub fn borrow(&self) -> &str { - //~^ ERROR: method `borrow` can be confused for the standard trait method `std::borrow + //~^ should_implement_trait + unimplemented!() } pub fn borrow_mut(&mut self) -> &mut str { - //~^ ERROR: method `borrow_mut` can be confused for the standard trait method `std::bo + //~^ should_implement_trait + unimplemented!() } pub fn clone(&self) -> Self { - //~^ ERROR: method `clone` can be confused for the standard trait method `std::clone:: + //~^ should_implement_trait + unimplemented!() } pub fn cmp(&self, other: &Self) -> Self { - //~^ ERROR: method `cmp` can be confused for the standard trait method `std::cmp::Ord: + //~^ should_implement_trait + unimplemented!() } pub fn default() -> Self { - //~^ ERROR: method `default` can be confused for the standard trait method `std::defau + //~^ should_implement_trait + unimplemented!() } pub fn deref(&self) -> &Self { - //~^ ERROR: method `deref` can be confused for the standard trait method `std::ops::De + //~^ should_implement_trait + unimplemented!() } pub fn deref_mut(&mut self) -> &mut Self { - //~^ ERROR: method `deref_mut` can be confused for the standard trait method `std::ops + //~^ should_implement_trait + unimplemented!() } pub fn div(self, rhs: Self) -> Self { - //~^ ERROR: method `div` can be confused for the standard trait method `std::ops::Div: + //~^ should_implement_trait + unimplemented!() } pub fn drop(&mut self) { - //~^ ERROR: method `drop` can be confused for the standard trait method `std::ops::Dro + //~^ should_implement_trait + unimplemented!() } // ********** diff --git a/tests/ui/should_impl_trait/method_list_1.stderr b/tests/ui/should_impl_trait/method_list_1.stderr index dfa55ace40f0..8738b61192a3 100644 --- a/tests/ui/should_impl_trait/method_list_1.stderr +++ b/tests/ui/should_impl_trait/method_list_1.stderr @@ -3,6 +3,7 @@ error: method `add` can be confused for the standard trait method `std::ops::Add | LL | / pub fn add(self, other: T) -> T { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -12,10 +13,11 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::should_implement_trait)]` error: method `as_mut` can be confused for the standard trait method `std::convert::AsMut::as_mut` - --> tests/ui/should_impl_trait/method_list_1.rs:30:5 + --> tests/ui/should_impl_trait/method_list_1.rs:31:5 | LL | / pub fn as_mut(&mut self) -> &mut T { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -23,10 +25,11 @@ LL | | } = help: consider implementing the trait `std::convert::AsMut` or choosing a less ambiguous method name error: method `as_ref` can be confused for the standard trait method `std::convert::AsRef::as_ref` - --> tests/ui/should_impl_trait/method_list_1.rs:35:5 + --> tests/ui/should_impl_trait/method_list_1.rs:37:5 | LL | / pub fn as_ref(&self) -> &T { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -34,10 +37,11 @@ LL | | } = help: consider implementing the trait `std::convert::AsRef` or choosing a less ambiguous method name error: method `bitand` can be confused for the standard trait method `std::ops::BitAnd::bitand` - --> tests/ui/should_impl_trait/method_list_1.rs:40:5 + --> tests/ui/should_impl_trait/method_list_1.rs:43:5 | LL | / pub fn bitand(self, rhs: T) -> T { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -45,10 +49,11 @@ LL | | } = help: consider implementing the trait `std::ops::BitAnd` or choosing a less ambiguous method name error: method `bitor` can be confused for the standard trait method `std::ops::BitOr::bitor` - --> tests/ui/should_impl_trait/method_list_1.rs:45:5 + --> tests/ui/should_impl_trait/method_list_1.rs:49:5 | LL | / pub fn bitor(self, rhs: Self) -> Self { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -56,10 +61,11 @@ LL | | } = help: consider implementing the trait `std::ops::BitOr` or choosing a less ambiguous method name error: method `bitxor` can be confused for the standard trait method `std::ops::BitXor::bitxor` - --> tests/ui/should_impl_trait/method_list_1.rs:50:5 + --> tests/ui/should_impl_trait/method_list_1.rs:55:5 | LL | / pub fn bitxor(self, rhs: Self) -> Self { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -67,10 +73,11 @@ LL | | } = help: consider implementing the trait `std::ops::BitXor` or choosing a less ambiguous method name error: method `borrow` can be confused for the standard trait method `std::borrow::Borrow::borrow` - --> tests/ui/should_impl_trait/method_list_1.rs:55:5 + --> tests/ui/should_impl_trait/method_list_1.rs:61:5 | LL | / pub fn borrow(&self) -> &str { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -78,10 +85,11 @@ LL | | } = help: consider implementing the trait `std::borrow::Borrow` or choosing a less ambiguous method name error: method `borrow_mut` can be confused for the standard trait method `std::borrow::BorrowMut::borrow_mut` - --> tests/ui/should_impl_trait/method_list_1.rs:60:5 + --> tests/ui/should_impl_trait/method_list_1.rs:67:5 | LL | / pub fn borrow_mut(&mut self) -> &mut str { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -89,10 +97,11 @@ LL | | } = help: consider implementing the trait `std::borrow::BorrowMut` or choosing a less ambiguous method name error: method `clone` can be confused for the standard trait method `std::clone::Clone::clone` - --> tests/ui/should_impl_trait/method_list_1.rs:65:5 + --> tests/ui/should_impl_trait/method_list_1.rs:73:5 | LL | / pub fn clone(&self) -> Self { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -100,10 +109,11 @@ LL | | } = help: consider implementing the trait `std::clone::Clone` or choosing a less ambiguous method name error: method `cmp` can be confused for the standard trait method `std::cmp::Ord::cmp` - --> tests/ui/should_impl_trait/method_list_1.rs:70:5 + --> tests/ui/should_impl_trait/method_list_1.rs:79:5 | LL | / pub fn cmp(&self, other: &Self) -> Self { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -111,10 +121,11 @@ LL | | } = help: consider implementing the trait `std::cmp::Ord` or choosing a less ambiguous method name error: method `default` can be confused for the standard trait method `std::default::Default::default` - --> tests/ui/should_impl_trait/method_list_1.rs:75:5 + --> tests/ui/should_impl_trait/method_list_1.rs:85:5 | LL | / pub fn default() -> Self { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -122,10 +133,11 @@ LL | | } = help: consider implementing the trait `std::default::Default` or choosing a less ambiguous method name error: method `deref` can be confused for the standard trait method `std::ops::Deref::deref` - --> tests/ui/should_impl_trait/method_list_1.rs:80:5 + --> tests/ui/should_impl_trait/method_list_1.rs:91:5 | LL | / pub fn deref(&self) -> &Self { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -133,10 +145,11 @@ LL | | } = help: consider implementing the trait `std::ops::Deref` or choosing a less ambiguous method name error: method `deref_mut` can be confused for the standard trait method `std::ops::DerefMut::deref_mut` - --> tests/ui/should_impl_trait/method_list_1.rs:85:5 + --> tests/ui/should_impl_trait/method_list_1.rs:97:5 | LL | / pub fn deref_mut(&mut self) -> &mut Self { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -144,10 +157,11 @@ LL | | } = help: consider implementing the trait `std::ops::DerefMut` or choosing a less ambiguous method name error: method `div` can be confused for the standard trait method `std::ops::Div::div` - --> tests/ui/should_impl_trait/method_list_1.rs:90:5 + --> tests/ui/should_impl_trait/method_list_1.rs:103:5 | LL | / pub fn div(self, rhs: Self) -> Self { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -155,10 +169,11 @@ LL | | } = help: consider implementing the trait `std::ops::Div` or choosing a less ambiguous method name error: method `drop` can be confused for the standard trait method `std::ops::Drop::drop` - --> tests/ui/should_impl_trait/method_list_1.rs:95:5 + --> tests/ui/should_impl_trait/method_list_1.rs:109:5 | LL | / pub fn drop(&mut self) { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ diff --git a/tests/ui/should_impl_trait/method_list_2.rs b/tests/ui/should_impl_trait/method_list_2.rs index 33211b32d74b..f0c4d4f15cb6 100644 --- a/tests/ui/should_impl_trait/method_list_2.rs +++ b/tests/ui/should_impl_trait/method_list_2.rs @@ -24,77 +24,92 @@ impl T { // ***************************************** pub fn eq(&self, other: &Self) -> bool { - //~^ ERROR: method `eq` can be confused for the standard trait method `std::cmp::Parti + //~^ should_implement_trait + unimplemented!() } pub fn from_iter(iter: T) -> Self { - //~^ ERROR: method `from_iter` can be confused for the standard trait method `std::ite + //~^ should_implement_trait + unimplemented!() } pub fn from_str(s: &str) -> Result { - //~^ ERROR: method `from_str` can be confused for the standard trait method `std::str: + //~^ should_implement_trait + unimplemented!() } pub fn hash(&self, state: &mut T) { - //~^ ERROR: method `hash` can be confused for the standard trait method `std::hash::Ha + //~^ should_implement_trait + unimplemented!() } pub fn index(&self, index: usize) -> &Self { - //~^ ERROR: method `index` can be confused for the standard trait method `std::ops::In + //~^ should_implement_trait + unimplemented!() } pub fn index_mut(&mut self, index: usize) -> &mut Self { - //~^ ERROR: method `index_mut` can be confused for the standard trait method `std::ops + //~^ should_implement_trait + unimplemented!() } pub fn into_iter(self) -> Self { - //~^ ERROR: method `into_iter` can be confused for the standard trait method `std::ite + //~^ should_implement_trait + unimplemented!() } pub fn mul(self, rhs: Self) -> Self { - //~^ ERROR: method `mul` can be confused for the standard trait method `std::ops::Mul: + //~^ should_implement_trait + unimplemented!() } pub fn neg(self) -> Self { - //~^ ERROR: method `neg` can be confused for the standard trait method `std::ops::Neg: + //~^ should_implement_trait + unimplemented!() } pub fn next(&mut self) -> Option { - //~^ ERROR: method `next` can be confused for the standard trait method `std::iter::It + //~^ should_implement_trait + unimplemented!() } pub fn not(self) -> Self { - //~^ ERROR: method `not` can be confused for the standard trait method `std::ops::Not: + //~^ should_implement_trait + unimplemented!() } pub fn rem(self, rhs: Self) -> Self { - //~^ ERROR: method `rem` can be confused for the standard trait method `std::ops::Rem: + //~^ should_implement_trait + unimplemented!() } pub fn shl(self, rhs: Self) -> Self { - //~^ ERROR: method `shl` can be confused for the standard trait method `std::ops::Shl: + //~^ should_implement_trait + unimplemented!() } pub fn shr(self, rhs: Self) -> Self { - //~^ ERROR: method `shr` can be confused for the standard trait method `std::ops::Shr: + //~^ should_implement_trait + unimplemented!() } pub fn sub(self, rhs: Self) -> Self { - //~^ ERROR: method `sub` can be confused for the standard trait method `std::ops::Sub: + //~^ should_implement_trait + unimplemented!() } // ********** diff --git a/tests/ui/should_impl_trait/method_list_2.stderr b/tests/ui/should_impl_trait/method_list_2.stderr index b1e5bbbfa4c5..85de74337020 100644 --- a/tests/ui/should_impl_trait/method_list_2.stderr +++ b/tests/ui/should_impl_trait/method_list_2.stderr @@ -3,6 +3,7 @@ error: method `eq` can be confused for the standard trait method `std::cmp::Part | LL | / pub fn eq(&self, other: &Self) -> bool { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -12,10 +13,11 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::should_implement_trait)]` error: method `from_iter` can be confused for the standard trait method `std::iter::FromIterator::from_iter` - --> tests/ui/should_impl_trait/method_list_2.rs:31:5 + --> tests/ui/should_impl_trait/method_list_2.rs:32:5 | LL | / pub fn from_iter(iter: T) -> Self { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -23,10 +25,11 @@ LL | | } = help: consider implementing the trait `std::iter::FromIterator` or choosing a less ambiguous method name error: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str` - --> tests/ui/should_impl_trait/method_list_2.rs:36:5 + --> tests/ui/should_impl_trait/method_list_2.rs:38:5 | LL | / pub fn from_str(s: &str) -> Result { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -34,10 +37,11 @@ LL | | } = help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name error: method `hash` can be confused for the standard trait method `std::hash::Hash::hash` - --> tests/ui/should_impl_trait/method_list_2.rs:41:5 + --> tests/ui/should_impl_trait/method_list_2.rs:44:5 | LL | / pub fn hash(&self, state: &mut T) { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -45,10 +49,11 @@ LL | | } = help: consider implementing the trait `std::hash::Hash` or choosing a less ambiguous method name error: method `index` can be confused for the standard trait method `std::ops::Index::index` - --> tests/ui/should_impl_trait/method_list_2.rs:46:5 + --> tests/ui/should_impl_trait/method_list_2.rs:50:5 | LL | / pub fn index(&self, index: usize) -> &Self { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -56,10 +61,11 @@ LL | | } = help: consider implementing the trait `std::ops::Index` or choosing a less ambiguous method name error: method `index_mut` can be confused for the standard trait method `std::ops::IndexMut::index_mut` - --> tests/ui/should_impl_trait/method_list_2.rs:51:5 + --> tests/ui/should_impl_trait/method_list_2.rs:56:5 | LL | / pub fn index_mut(&mut self, index: usize) -> &mut Self { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -67,10 +73,11 @@ LL | | } = help: consider implementing the trait `std::ops::IndexMut` or choosing a less ambiguous method name error: method `into_iter` can be confused for the standard trait method `std::iter::IntoIterator::into_iter` - --> tests/ui/should_impl_trait/method_list_2.rs:56:5 + --> tests/ui/should_impl_trait/method_list_2.rs:62:5 | LL | / pub fn into_iter(self) -> Self { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -78,10 +85,11 @@ LL | | } = help: consider implementing the trait `std::iter::IntoIterator` or choosing a less ambiguous method name error: method `mul` can be confused for the standard trait method `std::ops::Mul::mul` - --> tests/ui/should_impl_trait/method_list_2.rs:61:5 + --> tests/ui/should_impl_trait/method_list_2.rs:68:5 | LL | / pub fn mul(self, rhs: Self) -> Self { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -89,10 +97,11 @@ LL | | } = help: consider implementing the trait `std::ops::Mul` or choosing a less ambiguous method name error: method `neg` can be confused for the standard trait method `std::ops::Neg::neg` - --> tests/ui/should_impl_trait/method_list_2.rs:66:5 + --> tests/ui/should_impl_trait/method_list_2.rs:74:5 | LL | / pub fn neg(self) -> Self { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -100,10 +109,11 @@ LL | | } = help: consider implementing the trait `std::ops::Neg` or choosing a less ambiguous method name error: method `next` can be confused for the standard trait method `std::iter::Iterator::next` - --> tests/ui/should_impl_trait/method_list_2.rs:71:5 + --> tests/ui/should_impl_trait/method_list_2.rs:80:5 | LL | / pub fn next(&mut self) -> Option { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -111,10 +121,11 @@ LL | | } = help: consider implementing the trait `std::iter::Iterator` or choosing a less ambiguous method name error: method `not` can be confused for the standard trait method `std::ops::Not::not` - --> tests/ui/should_impl_trait/method_list_2.rs:76:5 + --> tests/ui/should_impl_trait/method_list_2.rs:86:5 | LL | / pub fn not(self) -> Self { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -122,10 +133,11 @@ LL | | } = help: consider implementing the trait `std::ops::Not` or choosing a less ambiguous method name error: method `rem` can be confused for the standard trait method `std::ops::Rem::rem` - --> tests/ui/should_impl_trait/method_list_2.rs:81:5 + --> tests/ui/should_impl_trait/method_list_2.rs:92:5 | LL | / pub fn rem(self, rhs: Self) -> Self { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -133,10 +145,11 @@ LL | | } = help: consider implementing the trait `std::ops::Rem` or choosing a less ambiguous method name error: method `shl` can be confused for the standard trait method `std::ops::Shl::shl` - --> tests/ui/should_impl_trait/method_list_2.rs:86:5 + --> tests/ui/should_impl_trait/method_list_2.rs:98:5 | LL | / pub fn shl(self, rhs: Self) -> Self { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -144,10 +157,11 @@ LL | | } = help: consider implementing the trait `std::ops::Shl` or choosing a less ambiguous method name error: method `shr` can be confused for the standard trait method `std::ops::Shr::shr` - --> tests/ui/should_impl_trait/method_list_2.rs:91:5 + --> tests/ui/should_impl_trait/method_list_2.rs:104:5 | LL | / pub fn shr(self, rhs: Self) -> Self { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ @@ -155,10 +169,11 @@ LL | | } = help: consider implementing the trait `std::ops::Shr` or choosing a less ambiguous method name error: method `sub` can be confused for the standard trait method `std::ops::Sub::sub` - --> tests/ui/should_impl_trait/method_list_2.rs:96:5 + --> tests/ui/should_impl_trait/method_list_2.rs:110:5 | LL | / pub fn sub(self, rhs: Self) -> Self { LL | | +LL | | LL | | unimplemented!() LL | | } | |_____^ diff --git a/tests/ui/should_panic_without_expect.rs b/tests/ui/should_panic_without_expect.rs index b554fdaf2249..a209f794b105 100644 --- a/tests/ui/should_panic_without_expect.rs +++ b/tests/ui/should_panic_without_expect.rs @@ -3,6 +3,7 @@ #[test] #[should_panic] +//~^ should_panic_without_expect fn no_message() {} #[test] diff --git a/tests/ui/significant_drop_in_scrutinee.rs b/tests/ui/significant_drop_in_scrutinee.rs index 39d550398d70..4f65a06680d6 100644 --- a/tests/ui/significant_drop_in_scrutinee.rs +++ b/tests/ui/significant_drop_in_scrutinee.rs @@ -58,8 +58,7 @@ fn should_trigger_lint_with_mutex_guard_in_match_scrutinee() { // is preserved until the end of the match, but there is no clear indication that this is the // case. match mutex.lock().unwrap().foo() { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee true => { mutex.lock().unwrap().bar(); }, @@ -146,8 +145,7 @@ fn should_trigger_lint_with_wrapped_mutex() { // lifetime is not obvious. Additionally, it is not obvious from looking at the scrutinee that // the temporary contains such a type, making it potentially even more surprising. match s.lock_m().get_the_value() { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee 1 => { println!("Got 1. Is it still 1?"); println!("{}", s.lock_m().get_the_value()); @@ -169,8 +167,7 @@ fn should_trigger_lint_with_double_wrapped_mutex() { // looking at the scrutinee that the temporary contains such a type, making it potentially even // more surprising. match s.lock_m_m().get_the_value() { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee 1 => { println!("Got 1. Is it still 1?"); println!("{}", s.lock_m().get_the_value()); @@ -219,8 +216,7 @@ fn should_trigger_lint_for_vec() { // which have significant drops. The types with significant drops are also non-obvious when // reading the expression in the scrutinee. match counter.temp_increment().len() { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee 2 => { let current_count = counter.i.load(Ordering::Relaxed); println!("Current count {}", current_count); @@ -244,8 +240,7 @@ fn should_trigger_lint_for_tuple_in_scrutinee() { { match (mutex1.lock().unwrap().s.len(), true) { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee (3, _) => { println!("started"); mutex1.lock().unwrap().s.len(); @@ -255,8 +250,7 @@ fn should_trigger_lint_for_tuple_in_scrutinee() { }; match (true, mutex1.lock().unwrap().s.len(), true) { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee (_, 3, _) => { println!("started"); mutex1.lock().unwrap().s.len(); @@ -267,10 +261,8 @@ fn should_trigger_lint_for_tuple_in_scrutinee() { let mutex2 = Mutex::new(StateWithField { s: "two".to_owned() }); match (mutex1.lock().unwrap().s.len(), true, mutex2.lock().unwrap().s.len()) { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until - //~| NOTE: this might lead to deadlocks or other unexpected behavior - //~| ERROR: temporary with significant `Drop` in `match` scrutinee will live until - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee + //~| significant_drop_in_scrutinee (3, _, 3) => { println!("started"); mutex1.lock().unwrap().s.len(); @@ -322,8 +314,7 @@ fn should_trigger_lint_for_accessing_field_in_mutex_in_one_side_of_binary_op() { let mutex = Mutex::new(StateWithField { s: "state".to_owned() }); match mutex.lock().unwrap().s.len() > 1 { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee true => { mutex.lock().unwrap().s.len(); }, @@ -331,8 +322,7 @@ fn should_trigger_lint_for_accessing_field_in_mutex_in_one_side_of_binary_op() { }; match 1 < mutex.lock().unwrap().s.len() { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee true => { mutex.lock().unwrap().s.len(); }, @@ -351,8 +341,8 @@ fn should_trigger_lint_for_accessing_fields_in_mutex_in_both_sides_of_binary_op( }); match mutex1.lock().unwrap().s.len() < mutex2.lock().unwrap().s.len() { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee + //~| significant_drop_in_scrutinee true => { println!( "{} < {}", @@ -364,8 +354,8 @@ fn should_trigger_lint_for_accessing_fields_in_mutex_in_both_sides_of_binary_op( }; match mutex1.lock().unwrap().s.len() >= mutex2.lock().unwrap().s.len() { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee + //~| significant_drop_in_scrutinee true => { println!( "{} >= {}", @@ -401,8 +391,7 @@ fn should_trigger_lint_for_return_from_closure_in_scrutinee() { // Should trigger lint because the temporary with a significant drop is returned from the // closure but not used directly in any match arms, so it has a potentially surprising lifetime. match get_mutex_guard().s.len() > 1 { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee true => { mutex1.lock().unwrap().s.len(); }, @@ -420,8 +409,7 @@ fn should_trigger_lint_for_return_from_match_in_scrutinee() { // significant drop is but not used directly in any match arms, so it has a potentially // surprising lifetime. match match i { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee 100 => mutex1.lock().unwrap(), _ => mutex2.lock().unwrap(), } @@ -448,8 +436,7 @@ fn should_trigger_lint_for_return_from_if_in_scrutinee() { // with a significant drop is but not used directly in any match arms, so it has a potentially // surprising lifetime. match if i > 1 { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee mutex1.lock().unwrap() } else { mutex2.lock().unwrap() @@ -504,8 +491,7 @@ fn should_trigger_lint_for_boxed_mutex_guard() { // Should trigger lint because a temporary Box holding a type with a significant drop in a match // scrutinee may have a potentially surprising lifetime. match s.lock().deref().deref() { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee 0 | 1 => println!("Value was less than 2"), _ => println!("Value is {}", s.lock().deref()), }; @@ -554,32 +540,28 @@ fn should_trigger_lint_in_assign_expr() { let mut i = 100; match mutex.lock().unwrap().i = i { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee _ => { println!("{}", mutex.lock().unwrap().i); }, }; match i = mutex.lock().unwrap().i { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee _ => { println!("{}", mutex.lock().unwrap().i); }, }; match mutex.lock().unwrap().i += 1 { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee _ => { println!("{}", mutex.lock().unwrap().i); }, }; match i += mutex.lock().unwrap().i { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee _ => { println!("{}", mutex.lock().unwrap().i); }, @@ -643,8 +625,7 @@ impl ResultReturner { fn should_trigger_lint_for_non_ref_move_and_clone_suggestion() { let rwlock = RwLock::::new(ResultReturner { s: "1".to_string() }); match rwlock.read().unwrap().to_number() { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee Ok(n) => println!("Converted to number: {}", n), Err(e) => println!("Could not convert {} to number", e), }; @@ -671,8 +652,7 @@ fn should_trigger_lint_without_significant_drop_in_arm() { // is preserved until the end of the match, but there is no clear indication that this is the // case. match mutex.lock().unwrap().foo() { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee true => do_bar(&mutex), false => {}, }; @@ -734,8 +714,7 @@ fn should_not_trigger_for_significant_drop_ref() { } match guard.take().len() { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee 0 => println!("empty"), _ => println!("not empty"), }; @@ -760,8 +739,7 @@ fn should_trigger_lint_if_and_only_if_lifetime_is_irrelevant() { // Should trigger lint even if `copy_old_lifetime()` has a lifetime, as the lifetime of // `&vec` is unrelated to the temporary with significant drop (i.e., the `MutexGuard`). for val in mutex.lock().unwrap().copy_old_lifetime() { - //~^ ERROR: temporary with significant `Drop` in `for` loop condition will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee println!("{}", val); } @@ -800,8 +778,7 @@ fn should_not_trigger_lint_with_explicit_drop() { // Should trigger lint if there is no explicit drop. for val in [mutex.lock().unwrap()[0], 2] { - //~^ ERROR: temporary with significant `Drop` in `for` loop condition will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee println!("{:?}", val); } } @@ -810,8 +787,7 @@ fn should_trigger_lint_in_if_let() { let mutex = Mutex::new(vec![1]); if let Some(val) = mutex.lock().unwrap().first().copied() { - //~^ ERROR: temporary with significant `Drop` in `if let` scrutinee will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee println!("{}", val); } @@ -826,8 +802,7 @@ fn should_trigger_lint_in_while_let() { let mutex = Mutex::new(vec![1]); while let Some(val) = mutex.lock().unwrap().pop() { - //~^ ERROR: temporary with significant `Drop` in `while let` scrutinee will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee println!("{}", val); } } @@ -838,6 +813,7 @@ async fn foo_async(mutex: &Mutex) -> Option> { async fn should_trigger_lint_for_async(mutex: Mutex) -> i32 { match *foo_async(&mutex).await.unwrap() { + //~^ significant_drop_in_scrutinee n if n < 10 => n, _ => 10, } @@ -857,8 +833,7 @@ fn should_trigger_lint_in_match_expr() { // is preserved until the end of the match, but there is no clear indication that this is the // case. let _ = match mutex.lock().unwrap().foo() { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior + //~^ significant_drop_in_scrutinee true => 0, false => 1, }; diff --git a/tests/ui/significant_drop_in_scrutinee.stderr b/tests/ui/significant_drop_in_scrutinee.stderr index f99d862aa6b2..b32b249fd429 100644 --- a/tests/ui/significant_drop_in_scrutinee.stderr +++ b/tests/ui/significant_drop_in_scrutinee.stderr @@ -20,7 +20,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:148:11 + --> tests/ui/significant_drop_in_scrutinee.rs:147:11 | LL | match s.lock_m().get_the_value() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -42,7 +42,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:171:11 + --> tests/ui/significant_drop_in_scrutinee.rs:169:11 | LL | match s.lock_m_m().get_the_value() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:221:11 + --> tests/ui/significant_drop_in_scrutinee.rs:218:11 | LL | match counter.temp_increment().len() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -80,7 +80,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:246:16 + --> tests/ui/significant_drop_in_scrutinee.rs:242:16 | LL | match (mutex1.lock().unwrap().s.len(), true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -99,7 +99,7 @@ LL ~ match (value, true) { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:257:22 + --> tests/ui/significant_drop_in_scrutinee.rs:252:22 | LL | match (true, mutex1.lock().unwrap().s.len(), true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -118,7 +118,7 @@ LL ~ match (true, value, true) { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:269:16 + --> tests/ui/significant_drop_in_scrutinee.rs:263:16 | LL | match (mutex1.lock().unwrap().s.len(), true, mutex2.lock().unwrap().s.len()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -139,7 +139,7 @@ LL ~ match (value, true, mutex2.lock().unwrap().s.len()) { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:269:54 + --> tests/ui/significant_drop_in_scrutinee.rs:263:54 | LL | match (mutex1.lock().unwrap().s.len(), true, mutex2.lock().unwrap().s.len()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -160,7 +160,7 @@ LL ~ match (mutex1.lock().unwrap().s.len(), true, value) { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:324:11 + --> tests/ui/significant_drop_in_scrutinee.rs:316:11 | LL | match mutex.lock().unwrap().s.len() > 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -179,7 +179,7 @@ LL ~ match value > 1 { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:333:15 + --> tests/ui/significant_drop_in_scrutinee.rs:324:15 | LL | match 1 < mutex.lock().unwrap().s.len() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -198,7 +198,7 @@ LL ~ match 1 < value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:353:11 + --> tests/ui/significant_drop_in_scrutinee.rs:343:11 | LL | match mutex1.lock().unwrap().s.len() < mutex2.lock().unwrap().s.len() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -219,7 +219,7 @@ LL ~ match value < mutex2.lock().unwrap().s.len() { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:353:44 + --> tests/ui/significant_drop_in_scrutinee.rs:343:44 | LL | match mutex1.lock().unwrap().s.len() < mutex2.lock().unwrap().s.len() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -240,7 +240,7 @@ LL ~ match mutex1.lock().unwrap().s.len() < value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:366:11 + --> tests/ui/significant_drop_in_scrutinee.rs:356:11 | LL | match mutex1.lock().unwrap().s.len() >= mutex2.lock().unwrap().s.len() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -261,7 +261,7 @@ LL ~ match value >= mutex2.lock().unwrap().s.len() { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:366:45 + --> tests/ui/significant_drop_in_scrutinee.rs:356:45 | LL | match mutex1.lock().unwrap().s.len() >= mutex2.lock().unwrap().s.len() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -282,7 +282,7 @@ LL ~ match mutex1.lock().unwrap().s.len() >= value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:403:11 + --> tests/ui/significant_drop_in_scrutinee.rs:393:11 | LL | match get_mutex_guard().s.len() > 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -301,14 +301,14 @@ LL ~ match value > 1 { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:422:11 + --> tests/ui/significant_drop_in_scrutinee.rs:411:11 | LL | match match i { | ___________^ LL | | -LL | | LL | | 100 => mutex1.lock().unwrap(), -... | +LL | | _ => mutex2.lock().unwrap(), +LL | | } LL | | .s LL | | .len() | |__________^ @@ -324,7 +324,6 @@ help: try moving the temporary above the match | LL ~ let value = match i { LL + -LL + LL + 100 => mutex1.lock().unwrap(), LL + _ => mutex2.lock().unwrap(), LL + } @@ -334,13 +333,13 @@ LL ~ match value | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:450:11 + --> tests/ui/significant_drop_in_scrutinee.rs:438:11 | LL | match if i > 1 { | ___________^ LL | | -LL | | LL | | mutex1.lock().unwrap() +LL | | } else { ... | LL | | .s LL | | .len() @@ -357,7 +356,6 @@ help: try moving the temporary above the match | LL ~ let value = if i > 1 { LL + -LL + LL + mutex1.lock().unwrap() LL + } else { LL + mutex2.lock().unwrap() @@ -368,7 +366,7 @@ LL ~ match value | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:506:11 + --> tests/ui/significant_drop_in_scrutinee.rs:493:11 | LL | match s.lock().deref().deref() { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -386,7 +384,7 @@ LL ~ match (&value) { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:556:11 + --> tests/ui/significant_drop_in_scrutinee.rs:542:11 | LL | match mutex.lock().unwrap().i = i { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -405,7 +403,7 @@ LL ~ match () { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:564:15 + --> tests/ui/significant_drop_in_scrutinee.rs:549:15 | LL | match i = mutex.lock().unwrap().i { | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -424,7 +422,7 @@ LL ~ match i = value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:572:11 + --> tests/ui/significant_drop_in_scrutinee.rs:556:11 | LL | match mutex.lock().unwrap().i += 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -443,7 +441,7 @@ LL ~ match () { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:580:16 + --> tests/ui/significant_drop_in_scrutinee.rs:563:16 | LL | match i += mutex.lock().unwrap().i { | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -462,7 +460,7 @@ LL ~ match i += value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:645:11 + --> tests/ui/significant_drop_in_scrutinee.rs:627:11 | LL | match rwlock.read().unwrap().to_number() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -478,7 +476,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:673:11 + --> tests/ui/significant_drop_in_scrutinee.rs:654:11 | LL | match mutex.lock().unwrap().foo() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -494,7 +492,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:736:11 + --> tests/ui/significant_drop_in_scrutinee.rs:716:11 | LL | match guard.take().len() { | ^^^^^^^^^^^^^^^^^^ @@ -510,7 +508,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `for` loop condition will live until the end of the `for` expression - --> tests/ui/significant_drop_in_scrutinee.rs:762:16 + --> tests/ui/significant_drop_in_scrutinee.rs:741:16 | LL | for val in mutex.lock().unwrap().copy_old_lifetime() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -526,7 +524,7 @@ LL ~ for val in value { | error: temporary with significant `Drop` in `for` loop condition will live until the end of the `for` expression - --> tests/ui/significant_drop_in_scrutinee.rs:802:17 + --> tests/ui/significant_drop_in_scrutinee.rs:780:17 | LL | for val in [mutex.lock().unwrap()[0], 2] { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -542,7 +540,7 @@ LL ~ for val in [value, 2] { | error: temporary with significant `Drop` in `if let` scrutinee will live until the end of the `if let` expression - --> tests/ui/significant_drop_in_scrutinee.rs:812:24 + --> tests/ui/significant_drop_in_scrutinee.rs:789:24 | LL | if let Some(val) = mutex.lock().unwrap().first().copied() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -558,7 +556,7 @@ LL ~ if let Some(val) = value { | error: temporary with significant `Drop` in `while let` scrutinee will live until the end of the `while let` expression - --> tests/ui/significant_drop_in_scrutinee.rs:828:27 + --> tests/ui/significant_drop_in_scrutinee.rs:804:27 | LL | while let Some(val) = mutex.lock().unwrap().pop() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -569,7 +567,7 @@ LL | } = note: this might lead to deadlocks or other unexpected behavior error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:840:11 + --> tests/ui/significant_drop_in_scrutinee.rs:815:11 | LL | match *foo_async(&mutex).await.unwrap() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -585,7 +583,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:859:19 + --> tests/ui/significant_drop_in_scrutinee.rs:835:19 | LL | let _ = match mutex.lock().unwrap().foo() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/significant_drop_tightening.fixed b/tests/ui/significant_drop_tightening.fixed index ed05f6e0c8d3..3d416056226c 100644 --- a/tests/ui/significant_drop_tightening.fixed +++ b/tests/ui/significant_drop_tightening.fixed @@ -8,6 +8,7 @@ pub fn complex_return_triggers_the_lint() -> i32 { } let mutex = Mutex::new(1); let lock = mutex.lock().unwrap(); + //~^ significant_drop_tightening let _ = *lock; let _ = *lock; drop(lock); @@ -103,6 +104,7 @@ pub fn unnecessary_contention_with_multiple_owned_results() { { let mutex = Mutex::new(1i32); let lock = mutex.lock().unwrap(); + //~^ significant_drop_tightening let rslt0 = lock.abs(); let rslt1 = lock.is_positive(); drop(lock); @@ -126,6 +128,7 @@ pub fn unnecessary_contention_with_single_owned_results() { let mutex = Mutex::new(1i32); let rslt0 = mutex.lock().unwrap().abs(); + //~^ significant_drop_tightening do_heavy_computation_that_takes_time(rslt0); } @@ -133,6 +136,7 @@ pub fn unnecessary_contention_with_single_owned_results() { let mutex = Mutex::new(vec![1i32]); mutex.lock().unwrap().clear(); + //~^ significant_drop_tightening do_heavy_computation_that_takes_time(()); } diff --git a/tests/ui/significant_drop_tightening.rs b/tests/ui/significant_drop_tightening.rs index e5f17278f0f6..d9c4ad543593 100644 --- a/tests/ui/significant_drop_tightening.rs +++ b/tests/ui/significant_drop_tightening.rs @@ -8,6 +8,7 @@ pub fn complex_return_triggers_the_lint() -> i32 { } let mutex = Mutex::new(1); let lock = mutex.lock().unwrap(); + //~^ significant_drop_tightening let _ = *lock; let _ = *lock; foo() @@ -102,6 +103,7 @@ pub fn unnecessary_contention_with_multiple_owned_results() { { let mutex = Mutex::new(1i32); let lock = mutex.lock().unwrap(); + //~^ significant_drop_tightening let rslt0 = lock.abs(); let rslt1 = lock.is_positive(); do_heavy_computation_that_takes_time((rslt0, rslt1)); @@ -123,12 +125,14 @@ pub fn unnecessary_contention_with_single_owned_results() { { let mutex = Mutex::new(1i32); let lock = mutex.lock().unwrap(); + //~^ significant_drop_tightening let rslt0 = lock.abs(); do_heavy_computation_that_takes_time(rslt0); } { let mutex = Mutex::new(vec![1i32]); let mut lock = mutex.lock().unwrap(); + //~^ significant_drop_tightening lock.clear(); do_heavy_computation_that_takes_time(()); } diff --git a/tests/ui/significant_drop_tightening.stderr b/tests/ui/significant_drop_tightening.stderr index aef774a3d360..25cd9da73a10 100644 --- a/tests/ui/significant_drop_tightening.stderr +++ b/tests/ui/significant_drop_tightening.stderr @@ -23,14 +23,13 @@ LL + drop(lock); | error: temporary with significant `Drop` can be early dropped - --> tests/ui/significant_drop_tightening.rs:104:13 + --> tests/ui/significant_drop_tightening.rs:105:13 | LL | / { LL | | let mutex = Mutex::new(1i32); LL | | let lock = mutex.lock().unwrap(); | | ^^^^ -LL | | let rslt0 = lock.abs(); -LL | | let rslt1 = lock.is_positive(); +... | LL | | do_heavy_computation_that_takes_time((rslt0, rslt1)); LL | | } | |_____- temporary `lock` is currently being dropped at the end of its contained scope @@ -43,13 +42,13 @@ LL + drop(lock); | error: temporary with significant `Drop` can be early dropped - --> tests/ui/significant_drop_tightening.rs:125:13 + --> tests/ui/significant_drop_tightening.rs:127:13 | LL | / { LL | | let mutex = Mutex::new(1i32); LL | | let lock = mutex.lock().unwrap(); | | ^^^^ -LL | | let rslt0 = lock.abs(); +... | LL | | do_heavy_computation_that_takes_time(rslt0); LL | | } | |_____- temporary `lock` is currently being dropped at the end of its contained scope @@ -59,17 +58,18 @@ help: merge the temporary construction with its single usage | LL ~ LL + let rslt0 = mutex.lock().unwrap().abs(); +LL | LL ~ | error: temporary with significant `Drop` can be early dropped - --> tests/ui/significant_drop_tightening.rs:131:17 + --> tests/ui/significant_drop_tightening.rs:134:17 | LL | / { LL | | let mutex = Mutex::new(vec![1i32]); LL | | let mut lock = mutex.lock().unwrap(); | | ^^^^ -LL | | lock.clear(); +... | LL | | do_heavy_computation_that_takes_time(()); LL | | } | |_____- temporary `lock` is currently being dropped at the end of its contained scope @@ -79,6 +79,7 @@ help: merge the temporary construction with its single usage | LL ~ LL + mutex.lock().unwrap().clear(); +LL | LL ~ | diff --git a/tests/ui/similar_names.rs b/tests/ui/similar_names.rs index f09693344915..69b6ab6220bf 100644 --- a/tests/ui/similar_names.rs +++ b/tests/ui/similar_names.rs @@ -45,12 +45,12 @@ fn main() { let blubx: i32; let bluby: i32; - //~^ ERROR: binding's name is too similar to existing binding + //~^ similar_names let cake: i32; let cakes: i32; let coke: i32; - //~^ ERROR: binding's name is too similar to existing binding + //~^ similar_names match 5 { cheese @ 1 => {}, @@ -69,12 +69,12 @@ fn main() { let xyz1abc: i32; let xyz2abc: i32; let xyzeabc: i32; - //~^ ERROR: binding's name is too similar to existing binding + //~^ similar_names let parser: i32; let parsed: i32; let parsee: i32; - //~^ ERROR: binding's name is too similar to existing binding + //~^ similar_names let setter: i32; let getter: i32; @@ -96,7 +96,7 @@ fn foo() { let Foo { apple: spring, bpple: sprang, - //~^ ERROR: binding's name is too similar to existing binding + //~^ similar_names } = unimplemented!(); } diff --git a/tests/ui/single_call_fn.rs b/tests/ui/single_call_fn.rs index a0597664da55..c1cc4032bec9 100644 --- a/tests/ui/single_call_fn.rs +++ b/tests/ui/single_call_fn.rs @@ -11,7 +11,9 @@ extern crate proc_macros; pub fn f() {} fn i() {} +//~^ single_call_fn fn j() {} +//~^ single_call_fn fn h() { // Linted @@ -32,6 +34,7 @@ fn g() { } fn c() { + //~^ single_call_fn println!("really"); println!("long"); println!("function..."); @@ -42,6 +45,7 @@ fn d() { } fn a() {} +//~^ single_call_fn fn b() { a(); @@ -87,6 +91,7 @@ fn l() { trait Trait { fn default() {} + //~^ single_call_fn fn foo(&self); } extern "C" { @@ -100,6 +105,7 @@ fn m(v: T) { struct S; impl S { fn foo() {} + //~^ single_call_fn } T::default(); S::foo(); diff --git a/tests/ui/single_call_fn.stderr b/tests/ui/single_call_fn.stderr index 14529beac616..8dd90a123852 100644 --- a/tests/ui/single_call_fn.stderr +++ b/tests/ui/single_call_fn.stderr @@ -5,7 +5,7 @@ LL | fn i() {} | ^^^^^^^^^ | note: used here - --> tests/ui/single_call_fn.rs:18:13 + --> tests/ui/single_call_fn.rs:20:13 | LL | let a = i; | ^ @@ -13,21 +13,22 @@ LL | let a = i; = help: to override `-D warnings` add `#[allow(clippy::single_call_fn)]` error: this function is only used once - --> tests/ui/single_call_fn.rs:14:1 + --> tests/ui/single_call_fn.rs:15:1 | LL | fn j() {} | ^^^^^^^^^ | note: used here - --> tests/ui/single_call_fn.rs:25:9 + --> tests/ui/single_call_fn.rs:27:9 | LL | j(); | ^ error: this function is only used once - --> tests/ui/single_call_fn.rs:34:1 + --> tests/ui/single_call_fn.rs:36:1 | LL | / fn c() { +LL | | LL | | println!("really"); LL | | println!("long"); LL | | println!("function..."); @@ -35,43 +36,43 @@ LL | | } | |_^ | note: used here - --> tests/ui/single_call_fn.rs:41:5 + --> tests/ui/single_call_fn.rs:44:5 | LL | c(); | ^ error: this function is only used once - --> tests/ui/single_call_fn.rs:44:1 + --> tests/ui/single_call_fn.rs:47:1 | LL | fn a() {} | ^^^^^^^^^ | note: used here - --> tests/ui/single_call_fn.rs:47:5 + --> tests/ui/single_call_fn.rs:51:5 | LL | a(); | ^ error: this function is only used once - --> tests/ui/single_call_fn.rs:89:5 + --> tests/ui/single_call_fn.rs:93:5 | LL | fn default() {} | ^^^^^^^^^^^^^^^ | note: used here - --> tests/ui/single_call_fn.rs:104:5 + --> tests/ui/single_call_fn.rs:110:5 | LL | T::default(); | ^^^^^^^^^^ error: this function is only used once - --> tests/ui/single_call_fn.rs:102:9 + --> tests/ui/single_call_fn.rs:107:9 | LL | fn foo() {} | ^^^^^^^^^^^ | note: used here - --> tests/ui/single_call_fn.rs:105:5 + --> tests/ui/single_call_fn.rs:111:5 | LL | S::foo(); | ^^^^^^ diff --git a/tests/ui/single_char_add_str.fixed b/tests/ui/single_char_add_str.fixed index aef15252b1bc..b729cf8b2ca1 100644 --- a/tests/ui/single_char_add_str.fixed +++ b/tests/ui/single_char_add_str.fixed @@ -12,44 +12,65 @@ fn main() { let mut string = String::new(); string.push('R'); + //~^ single_char_add_str string.push('\''); + //~^ single_char_add_str string.push('u'); string.push_str("st"); string.push_str(""); string.push('\x52'); + //~^ single_char_add_str string.push('\u{0052}'); + //~^ single_char_add_str string.push('a'); + //~^ single_char_add_str let c_ref = &'a'; string.push(*c_ref); + //~^ single_char_add_str let c = 'a'; string.push(c); + //~^ single_char_add_str string.push('a'); + //~^ single_char_add_str get_string!().push('ö'); + //~^ single_char_add_str // `insert_str` tests let mut string = String::new(); string.insert(0, 'R'); + //~^ single_char_add_str string.insert(1, '\''); + //~^ single_char_add_str string.insert(0, 'u'); string.insert_str(2, "st"); string.insert_str(0, ""); string.insert(0, '\x52'); + //~^ single_char_add_str string.insert(0, '\u{0052}'); + //~^ single_char_add_str let x: usize = 2; string.insert(x, 'a'); + //~^ single_char_add_str const Y: usize = 1; string.insert(Y, 'a'); + //~^ single_char_add_str string.insert(Y, '"'); + //~^ single_char_add_str string.insert(Y, '\''); + //~^ single_char_add_str string.insert(0, *c_ref); + //~^ single_char_add_str string.insert(0, c); + //~^ single_char_add_str string.insert(0, 'a'); + //~^ single_char_add_str get_string!().insert(1, '?'); + //~^ single_char_add_str } diff --git a/tests/ui/single_char_add_str.rs b/tests/ui/single_char_add_str.rs index 7f97250dacd4..a768c47db391 100644 --- a/tests/ui/single_char_add_str.rs +++ b/tests/ui/single_char_add_str.rs @@ -12,44 +12,65 @@ fn main() { let mut string = String::new(); string.push_str("R"); + //~^ single_char_add_str string.push_str("'"); + //~^ single_char_add_str string.push('u'); string.push_str("st"); string.push_str(""); string.push_str("\x52"); + //~^ single_char_add_str string.push_str("\u{0052}"); + //~^ single_char_add_str string.push_str(r##"a"##); + //~^ single_char_add_str let c_ref = &'a'; string.push_str(&c_ref.to_string()); + //~^ single_char_add_str let c = 'a'; string.push_str(&c.to_string()); + //~^ single_char_add_str string.push_str(&'a'.to_string()); + //~^ single_char_add_str get_string!().push_str("ö"); + //~^ single_char_add_str // `insert_str` tests let mut string = String::new(); string.insert_str(0, "R"); + //~^ single_char_add_str string.insert_str(1, "'"); + //~^ single_char_add_str string.insert(0, 'u'); string.insert_str(2, "st"); string.insert_str(0, ""); string.insert_str(0, "\x52"); + //~^ single_char_add_str string.insert_str(0, "\u{0052}"); + //~^ single_char_add_str let x: usize = 2; string.insert_str(x, r##"a"##); + //~^ single_char_add_str const Y: usize = 1; string.insert_str(Y, r##"a"##); + //~^ single_char_add_str string.insert_str(Y, r##"""##); + //~^ single_char_add_str string.insert_str(Y, r##"'"##); + //~^ single_char_add_str string.insert_str(0, &c_ref.to_string()); + //~^ single_char_add_str string.insert_str(0, &c.to_string()); + //~^ single_char_add_str string.insert_str(0, &'a'.to_string()); + //~^ single_char_add_str get_string!().insert_str(1, "?"); + //~^ single_char_add_str } diff --git a/tests/ui/single_char_add_str.stderr b/tests/ui/single_char_add_str.stderr index 7791c67578aa..a1fae93462c9 100644 --- a/tests/ui/single_char_add_str.stderr +++ b/tests/ui/single_char_add_str.stderr @@ -8,121 +8,121 @@ LL | string.push_str("R"); = help: to override `-D warnings` add `#[allow(clippy::single_char_add_str)]` error: calling `push_str()` using a single-character string literal - --> tests/ui/single_char_add_str.rs:15:5 + --> tests/ui/single_char_add_str.rs:16:5 | LL | string.push_str("'"); | ^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('\'')` error: calling `push_str()` using a single-character string literal - --> tests/ui/single_char_add_str.rs:20:5 + --> tests/ui/single_char_add_str.rs:22:5 | LL | string.push_str("\x52"); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('\x52')` error: calling `push_str()` using a single-character string literal - --> tests/ui/single_char_add_str.rs:21:5 + --> tests/ui/single_char_add_str.rs:24:5 | LL | string.push_str("\u{0052}"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('\u{0052}')` error: calling `push_str()` using a single-character string literal - --> tests/ui/single_char_add_str.rs:22:5 + --> tests/ui/single_char_add_str.rs:26:5 | LL | string.push_str(r##"a"##); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('a')` error: calling `push_str()` using a single-character converted to string - --> tests/ui/single_char_add_str.rs:25:5 + --> tests/ui/single_char_add_str.rs:30:5 | LL | string.push_str(&c_ref.to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` without `to_string()`: `string.push(*c_ref)` error: calling `push_str()` using a single-character converted to string - --> tests/ui/single_char_add_str.rs:27:5 + --> tests/ui/single_char_add_str.rs:33:5 | LL | string.push_str(&c.to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` without `to_string()`: `string.push(c)` error: calling `push_str()` using a single-character converted to string - --> tests/ui/single_char_add_str.rs:28:5 + --> tests/ui/single_char_add_str.rs:35:5 | LL | string.push_str(&'a'.to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` without `to_string()`: `string.push('a')` error: calling `push_str()` using a single-character string literal - --> tests/ui/single_char_add_str.rs:30:5 + --> tests/ui/single_char_add_str.rs:38:5 | LL | get_string!().push_str("ö"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `get_string!().push('ö')` error: calling `insert_str()` using a single-character string literal - --> tests/ui/single_char_add_str.rs:35:5 + --> tests/ui/single_char_add_str.rs:44:5 | LL | string.insert_str(0, "R"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(0, 'R')` error: calling `insert_str()` using a single-character string literal - --> tests/ui/single_char_add_str.rs:36:5 + --> tests/ui/single_char_add_str.rs:46:5 | LL | string.insert_str(1, "'"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(1, '\'')` error: calling `insert_str()` using a single-character string literal - --> tests/ui/single_char_add_str.rs:41:5 + --> tests/ui/single_char_add_str.rs:52:5 | LL | string.insert_str(0, "\x52"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(0, '\x52')` error: calling `insert_str()` using a single-character string literal - --> tests/ui/single_char_add_str.rs:42:5 + --> tests/ui/single_char_add_str.rs:54:5 | LL | string.insert_str(0, "\u{0052}"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(0, '\u{0052}')` error: calling `insert_str()` using a single-character string literal - --> tests/ui/single_char_add_str.rs:44:5 + --> tests/ui/single_char_add_str.rs:57:5 | LL | string.insert_str(x, r##"a"##); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(x, 'a')` error: calling `insert_str()` using a single-character string literal - --> tests/ui/single_char_add_str.rs:46:5 + --> tests/ui/single_char_add_str.rs:60:5 | LL | string.insert_str(Y, r##"a"##); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(Y, 'a')` error: calling `insert_str()` using a single-character string literal - --> tests/ui/single_char_add_str.rs:47:5 + --> tests/ui/single_char_add_str.rs:62:5 | LL | string.insert_str(Y, r##"""##); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(Y, '"')` error: calling `insert_str()` using a single-character string literal - --> tests/ui/single_char_add_str.rs:48:5 + --> tests/ui/single_char_add_str.rs:64:5 | LL | string.insert_str(Y, r##"'"##); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(Y, '\'')` error: calling `insert_str()` using a single-character converted to string - --> tests/ui/single_char_add_str.rs:50:5 + --> tests/ui/single_char_add_str.rs:67:5 | LL | string.insert_str(0, &c_ref.to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` without `to_string()`: `string.insert(0, *c_ref)` error: calling `insert_str()` using a single-character converted to string - --> tests/ui/single_char_add_str.rs:51:5 + --> tests/ui/single_char_add_str.rs:69:5 | LL | string.insert_str(0, &c.to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` without `to_string()`: `string.insert(0, c)` error: calling `insert_str()` using a single-character converted to string - --> tests/ui/single_char_add_str.rs:52:5 + --> tests/ui/single_char_add_str.rs:71:5 | LL | string.insert_str(0, &'a'.to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` without `to_string()`: `string.insert(0, 'a')` error: calling `insert_str()` using a single-character string literal - --> tests/ui/single_char_add_str.rs:54:5 + --> tests/ui/single_char_add_str.rs:74:5 | LL | get_string!().insert_str(1, "?"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `get_string!().insert(1, '?')` diff --git a/tests/ui/single_char_lifetime_names.rs b/tests/ui/single_char_lifetime_names.rs index 6731b5b13564..f4dcf46b0e2d 100644 --- a/tests/ui/single_char_lifetime_names.rs +++ b/tests/ui/single_char_lifetime_names.rs @@ -3,8 +3,8 @@ // Lifetimes should only be linted when they're introduced struct DiagnosticCtx<'a, 'b> -//~^ ERROR: single-character lifetime names are likely uninformative -//~| ERROR: single-character lifetime names are likely uninformative +//~^ single_char_lifetime_names +//~| single_char_lifetime_names where 'a: 'b, { @@ -14,8 +14,9 @@ where // Only the lifetimes on the `impl`'s generics should be linted impl<'a, 'b> DiagnosticCtx<'a, 'b> { - //~^ ERROR: single-character lifetime names are likely uninformative - //~| ERROR: single-character lifetime names are likely uninformative + //~^ single_char_lifetime_names + //~| single_char_lifetime_names + fn new(source: &'a str, unit: &'b ()) -> DiagnosticCtx<'a, 'b> { Self { _source: source, @@ -36,7 +37,8 @@ impl<'src, 'unit> DiagnosticCtx<'src, 'unit> { // Only 'a should be linted here fn split_once<'a>(base: &'a str, other: &'_ str) -> (&'a str, Option<&'a str>) { - //~^ ERROR: single-character lifetime names are likely uninformative + //~^ single_char_lifetime_names + base.split_once(other) .map(|(left, right)| (left, Some(right))) .unwrap_or((base, None)) diff --git a/tests/ui/single_char_lifetime_names.stderr b/tests/ui/single_char_lifetime_names.stderr index 005c897b19ba..834b654baa57 100644 --- a/tests/ui/single_char_lifetime_names.stderr +++ b/tests/ui/single_char_lifetime_names.stderr @@ -33,7 +33,7 @@ LL | impl<'a, 'b> DiagnosticCtx<'a, 'b> { = help: use a more informative name error: single-character lifetime names are likely uninformative - --> tests/ui/single_char_lifetime_names.rs:38:15 + --> tests/ui/single_char_lifetime_names.rs:39:15 | LL | fn split_once<'a>(base: &'a str, other: &'_ str) -> (&'a str, Option<&'a str>) { | ^^ diff --git a/tests/ui/single_char_pattern.fixed b/tests/ui/single_char_pattern.fixed index a18d6319f89d..9bf9d6630441 100644 --- a/tests/ui/single_char_pattern.fixed +++ b/tests/ui/single_char_pattern.fixed @@ -5,6 +5,7 @@ use std::collections::HashSet; fn main() { let x = "foo"; x.split('x'); + //~^ single_char_pattern x.split("xx"); x.split('x'); @@ -16,38 +17,67 @@ fn main() { // Can't use this lint for unicode code points which don't fit in a char x.split("❤️"); x.split_inclusive('x'); + //~^ single_char_pattern x.contains('x'); + //~^ single_char_pattern x.starts_with('x'); + //~^ single_char_pattern x.ends_with('x'); + //~^ single_char_pattern x.find('x'); + //~^ single_char_pattern x.rfind('x'); + //~^ single_char_pattern x.rsplit('x'); + //~^ single_char_pattern x.split_terminator('x'); + //~^ single_char_pattern x.rsplit_terminator('x'); + //~^ single_char_pattern x.splitn(2, 'x'); + //~^ single_char_pattern x.rsplitn(2, 'x'); + //~^ single_char_pattern x.split_once('x'); + //~^ single_char_pattern x.rsplit_once('x'); + //~^ single_char_pattern x.matches('x'); + //~^ single_char_pattern x.rmatches('x'); + //~^ single_char_pattern x.match_indices('x'); + //~^ single_char_pattern x.rmatch_indices('x'); + //~^ single_char_pattern x.trim_start_matches('x'); + //~^ single_char_pattern x.trim_end_matches('x'); + //~^ single_char_pattern x.replace('x', "y"); + //~^ single_char_pattern x.replacen('x', "y", 3); + //~^ single_char_pattern // Make sure we escape characters correctly. x.split('\n'); + //~^ single_char_pattern x.split('\''); + //~^ single_char_pattern x.split('\''); + //~^ single_char_pattern // Issue #11973: Don't escape `"` in `'"'` x.split('"'); + //~^ single_char_pattern let h = HashSet::::new(); h.contains("X"); // should not warn x.replace(';', ",").split(','); // issue #2978 + // + //~^^ single_char_pattern x.starts_with('\x03'); // issue #2996 + // + //~^^ single_char_pattern // Issue #3204 const S: &str = "#"; @@ -55,13 +85,20 @@ fn main() { // Raw string x.split('a'); + //~^ single_char_pattern x.split('a'); + //~^ single_char_pattern x.split('a'); + //~^ single_char_pattern x.split('\''); + //~^ single_char_pattern x.split('#'); + //~^ single_char_pattern // Must escape backslash in raw strings when converting to char #8060 x.split('\\'); + //~^ single_char_pattern x.split('\\'); + //~^ single_char_pattern // should not warn, the char versions are actually slower in some cases x.strip_prefix("x"); diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs index b52e6fb2fdfb..0560a848fe9d 100644 --- a/tests/ui/single_char_pattern.rs +++ b/tests/ui/single_char_pattern.rs @@ -5,6 +5,7 @@ use std::collections::HashSet; fn main() { let x = "foo"; x.split("x"); + //~^ single_char_pattern x.split("xx"); x.split('x'); @@ -16,38 +17,67 @@ fn main() { // Can't use this lint for unicode code points which don't fit in a char x.split("❤️"); x.split_inclusive("x"); + //~^ single_char_pattern x.contains("x"); + //~^ single_char_pattern x.starts_with("x"); + //~^ single_char_pattern x.ends_with("x"); + //~^ single_char_pattern x.find("x"); + //~^ single_char_pattern x.rfind("x"); + //~^ single_char_pattern x.rsplit("x"); + //~^ single_char_pattern x.split_terminator("x"); + //~^ single_char_pattern x.rsplit_terminator("x"); + //~^ single_char_pattern x.splitn(2, "x"); + //~^ single_char_pattern x.rsplitn(2, "x"); + //~^ single_char_pattern x.split_once("x"); + //~^ single_char_pattern x.rsplit_once("x"); + //~^ single_char_pattern x.matches("x"); + //~^ single_char_pattern x.rmatches("x"); + //~^ single_char_pattern x.match_indices("x"); + //~^ single_char_pattern x.rmatch_indices("x"); + //~^ single_char_pattern x.trim_start_matches("x"); + //~^ single_char_pattern x.trim_end_matches("x"); + //~^ single_char_pattern x.replace("x", "y"); + //~^ single_char_pattern x.replacen("x", "y", 3); + //~^ single_char_pattern // Make sure we escape characters correctly. x.split("\n"); + //~^ single_char_pattern x.split("'"); + //~^ single_char_pattern x.split("\'"); + //~^ single_char_pattern // Issue #11973: Don't escape `"` in `'"'` x.split("\""); + //~^ single_char_pattern let h = HashSet::::new(); h.contains("X"); // should not warn x.replace(';', ",").split(","); // issue #2978 + // + //~^^ single_char_pattern x.starts_with("\x03"); // issue #2996 + // + //~^^ single_char_pattern // Issue #3204 const S: &str = "#"; @@ -55,13 +85,20 @@ fn main() { // Raw string x.split(r"a"); + //~^ single_char_pattern x.split(r#"a"#); + //~^ single_char_pattern x.split(r###"a"###); + //~^ single_char_pattern x.split(r###"'"###); + //~^ single_char_pattern x.split(r###"#"###); + //~^ single_char_pattern // Must escape backslash in raw strings when converting to char #8060 x.split(r#"\"#); + //~^ single_char_pattern x.split(r"\"); + //~^ single_char_pattern // should not warn, the char versions are actually slower in some cases x.strip_prefix("x"); diff --git a/tests/ui/single_char_pattern.stderr b/tests/ui/single_char_pattern.stderr index b2deed23cbd5..aa4ba28884a8 100644 --- a/tests/ui/single_char_pattern.stderr +++ b/tests/ui/single_char_pattern.stderr @@ -8,205 +8,205 @@ LL | x.split("x"); = help: to override `-D warnings` add `#[allow(clippy::single_char_pattern)]` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:18:23 + --> tests/ui/single_char_pattern.rs:19:23 | LL | x.split_inclusive("x"); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:19:16 + --> tests/ui/single_char_pattern.rs:21:16 | LL | x.contains("x"); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:20:19 + --> tests/ui/single_char_pattern.rs:23:19 | LL | x.starts_with("x"); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:21:17 + --> tests/ui/single_char_pattern.rs:25:17 | LL | x.ends_with("x"); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:22:12 + --> tests/ui/single_char_pattern.rs:27:12 | LL | x.find("x"); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:23:13 + --> tests/ui/single_char_pattern.rs:29:13 | LL | x.rfind("x"); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:24:14 + --> tests/ui/single_char_pattern.rs:31:14 | LL | x.rsplit("x"); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:25:24 + --> tests/ui/single_char_pattern.rs:33:24 | LL | x.split_terminator("x"); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:26:25 + --> tests/ui/single_char_pattern.rs:35:25 | LL | x.rsplit_terminator("x"); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:27:17 + --> tests/ui/single_char_pattern.rs:37:17 | LL | x.splitn(2, "x"); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:28:18 + --> tests/ui/single_char_pattern.rs:39:18 | LL | x.rsplitn(2, "x"); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:29:18 + --> tests/ui/single_char_pattern.rs:41:18 | LL | x.split_once("x"); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:30:19 + --> tests/ui/single_char_pattern.rs:43:19 | LL | x.rsplit_once("x"); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:31:15 + --> tests/ui/single_char_pattern.rs:45:15 | LL | x.matches("x"); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:32:16 + --> tests/ui/single_char_pattern.rs:47:16 | LL | x.rmatches("x"); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:33:21 + --> tests/ui/single_char_pattern.rs:49:21 | LL | x.match_indices("x"); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:34:22 + --> tests/ui/single_char_pattern.rs:51:22 | LL | x.rmatch_indices("x"); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:35:26 + --> tests/ui/single_char_pattern.rs:53:26 | LL | x.trim_start_matches("x"); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:36:24 + --> tests/ui/single_char_pattern.rs:55:24 | LL | x.trim_end_matches("x"); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:37:15 + --> tests/ui/single_char_pattern.rs:57:15 | LL | x.replace("x", "y"); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:38:16 + --> tests/ui/single_char_pattern.rs:59:16 | LL | x.replacen("x", "y", 3); | ^^^ help: consider using a `char`: `'x'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:40:13 + --> tests/ui/single_char_pattern.rs:62:13 | LL | x.split("\n"); | ^^^^ help: consider using a `char`: `'\n'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:41:13 + --> tests/ui/single_char_pattern.rs:64:13 | LL | x.split("'"); | ^^^ help: consider using a `char`: `'\''` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:42:13 + --> tests/ui/single_char_pattern.rs:66:13 | LL | x.split("\'"); | ^^^^ help: consider using a `char`: `'\''` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:44:13 + --> tests/ui/single_char_pattern.rs:69:13 | LL | x.split("\""); | ^^^^ help: consider using a `char`: `'"'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:49:31 + --> tests/ui/single_char_pattern.rs:75:31 | LL | x.replace(';', ",").split(","); // issue #2978 | ^^^ help: consider using a `char`: `','` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:50:19 + --> tests/ui/single_char_pattern.rs:78:19 | LL | x.starts_with("\x03"); // issue #2996 | ^^^^^^ help: consider using a `char`: `'\x03'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:57:13 + --> tests/ui/single_char_pattern.rs:87:13 | LL | x.split(r"a"); | ^^^^ help: consider using a `char`: `'a'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:58:13 + --> tests/ui/single_char_pattern.rs:89:13 | LL | x.split(r#"a"#); | ^^^^^^ help: consider using a `char`: `'a'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:59:13 + --> tests/ui/single_char_pattern.rs:91:13 | LL | x.split(r###"a"###); | ^^^^^^^^^^ help: consider using a `char`: `'a'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:60:13 + --> tests/ui/single_char_pattern.rs:93:13 | LL | x.split(r###"'"###); | ^^^^^^^^^^ help: consider using a `char`: `'\''` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:61:13 + --> tests/ui/single_char_pattern.rs:95:13 | LL | x.split(r###"#"###); | ^^^^^^^^^^ help: consider using a `char`: `'#'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:63:13 + --> tests/ui/single_char_pattern.rs:98:13 | LL | x.split(r#"\"#); | ^^^^^^ help: consider using a `char`: `'\\'` error: single-character string constant used as pattern - --> tests/ui/single_char_pattern.rs:64:13 + --> tests/ui/single_char_pattern.rs:100:13 | LL | x.split(r"\"); | ^^^^ help: consider using a `char`: `'\\'` diff --git a/tests/ui/single_component_path_imports.fixed b/tests/ui/single_component_path_imports.fixed index 3e81bcd5e487..180a55813b19 100644 --- a/tests/ui/single_component_path_imports.fixed +++ b/tests/ui/single_component_path_imports.fixed @@ -3,6 +3,7 @@ use core; +//~^ single_component_path_imports use serde as edres; @@ -29,6 +30,7 @@ fn main() { mod hello_mod { + //~^ single_component_path_imports #[allow(dead_code)] fn hello_mod() {} } diff --git a/tests/ui/single_component_path_imports.rs b/tests/ui/single_component_path_imports.rs index 2d72f122adf2..888c533c534c 100644 --- a/tests/ui/single_component_path_imports.rs +++ b/tests/ui/single_component_path_imports.rs @@ -4,6 +4,7 @@ use core; use regex; +//~^ single_component_path_imports use serde as edres; @@ -30,6 +31,7 @@ fn main() { mod hello_mod { use regex; + //~^ single_component_path_imports #[allow(dead_code)] fn hello_mod() {} } diff --git a/tests/ui/single_component_path_imports.stderr b/tests/ui/single_component_path_imports.stderr index 95d7e4d85b7c..f1c56b14358f 100644 --- a/tests/ui/single_component_path_imports.stderr +++ b/tests/ui/single_component_path_imports.stderr @@ -8,7 +8,7 @@ LL | use regex; = help: to override `-D warnings` add `#[allow(clippy::single_component_path_imports)]` error: this import is redundant - --> tests/ui/single_component_path_imports.rs:32:5 + --> tests/ui/single_component_path_imports.rs:33:5 | LL | use regex; | ^^^^^^^^^^ help: remove it entirely diff --git a/tests/ui/single_component_path_imports_macro.rs b/tests/ui/single_component_path_imports_macro.rs index fda294a61546..f655ea482d1c 100644 --- a/tests/ui/single_component_path_imports_macro.rs +++ b/tests/ui/single_component_path_imports_macro.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::single_component_path_imports)] #![allow(unused_imports)] diff --git a/tests/ui/single_component_path_imports_nested_first.rs b/tests/ui/single_component_path_imports_nested_first.rs index b4a1ce1d6aec..acfda8b3a9c8 100644 --- a/tests/ui/single_component_path_imports_nested_first.rs +++ b/tests/ui/single_component_path_imports_nested_first.rs @@ -2,8 +2,7 @@ #![allow(unused_imports)] //@no-rustfix use regex; -//~^ ERROR: this import is redundant -//~| NOTE: `-D clippy::single-component-path-imports` implied by `-D warnings` +//~^ single_component_path_imports use serde as edres; @@ -15,8 +14,9 @@ fn main() { mod root_nested_use_mod { use {regex, serde}; - //~^ ERROR: this import is redundant - //~| ERROR: this import is redundant + //~^ single_component_path_imports + //~| single_component_path_imports + #[allow(dead_code)] fn root_nested_use_mod() {} } diff --git a/tests/ui/single_component_path_imports_nested_first.stderr b/tests/ui/single_component_path_imports_nested_first.stderr index 8eec877860e7..6dbfd2711b4a 100644 --- a/tests/ui/single_component_path_imports_nested_first.stderr +++ b/tests/ui/single_component_path_imports_nested_first.stderr @@ -8,7 +8,7 @@ LL | use regex; = help: to override `-D warnings` add `#[allow(clippy::single_component_path_imports)]` error: this import is redundant - --> tests/ui/single_component_path_imports_nested_first.rs:17:10 + --> tests/ui/single_component_path_imports_nested_first.rs:16:10 | LL | use {regex, serde}; | ^^^^^ @@ -16,7 +16,7 @@ LL | use {regex, serde}; = help: remove this import error: this import is redundant - --> tests/ui/single_component_path_imports_nested_first.rs:17:17 + --> tests/ui/single_component_path_imports_nested_first.rs:16:17 | LL | use {regex, serde}; | ^^^^^ diff --git a/tests/ui/single_component_path_imports_self_after.rs b/tests/ui/single_component_path_imports_self_after.rs index 5723d480a2e1..a0f2cf690809 100644 --- a/tests/ui/single_component_path_imports_self_after.rs +++ b/tests/ui/single_component_path_imports_self_after.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::single_component_path_imports)] #![allow(unused_imports)] diff --git a/tests/ui/single_component_path_imports_self_before.rs b/tests/ui/single_component_path_imports_self_before.rs index 8a4fbf0dc5b6..b80580da10c3 100644 --- a/tests/ui/single_component_path_imports_self_before.rs +++ b/tests/ui/single_component_path_imports_self_before.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![warn(clippy::single_component_path_imports)] #![allow(unused_imports)] diff --git a/tests/ui/single_element_loop.fixed b/tests/ui/single_element_loop.fixed index 64cbd5e9c905..76c3cf56c11e 100644 --- a/tests/ui/single_element_loop.fixed +++ b/tests/ui/single_element_loop.fixed @@ -7,27 +7,33 @@ fn main() { let item1 = 2; { let item = &item1; + //~^ single_element_loop dbg!(item); } { let item = &item1; + //~^ single_element_loop dbg!(item); } for item in 0..5 { + //~^ single_element_loop dbg!(item); } for item in 0..5 { + //~^ single_element_loop dbg!(item); } for item in 0..5 { + //~^ single_element_loop dbg!(item); } for item in 0..5 { + //~^ single_element_loop dbg!(item); } @@ -48,6 +54,7 @@ fn main() { // should lint (issue #10018) { let _ = 42; + //~^ single_element_loop let _f = |n: u32| { for i in 0..n { if i > 10 { @@ -63,6 +70,7 @@ fn main() { { let (Ok(mut _x) | Err(mut _x)) = res_void; + //~^ single_element_loop let ptr: *const bool = std::ptr::null(); } } diff --git a/tests/ui/single_element_loop.rs b/tests/ui/single_element_loop.rs index 92406f1c1cac..2eb928397b0a 100644 --- a/tests/ui/single_element_loop.rs +++ b/tests/ui/single_element_loop.rs @@ -6,26 +6,32 @@ fn main() { let item1 = 2; for item in &[item1] { + //~^ single_element_loop dbg!(item); } for item in [item1].iter() { + //~^ single_element_loop dbg!(item); } for item in &[0..5] { + //~^ single_element_loop dbg!(item); } for item in [0..5].iter_mut() { + //~^ single_element_loop dbg!(item); } for item in [0..5] { + //~^ single_element_loop dbg!(item); } for item in [0..5].into_iter() { + //~^ single_element_loop dbg!(item); } @@ -45,6 +51,7 @@ fn main() { // should lint (issue #10018) for _ in [42] { + //~^ single_element_loop let _f = |n: u32| { for i in 0..n { if i > 10 { @@ -59,6 +66,7 @@ fn main() { let res_void: Result = Ok(true); for (Ok(mut _x) | Err(mut _x)) in [res_void] { + //~^ single_element_loop let ptr: *const bool = std::ptr::null(); } } diff --git a/tests/ui/single_element_loop.stderr b/tests/ui/single_element_loop.stderr index 73453dd2dfd8..639f8d2d1b98 100644 --- a/tests/ui/single_element_loop.stderr +++ b/tests/ui/single_element_loop.stderr @@ -2,6 +2,7 @@ error: for loop over a single element --> tests/ui/single_element_loop.rs:8:5 | LL | / for item in &[item1] { +LL | | LL | | dbg!(item); LL | | } | |_____^ @@ -12,14 +13,16 @@ help: try | LL ~ { LL + let item = &item1; +LL + LL + dbg!(item); LL + } | error: for loop over a single element - --> tests/ui/single_element_loop.rs:12:5 + --> tests/ui/single_element_loop.rs:13:5 | LL | / for item in [item1].iter() { +LL | | LL | | dbg!(item); LL | | } | |_____^ @@ -28,41 +31,42 @@ help: try | LL ~ { LL + let item = &item1; +LL + LL + dbg!(item); LL + } | error: this loops only once with `item` being `0..5` - --> tests/ui/single_element_loop.rs:16:17 + --> tests/ui/single_element_loop.rs:18:17 | LL | for item in &[0..5] { | ^^^^^^^ help: did you mean to iterate over the range instead?: `0..5` error: this loops only once with `item` being `0..5` - --> tests/ui/single_element_loop.rs:20:17 + --> tests/ui/single_element_loop.rs:23:17 | LL | for item in [0..5].iter_mut() { | ^^^^^^^^^^^^^^^^^ help: did you mean to iterate over the range instead?: `0..5` error: this loops only once with `item` being `0..5` - --> tests/ui/single_element_loop.rs:24:17 + --> tests/ui/single_element_loop.rs:28:17 | LL | for item in [0..5] { | ^^^^^^ help: did you mean to iterate over the range instead?: `0..5` error: this loops only once with `item` being `0..5` - --> tests/ui/single_element_loop.rs:28:17 + --> tests/ui/single_element_loop.rs:33:17 | LL | for item in [0..5].into_iter() { | ^^^^^^^^^^^^^^^^^^ help: did you mean to iterate over the range instead?: `0..5` error: for loop over a single element - --> tests/ui/single_element_loop.rs:47:5 + --> tests/ui/single_element_loop.rs:53:5 | LL | / for _ in [42] { +LL | | LL | | let _f = |n: u32| { LL | | for i in 0..n { -LL | | if i > 10 { ... | LL | | }; LL | | } @@ -72,6 +76,7 @@ help: try | LL ~ { LL + let _ = 42; +LL + LL + let _f = |n: u32| { LL + for i in 0..n { LL + if i > 10 { @@ -84,9 +89,10 @@ LL + } | error: for loop over a single element - --> tests/ui/single_element_loop.rs:61:5 + --> tests/ui/single_element_loop.rs:68:5 | LL | / for (Ok(mut _x) | Err(mut _x)) in [res_void] { +LL | | LL | | let ptr: *const bool = std::ptr::null(); LL | | } | |_____^ @@ -95,6 +101,7 @@ help: try | LL ~ { LL + let (Ok(mut _x) | Err(mut _x)) = res_void; +LL + LL + let ptr: *const bool = std::ptr::null(); LL + } | diff --git a/tests/ui/single_match.fixed b/tests/ui/single_match.fixed index d3d5fd8b35c8..c6ffe93eb7ab 100644 --- a/tests/ui/single_match.fixed +++ b/tests/ui/single_match.fixed @@ -15,6 +15,7 @@ fn single_match() { if let Some(y) = x { println!("{:?}", y); }; + //~^^^^^^ single_match let x = Some(1u8); match x { @@ -27,6 +28,7 @@ fn single_match() { let z = (1u8, 1u8); if let (2..=3, 7..=9) = z { dummy() }; + //~^^^^ single_match // Not linted (pattern guards used) match x { @@ -53,12 +55,15 @@ fn single_match_know_enum() { let y: Result<_, i8> = Ok(1i8); if let Some(y) = x { dummy() }; + //~^^^^ single_match if let Ok(y) = y { dummy() }; + //~^^^^ single_match let c = Cow::Borrowed(""); if let Cow::Borrowed(..) = c { dummy() }; + //~^^^^ single_match let z = Foo::Bar; // no warning @@ -77,6 +82,7 @@ fn single_match_know_enum() { fn if_suggestion() { let x = "test"; if x == "test" { println!() } + //~^^^^ single_match #[derive(PartialEq, Eq)] enum Foo { @@ -87,14 +93,18 @@ fn if_suggestion() { let x = Foo::A; if x == Foo::A { println!() } + //~^^^^ single_match const FOO_C: Foo = Foo::C(0); if x == FOO_C { println!() } + //~^^^^ single_match if x == Foo::A { println!() } + //~^^^^ single_match let x = &x; if x == &Foo::A { println!() } + //~^^^^ single_match enum Bar { A, @@ -109,11 +119,13 @@ fn if_suggestion() { let x = Bar::A; if let Bar::A = x { println!() } + //~^^^^ single_match // issue #7038 struct X; let x = Some(X); if let None = x { println!() }; + //~^^^^ single_match } // See: issue #8282 @@ -133,12 +145,15 @@ fn ranges() { // lint if let (Some(_), _) = x {} + //~^^^^ single_match // lint if let (Some(E::V), _) = x { todo!() } + //~^^^^ single_match // lint if let (.., Some(E::V), _) = (Some(42), Some(E::V), Some(42)) {} + //~^^^^ single_match // Don't lint, see above. match (Some(E::V), Some(E::V), Some(E::V)) { @@ -211,6 +226,7 @@ fn issue_10808(bar: Option) { let r = &v as *const i32; println!("{}", *r); } } + //~^^^^^^^ single_match if let Some(v) = bar { unsafe { @@ -218,6 +234,7 @@ fn issue_10808(bar: Option) { println!("{}", *r); } } + //~^^^^^^^^^^ single_match } mod issue8634 { @@ -289,6 +306,7 @@ fn issue11365() { } if let Ok(Some(A)) = Ok::<_, u32>(Some(A)) { println!() } + //~^^^^ single_match match &Some(A) { Some(A | B | C) => println!(), @@ -301,10 +319,12 @@ fn issue11365() { } if let Some(A | B) = &Some(A) { println!() } + //~^^^^ single_match } fn issue12758(s: &[u8]) { if &s[0..3] == b"foo" { println!() } + //~^^^^ single_match } #[derive(Eq, PartialEq)] @@ -315,20 +335,26 @@ const CONST_I32: i32 = 1; fn irrefutable_match() { println!(); + //~^^^^ single_match println!(); + //~^^^^ single_match let i = 0; { let a = 1; let b = 2; } + //~^^^^^^^ single_match + //~^^^^ single_match + //~^^^^ single_match println!(); + //~^^^^ single_match let mut x = vec![1i8]; diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs index 2f3547c50639..dc758fa4281c 100644 --- a/tests/ui/single_match.rs +++ b/tests/ui/single_match.rs @@ -18,6 +18,7 @@ fn single_match() { }, _ => (), }; + //~^^^^^^ single_match let x = Some(1u8); match x { @@ -33,6 +34,7 @@ fn single_match() { (2..=3, 7..=9) => dummy(), _ => {}, }; + //~^^^^ single_match // Not linted (pattern guards used) match x { @@ -62,11 +64,13 @@ fn single_match_know_enum() { Some(y) => dummy(), None => (), }; + //~^^^^ single_match match y { Ok(y) => dummy(), Err(..) => (), }; + //~^^^^ single_match let c = Cow::Borrowed(""); @@ -74,6 +78,7 @@ fn single_match_know_enum() { Cow::Borrowed(..) => dummy(), Cow::Owned(..) => (), }; + //~^^^^ single_match let z = Foo::Bar; // no warning @@ -95,6 +100,7 @@ fn if_suggestion() { "test" => println!(), _ => (), } + //~^^^^ single_match #[derive(PartialEq, Eq)] enum Foo { @@ -108,23 +114,27 @@ fn if_suggestion() { Foo::A => println!(), _ => (), } + //~^^^^ single_match const FOO_C: Foo = Foo::C(0); match x { FOO_C => println!(), _ => (), } + //~^^^^ single_match match &&x { Foo::A => println!(), _ => (), } + //~^^^^ single_match let x = &x; match &x { Foo::A => println!(), _ => (), } + //~^^^^ single_match enum Bar { A, @@ -142,6 +152,7 @@ fn if_suggestion() { Bar::A => println!(), _ => (), } + //~^^^^ single_match // issue #7038 struct X; @@ -150,6 +161,7 @@ fn if_suggestion() { None => println!(), _ => (), }; + //~^^^^ single_match } // See: issue #8282 @@ -172,18 +184,21 @@ fn ranges() { (Some(_), _) => {}, (None, _) => {}, } + //~^^^^ single_match // lint match x { (Some(E::V), _) => todo!(), (_, _) => {}, } + //~^^^^ single_match // lint match (Some(42), Some(E::V), Some(42)) { (.., Some(E::V), _) => {}, (..) => {}, } + //~^^^^ single_match // Don't lint, see above. match (Some(E::V), Some(E::V), Some(E::V)) { @@ -259,6 +274,7 @@ fn issue_10808(bar: Option) { }, _ => {}, } + //~^^^^^^^ single_match match bar { #[rustfmt::skip] @@ -270,6 +286,7 @@ fn issue_10808(bar: Option) { }, _ => {}, } + //~^^^^^^^^^^ single_match } mod issue8634 { @@ -344,6 +361,7 @@ fn issue11365() { Ok(Some(A)) => println!(), Err(_) | Ok(None | Some(_)) => {}, } + //~^^^^ single_match match &Some(A) { Some(A | B | C) => println!(), @@ -359,6 +377,7 @@ fn issue11365() { Some(A | B) => println!(), None | Some(_) => {}, } + //~^^^^ single_match } fn issue12758(s: &[u8]) { @@ -366,6 +385,7 @@ fn issue12758(s: &[u8]) { b"foo" => println!(), _ => {}, } + //~^^^^ single_match } #[derive(Eq, PartialEq)] @@ -379,11 +399,13 @@ fn irrefutable_match() { DATA => println!(), _ => {}, } + //~^^^^ single_match match CONST_I32 { CONST_I32 => println!(), _ => {}, } + //~^^^^ single_match let i = 0; match i { @@ -393,21 +415,25 @@ fn irrefutable_match() { }, _ => {}, } + //~^^^^^^^ single_match match i { i => {}, _ => {}, } + //~^^^^ single_match match i { i => (), _ => (), } + //~^^^^ single_match match CONST_I32 { CONST_I32 => println!(), _ => {}, } + //~^^^^ single_match let mut x = vec![1i8]; diff --git a/tests/ui/single_match.stderr b/tests/ui/single_match.stderr index 54bbfbac093c..c88296959489 100644 --- a/tests/ui/single_match.stderr +++ b/tests/ui/single_match.stderr @@ -19,7 +19,7 @@ LL ~ }; | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:32:5 + --> tests/ui/single_match.rs:33:5 | LL | / match z { LL | | (2..=3, 7..=9) => dummy(), @@ -28,7 +28,7 @@ LL | | }; | |_____^ help: try: `if let (2..=3, 7..=9) = z { dummy() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:61:5 + --> tests/ui/single_match.rs:63:5 | LL | / match x { LL | | Some(y) => dummy(), @@ -37,7 +37,7 @@ LL | | }; | |_____^ help: try: `if let Some(y) = x { dummy() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:66:5 + --> tests/ui/single_match.rs:69:5 | LL | / match y { LL | | Ok(y) => dummy(), @@ -46,7 +46,7 @@ LL | | }; | |_____^ help: try: `if let Ok(y) = y { dummy() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:73:5 + --> tests/ui/single_match.rs:77:5 | LL | / match c { LL | | Cow::Borrowed(..) => dummy(), @@ -55,7 +55,7 @@ LL | | }; | |_____^ help: try: `if let Cow::Borrowed(..) = c { dummy() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:94:5 + --> tests/ui/single_match.rs:99:5 | LL | / match x { LL | | "test" => println!(), @@ -64,7 +64,7 @@ LL | | } | |_____^ help: try: `if x == "test" { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:107:5 + --> tests/ui/single_match.rs:113:5 | LL | / match x { LL | | Foo::A => println!(), @@ -73,7 +73,7 @@ LL | | } | |_____^ help: try: `if x == Foo::A { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:113:5 + --> tests/ui/single_match.rs:120:5 | LL | / match x { LL | | FOO_C => println!(), @@ -82,7 +82,7 @@ LL | | } | |_____^ help: try: `if x == FOO_C { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:118:5 + --> tests/ui/single_match.rs:126:5 | LL | / match &&x { LL | | Foo::A => println!(), @@ -91,7 +91,7 @@ LL | | } | |_____^ help: try: `if x == Foo::A { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:124:5 + --> tests/ui/single_match.rs:133:5 | LL | / match &x { LL | | Foo::A => println!(), @@ -100,7 +100,7 @@ LL | | } | |_____^ help: try: `if x == &Foo::A { println!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:141:5 + --> tests/ui/single_match.rs:151:5 | LL | / match x { LL | | Bar::A => println!(), @@ -109,7 +109,7 @@ LL | | } | |_____^ help: try: `if let Bar::A = x { println!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:149:5 + --> tests/ui/single_match.rs:160:5 | LL | / match x { LL | | None => println!(), @@ -118,7 +118,7 @@ LL | | }; | |_____^ help: try: `if let None = x { println!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:171:5 + --> tests/ui/single_match.rs:183:5 | LL | / match x { LL | | (Some(_), _) => {}, @@ -127,7 +127,7 @@ LL | | } | |_____^ help: try: `if let (Some(_), _) = x {}` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:177:5 + --> tests/ui/single_match.rs:190:5 | LL | / match x { LL | | (Some(E::V), _) => todo!(), @@ -136,7 +136,7 @@ LL | | } | |_____^ help: try: `if let (Some(E::V), _) = x { todo!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:183:5 + --> tests/ui/single_match.rs:197:5 | LL | / match (Some(42), Some(E::V), Some(42)) { LL | | (.., Some(E::V), _) => {}, @@ -145,7 +145,7 @@ LL | | } | |_____^ help: try: `if let (.., Some(E::V), _) = (Some(42), Some(E::V), Some(42)) {}` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:255:5 + --> tests/ui/single_match.rs:270:5 | LL | / match bar { LL | | Some(v) => unsafe { @@ -165,7 +165,7 @@ LL + } } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:263:5 + --> tests/ui/single_match.rs:279:5 | LL | / match bar { LL | | #[rustfmt::skip] @@ -187,7 +187,7 @@ LL + } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:343:5 + --> tests/ui/single_match.rs:360:5 | LL | / match Ok::<_, u32>(Some(A)) { LL | | Ok(Some(A)) => println!(), @@ -196,7 +196,7 @@ LL | | } | |_____^ help: try: `if let Ok(Some(A)) = Ok::<_, u32>(Some(A)) { println!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:358:5 + --> tests/ui/single_match.rs:376:5 | LL | / match &Some(A) { LL | | Some(A | B) => println!(), @@ -205,7 +205,7 @@ LL | | } | |_____^ help: try: `if let Some(A | B) = &Some(A) { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:365:5 + --> tests/ui/single_match.rs:384:5 | LL | / match &s[0..3] { LL | | b"foo" => println!(), @@ -214,7 +214,7 @@ LL | | } | |_____^ help: try: `if &s[0..3] == b"foo" { println!() }` error: this pattern is irrefutable, `match` is useless - --> tests/ui/single_match.rs:378:5 + --> tests/ui/single_match.rs:398:5 | LL | / match DATA { LL | | DATA => println!(), @@ -223,7 +223,7 @@ LL | | } | |_____^ help: try: `println!();` error: this pattern is irrefutable, `match` is useless - --> tests/ui/single_match.rs:383:5 + --> tests/ui/single_match.rs:404:5 | LL | / match CONST_I32 { LL | | CONST_I32 => println!(), @@ -232,7 +232,7 @@ LL | | } | |_____^ help: try: `println!();` error: this pattern is irrefutable, `match` is useless - --> tests/ui/single_match.rs:389:5 + --> tests/ui/single_match.rs:411:5 | LL | / match i { LL | | i => { @@ -252,7 +252,7 @@ LL + } | error: this pattern is irrefutable, `match` is useless - --> tests/ui/single_match.rs:397:5 + --> tests/ui/single_match.rs:420:5 | LL | / match i { LL | | i => {}, @@ -261,7 +261,7 @@ LL | | } | |_____^ help: `match` expression can be removed error: this pattern is irrefutable, `match` is useless - --> tests/ui/single_match.rs:402:5 + --> tests/ui/single_match.rs:426:5 | LL | / match i { LL | | i => (), @@ -270,7 +270,7 @@ LL | | } | |_____^ help: `match` expression can be removed error: this pattern is irrefutable, `match` is useless - --> tests/ui/single_match.rs:407:5 + --> tests/ui/single_match.rs:432:5 | LL | / match CONST_I32 { LL | | CONST_I32 => println!(), diff --git a/tests/ui/single_match_else.fixed b/tests/ui/single_match_else.fixed index c2ca746976bd..64782bf62a78 100644 --- a/tests/ui/single_match_else.fixed +++ b/tests/ui/single_match_else.fixed @@ -18,6 +18,7 @@ fn unwrap_addr() -> Option<&'static ExprNode> { let x = 5; None }; + //~^^^^^^^ single_match_else // Don't lint with_span!(span match ExprNode::Butterflies { @@ -80,12 +81,14 @@ fn main() { println!("else block"); return } + //~^^^^^^^ single_match_else // lint here if let Some(a) = Some(1) { println!("${:?}", a) } else { println!("else block"); return; } + //~^^^^^^^ single_match_else // lint here use std::convert::Infallible; @@ -93,12 +96,14 @@ fn main() { println!("else block"); return; } + //~^^^^^^^ single_match_else use std::borrow::Cow; if let Cow::Owned(a) = Cow::from("moo") { println!("${:?}", a) } else { println!("else block"); return; } + //~^^^^^^^ single_match_else } fn issue_10808(bar: Option) { @@ -109,6 +114,7 @@ fn issue_10808(bar: Option) { println!("None1"); println!("None2"); } + //~^^^^^^^^^^ single_match_else if let Some(v) = bar { println!("Some"); @@ -118,6 +124,7 @@ fn issue_10808(bar: Option) { let r = &v as *const i32; println!("{}", *r); } } + //~^^^^^^^^^^^ single_match_else if let Some(v) = bar { unsafe { let r = &v as *const i32; @@ -127,6 +134,7 @@ fn issue_10808(bar: Option) { let r = &v as *const i32; println!("{}", *r); } } + //~^^^^^^^^^^^ single_match_else if let Some(v) = bar { unsafe { @@ -137,6 +145,7 @@ fn issue_10808(bar: Option) { println!("None"); println!("None"); } + //~^^^^^^^^^^^^^ single_match_else match bar { Some(v) => { @@ -174,4 +183,5 @@ fn issue_10808(bar: Option) { fn irrefutable_match() -> Option<&'static ExprNode> { Some(&NODE) + //~^^^^^^^ single_match_else } diff --git a/tests/ui/single_match_else.rs b/tests/ui/single_match_else.rs index 2d9e877ee0fe..3f86f4d51803 100644 --- a/tests/ui/single_match_else.rs +++ b/tests/ui/single_match_else.rs @@ -21,6 +21,7 @@ fn unwrap_addr() -> Option<&'static ExprNode> { None }, }; + //~^^^^^^^ single_match_else // Don't lint with_span!(span match ExprNode::Butterflies { @@ -86,6 +87,7 @@ fn main() { return }, } + //~^^^^^^^ single_match_else // lint here match Some(1) { @@ -95,6 +97,7 @@ fn main() { return; }, } + //~^^^^^^^ single_match_else // lint here use std::convert::Infallible; @@ -105,6 +108,7 @@ fn main() { return; } } + //~^^^^^^^ single_match_else use std::borrow::Cow; match Cow::from("moo") { @@ -114,6 +118,7 @@ fn main() { return; } } + //~^^^^^^^ single_match_else } fn issue_10808(bar: Option) { @@ -127,6 +132,7 @@ fn issue_10808(bar: Option) { println!("None2"); }, } + //~^^^^^^^^^^ single_match_else match bar { Some(v) => { @@ -139,6 +145,7 @@ fn issue_10808(bar: Option) { println!("{}", *r); }, } + //~^^^^^^^^^^^ single_match_else match bar { Some(v) => unsafe { @@ -151,6 +158,7 @@ fn issue_10808(bar: Option) { println!("{}", *r); }, } + //~^^^^^^^^^^^ single_match_else match bar { #[rustfmt::skip] @@ -165,6 +173,7 @@ fn issue_10808(bar: Option) { println!("None"); }, } + //~^^^^^^^^^^^^^ single_match_else match bar { Some(v) => { @@ -208,4 +217,5 @@ fn irrefutable_match() -> Option<&'static ExprNode> { None }, } + //~^^^^^^^ single_match_else } diff --git a/tests/ui/single_match_else.stderr b/tests/ui/single_match_else.stderr index aa494520b841..7d4ba5fb75ef 100644 --- a/tests/ui/single_match_else.stderr +++ b/tests/ui/single_match_else.stderr @@ -22,7 +22,7 @@ LL ~ }; | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:82:5 + --> tests/ui/single_match_else.rs:83:5 | LL | / match Some(1) { LL | | Some(a) => println!("${:?}", a), @@ -42,7 +42,7 @@ LL + } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:91:5 + --> tests/ui/single_match_else.rs:93:5 | LL | / match Some(1) { LL | | Some(a) => println!("${:?}", a), @@ -62,7 +62,7 @@ LL + } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:101:5 + --> tests/ui/single_match_else.rs:104:5 | LL | / match Result::::Ok(1) { LL | | Ok(a) => println!("${:?}", a), @@ -81,7 +81,7 @@ LL + } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:110:5 + --> tests/ui/single_match_else.rs:114:5 | LL | / match Cow::from("moo") { LL | | Cow::Owned(a) => println!("${:?}", a), @@ -100,7 +100,7 @@ LL + } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:120:5 + --> tests/ui/single_match_else.rs:125:5 | LL | / match bar { LL | | Some(v) => unsafe { @@ -123,7 +123,7 @@ LL + } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:131:5 + --> tests/ui/single_match_else.rs:137:5 | LL | / match bar { LL | | Some(v) => { @@ -147,7 +147,7 @@ LL + } } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:143:5 + --> tests/ui/single_match_else.rs:150:5 | LL | / match bar { LL | | Some(v) => unsafe { @@ -171,7 +171,7 @@ LL + } } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:155:5 + --> tests/ui/single_match_else.rs:163:5 | LL | / match bar { LL | | #[rustfmt::skip] @@ -196,7 +196,7 @@ LL + } | error: this pattern is irrefutable, `match` is useless - --> tests/ui/single_match_else.rs:204:5 + --> tests/ui/single_match_else.rs:213:5 | LL | / match ExprNode::Butterflies { LL | | ExprNode::Butterflies => Some(&NODE), diff --git a/tests/ui/single_option_map.rs b/tests/ui/single_option_map.rs new file mode 100644 index 000000000000..6126582f4635 --- /dev/null +++ b/tests/ui/single_option_map.rs @@ -0,0 +1,72 @@ +#![warn(clippy::single_option_map)] + +use std::sync::atomic::{AtomicUsize, Ordering}; + +static ATOM: AtomicUsize = AtomicUsize::new(42); +static MAYBE_ATOMIC: Option<&AtomicUsize> = Some(&ATOM); + +fn h(arg: Option) -> Option { + //~^ single_option_map + + arg.map(|x| x * 2) +} + +fn j(arg: Option) -> Option { + //~^ single_option_map + + arg.map(|x| x * 2) +} + +fn mul_args(a: String, b: u64) -> String { + a +} + +fn mul_args_opt(a: Option, b: u64) -> Option { + //~^ single_option_map + + a.map(|val| mul_args(val, b + 1)) +} + +// No lint: no `Option` argument argument +fn maps_static_option() -> Option { + MAYBE_ATOMIC.map(|a| a.load(Ordering::Relaxed)) +} + +// No lint: wrapped by another function +fn manipulate(i: i32) -> i32 { + i + 1 +} +// No lint: wraps another function to do the optional thing +fn manipulate_opt(opt_i: Option) -> Option { + opt_i.map(manipulate) +} + +// No lint: maps other than the receiver +fn map_not_arg(arg: Option) -> Option { + maps_static_option().map(|_| arg.unwrap()) +} + +// No lint: wrapper function with η-expanded form +#[allow(clippy::redundant_closure)] +fn manipulate_opt_explicit(opt_i: Option) -> Option { + opt_i.map(|x| manipulate(x)) +} + +// No lint +fn multi_args(a: String, b: bool, c: u64) -> String { + a +} + +// No lint: contains only map of a closure that binds other arguments +fn multi_args_opt(a: Option, b: bool, c: u64) -> Option { + a.map(|a| multi_args(a, b, c)) +} + +fn main() { + let answer = Some(42u32); + let h_result = h(answer); + + let answer = Some(42u64); + let j_result = j(answer); + maps_static_option(); +} diff --git a/tests/ui/single_option_map.stderr b/tests/ui/single_option_map.stderr new file mode 100644 index 000000000000..11865c5b569f --- /dev/null +++ b/tests/ui/single_option_map.stderr @@ -0,0 +1,40 @@ +error: `fn` that only maps over argument + --> tests/ui/single_option_map.rs:8:1 + | +LL | / fn h(arg: Option) -> Option { +LL | | +LL | | +LL | | arg.map(|x| x * 2) +LL | | } + | |_^ + | + = help: move the `.map` to the caller or to an `_opt` function + = note: `-D clippy::single-option-map` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::single_option_map)]` + +error: `fn` that only maps over argument + --> tests/ui/single_option_map.rs:14:1 + | +LL | / fn j(arg: Option) -> Option { +LL | | +LL | | +LL | | arg.map(|x| x * 2) +LL | | } + | |_^ + | + = help: move the `.map` to the caller or to an `_opt` function + +error: `fn` that only maps over argument + --> tests/ui/single_option_map.rs:24:1 + | +LL | / fn mul_args_opt(a: Option, b: u64) -> Option { +LL | | +LL | | +LL | | a.map(|val| mul_args(val, b + 1)) +LL | | } + | |_^ + | + = help: move the `.map` to the caller or to an `_opt` function + +error: aborting due to 3 previous errors + diff --git a/tests/ui/single_range_in_vec_init.rs b/tests/ui/single_range_in_vec_init.rs index 7887cfc61750..c6c0cb347dc6 100644 --- a/tests/ui/single_range_in_vec_init.rs +++ b/tests/ui/single_range_in_vec_init.rs @@ -24,16 +24,26 @@ fn awa_vec(start: T, end: T) { fn main() { // Lint [0..200]; + //~^ single_range_in_vec_init vec![0..200]; + //~^ single_range_in_vec_init [0u8..200]; + //~^ single_range_in_vec_init [0usize..200]; + //~^ single_range_in_vec_init [0..200usize]; + //~^ single_range_in_vec_init vec![0u8..200]; + //~^ single_range_in_vec_init vec![0usize..200]; + //~^ single_range_in_vec_init vec![0..200usize]; + //~^ single_range_in_vec_init // Only suggest collect [0..200isize]; + //~^ single_range_in_vec_init vec![0..200isize]; + //~^ single_range_in_vec_init // Do not lint [0..200, 0..100]; vec![0..200, 0..100]; diff --git a/tests/ui/single_range_in_vec_init.stderr b/tests/ui/single_range_in_vec_init.stderr index b3bc8dd4aca1..a99127a7606f 100644 --- a/tests/ui/single_range_in_vec_init.stderr +++ b/tests/ui/single_range_in_vec_init.stderr @@ -18,7 +18,7 @@ LL + [0; 200]; | error: a `Vec` of `Range` that is only one element - --> tests/ui/single_range_in_vec_init.rs:27:5 + --> tests/ui/single_range_in_vec_init.rs:28:5 | LL | vec![0..200]; | ^^^^^^^^^^^^ @@ -35,7 +35,7 @@ LL + vec![0; 200]; | error: an array of `Range` that is only one element - --> tests/ui/single_range_in_vec_init.rs:28:5 + --> tests/ui/single_range_in_vec_init.rs:30:5 | LL | [0u8..200]; | ^^^^^^^^^^ @@ -52,7 +52,7 @@ LL + [0u8; 200]; | error: an array of `Range` that is only one element - --> tests/ui/single_range_in_vec_init.rs:29:5 + --> tests/ui/single_range_in_vec_init.rs:32:5 | LL | [0usize..200]; | ^^^^^^^^^^^^^ @@ -69,7 +69,7 @@ LL + [0usize; 200]; | error: an array of `Range` that is only one element - --> tests/ui/single_range_in_vec_init.rs:30:5 + --> tests/ui/single_range_in_vec_init.rs:34:5 | LL | [0..200usize]; | ^^^^^^^^^^^^^ @@ -86,7 +86,7 @@ LL + [0; 200usize]; | error: a `Vec` of `Range` that is only one element - --> tests/ui/single_range_in_vec_init.rs:31:5 + --> tests/ui/single_range_in_vec_init.rs:36:5 | LL | vec![0u8..200]; | ^^^^^^^^^^^^^^ @@ -103,7 +103,7 @@ LL + vec![0u8; 200]; | error: a `Vec` of `Range` that is only one element - --> tests/ui/single_range_in_vec_init.rs:32:5 + --> tests/ui/single_range_in_vec_init.rs:38:5 | LL | vec![0usize..200]; | ^^^^^^^^^^^^^^^^^ @@ -120,7 +120,7 @@ LL + vec![0usize; 200]; | error: a `Vec` of `Range` that is only one element - --> tests/ui/single_range_in_vec_init.rs:33:5 + --> tests/ui/single_range_in_vec_init.rs:40:5 | LL | vec![0..200usize]; | ^^^^^^^^^^^^^^^^^ @@ -137,7 +137,7 @@ LL + vec![0; 200usize]; | error: an array of `Range` that is only one element - --> tests/ui/single_range_in_vec_init.rs:35:5 + --> tests/ui/single_range_in_vec_init.rs:43:5 | LL | [0..200isize]; | ^^^^^^^^^^^^^ @@ -149,7 +149,7 @@ LL + (0..200isize).collect::>(); | error: a `Vec` of `Range` that is only one element - --> tests/ui/single_range_in_vec_init.rs:36:5 + --> tests/ui/single_range_in_vec_init.rs:45:5 | LL | vec![0..200isize]; | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/size_of_in_element_count/expressions.rs b/tests/ui/size_of_in_element_count/expressions.rs index f405ba200acd..3fe4d923441d 100644 --- a/tests/ui/size_of_in_element_count/expressions.rs +++ b/tests/ui/size_of_in_element_count/expressions.rs @@ -13,15 +13,15 @@ fn main() { // Count expression involving multiplication of size_of (Should trigger the lint) unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::() * SIZE) }; - //~^ ERROR: found a count of bytes instead of a count of elements of `T` + //~^ size_of_in_element_count // Count expression involving nested multiplications of size_of (Should trigger the lint) unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), HALF_SIZE * size_of_val(&x[0]) * 2) }; - //~^ ERROR: found a count of bytes instead of a count of elements of `T` + //~^ size_of_in_element_count // Count expression involving divisions of size_of (Should trigger the lint) unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE * size_of::() / 2) }; - //~^ ERROR: found a count of bytes instead of a count of elements of `T` + //~^ size_of_in_element_count // Count expression involving divisions by size_of (Should not trigger the lint) unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / size_of::()) }; @@ -31,7 +31,7 @@ fn main() { // Count expression involving recursive divisions by size_of (Should trigger the lint) unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / (2 / size_of::())) }; - //~^ ERROR: found a count of bytes instead of a count of elements of `T` + //~^ size_of_in_element_count // No size_of calls (Should not trigger the lint) unsafe { copy(x.as_ptr(), y.as_mut_ptr(), SIZE) }; diff --git a/tests/ui/size_of_in_element_count/functions.rs b/tests/ui/size_of_in_element_count/functions.rs index af18136a1dbe..afd12edec1ed 100644 --- a/tests/ui/size_of_in_element_count/functions.rs +++ b/tests/ui/size_of_in_element_count/functions.rs @@ -16,47 +16,59 @@ fn main() { // Count is size_of (Should trigger the lint) unsafe { copy_nonoverlapping::(x.as_ptr(), y.as_mut_ptr(), size_of::()) }; - //~^ ERROR: found a count of bytes instead of a count of elements of `T` + //~^ size_of_in_element_count + unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) }; - //~^ ERROR: found a count of bytes instead of a count of elements of `T` + //~^ size_of_in_element_count unsafe { x.as_ptr().copy_to(y.as_mut_ptr(), size_of::()) }; - //~^ ERROR: found a count of bytes instead of a count of elements of `T` + //~^ size_of_in_element_count + unsafe { x.as_ptr().copy_to_nonoverlapping(y.as_mut_ptr(), size_of::()) }; - //~^ ERROR: found a count of bytes instead of a count of elements of `T` + //~^ size_of_in_element_count + unsafe { y.as_mut_ptr().copy_from(x.as_ptr(), size_of::()) }; - //~^ ERROR: found a count of bytes instead of a count of elements of `T` + //~^ size_of_in_element_count + unsafe { y.as_mut_ptr().copy_from_nonoverlapping(x.as_ptr(), size_of::()) }; - //~^ ERROR: found a count of bytes instead of a count of elements of `T` + //~^ size_of_in_element_count unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of::()) }; - //~^ ERROR: found a count of bytes instead of a count of elements of `T` + //~^ size_of_in_element_count + unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) }; - //~^ ERROR: found a count of bytes instead of a count of elements of `T` + //~^ size_of_in_element_count unsafe { swap_nonoverlapping(y.as_mut_ptr(), x.as_mut_ptr(), size_of::() * SIZE) }; - //~^ ERROR: found a count of bytes instead of a count of elements of `T` + //~^ size_of_in_element_count slice_from_raw_parts_mut(y.as_mut_ptr(), size_of::() * SIZE); - //~^ ERROR: found a count of bytes instead of a count of elements of `T` + //~^ size_of_in_element_count + slice_from_raw_parts(y.as_ptr(), size_of::() * SIZE); - //~^ ERROR: found a count of bytes instead of a count of elements of `T` + //~^ size_of_in_element_count unsafe { from_raw_parts_mut(y.as_mut_ptr(), size_of::() * SIZE) }; - //~^ ERROR: found a count of bytes instead of a count of elements of `T` + //~^ size_of_in_element_count + unsafe { from_raw_parts(y.as_ptr(), size_of::() * SIZE) }; - //~^ ERROR: found a count of bytes instead of a count of elements of `T` + //~^ size_of_in_element_count unsafe { y.as_mut_ptr().sub(size_of::()) }; - //~^ ERROR: found a count of bytes instead of a count of elements of `T` + //~^ size_of_in_element_count + y.as_ptr().wrapping_sub(size_of::()); - //~^ ERROR: found a count of bytes instead of a count of elements of `T` + //~^ size_of_in_element_count + unsafe { y.as_ptr().add(size_of::()) }; - //~^ ERROR: found a count of bytes instead of a count of elements of `T` + //~^ size_of_in_element_count + y.as_mut_ptr().wrapping_add(size_of::()); - //~^ ERROR: found a count of bytes instead of a count of elements of `T` + //~^ size_of_in_element_count + unsafe { y.as_ptr().offset(size_of::() as isize) }; - //~^ ERROR: found a count of bytes instead of a count of elements of `T` + //~^ size_of_in_element_count + y.as_mut_ptr().wrapping_offset(size_of::() as isize); - //~^ ERROR: found a count of bytes instead of a count of elements of `T` + //~^ size_of_in_element_count } diff --git a/tests/ui/size_of_in_element_count/functions.stderr b/tests/ui/size_of_in_element_count/functions.stderr index de54789b2251..f11c33167669 100644 --- a/tests/ui/size_of_in_element_count/functions.stderr +++ b/tests/ui/size_of_in_element_count/functions.stderr @@ -9,7 +9,7 @@ LL | unsafe { copy_nonoverlapping::(x.as_ptr(), y.as_mut_ptr(), size_of = help: to override `-D warnings` add `#[allow(clippy::size_of_in_element_count)]` error: found a count of bytes instead of a count of elements of `T` - --> tests/ui/size_of_in_element_count/functions.rs:20:62 + --> tests/ui/size_of_in_element_count/functions.rs:21:62 | LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) }; | ^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type error: found a count of bytes instead of a count of elements of `T` - --> tests/ui/size_of_in_element_count/functions.rs:23:49 + --> tests/ui/size_of_in_element_count/functions.rs:24:49 | LL | unsafe { x.as_ptr().copy_to(y.as_mut_ptr(), size_of::()) }; | ^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | unsafe { x.as_ptr().copy_to(y.as_mut_ptr(), size_of::()) }; = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type error: found a count of bytes instead of a count of elements of `T` - --> tests/ui/size_of_in_element_count/functions.rs:25:64 + --> tests/ui/size_of_in_element_count/functions.rs:27:64 | LL | unsafe { x.as_ptr().copy_to_nonoverlapping(y.as_mut_ptr(), size_of::()) }; | ^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | unsafe { x.as_ptr().copy_to_nonoverlapping(y.as_mut_ptr(), size_of:: tests/ui/size_of_in_element_count/functions.rs:27:51 + --> tests/ui/size_of_in_element_count/functions.rs:30:51 | LL | unsafe { y.as_mut_ptr().copy_from(x.as_ptr(), size_of::()) }; | ^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | unsafe { y.as_mut_ptr().copy_from(x.as_ptr(), size_of::()) }; = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type error: found a count of bytes instead of a count of elements of `T` - --> tests/ui/size_of_in_element_count/functions.rs:29:66 + --> tests/ui/size_of_in_element_count/functions.rs:33:66 | LL | unsafe { y.as_mut_ptr().copy_from_nonoverlapping(x.as_ptr(), size_of::()) }; | ^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | unsafe { y.as_mut_ptr().copy_from_nonoverlapping(x.as_ptr(), size_of::< = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type error: found a count of bytes instead of a count of elements of `T` - --> tests/ui/size_of_in_element_count/functions.rs:32:47 + --> tests/ui/size_of_in_element_count/functions.rs:36:47 | LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of::()) }; | ^^^^^^^^^^^^^^^^ @@ -57,7 +57,7 @@ LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of::()) }; = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type error: found a count of bytes instead of a count of elements of `T` - --> tests/ui/size_of_in_element_count/functions.rs:34:47 + --> tests/ui/size_of_in_element_count/functions.rs:39:47 | LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) }; | ^^^^^^^^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) }; = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type error: found a count of bytes instead of a count of elements of `T` - --> tests/ui/size_of_in_element_count/functions.rs:37:66 + --> tests/ui/size_of_in_element_count/functions.rs:42:66 | LL | unsafe { swap_nonoverlapping(y.as_mut_ptr(), x.as_mut_ptr(), size_of::() * SIZE) }; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | unsafe { swap_nonoverlapping(y.as_mut_ptr(), x.as_mut_ptr(), size_of::< = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type error: found a count of bytes instead of a count of elements of `T` - --> tests/ui/size_of_in_element_count/functions.rs:40:46 + --> tests/ui/size_of_in_element_count/functions.rs:45:46 | LL | slice_from_raw_parts_mut(y.as_mut_ptr(), size_of::() * SIZE); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -81,7 +81,7 @@ LL | slice_from_raw_parts_mut(y.as_mut_ptr(), size_of::() * SIZE); = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type error: found a count of bytes instead of a count of elements of `T` - --> tests/ui/size_of_in_element_count/functions.rs:42:38 + --> tests/ui/size_of_in_element_count/functions.rs:48:38 | LL | slice_from_raw_parts(y.as_ptr(), size_of::() * SIZE); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -89,7 +89,7 @@ LL | slice_from_raw_parts(y.as_ptr(), size_of::() * SIZE); = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type error: found a count of bytes instead of a count of elements of `T` - --> tests/ui/size_of_in_element_count/functions.rs:45:49 + --> tests/ui/size_of_in_element_count/functions.rs:51:49 | LL | unsafe { from_raw_parts_mut(y.as_mut_ptr(), size_of::() * SIZE) }; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL | unsafe { from_raw_parts_mut(y.as_mut_ptr(), size_of::() * SIZE) }; = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type error: found a count of bytes instead of a count of elements of `T` - --> tests/ui/size_of_in_element_count/functions.rs:47:41 + --> tests/ui/size_of_in_element_count/functions.rs:54:41 | LL | unsafe { from_raw_parts(y.as_ptr(), size_of::() * SIZE) }; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -105,7 +105,7 @@ LL | unsafe { from_raw_parts(y.as_ptr(), size_of::() * SIZE) }; = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type error: found a count of bytes instead of a count of elements of `T` - --> tests/ui/size_of_in_element_count/functions.rs:50:33 + --> tests/ui/size_of_in_element_count/functions.rs:57:33 | LL | unsafe { y.as_mut_ptr().sub(size_of::()) }; | ^^^^^^^^^^^^^^^^ @@ -113,7 +113,7 @@ LL | unsafe { y.as_mut_ptr().sub(size_of::()) }; = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type error: found a count of bytes instead of a count of elements of `T` - --> tests/ui/size_of_in_element_count/functions.rs:52:29 + --> tests/ui/size_of_in_element_count/functions.rs:60:29 | LL | y.as_ptr().wrapping_sub(size_of::()); | ^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL | y.as_ptr().wrapping_sub(size_of::()); = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type error: found a count of bytes instead of a count of elements of `T` - --> tests/ui/size_of_in_element_count/functions.rs:54:29 + --> tests/ui/size_of_in_element_count/functions.rs:63:29 | LL | unsafe { y.as_ptr().add(size_of::()) }; | ^^^^^^^^^^^^^^^^ @@ -129,7 +129,7 @@ LL | unsafe { y.as_ptr().add(size_of::()) }; = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type error: found a count of bytes instead of a count of elements of `T` - --> tests/ui/size_of_in_element_count/functions.rs:56:33 + --> tests/ui/size_of_in_element_count/functions.rs:66:33 | LL | y.as_mut_ptr().wrapping_add(size_of::()); | ^^^^^^^^^^^^^^^^ @@ -137,7 +137,7 @@ LL | y.as_mut_ptr().wrapping_add(size_of::()); = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type error: found a count of bytes instead of a count of elements of `T` - --> tests/ui/size_of_in_element_count/functions.rs:58:32 + --> tests/ui/size_of_in_element_count/functions.rs:69:32 | LL | unsafe { y.as_ptr().offset(size_of::() as isize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -145,7 +145,7 @@ LL | unsafe { y.as_ptr().offset(size_of::() as isize) }; = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type error: found a count of bytes instead of a count of elements of `T` - --> tests/ui/size_of_in_element_count/functions.rs:60:36 + --> tests/ui/size_of_in_element_count/functions.rs:72:36 | LL | y.as_mut_ptr().wrapping_offset(size_of::() as isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/size_of_ref.rs b/tests/ui/size_of_ref.rs index 670c6c080eca..9a6a9419f681 100644 --- a/tests/ui/size_of_ref.rs +++ b/tests/ui/size_of_ref.rs @@ -11,9 +11,10 @@ fn main() { size_of_val(y); // no lint size_of_val(&&x); - //~^ ERROR: argument to `std::mem::size_of_val()` is a reference to a reference + //~^ size_of_ref + size_of_val(&y); - //~^ ERROR: argument to `std::mem::size_of_val()` is a reference to a reference + //~^ size_of_ref } struct S { @@ -25,6 +26,6 @@ impl S { /// Get size of object including `self`, in bytes. pub fn size(&self) -> usize { std::mem::size_of_val(&self) + (std::mem::size_of::() * self.data.capacity()) - //~^ ERROR: argument to `std::mem::size_of_val()` is a reference to a reference + //~^ size_of_ref } } diff --git a/tests/ui/size_of_ref.stderr b/tests/ui/size_of_ref.stderr index bb8f08de531c..6ac0b0dd2f06 100644 --- a/tests/ui/size_of_ref.stderr +++ b/tests/ui/size_of_ref.stderr @@ -9,7 +9,7 @@ LL | size_of_val(&&x); = help: to override `-D warnings` add `#[allow(clippy::size_of_ref)]` error: argument to `std::mem::size_of_val()` is a reference to a reference - --> tests/ui/size_of_ref.rs:15:5 + --> tests/ui/size_of_ref.rs:16:5 | LL | size_of_val(&y); | ^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | size_of_val(&y); = help: dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the size of the reference-type error: argument to `std::mem::size_of_val()` is a reference to a reference - --> tests/ui/size_of_ref.rs:27:9 + --> tests/ui/size_of_ref.rs:28:9 | LL | std::mem::size_of_val(&self) + (std::mem::size_of::() * self.data.capacity()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/skip_while_next.rs b/tests/ui/skip_while_next.rs index 8e4cd82cec30..96f4604ad42d 100644 --- a/tests/ui/skip_while_next.rs +++ b/tests/ui/skip_while_next.rs @@ -12,9 +12,11 @@ fn skip_while_next() { // Single-line case. let _ = v.iter().skip_while(|&x| *x < 0).next(); + //~^ skip_while_next // Multi-line case. let _ = v.iter().skip_while(|&x| { + //~^ skip_while_next *x < 0 } ).next(); diff --git a/tests/ui/skip_while_next.stderr b/tests/ui/skip_while_next.stderr index 2c1b9eeba3b6..5db8b4bcb522 100644 --- a/tests/ui/skip_while_next.stderr +++ b/tests/ui/skip_while_next.stderr @@ -9,10 +9,11 @@ LL | let _ = v.iter().skip_while(|&x| *x < 0).next(); = help: to override `-D warnings` add `#[allow(clippy::skip_while_next)]` error: called `skip_while(
{}
{table}
", invocation.cmdline - )?; + ); } eprintln!("Recorded {} bootstrap invocation(s)", metrics.invocations.len()); - - Ok(()) } -fn record_test_suites(metrics: &JsonRoot, file: &mut File) -> anyhow::Result<()> { +fn record_test_suites(metrics: &JsonRoot) { let suites = get_test_suites(&metrics); if !suites.is_empty() { let aggregated = aggregate_test_suites(&suites); let table = render_table(aggregated); - writeln!(file, "\n# Test results\n")?; - writeln!(file, "{table}")?; + println!("\n# Test results\n"); + println!("{table}"); } else { eprintln!("No test suites found in metrics"); } - - Ok(()) } fn render_table(suites: BTreeMap) -> String { From e757deab233aea31612c593773f242b6b9c6e386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 15 Mar 2025 11:16:09 +0100 Subject: [PATCH 202/745] Refactor metrics and analysis in citool to distinguish them better --- .../src/{merge_report.rs => analysis.rs} | 208 ++++++++++-------- src/ci/citool/src/main.rs | 17 +- src/ci/citool/src/metrics.rs | 190 ++++++---------- src/ci/citool/src/utils.rs | 4 + 4 files changed, 198 insertions(+), 221 deletions(-) rename src/ci/citool/src/{merge_report.rs => analysis.rs} (62%) diff --git a/src/ci/citool/src/merge_report.rs b/src/ci/citool/src/analysis.rs similarity index 62% rename from src/ci/citool/src/merge_report.rs rename to src/ci/citool/src/analysis.rs index 62daa2e68530..87c5708fa602 100644 --- a/src/ci/citool/src/merge_report.rs +++ b/src/ci/citool/src/analysis.rs @@ -1,97 +1,135 @@ -use std::collections::{HashMap, HashSet}; -use std::path::PathBuf; +use crate::metrics; +use crate::metrics::{JobMetrics, JobName, get_test_suites}; +use crate::utils::pluralize; +use build_helper::metrics::{ + BuildStep, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, format_build_steps, +}; +use std::collections::{BTreeMap, HashMap, HashSet}; -use anyhow::Context; -use build_helper::metrics::{JsonRoot, TestOutcome, TestSuiteMetadata}; - -use crate::jobs::JobDatabase; -use crate::metrics::get_test_suites; - -type Sha = String; -type JobName = String; - -/// Computes a post merge CI analysis report between the `parent` and `current` commits. -pub fn post_merge_report(job_db: JobDatabase, parent: Sha, current: Sha) -> anyhow::Result<()> { - let jobs = download_all_metrics(&job_db, &parent, ¤t)?; - let aggregated_test_diffs = aggregate_test_diffs(&jobs)?; - - println!("Comparing {parent} (base) -> {current} (this PR)\n"); - report_test_diffs(aggregated_test_diffs); - - Ok(()) +pub fn output_bootstrap_stats(metrics: &JsonRoot) { + if !metrics.invocations.is_empty() { + println!("# Bootstrap steps"); + record_bootstrap_step_durations(&metrics); + record_test_suites(&metrics); + } } -struct JobMetrics { - parent: Option, - current: JsonRoot, -} - -/// Download before/after metrics for all auto jobs in the job database. -fn download_all_metrics( - job_db: &JobDatabase, - parent: &str, - current: &str, -) -> anyhow::Result> { - let mut jobs = HashMap::default(); - - for job in &job_db.auto_jobs { - eprintln!("Downloading metrics of job {}", job.name); - let metrics_parent = match download_job_metrics(&job.name, parent) { - Ok(metrics) => Some(metrics), - Err(error) => { - eprintln!( - r#"Did not find metrics for job `{}` at `{}`: {error:?}. -Maybe it was newly added?"#, - job.name, parent - ); - None - } - }; - let metrics_current = download_job_metrics(&job.name, current)?; - jobs.insert( - job.name.clone(), - JobMetrics { parent: metrics_parent, current: metrics_current }, +fn record_bootstrap_step_durations(metrics: &JsonRoot) { + for invocation in &metrics.invocations { + let step = BuildStep::from_invocation(invocation); + let table = format_build_steps(&step); + eprintln!("Step `{}`\n{table}\n", invocation.cmdline); + println!( + r"
+{} +
{table}
+
+", + invocation.cmdline ); } - Ok(jobs) + eprintln!("Recorded {} bootstrap invocation(s)", metrics.invocations.len()); } -/// Downloads job metrics of the given job for the given commit. -/// Caches the result on the local disk. -fn download_job_metrics(job_name: &str, sha: &str) -> anyhow::Result { - let cache_path = PathBuf::from(".citool-cache").join(sha).join(job_name).join("metrics.json"); - if let Some(cache_entry) = - std::fs::read_to_string(&cache_path).ok().and_then(|data| serde_json::from_str(&data).ok()) - { - return Ok(cache_entry); +fn record_test_suites(metrics: &JsonRoot) { + let suites = metrics::get_test_suites(&metrics); + + if !suites.is_empty() { + let aggregated = aggregate_test_suites(&suites); + let table = render_table(aggregated); + println!("\n# Test results\n"); + println!("{table}"); + } else { + eprintln!("No test suites found in metrics"); + } +} + +fn render_table(suites: BTreeMap) -> String { + use std::fmt::Write; + + let mut table = "| Test suite | Passed ✅ | Ignored 🚫 | Failed ❌ |\n".to_string(); + writeln!(table, "|:------|------:|------:|------:|").unwrap(); + + fn compute_pct(value: f64, total: f64) -> f64 { + if total == 0.0 { 0.0 } else { value / total } } - let url = get_metrics_url(job_name, sha); - let mut response = ureq::get(&url).call()?; - if !response.status().is_success() { - return Err(anyhow::anyhow!( - "Cannot fetch metrics from {url}: {}\n{}", - response.status(), - response.body_mut().read_to_string()? - )); - } - let data: JsonRoot = response - .body_mut() - .read_json() - .with_context(|| anyhow::anyhow!("cannot deserialize metrics from {url}"))?; + fn write_row( + buffer: &mut String, + name: &str, + record: &TestSuiteRecord, + surround: &str, + ) -> std::fmt::Result { + let TestSuiteRecord { passed, ignored, failed } = record; + let total = (record.passed + record.ignored + record.failed) as f64; + let passed_pct = compute_pct(*passed as f64, total) * 100.0; + let ignored_pct = compute_pct(*ignored as f64, total) * 100.0; + let failed_pct = compute_pct(*failed as f64, total) * 100.0; - // Ignore errors if cache cannot be created - if std::fs::create_dir_all(cache_path.parent().unwrap()).is_ok() { - if let Ok(serialized) = serde_json::to_string(&data) { - let _ = std::fs::write(&cache_path, &serialized); + write!(buffer, "| {surround}{name}{surround} |")?; + write!(buffer, " {surround}{passed} ({passed_pct:.0}%){surround} |")?; + write!(buffer, " {surround}{ignored} ({ignored_pct:.0}%){surround} |")?; + writeln!(buffer, " {surround}{failed} ({failed_pct:.0}%){surround} |")?; + + Ok(()) + } + + let mut total = TestSuiteRecord::default(); + for (name, record) in suites { + write_row(&mut table, &name, &record, "").unwrap(); + total.passed += record.passed; + total.ignored += record.ignored; + total.failed += record.failed; + } + write_row(&mut table, "Total", &total, "**").unwrap(); + table +} + +/// Computes a post merge CI analysis report of test differences +/// between the `parent` and `current` commits. +pub fn output_test_diffs(job_metrics: HashMap) { + let aggregated_test_diffs = aggregate_test_diffs(&job_metrics); + report_test_diffs(aggregated_test_diffs); +} + +#[derive(Default)] +struct TestSuiteRecord { + passed: u64, + ignored: u64, + failed: u64, +} + +fn test_metadata_name(metadata: &TestSuiteMetadata) -> String { + match metadata { + TestSuiteMetadata::CargoPackage { crates, stage, .. } => { + format!("{} (stage {stage})", crates.join(", ")) + } + TestSuiteMetadata::Compiletest { suite, stage, .. } => { + format!("{suite} (stage {stage})") } } - Ok(data) } -fn get_metrics_url(job_name: &str, sha: &str) -> String { - let suffix = if job_name.ends_with("-alt") { "-alt" } else { "" }; - format!("https://ci-artifacts.rust-lang.org/rustc-builds{suffix}/{sha}/metrics-{job_name}.json") +fn aggregate_test_suites(suites: &[&TestSuite]) -> BTreeMap { + let mut records: BTreeMap = BTreeMap::new(); + for suite in suites { + let name = test_metadata_name(&suite.metadata); + let record = records.entry(name).or_default(); + for test in &suite.tests { + match test.outcome { + TestOutcome::Passed => { + record.passed += 1; + } + TestOutcome::Failed => { + record.failed += 1; + } + TestOutcome::Ignored { .. } => { + record.ignored += 1; + } + } + } + } + records } /// Represents a difference in the outcome of tests between a base and a current commit. @@ -101,9 +139,7 @@ struct AggregatedTestDiffs { diffs: HashMap>, } -fn aggregate_test_diffs( - jobs: &HashMap, -) -> anyhow::Result { +fn aggregate_test_diffs(jobs: &HashMap) -> AggregatedTestDiffs { let mut diffs: HashMap> = HashMap::new(); // Aggregate test suites @@ -117,7 +153,7 @@ fn aggregate_test_diffs( } } - Ok(AggregatedTestDiffs { diffs }) + AggregatedTestDiffs { diffs } } #[derive(Eq, PartialEq, Hash, Debug)] @@ -312,7 +348,3 @@ fn report_test_diffs(diff: AggregatedTestDiffs) { ); } } - -fn pluralize(text: &str, count: usize) -> String { - if count == 1 { text.to_string() } else { format!("{text}s") } -} diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs index 53fe75900750..5f1932854b5a 100644 --- a/src/ci/citool/src/main.rs +++ b/src/ci/citool/src/main.rs @@ -1,7 +1,7 @@ +mod analysis; mod cpu_usage; mod datadog; mod jobs; -mod merge_report; mod metrics; mod utils; @@ -14,12 +14,13 @@ use clap::Parser; use jobs::JobDatabase; use serde_yaml::Value; +use crate::analysis::output_test_diffs; use crate::cpu_usage::load_cpu_usage; use crate::datadog::upload_datadog_metric; use crate::jobs::RunType; -use crate::merge_report::post_merge_report; -use crate::metrics::postprocess_metrics; +use crate::metrics::{download_auto_job_metrics, load_metrics}; use crate::utils::load_env_var; +use analysis::output_bootstrap_stats; const CI_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/.."); const DOCKER_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../docker"); @@ -209,10 +210,14 @@ fn main() -> anyhow::Result<()> { upload_ci_metrics(&cpu_usage_csv)?; } Args::PostprocessMetrics { metrics_path } => { - postprocess_metrics(&metrics_path)?; + let metrics = load_metrics(&metrics_path)?; + output_bootstrap_stats(&metrics); } - Args::PostMergeReport { current: commit, parent } => { - post_merge_report(load_db(default_jobs_file)?, parent, commit)?; + Args::PostMergeReport { current, parent } => { + let db = load_db(default_jobs_file)?; + let metrics = download_auto_job_metrics(&db, &parent, ¤t)?; + println!("Comparing {parent} (base) -> {current} (this PR)\n"); + output_test_diffs(metrics); } } diff --git a/src/ci/citool/src/metrics.rs b/src/ci/citool/src/metrics.rs index 8da4d4e53e64..117a4f372c4c 100644 --- a/src/ci/citool/src/metrics.rs +++ b/src/ci/citool/src/metrics.rs @@ -1,133 +1,11 @@ -use std::collections::BTreeMap; use std::path::Path; +use crate::jobs::JobDatabase; use anyhow::Context; -use build_helper::metrics::{ - BuildStep, JsonNode, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, format_build_steps, -}; +use build_helper::metrics::{JsonNode, JsonRoot, TestSuite}; +use std::collections::HashMap; -pub fn postprocess_metrics(metrics_path: &Path) -> anyhow::Result<()> { - let metrics = load_metrics(metrics_path)?; - - if !metrics.invocations.is_empty() { - println!("# Bootstrap steps"); - record_bootstrap_step_durations(&metrics); - record_test_suites(&metrics); - } - - Ok(()) -} - -fn record_bootstrap_step_durations(metrics: &JsonRoot) { - for invocation in &metrics.invocations { - let step = BuildStep::from_invocation(invocation); - let table = format_build_steps(&step); - eprintln!("Step `{}`\n{table}\n", invocation.cmdline); - println!( - r"
-{} -
{table}
-
-", - invocation.cmdline - ); - } - eprintln!("Recorded {} bootstrap invocation(s)", metrics.invocations.len()); -} - -fn record_test_suites(metrics: &JsonRoot) { - let suites = get_test_suites(&metrics); - - if !suites.is_empty() { - let aggregated = aggregate_test_suites(&suites); - let table = render_table(aggregated); - println!("\n# Test results\n"); - println!("{table}"); - } else { - eprintln!("No test suites found in metrics"); - } -} - -fn render_table(suites: BTreeMap) -> String { - use std::fmt::Write; - - let mut table = "| Test suite | Passed ✅ | Ignored 🚫 | Failed ❌ |\n".to_string(); - writeln!(table, "|:------|------:|------:|------:|").unwrap(); - - fn compute_pct(value: f64, total: f64) -> f64 { - if total == 0.0 { 0.0 } else { value / total } - } - - fn write_row( - buffer: &mut String, - name: &str, - record: &TestSuiteRecord, - surround: &str, - ) -> std::fmt::Result { - let TestSuiteRecord { passed, ignored, failed } = record; - let total = (record.passed + record.ignored + record.failed) as f64; - let passed_pct = compute_pct(*passed as f64, total) * 100.0; - let ignored_pct = compute_pct(*ignored as f64, total) * 100.0; - let failed_pct = compute_pct(*failed as f64, total) * 100.0; - - write!(buffer, "| {surround}{name}{surround} |")?; - write!(buffer, " {surround}{passed} ({passed_pct:.0}%){surround} |")?; - write!(buffer, " {surround}{ignored} ({ignored_pct:.0}%){surround} |")?; - writeln!(buffer, " {surround}{failed} ({failed_pct:.0}%){surround} |")?; - - Ok(()) - } - - let mut total = TestSuiteRecord::default(); - for (name, record) in suites { - write_row(&mut table, &name, &record, "").unwrap(); - total.passed += record.passed; - total.ignored += record.ignored; - total.failed += record.failed; - } - write_row(&mut table, "Total", &total, "**").unwrap(); - table -} - -#[derive(Default)] -struct TestSuiteRecord { - passed: u64, - ignored: u64, - failed: u64, -} - -fn test_metadata_name(metadata: &TestSuiteMetadata) -> String { - match metadata { - TestSuiteMetadata::CargoPackage { crates, stage, .. } => { - format!("{} (stage {stage})", crates.join(", ")) - } - TestSuiteMetadata::Compiletest { suite, stage, .. } => { - format!("{suite} (stage {stage})") - } - } -} - -fn aggregate_test_suites(suites: &[&TestSuite]) -> BTreeMap { - let mut records: BTreeMap = BTreeMap::new(); - for suite in suites { - let name = test_metadata_name(&suite.metadata); - let record = records.entry(name).or_default(); - for test in &suite.tests { - match test.outcome { - TestOutcome::Passed => { - record.passed += 1; - } - TestOutcome::Failed => { - record.failed += 1; - } - TestOutcome::Ignored { .. } => { - record.ignored += 1; - } - } - } - } - records -} +pub type JobName = String; pub fn get_test_suites(metrics: &JsonRoot) -> Vec<&TestSuite> { fn visit_test_suites<'a>(nodes: &'a [JsonNode], suites: &mut Vec<&'a TestSuite>) { @@ -150,10 +28,68 @@ pub fn get_test_suites(metrics: &JsonRoot) -> Vec<&TestSuite> { suites } -fn load_metrics(path: &Path) -> anyhow::Result { +pub fn load_metrics(path: &Path) -> anyhow::Result { let metrics = std::fs::read_to_string(path) .with_context(|| format!("Cannot read JSON metrics from {path:?}"))?; let metrics: JsonRoot = serde_json::from_str(&metrics) .with_context(|| format!("Cannot deserialize JSON metrics from {path:?}"))?; Ok(metrics) } + +pub struct JobMetrics { + pub parent: Option, + pub current: JsonRoot, +} + +/// Download before/after metrics for all auto jobs in the job database. +/// `parent` and `current` should be commit SHAs. +pub fn download_auto_job_metrics( + job_db: &JobDatabase, + parent: &str, + current: &str, +) -> anyhow::Result> { + let mut jobs = HashMap::default(); + + for job in &job_db.auto_jobs { + eprintln!("Downloading metrics of job {}", job.name); + let metrics_parent = match download_job_metrics(&job.name, parent) { + Ok(metrics) => Some(metrics), + Err(error) => { + eprintln!( + r#"Did not find metrics for job `{}` at `{}`: {error:?}. +Maybe it was newly added?"#, + job.name, parent + ); + None + } + }; + let metrics_current = download_job_metrics(&job.name, current)?; + jobs.insert( + job.name.clone(), + JobMetrics { parent: metrics_parent, current: metrics_current }, + ); + } + Ok(jobs) +} + +pub fn download_job_metrics(job_name: &str, sha: &str) -> anyhow::Result { + let url = get_metrics_url(job_name, sha); + let mut response = ureq::get(&url).call()?; + if !response.status().is_success() { + return Err(anyhow::anyhow!( + "Cannot fetch metrics from {url}: {}\n{}", + response.status(), + response.body_mut().read_to_string()? + )); + } + let data: JsonRoot = response + .body_mut() + .read_json() + .with_context(|| anyhow::anyhow!("cannot deserialize metrics from {url}"))?; + Ok(data) +} + +fn get_metrics_url(job_name: &str, sha: &str) -> String { + let suffix = if job_name.ends_with("-alt") { "-alt" } else { "" }; + format!("https://ci-artifacts.rust-lang.org/rustc-builds{suffix}/{sha}/metrics-{job_name}.json") +} diff --git a/src/ci/citool/src/utils.rs b/src/ci/citool/src/utils.rs index 9cc220987bdf..a18af96bf3de 100644 --- a/src/ci/citool/src/utils.rs +++ b/src/ci/citool/src/utils.rs @@ -9,3 +9,7 @@ pub fn load_env_var(name: &str) -> anyhow::Result { pub fn read_to_string>(path: P) -> anyhow::Result { std::fs::read_to_string(&path).with_context(|| format!("Cannot read file {:?}", path.as_ref())) } + +pub fn pluralize(text: &str, count: usize) -> String { + if count == 1 { text.to_string() } else { format!("{text}s") } +} From 413fd52ea98a1cd986afa3201a259304a3b58599 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 15 Mar 2025 09:32:57 +0100 Subject: [PATCH 203/745] Print number of found test diffs --- src/ci/citool/src/analysis.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 87c5708fa602..8e4ab03f3b3a 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -244,6 +244,7 @@ fn report_test_diffs(diff: AggregatedTestDiffs) { println!("No test diffs found"); return; } + println!("\n{} test {} found\n", diff.diffs.len(), pluralize("difference", diff.diffs.len())); fn format_outcome(outcome: &TestOutcome) -> String { match outcome { From 6c24c9c088a0eb858976781090a5b1fbb57981bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 15 Mar 2025 09:34:35 +0100 Subject: [PATCH 204/745] Use first-level heading for test differences header --- src/ci/citool/src/analysis.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 8e4ab03f3b3a..02199636fc79 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -239,7 +239,7 @@ fn normalize_test_name(name: &str) -> String { /// Prints test changes in Markdown format to stdout. fn report_test_diffs(diff: AggregatedTestDiffs) { - println!("## Test differences"); + println!("# Test differences"); if diff.diffs.is_empty() { println!("No test diffs found"); return; From 30d57576b9040a438adc2414540da3778addf34b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 15 Mar 2025 09:35:29 +0100 Subject: [PATCH 205/745] Print test diffs into GitHub summary So that we can also observe them for try builds, before merging a PR. --- .github/workflows/ci.yml | 5 +++++ src/ci/citool/src/main.rs | 41 +++++++++++++++++++++++++++++++++------ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ffcdc40de3a7..aaae67c28bc7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -252,7 +252,12 @@ jobs: exit 0 fi + # Get closest bors merge commit + PARENT_COMMIT=`git rev-list --author='bors ' -n1 --first-parent HEAD^1` + ./build/citool/debug/citool postprocess-metrics \ + --job-name ${CI_JOB_NAME} \ + --parent ${PARENT_COMMIT} \ ${METRICS} >> ${GITHUB_STEP_SUMMARY} - name: upload job metrics to DataDog diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs index 5f1932854b5a..fb0639367bd0 100644 --- a/src/ci/citool/src/main.rs +++ b/src/ci/citool/src/main.rs @@ -5,7 +5,7 @@ mod jobs; mod metrics; mod utils; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, HashMap}; use std::path::{Path, PathBuf}; use std::process::Command; @@ -18,7 +18,7 @@ use crate::analysis::output_test_diffs; use crate::cpu_usage::load_cpu_usage; use crate::datadog::upload_datadog_metric; use crate::jobs::RunType; -use crate::metrics::{download_auto_job_metrics, load_metrics}; +use crate::metrics::{JobMetrics, download_auto_job_metrics, download_job_metrics, load_metrics}; use crate::utils::load_env_var; use analysis::output_bootstrap_stats; @@ -138,6 +138,27 @@ fn upload_ci_metrics(cpu_usage_csv: &Path) -> anyhow::Result<()> { Ok(()) } +fn postprocess_metrics( + metrics_path: PathBuf, + parent: Option, + job_name: Option, +) -> anyhow::Result<()> { + let metrics = load_metrics(&metrics_path)?; + output_bootstrap_stats(&metrics); + + let (Some(parent), Some(job_name)) = (parent, job_name) else { + return Ok(()); + }; + + let parent_metrics = + download_job_metrics(&job_name, &parent).context("cannot download parent metrics")?; + let job_metrics = + HashMap::from([(job_name, JobMetrics { parent: Some(parent_metrics), current: metrics })]); + output_test_diffs(job_metrics); + + Ok(()) +} + #[derive(clap::Parser)] enum Args { /// Calculate a list of jobs that should be executed on CI. @@ -155,10 +176,19 @@ enum Args { #[clap(long = "type", default_value = "auto")] job_type: JobType, }, - /// Postprocess the metrics.json file generated by bootstrap. + /// Postprocess the metrics.json file generated by bootstrap and output + /// various statistics. + /// If `--parent` and `--job-name` are provided, also display a diff + /// against previous metrics that are downloaded from CI. PostprocessMetrics { /// Path to the metrics.json file metrics_path: PathBuf, + /// A parent SHA against which to compare. + #[clap(long, requires("job_name"))] + parent: Option, + /// The name of the current job. + #[clap(long, requires("parent"))] + job_name: Option, }, /// Upload CI metrics to Datadog. UploadBuildMetrics { @@ -209,9 +239,8 @@ fn main() -> anyhow::Result<()> { Args::UploadBuildMetrics { cpu_usage_csv } => { upload_ci_metrics(&cpu_usage_csv)?; } - Args::PostprocessMetrics { metrics_path } => { - let metrics = load_metrics(&metrics_path)?; - output_bootstrap_stats(&metrics); + Args::PostprocessMetrics { metrics_path, parent, job_name } => { + postprocess_metrics(metrics_path, parent, job_name)?; } Args::PostMergeReport { current, parent } => { let db = load_db(default_jobs_file)?; From 634a11ef4864eb3cdaefa34d320f4be4f679b542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 15 Mar 2025 09:37:19 +0100 Subject: [PATCH 206/745] Add bootstrap stage to test names --- src/ci/citool/src/analysis.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 02199636fc79..566b8e603fbb 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -225,16 +225,23 @@ fn aggregate_tests(metrics: &JsonRoot) -> TestSuiteData { // Poor man's detection of doctests based on the "(line XYZ)" suffix let is_doctest = matches!(suite.metadata, TestSuiteMetadata::CargoPackage { .. }) && test.name.contains("(line"); - let test_entry = Test { name: normalize_test_name(&test.name), is_doctest }; + let test_entry = Test { name: generate_test_name(&test.name, &suite), is_doctest }; tests.insert(test_entry, test.outcome.clone()); } } TestSuiteData { tests } } -/// Normalizes Windows-style path delimiters to Unix-style paths. -fn normalize_test_name(name: &str) -> String { - name.replace('\\', "/") +/// Normalizes Windows-style path delimiters to Unix-style paths +/// and adds suite metadata to the test name. +fn generate_test_name(name: &str, suite: &TestSuite) -> String { + let name = name.replace('\\', "/"); + let stage = match suite.metadata { + TestSuiteMetadata::CargoPackage { stage, .. } => stage, + TestSuiteMetadata::Compiletest { stage, .. } => stage, + }; + + format!("{name} (stage {stage})") } /// Prints test changes in Markdown format to stdout. From 232be8614d8bc396f3c0917916c96ef0ee939ad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 15 Mar 2025 09:41:00 +0100 Subject: [PATCH 207/745] Add a helper function for outputting details --- src/ci/citool/src/analysis.rs | 13 ++++--------- src/ci/citool/src/utils.rs | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 566b8e603fbb..8a3754435770 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -1,6 +1,6 @@ use crate::metrics; use crate::metrics::{JobMetrics, JobName, get_test_suites}; -use crate::utils::pluralize; +use crate::utils::{output_details, pluralize}; use build_helper::metrics::{ BuildStep, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, format_build_steps, }; @@ -19,14 +19,9 @@ fn record_bootstrap_step_durations(metrics: &JsonRoot) { let step = BuildStep::from_invocation(invocation); let table = format_build_steps(&step); eprintln!("Step `{}`\n{table}\n", invocation.cmdline); - println!( - r"
-{} -
{table}
-
-", - invocation.cmdline - ); + output_details(&invocation.cmdline, || { + println!("
{table}
"); + }); } eprintln!("Recorded {} bootstrap invocation(s)", metrics.invocations.len()); } diff --git a/src/ci/citool/src/utils.rs b/src/ci/citool/src/utils.rs index a18af96bf3de..bbe24c3633bc 100644 --- a/src/ci/citool/src/utils.rs +++ b/src/ci/citool/src/utils.rs @@ -13,3 +13,17 @@ pub fn read_to_string>(path: P) -> anyhow::Result { pub fn pluralize(text: &str, count: usize) -> String { if count == 1 { text.to_string() } else { format!("{text}s") } } + +/// Outputs a HTML
section with the provided summary. +/// Output printed by `func` will be contained within the section. +pub fn output_details(summary: &str, func: F) +where + F: FnOnce(), +{ + println!( + r"
+{summary}" + ); + func(); + println!("
\n"); +} From b4cccf01587ac672dee7a92df7e3e21728f5b7aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 15 Mar 2025 10:00:11 +0100 Subject: [PATCH 208/745] Put test differences into a `
` section and add better explanation of the post merge report --- src/ci/citool/src/analysis.rs | 63 +++++++++++++++++++---------------- src/ci/citool/src/main.rs | 23 ++++++++++--- src/ci/citool/src/utils.rs | 4 ++- 3 files changed, 56 insertions(+), 34 deletions(-) diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 8a3754435770..6469bc251be6 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -246,7 +246,6 @@ fn report_test_diffs(diff: AggregatedTestDiffs) { println!("No test diffs found"); return; } - println!("\n{} test {} found\n", diff.diffs.len(), pluralize("difference", diff.diffs.len())); fn format_outcome(outcome: &TestOutcome) -> String { match outcome { @@ -320,34 +319,42 @@ fn report_test_diffs(diff: AggregatedTestDiffs) { // Sort diffs by job group and test name grouped_diffs.sort_by(|(d1, g1), (d2, g2)| g1.cmp(&g2).then(d1.test.name.cmp(&d2.test.name))); - for (diff, job_group) in grouped_diffs { - println!( - "- `{}`: {} ({})", - diff.test.name, - format_diff(&diff.diff), - format_job_group(job_group) - ); - } + output_details( + &format!("Show {} test {}\n", original_diff_count, pluralize("diff", original_diff_count)), + || { + for (diff, job_group) in grouped_diffs { + println!( + "- `{}`: {} ({})", + diff.test.name, + format_diff(&diff.diff), + format_job_group(job_group) + ); + } - let extra_diffs = diffs.len().saturating_sub(max_diff_count); - if extra_diffs > 0 { - println!("\n(and {extra_diffs} additional {})", pluralize("test diff", extra_diffs)); - } + let extra_diffs = diffs.len().saturating_sub(max_diff_count); + if extra_diffs > 0 { + println!( + "\n(and {extra_diffs} additional {})", + pluralize("test diff", extra_diffs) + ); + } - if doctest_count > 0 { - println!( - "\nAdditionally, {doctest_count} doctest {} were found. These are ignored, as they are noisy.", - pluralize("diff", doctest_count) - ); - } + if doctest_count > 0 { + println!( + "\nAdditionally, {doctest_count} doctest {} were found. These are ignored, as they are noisy.", + pluralize("diff", doctest_count) + ); + } - // Now print the job group index - println!("\n**Job group index**\n"); - for (group, jobs) in job_index.into_iter().enumerate() { - println!( - "- {}: {}", - format_job_group(group as u64), - jobs.iter().map(|j| format!("`{j}`")).collect::>().join(", ") - ); - } + // Now print the job group index + println!("\n**Job group index**\n"); + for (group, jobs) in job_index.into_iter().enumerate() { + println!( + "- {}: {}", + format_job_group(group as u64), + jobs.iter().map(|j| format!("`{j}`")).collect::>().join(", ") + ); + } + }, + ); } diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs index fb0639367bd0..01483a2633d0 100644 --- a/src/ci/citool/src/main.rs +++ b/src/ci/citool/src/main.rs @@ -19,7 +19,7 @@ use crate::cpu_usage::load_cpu_usage; use crate::datadog::upload_datadog_metric; use crate::jobs::RunType; use crate::metrics::{JobMetrics, download_auto_job_metrics, download_job_metrics, load_metrics}; -use crate::utils::load_env_var; +use crate::utils::{load_env_var, output_details}; use analysis::output_bootstrap_stats; const CI_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/.."); @@ -159,6 +159,22 @@ fn postprocess_metrics( Ok(()) } +fn post_merge_report(db: JobDatabase, current: String, parent: String) -> anyhow::Result<()> { + let metrics = download_auto_job_metrics(&db, &parent, ¤t)?; + + output_details("What is this?", || { + println!( + r#"This is an experimental post-merge analysis report that shows differences in +test outcomes between the merged PR and its parent PR."# + ); + }); + + println!("\nComparing {parent} (parent) -> {current} (this PR)\n"); + output_test_diffs(metrics); + + Ok(()) +} + #[derive(clap::Parser)] enum Args { /// Calculate a list of jobs that should be executed on CI. @@ -243,10 +259,7 @@ fn main() -> anyhow::Result<()> { postprocess_metrics(metrics_path, parent, job_name)?; } Args::PostMergeReport { current, parent } => { - let db = load_db(default_jobs_file)?; - let metrics = download_auto_job_metrics(&db, &parent, ¤t)?; - println!("Comparing {parent} (base) -> {current} (this PR)\n"); - output_test_diffs(metrics); + post_merge_report(load_db(default_jobs_file)?, current, parent)?; } } diff --git a/src/ci/citool/src/utils.rs b/src/ci/citool/src/utils.rs index bbe24c3633bc..b9b1bf4d4550 100644 --- a/src/ci/citool/src/utils.rs +++ b/src/ci/citool/src/utils.rs @@ -22,7 +22,9 @@ where { println!( r"
-{summary}" +{summary} + +" ); func(); println!("
\n"); From e84531811160308fbdd0a8ec3e9b697bb17ccd02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 15 Mar 2025 11:11:56 +0100 Subject: [PATCH 209/745] Do not error out on missing parent metrics --- src/ci/citool/src/main.rs | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs index 01483a2633d0..29f94e2be5db 100644 --- a/src/ci/citool/src/main.rs +++ b/src/ci/citool/src/main.rs @@ -150,11 +150,24 @@ fn postprocess_metrics( return Ok(()); }; - let parent_metrics = - download_job_metrics(&job_name, &parent).context("cannot download parent metrics")?; - let job_metrics = - HashMap::from([(job_name, JobMetrics { parent: Some(parent_metrics), current: metrics })]); - output_test_diffs(job_metrics); + // This command is executed also on PR builds, which might not have parent metrics + // available, because some PR jobs don't run on auto builds, and PR jobs do not upload metrics + // due to missing permissions. + // To avoid having to detect if this is a PR job, and to avoid having failed steps in PR jobs, + // we simply print an error if the parent metrics were not found, but otherwise exit + // successfully. + match download_job_metrics(&job_name, &parent).context("cannot download parent metrics") { + Ok(parent_metrics) => { + let job_metrics = HashMap::from([( + job_name, + JobMetrics { parent: Some(parent_metrics), current: metrics }, + )]); + output_test_diffs(job_metrics); + } + Err(error) => { + eprintln!("Metrics for job `{job_name}` and commit `{parent}` not found: {error:?}"); + } + } Ok(()) } From 4801dba9af6e6c1b3bb06959893f68ed031f6325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 15 Mar 2025 11:34:55 +0100 Subject: [PATCH 210/745] Reformat code --- src/ci/citool/src/analysis.rs | 10 ++++++---- src/ci/citool/src/main.rs | 2 +- src/ci/citool/src/metrics.rs | 5 +++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 6469bc251be6..2088ce296209 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -1,10 +1,12 @@ -use crate::metrics; -use crate::metrics::{JobMetrics, JobName, get_test_suites}; -use crate::utils::{output_details, pluralize}; +use std::collections::{BTreeMap, HashMap, HashSet}; + use build_helper::metrics::{ BuildStep, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, format_build_steps, }; -use std::collections::{BTreeMap, HashMap, HashSet}; + +use crate::metrics; +use crate::metrics::{JobMetrics, JobName, get_test_suites}; +use crate::utils::{output_details, pluralize}; pub fn output_bootstrap_stats(metrics: &JsonRoot) { if !metrics.invocations.is_empty() { diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs index 29f94e2be5db..9e4b558d77aa 100644 --- a/src/ci/citool/src/main.rs +++ b/src/ci/citool/src/main.rs @@ -9,6 +9,7 @@ use std::collections::{BTreeMap, HashMap}; use std::path::{Path, PathBuf}; use std::process::Command; +use analysis::output_bootstrap_stats; use anyhow::Context; use clap::Parser; use jobs::JobDatabase; @@ -20,7 +21,6 @@ use crate::datadog::upload_datadog_metric; use crate::jobs::RunType; use crate::metrics::{JobMetrics, download_auto_job_metrics, download_job_metrics, load_metrics}; use crate::utils::{load_env_var, output_details}; -use analysis::output_bootstrap_stats; const CI_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/.."); const DOCKER_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../docker"); diff --git a/src/ci/citool/src/metrics.rs b/src/ci/citool/src/metrics.rs index 117a4f372c4c..263011a33708 100644 --- a/src/ci/citool/src/metrics.rs +++ b/src/ci/citool/src/metrics.rs @@ -1,9 +1,10 @@ +use std::collections::HashMap; use std::path::Path; -use crate::jobs::JobDatabase; use anyhow::Context; use build_helper::metrics::{JsonNode, JsonRoot, TestSuite}; -use std::collections::HashMap; + +use crate::jobs::JobDatabase; pub type JobName = String; From 7c792e29d71f83407318e730015caa0003bbb9f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 15 Mar 2025 13:10:49 +0100 Subject: [PATCH 211/745] Only use `DIST_TRY_BUILD` for try jobs that were not selected explicitly --- src/ci/citool/src/jobs.rs | 14 ++++++++++++++ src/ci/citool/tests/jobs.rs | 10 +++++----- src/ci/citool/tests/test-jobs.yml | 7 ------- src/ci/github-actions/jobs.yml | 12 +++++------- 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/ci/citool/src/jobs.rs b/src/ci/citool/src/jobs.rs index 0de8b740227d..13880ad466a6 100644 --- a/src/ci/citool/src/jobs.rs +++ b/src/ci/citool/src/jobs.rs @@ -185,6 +185,20 @@ fn calculate_jobs( env.extend(crate::yaml_map_to_json(&job.env)); let full_name = format!("{prefix} - {}", job.name); + // When the default `@bors try` job is executed (which is usually done + // for benchmarking performance, running crater or for downloading the + // built toolchain using `rustup-toolchain-install-master`), + // we inject the `DIST_TRY_BUILD` environment variable to the jobs + // to tell `opt-dist` to make the build faster by skipping certain steps. + if let RunType::TryJob { job_patterns } = run_type { + if job_patterns.is_none() { + env.insert( + "DIST_TRY_BUILD".to_string(), + serde_json::value::Value::Number(1.into()), + ); + } + } + GithubActionsJob { name: job.name, full_name, diff --git a/src/ci/citool/tests/jobs.rs b/src/ci/citool/tests/jobs.rs index 788f5e7e4f66..c644f885be30 100644 --- a/src/ci/citool/tests/jobs.rs +++ b/src/ci/citool/tests/jobs.rs @@ -14,10 +14,10 @@ fn auto_jobs() { #[test] fn try_jobs() { let stdout = get_matrix("push", "commit", "refs/heads/try"); - insta::assert_snapshot!(stdout, @r#" + insta::assert_snapshot!(stdout, @r###" jobs=[{"name":"dist-x86_64-linux","full_name":"try - dist-x86_64-linux","os":"ubuntu-22.04-16core-64gb","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_TRY_BUILD":1,"TOOLSTATE_PUBLISH":1}}] run_type=try - "#); + "###); } #[test] @@ -30,10 +30,10 @@ try-job: aarch64-gnu try-job: dist-i686-msvc"#, "refs/heads/try", ); - insta::assert_snapshot!(stdout, @r#" - jobs=[{"name":"aarch64-gnu","full_name":"try - aarch64-gnu","os":"ubuntu-22.04-arm","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","DIST_TRY_BUILD":1,"TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"dist-i686-msvc","full_name":"try - dist-i686-msvc","os":"windows-2022","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_REQUIRE_ALL_TOOLS":1,"DIST_TRY_BUILD":1,"RUST_CONFIGURE_ARGS":"--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler","SCRIPT":"python x.py dist bootstrap --include-default-paths","TOOLSTATE_PUBLISH":1}}] + insta::assert_snapshot!(stdout, @r###" + jobs=[{"name":"aarch64-gnu","full_name":"try - aarch64-gnu","os":"ubuntu-22.04-arm","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"dist-i686-msvc","full_name":"try - dist-i686-msvc","os":"windows-2022","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_REQUIRE_ALL_TOOLS":1,"RUST_CONFIGURE_ARGS":"--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler","SCRIPT":"python x.py dist bootstrap --include-default-paths","TOOLSTATE_PUBLISH":1}}] run_type=try - "#); + "###); } #[test] diff --git a/src/ci/citool/tests/test-jobs.yml b/src/ci/citool/tests/test-jobs.yml index ff4d1772f59b..3593b3f7df63 100644 --- a/src/ci/citool/tests/test-jobs.yml +++ b/src/ci/citool/tests/test-jobs.yml @@ -53,13 +53,6 @@ envs: try: <<: *production - # The following env var activates faster `try` builds in `opt-dist` by, e.g. - # - building only the more commonly useful components (we rarely need e.g. rust-docs in try - # builds) - # - not running `opt-dist`'s post-optimization smoke tests on the resulting toolchain - # - # If you *want* these to happen however, temporarily comment it before triggering a try build. - DIST_TRY_BUILD: 1 auto: <<: *production diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index d8c3625af286..ae029cb77799 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -82,15 +82,13 @@ envs: AWS_REGION: us-west-1 TOOLSTATE_PUBLISH: 1 + # Try builds started through `@bors try` (without specifying custom jobs + # in the PR description) will be passed the `DIST_TRY_BUILD` environment + # variable by citool. + # This tells the `opt-dist` tool to skip building certain components + # and skip running tests, so that the try build finishes faster. try: <<: *production - # The following env var activates faster `try` builds in `opt-dist` by, e.g. - # - building only the more commonly useful components (we rarely need e.g. rust-docs in try - # builds) - # - not running `opt-dist`'s post-optimization smoke tests on the resulting toolchain - # - # If you *want* these to happen however, temporarily comment it before triggering a try build. - DIST_TRY_BUILD: 1 auto: <<: *production From eca391fbd4544e3f200f0ee08ef8d6f0a469542e Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Sat, 15 Mar 2025 12:31:36 +0000 Subject: [PATCH 212/745] Cleanup `LangString::parse` Flatten some `if`s into match patterns Use `str::strip_prefix` instead of `starts_with`+indexing Avoid redundant tests for `extra.is_some()` --- src/librustdoc/html/markdown.rs | 85 ++++++++++++++++----------------- 1 file changed, 41 insertions(+), 44 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 079651e86031..e516b498c189 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -1200,11 +1200,12 @@ impl LangString { data.ignore = Ignore::All; seen_rust_tags = !seen_other_tags; } - LangStringToken::LangToken(x) if x.starts_with("ignore-") => { - if enable_per_target_ignores { - ignores.push(x.trim_start_matches("ignore-").to_owned()); - seen_rust_tags = !seen_other_tags; - } + LangStringToken::LangToken(x) + if let Some(ignore) = x.strip_prefix("ignore-") + && enable_per_target_ignores => + { + ignores.push(ignore.to_owned()); + seen_rust_tags = !seen_other_tags; } LangStringToken::LangToken("rust") => { data.rust = true; @@ -1226,37 +1227,39 @@ impl LangString { data.standalone_crate = true; seen_rust_tags = !seen_other_tags || seen_rust_tags; } - LangStringToken::LangToken(x) if x.starts_with("edition") => { - data.edition = x[7..].parse::().ok(); + LangStringToken::LangToken(x) + if let Some(edition) = x.strip_prefix("edition") => + { + data.edition = edition.parse::().ok(); } LangStringToken::LangToken(x) - if x.starts_with("rust") && x[4..].parse::().is_ok() => + if let Some(edition) = x.strip_prefix("rust") + && edition.parse::().is_ok() + && let Some(extra) = extra => { - if let Some(extra) = extra { - extra.error_invalid_codeblock_attr_with_help( - format!("unknown attribute `{x}`"), - |lint| { - lint.help(format!( - "there is an attribute with a similar name: `edition{}`", - &x[4..], - )); - }, - ); - } + extra.error_invalid_codeblock_attr_with_help( + format!("unknown attribute `{x}`"), + |lint| { + lint.help(format!( + "there is an attribute with a similar name: `edition{edition}`" + )); + }, + ); } LangStringToken::LangToken(x) - if allow_error_code_check && x.starts_with('E') && x.len() == 5 => + if allow_error_code_check + && let Some(error_code) = x.strip_prefix('E') + && error_code.len() == 4 => { - if x[1..].parse::().is_ok() { + if error_code.parse::().is_ok() { data.error_codes.push(x.to_owned()); seen_rust_tags = !seen_other_tags || seen_rust_tags; } else { seen_other_tags = true; } } - LangStringToken::LangToken(x) if extra.is_some() => { - let s = x.to_lowercase(); - if let Some(help) = match s.as_str() { + LangStringToken::LangToken(x) if let Some(extra) = extra => { + if let Some(help) = match x.to_lowercase().as_str() { "compile-fail" | "compile_fail" | "compilefail" => Some( "use `compile_fail` to invert the results of this test, so that it \ passes if it cannot be compiled and fails if it can", @@ -1273,33 +1276,27 @@ impl LangString { "use `test_harness` to run functions marked `#[test]` instead of a \ potentially-implicit `main` function", ), - "standalone" | "standalone_crate" | "standalone-crate" => { - if let Some(extra) = extra - && extra.sp.at_least_rust_2024() - { - Some( - "use `standalone_crate` to compile this code block \ + "standalone" | "standalone_crate" | "standalone-crate" + if extra.sp.at_least_rust_2024() => + { + Some( + "use `standalone_crate` to compile this code block \ separately", - ) - } else { - None - } + ) } _ => None, } { - if let Some(extra) = extra { - extra.error_invalid_codeblock_attr_with_help( - format!("unknown attribute `{x}`"), - |lint| { - lint.help(help).help( - "this code block may be skipped during testing, \ + extra.error_invalid_codeblock_attr_with_help( + format!("unknown attribute `{x}`"), + |lint| { + lint.help(help).help( + "this code block may be skipped during testing, \ because unknown attributes are treated as markers for \ code samples written in other programming languages, \ unless it is also explicitly marked as `rust`", - ); - }, - ); - } + ); + }, + ); } seen_other_tags = true; data.unknown.push(x.to_owned()); From 360a87d51df99df2c2d2cbec0e5b30dbd9c03e59 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 13 Sep 2024 16:19:38 +0300 Subject: [PATCH 213/745] hygiene: Asserts, comments, code cleanup --- compiler/rustc_span/src/hygiene.rs | 144 ++++++++++++++++++----------- 1 file changed, 91 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 62027caa3537..b872f5e9d38f 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -27,9 +27,9 @@ use std::cell::RefCell; use std::collections::hash_map::Entry; use std::collections::hash_set::Entry as SetEntry; -use std::fmt; use std::hash::Hash; use std::sync::Arc; +use std::{fmt, iter, mem}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -57,7 +57,11 @@ pub struct SyntaxContext(u32); impl !Ord for SyntaxContext {} impl !PartialOrd for SyntaxContext {} -#[derive(Debug, Encodable, Decodable, Clone)] +/// If this part of two syntax contexts is equal, then the whole syntax contexts should be equal. +/// The other fields are only for caching. +type SyntaxContextKey = (SyntaxContext, ExpnId, Transparency); + +#[derive(Clone, Copy, PartialEq, Debug, Encodable, Decodable)] pub struct SyntaxContextData { outer_expn: ExpnId, outer_transparency: Transparency, @@ -70,6 +74,27 @@ pub struct SyntaxContextData { dollar_crate_name: Symbol, } +impl SyntaxContextData { + fn root() -> SyntaxContextData { + SyntaxContextData { + outer_expn: ExpnId::root(), + outer_transparency: Transparency::Opaque, + parent: SyntaxContext::root(), + opaque: SyntaxContext::root(), + opaque_and_semitransparent: SyntaxContext::root(), + dollar_crate_name: kw::DollarCrate, + } + } + + fn decode_placeholder() -> SyntaxContextData { + SyntaxContextData { dollar_crate_name: kw::Empty, ..SyntaxContextData::root() } + } + + fn is_decode_placeholder(&self) -> bool { + self.dollar_crate_name == kw::Empty + } +} + rustc_index::newtype_index! { /// A unique ID associated with a macro invocation and expansion. #[orderable] @@ -342,7 +367,7 @@ pub(crate) struct HygieneData { foreign_expn_hashes: FxHashMap, expn_hash_to_expn_id: UnhashMap, syntax_context_data: Vec, - syntax_context_map: FxHashMap<(SyntaxContext, ExpnId, Transparency), SyntaxContext>, + syntax_context_map: FxHashMap, /// Maps the `local_hash` of an `ExpnData` to the next disambiguator value. /// This is used by `update_disambiguator` to keep track of which `ExpnData`s /// would have collisions without a disambiguator. @@ -361,21 +386,15 @@ impl HygieneData { None, ); + let root_ctxt_data = SyntaxContextData::root(); HygieneData { local_expn_data: IndexVec::from_elem_n(Some(root_data), 1), local_expn_hashes: IndexVec::from_elem_n(ExpnHash(Fingerprint::ZERO), 1), foreign_expn_data: FxHashMap::default(), foreign_expn_hashes: FxHashMap::default(), - expn_hash_to_expn_id: std::iter::once((ExpnHash(Fingerprint::ZERO), ExpnId::root())) + expn_hash_to_expn_id: iter::once((ExpnHash(Fingerprint::ZERO), ExpnId::root())) .collect(), - syntax_context_data: vec![SyntaxContextData { - outer_expn: ExpnId::root(), - outer_transparency: Transparency::Opaque, - parent: SyntaxContext(0), - opaque: SyntaxContext(0), - opaque_and_semitransparent: SyntaxContext(0), - dollar_crate_name: kw::DollarCrate, - }], + syntax_context_data: vec![root_ctxt_data], syntax_context_map: FxHashMap::default(), expn_data_disambiguators: UnhashMap::default(), } @@ -425,23 +444,28 @@ impl HygieneData { } fn normalize_to_macros_2_0(&self, ctxt: SyntaxContext) -> SyntaxContext { + debug_assert!(!self.syntax_context_data[ctxt.0 as usize].is_decode_placeholder()); self.syntax_context_data[ctxt.0 as usize].opaque } fn normalize_to_macro_rules(&self, ctxt: SyntaxContext) -> SyntaxContext { + debug_assert!(!self.syntax_context_data[ctxt.0 as usize].is_decode_placeholder()); self.syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent } fn outer_expn(&self, ctxt: SyntaxContext) -> ExpnId { + debug_assert!(!self.syntax_context_data[ctxt.0 as usize].is_decode_placeholder()); self.syntax_context_data[ctxt.0 as usize].outer_expn } fn outer_mark(&self, ctxt: SyntaxContext) -> (ExpnId, Transparency) { + debug_assert!(!self.syntax_context_data[ctxt.0 as usize].is_decode_placeholder()); let data = &self.syntax_context_data[ctxt.0 as usize]; (data.outer_expn, data.outer_transparency) } fn parent_ctxt(&self, ctxt: SyntaxContext) -> SyntaxContext { + debug_assert!(!self.syntax_context_data[ctxt.0 as usize].is_decode_placeholder()); self.syntax_context_data[ctxt.0 as usize].parent } @@ -551,6 +575,7 @@ impl HygieneData { transparency: Transparency, ) -> SyntaxContext { let syntax_context_data = &mut self.syntax_context_data; + debug_assert!(!syntax_context_data[ctxt.0 as usize].is_decode_placeholder()); let mut opaque = syntax_context_data[ctxt.0 as usize].opaque; let mut opaque_and_semitransparent = syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent; @@ -561,7 +586,7 @@ impl HygieneData { .syntax_context_map .entry((parent, expn_id, transparency)) .or_insert_with(|| { - let new_opaque = SyntaxContext(syntax_context_data.len() as u32); + let new_opaque = SyntaxContext::from_usize(syntax_context_data.len()); syntax_context_data.push(SyntaxContextData { outer_expn: expn_id, outer_transparency: transparency, @@ -581,7 +606,7 @@ impl HygieneData { .entry((parent, expn_id, transparency)) .or_insert_with(|| { let new_opaque_and_semitransparent = - SyntaxContext(syntax_context_data.len() as u32); + SyntaxContext::from_usize(syntax_context_data.len()); syntax_context_data.push(SyntaxContextData { outer_expn: expn_id, outer_transparency: transparency, @@ -596,8 +621,6 @@ impl HygieneData { let parent = ctxt; *self.syntax_context_map.entry((parent, expn_id, transparency)).or_insert_with(|| { - let new_opaque_and_semitransparent_and_transparent = - SyntaxContext(syntax_context_data.len() as u32); syntax_context_data.push(SyntaxContextData { outer_expn: expn_id, outer_transparency: transparency, @@ -606,7 +629,7 @@ impl HygieneData { opaque_and_semitransparent, dollar_crate_name: kw::DollarCrate, }); - new_opaque_and_semitransparent_and_transparent + SyntaxContext::from_usize(syntax_context_data.len() - 1) }) } } @@ -713,6 +736,10 @@ impl SyntaxContext { SyntaxContext(raw as u32) } + fn from_usize(raw: usize) -> SyntaxContext { + SyntaxContext(u32::try_from(raw).unwrap()) + } + /// Extend a syntax context with a given expansion and transparency. pub fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> SyntaxContext { HygieneData::with(|data| data.apply_mark(self, expn_id, transparency)) @@ -893,7 +920,10 @@ impl SyntaxContext { } pub(crate) fn dollar_crate_name(self) -> Symbol { - HygieneData::with(|data| data.syntax_context_data[self.0 as usize].dollar_crate_name) + HygieneData::with(|data| { + debug_assert!(!data.syntax_context_data[self.0 as usize].is_decode_placeholder()); + data.syntax_context_data[self.0 as usize].dollar_crate_name + }) } pub fn edition(self) -> Edition { @@ -1244,7 +1274,7 @@ impl HygieneEncodeContext { // Consume the current round of SyntaxContexts. // Drop the lock() temporary early - let latest_ctxts = { std::mem::take(&mut *self.latest_ctxts.lock()) }; + let latest_ctxts = { mem::take(&mut *self.latest_ctxts.lock()) }; // It's fine to iterate over a HashMap, because the serialization // of the table that we insert data into doesn't depend on insertion @@ -1256,7 +1286,7 @@ impl HygieneEncodeContext { } }); - let latest_expns = { std::mem::take(&mut *self.latest_expns.lock()) }; + let latest_expns = { mem::take(&mut *self.latest_expns.lock()) }; // Same as above, this is fine as we are inserting into a order-independent hashset #[allow(rustc::potential_query_instability)] @@ -1373,9 +1403,11 @@ pub fn decode_syntax_context SyntaxContext return SyntaxContext::root(); } - let ctxt = { + let pending_ctxt = { let mut inner = context.inner.lock(); + // Reminder: `HygieneDecodeContext` is per-crate, so there are no collisions between + // raw ids from different crate metadatas. if let Some(ctxt) = inner.remapped_ctxts.get(raw_id as usize).copied().flatten() { // This has already been decoded. return ctxt; @@ -1383,18 +1415,21 @@ pub fn decode_syntax_context SyntaxContext match inner.decoding.entry(raw_id) { Entry::Occupied(ctxt_entry) => { + let pending_ctxt = *ctxt_entry.get(); match context.local_in_progress.borrow_mut().entry(raw_id) { - SetEntry::Occupied(..) => { - // We're decoding this already on the current thread. Return here - // and let the function higher up the stack finish decoding to handle - // recursive cases. - return *ctxt_entry.get(); - } + // We're decoding this already on the current thread. Return here and let the + // function higher up the stack finish decoding to handle recursive cases. + // Hopefully having a `SyntaxContext` that refers to an incorrect data is ok + // during reminder of the decoding process, it's certainly not ok after the + // top level decoding function returns. + SetEntry::Occupied(..) => return pending_ctxt, + // Some other thread is currently decoding this. + // Race with it (alternatively we could wait here). + // We cannot return this value, unlike in the recursive case above, because it + // may expose a `SyntaxContext` pointing to incorrect data to arbitrary code. SetEntry::Vacant(entry) => { entry.insert(); - - // Some other thread is current decoding this. Race with it. - *ctxt_entry.get() + pending_ctxt } } } @@ -1405,18 +1440,10 @@ pub fn decode_syntax_context SyntaxContext // Allocate and store SyntaxContext id *before* calling the decoder function, // as the SyntaxContextData may reference itself. let new_ctxt = HygieneData::with(|hygiene_data| { - let new_ctxt = SyntaxContext(hygiene_data.syntax_context_data.len() as u32); // Push a dummy SyntaxContextData to ensure that nobody else can get the - // same ID as us. This will be overwritten after call `decode_Data` - hygiene_data.syntax_context_data.push(SyntaxContextData { - outer_expn: ExpnId::root(), - outer_transparency: Transparency::Transparent, - parent: SyntaxContext::root(), - opaque: SyntaxContext::root(), - opaque_and_semitransparent: SyntaxContext::root(), - dollar_crate_name: kw::Empty, - }); - new_ctxt + // same ID as us. This will be overwritten after call `decode_data`. + hygiene_data.syntax_context_data.push(SyntaxContextData::decode_placeholder()); + SyntaxContext::from_usize(hygiene_data.syntax_context_data.len() - 1) }); entry.insert(new_ctxt); new_ctxt @@ -1426,27 +1453,38 @@ pub fn decode_syntax_context SyntaxContext // Don't try to decode data while holding the lock, since we need to // be able to recursively decode a SyntaxContext - let mut ctxt_data = decode_data(d, raw_id); - // Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names` - // We don't care what the encoding crate set this to - we want to resolve it - // from the perspective of the current compilation session - ctxt_data.dollar_crate_name = kw::DollarCrate; + let ctxt_data = decode_data(d, raw_id); - // Overwrite the dummy data with our decoded SyntaxContextData - HygieneData::with(|hygiene_data| { - if let Some(old) = hygiene_data.syntax_context_data.get(raw_id as usize) + let ctxt = HygieneData::with(|hygiene_data| { + let old = if let Some(old) = hygiene_data.syntax_context_data.get(raw_id as usize) && old.outer_expn == ctxt_data.outer_expn && old.outer_transparency == ctxt_data.outer_transparency && old.parent == ctxt_data.parent { - ctxt_data = old.clone(); + Some(old.clone()) + } else { + None + }; + // Overwrite its placeholder data with our decoded data. + let ctxt_data_ref = &mut hygiene_data.syntax_context_data[pending_ctxt.as_u32() as usize]; + let prev_ctxt_data = mem::replace(ctxt_data_ref, ctxt_data); + // Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names`. + // We don't care what the encoding crate set this to - we want to resolve it + // from the perspective of the current compilation session + ctxt_data_ref.dollar_crate_name = kw::DollarCrate; + if let Some(old) = old { + *ctxt_data_ref = old; } - - hygiene_data.syntax_context_data[ctxt.as_u32() as usize] = ctxt_data; + // Make sure nothing weird happened while `decode_data` was running. + if !prev_ctxt_data.is_decode_placeholder() { + // Another thread may have already inserted the decoded data, + // but the decoded data should match. + assert_eq!(prev_ctxt_data, *ctxt_data_ref); + } + pending_ctxt }); // Mark the context as completed - context.local_in_progress.borrow_mut().remove(&raw_id); let mut inner = context.inner.lock(); From 6e1effe948525538427b2a6932f1619d74776cef Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 13 Sep 2024 23:08:37 +0300 Subject: [PATCH 214/745] hygiene: Ensure uniqueness of `SyntaxContextData`s --- compiler/rustc_span/src/hygiene.rs | 60 +++++++++++++++++------------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index b872f5e9d38f..36ecbe1cb78c 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -93,6 +93,10 @@ impl SyntaxContextData { fn is_decode_placeholder(&self) -> bool { self.dollar_crate_name == kw::Empty } + + fn key(&self) -> SyntaxContextKey { + (self.parent, self.outer_expn, self.outer_transparency) + } } rustc_index::newtype_index! { @@ -395,7 +399,7 @@ impl HygieneData { expn_hash_to_expn_id: iter::once((ExpnHash(Fingerprint::ZERO), ExpnId::root())) .collect(), syntax_context_data: vec![root_ctxt_data], - syntax_context_map: FxHashMap::default(), + syntax_context_map: iter::once((root_ctxt_data.key(), SyntaxContext(0))).collect(), expn_data_disambiguators: UnhashMap::default(), } } @@ -1454,34 +1458,38 @@ pub fn decode_syntax_context SyntaxContext // Don't try to decode data while holding the lock, since we need to // be able to recursively decode a SyntaxContext let ctxt_data = decode_data(d, raw_id); + let ctxt_key = ctxt_data.key(); let ctxt = HygieneData::with(|hygiene_data| { - let old = if let Some(old) = hygiene_data.syntax_context_data.get(raw_id as usize) - && old.outer_expn == ctxt_data.outer_expn - && old.outer_transparency == ctxt_data.outer_transparency - && old.parent == ctxt_data.parent - { - Some(old.clone()) - } else { - None - }; - // Overwrite its placeholder data with our decoded data. - let ctxt_data_ref = &mut hygiene_data.syntax_context_data[pending_ctxt.as_u32() as usize]; - let prev_ctxt_data = mem::replace(ctxt_data_ref, ctxt_data); - // Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names`. - // We don't care what the encoding crate set this to - we want to resolve it - // from the perspective of the current compilation session - ctxt_data_ref.dollar_crate_name = kw::DollarCrate; - if let Some(old) = old { - *ctxt_data_ref = old; + match hygiene_data.syntax_context_map.get(&ctxt_key) { + // Ensure that syntax contexts are unique. + // If syntax contexts with the given key already exists, reuse it instead of + // using `pending_ctxt`. + // `pending_ctxt` will leave an unused hole in the vector of syntax contexts. + // Hopefully its value isn't stored anywhere during decoding and its dummy data + // is never accessed later. The `is_decode_placeholder` asserts on all + // accesses to syntax context data attempt to ensure it. + Some(&ctxt) => ctxt, + // This is a completely new context. + // Overwrite its placeholder data with our decoded data. + None => { + let ctxt_data_ref = + &mut hygiene_data.syntax_context_data[pending_ctxt.as_u32() as usize]; + let prev_ctxt_data = mem::replace(ctxt_data_ref, ctxt_data); + // Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names`. + // We don't care what the encoding crate set this to - we want to resolve it + // from the perspective of the current compilation session. + ctxt_data_ref.dollar_crate_name = kw::DollarCrate; + // Make sure nothing weird happened while `decode_data` was running. + if !prev_ctxt_data.is_decode_placeholder() { + // Another thread may have already inserted the decoded data, + // but the decoded data should match. + assert_eq!(prev_ctxt_data, *ctxt_data_ref); + } + hygiene_data.syntax_context_map.insert(ctxt_key, pending_ctxt); + pending_ctxt + } } - // Make sure nothing weird happened while `decode_data` was running. - if !prev_ctxt_data.is_decode_placeholder() { - // Another thread may have already inserted the decoded data, - // but the decoded data should match. - assert_eq!(prev_ctxt_data, *ctxt_data_ref); - } - pending_ctxt }); // Mark the context as completed From 07328d5d408f707f92c4208cb5d4042af981ff43 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 15 Mar 2025 02:54:53 +0300 Subject: [PATCH 215/745] hygiene: Update `$crate` pretty-printing to account for holes in syntax contexts --- compiler/rustc_span/src/hygiene.rs | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 36ecbe1cb78c..4390085cd049 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -653,25 +653,26 @@ pub fn walk_chain_collapsed(span: Span, to: Span) -> Span { pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symbol) { // The new contexts that need updating are at the end of the list and have `$crate` as a name. - let (len, to_update) = HygieneData::with(|data| { - ( - data.syntax_context_data.len(), - data.syntax_context_data - .iter() - .rev() - .take_while(|scdata| scdata.dollar_crate_name == kw::DollarCrate) - .count(), - ) + // Also decoding placeholders can be encountered among both old and new contexts. + let mut to_update = vec![]; + HygieneData::with(|data| { + for (idx, scdata) in data.syntax_context_data.iter().enumerate().rev() { + if scdata.dollar_crate_name == kw::DollarCrate { + to_update.push((idx, kw::DollarCrate)); + } else if !scdata.is_decode_placeholder() { + break; + } + } }); // The callback must be called from outside of the `HygieneData` lock, // since it will try to acquire it too. - let range_to_update = len - to_update..len; - let names: Vec<_> = - range_to_update.clone().map(|idx| get_name(SyntaxContext::from_u32(idx as u32))).collect(); + for (idx, name) in &mut to_update { + *name = get_name(SyntaxContext::from_usize(*idx)); + } HygieneData::with(|data| { - range_to_update.zip(names).for_each(|(idx, name)| { + for (idx, name) in to_update { data.syntax_context_data[idx].dollar_crate_name = name; - }) + } }) } From e1388bfb036d1511587dd75e917038b9080a43d1 Mon Sep 17 00:00:00 2001 From: okaneco <47607823+okaneco@users.noreply.github.com> Date: Sat, 15 Mar 2025 13:54:40 -0400 Subject: [PATCH 216/745] core/slice: Mark some `split_off` variants unstably const Introduce feature `const_split_off_first_last` Mark `split_off_first`, `split_off_first_mut`, `split_off_last`, and `split_off_last_mut` unstably const --- library/core/src/slice/mod.rs | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 3570d8d08766..abc1d6935731 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -4446,8 +4446,10 @@ impl [T] { /// ``` #[inline] #[stable(feature = "slice_take", since = "CURRENT_RUSTC_VERSION")] - pub fn split_off_first<'a>(self: &mut &'a Self) -> Option<&'a T> { - let (first, rem) = self.split_first()?; + #[rustc_const_unstable(feature = "const_split_off_first_last", issue = "138539")] + pub const fn split_off_first<'a>(self: &mut &'a Self) -> Option<&'a T> { + // FIXME(const-hack): Use `?` when available in const instead of `let-else`. + let Some((first, rem)) = self.split_first() else { return None }; *self = rem; Some(first) } @@ -4469,8 +4471,11 @@ impl [T] { /// ``` #[inline] #[stable(feature = "slice_take", since = "CURRENT_RUSTC_VERSION")] - pub fn split_off_first_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> { - let (first, rem) = mem::take(self).split_first_mut()?; + #[rustc_const_unstable(feature = "const_split_off_first_last", issue = "138539")] + pub const fn split_off_first_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> { + // FIXME(const-hack): Use `mem::take` and `?` when available in const. + // Original: `mem::take(self).split_first_mut()?` + let Some((first, rem)) = mem::replace(self, &mut []).split_first_mut() else { return None }; *self = rem; Some(first) } @@ -4491,8 +4496,10 @@ impl [T] { /// ``` #[inline] #[stable(feature = "slice_take", since = "CURRENT_RUSTC_VERSION")] - pub fn split_off_last<'a>(self: &mut &'a Self) -> Option<&'a T> { - let (last, rem) = self.split_last()?; + #[rustc_const_unstable(feature = "const_split_off_first_last", issue = "138539")] + pub const fn split_off_last<'a>(self: &mut &'a Self) -> Option<&'a T> { + // FIXME(const-hack): Use `?` when available in const instead of `let-else`. + let Some((last, rem)) = self.split_last() else { return None }; *self = rem; Some(last) } @@ -4514,8 +4521,11 @@ impl [T] { /// ``` #[inline] #[stable(feature = "slice_take", since = "CURRENT_RUSTC_VERSION")] - pub fn split_off_last_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> { - let (last, rem) = mem::take(self).split_last_mut()?; + #[rustc_const_unstable(feature = "const_split_off_first_last", issue = "138539")] + pub const fn split_off_last_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> { + // FIXME(const-hack): Use `mem::take` and `?` when available in const. + // Original: `mem::take(self).split_last_mut()?` + let Some((last, rem)) = mem::replace(self, &mut []).split_last_mut() else { return None }; *self = rem; Some(last) } From 1cdddd67a333fd8e70334395ad33694a575037b4 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 26 Feb 2025 17:40:06 -0800 Subject: [PATCH 217/745] Add MIR pre-codegen tests to track 138544 --- tests/mir-opt/pre-codegen/checked_ops.rs | 39 ++++++++++- ...b_at_home.PreCodegen.after.panic-abort.mir | 48 +++++++++++++ ..._at_home.PreCodegen.after.panic-unwind.mir | 48 +++++++++++++ ...ecked_sub.PreCodegen.after.panic-abort.mir | 44 ++++++++++++ ...cked_sub.PreCodegen.after.panic-unwind.mir | 44 ++++++++++++ ...mple_option_map.ezmap.PreCodegen.after.mir | 2 +- ...map_via_question_mark.PreCodegen.after.mir | 70 +++++++++++++++++++ .../mir-opt/pre-codegen/simple_option_map.rs | 24 ++++++- 8 files changed, 315 insertions(+), 4 deletions(-) create mode 100644 tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-abort.mir create mode 100644 tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-unwind.mir create mode 100644 tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-abort.mir create mode 100644 tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-unwind.mir create mode 100644 tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir diff --git a/tests/mir-opt/pre-codegen/checked_ops.rs b/tests/mir-opt/pre-codegen/checked_ops.rs index 56f8e3f83384..8fd340503f54 100644 --- a/tests/mir-opt/pre-codegen/checked_ops.rs +++ b/tests/mir-opt/pre-codegen/checked_ops.rs @@ -1,4 +1,3 @@ -// skip-filecheck //@ compile-flags: -O -Zmir-opt-level=2 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY @@ -8,10 +7,48 @@ // EMIT_MIR checked_ops.step_forward.PreCodegen.after.mir pub fn step_forward(x: u16, n: usize) -> u16 { // This uses `u16` so that the conversion to usize is always widening. + + // CHECK-LABEL: fn step_forward + // CHECK: inlined{{.+}}forward std::iter::Step::forward(x, n) } // EMIT_MIR checked_ops.checked_shl.PreCodegen.after.mir pub fn checked_shl(x: u32, rhs: u32) -> Option { + // CHECK-LABEL: fn checked_shl + // CHECK: [[TEMP:_[0-9]+]] = ShlUnchecked(copy _1, copy _2) + // CHECK: _0 = Option::::Some({{move|copy}} [[TEMP]]) x.checked_shl(rhs) } + +// EMIT_MIR checked_ops.use_checked_sub.PreCodegen.after.mir +pub fn use_checked_sub(x: u32, rhs: u32) { + // We want this to be equivalent to open-coding it, leaving no `Option`s around. + // FIXME(#138544): It's not yet. + + // CHECK-LABEL: fn use_checked_sub + // CHECK: inlined{{.+}}u32{{.+}}checked_sub + // CHECK: [[DELTA:_[0-9]+]] = SubUnchecked(copy _1, copy _2) + // CHECK: [[TEMP1:_.+]] = Option::::Some(move [[DELTA]]); + // CHECK: [[TEMP2:_.+]] = {{move|copy}} (([[TEMP1]] as Some).0: u32); + // CHECK: do_something({{move|copy}} [[TEMP2]]) + if let Some(delta) = x.checked_sub(rhs) { + do_something(delta); + } +} + +// EMIT_MIR checked_ops.saturating_sub_at_home.PreCodegen.after.mir +pub fn saturating_sub_at_home(lhs: u32, rhs: u32) -> u32 { + // FIXME(#138544): Similarly here, the `Option` ought to optimize away + + // CHECK-LABEL: fn saturating_sub_at_home + // CHECK: [[DELTA:_[0-9]+]] = SubUnchecked(copy _1, copy _2) + // CHECK: [[TEMP1:_.+]] = Option::::Some({{move|copy}} [[DELTA]]); + // CHECK: [[TEMP2:_.+]] = {{move|copy}} (([[TEMP1]] as Some).0: u32); + // CHECK: _0 = {{move|copy}} [[TEMP2]]; + u32::checked_sub(lhs, rhs).unwrap_or(0) +} + +unsafe extern "Rust" { + safe fn do_something(_: u32); +} diff --git a/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-abort.mir new file mode 100644 index 000000000000..5b4fdeda8573 --- /dev/null +++ b/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-abort.mir @@ -0,0 +1,48 @@ +// MIR for `saturating_sub_at_home` after PreCodegen + +fn saturating_sub_at_home(_1: u32, _2: u32) -> u32 { + debug lhs => _1; + debug rhs => _2; + let mut _0: u32; + let mut _5: std::option::Option; + scope 1 (inlined core::num::::checked_sub) { + let mut _3: bool; + let mut _4: u32; + } + scope 2 (inlined Option::::unwrap_or) { + let _6: u32; + scope 3 { + } + } + + bb0: { + StorageLive(_5); + StorageLive(_3); + _3 = Lt(copy _1, copy _2); + switchInt(move _3) -> [0: bb1, otherwise: bb2]; + } + + bb1: { + StorageLive(_4); + _4 = SubUnchecked(copy _1, copy _2); + _5 = Option::::Some(move _4); + StorageDead(_4); + StorageDead(_3); + StorageLive(_6); + _6 = move ((_5 as Some).0: u32); + _0 = move _6; + StorageDead(_6); + goto -> bb3; + } + + bb2: { + StorageDead(_3); + _0 = const 0_u32; + goto -> bb3; + } + + bb3: { + StorageDead(_5); + return; + } +} diff --git a/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-unwind.mir new file mode 100644 index 000000000000..5b4fdeda8573 --- /dev/null +++ b/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-unwind.mir @@ -0,0 +1,48 @@ +// MIR for `saturating_sub_at_home` after PreCodegen + +fn saturating_sub_at_home(_1: u32, _2: u32) -> u32 { + debug lhs => _1; + debug rhs => _2; + let mut _0: u32; + let mut _5: std::option::Option; + scope 1 (inlined core::num::::checked_sub) { + let mut _3: bool; + let mut _4: u32; + } + scope 2 (inlined Option::::unwrap_or) { + let _6: u32; + scope 3 { + } + } + + bb0: { + StorageLive(_5); + StorageLive(_3); + _3 = Lt(copy _1, copy _2); + switchInt(move _3) -> [0: bb1, otherwise: bb2]; + } + + bb1: { + StorageLive(_4); + _4 = SubUnchecked(copy _1, copy _2); + _5 = Option::::Some(move _4); + StorageDead(_4); + StorageDead(_3); + StorageLive(_6); + _6 = move ((_5 as Some).0: u32); + _0 = move _6; + StorageDead(_6); + goto -> bb3; + } + + bb2: { + StorageDead(_3); + _0 = const 0_u32; + goto -> bb3; + } + + bb3: { + StorageDead(_5); + return; + } +} diff --git a/tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-abort.mir new file mode 100644 index 000000000000..3c475cd40309 --- /dev/null +++ b/tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-abort.mir @@ -0,0 +1,44 @@ +// MIR for `use_checked_sub` after PreCodegen + +fn use_checked_sub(_1: u32, _2: u32) -> () { + debug x => _1; + debug rhs => _2; + let mut _0: (); + let mut _5: std::option::Option; + let _7: (); + scope 1 { + debug delta => _6; + let _6: u32; + scope 2 (inlined core::num::::checked_sub) { + let mut _3: bool; + let mut _4: u32; + } + } + + bb0: { + StorageLive(_5); + StorageLive(_3); + _3 = Lt(copy _1, copy _2); + switchInt(move _3) -> [0: bb1, otherwise: bb2]; + } + + bb1: { + StorageLive(_4); + _4 = SubUnchecked(copy _1, copy _2); + _5 = Option::::Some(move _4); + StorageDead(_4); + StorageDead(_3); + _6 = copy ((_5 as Some).0: u32); + _7 = do_something(move _6) -> [return: bb3, unwind unreachable]; + } + + bb2: { + StorageDead(_3); + goto -> bb3; + } + + bb3: { + StorageDead(_5); + return; + } +} diff --git a/tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-unwind.mir new file mode 100644 index 000000000000..3ef09764b1c5 --- /dev/null +++ b/tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-unwind.mir @@ -0,0 +1,44 @@ +// MIR for `use_checked_sub` after PreCodegen + +fn use_checked_sub(_1: u32, _2: u32) -> () { + debug x => _1; + debug rhs => _2; + let mut _0: (); + let mut _5: std::option::Option; + let _7: (); + scope 1 { + debug delta => _6; + let _6: u32; + scope 2 (inlined core::num::::checked_sub) { + let mut _3: bool; + let mut _4: u32; + } + } + + bb0: { + StorageLive(_5); + StorageLive(_3); + _3 = Lt(copy _1, copy _2); + switchInt(move _3) -> [0: bb1, otherwise: bb2]; + } + + bb1: { + StorageLive(_4); + _4 = SubUnchecked(copy _1, copy _2); + _5 = Option::::Some(move _4); + StorageDead(_4); + StorageDead(_3); + _6 = copy ((_5 as Some).0: u32); + _7 = do_something(move _6) -> [return: bb3, unwind continue]; + } + + bb2: { + StorageDead(_3); + goto -> bb3; + } + + bb3: { + StorageDead(_5); + return; + } +} diff --git a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir index cbfc58194cc1..7595ad88d9df 100644 --- a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir @@ -3,7 +3,7 @@ fn ezmap(_1: Option) -> Option { debug x => _1; let mut _0: std::option::Option; - scope 1 (inlined map::) { + scope 1 (inlined map::) { let mut _2: isize; let _3: i32; let mut _4: i32; diff --git a/tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir new file mode 100644 index 000000000000..b921b96966b2 --- /dev/null +++ b/tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir @@ -0,0 +1,70 @@ +// MIR for `map_via_question_mark` after PreCodegen + +fn map_via_question_mark(_1: Option) -> Option { + debug x => _1; + let mut _0: std::option::Option; + let mut _4: std::ops::ControlFlow, i32>; + let _5: i32; + let mut _6: i32; + scope 1 { + debug residual => const Option::::None; + scope 2 { + scope 7 (inlined as FromResidual>>::from_residual) { + } + } + } + scope 3 { + debug val => _5; + scope 4 { + } + } + scope 5 (inlined as Try>::branch) { + let mut _2: isize; + let _3: i32; + scope 6 { + } + } + + bb0: { + StorageLive(_6); + StorageLive(_4); + StorageLive(_2); + StorageLive(_3); + _2 = discriminant(_1); + switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb4]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); + _0 = const Option::::None; + StorageDead(_6); + StorageDead(_4); + goto -> bb3; + } + + bb2: { + _3 = copy ((_1 as Some).0: i32); + _4 = ControlFlow::, i32>::Continue(copy _3); + StorageDead(_3); + StorageDead(_2); + _5 = copy ((_4 as Continue).0: i32); + _6 = Add(copy _5, const 1_i32); + _0 = Option::::Some(move _6); + StorageDead(_6); + StorageDead(_4); + goto -> bb3; + } + + bb3: { + return; + } + + bb4: { + unreachable; + } +} + +ALLOC0 (size: 8, align: 4) { + 00 00 00 00 __ __ __ __ │ ....░░░░ +} diff --git a/tests/mir-opt/pre-codegen/simple_option_map.rs b/tests/mir-opt/pre-codegen/simple_option_map.rs index 0c432be0419b..f0d7b51a6439 100644 --- a/tests/mir-opt/pre-codegen/simple_option_map.rs +++ b/tests/mir-opt/pre-codegen/simple_option_map.rs @@ -1,7 +1,6 @@ -// skip-filecheck //@ compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 -#[inline(always)] +#[inline] fn map(slf: Option, f: F) -> Option where F: FnOnce(T) -> U, @@ -14,9 +13,30 @@ where // EMIT_MIR simple_option_map.ezmap.PreCodegen.after.mir pub fn ezmap(x: Option) -> Option { + // We expect this to all be inlined, as though it was written without the + // combinator and without the closure, using just a plain match. + + // CHECK-LABEL: fn ezmap + // CHECK: [[INNER:_.+]] = copy ((_1 as Some).0: i32); + // CHECK: [[SUCC:_.+]] = Add({{copy|move}} [[INNER]], const 1_i32); + // CHECK: _0 = Option::::Some({{copy|move}} [[SUCC]]); map(x, |n| n + 1) } +// EMIT_MIR simple_option_map.map_via_question_mark.PreCodegen.after.mir +pub fn map_via_question_mark(x: Option) -> Option { + // FIXME(#138544): Ideally this would optimize out the `ControlFlow` local. + + // CHECK-LABEL: fn map_via_question_mark + // CHECK: [[INNER:_.+]] = copy ((_1 as Some).0: i32); + // CHECK: [[TEMP1:_.+]] = ControlFlow::, i32>::Continue(copy [[INNER]]); + // CHECK: [[TEMP2:_.+]] = copy (([[TEMP1]] as Continue).0: i32); + // CHECK: [[SUCC:_.+]] = Add({{copy|move}} [[TEMP2]], const 1_i32); + // CHECK: _0 = Option::::Some({{copy|move}} [[SUCC]]); + Some(x? + 1) +} + fn main() { assert_eq!(None, ezmap(None)); + assert_eq!(None, map_via_question_mark(None)); } From 4e9caa3985dba0aee3b9c12851250854d06694d2 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 15 Mar 2025 15:59:24 -0700 Subject: [PATCH 218/745] question_mark: suggest `as_ref`/`as_mut` if ref binding is used --- clippy_lints/src/question_mark.rs | 43 ++++++++++++++++++++++++++++-- tests/ui/question_mark.fixed | 34 ++++++++++++++++++++++++ tests/ui/question_mark.rs | 44 +++++++++++++++++++++++++++++++ tests/ui/question_mark.stderr | 42 ++++++++++++++++++++++++++++- 4 files changed, 160 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 4f5f3eb6c15a..5d5b3bf44abb 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -145,8 +145,47 @@ fn check_let_some_else_return_none(cx: &LateContext<'_>, stmt: &Stmt<'_>) { { let mut applicability = Applicability::MaybeIncorrect; let init_expr_str = snippet_with_applicability(cx, init_expr.span, "..", &mut applicability); - let receiver_str = snippet_with_applicability(cx, inner_pat.span, "..", &mut applicability); - let sugg = format!("let {receiver_str} = {init_expr_str}?;",); + // Take care when binding is `ref` + let sugg = if let PatKind::Binding( + BindingMode(ByRef::Yes(ref_mutability), binding_mutability), + _hir_id, + ident, + subpattern, + ) = inner_pat.kind + { + let (from_method, replace_to) = match ref_mutability { + Mutability::Mut => (".as_mut()", "&mut "), + Mutability::Not => (".as_ref()", "&"), + }; + + let mutability_str = match binding_mutability { + Mutability::Mut => "mut ", + Mutability::Not => "", + }; + + // Handle subpattern (@ subpattern) + let maybe_subpattern = match subpattern { + Some(Pat { + kind: PatKind::Binding(BindingMode(ByRef::Yes(_), _), _, subident, None), + .. + }) => { + // avoid `&ref` + // note that, because you can't have aliased, mutable references, we don't have to worry about + // the outer and inner mutability being different + format!(" @ {subident}") + }, + Some(subpattern) => { + let substr = snippet_with_applicability(cx, subpattern.span, "..", &mut applicability); + format!(" @ {replace_to}{substr}") + }, + None => String::new(), + }; + + format!("let {mutability_str}{ident}{maybe_subpattern} = {init_expr_str}{from_method}?;") + } else { + let receiver_str = snippet_with_applicability(cx, inner_pat.span, "..", &mut applicability); + format!("let {receiver_str} = {init_expr_str}?;") + }; span_lint_and_sugg( cx, QUESTION_MARK, diff --git a/tests/ui/question_mark.fixed b/tests/ui/question_mark.fixed index 8dfef3202be9..41e3910ad486 100644 --- a/tests/ui/question_mark.fixed +++ b/tests/ui/question_mark.fixed @@ -375,3 +375,37 @@ fn issue12412(foo: &Foo, bar: &Bar) -> Option<()> { //~^^^ question_mark Some(()) } + +struct StructWithOptionString { + opt_x: Option, +} + +struct WrapperStructWithString(String); + +#[allow(clippy::disallowed_names)] +fn issue_13417(foo: &mut StructWithOptionString) -> Option { + let x = foo.opt_x.as_ref()?; + //~^^^ question_mark + let opt_y = Some(x.clone()); + std::mem::replace(&mut foo.opt_x, opt_y) +} + +#[allow(clippy::disallowed_names)] +fn issue_13417_mut(foo: &mut StructWithOptionString) -> Option { + let x = foo.opt_x.as_mut()?; + //~^^^ question_mark + let opt_y = Some(x.clone()); + std::mem::replace(&mut foo.opt_x, opt_y) +} + +#[allow(clippy::disallowed_names)] +#[allow(unused)] +fn issue_13417_weirder(foo: &mut StructWithOptionString, mut bar: Option) -> Option<()> { + let x @ y = foo.opt_x.as_ref()?; + //~^^^ question_mark + let x @ &WrapperStructWithString(_) = bar.as_ref()?; + //~^^^ question_mark + let x @ &mut WrapperStructWithString(_) = bar.as_mut()?; + //~^^^ question_mark + Some(()) +} diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs index fffaa803f39c..e570788bfdf1 100644 --- a/tests/ui/question_mark.rs +++ b/tests/ui/question_mark.rs @@ -452,3 +452,47 @@ fn issue12412(foo: &Foo, bar: &Bar) -> Option<()> { //~^^^ question_mark Some(()) } + +struct StructWithOptionString { + opt_x: Option, +} + +struct WrapperStructWithString(String); + +#[allow(clippy::disallowed_names)] +fn issue_13417(foo: &mut StructWithOptionString) -> Option { + let Some(ref x) = foo.opt_x else { + return None; + }; + //~^^^ question_mark + let opt_y = Some(x.clone()); + std::mem::replace(&mut foo.opt_x, opt_y) +} + +#[allow(clippy::disallowed_names)] +fn issue_13417_mut(foo: &mut StructWithOptionString) -> Option { + let Some(ref mut x) = foo.opt_x else { + return None; + }; + //~^^^ question_mark + let opt_y = Some(x.clone()); + std::mem::replace(&mut foo.opt_x, opt_y) +} + +#[allow(clippy::disallowed_names)] +#[allow(unused)] +fn issue_13417_weirder(foo: &mut StructWithOptionString, mut bar: Option) -> Option<()> { + let Some(ref x @ ref y) = foo.opt_x else { + return None; + }; + //~^^^ question_mark + let Some(ref x @ WrapperStructWithString(_)) = bar else { + return None; + }; + //~^^^ question_mark + let Some(ref mut x @ WrapperStructWithString(_)) = bar else { + return None; + }; + //~^^^ question_mark + Some(()) +} diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr index c4db0fbc3022..7c80878fe817 100644 --- a/tests/ui/question_mark.stderr +++ b/tests/ui/question_mark.stderr @@ -215,5 +215,45 @@ LL | | return None; LL | | }; | |______^ help: replace it with: `let v = bar.foo.owned.clone()?;` -error: aborting due to 22 previous errors +error: this `let...else` may be rewritten with the `?` operator + --> tests/ui/question_mark.rs:464:5 + | +LL | / let Some(ref x) = foo.opt_x else { +LL | | return None; +LL | | }; + | |______^ help: replace it with: `let x = foo.opt_x.as_ref()?;` + +error: this `let...else` may be rewritten with the `?` operator + --> tests/ui/question_mark.rs:474:5 + | +LL | / let Some(ref mut x) = foo.opt_x else { +LL | | return None; +LL | | }; + | |______^ help: replace it with: `let x = foo.opt_x.as_mut()?;` + +error: this `let...else` may be rewritten with the `?` operator + --> tests/ui/question_mark.rs:485:5 + | +LL | / let Some(ref x @ ref y) = foo.opt_x else { +LL | | return None; +LL | | }; + | |______^ help: replace it with: `let x @ y = foo.opt_x.as_ref()?;` + +error: this `let...else` may be rewritten with the `?` operator + --> tests/ui/question_mark.rs:489:5 + | +LL | / let Some(ref x @ WrapperStructWithString(_)) = bar else { +LL | | return None; +LL | | }; + | |______^ help: replace it with: `let x @ &WrapperStructWithString(_) = bar.as_ref()?;` + +error: this `let...else` may be rewritten with the `?` operator + --> tests/ui/question_mark.rs:493:5 + | +LL | / let Some(ref mut x @ WrapperStructWithString(_)) = bar else { +LL | | return None; +LL | | }; + | |______^ help: replace it with: `let x @ &mut WrapperStructWithString(_) = bar.as_mut()?;` + +error: aborting due to 27 previous errors From 642634c39b00a4630e461b431cce0fc38a640b66 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sun, 16 Mar 2025 05:05:14 +0000 Subject: [PATCH 219/745] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index cc3d0cfc717b..94b593e0e326 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -d9e5539a39192028a7b15ae596a8685017faecee +9f274ba3997030a2b7656755a6810fd26cb709f3 From 9845b100ec70512b18a5cc2f9ddca9994287244b Mon Sep 17 00:00:00 2001 From: xFrednet Date: Sun, 16 Mar 2025 15:19:49 +0100 Subject: [PATCH 220/745] Remove `@xFrednet` from docs :wave: --- book/src/development/the_team.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/book/src/development/the_team.md b/book/src/development/the_team.md index 6bc0783b166a..da5d084ed97f 100644 --- a/book/src/development/the_team.md +++ b/book/src/development/the_team.md @@ -102,8 +102,7 @@ is responsible for maintaining Clippy. 5. **Update the changelog** - This needs to be done for every release, every six weeks. This is usually - done by @xFrednet. + This needs to be done for every release, every six weeks. ### Membership From 5bb37b7580aaab8578cb7bb30cf1a62cbfb85a27 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 16 Mar 2025 14:55:32 +0000 Subject: [PATCH 221/745] Fix usage of vector registers in inline asm on arm64 --- src/inline_asm.rs | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/inline_asm.rs b/src/inline_asm.rs index 310b226814d4..59d109341311 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -652,6 +652,20 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { .emit(&mut generated_asm, InlineAsmArch::X86_64, *modifier) .unwrap(), }, + InlineAsmArch::AArch64 => match reg { + InlineAsmReg::AArch64(reg) if reg.vreg_index().is_some() => { + // rustc emits v0 rather than q0 + reg.emit( + &mut generated_asm, + InlineAsmArch::AArch64, + Some(modifier.unwrap_or('q')), + ) + .unwrap() + } + _ => reg + .emit(&mut generated_asm, InlineAsmArch::AArch64, *modifier) + .unwrap(), + }, _ => reg.emit(&mut generated_asm, self.arch, *modifier).unwrap(), } } @@ -809,7 +823,13 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { } InlineAsmArch::AArch64 => { generated_asm.push_str(" str "); - reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap(); + match reg { + InlineAsmReg::AArch64(reg) if reg.vreg_index().is_some() => { + // rustc emits v0 rather than q0 + reg.emit(generated_asm, InlineAsmArch::AArch64, Some('q')).unwrap() + } + _ => reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap(), + } writeln!(generated_asm, ", [x19, 0x{:x}]", offset.bytes()).unwrap(); } InlineAsmArch::RiscV64 => { @@ -851,7 +871,13 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { } InlineAsmArch::AArch64 => { generated_asm.push_str(" ldr "); - reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap(); + match reg { + InlineAsmReg::AArch64(reg) if reg.vreg_index().is_some() => { + // rustc emits v0 rather than q0 + reg.emit(generated_asm, InlineAsmArch::AArch64, Some('q')).unwrap() + } + _ => reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap(), + } writeln!(generated_asm, ", [x19, 0x{:x}]", offset.bytes()).unwrap(); } InlineAsmArch::RiscV64 => { From 9eab0780657f79bbb44808ecc5c410abdfa0c011 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 22 Feb 2025 23:55:08 +0000 Subject: [PATCH 222/745] Suppress must_use in compiler and tools --- clippy_lints/src/loops/mut_range_bound.rs | 2 +- clippy_lints/src/methods/read_line_without_trim.rs | 2 +- clippy_lints/src/pass_by_ref_or_value.rs | 2 +- clippy_lints/src/unconditional_recursion.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/loops/mut_range_bound.rs b/clippy_lints/src/loops/mut_range_bound.rs index fb5d49a10047..5afcf51167d4 100644 --- a/clippy_lints/src/loops/mut_range_bound.rs +++ b/clippy_lints/src/loops/mut_range_bound.rs @@ -129,7 +129,7 @@ impl BreakAfterExprVisitor { }; get_enclosing_block(cx, hir_id).is_some_and(|block| { - visitor.visit_block(block); + let _ = visitor.visit_block(block); visitor.break_after_expr }) } diff --git a/clippy_lints/src/methods/read_line_without_trim.rs b/clippy_lints/src/methods/read_line_without_trim.rs index c9251c1b8497..fe999a3b5f8f 100644 --- a/clippy_lints/src/methods/read_line_without_trim.rs +++ b/clippy_lints/src/methods/read_line_without_trim.rs @@ -40,7 +40,7 @@ pub fn check(cx: &LateContext<'_>, call: &Expr<'_>, recv: &Expr<'_>, arg: &Expr< // We've checked that `call` is a call to `Stdin::read_line()` with the right receiver, // now let's check if the first use of the string passed to `::read_line()` // is used for operations that will always fail (e.g. parsing "6\n" into a number) - for_each_local_use_after_expr(cx, local_id, call.hir_id, |expr| { + let _ = for_each_local_use_after_expr(cx, local_id, call.hir_id, |expr| { if let Some(parent) = get_parent_expr(cx, expr) { let data = if let ExprKind::MethodCall(segment, recv, args, span) = parent.kind { if args.is_empty() diff --git a/clippy_lints/src/pass_by_ref_or_value.rs b/clippy_lints/src/pass_by_ref_or_value.rs index 320c0286bb7b..0a8e28856487 100644 --- a/clippy_lints/src/pass_by_ref_or_value.rs +++ b/clippy_lints/src/pass_by_ref_or_value.rs @@ -141,7 +141,7 @@ impl PassByRefOrValue { // Gather all the lifetimes found in the output type which may affect whether // `TRIVIALLY_COPY_PASS_BY_REF` should be linted. let mut output_regions = FxHashSet::default(); - for_each_top_level_late_bound_region(fn_sig.skip_binder().output(), |region| -> ControlFlow { + let _ = for_each_top_level_late_bound_region(fn_sig.skip_binder().output(), |region| -> ControlFlow { output_regions.insert(region); ControlFlow::Continue(()) }); diff --git a/clippy_lints/src/unconditional_recursion.rs b/clippy_lints/src/unconditional_recursion.rs index a443043bef90..51c7d6fce312 100644 --- a/clippy_lints/src/unconditional_recursion.rs +++ b/clippy_lints/src/unconditional_recursion.rs @@ -381,7 +381,7 @@ impl UnconditionalRecursion { implemented_ty_id, method_span, }; - walk_body(&mut c, body); + let _ = walk_body(&mut c, body); } } } From b23fcb0147d4c0c295cdf59fc092ebc435355081 Mon Sep 17 00:00:00 2001 From: tk <49250442+tkr-sh@users.noreply.github.com> Date: Sun, 16 Mar 2025 19:36:09 +0100 Subject: [PATCH 223/745] fix: bad indent in doc comments Sometimes, in doc comments, there are 3 spaces + 1 instead of 4 spaces + 1. To make it coherent with the rest of the clippy codebase, I `fd -t f -X sed -E -i 's,/// (\S),/// \1,g'` and manually verified and fixed the relevant part of code that had bad indentation. --- clippy_lints/src/ignored_unit_patterns.rs | 8 ++++---- clippy_lints/src/iter_not_returning_iterator.rs | 6 +++--- clippy_lints/src/loops/mod.rs | 2 +- clippy_lints/src/manual_ignore_case_cmp.rs | 2 +- clippy_lints/src/methods/mod.rs | 4 ++-- clippy_lints/src/missing_inline.rs | 10 +++++----- clippy_lints/src/needless_question_mark.rs | 2 +- clippy_lints/src/partialeq_ne_impl.rs | 4 ++-- clippy_lints/src/question_mark.rs | 2 +- clippy_lints/src/redundant_async_block.rs | 4 ++-- clippy_lints/src/redundant_locals.rs | 2 +- clippy_lints/src/unnecessary_semicolon.rs | 2 +- 12 files changed, 24 insertions(+), 24 deletions(-) diff --git a/clippy_lints/src/ignored_unit_patterns.rs b/clippy_lints/src/ignored_unit_patterns.rs index 54b8adbc8ac7..e4ace3bdabf0 100644 --- a/clippy_lints/src/ignored_unit_patterns.rs +++ b/clippy_lints/src/ignored_unit_patterns.rs @@ -17,15 +17,15 @@ declare_clippy_lint! { /// ### Example /// ```no_run /// match std::fs::create_dir("tmp-work-dir") { - /// Ok(_) => println!("Working directory created"), - /// Err(s) => eprintln!("Could not create directory: {s}"), + /// Ok(_) => println!("Working directory created"), + /// Err(s) => eprintln!("Could not create directory: {s}"), /// } /// ``` /// Use instead: /// ```no_run /// match std::fs::create_dir("tmp-work-dir") { - /// Ok(()) => println!("Working directory created"), - /// Err(s) => eprintln!("Could not create directory: {s}"), + /// Ok(()) => println!("Working directory created"), + /// Err(s) => eprintln!("Could not create directory: {s}"), /// } /// ``` #[clippy::version = "1.73.0"] diff --git a/clippy_lints/src/iter_not_returning_iterator.rs b/clippy_lints/src/iter_not_returning_iterator.rs index 4bc6ad0798c9..753360906d66 100644 --- a/clippy_lints/src/iter_not_returning_iterator.rs +++ b/clippy_lints/src/iter_not_returning_iterator.rs @@ -28,9 +28,9 @@ declare_clippy_lint! { /// use std::str::Chars; /// struct Data {} /// impl Data { - /// fn iter(&self) -> Chars<'static> { - /// todo!() - /// } + /// fn iter(&self) -> Chars<'static> { + /// todo!() + /// } /// } /// ``` #[clippy::version = "1.57.0"] diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs index ed725a039891..4b0bf5a4b3c9 100644 --- a/clippy_lints/src/loops/mod.rs +++ b/clippy_lints/src/loops/mod.rs @@ -469,7 +469,7 @@ declare_clippy_lint! { /// let item2 = 3; /// let mut vec: Vec = Vec::new(); /// for _ in 0..20 { - /// vec.push(item1); + /// vec.push(item1); /// } /// for _ in 0..30 { /// vec.push(item2); diff --git a/clippy_lints/src/manual_ignore_case_cmp.rs b/clippy_lints/src/manual_ignore_case_cmp.rs index 506f4f6d9de1..d92069edb6d0 100644 --- a/clippy_lints/src/manual_ignore_case_cmp.rs +++ b/clippy_lints/src/manual_ignore_case_cmp.rs @@ -29,7 +29,7 @@ declare_clippy_lint! { /// Use instead: /// ```no_run /// fn compare(a: &str, b: &str) -> bool { - /// a.eq_ignore_ascii_case(b) || a.eq_ignore_ascii_case("abc") + /// a.eq_ignore_ascii_case(b) || a.eq_ignore_ascii_case("abc") /// } /// ``` #[clippy::version = "1.84.0"] diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 94d3657d9f12..055991ee2951 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -4447,13 +4447,13 @@ declare_clippy_lint! { /// ### Example /// ```no_run /// fn foo(values: &[u8]) -> bool { - /// values.iter().any(|&v| v == 10) + /// values.iter().any(|&v| v == 10) /// } /// ``` /// Use instead: /// ```no_run /// fn foo(values: &[u8]) -> bool { - /// values.contains(&10) + /// values.contains(&10) /// } /// ``` #[clippy::version = "1.86.0"] diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index 3cf1a80607e8..0c6f51925e0c 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -37,7 +37,7 @@ declare_clippy_lint! { /// /// struct Baz; /// impl Baz { - /// fn private() {} // ok + /// fn private() {} // ok /// } /// /// impl Bar for Baz { @@ -46,13 +46,13 @@ declare_clippy_lint! { /// /// pub struct PubBaz; /// impl PubBaz { - /// fn private() {} // ok - /// pub fn not_private() {} // missing #[inline] + /// fn private() {} // ok + /// pub fn not_private() {} // missing #[inline] /// } /// /// impl Bar for PubBaz { - /// fn bar() {} // missing #[inline] - /// fn def_bar() {} // missing #[inline] + /// fn bar() {} // missing #[inline] + /// fn def_bar() {} // missing #[inline] /// } /// ``` /// diff --git a/clippy_lints/src/needless_question_mark.rs b/clippy_lints/src/needless_question_mark.rs index 37463cfec9a2..72b0a80260e9 100644 --- a/clippy_lints/src/needless_question_mark.rs +++ b/clippy_lints/src/needless_question_mark.rs @@ -40,7 +40,7 @@ declare_clippy_lint! { /// } /// /// fn f(to: TO) -> Option { - /// to.magic + /// to.magic /// } /// /// struct TR { diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index 55676522419c..65671b478ba7 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -19,8 +19,8 @@ declare_clippy_lint! { /// struct Foo; /// /// impl PartialEq for Foo { - /// fn eq(&self, other: &Foo) -> bool { true } - /// fn ne(&self, other: &Foo) -> bool { !(self == other) } + /// fn eq(&self, other: &Foo) -> bool { true } + /// fn ne(&self, other: &Foo) -> bool { !(self == other) } /// } /// ``` #[clippy::version = "pre 1.29.0"] diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 4f5f3eb6c15a..005bf8ce405f 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -230,7 +230,7 @@ fn expr_return_none_or_err( /// /// ```ignore /// if option.is_none() { -/// return None; +/// return None; /// } /// ``` /// diff --git a/clippy_lints/src/redundant_async_block.rs b/clippy_lints/src/redundant_async_block.rs index bc5e8fd2c258..8289ec47bc7e 100644 --- a/clippy_lints/src/redundant_async_block.rs +++ b/clippy_lints/src/redundant_async_block.rs @@ -23,7 +23,7 @@ declare_clippy_lint! { /// ### Example /// ```no_run /// let f = async { - /// 1 + 2 + /// 1 + 2 /// }; /// let fut = async { /// f.await @@ -32,7 +32,7 @@ declare_clippy_lint! { /// Use instead: /// ```no_run /// let f = async { - /// 1 + 2 + /// 1 + 2 /// }; /// let fut = f; /// ``` diff --git a/clippy_lints/src/redundant_locals.rs b/clippy_lints/src/redundant_locals.rs index defb6684cffb..8f33a47e2908 100644 --- a/clippy_lints/src/redundant_locals.rs +++ b/clippy_lints/src/redundant_locals.rs @@ -26,7 +26,7 @@ declare_clippy_lint! { /// let a = a; /// /// fn foo(b: i32) { - /// let b = b; + /// let b = b; /// } /// ``` /// Use instead: diff --git a/clippy_lints/src/unnecessary_semicolon.rs b/clippy_lints/src/unnecessary_semicolon.rs index e5267620c4fb..f1d1a76d0c2d 100644 --- a/clippy_lints/src/unnecessary_semicolon.rs +++ b/clippy_lints/src/unnecessary_semicolon.rs @@ -26,7 +26,7 @@ declare_clippy_lint! { /// ```no_run /// # let a: u32 = 42; /// if a > 10 { - /// println!("a is greater than 10"); + /// println!("a is greater than 10"); /// } /// ``` #[clippy::version = "1.86.0"] From b2fda93aacd2ad795199140068b9c8a055840b0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sun, 16 Mar 2025 20:42:37 +0100 Subject: [PATCH 224/745] Add a note to rustc-dev-guide --- src/doc/rustc-dev-guide/src/tests/ci.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/doc/rustc-dev-guide/src/tests/ci.md b/src/doc/rustc-dev-guide/src/tests/ci.md index 0c0f750a45d7..2af09a60513b 100644 --- a/src/doc/rustc-dev-guide/src/tests/ci.md +++ b/src/doc/rustc-dev-guide/src/tests/ci.md @@ -180,6 +180,8 @@ their results can be seen [here](https://github.com/rust-lang-ci/rust/actions), although usually you will be notified of the result by a comment made by bors on the corresponding PR. +Note that if you start the default try job using `@bors try`, it will skip building several `dist` components and running post-optimization tests, to make the build duration shorter. If you want to execute the full build as it would happen before a merge, add an explicit `try-job` pattern with the name of the default try job (currently `dist-x86_64-linux`). + Multiple try builds can execute concurrently across different PRs.
From aa2c24b03b893f7e65e1755a237ffe0387509b25 Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Sun, 9 Mar 2025 01:03:11 +0530 Subject: [PATCH 225/745] uefi: Add OwnedEvent abstraction - Events are going to become quite important for Networking, so needed owned abstractions. - Switch to OwnedEvent abstraction for Exit boot services event. Signed-off-by: Ayush Singh --- library/std/src/sys/pal/uefi/helpers.rs | 86 +++++++++++++++---------- library/std/src/sys/pal/uefi/mod.rs | 10 +-- 2 files changed, 58 insertions(+), 38 deletions(-) diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs index 0a2a8f5ef67b..a0433ddfd967 100644 --- a/library/std/src/sys/pal/uefi/helpers.rs +++ b/library/std/src/sys/pal/uefi/helpers.rs @@ -120,39 +120,6 @@ pub(crate) fn open_protocol( } } -pub(crate) fn create_event( - signal: u32, - tpl: efi::Tpl, - handler: Option, - context: *mut crate::ffi::c_void, -) -> io::Result> { - let boot_services: NonNull = - boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast(); - let mut event: r_efi::efi::Event = crate::ptr::null_mut(); - let r = unsafe { - let create_event = (*boot_services.as_ptr()).create_event; - (create_event)(signal, tpl, handler, context, &mut event) - }; - if r.is_error() { - Err(crate::io::Error::from_raw_os_error(r.as_usize())) - } else { - NonNull::new(event).ok_or(const_error!(io::ErrorKind::Other, "null protocol")) - } -} - -/// # SAFETY -/// - The supplied event must be valid -pub(crate) unsafe fn close_event(evt: NonNull) -> io::Result<()> { - let boot_services: NonNull = - boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast(); - let r = unsafe { - let close_event = (*boot_services.as_ptr()).close_event; - (close_event)(evt.as_ptr()) - }; - - if r.is_error() { Err(crate::io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) } -} - /// Gets the Protocol for current system handle. /// /// Note: Some protocols need to be manually freed. It is the caller's responsibility to do so. @@ -559,3 +526,56 @@ impl Drop for ServiceProtocol { } } } + +#[repr(transparent)] +pub(crate) struct OwnedEvent(NonNull); + +impl OwnedEvent { + pub(crate) fn new( + signal: u32, + tpl: efi::Tpl, + handler: Option, + context: Option>, + ) -> io::Result { + let boot_services: NonNull = + boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast(); + let mut event: r_efi::efi::Event = crate::ptr::null_mut(); + let context = context.map(NonNull::as_ptr).unwrap_or(crate::ptr::null_mut()); + + let r = unsafe { + let create_event = (*boot_services.as_ptr()).create_event; + (create_event)(signal, tpl, handler, context, &mut event) + }; + + if r.is_error() { + Err(crate::io::Error::from_raw_os_error(r.as_usize())) + } else { + NonNull::new(event) + .ok_or(const_error!(io::ErrorKind::Other, "failed to create event")) + .map(Self) + } + } + + pub(crate) fn into_raw(self) -> *mut crate::ffi::c_void { + let r = self.0.as_ptr(); + crate::mem::forget(self); + r + } + + /// SAFETY: Assumes that ptr is a non-null valid UEFI event + pub(crate) unsafe fn from_raw(ptr: *mut crate::ffi::c_void) -> Self { + Self(unsafe { NonNull::new_unchecked(ptr) }) + } +} + +impl Drop for OwnedEvent { + fn drop(&mut self) { + if let Some(boot_services) = boot_services() { + let bt: NonNull = boot_services.cast(); + unsafe { + let close_event = (*bt.as_ptr()).close_event; + (close_event)(self.0.as_ptr()) + }; + } + } +} diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs index 6a03e240c6bd..ed39130ab41b 100644 --- a/library/std/src/sys/pal/uefi/mod.rs +++ b/library/std/src/sys/pal/uefi/mod.rs @@ -49,17 +49,17 @@ pub(crate) unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) { unsafe { uefi::env::init_globals(image_handle, system_table) }; // Register exit boot services handler - match helpers::create_event( + match helpers::OwnedEvent::new( r_efi::efi::EVT_SIGNAL_EXIT_BOOT_SERVICES, r_efi::efi::TPL_NOTIFY, Some(exit_boot_service_handler), - crate::ptr::null_mut(), + None, ) { Ok(x) => { if EXIT_BOOT_SERVICE_EVENT .compare_exchange( crate::ptr::null_mut(), - x.as_ptr(), + x.into_raw(), Ordering::Release, Ordering::Acquire, ) @@ -79,7 +79,7 @@ pub unsafe fn cleanup() { if let Some(exit_boot_service_event) = NonNull::new(EXIT_BOOT_SERVICE_EVENT.swap(crate::ptr::null_mut(), Ordering::Acquire)) { - let _ = unsafe { helpers::close_event(exit_boot_service_event) }; + let _ = unsafe { helpers::OwnedEvent::from_raw(exit_boot_service_event.as_ptr()) }; } } @@ -145,7 +145,7 @@ pub fn abort_internal() -> ! { if let Some(exit_boot_service_event) = NonNull::new(EXIT_BOOT_SERVICE_EVENT.load(Ordering::Acquire)) { - let _ = unsafe { helpers::close_event(exit_boot_service_event) }; + let _ = unsafe { helpers::OwnedEvent::from_raw(exit_boot_service_event.as_ptr()) }; } if let (Some(boot_services), Some(handle)) = From f5ecb74bf9aa01201c5c7aa5dca16b3686a400e9 Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Sun, 16 Mar 2025 20:23:22 +0000 Subject: [PATCH 226/745] rustdoc-json: Add tests for `#[repr(...)]` Co-authored-by: Predrag Gruevski --- tests/rustdoc-json/attrs/repr_align.rs | 8 ++ tests/rustdoc-json/attrs/repr_c.rs | 18 +++++ tests/rustdoc-json/attrs/repr_combination.rs | 78 ++++++++++++++++++++ tests/rustdoc-json/attrs/repr_int_enum.rs | 19 +++++ tests/rustdoc-json/attrs/repr_packed.rs | 18 +++++ tests/rustdoc-json/attrs/repr_transparent.rs | 22 ++++++ 6 files changed, 163 insertions(+) create mode 100644 tests/rustdoc-json/attrs/repr_align.rs create mode 100644 tests/rustdoc-json/attrs/repr_c.rs create mode 100644 tests/rustdoc-json/attrs/repr_combination.rs create mode 100644 tests/rustdoc-json/attrs/repr_int_enum.rs create mode 100644 tests/rustdoc-json/attrs/repr_packed.rs create mode 100644 tests/rustdoc-json/attrs/repr_transparent.rs diff --git a/tests/rustdoc-json/attrs/repr_align.rs b/tests/rustdoc-json/attrs/repr_align.rs new file mode 100644 index 000000000000..bebbe1fea349 --- /dev/null +++ b/tests/rustdoc-json/attrs/repr_align.rs @@ -0,0 +1,8 @@ +#![no_std] + +//@ is "$.index[*][?(@.name=='Aligned')].attrs" '["#[attr = Repr([ReprAlign(Align(4 bytes))])]\n"]' +#[repr(align(4))] +pub struct Aligned { + a: i8, + b: i64, +} diff --git a/tests/rustdoc-json/attrs/repr_c.rs b/tests/rustdoc-json/attrs/repr_c.rs new file mode 100644 index 000000000000..609d33d94de7 --- /dev/null +++ b/tests/rustdoc-json/attrs/repr_c.rs @@ -0,0 +1,18 @@ +#![no_std] + +//@ is "$.index[*][?(@.name=='ReprCStruct')].attrs" '["#[attr = Repr([ReprC])]\n"]' +#[repr(C)] +pub struct ReprCStruct(pub i64); + +//@ is "$.index[*][?(@.name=='ReprCEnum')].attrs" '["#[attr = Repr([ReprC])]\n"]' +#[repr(C)] +pub enum ReprCEnum { + First, +} + +//@ is "$.index[*][?(@.name=='ReprCUnion')].attrs" '["#[attr = Repr([ReprC])]\n"]' +#[repr(C)] +pub union ReprCUnion { + pub left: i64, + pub right: u64, +} diff --git a/tests/rustdoc-json/attrs/repr_combination.rs b/tests/rustdoc-json/attrs/repr_combination.rs new file mode 100644 index 000000000000..662bfef67cb8 --- /dev/null +++ b/tests/rustdoc-json/attrs/repr_combination.rs @@ -0,0 +1,78 @@ +#![no_std] + +// Combinations of `#[repr(..)]` attributes. + +//@ is "$.index[*][?(@.name=='ReprCI8')].attrs" '["#[attr = Repr([ReprC, ReprInt(SignedInt(I8))])]\n"]' +#[repr(C, i8)] +pub enum ReprCI8 { + First, +} + +//@ is "$.index[*][?(@.name=='SeparateReprCI16')].attrs" '["#[attr = Repr([ReprC, ReprInt(SignedInt(I16))])]\n"]' +#[repr(C)] +#[repr(i16)] +pub enum SeparateReprCI16 { + First, +} + +//@ is "$.index[*][?(@.name=='ReversedReprCUsize')].attrs" '["#[attr = Repr([ReprInt(UnsignedInt(Usize)), ReprC])]\n"]' +#[repr(usize, C)] +pub enum ReversedReprCUsize { + First, +} + +//@ is "$.index[*][?(@.name=='ReprCPacked')].attrs" '["#[attr = Repr([ReprC, ReprPacked(Align(1 bytes))])]\n"]' +#[repr(C, packed)] +pub struct ReprCPacked { + a: i8, + b: i64, +} + +//@ is "$.index[*][?(@.name=='SeparateReprCPacked')].attrs" '["#[attr = Repr([ReprC, ReprPacked(Align(2 bytes))])]\n"]' +#[repr(C)] +#[repr(packed(2))] +pub struct SeparateReprCPacked { + a: i8, + b: i64, +} + +//@ is "$.index[*][?(@.name=='ReversedReprCPacked')].attrs" '["#[attr = Repr([ReprPacked(Align(2 bytes)), ReprC])]\n"]' +#[repr(packed(2), C)] +pub struct ReversedReprCPacked { + a: i8, + b: i64, +} + +//@ is "$.index[*][?(@.name=='ReprCAlign')].attrs" '["#[attr = Repr([ReprC, ReprAlign(Align(16 bytes))])]\n"]' +#[repr(C, align(16))] +pub struct ReprCAlign { + a: i8, + b: i64, +} + +//@ is "$.index[*][?(@.name=='SeparateReprCAlign')].attrs" '["#[attr = Repr([ReprC, ReprAlign(Align(2 bytes))])]\n"]' +#[repr(C)] +#[repr(align(2))] +pub struct SeparateReprCAlign { + a: i8, + b: i64, +} + +//@ is "$.index[*][?(@.name=='ReversedReprCAlign')].attrs" '["#[attr = Repr([ReprAlign(Align(2 bytes)), ReprC])]\n"]' +#[repr(align(2), C)] +pub struct ReversedReprCAlign { + a: i8, + b: i64, +} + +//@ is "$.index[*][?(@.name=='AlignedExplicitRepr')].attrs" '["#[attr = Repr([ReprC, ReprAlign(Align(16 bytes)), ReprInt(SignedInt(Isize))])]\n"]' +#[repr(C, align(16), isize)] +pub enum AlignedExplicitRepr { + First, +} + +//@ is "$.index[*][?(@.name=='ReorderedAlignedExplicitRepr')].attrs" '["#[attr = Repr([ReprInt(SignedInt(Isize)), ReprC, ReprAlign(Align(16 bytes))])]\n"]' +#[repr(isize, C, align(16))] +pub enum ReorderedAlignedExplicitRepr { + First, +} diff --git a/tests/rustdoc-json/attrs/repr_int_enum.rs b/tests/rustdoc-json/attrs/repr_int_enum.rs new file mode 100644 index 000000000000..2ad57de27988 --- /dev/null +++ b/tests/rustdoc-json/attrs/repr_int_enum.rs @@ -0,0 +1,19 @@ +#![no_std] + +//@ is "$.index[*][?(@.name=='I8')].attrs" '["#[attr = Repr([ReprInt(SignedInt(I8))])]\n"]' +#[repr(i8)] +pub enum I8 { + First, +} + +//@ is "$.index[*][?(@.name=='I32')].attrs" '["#[attr = Repr([ReprInt(SignedInt(I32))])]\n"]' +#[repr(i32)] +pub enum I32 { + First, +} + +//@ is "$.index[*][?(@.name=='Usize')].attrs" '["#[attr = Repr([ReprInt(UnsignedInt(Usize))])]\n"]' +#[repr(usize)] +pub enum Usize { + First, +} diff --git a/tests/rustdoc-json/attrs/repr_packed.rs b/tests/rustdoc-json/attrs/repr_packed.rs new file mode 100644 index 000000000000..33acc23b7c89 --- /dev/null +++ b/tests/rustdoc-json/attrs/repr_packed.rs @@ -0,0 +1,18 @@ +#![no_std] + +// Note the normalization: +// `#[repr(packed)]` in has the implict "1" in rustdoc JSON. + +//@ is "$.index[*][?(@.name=='Packed')].attrs" '["#[attr = Repr([ReprPacked(Align(1 bytes))])]\n"]' +#[repr(packed)] +pub struct Packed { + a: i8, + b: i64, +} + +//@ is "$.index[*][?(@.name=='PackedAligned')].attrs" '["#[attr = Repr([ReprPacked(Align(4 bytes))])]\n"]' +#[repr(packed(4))] +pub struct PackedAligned { + a: i8, + b: i64, +} diff --git a/tests/rustdoc-json/attrs/repr_transparent.rs b/tests/rustdoc-json/attrs/repr_transparent.rs new file mode 100644 index 000000000000..ef6e69f8703b --- /dev/null +++ b/tests/rustdoc-json/attrs/repr_transparent.rs @@ -0,0 +1,22 @@ +#![no_std] + +// Rustdoc JSON currently includes `#[repr(transparent)]` +// even if the transparency is not part of the public API +// +// https://doc.rust-lang.org/nomicon/other-reprs.html#reprtransparent + +//@ is "$.index[*][?(@.name=='Transparent')].attrs" '["#[attr = Repr([ReprTransparent])]\n"]' +#[repr(transparent)] +pub struct Transparent(pub i64); + +//@ is "$.index[*][?(@.name=='TransparentNonPub')].attrs" '["#[attr = Repr([ReprTransparent])]\n"]' +#[repr(transparent)] +pub struct TransparentNonPub(i64); + +//@ is "$.index[*][?(@.name=='AllZst')].attrs" '["#[attr = Repr([ReprTransparent])]\n"]' +#[repr(transparent)] +pub struct AllZst<'a>(pub core::marker::PhantomData<&'a ()>, ()); + +//@ is "$.index[*][?(@.name=='AllZstNotPublic')].attrs" '["#[attr = Repr([ReprTransparent])]\n"]' +#[repr(transparent)] +pub struct AllZstNotPublic<'a>(core::marker::PhantomData<&'a ()>, ()); From c26142697c417010fe338dddd2b771af872d02ba Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 16 Mar 2025 21:14:41 +0100 Subject: [PATCH 227/745] add `naked_functions_target_feature` unstable feature --- compiler/rustc_feature/src/unstable.rs | 2 ++ compiler/rustc_passes/src/check_attr.rs | 16 +++++++++++++- compiler/rustc_span/src/symbol.rs | 1 + .../ui/asm/naked-functions-target-feature.rs | 21 +++++++++++++++++++ tests/ui/asm/naked-functions.rs | 7 ------- ...ure-gate-naked_functions_target_feature.rs | 15 +++++++++++++ ...gate-naked_functions_target_feature.stderr | 13 ++++++++++++ 7 files changed, 67 insertions(+), 8 deletions(-) create mode 100644 tests/ui/asm/naked-functions-target-feature.rs create mode 100644 tests/ui/feature-gates/feature-gate-naked_functions_target_feature.rs create mode 100644 tests/ui/feature-gates/feature-gate-naked_functions_target_feature.stderr diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 3c61bfd1c93f..736d18217b47 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -568,6 +568,8 @@ declare_features! ( (incomplete, mut_ref, "1.79.0", Some(123076)), /// Allows using `#[naked]` on functions. (unstable, naked_functions, "1.9.0", Some(90957)), + /// Allows using `#[target_feature(enable = "...")]` on `#[naked]` on functions. + (unstable, naked_functions_target_feature, "1.86.0", Some(138568)), /// Allows specifying the as-needed link modifier (unstable, native_link_modifiers_as_needed, "1.53.0", Some(81490)), /// Allow negative trait implementations. diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index ece5a53aaa9c..7f624747a468 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -598,7 +598,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { sym::repr, // code generation sym::cold, - sym::target_feature, // documentation sym::doc, ]; @@ -624,6 +623,21 @@ impl<'tcx> CheckAttrVisitor<'tcx> { _ => {} } + if other_attr.has_name(sym::target_feature) { + if !self.tcx.features().naked_functions_target_feature() { + feature_err( + &self.tcx.sess, + sym::naked_functions_target_feature, + other_attr.span(), + "`#[target_feature(/* ... */)]` is currently unstable on `#[naked]` functions", + ).emit(); + + return; + } else { + continue; + } + } + if !ALLOW_LIST.iter().any(|name| other_attr.has_name(*name)) { self.dcx().emit_err(errors::NakedFunctionIncompatibleAttribute { span: other_attr.span(), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8a8bec35d819..9770e315b15c 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1375,6 +1375,7 @@ symbols! { naked, naked_asm, naked_functions, + naked_functions_target_feature, name, names, native_link_modifiers, diff --git a/tests/ui/asm/naked-functions-target-feature.rs b/tests/ui/asm/naked-functions-target-feature.rs new file mode 100644 index 000000000000..afe1a3891472 --- /dev/null +++ b/tests/ui/asm/naked-functions-target-feature.rs @@ -0,0 +1,21 @@ +//@ build-pass +//@ needs-asm-support + +#![feature(naked_functions, naked_functions_target_feature)] +#![crate_type = "lib"] + +use std::arch::{asm, naked_asm}; + +#[cfg(target_arch = "x86_64")] +#[target_feature(enable = "sse2")] +#[naked] +pub unsafe extern "C" fn compatible_target_feature() { + naked_asm!(""); +} + +#[cfg(target_arch = "aarch64")] +#[target_feature(enable = "neon")] +#[naked] +pub unsafe extern "C" fn compatible_target_feature() { + naked_asm!(""); +} diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs index e7e5d84f2a5d..3d4d414539c1 100644 --- a/tests/ui/asm/naked-functions.rs +++ b/tests/ui/asm/naked-functions.rs @@ -230,13 +230,6 @@ pub unsafe extern "C" fn compatible_codegen_attributes() { naked_asm!("", options(raw)); } -#[cfg(target_arch = "x86_64")] -#[target_feature(enable = "sse2")] -#[naked] -pub unsafe extern "C" fn compatible_target_feature() { - naked_asm!(""); -} - #[doc = "foo bar baz"] /// a doc comment // a normal comment diff --git a/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.rs b/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.rs new file mode 100644 index 000000000000..0d3af4c5fe0a --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.rs @@ -0,0 +1,15 @@ +//@ needs-asm-support +//@ only-x86_64 + +#![feature(naked_functions)] + +use std::arch::naked_asm; + +#[naked] +#[target_feature(enable = "avx2")] +//~^ ERROR: `#[target_feature(/* ... */)]` is currently unstable on `#[naked]` functions +extern "C" fn naked() { + unsafe { naked_asm!("") } +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.stderr b/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.stderr new file mode 100644 index 000000000000..b0592d08046f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.stderr @@ -0,0 +1,13 @@ +error[E0658]: `#[target_feature(/* ... */)]` is currently unstable on `#[naked]` functions + --> $DIR/feature-gate-naked_functions_target_feature.rs:9:1 + | +LL | #[target_feature(enable = "avx2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #138568 for more information + = help: add `#![feature(naked_functions_target_feature)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. From 6698c26b3ab9ef90a31af1afc367bab3a359563c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 12 Mar 2025 13:45:48 +1100 Subject: [PATCH 228/745] Fix `is_relevant_impl`. It determines if a function should have any `inline` attributes checked. For `ItemKind::Fn` it returns true or false depending on the details of the function; for anything other item kind it returns *true*. This latter case should instead be *false*. (In the nearby and similar functions `is_relevant_impl` and `is_relevant_trait` the non-function cases return false.) The effect of this is that non-functions are no longer checked. But rustc already disallows `inline` on any non-function items. So if anything its a tiny performance win, because that was useless anyway. --- src/tools/clippy/clippy_lints/src/attrs/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy/clippy_lints/src/attrs/utils.rs b/src/tools/clippy/clippy_lints/src/attrs/utils.rs index 0e650e493925..a5ce2137bffe 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/utils.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/utils.rs @@ -24,7 +24,7 @@ pub(super) fn is_relevant_item(cx: &LateContext<'_>, item: &Item<'_>) -> bool { if let ItemKind::Fn { body: eid, .. } = item.kind { is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir_body(eid).value) } else { - true + false } } From 2b431f768b283319d52be7353024c8426fe8e9fe Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 12 Mar 2025 13:45:48 +1100 Subject: [PATCH 229/745] Fix `is_relevant_impl`. It determines if a function should have any `inline` attributes checked. For `ItemKind::Fn` it returns true or false depending on the details of the function; for anything other item kind it returns *true*. This latter case should instead be *false*. (In the nearby and similar functions `is_relevant_impl` and `is_relevant_trait` the non-function cases return false.) The effect of this is that non-functions are no longer checked. But rustc already disallows `inline` on any non-function items. So if anything its a tiny performance win, because that was useless anyway. --- clippy_lints/src/attrs/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/attrs/utils.rs b/clippy_lints/src/attrs/utils.rs index 0e650e493925..a5ce2137bffe 100644 --- a/clippy_lints/src/attrs/utils.rs +++ b/clippy_lints/src/attrs/utils.rs @@ -24,7 +24,7 @@ pub(super) fn is_relevant_item(cx: &LateContext<'_>, item: &Item<'_>) -> bool { if let ItemKind::Fn { body: eid, .. } = item.kind { is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir_body(eid).value) } else { - true + false } } From b14810669a805003cf6392447c08eed79441936f Mon Sep 17 00:00:00 2001 From: Charalampos Mitrodimas Date: Sun, 16 Mar 2025 11:28:21 +0100 Subject: [PATCH 230/745] Fix ICE: attempted to remap an already remapped filename This commit fixes an internal compiler error (ICE) that occurs when rustdoc attempts to process macros with a remapped filename. The issue arose during macro expansion when the `--remap-path-prefix` option was used. Instead of passing remapped filenames through, which would trigger the "attempted to remap an already remapped filename" panic, we now extract the original local path from remapped filenames before processing them. A test case has been added to verify this behavior. Fixes #138520 Signed-off-by: Charalampos Mitrodimas --- src/librustdoc/clean/render_macro_matchers.rs | 4 ++-- tests/rustdoc-ui/remap-path-prefix-macro.rs | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 tests/rustdoc-ui/remap-path-prefix-macro.rs diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs index 88db853d7c38..31f9c284d7dd 100644 --- a/src/librustdoc/clean/render_macro_matchers.rs +++ b/src/librustdoc/clean/render_macro_matchers.rs @@ -4,8 +4,8 @@ use rustc_ast_pretty::pprust::PrintState; use rustc_ast_pretty::pprust::state::State as Printer; use rustc_middle::ty::TyCtxt; use rustc_session::parse::ParseSess; -use rustc_span::Span; use rustc_span::symbol::{Ident, Symbol, kw}; +use rustc_span::{FileName, Span}; /// Render a macro matcher in a format suitable for displaying to the user /// as part of an item declaration. @@ -63,7 +63,7 @@ fn snippet_equal_to_token(tcx: TyCtxt<'_>, matcher: &TokenTree) -> Option parser, diff --git a/tests/rustdoc-ui/remap-path-prefix-macro.rs b/tests/rustdoc-ui/remap-path-prefix-macro.rs new file mode 100644 index 000000000000..1be22694b8cd --- /dev/null +++ b/tests/rustdoc-ui/remap-path-prefix-macro.rs @@ -0,0 +1,9 @@ +// Regression test for "attempted to remap an already remapped filename" ICE in rustdoc +// when using --remap-path-prefix with macro rendering. +// + +//@ compile-flags:-Z unstable-options --remap-path-prefix={{src-base}}=remapped_path +//@ rustc-env:RUST_BACKTRACE=0 +//@ build-pass + +macro_rules! f(() => {}); From 6ccaea19895cc8c0861f3a8707f888a15f8be3a1 Mon Sep 17 00:00:00 2001 From: Andrew Zhogin Date: Fri, 7 Mar 2025 05:34:12 +0700 Subject: [PATCH 231/745] Target modifiers fix for bool flags without value --- compiler/rustc_metadata/messages.ftl | 17 ++++- compiler/rustc_metadata/src/creader.rs | 69 ++++++++++++++----- compiler/rustc_metadata/src/errors.rs | 36 +++++++++- compiler/rustc_session/src/options.rs | 52 +++++++------- .../auxiliary/enabled_reg_struct_return.rs | 7 ++ .../defaults_check.error.stderr | 4 +- .../no_value_bool.error.stderr | 13 ++++ .../no_value_bool.error_explicit.stderr | 13 ++++ tests/ui/target_modifiers/no_value_bool.rs | 22 ++++++ 9 files changed, 184 insertions(+), 49 deletions(-) create mode 100644 tests/ui/target_modifiers/auxiliary/enabled_reg_struct_return.rs create mode 100644 tests/ui/target_modifiers/no_value_bool.error.stderr create mode 100644 tests/ui/target_modifiers/no_value_bool.error_explicit.stderr create mode 100644 tests/ui/target_modifiers/no_value_bool.rs diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index 20f66fae5c01..9adbcabcf450 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -118,12 +118,23 @@ metadata_incompatible_rustc = metadata_incompatible_target_modifiers = mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}` - .note = `{$flag_name_prefixed}={$flag_local_value}` in this crate is incompatible with `{$flag_name_prefixed}={$flag_extern_value}` in dependency `{$extern_crate}` + .note = `{$flag_name_prefixed}={$local_value}` in this crate is incompatible with `{$flag_name_prefixed}={$extern_value}` in dependency `{$extern_crate}` .help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely - metadata_incompatible_target_modifiers_help_allow = if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch={$flag_name}` to silence this error -metadata_incompatible_target_modifiers_help_fix = set `{$flag_name_prefixed}={$flag_extern_value}` in this crate or `{$flag_name_prefixed}={$flag_local_value}` in `{$extern_crate}` +metadata_incompatible_target_modifiers_help_fix = set `{$flag_name_prefixed}={$extern_value}` in this crate or `{$flag_name_prefixed}={$local_value}` in `{$extern_crate}` +metadata_incompatible_target_modifiers_help_fix_l_missed = set `{$flag_name_prefixed}={$extern_value}` in this crate or unset `{$flag_name_prefixed}` in `{$extern_crate}` + +metadata_incompatible_target_modifiers_help_fix_r_missed = unset `{$flag_name_prefixed}` in this crate or set `{$flag_name_prefixed}={$local_value}` in `{$extern_crate}` + +metadata_incompatible_target_modifiers_l_missed = + mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}` + .note = unset `{$flag_name_prefixed}` in this crate is incompatible with `{$flag_name_prefixed}={$extern_value}` in dependency `{$extern_crate}` + .help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely +metadata_incompatible_target_modifiers_r_missed = + mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}` + .note = `{$flag_name_prefixed}={$local_value}` in this crate is incompatible with unset `{$flag_name_prefixed}` in dependency `{$extern_crate}` + .help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely metadata_incompatible_wasm_link = `wasm_import_module` is incompatible with other arguments in `#[link]` attributes diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 12503ffd1a67..b7f13e0afdcd 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -358,30 +358,58 @@ impl CStore { ) { let span = krate.spans.inner_span.shrink_to_lo(); let allowed_flag_mismatches = &tcx.sess.opts.cg.unsafe_allow_abi_mismatch; - let name = tcx.crate_name(LOCAL_CRATE); + let local_crate = tcx.crate_name(LOCAL_CRATE); let tmod_extender = |tmod: &TargetModifier| (tmod.extend(), tmod.clone()); let report_diff = |prefix: &String, opt_name: &String, - flag_local_value: &String, - flag_extern_value: &String| { + flag_local_value: Option<&String>, + flag_extern_value: Option<&String>| { if allowed_flag_mismatches.contains(&opt_name) { return; } - tcx.dcx().emit_err(errors::IncompatibleTargetModifiers { - span, - extern_crate: data.name(), - local_crate: name, - flag_name: opt_name.clone(), - flag_name_prefixed: format!("-{}{}", prefix, opt_name), - flag_local_value: flag_local_value.to_string(), - flag_extern_value: flag_extern_value.to_string(), - }); + let extern_crate = data.name(); + let flag_name = opt_name.clone(); + let flag_name_prefixed = format!("-{}{}", prefix, opt_name); + + match (flag_local_value, flag_extern_value) { + (Some(local_value), Some(extern_value)) => { + tcx.dcx().emit_err(errors::IncompatibleTargetModifiers { + span, + extern_crate, + local_crate, + flag_name, + flag_name_prefixed, + local_value: local_value.to_string(), + extern_value: extern_value.to_string(), + }) + } + (None, Some(extern_value)) => { + tcx.dcx().emit_err(errors::IncompatibleTargetModifiersLMissed { + span, + extern_crate, + local_crate, + flag_name, + flag_name_prefixed, + extern_value: extern_value.to_string(), + }) + } + (Some(local_value), None) => { + tcx.dcx().emit_err(errors::IncompatibleTargetModifiersRMissed { + span, + extern_crate, + local_crate, + flag_name, + flag_name_prefixed, + local_value: local_value.to_string(), + }) + } + (None, None) => panic!("Incorrect target modifiers report_diff(None, None)"), + }; }; let mut it1 = mods.iter().map(tmod_extender); let mut it2 = dep_mods.iter().map(tmod_extender); let mut left_name_val: Option<(ExtendedTargetModifierInfo, TargetModifier)> = None; let mut right_name_val: Option<(ExtendedTargetModifierInfo, TargetModifier)> = None; - let no_val = "*".to_string(); loop { left_name_val = left_name_val.or_else(|| it1.next()); right_name_val = right_name_val.or_else(|| it2.next()); @@ -389,26 +417,31 @@ impl CStore { (Some(l), Some(r)) => match l.1.opt.cmp(&r.1.opt) { cmp::Ordering::Equal => { if l.0.tech_value != r.0.tech_value { - report_diff(&l.0.prefix, &l.0.name, &l.1.value_name, &r.1.value_name); + report_diff( + &l.0.prefix, + &l.0.name, + Some(&l.1.value_name), + Some(&r.1.value_name), + ); } left_name_val = None; right_name_val = None; } cmp::Ordering::Greater => { - report_diff(&r.0.prefix, &r.0.name, &no_val, &r.1.value_name); + report_diff(&r.0.prefix, &r.0.name, None, Some(&r.1.value_name)); right_name_val = None; } cmp::Ordering::Less => { - report_diff(&l.0.prefix, &l.0.name, &l.1.value_name, &no_val); + report_diff(&l.0.prefix, &l.0.name, Some(&l.1.value_name), None); left_name_val = None; } }, (Some(l), None) => { - report_diff(&l.0.prefix, &l.0.name, &l.1.value_name, &no_val); + report_diff(&l.0.prefix, &l.0.name, Some(&l.1.value_name), None); left_name_val = None; } (None, Some(r)) => { - report_diff(&r.0.prefix, &r.0.name, &no_val, &r.1.value_name); + report_diff(&r.0.prefix, &r.0.name, None, Some(&r.1.value_name)); right_name_val = None; } (None, None) => break, diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 2ad6389c0b4a..0c54628598c4 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -759,8 +759,40 @@ pub struct IncompatibleTargetModifiers { pub local_crate: Symbol, pub flag_name: String, pub flag_name_prefixed: String, - pub flag_local_value: String, - pub flag_extern_value: String, + pub local_value: String, + pub extern_value: String, +} + +#[derive(Diagnostic)] +#[diag(metadata_incompatible_target_modifiers_l_missed)] +#[help] +#[note] +#[help(metadata_incompatible_target_modifiers_help_fix_l_missed)] +#[help(metadata_incompatible_target_modifiers_help_allow)] +pub struct IncompatibleTargetModifiersLMissed { + #[primary_span] + pub span: Span, + pub extern_crate: Symbol, + pub local_crate: Symbol, + pub flag_name: String, + pub flag_name_prefixed: String, + pub extern_value: String, +} + +#[derive(Diagnostic)] +#[diag(metadata_incompatible_target_modifiers_r_missed)] +#[help] +#[note] +#[help(metadata_incompatible_target_modifiers_help_fix_r_missed)] +#[help(metadata_incompatible_target_modifiers_help_allow)] +pub struct IncompatibleTargetModifiersRMissed { + #[primary_span] + pub span: Span, + pub extern_crate: Symbol, + pub local_crate: Symbol, + pub flag_name: String, + pub flag_name_prefixed: String, + pub local_value: String, } #[derive(Diagnostic)] diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 8977365ee73d..599b4fa91090 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -94,45 +94,49 @@ fn tmod_push_impl( tmod_vals: &BTreeMap, tmods: &mut Vec, ) { - tmods.push(TargetModifier { opt, value_name: tmod_vals.get(&opt).cloned().unwrap_or_default() }) + if let Some(v) = tmod_vals.get(&opt) { + tmods.push(TargetModifier { opt, value_name: v.clone() }) + } } macro_rules! tmod_push { - ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $mods:expr, $tmod_vals:expr) => { - tmod_push_impl( - OptionsTargetModifiers::$struct_name($tmod_enum_name::$opt_name), - $tmod_vals, - $mods, - ); + ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr) => { + if *$opt_expr != $init { + tmod_push_impl( + OptionsTargetModifiers::$struct_name($tmod_enum_name::$opt_name), + $tmod_vals, + $mods, + ); + } }; } macro_rules! gather_tmods { - ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, + ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr, [SUBSTRUCT], [TARGET_MODIFIER]) => { compile_error!("SUBSTRUCT can't be target modifier"); }; - ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, + ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr, [UNTRACKED], [TARGET_MODIFIER]) => { - tmod_push!($struct_name, $tmod_enum_name, $opt_name, $mods, $tmod_vals) + tmod_push!($struct_name, $tmod_enum_name, $opt_name, $opt_expr, $init, $mods, $tmod_vals) }; - ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, + ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr, [TRACKED], [TARGET_MODIFIER]) => { - tmod_push!($struct_name, $tmod_enum_name, $opt_name, $mods, $tmod_vals) + tmod_push!($struct_name, $tmod_enum_name, $opt_name, $opt_expr, $init, $mods, $tmod_vals) }; - ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, + ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr, [TRACKED_NO_CRATE_HASH], [TARGET_MODIFIER]) => { - tmod_push!($struct_name, $tmod_enum_name, $opt_name, $mods, $tmod_vals) + tmod_push!($struct_name, $tmod_enum_name, $opt_name, $opt_expr, $init, $mods, $tmod_vals) }; - ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, + ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr, [SUBSTRUCT], []) => { $opt_expr.gather_target_modifiers($mods, $tmod_vals); }; - ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, + ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr, [UNTRACKED], []) => {{}}; - ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, + ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr, [TRACKED], []) => {{}}; - ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr, + ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr, [TRACKED_NO_CRATE_HASH], []) => {{}}; } @@ -474,7 +478,8 @@ macro_rules! tmod_enum { $($pout)* Self::$opt => { let mut parsed : $t = Default::default(); - parse::$parse(&mut parsed, Some($puser_value)); + let val = if $puser_value.is_empty() { None } else { Some($puser_value) }; + parse::$parse(&mut parsed, val); ExtendedTargetModifierInfo { prefix: $prefix.to_string(), name: stringify!($opt).to_string().replace('_', "-"), @@ -569,7 +574,7 @@ macro_rules! options { _tmod_vals: &BTreeMap, ) { $({ - gather_tmods!($struct_name, $tmod_enum_name, $opt, &self.$opt, _mods, _tmod_vals, + gather_tmods!($struct_name, $tmod_enum_name, $opt, &self.$opt, $init, _mods, _tmod_vals, [$dep_tracking_marker], [$($tmod),*]); })* } @@ -681,10 +686,9 @@ fn build_options( ), } } - if let Some(tmod) = *tmod - && let Some(value) = value - { - target_modifiers.insert(tmod, value.to_string()); + if let Some(tmod) = *tmod { + let v = value.map_or(String::new(), ToOwned::to_owned); + target_modifiers.insert(tmod, v); } } None => early_dcx.early_fatal(format!("unknown {outputname} option: `{key}`")), diff --git a/tests/ui/target_modifiers/auxiliary/enabled_reg_struct_return.rs b/tests/ui/target_modifiers/auxiliary/enabled_reg_struct_return.rs new file mode 100644 index 000000000000..4bda4ba24c54 --- /dev/null +++ b/tests/ui/target_modifiers/auxiliary/enabled_reg_struct_return.rs @@ -0,0 +1,7 @@ +//@ no-prefer-dynamic +//@ compile-flags: --target i686-unknown-linux-gnu -Zreg-struct-return=true +//@ needs-llvm-components: x86 + +#![feature(no_core)] +#![crate_type = "rlib"] +#![no_core] diff --git a/tests/ui/target_modifiers/defaults_check.error.stderr b/tests/ui/target_modifiers/defaults_check.error.stderr index 4833fe906775..936fbbc94d6d 100644 --- a/tests/ui/target_modifiers/defaults_check.error.stderr +++ b/tests/ui/target_modifiers/defaults_check.error.stderr @@ -5,8 +5,8 @@ LL | #![feature(no_core)] | ^ | = help: the `-Zreg-struct-return` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely - = note: `-Zreg-struct-return=true` in this crate is incompatible with `-Zreg-struct-return=` in dependency `default_reg_struct_return` - = help: set `-Zreg-struct-return=` in this crate or `-Zreg-struct-return=true` in `default_reg_struct_return` + = note: `-Zreg-struct-return=true` in this crate is incompatible with unset `-Zreg-struct-return` in dependency `default_reg_struct_return` + = help: unset `-Zreg-struct-return` in this crate or set `-Zreg-struct-return=true` in `default_reg_struct_return` = help: if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=reg-struct-return` to silence this error error: aborting due to 1 previous error diff --git a/tests/ui/target_modifiers/no_value_bool.error.stderr b/tests/ui/target_modifiers/no_value_bool.error.stderr new file mode 100644 index 000000000000..0484960dc62d --- /dev/null +++ b/tests/ui/target_modifiers/no_value_bool.error.stderr @@ -0,0 +1,13 @@ +error: mixing `-Zreg-struct-return` will cause an ABI mismatch in crate `no_value_bool` + --> $DIR/no_value_bool.rs:16:1 + | +LL | #![feature(no_core)] + | ^ + | + = help: the `-Zreg-struct-return` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely + = note: unset `-Zreg-struct-return` in this crate is incompatible with `-Zreg-struct-return=true` in dependency `enabled_reg_struct_return` + = help: set `-Zreg-struct-return=true` in this crate or unset `-Zreg-struct-return` in `enabled_reg_struct_return` + = help: if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=reg-struct-return` to silence this error + +error: aborting due to 1 previous error + diff --git a/tests/ui/target_modifiers/no_value_bool.error_explicit.stderr b/tests/ui/target_modifiers/no_value_bool.error_explicit.stderr new file mode 100644 index 000000000000..0484960dc62d --- /dev/null +++ b/tests/ui/target_modifiers/no_value_bool.error_explicit.stderr @@ -0,0 +1,13 @@ +error: mixing `-Zreg-struct-return` will cause an ABI mismatch in crate `no_value_bool` + --> $DIR/no_value_bool.rs:16:1 + | +LL | #![feature(no_core)] + | ^ + | + = help: the `-Zreg-struct-return` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely + = note: unset `-Zreg-struct-return` in this crate is incompatible with `-Zreg-struct-return=true` in dependency `enabled_reg_struct_return` + = help: set `-Zreg-struct-return=true` in this crate or unset `-Zreg-struct-return` in `enabled_reg_struct_return` + = help: if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=reg-struct-return` to silence this error + +error: aborting due to 1 previous error + diff --git a/tests/ui/target_modifiers/no_value_bool.rs b/tests/ui/target_modifiers/no_value_bool.rs new file mode 100644 index 000000000000..ceba40afa896 --- /dev/null +++ b/tests/ui/target_modifiers/no_value_bool.rs @@ -0,0 +1,22 @@ +// Tests that bool target modifier value (true) in dependency crate is ok linked +// with the -Zflag specified without value (-Zflag=true is consistent with -Zflag) + +//@ aux-build:enabled_reg_struct_return.rs +//@ compile-flags: --target i686-unknown-linux-gnu -Cpanic=abort +//@ needs-llvm-components: x86 + +//@ revisions: ok ok_explicit error error_explicit +//@[ok] compile-flags: -Zreg-struct-return +//@[ok_explicit] compile-flags: -Zreg-struct-return=true +//@[error] compile-flags: +//@[error_explicit] compile-flags: -Zreg-struct-return=false +//@[ok] check-pass +//@[ok_explicit] check-pass + +#![feature(no_core)] +//[error]~^ ERROR mixing `-Zreg-struct-return` will cause an ABI mismatch in crate `no_value_bool` +//[error_explicit]~^^ ERROR mixing `-Zreg-struct-return` will cause an ABI mismatch in crate `no_value_bool` +#![crate_type = "rlib"] +#![no_core] + +extern crate enabled_reg_struct_return; From a3865b1a3d92399ebe523c0ffa4ca0f5caf40f9b Mon Sep 17 00:00:00 2001 From: yanglsh Date: Thu, 13 Feb 2025 11:40:42 +0800 Subject: [PATCH 232/745] fix: `option_if_let_else` FP when value partially moved --- clippy_lints/src/option_if_let_else.rs | 86 +++++++++++++++++++++++++- tests/ui/option_if_let_else.fixed | 20 ++++++ tests/ui/option_if_let_else.rs | 20 ++++++ 3 files changed, 124 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index de9f055863cb..2824e4fdb1f2 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -1,16 +1,23 @@ +use std::ops::ControlFlow; + use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::sugg::Sugg; +use clippy_utils::ty::is_copy; use clippy_utils::{ CaptureKind, can_move_expr_to_closure, eager_or_lazy, higher, is_else_clause, is_in_const_context, is_res_lang_ctor, peel_blocks, peel_hir_expr_while, }; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::def::Res; +use rustc_hir::intravisit::{Visitor, walk_expr, walk_path}; use rustc_hir::{ - Arm, BindingMode, Expr, ExprKind, MatchSource, Mutability, Pat, PatExpr, PatExprKind, PatKind, Path, QPath, UnOp, + Arm, BindingMode, Expr, ExprKind, HirId, MatchSource, Mutability, Node, Pat, PatExpr, PatExprKind, PatKind, Path, + QPath, UnOp, }; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::hir::nested_filter; use rustc_session::declare_lint_pass; use rustc_span::SyntaxContext; @@ -110,11 +117,12 @@ fn format_option_in_sugg(cond_sugg: Sugg<'_>, as_ref: bool, as_mut: bool) -> Str ) } +#[expect(clippy::too_many_lines)] fn try_get_option_occurrence<'tcx>( cx: &LateContext<'tcx>, ctxt: SyntaxContext, pat: &Pat<'tcx>, - expr: &Expr<'_>, + expr: &'tcx Expr<'_>, if_then: &'tcx Expr<'_>, if_else: &'tcx Expr<'_>, ) -> Option { @@ -182,6 +190,26 @@ fn try_get_option_occurrence<'tcx>( Some(CaptureKind::Ref(Mutability::Not)) | None => (), } } + } else if !is_copy(cx, cx.typeck_results().expr_ty(expr)) + // TODO: Cover more match cases + && matches!( + expr.kind, + ExprKind::Field(_, _) | ExprKind::Path(_) | ExprKind::Index(_, _, _) + ) + { + let mut condition_visitor = ConditionVisitor { + cx, + identifiers: FxHashSet::default(), + }; + condition_visitor.visit_expr(cond_expr); + + let mut reference_visitor = ReferenceVisitor { + cx, + identifiers: condition_visitor.identifiers, + }; + if reference_visitor.visit_expr(none_body).is_break() { + return None; + } } let mut app = Applicability::Unspecified; @@ -219,6 +247,60 @@ fn try_get_option_occurrence<'tcx>( None } +/// This visitor looks for bindings in the block that mention a local variable. Then gets the +/// identifiers. The list of identifiers will then be used to check if the block mentions the +/// same local. See [`ReferenceVisitor`] for more. +struct ConditionVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + identifiers: FxHashSet, +} + +impl<'tcx> Visitor<'tcx> for ConditionVisitor<'_, 'tcx> { + type NestedFilter = nested_filter::All; + + fn visit_path(&mut self, path: &Path<'tcx>, _: HirId) { + if let Res::Local(local_id) = path.res + && let Node::Pat(pat) = self.cx.tcx.hir_node(local_id) + && let PatKind::Binding(_, local_id, ..) = pat.kind + { + self.identifiers.insert(local_id); + } + walk_path(self, path); + } + + fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { + self.cx.tcx + } +} + +/// This visitor checks if the block contains references to the local variables that are +/// used in the block. See [`ConditionVisitor`] for more. +struct ReferenceVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + identifiers: FxHashSet, +} + +impl<'tcx> Visitor<'tcx> for ReferenceVisitor<'_, 'tcx> { + type NestedFilter = nested_filter::All; + type Result = ControlFlow<()>; + fn visit_expr(&mut self, expr: &'tcx Expr<'_>) -> ControlFlow<()> { + if let ExprKind::Path(ref path) = expr.kind + && let QPath::Resolved(_, path) = path + && let Res::Local(local_id) = path.res + && let Node::Pat(pat) = self.cx.tcx.hir_node(local_id) + && let PatKind::Binding(_, local_id, ..) = pat.kind + && self.identifiers.contains(&local_id) + { + return ControlFlow::Break(()); + } + walk_expr(self, expr) + } + + fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { + self.cx.tcx + } +} + fn try_get_inner_pat_and_is_result<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option<(&'tcx Pat<'tcx>, bool)> { if let PatKind::TupleStruct(ref qpath, [inner_pat], ..) = pat.kind { let res = cx.qpath_res(qpath, pat.hir_id); diff --git a/tests/ui/option_if_let_else.fixed b/tests/ui/option_if_let_else.fixed index f5a869cf2831..ee3098896017 100644 --- a/tests/ui/option_if_let_else.fixed +++ b/tests/ui/option_if_let_else.fixed @@ -268,3 +268,23 @@ fn issue11893() { panic!("Haven't thought about this condition."); } } + +mod issue13964 { + #[derive(Debug)] + struct A(Option); + + fn foo(a: A) { + let _ = match a.0 { + Some(x) => x, + None => panic!("{a:?} is invalid."), + }; + } + + fn bar(a: A) { + let _ = if let Some(x) = a.0 { + x + } else { + panic!("{a:?} is invalid.") + }; + } +} diff --git a/tests/ui/option_if_let_else.rs b/tests/ui/option_if_let_else.rs index d48272e618ac..525a5df4371c 100644 --- a/tests/ui/option_if_let_else.rs +++ b/tests/ui/option_if_let_else.rs @@ -331,3 +331,23 @@ fn issue11893() { panic!("Haven't thought about this condition."); } } + +mod issue13964 { + #[derive(Debug)] + struct A(Option); + + fn foo(a: A) { + let _ = match a.0 { + Some(x) => x, + None => panic!("{a:?} is invalid."), + }; + } + + fn bar(a: A) { + let _ = if let Some(x) = a.0 { + x + } else { + panic!("{a:?} is invalid.") + }; + } +} From f478853f425fc0207add653b48c49c937acaa94e Mon Sep 17 00:00:00 2001 From: Zachary S Date: Mon, 17 Mar 2025 00:25:15 -0500 Subject: [PATCH 233/745] If a label is placed on the block of a loop instead of the header, suggest moving it to the header. --- .../rustc_parse/src/parser/diagnostics.rs | 29 +++- compiler/rustc_parse/src/parser/expr.rs | 36 +++-- compiler/rustc_parse/src/parser/item.rs | 2 +- compiler/rustc_parse/src/parser/mod.rs | 2 +- compiler/rustc_parse/src/parser/stmt.rs | 22 ++- tests/ui/loops/label-on-block-suggest-move.rs | 90 +++++++++++ .../loops/label-on-block-suggest-move.stderr | 140 ++++++++++++++++++ 7 files changed, 296 insertions(+), 25 deletions(-) create mode 100644 tests/ui/loops/label-on-block-suggest-move.rs create mode 100644 tests/ui/loops/label-on-block-suggest-move.stderr diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 716ababb0080..c1cca1186af4 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2874,7 +2874,12 @@ impl<'a> Parser<'a> { first_pat } - pub(crate) fn maybe_recover_unexpected_block_label(&mut self) -> bool { + /// If `loop_header` is `Some` and an unexpected block label is encountered, + /// it is suggested to be moved just before `loop_header`, else it is suggested to be removed. + pub(crate) fn maybe_recover_unexpected_block_label( + &mut self, + loop_header: Option, + ) -> bool { // Check for `'a : {` if !(self.check_lifetime() && self.look_ahead(1, |t| *t == token::Colon) @@ -2885,16 +2890,28 @@ impl<'a> Parser<'a> { let label = self.eat_label().expect("just checked if a label exists"); self.bump(); // eat `:` let span = label.ident.span.to(self.prev_token.span); - self.dcx() + let mut diag = self + .dcx() .struct_span_err(span, "block label not supported here") - .with_span_label(span, "not supported here") - .with_tool_only_span_suggestion( + .with_span_label(span, "not supported here"); + if let Some(loop_header) = loop_header { + diag.multipart_suggestion( + "if you meant to label the loop, move this label before the loop", + vec![ + (label.ident.span.until(self.token.span), String::from("")), + (loop_header.shrink_to_lo(), format!("{}: ", label.ident)), + ], + Applicability::MachineApplicable, + ); + } else { + diag.tool_only_span_suggestion( label.ident.span.until(self.token.span), "remove this block label", "", Applicability::MachineApplicable, - ) - .emit(); + ); + } + diag.emit(); true } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 0774324eae74..cd931888fbaa 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2286,7 +2286,7 @@ impl<'a> Parser<'a> { }); } - let (attrs, blk) = self.parse_block_common(lo, blk_mode, true)?; + let (attrs, blk) = self.parse_block_common(lo, blk_mode, true, None)?; Ok(self.mk_expr_with_attrs(blk.span, ExprKind::Block(blk, opt_label), attrs)) } @@ -2851,7 +2851,11 @@ impl<'a> Parser<'a> { )); } - let (attrs, loop_block) = self.parse_inner_attrs_and_block()?; + let (attrs, loop_block) = self.parse_inner_attrs_and_block( + // Only suggest moving erroneous block label to the loop header + // if there is not already a label there + opt_label.is_none().then_some(lo), + )?; let kind = ExprKind::ForLoop { pat, iter: expr, body: loop_block, label: opt_label, kind }; @@ -2894,11 +2898,17 @@ impl<'a> Parser<'a> { err.span_label(lo, "while parsing the condition of this `while` expression"); err })?; - let (attrs, body) = self.parse_inner_attrs_and_block().map_err(|mut err| { - err.span_label(lo, "while parsing the body of this `while` expression"); - err.span_label(cond.span, "this `while` condition successfully parsed"); - err - })?; + let (attrs, body) = self + .parse_inner_attrs_and_block( + // Only suggest moving erroneous block label to the loop header + // if there is not already a label there + opt_label.is_none().then_some(lo), + ) + .map_err(|mut err| { + err.span_label(lo, "while parsing the body of this `while` expression"); + err.span_label(cond.span, "this `while` condition successfully parsed"); + err + })?; self.recover_loop_else("while", lo)?; @@ -2912,7 +2922,11 @@ impl<'a> Parser<'a> { /// Parses `loop { ... }` (`loop` token already eaten). fn parse_expr_loop(&mut self, opt_label: Option
"); write_str( @@ -1392,6 +1403,7 @@ fn render_assoc_items_inner( } } +/// `derefs` is the set of all deref targets that have already been handled. fn render_deref_methods( mut w: impl Write, cx: &Context<'_>, diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 3130815af0bd..9c78dcdc571d 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -533,7 +533,10 @@ fn sidebar_deref_methods<'a>( debug!("found inner_impl: {impls:?}"); let mut ret = impls .iter() - .filter(|i| i.inner_impl().trait_.is_none()) + .filter(|i| { + i.inner_impl().trait_.is_none() + && real_target.is_doc_subtype_of(&i.inner_impl().for_, &c) + }) .flat_map(|i| get_methods(i.inner_impl(), true, used_links, deref_mut, cx.tcx())) .collect::>(); if !ret.is_empty() { diff --git a/tests/rustdoc/deref/deref-methods-24686-target.rs b/tests/rustdoc/deref/deref-methods-24686-target.rs new file mode 100644 index 000000000000..e019488ca802 --- /dev/null +++ b/tests/rustdoc/deref/deref-methods-24686-target.rs @@ -0,0 +1,27 @@ +#![crate_name = "foo"] + +// test for https://github.com/rust-lang/rust/issues/24686 +use std::ops::Deref; + +pub struct Foo(T); +impl Foo { + pub fn get_i32(&self) -> i32 { self.0 } +} +impl Foo { + pub fn get_u32(&self) -> u32 { self.0 } +} + +// Note that the same href is used both on the method itself, +// and on the sidebar items. +//@ has foo/struct.Bar.html +//@ has - '//a[@href="#method.get_i32"]' 'get_i32' +//@ !has - '//a[@href="#method.get_u32"]' 'get_u32' +//@ count - '//ul[@class="block deref-methods"]//a' 1 +//@ count - '//a[@href="#method.get_i32"]' 2 +pub struct Bar(Foo); +impl Deref for Bar { + type Target = Foo; + fn deref(&self) -> &Foo { + &self.0 + } +} From bafdbcadd5e70e4a1a35647002c30efd315621b4 Mon Sep 17 00:00:00 2001 From: Predrag Gruevski Date: Tue, 4 Mar 2025 22:02:06 +0000 Subject: [PATCH 437/745] rustdoc: Use own logic to print `#[repr(..)]` attributes in JSON output. --- src/librustdoc/clean/types.rs | 25 +++++++++++----- src/rustdoc-json-types/lib.rs | 22 +++++++++++--- tests/rustdoc-json/attrs/repr_align.rs | 2 +- tests/rustdoc-json/attrs/repr_c.rs | 6 ++-- tests/rustdoc-json/attrs/repr_combination.rs | 23 ++++++++------- tests/rustdoc-json/attrs/repr_int_enum.rs | 6 ++-- tests/rustdoc-json/attrs/repr_packed.rs | 8 ++--- tests/rustdoc-json/attrs/repr_transparent.rs | 29 ++++++++++++++----- .../rustdoc-json/enums/discriminant/struct.rs | 2 +- .../rustdoc-json/enums/discriminant/tuple.rs | 2 +- 10 files changed, 82 insertions(+), 43 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 3b2dcb3db81d..1207f2f0360f 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -768,12 +768,22 @@ impl Item { .iter() .filter_map(|attr| { if is_json { - if matches!(attr, hir::Attribute::Parsed(AttributeKind::Deprecation { .. })) { - // rustdoc-json stores this in `Item::deprecation`, so we - // don't want it it `Item::attrs`. - None - } else { - Some(rustc_hir_pretty::attribute_to_string(&tcx, attr)) + match attr { + hir::Attribute::Parsed(AttributeKind::Deprecation { .. }) => { + // rustdoc-json stores this in `Item::deprecation`, so we + // don't want it it `Item::attrs`. + None + } + rustc_hir::Attribute::Parsed(rustc_attr_parsing::AttributeKind::Repr( + .., + )) => { + // We have separate pretty-printing logic for `#[repr(..)]` attributes. + // For example, there are circumstances where `#[repr(transparent)]` + // is applied but should not be publicly shown in rustdoc + // because it isn't public API. + None + } + _ => Some(rustc_hir_pretty::attribute_to_string(&tcx, attr)), } } else if ALLOWED_ATTRIBUTES.contains(&attr.name_or_empty()) { Some( @@ -789,8 +799,7 @@ impl Item { .collect(); // Add #[repr(...)] - if !is_json - && let Some(def_id) = self.def_id() + if let Some(def_id) = self.def_id() && let ItemType::Struct | ItemType::Enum | ItemType::Union = self.type_() { let adt = tcx.adt_def(def_id); diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 44e82c7d8b19..137fe4c4c354 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -30,7 +30,7 @@ pub type FxHashMap = HashMap; // re-export for use in src/librustdoc /// This integer is incremented with every breaking change to the API, /// and is returned along with the JSON blob as [`Crate::format_version`]. /// Consuming code should assert that this value matches the format version(s) that it supports. -pub const FORMAT_VERSION: u32 = 42; +pub const FORMAT_VERSION: u32 = 43; /// The root of the emitted JSON blob. /// @@ -120,9 +120,23 @@ pub struct Item { pub docs: Option, /// This mapping resolves [intra-doc links](https://github.com/rust-lang/rfcs/blob/master/text/1946-intra-rustdoc-links.md) from the docstring to their IDs pub links: HashMap, - /// Stringified versions of parsed attributes on this item. - /// Essentially debug printed (e.g. `#[inline]` becomes something similar to `#[attr="Inline(Hint)"]`). - /// Equivalent to the hir pretty-printing of attributes. + /// Attributes on this item. + /// + /// Does not include `#[deprecated]` attributes: see the [`Self::deprecation`] field instead. + /// + /// Some attributes appear in pretty-printed Rust form, regardless of their formatting + /// in the original source code. For example: + /// - `#[non_exhaustive]` and `#[must_use]` are represented as themselves. + /// - `#[no_mangle]` and `#[export_name]` are also represented as themselves. + /// - `#[repr(C)]` and other reprs also appear as themselves, + /// though potentially with a different order: e.g. `repr(i8, C)` may become `repr(C, i8)`. + /// Multiple repr attributes on the same item may be combined into an equivalent single attr. + /// + /// Other attributes may appear debug-printed. For example: + /// - `#[inline]` becomes something similar to `#[attr="Inline(Hint)"]`. + /// + /// As an internal implementation detail subject to change, this debug-printing format + /// is currently equivalent to the HIR pretty-printing of parsed attributes. pub attrs: Vec, /// Information about the item’s deprecation, if present. pub deprecation: Option, diff --git a/tests/rustdoc-json/attrs/repr_align.rs b/tests/rustdoc-json/attrs/repr_align.rs index 83506737b211..c6debda7f1c9 100644 --- a/tests/rustdoc-json/attrs/repr_align.rs +++ b/tests/rustdoc-json/attrs/repr_align.rs @@ -1,6 +1,6 @@ #![no_std] -//@ is "$.index[?(@.name=='Aligned')].attrs" '["#[attr = Repr([ReprAlign(Align(4 bytes))])]\n"]' +//@ is "$.index[?(@.name=='Aligned')].attrs" '["#[repr(align(4))]"]' #[repr(align(4))] pub struct Aligned { a: i8, diff --git a/tests/rustdoc-json/attrs/repr_c.rs b/tests/rustdoc-json/attrs/repr_c.rs index 018086b3c1ff..e6219413f308 100644 --- a/tests/rustdoc-json/attrs/repr_c.rs +++ b/tests/rustdoc-json/attrs/repr_c.rs @@ -1,16 +1,16 @@ #![no_std] -//@ is "$.index[?(@.name=='ReprCStruct')].attrs" '["#[attr = Repr([ReprC])]\n"]' +//@ is "$.index[?(@.name=='ReprCStruct')].attrs" '["#[repr(C)]"]' #[repr(C)] pub struct ReprCStruct(pub i64); -//@ is "$.index[?(@.name=='ReprCEnum')].attrs" '["#[attr = Repr([ReprC])]\n"]' +//@ is "$.index[?(@.name=='ReprCEnum')].attrs" '["#[repr(C)]"]' #[repr(C)] pub enum ReprCEnum { First, } -//@ is "$.index[?(@.name=='ReprCUnion')].attrs" '["#[attr = Repr([ReprC])]\n"]' +//@ is "$.index[?(@.name=='ReprCUnion')].attrs" '["#[repr(C)]"]' #[repr(C)] pub union ReprCUnion { pub left: i64, diff --git a/tests/rustdoc-json/attrs/repr_combination.rs b/tests/rustdoc-json/attrs/repr_combination.rs index c3ef8becb779..0e8e2ef0d83e 100644 --- a/tests/rustdoc-json/attrs/repr_combination.rs +++ b/tests/rustdoc-json/attrs/repr_combination.rs @@ -1,34 +1,35 @@ #![no_std] // Combinations of `#[repr(..)]` attributes. +// Rustdoc JSON emits normalized output, regardless of the original source. -//@ is "$.index[?(@.name=='ReprCI8')].attrs" '["#[attr = Repr([ReprC, ReprInt(SignedInt(I8))])]\n"]' +//@ is "$.index[?(@.name=='ReprCI8')].attrs" '["#[repr(C, i8)]"]' #[repr(C, i8)] pub enum ReprCI8 { First, } -//@ is "$.index[?(@.name=='SeparateReprCI16')].attrs" '["#[attr = Repr([ReprC, ReprInt(SignedInt(I16))])]\n"]' +//@ is "$.index[?(@.name=='SeparateReprCI16')].attrs" '["#[repr(C, i16)]"]' #[repr(C)] #[repr(i16)] pub enum SeparateReprCI16 { First, } -//@ is "$.index[?(@.name=='ReversedReprCUsize')].attrs" '["#[attr = Repr([ReprInt(UnsignedInt(Usize)), ReprC])]\n"]' +//@ is "$.index[?(@.name=='ReversedReprCUsize')].attrs" '["#[repr(C, usize)]"]' #[repr(usize, C)] pub enum ReversedReprCUsize { First, } -//@ is "$.index[?(@.name=='ReprCPacked')].attrs" '["#[attr = Repr([ReprC, ReprPacked(Align(1 bytes))])]\n"]' +//@ is "$.index[?(@.name=='ReprCPacked')].attrs" '["#[repr(C, packed(1))]"]' #[repr(C, packed)] pub struct ReprCPacked { a: i8, b: i64, } -//@ is "$.index[?(@.name=='SeparateReprCPacked')].attrs" '["#[attr = Repr([ReprC, ReprPacked(Align(2 bytes))])]\n"]' +//@ is "$.index[?(@.name=='SeparateReprCPacked')].attrs" '["#[repr(C, packed(2))]"]' #[repr(C)] #[repr(packed(2))] pub struct SeparateReprCPacked { @@ -36,21 +37,21 @@ pub struct SeparateReprCPacked { b: i64, } -//@ is "$.index[?(@.name=='ReversedReprCPacked')].attrs" '["#[attr = Repr([ReprPacked(Align(2 bytes)), ReprC])]\n"]' +//@ is "$.index[?(@.name=='ReversedReprCPacked')].attrs" '["#[repr(C, packed(2))]"]' #[repr(packed(2), C)] pub struct ReversedReprCPacked { a: i8, b: i64, } -//@ is "$.index[?(@.name=='ReprCAlign')].attrs" '["#[attr = Repr([ReprC, ReprAlign(Align(16 bytes))])]\n"]' +//@ is "$.index[?(@.name=='ReprCAlign')].attrs" '["#[repr(C, align(16))]"]' #[repr(C, align(16))] pub struct ReprCAlign { a: i8, b: i64, } -//@ is "$.index[?(@.name=='SeparateReprCAlign')].attrs" '["#[attr = Repr([ReprC, ReprAlign(Align(2 bytes))])]\n"]' +//@ is "$.index[?(@.name=='SeparateReprCAlign')].attrs" '["#[repr(C, align(2))]"]' #[repr(C)] #[repr(align(2))] pub struct SeparateReprCAlign { @@ -58,20 +59,20 @@ pub struct SeparateReprCAlign { b: i64, } -//@ is "$.index[?(@.name=='ReversedReprCAlign')].attrs" '["#[attr = Repr([ReprAlign(Align(2 bytes)), ReprC])]\n"]' +//@ is "$.index[?(@.name=='ReversedReprCAlign')].attrs" '["#[repr(C, align(2))]"]' #[repr(align(2), C)] pub struct ReversedReprCAlign { a: i8, b: i64, } -//@ is "$.index[?(@.name=='AlignedExplicitRepr')].attrs" '["#[attr = Repr([ReprC, ReprAlign(Align(16 bytes)), ReprInt(SignedInt(Isize))])]\n"]' +//@ is "$.index[?(@.name=='AlignedExplicitRepr')].attrs" '["#[repr(C, align(16), isize)]"]' #[repr(C, align(16), isize)] pub enum AlignedExplicitRepr { First, } -//@ is "$.index[?(@.name=='ReorderedAlignedExplicitRepr')].attrs" '["#[attr = Repr([ReprInt(SignedInt(Isize)), ReprC, ReprAlign(Align(16 bytes))])]\n"]' +//@ is "$.index[?(@.name=='ReorderedAlignedExplicitRepr')].attrs" '["#[repr(C, align(16), isize)]"]' #[repr(isize, C, align(16))] pub enum ReorderedAlignedExplicitRepr { First, diff --git a/tests/rustdoc-json/attrs/repr_int_enum.rs b/tests/rustdoc-json/attrs/repr_int_enum.rs index 206cb7835f52..9b09f341d4fe 100644 --- a/tests/rustdoc-json/attrs/repr_int_enum.rs +++ b/tests/rustdoc-json/attrs/repr_int_enum.rs @@ -1,18 +1,18 @@ #![no_std] -//@ is "$.index[?(@.name=='I8')].attrs" '["#[attr = Repr([ReprInt(SignedInt(I8))])]\n"]' +//@ is "$.index[?(@.name=='I8')].attrs" '["#[repr(i8)]"]' #[repr(i8)] pub enum I8 { First, } -//@ is "$.index[?(@.name=='I32')].attrs" '["#[attr = Repr([ReprInt(SignedInt(I32))])]\n"]' +//@ is "$.index[?(@.name=='I32')].attrs" '["#[repr(i32)]"]' #[repr(i32)] pub enum I32 { First, } -//@ is "$.index[?(@.name=='Usize')].attrs" '["#[attr = Repr([ReprInt(UnsignedInt(Usize))])]\n"]' +//@ is "$.index[?(@.name=='Usize')].attrs" '["#[repr(usize)]"]' #[repr(usize)] pub enum Usize { First, diff --git a/tests/rustdoc-json/attrs/repr_packed.rs b/tests/rustdoc-json/attrs/repr_packed.rs index d4c400f72f81..9f3fd86c4b03 100644 --- a/tests/rustdoc-json/attrs/repr_packed.rs +++ b/tests/rustdoc-json/attrs/repr_packed.rs @@ -1,16 +1,16 @@ #![no_std] // Note the normalization: -// `#[repr(packed)]` in has the implict "1" in rustdoc JSON. - -//@ is "$.index[?(@.name=='Packed')].attrs" '["#[attr = Repr([ReprPacked(Align(1 bytes))])]\n"]' +// `#[repr(packed)]` in source becomes `#[repr(packed(1))]` in rustdoc JSON. +// +//@ is "$.index[?(@.name=='Packed')].attrs" '["#[repr(packed(1))]"]' #[repr(packed)] pub struct Packed { a: i8, b: i64, } -//@ is "$.index[?(@.name=='PackedAligned')].attrs" '["#[attr = Repr([ReprPacked(Align(4 bytes))])]\n"]' +//@ is "$.index[?(@.name=='PackedAligned')].attrs" '["#[repr(packed(4))]"]' #[repr(packed(4))] pub struct PackedAligned { a: i8, diff --git a/tests/rustdoc-json/attrs/repr_transparent.rs b/tests/rustdoc-json/attrs/repr_transparent.rs index 3f57b21dcc52..1e634ca901dc 100644 --- a/tests/rustdoc-json/attrs/repr_transparent.rs +++ b/tests/rustdoc-json/attrs/repr_transparent.rs @@ -1,22 +1,37 @@ #![no_std] -// Rustdoc JSON currently includes `#[repr(transparent)]` -// even if the transparency is not part of the public API +// Rustdoc JSON *only* includes `#[repr(transparent)]` +// if the transparency is public API: +// - if a non-1-ZST field exists, it has to be public +// - otherwise, all fields are 1-ZST and at least one of them is public // -// https://doc.rust-lang.org/nomicon/other-reprs.html#reprtransparent +// More info: https://doc.rust-lang.org/nomicon/other-reprs.html#reprtransparent -//@ is "$.index[?(@.name=='Transparent')].attrs" '["#[attr = Repr([ReprTransparent])]\n"]' +// Here, the non-1-ZST field is public. +// We expect `#[repr(transparent)]` in the attributes. +// +//@ is "$.index[?(@.name=='Transparent')].attrs" '["#[repr(transparent)]"]' #[repr(transparent)] pub struct Transparent(pub i64); -//@ is "$.index[?(@.name=='TransparentNonPub')].attrs" '["#[attr = Repr([ReprTransparent])]\n"]' +// Here the non-1-ZST field isn't public, so the attribute isn't included. +// +//@ has "$.index[?(@.name=='TransparentNonPub')]" +//@ is "$.index[?(@.name=='TransparentNonPub')].attrs" '[]' #[repr(transparent)] pub struct TransparentNonPub(i64); -//@ is "$.index[?(@.name=='AllZst')].attrs" '["#[attr = Repr([ReprTransparent])]\n"]' +// Only 1-ZST fields here, and one of them is public. +// We expect `#[repr(transparent)]` in the attributes. +// +//@ is "$.index[?(@.name=='AllZst')].attrs" '["#[repr(transparent)]"]' #[repr(transparent)] pub struct AllZst<'a>(pub core::marker::PhantomData<&'a ()>, ()); -//@ is "$.index[?(@.name=='AllZstNotPublic')].attrs" '["#[attr = Repr([ReprTransparent])]\n"]' +// Only 1-ZST fields here but none of them are public. +// The attribute isn't included. +// +//@ has "$.index[?(@.name=='AllZstNotPublic')]" +//@ is "$.index[?(@.name=='AllZstNotPublic')].attrs" '[]' #[repr(transparent)] pub struct AllZstNotPublic<'a>(core::marker::PhantomData<&'a ()>, ()); diff --git a/tests/rustdoc-json/enums/discriminant/struct.rs b/tests/rustdoc-json/enums/discriminant/struct.rs index 08fb80540fa9..ea669e6a0b30 100644 --- a/tests/rustdoc-json/enums/discriminant/struct.rs +++ b/tests/rustdoc-json/enums/discriminant/struct.rs @@ -1,5 +1,5 @@ #[repr(i32)] -//@ is "$.index[?(@.name=='Foo')].attrs" '["#[attr = Repr([ReprInt(SignedInt(I32))])]\n"]' +//@ is "$.index[?(@.name=='Foo')].attrs" '["#[repr(i32)]"]' pub enum Foo { //@ is "$.index[?(@.name=='Struct')].inner.variant.discriminant" null //@ count "$.index[?(@.name=='Struct')].inner.variant.kind.struct.fields[*]" 0 diff --git a/tests/rustdoc-json/enums/discriminant/tuple.rs b/tests/rustdoc-json/enums/discriminant/tuple.rs index c74e9a2c58dd..1b8e791eb230 100644 --- a/tests/rustdoc-json/enums/discriminant/tuple.rs +++ b/tests/rustdoc-json/enums/discriminant/tuple.rs @@ -1,5 +1,5 @@ #[repr(u32)] -//@ is "$.index[?(@.name=='Foo')].attrs" '["#[attr = Repr([ReprInt(UnsignedInt(U32))])]\n"]' +//@ is "$.index[?(@.name=='Foo')].attrs" '["#[repr(u32)]"]' pub enum Foo { //@ is "$.index[?(@.name=='Tuple')].inner.variant.discriminant" null //@ count "$.index[?(@.name=='Tuple')].inner.variant.kind.tuple[*]" 0 From fa0c951a2795a0e1e5caa94317309a8bdb9b94a5 Mon Sep 17 00:00:00 2001 From: Chiichen Date: Sun, 23 Mar 2025 12:41:23 +0800 Subject: [PATCH 438/745] doc: rename reference #create-a-configtoml to #create-a-bootstraptoml --- bootstrap.example.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bootstrap.example.toml b/bootstrap.example.toml index 294d9780716e..caffe1a93712 100644 --- a/bootstrap.example.toml +++ b/bootstrap.example.toml @@ -1,7 +1,7 @@ # Sample TOML configuration file for building Rust. # # To configure bootstrap, run `./configure` or `./x.py setup`. -# See https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html#create-a-configtoml for more information. +# See https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html#create-a-bootstraptoml for more information. # # All options are commented out by default in this file, and they're commented # out with their default values. The build system by default looks for @@ -446,7 +446,7 @@ # a specific version. #ccache = false -# List of paths to exclude from the build and test processes. +# List of paths to exclude from the build and test processes. # For example, exclude = ["tests/ui", "src/tools/tidy"]. #exclude = [] From 5950c862bd3c2c410197d17d173cade26d38f041 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 17 Mar 2025 13:06:34 +0100 Subject: [PATCH 439/745] Slim `rustc_parse_format` dependencies down `rustc_index` is only used for its size assertion macro, so demote it to a dev-dependency gated under testing instead --- compiler/rustc_parse_format/Cargo.toml | 4 +++- compiler/rustc_parse_format/src/lib.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_parse_format/Cargo.toml b/compiler/rustc_parse_format/Cargo.toml index d6c3bd9877c9..289e062fb5e2 100644 --- a/compiler/rustc_parse_format/Cargo.toml +++ b/compiler/rustc_parse_format/Cargo.toml @@ -8,5 +8,7 @@ edition = "2024" rustc_lexer = { path = "../rustc_lexer" } # tidy-alphabetical-end -[target.'cfg(target_pointer_width = "64")'.dependencies] +[target.'cfg(target_pointer_width = "64")'.dev-dependencies] +# tidy-alphabetical-start rustc_index = { path = "../rustc_index", default-features = false } +# tidy-alphabetical-end diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 5b8a2fe52d3f..97931742985e 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -1105,7 +1105,7 @@ fn unescape_string(string: &str) -> Option { } // Assert a reasonable size for `Piece` -#[cfg(target_pointer_width = "64")] +#[cfg(all(test, target_pointer_width = "64"))] rustc_index::static_assert_size!(Piece<'_>, 16); #[cfg(test)] From 20f4a0d586fcb27936f07f001bf128b2f407b018 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Sun, 23 Mar 2025 17:02:42 +0900 Subject: [PATCH 440/745] fix ICE #138415 --- compiler/rustc_ast_lowering/src/item.rs | 4 ++-- .../invalid-extern-fn-body.rs | 11 ++++++++++ .../invalid-extern-fn-body.stderr | 20 +++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.rs create mode 100644 tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.stderr diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index bd011d59aaa7..518349343b3a 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1724,8 +1724,8 @@ impl<'hir> LoweringContext<'_, 'hir> { return; }; let define_opaque = define_opaque.iter().filter_map(|(id, path)| { - let res = self.resolver.get_partial_res(*id).unwrap(); - let Some(did) = res.expect_full_res().opt_def_id() else { + let res = self.resolver.get_partial_res(*id); + let Some(did) = res.and_then(|res| res.expect_full_res().opt_def_id()) else { self.dcx().span_delayed_bug(path.span, "should have errored in resolve"); return None; }; diff --git a/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.rs b/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.rs new file mode 100644 index 000000000000..d873af44adf9 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.rs @@ -0,0 +1,11 @@ +#![feature(type_alias_impl_trait)] + +extern "C" { + fn a() { + //~^ ERROR incorrect function inside `extern` block + #[define_opaque(String)] + fn c() {} + } +} + +pub fn main() {} diff --git a/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.stderr b/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.stderr new file mode 100644 index 000000000000..2e944257d8f6 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.stderr @@ -0,0 +1,20 @@ +error: incorrect function inside `extern` block + --> $DIR/invalid-extern-fn-body.rs:4:8 + | +LL | extern "C" { + | ---------- `extern` blocks define existing foreign functions and functions inside of them cannot have a body +LL | fn a() { + | ________^___- + | | | + | | cannot have a body +LL | | +LL | | #[define_opaque(String)] +LL | | fn c() {} +LL | | } + | |_____- help: remove the invalid body: `;` + | + = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to 1 previous error + From 34b7d51b95663071729b83a2127bdd6a98b9ca08 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Sun, 23 Mar 2025 17:47:10 +0900 Subject: [PATCH 441/745] fix typo --- library/core/src/macros/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index fa0d882181a5..5f200b31d1ae 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1744,7 +1744,7 @@ pub(crate) mod builtin { } /// Provide a list of type aliases and other opaque-type-containing type definitions. - /// This list will be used in the body of the item it is applied to to define opaque + /// This list will be used in the body of the item it is applied to define opaque /// types' hidden types. /// Can only be applied to things that have bodies. #[unstable( From 0e7dbab1fc4a2cfc63bac4f5c4d283d2504f1547 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 18 Mar 2025 13:16:01 +0800 Subject: [PATCH 442/745] Implement `supported-crate-types` print request As an unstable print request. --- compiler/rustc_driver_impl/src/lib.rs | 14 +++++++++++-- compiler/rustc_session/src/config.rs | 7 ++++++- tests/ui/print-request/stability.rs | 4 ++++ .../supported-crate-types.linux.stdout | 7 +++++++ .../supported-crate-types.musl.stdout | 5 +++++ .../ui/print-request/supported-crate-types.rs | 20 +++++++++++++++++++ .../supported-crate-types.wasm.stdout | 5 +++++ 7 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 tests/ui/print-request/supported-crate-types.linux.stdout create mode 100644 tests/ui/print-request/supported-crate-types.musl.stdout create mode 100644 tests/ui/print-request/supported-crate-types.rs create mode 100644 tests/ui/print-request/supported-crate-types.wasm.stdout diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 4ba076c64e10..37755e7d61db 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -20,7 +20,7 @@ // tidy-alphabetical-end use std::cmp::max; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, BTreeSet}; use std::ffi::OsString; use std::fmt::Write as _; use std::fs::{self, File}; @@ -61,7 +61,7 @@ use rustc_session::config::{ }; use rustc_session::getopts::{self, Matches}; use rustc_session::lint::{Lint, LintId}; -use rustc_session::output::collect_crate_types; +use rustc_session::output::{CRATE_TYPES, collect_crate_types, invalid_output_for_target}; use rustc_session::{EarlyDiagCtxt, Session, config, filesearch}; use rustc_span::FileName; use rustc_target::json::ToJson; @@ -790,6 +790,16 @@ fn print_crate_info( sess.dcx().fatal("only Apple targets currently support deployment version info") } } + SupportedCrateTypes => { + let supported_crate_types = CRATE_TYPES + .iter() + .filter(|(_, crate_type)| !invalid_output_for_target(&sess, *crate_type)) + .map(|(crate_type_sym, _)| *crate_type_sym) + .collect::>(); + for supported_crate_type in supported_crate_types { + println_info!("{}", supported_crate_type.as_str()); + } + } } req.out.overwrite(&crate_info, sess); diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 43b78423c727..ed336cc55961 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -58,6 +58,7 @@ pub const PRINT_KINDS: &[(&str, PrintKind)] = &[ ("relocation-models", PrintKind::RelocationModels), ("split-debuginfo", PrintKind::SplitDebuginfo), ("stack-protector-strategies", PrintKind::StackProtectorStrategies), + ("supported-crate-types", PrintKind::SupportedCrateTypes), ("sysroot", PrintKind::Sysroot), ("target-cpus", PrintKind::TargetCPUs), ("target-features", PrintKind::TargetFeatures), @@ -888,6 +889,7 @@ pub enum PrintKind { RelocationModels, SplitDebuginfo, StackProtectorStrategies, + SupportedCrateTypes, Sysroot, TargetCPUs, TargetFeatures, @@ -2063,7 +2065,10 @@ fn check_print_request_stability( (print_name, print_kind): (&str, PrintKind), ) { match print_kind { - PrintKind::AllTargetSpecsJson | PrintKind::CheckCfg | PrintKind::TargetSpecJson + PrintKind::AllTargetSpecsJson + | PrintKind::CheckCfg + | PrintKind::SupportedCrateTypes + | PrintKind::TargetSpecJson if !unstable_opts.unstable_options => { early_dcx.early_fatal(format!( diff --git a/tests/ui/print-request/stability.rs b/tests/ui/print-request/stability.rs index b205b0555691..c3421224d720 100644 --- a/tests/ui/print-request/stability.rs +++ b/tests/ui/print-request/stability.rs @@ -22,6 +22,10 @@ //@[check_cfg] compile-flags: --print=check-cfg //@[check_cfg] error-pattern: the `-Z unstable-options` flag must also be passed +//@ revisions: supported_crate_types +//@[supported_crate_types] compile-flags: --print=supported-crate-types +//@[supported_crate_types] error-pattern: the `-Z unstable-options` flag must also be passed + //@ revisions: target_spec_json //@[target_spec_json] compile-flags: --print=target-spec-json //@[target_spec_json] error-pattern: the `-Z unstable-options` flag must also be passed diff --git a/tests/ui/print-request/supported-crate-types.linux.stdout b/tests/ui/print-request/supported-crate-types.linux.stdout new file mode 100644 index 000000000000..721adb432e7a --- /dev/null +++ b/tests/ui/print-request/supported-crate-types.linux.stdout @@ -0,0 +1,7 @@ +bin +cdylib +dylib +lib +proc-macro +rlib +staticlib diff --git a/tests/ui/print-request/supported-crate-types.musl.stdout b/tests/ui/print-request/supported-crate-types.musl.stdout new file mode 100644 index 000000000000..1f4b991e49fd --- /dev/null +++ b/tests/ui/print-request/supported-crate-types.musl.stdout @@ -0,0 +1,5 @@ +bin +lib +proc-macro +rlib +staticlib diff --git a/tests/ui/print-request/supported-crate-types.rs b/tests/ui/print-request/supported-crate-types.rs new file mode 100644 index 000000000000..c8b4c0c1a416 --- /dev/null +++ b/tests/ui/print-request/supported-crate-types.rs @@ -0,0 +1,20 @@ +//! Basic smoke test for `--print=supported-crate-types`, which should print a newline delimited +//! list of crate types supported by the given target. This test cherry-picks a few well-known +//! targets as examples. +//! +//! Tracking issue: + +// ignore-tidy-linelength + +//@ check-pass + +//@ revisions: wasm musl linux + +//@[wasm] compile-flags: --target=wasm32-unknown-unknown --print=supported-crate-types -Zunstable-options +//@[wasm] needs-llvm-components: webassembly + +//@[musl] compile-flags: --target=x86_64-unknown-linux-musl --print=supported-crate-types -Zunstable-options +//@[musl] needs-llvm-components: x86 + +//@[linux] compile-flags: --target=x86_64-unknown-linux-gnu --print=supported-crate-types -Zunstable-options +//@[linux] needs-llvm-components: x86 diff --git a/tests/ui/print-request/supported-crate-types.wasm.stdout b/tests/ui/print-request/supported-crate-types.wasm.stdout new file mode 100644 index 000000000000..ca1de519598a --- /dev/null +++ b/tests/ui/print-request/supported-crate-types.wasm.stdout @@ -0,0 +1,5 @@ +bin +cdylib +lib +rlib +staticlib From 13530afc08909a44874dc1e8667747fddb48e3c7 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 18 Mar 2025 13:37:36 +0800 Subject: [PATCH 443/745] Document `supported-crate-types` print request in unstable book --- .../print-supported-crate-types.md | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/doc/unstable-book/src/compiler-flags/print-supported-crate-types.md diff --git a/src/doc/unstable-book/src/compiler-flags/print-supported-crate-types.md b/src/doc/unstable-book/src/compiler-flags/print-supported-crate-types.md new file mode 100644 index 000000000000..f285d6e71751 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/print-supported-crate-types.md @@ -0,0 +1,27 @@ +# `print=supported-crate-types` + +The tracking issue for this feature is: [#138640](https://github.com/rust-lang/rust/issues/138640). + +------------------------ + +This option of the `--print` flag produces a list of crate types (delimited by newlines) supported for the given target. + +The crate type strings correspond to the values accepted by the `--crate-type` flag. + +Intended to be used like this: + +```bash +rustc --print=supported-crate-types -Zunstable-options --target=x86_64-unknown-linux-gnu +``` + +Example output for `x86_64-unknown-linux-gnu`: + +```text +bin +cdylib +dylib +lib +proc-macro +rlib +staticlib +``` From f1b8d896597534af16e3c1e540c336b9b444af0a Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 18 Mar 2025 14:39:46 +0800 Subject: [PATCH 444/745] Rebless tests with changed help due to new print request option --- tests/run-make/rustc-help/help-v.stdout | 2 +- tests/run-make/rustc-help/help.stdout | 2 +- tests/ui/invalid-compile-flags/print-without-arg.stderr | 2 +- tests/ui/invalid-compile-flags/print.stderr | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/run-make/rustc-help/help-v.stdout b/tests/run-make/rustc-help/help-v.stdout index c8ea09ee2c8a..98e56735082d 100644 --- a/tests/run-make/rustc-help/help-v.stdout +++ b/tests/run-make/rustc-help/help-v.stdout @@ -29,7 +29,7 @@ Options: --emit [asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir] Comma separated list of types of output for the compiler to emit - --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models] + --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models] Compiler information to print on stdout -g Equivalent to -C debuginfo=2 -O Equivalent to -C opt-level=3 diff --git a/tests/run-make/rustc-help/help.stdout b/tests/run-make/rustc-help/help.stdout index 434e71e901e4..040555f1d04f 100644 --- a/tests/run-make/rustc-help/help.stdout +++ b/tests/run-make/rustc-help/help.stdout @@ -29,7 +29,7 @@ Options: --emit [asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir] Comma separated list of types of output for the compiler to emit - --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models] + --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models] Compiler information to print on stdout -g Equivalent to -C debuginfo=2 -O Equivalent to -C opt-level=3 diff --git a/tests/ui/invalid-compile-flags/print-without-arg.stderr b/tests/ui/invalid-compile-flags/print-without-arg.stderr index 05d42247d419..aa8a2ae42db2 100644 --- a/tests/ui/invalid-compile-flags/print-without-arg.stderr +++ b/tests/ui/invalid-compile-flags/print-without-arg.stderr @@ -1,5 +1,5 @@ error: Argument to option 'print' missing Usage: - --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models] + --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models] Compiler information to print on stdout diff --git a/tests/ui/invalid-compile-flags/print.stderr b/tests/ui/invalid-compile-flags/print.stderr index 4ea06a06539a..f9cfb1616ce5 100644 --- a/tests/ui/invalid-compile-flags/print.stderr +++ b/tests/ui/invalid-compile-flags/print.stderr @@ -1,5 +1,5 @@ error: unknown print request: `yyyy` | - = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models` + = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models` = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information From f2cde8eeb4378b99cb722a9ef4a2f6cc83b805e1 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Fri, 21 Mar 2025 14:52:26 +0800 Subject: [PATCH 445/745] Adjust `rustc-print-info-issue-138612.rs` - Document test intent to check for `-Whelp` suggestion if `--print=lints` was specified. - Move this test under `tests/ui/print-request/` and rename it to `print-lints-help.rs` to better reflect what it is checking. --- tests/ui/print-request/print-lints-help.rs | 7 +++++++ .../print-lints-help.stderr} | 2 +- tests/ui/rustc-print-info-issue-138612.rs | 2 -- 3 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 tests/ui/print-request/print-lints-help.rs rename tests/ui/{rustc-print-info-issue-138612.stderr => print-request/print-lints-help.stderr} (74%) delete mode 100644 tests/ui/rustc-print-info-issue-138612.rs diff --git a/tests/ui/print-request/print-lints-help.rs b/tests/ui/print-request/print-lints-help.rs new file mode 100644 index 000000000000..420eae27ed43 --- /dev/null +++ b/tests/ui/print-request/print-lints-help.rs @@ -0,0 +1,7 @@ +//! Check that we point to `-Whelp` to guide the user to find the list of lints if the user requests +//! `--print=lints` (which is not a valid print request). + +//@ compile-flags: --print lints +//@ error-pattern: error: unknown print request: `lints` +//@ error-pattern: help: use `-Whelp` to print a list of lints +//@ error-pattern: help: for more information, see the rustc book diff --git a/tests/ui/rustc-print-info-issue-138612.stderr b/tests/ui/print-request/print-lints-help.stderr similarity index 74% rename from tests/ui/rustc-print-info-issue-138612.stderr rename to tests/ui/print-request/print-lints-help.stderr index 4f7ed8219521..0530d11f2e80 100644 --- a/tests/ui/rustc-print-info-issue-138612.stderr +++ b/tests/ui/print-request/print-lints-help.stderr @@ -1,6 +1,6 @@ error: unknown print request: `lints` | - = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models` + = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models` = help: use `-Whelp` to print a list of lints = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information diff --git a/tests/ui/rustc-print-info-issue-138612.rs b/tests/ui/rustc-print-info-issue-138612.rs deleted file mode 100644 index 65b595635b15..000000000000 --- a/tests/ui/rustc-print-info-issue-138612.rs +++ /dev/null @@ -1,2 +0,0 @@ -//@ check-fail -//@ compile-flags: /dev/null --print lints From f10b58714e864ac7c1f6d6ac1666f26d4a1ca955 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Sun, 23 Mar 2025 19:28:10 +0800 Subject: [PATCH 446/745] Say which test failed the `COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS` assertion --- src/tools/compiletest/src/header.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 7675e13990d6..d7a5f304d238 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -1385,7 +1385,7 @@ pub fn make_test_description( decision!(cfg::handle_ignore(config, ln)); decision!(cfg::handle_only(config, ln)); decision!(needs::handle_needs(&cache.needs, config, ln)); - decision!(ignore_llvm(config, ln)); + decision!(ignore_llvm(config, path, ln)); decision!(ignore_cdb(config, ln)); decision!(ignore_gdb(config, ln)); decision!(ignore_lldb(config, ln)); @@ -1525,7 +1525,7 @@ fn ignore_lldb(config: &Config, line: &str) -> IgnoreDecision { IgnoreDecision::Continue } -fn ignore_llvm(config: &Config, line: &str) -> IgnoreDecision { +fn ignore_llvm(config: &Config, path: &Path, line: &str) -> IgnoreDecision { if let Some(needed_components) = config.parse_name_value_directive(line, "needs-llvm-components") { @@ -1536,8 +1536,9 @@ fn ignore_llvm(config: &Config, line: &str) -> IgnoreDecision { { if env::var_os("COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS").is_some() { panic!( - "missing LLVM component {}, and COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS is set", - missing_component + "missing LLVM component {}, and COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS is set: {}", + missing_component, + path.display() ); } return IgnoreDecision::Ignore { From eb3707e4b49e7d19d048cf2187d6e3643be9dba2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 6 Mar 2025 20:50:51 +0000 Subject: [PATCH 447/745] Stabilize precise_capturing_in_traits --- compiler/rustc_ast_lowering/messages.ftl | 3 --- compiler/rustc_ast_lowering/src/errors.rs | 8 ------- compiler/rustc_ast_lowering/src/lib.rs | 22 ------------------- compiler/rustc_feature/src/accepted.rs | 2 ++ compiler/rustc_feature/src/unstable.rs | 2 -- ...eature-gate-precise_capturing_in_traits.rs | 6 ----- ...re-gate-precise_capturing_in_traits.stderr | 13 ----------- tests/ui/impl-trait/in-trait/dump.rs | 2 +- .../ui/impl-trait/in-trait/refine-captures.rs | 2 -- .../in-trait/refine-captures.stderr | 8 +++---- tests/ui/impl-trait/in-trait/variance.rs | 2 +- .../forgot-to-capture-type.rs | 2 -- .../forgot-to-capture-type.stderr | 4 ++-- .../impl-trait/precise-capturing/redundant.rs | 1 - .../precise-capturing/redundant.stderr | 10 ++++----- .../rpitit-captures-more-method-lifetimes.rs | 2 -- ...itit-captures-more-method-lifetimes.stderr | 4 ++-- .../rpitit-impl-captures-too-much.rs | 2 -- .../rpitit-impl-captures-too-much.stderr | 4 ++-- .../precise-capturing/rpitit-outlives-2.rs | 2 -- .../precise-capturing/rpitit-outlives.rs | 2 -- .../ui/impl-trait/precise-capturing/rpitit.rs | 2 -- .../precise-capturing/rpitit.stderr | 6 ++--- .../precise-capturing/self-capture.rs | 2 -- 24 files changed, 22 insertions(+), 91 deletions(-) delete mode 100644 tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs delete mode 100644 tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index 65e5b530bbe3..5ef76fb64aaf 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -141,9 +141,6 @@ ast_lowering_never_pattern_with_guard = ast_lowering_no_precise_captures_on_apit = `use<...>` precise capturing syntax not allowed in argument-position `impl Trait` -ast_lowering_no_precise_captures_on_rpitit = `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - .note = currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope - ast_lowering_previously_used_here = previously used here ast_lowering_register1 = register `{$reg1_name}` diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index ceeb5dffbea0..576fa9731e90 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -444,14 +444,6 @@ pub(crate) struct NoPreciseCapturesOnApit { pub span: Span, } -#[derive(Diagnostic)] -#[diag(ast_lowering_no_precise_captures_on_rpitit)] -#[note] -pub(crate) struct NoPreciseCapturesOnRpitit { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(ast_lowering_yield_in_closure)] pub(crate) struct YieldInClosure { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e08850da4a7a..787706597368 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1438,28 +1438,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // frequently opened issues show. let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None); - // Feature gate for RPITIT + use<..> - match origin { - rustc_hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl: Some(_), .. } => { - if !self.tcx.features().precise_capturing_in_traits() - && let Some(span) = bounds.iter().find_map(|bound| match *bound { - ast::GenericBound::Use(_, span) => Some(span), - _ => None, - }) - { - let mut diag = - self.tcx.dcx().create_err(errors::NoPreciseCapturesOnRpitit { span }); - add_feature_diagnostics( - &mut diag, - self.tcx.sess, - sym::precise_capturing_in_traits, - ); - diag.emit(); - } - } - _ => {} - } - self.lower_opaque_inner(opaque_ty_node_id, origin, opaque_ty_span, |this| { this.lower_param_bounds(bounds, itctx) }) diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 980f39460354..88e6593572bc 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -331,6 +331,8 @@ declare_features! ( (accepted, pattern_parentheses, "1.31.0", Some(51087)), /// Allows `use<'a, 'b, A, B>` in `impl Trait + use<...>` for precise capture of generic args. (accepted, precise_capturing, "1.82.0", Some(123432)), + /// Allows `use<..>` precise capturign on impl Trait in traits. + (accepted, precise_capturing_in_traits, "CURRENT_RUSTC_VERSION", Some(130044)), /// Allows procedural macros in `proc-macro` crates. (accepted, proc_macro, "1.29.0", Some(38356)), /// Allows multi-segment paths in attributes and derives. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 4707daea0891..72468dd4714d 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -600,8 +600,6 @@ declare_features! ( (incomplete, pin_ergonomics, "1.83.0", Some(130494)), /// Allows postfix match `expr.match { ... }` (unstable, postfix_match, "1.79.0", Some(121618)), - /// Allows `use<..>` precise capturign on impl Trait in traits. - (unstable, precise_capturing_in_traits, "1.83.0", Some(130044)), /// Allows macro attributes on expressions, statements and non-inline modules. (unstable, proc_macro_hygiene, "1.30.0", Some(54727)), /// Allows the use of raw-dylibs on ELF platforms diff --git a/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs b/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs deleted file mode 100644 index 308b41dfc68a..000000000000 --- a/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs +++ /dev/null @@ -1,6 +0,0 @@ -trait Foo { - fn test() -> impl Sized + use; - //~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position -} - -fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr b/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr deleted file mode 100644 index b2c6bf61124d..000000000000 --- a/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/feature-gate-precise_capturing_in_traits.rs:2:31 - | -LL | fn test() -> impl Sized + use; - | ^^^^^^^^^ - | - = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope - = note: see issue #130044 for more information - = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 1 previous error - diff --git a/tests/ui/impl-trait/in-trait/dump.rs b/tests/ui/impl-trait/in-trait/dump.rs index 47198d511505..20b0e60702fa 100644 --- a/tests/ui/impl-trait/in-trait/dump.rs +++ b/tests/ui/impl-trait/in-trait/dump.rs @@ -1,6 +1,6 @@ //@ compile-flags: -Zverbose-internals -#![feature(precise_capturing_in_traits, rustc_attrs)] +#![feature(rustc_attrs)] #![rustc_hidden_type_of_opaques] trait Foo { diff --git a/tests/ui/impl-trait/in-trait/refine-captures.rs b/tests/ui/impl-trait/in-trait/refine-captures.rs index e7dffcb52aae..199cc464c4e5 100644 --- a/tests/ui/impl-trait/in-trait/refine-captures.rs +++ b/tests/ui/impl-trait/in-trait/refine-captures.rs @@ -1,5 +1,3 @@ -#![feature(precise_capturing_in_traits)] - trait LifetimeParam<'a> { fn test() -> impl Sized; } diff --git a/tests/ui/impl-trait/in-trait/refine-captures.stderr b/tests/ui/impl-trait/in-trait/refine-captures.stderr index 166991894d16..6f213f161449 100644 --- a/tests/ui/impl-trait/in-trait/refine-captures.stderr +++ b/tests/ui/impl-trait/in-trait/refine-captures.stderr @@ -1,5 +1,5 @@ warning: impl trait in impl method captures fewer lifetimes than in trait - --> $DIR/refine-captures.rs:8:31 + --> $DIR/refine-captures.rs:6:31 | LL | fn test() -> impl Sized + use<> {} | ^^^^^ @@ -13,7 +13,7 @@ LL | fn test() -> impl Sized + use<'a> {} | ++ warning: impl trait in impl method captures fewer lifetimes than in trait - --> $DIR/refine-captures.rs:22:31 + --> $DIR/refine-captures.rs:20:31 | LL | fn test() -> impl Sized + use<> {} | ^^^^^ @@ -26,7 +26,7 @@ LL | fn test() -> impl Sized + use<'a> {} | ++ warning: impl trait in impl method captures fewer lifetimes than in trait - --> $DIR/refine-captures.rs:27:31 + --> $DIR/refine-captures.rs:25:31 | LL | fn test() -> impl Sized + use<'b> {} | ^^^^^^^ @@ -39,7 +39,7 @@ LL | fn test() -> impl Sized + use<'a, 'b> {} | ++++ error: `impl Trait` must mention all type parameters in scope in `use<...>` - --> $DIR/refine-captures.rs:32:18 + --> $DIR/refine-captures.rs:30:18 | LL | impl TypeParam for u64 { | - type parameter is implicitly captured by this `impl Trait` diff --git a/tests/ui/impl-trait/in-trait/variance.rs b/tests/ui/impl-trait/in-trait/variance.rs index cd2f43fca9a6..c0f569c690ab 100644 --- a/tests/ui/impl-trait/in-trait/variance.rs +++ b/tests/ui/impl-trait/in-trait/variance.rs @@ -1,4 +1,4 @@ -#![feature(rustc_attrs, precise_capturing_in_traits)] +#![feature(rustc_attrs)] #![allow(internal_features)] #![rustc_variance_of_opaques] diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs index 6c2477c9744a..1b52b1702019 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs @@ -1,5 +1,3 @@ -#![feature(precise_capturing_in_traits)] - fn type_param() -> impl Sized + use<> {} //~^ ERROR `impl Trait` must mention all type parameters in scope diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr index 93b44a0c18c2..93c35203f1dc 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr @@ -1,5 +1,5 @@ error: `impl Trait` must mention all type parameters in scope in `use<...>` - --> $DIR/forgot-to-capture-type.rs:3:23 + --> $DIR/forgot-to-capture-type.rs:1:23 | LL | fn type_param() -> impl Sized + use<> {} | - ^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | fn type_param() -> impl Sized + use<> {} = note: currently, all type parameters are required to be mentioned in the precise captures list error: `impl Trait` must mention the `Self` type of the trait in `use<...>` - --> $DIR/forgot-to-capture-type.rs:7:17 + --> $DIR/forgot-to-capture-type.rs:5:17 | LL | trait Foo { | --------- `Self` type parameter is implicitly captured by this `impl Trait` diff --git a/tests/ui/impl-trait/precise-capturing/redundant.rs b/tests/ui/impl-trait/precise-capturing/redundant.rs index 32dc09273175..2385827db228 100644 --- a/tests/ui/impl-trait/precise-capturing/redundant.rs +++ b/tests/ui/impl-trait/precise-capturing/redundant.rs @@ -1,6 +1,5 @@ //@ edition: 2024 -#![feature(precise_capturing_in_traits)] #![deny(impl_trait_redundant_captures)] fn hello<'a>() -> impl Sized + use<'a> {} diff --git a/tests/ui/impl-trait/precise-capturing/redundant.stderr b/tests/ui/impl-trait/precise-capturing/redundant.stderr index 5c8b35c22858..c9f84d360e3c 100644 --- a/tests/ui/impl-trait/precise-capturing/redundant.stderr +++ b/tests/ui/impl-trait/precise-capturing/redundant.stderr @@ -1,5 +1,5 @@ error: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant - --> $DIR/redundant.rs:6:19 + --> $DIR/redundant.rs:5:19 | LL | fn hello<'a>() -> impl Sized + use<'a> {} | ^^^^^^^^^^^^^------- @@ -7,13 +7,13 @@ LL | fn hello<'a>() -> impl Sized + use<'a> {} | help: remove the `use<...>` syntax | note: the lint level is defined here - --> $DIR/redundant.rs:4:9 + --> $DIR/redundant.rs:3:9 | LL | #![deny(impl_trait_redundant_captures)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant - --> $DIR/redundant.rs:11:27 + --> $DIR/redundant.rs:10:27 | LL | fn inherent(&self) -> impl Sized + use<'_> {} | ^^^^^^^^^^^^^------- @@ -21,7 +21,7 @@ LL | fn inherent(&self) -> impl Sized + use<'_> {} | help: remove the `use<...>` syntax error: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant - --> $DIR/redundant.rs:16:22 + --> $DIR/redundant.rs:15:22 | LL | fn in_trait() -> impl Sized + use<'a, Self>; | ^^^^^^^^^^^^^------------- @@ -29,7 +29,7 @@ LL | fn in_trait() -> impl Sized + use<'a, Self>; | help: remove the `use<...>` syntax error: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant - --> $DIR/redundant.rs:20:22 + --> $DIR/redundant.rs:19:22 | LL | fn in_trait() -> impl Sized + use<'a> {} | ^^^^^^^^^^^^^------- diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs index b39c1408c050..f6126c033391 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs +++ b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs @@ -2,8 +2,6 @@ // trait definition, which is not allowed. Due to the default lifetime capture // rules of RPITITs, this is only doable if we use precise capturing. -#![feature(precise_capturing_in_traits)] - pub trait Foo { fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use; } diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr index 45f755d3cc1b..d90660188806 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr @@ -1,5 +1,5 @@ error: return type captures more lifetimes than trait definition - --> $DIR/rpitit-captures-more-method-lifetimes.rs:12:40 + --> $DIR/rpitit-captures-more-method-lifetimes.rs:10:40 | LL | fn bar<'im: 'im>(&'im mut self) -> impl Sized + use<'im> {} | --- ^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | fn bar<'im: 'im>(&'im mut self) -> impl Sized + use<'im> {} | this lifetime was captured | note: hidden type must only reference lifetimes captured by this impl trait - --> $DIR/rpitit-captures-more-method-lifetimes.rs:8:40 + --> $DIR/rpitit-captures-more-method-lifetimes.rs:6:40 | LL | fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use; | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs index b16b0522d6e1..115cab1cb992 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs +++ b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs @@ -1,5 +1,3 @@ -#![feature(precise_capturing_in_traits)] - struct Invariant<'a>(&'a mut &'a mut ()); trait Trait { diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr index 360f0d7e7f37..123e0acf171c 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr @@ -1,5 +1,5 @@ error: return type captures more lifetimes than trait definition - --> $DIR/rpitit-impl-captures-too-much.rs:10:39 + --> $DIR/rpitit-impl-captures-too-much.rs:8:39 | LL | fn hello(self_: Invariant<'_>) -> impl Sized + use; | -- this lifetime was captured @@ -8,7 +8,7 @@ LL | fn hello(self_: Invariant<'_>) -> impl Sized + use<'_> {} | ^^^^^^^^^^^^^^^^^^^^ | note: hidden type must only reference lifetimes captured by this impl trait - --> $DIR/rpitit-impl-captures-too-much.rs:6:39 + --> $DIR/rpitit-impl-captures-too-much.rs:4:39 | LL | fn hello(self_: Invariant<'_>) -> impl Sized + use; | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-outlives-2.rs b/tests/ui/impl-trait/precise-capturing/rpitit-outlives-2.rs index 6f7e1a0eaefa..6fc129a6480c 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit-outlives-2.rs +++ b/tests/ui/impl-trait/precise-capturing/rpitit-outlives-2.rs @@ -2,8 +2,6 @@ // Ensure that we skip uncaptured args from RPITITs when comptuing outlives. -#![feature(precise_capturing_in_traits)] - struct Invariant(*mut T); trait Foo { diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-outlives.rs b/tests/ui/impl-trait/precise-capturing/rpitit-outlives.rs index 94d81d766f72..616368d25cf4 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit-outlives.rs +++ b/tests/ui/impl-trait/precise-capturing/rpitit-outlives.rs @@ -3,8 +3,6 @@ // Ensure that we skip uncaptured args from RPITITs when collecting the regions // to enforce member constraints in opaque type inference. -#![feature(precise_capturing_in_traits)] - struct Invariant(*mut T); trait Foo { diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.rs b/tests/ui/impl-trait/precise-capturing/rpitit.rs index 3f887e8e47f1..91c52817d857 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit.rs +++ b/tests/ui/impl-trait/precise-capturing/rpitit.rs @@ -3,8 +3,6 @@ // To fix this soundly, we need to make sure that all the trait header args // remain captured, since they affect trait selection. -#![feature(precise_capturing_in_traits)] - fn eq_types(_: T, _: T) {} trait TraitLt<'a: 'a> { diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.stderr b/tests/ui/impl-trait/precise-capturing/rpitit.stderr index 498eae54a1c6..ff461e81079b 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit.stderr @@ -1,5 +1,5 @@ error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list - --> $DIR/rpitit.rs:11:19 + --> $DIR/rpitit.rs:9:19 | LL | trait TraitLt<'a: 'a> { | -- all lifetime parameters originating from a trait are captured implicitly @@ -7,7 +7,7 @@ LL | fn hello() -> impl Sized + use; | ^^^^^^^^^^^^^^^^^^^^^^ error: lifetime may not live long enough - --> $DIR/rpitit.rs:15:5 + --> $DIR/rpitit.rs:13:5 | LL | fn trait_lt<'a, 'b, T: for<'r> TraitLt<'r>> () { | -- -- lifetime `'b` defined here @@ -24,7 +24,7 @@ LL | | ); = help: consider adding the following bound: `'a: 'b` error: lifetime may not live long enough - --> $DIR/rpitit.rs:15:5 + --> $DIR/rpitit.rs:13:5 | LL | fn trait_lt<'a, 'b, T: for<'r> TraitLt<'r>> () { | -- -- lifetime `'b` defined here diff --git a/tests/ui/impl-trait/precise-capturing/self-capture.rs b/tests/ui/impl-trait/precise-capturing/self-capture.rs index 15985da50b55..66fbfc780438 100644 --- a/tests/ui/impl-trait/precise-capturing/self-capture.rs +++ b/tests/ui/impl-trait/precise-capturing/self-capture.rs @@ -1,7 +1,5 @@ //@ check-pass -#![feature(precise_capturing_in_traits)] - trait Foo { fn bar<'a>() -> impl Sized + use; } From 264e1addfd72181741188ab318f2542e86ad4d53 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 23 Mar 2025 16:26:03 +0000 Subject: [PATCH 448/745] Rustup to rustc 1.87.0-nightly (b48576b4d 2025-03-22) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index cbed84253fbe..a6b0bf5fba1a 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-03-21" +channel = "nightly-2025-03-23" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From 542dbbdcfed457beb70b2133e57c312537711564 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 23 Mar 2025 17:36:31 +0000 Subject: [PATCH 449/745] Fix rustc testsuite --- scripts/setup_rust_fork.sh | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/scripts/setup_rust_fork.sh b/scripts/setup_rust_fork.sh index c2c8e625f60b..ca6426f2ba9d 100644 --- a/scripts/setup_rust_fork.sh +++ b/scripts/setup_rust_fork.sh @@ -46,6 +46,28 @@ llvm-tools = false std-features = ["panic-unwind", "compiler-builtins-no-f16-f128"] EOF + +cat < Date: Sun, 23 Mar 2025 16:24:39 +0000 Subject: [PATCH 450/745] Visit coroutine kind ty in FlagComputation --- compiler/rustc_middle/src/ty/flags.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 0b8f0e8cd41d..abfc5463c8ff 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -113,6 +113,7 @@ impl FlagComputation { self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE; } + self.add_ty(args.kind_ty()); self.add_ty(args.resume_ty()); self.add_ty(args.return_ty()); self.add_ty(args.witness()); From e4f13e3ccd143b866044f7875d3caf866cfa66fd Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 23 Mar 2025 16:37:27 +0000 Subject: [PATCH 451/745] Remove HAS_TY_COROUTINE --- compiler/rustc_middle/src/ty/flags.rs | 1 - compiler/rustc_type_ir/src/flags.rs | 5 +---- compiler/rustc_type_ir/src/visit.rs | 4 ---- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index abfc5463c8ff..8d5a213b7460 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -128,7 +128,6 @@ impl FlagComputation { if should_remove_further_specializable { self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE; } - self.add_flags(TypeFlags::HAS_TY_COROUTINE); } &ty::Closure(_, args) => { diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index 81aa4a1f19ee..fe401b11f396 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -119,10 +119,7 @@ bitflags::bitflags! { /// Does this value have `InferConst::Fresh`? const HAS_CT_FRESH = 1 << 23; - /// Does this have `Coroutine` or `CoroutineWitness`? - const HAS_TY_COROUTINE = 1 << 24; - /// Does this have any binders with bound vars (e.g. that need to be anonymized)? - const HAS_BINDER_VARS = 1 << 25; + const HAS_BINDER_VARS = 1 << 24; } } diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 119b658a2bf3..2285e0e75de0 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -269,10 +269,6 @@ pub trait TypeVisitableExt: TypeVisitable { self.has_type_flags(TypeFlags::HAS_TY_OPAQUE) } - fn has_coroutines(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_TY_COROUTINE) - } - fn references_error(&self) -> bool { self.has_type_flags(TypeFlags::HAS_ERROR) } From 77a106e61fe8331e646212382cd2ee5d2bbcd149 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 23 Mar 2025 16:44:30 +0000 Subject: [PATCH 452/745] Remove STILL_FURTHER_SPECIALIZABLE special casing --- compiler/rustc_middle/src/ty/flags.rs | 91 +++++---------------------- compiler/rustc_type_ir/src/flags.rs | 13 ++-- 2 files changed, 25 insertions(+), 79 deletions(-) diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 8d5a213b7460..b0c442d28f0a 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -101,63 +101,13 @@ impl FlagComputation { &ty::Param(_) => { self.add_flags(TypeFlags::HAS_TY_PARAM); - self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } - ty::Coroutine(_, args) => { - let args = args.as_coroutine(); - let should_remove_further_specializable = - !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE); - self.add_args(args.parent_args()); - if should_remove_further_specializable { - self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE; - } - - self.add_ty(args.kind_ty()); - self.add_ty(args.resume_ty()); - self.add_ty(args.return_ty()); - self.add_ty(args.witness()); - self.add_ty(args.yield_ty()); - self.add_ty(args.tupled_upvars_ty()); - } - - ty::CoroutineWitness(_, args) => { - let should_remove_further_specializable = - !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE); + &ty::Closure(_, args) + | &ty::Coroutine(_, args) + | &ty::CoroutineClosure(_, args) + | &ty::CoroutineWitness(_, args) => { self.add_args(args); - if should_remove_further_specializable { - self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE; - } - } - - &ty::Closure(_, args) => { - let args = args.as_closure(); - let should_remove_further_specializable = - !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE); - self.add_args(args.parent_args()); - if should_remove_further_specializable { - self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE; - } - - self.add_ty(args.sig_as_fn_ptr_ty()); - self.add_ty(args.kind_ty()); - self.add_ty(args.tupled_upvars_ty()); - } - - &ty::CoroutineClosure(_, args) => { - let args = args.as_coroutine_closure(); - let should_remove_further_specializable = - !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE); - self.add_args(args.parent_args()); - if should_remove_further_specializable { - self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE; - } - - self.add_ty(args.kind_ty()); - self.add_ty(args.signature_parts_ty()); - self.add_ty(args.tupled_upvars_ty()); - self.add_ty(args.coroutine_captures_by_ref_ty()); - self.add_ty(args.coroutine_witness_ty()); } &ty::Bound(debruijn, _) => { @@ -167,21 +117,17 @@ impl FlagComputation { &ty::Placeholder(..) => { self.add_flags(TypeFlags::HAS_TY_PLACEHOLDER); - self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } - &ty::Infer(infer) => { - self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); - match infer { - ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => { - self.add_flags(TypeFlags::HAS_TY_FRESH) - } - - ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => { - self.add_flags(TypeFlags::HAS_TY_INFER) - } + &ty::Infer(infer) => match infer { + ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => { + self.add_flags(TypeFlags::HAS_TY_FRESH) } - } + + ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => { + self.add_flags(TypeFlags::HAS_TY_INFER) + } + }, &ty::Adt(_, args) => { self.add_args(args); @@ -358,24 +304,19 @@ impl FlagComputation { self.add_args(uv.args); self.add_flags(TypeFlags::HAS_CT_PROJECTION); } - ty::ConstKind::Infer(infer) => { - self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); - match infer { - InferConst::Fresh(_) => self.add_flags(TypeFlags::HAS_CT_FRESH), - InferConst::Var(_) => self.add_flags(TypeFlags::HAS_CT_INFER), - } - } + ty::ConstKind::Infer(infer) => match infer { + InferConst::Fresh(_) => self.add_flags(TypeFlags::HAS_CT_FRESH), + InferConst::Var(_) => self.add_flags(TypeFlags::HAS_CT_INFER), + }, ty::ConstKind::Bound(debruijn, _) => { self.add_bound_var(debruijn); self.add_flags(TypeFlags::HAS_CT_BOUND); } ty::ConstKind::Param(_) => { self.add_flags(TypeFlags::HAS_CT_PARAM); - self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } ty::ConstKind::Placeholder(_) => { self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER); - self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } ty::ConstKind::Value(cv) => self.add_ty(cv.ty), ty::ConstKind::Expr(e) => self.add_args(e.args()), diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index fe401b11f396..6a2498242fee 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -111,15 +111,20 @@ bitflags::bitflags! { /// Does this value have parameters/placeholders/inference variables which could be /// replaced later, in a way that would change the results of `impl` specialization? - const STILL_FURTHER_SPECIALIZABLE = 1 << 21; + const STILL_FURTHER_SPECIALIZABLE = TypeFlags::HAS_TY_PARAM.bits() + | TypeFlags::HAS_TY_PLACEHOLDER.bits() + | TypeFlags::HAS_TY_INFER.bits() + | TypeFlags::HAS_CT_PARAM.bits() + | TypeFlags::HAS_CT_PLACEHOLDER.bits() + | TypeFlags::HAS_CT_INFER.bits(); /// Does this value have `InferTy::FreshTy/FreshIntTy/FreshFloatTy`? - const HAS_TY_FRESH = 1 << 22; + const HAS_TY_FRESH = 1 << 21; /// Does this value have `InferConst::Fresh`? - const HAS_CT_FRESH = 1 << 23; + const HAS_CT_FRESH = 1 << 22; /// Does this have any binders with bound vars (e.g. that need to be anonymized)? - const HAS_BINDER_VARS = 1 << 24; + const HAS_BINDER_VARS = 1 << 23; } } From 575f129faa5126869f11ef945276072b097a2b2a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 22 Mar 2025 22:09:16 +0000 Subject: [PATCH 453/745] Obligation::as_goal --- .../src/fn_ctxt/inspect_obligations.rs | 4 ++-- compiler/rustc_infer/src/infer/opaque_types/mod.rs | 3 +-- compiler/rustc_infer/src/traits/mod.rs | 12 ++++++------ compiler/rustc_trait_selection/src/solve/delegate.rs | 2 +- compiler/rustc_trait_selection/src/solve/fulfill.rs | 4 ++-- .../src/solve/fulfill/derive_errors.rs | 8 ++++---- .../rustc_trait_selection/src/traits/coherence.rs | 2 +- 7 files changed, 17 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs index 95b9cb3be627..e068e6079027 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs @@ -1,7 +1,7 @@ //! A utility module to inspect currently ambiguous obligations in the current context. use rustc_infer::traits::{self, ObligationCause, PredicateObligations}; -use rustc_middle::traits::solve::{Goal, GoalSource}; +use rustc_middle::traits::solve::GoalSource; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_span::Span; use rustc_trait_selection::solve::inspect::{ @@ -85,7 +85,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { root_cause: &obligation.cause, }; - let goal = Goal::new(self.tcx, obligation.param_env, obligation.predicate); + let goal = obligation.as_goal(); self.visit_proof_tree(goal, &mut visitor); } diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 3fa1923121a2..215b13337266 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -246,8 +246,7 @@ impl<'tcx> InferCtxt<'tcx> { .eq(DefineOpaqueTypes::Yes, prev, hidden_ty)? .obligations .into_iter() - // FIXME: Shuttling between obligations and goals is awkward. - .map(Goal::from), + .map(|obligation| obligation.as_goal()), ); } } diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index ac641ef56522..b537750f1b51 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -54,6 +54,12 @@ pub struct Obligation<'tcx, T> { pub recursion_depth: usize, } +impl<'tcx, T: Copy> Obligation<'tcx, T> { + pub fn as_goal(&self) -> solve::Goal<'tcx, T> { + solve::Goal { param_env: self.param_env, predicate: self.predicate } + } +} + impl<'tcx, T: PartialEq> PartialEq> for Obligation<'tcx, T> { #[inline] fn eq(&self, other: &Obligation<'tcx, T>) -> bool { @@ -75,12 +81,6 @@ impl Hash for Obligation<'_, T> { } } -impl<'tcx, P> From> for solve::Goal<'tcx, P> { - fn from(value: Obligation<'tcx, P>) -> Self { - solve::Goal { param_env: value.param_env, predicate: value.predicate } - } -} - pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>; pub type TraitObligation<'tcx> = Obligation<'tcx, ty::TraitPredicate<'tcx>>; pub type PolyTraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>; diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index af5a60027ba4..3d9a90eb74e7 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -96,7 +96,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< ) -> Option>>> { crate::traits::wf::unnormalized_obligations(&self.0, param_env, arg, DUMMY_SP, CRATE_DEF_ID) .map(|obligations| { - obligations.into_iter().map(|obligation| obligation.into()).collect() + obligations.into_iter().map(|obligation| obligation.as_goal()).collect() }) } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 704ba6e501d8..192e632a2d5b 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -80,7 +80,7 @@ impl<'tcx> ObligationStorage<'tcx> { // change. // FIXME: is merged, this can be removed. self.overflowed.extend(ExtractIf::new(&mut self.pending, |o| { - let goal = o.clone().into(); + let goal = o.as_goal(); let result = <&SolverDelegate<'tcx>>::from(infcx) .evaluate_root_goal(goal, GenerateProofTree::No, o.cause.span) .0; @@ -161,7 +161,7 @@ where let mut has_changed = false; for obligation in self.obligations.unstalled_for_select() { - let goal = obligation.clone().into(); + let goal = obligation.as_goal(); let result = <&SolverDelegate<'tcx>>::from(infcx) .evaluate_root_goal(goal, GenerateProofTree::No, obligation.cause.span) .0; diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index 352ac7c1a4e6..3a939df25e07 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -10,7 +10,7 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_next_trait_solver::solve::{GenerateProofTree, SolverDelegateEvalExt as _}; -use rustc_type_ir::solve::{Goal, NoSolution}; +use rustc_type_ir::solve::NoSolution; use tracing::{instrument, trace}; use crate::solve::Certainty; @@ -89,7 +89,7 @@ pub(super) fn fulfillment_error_for_stalled<'tcx>( let (code, refine_obligation) = infcx.probe(|_| { match <&SolverDelegate<'tcx>>::from(infcx) .evaluate_root_goal( - root_obligation.clone().into(), + root_obligation.as_goal(), GenerateProofTree::No, root_obligation.cause.span, ) @@ -155,7 +155,7 @@ fn find_best_leaf_obligation<'tcx>( .fudge_inference_if_ok(|| { infcx .visit_proof_tree( - obligation.clone().into(), + obligation.as_goal(), &mut BestObligation { obligation: obligation.clone(), consider_ambiguities }, ) .break_value() @@ -245,7 +245,7 @@ impl<'tcx> BestObligation<'tcx> { { let nested_goal = candidate.instantiate_proof_tree_for_nested_goal( GoalSource::Misc, - Goal::new(infcx.tcx, obligation.param_env, obligation.predicate), + obligation.as_goal(), self.span(), ); // Skip nested goals that aren't the *reason* for our goal's failure. diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 4c7172c32781..bcc247ba53c2 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -625,7 +625,7 @@ fn compute_intercrate_ambiguity_causes<'tcx>( let mut causes: FxIndexSet> = Default::default(); for obligation in obligations { - search_ambiguity_causes(infcx, obligation.clone().into(), &mut causes); + search_ambiguity_causes(infcx, obligation.as_goal(), &mut causes); } causes From d588bc2a2b49cb9f18fe051774a3f4a41ab5068e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 22 Mar 2025 21:01:11 +0000 Subject: [PATCH 454/745] Don't super fold const in Resolver --- compiler/rustc_hir_typeck/src/writeback.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 6a3417ae5d6f..748cb11290d9 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -864,10 +864,7 @@ impl<'cx, 'tcx> TypeFolder> for Resolver<'cx, 'tcx> { } fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { - self.handle_term(ct, ty::Const::outer_exclusive_binder, |tcx, guar| { - ty::Const::new_error(tcx, guar) - }) - .super_fold_with(self) + self.handle_term(ct, ty::Const::outer_exclusive_binder, ty::Const::new_error) } fn fold_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { From fad34c603cd6c7e432f297e682bb68a2cf55df0b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 23 Mar 2025 18:34:33 +0000 Subject: [PATCH 455/745] Explicitly don't fold coroutine obligations in writeback --- compiler/rustc_hir_typeck/src/writeback.rs | 45 +++++++++++++++------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 748cb11290d9..b63c0b6ab7e0 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -548,7 +548,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let fcx_typeck_results = self.fcx.typeck_results.borrow(); assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner); for (predicate, cause) in &fcx_typeck_results.coroutine_stalled_predicates { - let (predicate, cause) = self.resolve((*predicate, cause.clone()), &cause.span); + let (predicate, cause) = + self.resolve_coroutine_predicate((*predicate, cause.clone()), &cause.span); self.typeck_results.coroutine_stalled_predicates.insert((predicate, cause)); } } @@ -730,7 +731,25 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { T: TypeFoldable>, { let value = self.fcx.resolve_vars_if_possible(value); - let value = value.fold_with(&mut Resolver::new(self.fcx, span, self.body)); + let value = value.fold_with(&mut Resolver::new(self.fcx, span, self.body, true)); + assert!(!value.has_infer()); + + // We may have introduced e.g. `ty::Error`, if inference failed, make sure + // to mark the `TypeckResults` as tainted in that case, so that downstream + // users of the typeck results don't produce extra errors, or worse, ICEs. + if let Err(guar) = value.error_reported() { + self.typeck_results.tainted_by_errors = Some(guar); + } + + value + } + + fn resolve_coroutine_predicate(&mut self, value: T, span: &dyn Locatable) -> T + where + T: TypeFoldable>, + { + let value = self.fcx.resolve_vars_if_possible(value); + let value = value.fold_with(&mut Resolver::new(self.fcx, span, self.body, false)); assert!(!value.has_infer()); // We may have introduced e.g. `ty::Error`, if inference failed, make sure @@ -774,8 +793,9 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { fcx: &'cx FnCtxt<'cx, 'tcx>, span: &'cx dyn Locatable, body: &'tcx hir::Body<'tcx>, + should_normalize: bool, ) -> Resolver<'cx, 'tcx> { - Resolver { fcx, span, body, should_normalize: fcx.next_trait_solver() } + Resolver { fcx, span, body, should_normalize } } fn report_error(&self, p: impl Into>) -> ErrorGuaranteed { @@ -805,10 +825,9 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { T: Into> + TypeSuperFoldable> + Copy, { let tcx = self.fcx.tcx; - // We must deeply normalize in the new solver, since later lints - // expect that types that show up in the typeck are fully - // normalized. - let mut value = if self.should_normalize { + // We must deeply normalize in the new solver, since later lints expect + // that types that show up in the typeck are fully normalized. + let mut value = if self.should_normalize && self.fcx.next_trait_solver() { let body_id = tcx.hir_body_owner_def_id(self.body.id()); let cause = ObligationCause::misc(self.span.to_span(tcx), body_id); let at = self.fcx.at(&cause, self.fcx.param_env); @@ -868,13 +887,11 @@ impl<'cx, 'tcx> TypeFolder> for Resolver<'cx, 'tcx> { } fn fold_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { - // Do not normalize predicates in the new solver. The new solver is - // supposed to handle unnormalized predicates and incorrectly normalizing - // them can be unsound, e.g. for `WellFormed` predicates. - let prev = mem::replace(&mut self.should_normalize, false); - let predicate = predicate.super_fold_with(self); - self.should_normalize = prev; - predicate + assert!( + !self.should_normalize, + "normalizing predicates in writeback is not generally sound" + ); + predicate.super_fold_with(self) } } From 6948343b9fd4855377fd68c93b9c027d525df590 Mon Sep 17 00:00:00 2001 From: Hadrien Eyraud Date: Thu, 9 Jan 2025 18:39:40 +0100 Subject: [PATCH 456/745] fix: Check empty SIMD vector in inline asm --- .../rustc_hir_analysis/src/check/intrinsicck.rs | 8 ++++++++ tests/crashes/134334.rs | 9 --------- tests/ui/simd/empty-simd-vector-in-operand.rs | 14 ++++++++++++++ tests/ui/simd/empty-simd-vector-in-operand.stderr | 15 +++++++++++++++ 4 files changed, 37 insertions(+), 9 deletions(-) delete mode 100644 tests/crashes/134334.rs create mode 100644 tests/ui/simd/empty-simd-vector-in-operand.rs create mode 100644 tests/ui/simd/empty-simd-vector-in-operand.stderr diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index d63165f0f169..32a582aadc1c 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -29,6 +29,7 @@ enum NonAsmTypeReason<'tcx> { Invalid(Ty<'tcx>), InvalidElement(DefId, Ty<'tcx>), NotSizedPtr(Ty<'tcx>), + EmptySIMDArray(Ty<'tcx>), } impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { @@ -102,6 +103,9 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { } ty::Adt(adt, args) if adt.repr().simd() => { let fields = &adt.non_enum_variant().fields; + if fields.is_empty() { + return Err(NonAsmTypeReason::EmptySIMDArray(ty)); + } let field = &fields[FieldIdx::ZERO]; let elem_ty = field.ty(self.tcx(), args); @@ -226,6 +230,10 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { can be used as arguments for inline assembly", ).emit(); } + NonAsmTypeReason::EmptySIMDArray(ty) => { + let msg = format!("use of empty SIMD vector `{ty}`"); + self.infcx.dcx().struct_span_err(expr.span, msg).emit(); + } } return None; } diff --git a/tests/crashes/134334.rs b/tests/crashes/134334.rs deleted file mode 100644 index d99df7bdc1ed..000000000000 --- a/tests/crashes/134334.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ known-bug: #134334 -//@ only-x86_64 - -#[repr(simd)] -struct A(); - -fn main() { - std::arch::asm!("{}", in(xmm_reg) A()); -} diff --git a/tests/ui/simd/empty-simd-vector-in-operand.rs b/tests/ui/simd/empty-simd-vector-in-operand.rs new file mode 100644 index 000000000000..ae21461eb95b --- /dev/null +++ b/tests/ui/simd/empty-simd-vector-in-operand.rs @@ -0,0 +1,14 @@ +// Regression test for issue #134224. + +#![feature(repr_simd)] + +#[repr(simd)] +struct A(); +//~^ ERROR SIMD vector cannot be empty + +fn main() { + unsafe { + std::arch::asm!("{}", in(xmm_reg) A()); + //~^ use of empty SIMD vector `A` + } +} diff --git a/tests/ui/simd/empty-simd-vector-in-operand.stderr b/tests/ui/simd/empty-simd-vector-in-operand.stderr new file mode 100644 index 000000000000..a0faf5f06d20 --- /dev/null +++ b/tests/ui/simd/empty-simd-vector-in-operand.stderr @@ -0,0 +1,15 @@ +error[E0075]: SIMD vector cannot be empty + --> $DIR/empty-simd-vector-in-operand.rs:6:1 + | +LL | struct A(); + | ^^^^^^^^ + +error: use of empty SIMD vector `A` + --> $DIR/empty-simd-vector-in-operand.rs:11:43 + | +LL | std::arch::asm!("{}", in(xmm_reg) A()); + | ^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0075`. From ff699ce9f55e974e9181a800203fae9d73b90e37 Mon Sep 17 00:00:00 2001 From: Hadrien Eyraud Date: Mon, 3 Feb 2025 14:16:27 +0100 Subject: [PATCH 457/745] fix: running the test only on x86_64. The test was failing on aarch64-apple-darwin. --- tests/ui/simd/empty-simd-vector-in-operand.rs | 1 + tests/ui/simd/empty-simd-vector-in-operand.stderr | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/ui/simd/empty-simd-vector-in-operand.rs b/tests/ui/simd/empty-simd-vector-in-operand.rs index ae21461eb95b..2a2a6c0737db 100644 --- a/tests/ui/simd/empty-simd-vector-in-operand.rs +++ b/tests/ui/simd/empty-simd-vector-in-operand.rs @@ -1,4 +1,5 @@ // Regression test for issue #134224. +//@ only-x86_64 #![feature(repr_simd)] diff --git a/tests/ui/simd/empty-simd-vector-in-operand.stderr b/tests/ui/simd/empty-simd-vector-in-operand.stderr index a0faf5f06d20..7210dddd461f 100644 --- a/tests/ui/simd/empty-simd-vector-in-operand.stderr +++ b/tests/ui/simd/empty-simd-vector-in-operand.stderr @@ -1,11 +1,11 @@ error[E0075]: SIMD vector cannot be empty - --> $DIR/empty-simd-vector-in-operand.rs:6:1 + --> $DIR/empty-simd-vector-in-operand.rs:7:1 | LL | struct A(); | ^^^^^^^^ error: use of empty SIMD vector `A` - --> $DIR/empty-simd-vector-in-operand.rs:11:43 + --> $DIR/empty-simd-vector-in-operand.rs:12:43 | LL | std::arch::asm!("{}", in(xmm_reg) A()); | ^^^ From 7210df1a9ac3cec2e925012bcc9190c13b5a2402 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 23 Mar 2025 18:45:34 +0100 Subject: [PATCH 458/745] Rework `--print` options documentation --- src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/command-line-arguments.md | 53 +---- .../command-line-arguments/print-options.md | 212 ++++++++++++++++++ 3 files changed, 214 insertions(+), 52 deletions(-) create mode 100644 src/doc/rustc/src/command-line-arguments/print-options.md diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 542ee9fffce3..e258b0a76ffd 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -2,6 +2,7 @@ - [What is rustc?](what-is-rustc.md) - [Command-line Arguments](command-line-arguments.md) + - [Print Options](command-line-arguments/print-options.md) - [Codegen Options](codegen-options/index.md) - [Jobserver](jobserver.md) - [Lints](lints/index.md) diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index 9dd2e7de1b33..b704cee705b0 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -247,58 +247,7 @@ types to stdout at the same time will result in an error. ## `--print`: print compiler information -This flag prints out various information about the compiler. This flag may be -specified multiple times, and the information is printed in the order the -flags are specified. Specifying a `--print` flag will usually disable the -[`--emit`](#option-emit) step and will only print the requested information. -The valid types of print values are: - -- `crate-name` — The name of the crate. -- `file-names` — The names of the files created by the `link` emit kind. -- `sysroot` — Path to the sysroot. -- `target-libdir` — Path to the target libdir. -- `host-tuple` — The target-tuple string of the host compiler (e.g. `x86_64-unknown-linux-gnu`) -- `cfg` — List of cfg values. See [conditional compilation] for more - information about cfg values. -- `target-list` — List of known targets. The target may be selected with the - `--target` flag. -- `target-cpus` — List of available CPU values for the current target. The - target CPU may be selected with the [`-C target-cpu=val` - flag](codegen-options/index.md#target-cpu). -- `target-features` — List of available target features for the current - target. Target features may be enabled with the [`-C target-feature=val` - flag](codegen-options/index.md#target-feature). This flag is unsafe. See - [known issues](targets/known-issues.md) for more details. -- `relocation-models` — List of relocation models. Relocation models may be - selected with the [`-C relocation-model=val` - flag](codegen-options/index.md#relocation-model). -- `code-models` — List of code models. Code models may be selected with the - [`-C code-model=val` flag](codegen-options/index.md#code-model). -- `tls-models` — List of Thread Local Storage models supported. The model may - be selected with the `-Z tls-model=val` flag. -- `native-static-libs` — This may be used when creating a `staticlib` crate - type. If this is the only flag, it will perform a full compilation and - include a diagnostic note that indicates the linker flags to use when - linking the resulting static library. The note starts with the text - `native-static-libs:` to make it easier to fetch the output. -- `link-args` — This flag does not disable the `--emit` step. When linking, - this flag causes `rustc` to print the full linker invocation in a - human-readable form. This can be useful when debugging linker options. The - exact format of this debugging output is not a stable guarantee, other than - that it will include the linker executable and the text of each command-line - argument passed to the linker. -- `deployment-target` — The currently selected [deployment target] (or minimum OS version) - for the selected Apple platform target. This value can be used or passed along to other - components alongside a Rust build that need this information, such as C compilers. - This returns rustc's minimum supported deployment target if no `*_DEPLOYMENT_TARGET` variable - is present in the environment, or otherwise returns the variable's parsed value. - -A filepath may optionally be specified for each requested information kind, in -the format `--print KIND=PATH`, just like for `--emit`. When a path is -specified, information will be written there instead of to stdout. - -[conditional compilation]: ../reference/conditional-compilation.html -[deployment target]: https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/cross_development/Configuring/configuring.html +This flag will allow you to set [print options](command-line-arguments/print-options.md). ## `-g`: include debug information diff --git a/src/doc/rustc/src/command-line-arguments/print-options.md b/src/doc/rustc/src/command-line-arguments/print-options.md new file mode 100644 index 000000000000..1f33e91e5d1b --- /dev/null +++ b/src/doc/rustc/src/command-line-arguments/print-options.md @@ -0,0 +1,212 @@ +# Print Options + +All of these options are passed to `rustc` via the `--print` flag. + +Those options prints out various information about the compiler. Multiple options can be +specified, and the information is printed in the order the options are specified. + +Specifying an option will usually disable the [`--emit`](../command-line-arguments.md#option-emit) +step and will only print the requested information. + +A filepath may optionally be specified for each requested information kind, in the format +`--print KIND=PATH`, just like for `--emit`. When a path is specified, information will be +written there instead of to stdout. + +## `crate-name` + +The name of the crate. + +Generally coming from either from the `#![crate_name = "..."]` attribute, +[`--crate-name` flag](../command-line-arguments.md#option-crate-name) or the filename. + +Example: + +```bash +$ rustc --print crate-name --crate-name my_crate a.rs +my_crate +``` + +## `file-names` + +The names of the files created by the `link` emit kind. + +## `sysroot` + +Abosulte path to the sysroot. + +Example (with rustup and the stable toolchain): + +```bash +$ rustc --print sysroot a.rs +/home/[REDACTED]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu +``` + +## `target-libdir` + +Path to the target libdir. + +Example (with rustup and the stable toolchain): + +```bash +$ rustc --print target-libdir a.rs +/home/[REDACTED]/.rustup/toolchains/beta-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib +``` + +## `host-tuple` + +The target-tuple string of the host compiler. + +Example: + +```bash +$ rustc --print host-tuple a.rs +x86_64-unknown-linux-gnu +``` + +Example with the `--target` flag: + +```bash +$ rustc --print host-tuple --target "armv7-unknown-linux-gnueabihf" a.rs +x86_64-unknown-linux-gnu +``` + +## `cfg` + +List of cfg values. See [conditional compilation] for more information about cfg values. + +Example (for `x86_64-unknown-linux-gnu`): + +```bash +$ rustc --print cfg a.rs +debug_assertions +panic="unwind" +target_abi="" +target_arch="x86_64" +target_endian="little" +target_env="gnu" +target_family="unix" +target_feature="fxsr" +target_feature="sse" +target_feature="sse2" +target_has_atomic="16" +target_has_atomic="32" +target_has_atomic="64" +target_has_atomic="8" +target_has_atomic="ptr" +target_os="linux" +target_pointer_width="64" +target_vendor="unknown" +unix +``` + +## `target-list` + +List of known targets. The target may be selected with the `--target` flag. + +## `target-cpus` + +List of available CPU values for the current target. The target CPU may be selected with +the [`-C target-cpu=val` flag](../codegen-options/index.md#target-cpu). + +## `target-features` + +List of available target features for the *current target*. + +Target features may be enabled with the **unsafe** +[`-C target-feature=val` flag](../codegen-options/index.md#target-feature). + +See [known issues](../targets/known-issues.md) for more details. + +## `relocation-models` + +List of relocation models. Relocation models may be selected with the +[`-C relocation-model=val` flag](../codegen-options/index.md#relocation-model). + +Example: + +```bash +$ rustc --print relocation-models a.rs +Available relocation models: + static + pic + pie + dynamic-no-pic + ropi + rwpi + ropi-rwpi + default +``` + +## `code-models` + +List of code models. Code models may be selected with the +[`-C code-model=val` flag](../codegen-options/index.md#code-model). + +Example: + +```bash +$ rustc --print code-models a.rs +Available code models: + tiny + small + kernel + medium + large +``` + +## `tls-models` + +List of Thread Local Storage models supported. The model may be selected with the +`-Z tls-model=val` flag. + +Example: + +```bash +$ rustc --print tls-models a.rs +Available TLS models: + global-dynamic + local-dynamic + initial-exec + local-exec + emulated +``` + +## `native-static-libs` + +This may be used when creating a `staticlib` crate type. + +If this is the only flag, it will perform a full compilation and include a diagnostic note +that indicates the linker flags to use when linking the resulting static library. + +The note starts with the text `native-static-libs:` to make it easier to fetch the output. + +Example: + +```bash +$ rustc --print native-static-libs --crate-type staticlib a.rs +note: Link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms. + +note: native-static-libs: -lgcc_s -lutil [REDACTED] -lpthread -lm -ldl -lc +``` + +## `link-args` + +This flag does not disable the `--emit` step. This can be useful when debugging linker options. + +When linking, this flag causes `rustc` to print the full linker invocation in a human-readable +form. The exact format of this debugging output is not a stable guarantee, other than that it +will include the linker executable and the text of each command-line argument passed to the +linker. + +## `deployment-target` + +The currently selected [deployment target] (or minimum OS version) for the selected Apple +platform target. + +This value can be used or passed along to other components alongside a Rust build that need +this information, such as C compilers. This returns rustc's minimum supported deployment target +if no `*_DEPLOYMENT_TARGET` variable is present in the environment, or otherwise returns the +variable's parsed value. + +[conditional compilation]: ../../reference/conditional-compilation.html +[deployment target]: https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/cross_development/Configuring/configuring.html From 7781346243c1e1a038e0bc6fa11e5e1aefea7d4a Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 23 Mar 2025 15:27:31 -0700 Subject: [PATCH 459/745] Stop using specialization for this Uses `__`-named `doc(hidden)` methods instead. --- library/core/src/cmp.rs | 162 ++++++++++-------- library/core/src/tuple.rs | 13 +- ...e_ord.demo_ge_partial.PreCodegen.after.mir | 2 +- ...ple_ord.demo_le_total.PreCodegen.after.mir | 2 +- 4 files changed, 95 insertions(+), 84 deletions(-) diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index af14c4b50725..0b0dbf723b65 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -29,7 +29,7 @@ mod bytewise; pub(crate) use bytewise::BytewiseEq; use self::Ordering::*; -use crate::ops::ControlFlow::{self, Break, Continue}; +use crate::ops::ControlFlow; /// Trait for comparisons using the equality operator. /// @@ -1436,6 +1436,67 @@ pub trait PartialOrd: PartialEq { fn ge(&self, other: &Rhs) -> bool { self.partial_cmp(other).is_some_and(Ordering::is_ge) } + + /// If `self == other`, returns `ControlFlow::Continue(())`. + /// Otherwise, returns `ControlFlow::Break(self < other)`. + /// + /// This is useful for chaining together calls when implementing a lexical + /// `PartialOrd::lt`, as it allows types (like primitives) which can cheaply + /// check `==` and `<` separately to do rather than needing to calculate + /// (then optimize out) the three-way `Ordering` result. + #[inline] + #[must_use] + // Added to improve the behaviour of tuples; not necessarily stabilization-track. + #[unstable(feature = "partial_ord_chaining_methods", issue = "none")] + #[doc(hidden)] + fn __chaining_lt(&self, other: &Rhs) -> ControlFlow { + default_chaining_impl(self, other, Ordering::is_lt) + } + + /// Same as `__chaining_lt`, but for `<=` instead of `<`. + #[inline] + #[must_use] + #[unstable(feature = "partial_ord_chaining_methods", issue = "none")] + #[doc(hidden)] + fn __chaining_le(&self, other: &Rhs) -> ControlFlow { + default_chaining_impl(self, other, Ordering::is_le) + } + + /// Same as `__chaining_lt`, but for `>` instead of `<`. + #[inline] + #[must_use] + #[unstable(feature = "partial_ord_chaining_methods", issue = "none")] + #[doc(hidden)] + fn __chaining_gt(&self, other: &Rhs) -> ControlFlow { + default_chaining_impl(self, other, Ordering::is_gt) + } + + /// Same as `__chaining_lt`, but for `>=` instead of `<`. + #[inline] + #[must_use] + #[unstable(feature = "partial_ord_chaining_methods", issue = "none")] + #[doc(hidden)] + fn __chaining_ge(&self, other: &Rhs) -> ControlFlow { + default_chaining_impl(self, other, Ordering::is_ge) + } +} + +fn default_chaining_impl( + lhs: &T, + rhs: &U, + p: impl FnOnce(Ordering) -> bool, +) -> ControlFlow +where + T: PartialOrd, +{ + // It's important that this only call `partial_cmp` once, not call `eq` then + // one of the relational operators. We don't want to `bcmp`-then-`memcp` a + // `String`, for example, or similarly for other data structures (#108157). + match >::partial_cmp(lhs, rhs) { + Some(Equal) => ControlFlow::Continue(()), + Some(c) => ControlFlow::Break(p(c)), + None => ControlFlow::Break(false), + } } /// Derive macro generating an impl of the trait [`PartialOrd`]. @@ -1447,54 +1508,6 @@ pub macro PartialOrd($item:item) { /* compiler built-in */ } -/// Helpers for chaining together field PartialOrds into the full type's ordering. -/// -/// If the two values are equal, returns `ControlFlow::Continue`. -/// If the two values are not equal, returns `ControlFlow::Break(self OP other)`. -/// -/// This allows simple types like `i32` and `f64` to just emit two comparisons -/// directly, instead of needing to optimize the 3-way comparison. -/// -/// Currently this is done using specialization, but it doesn't need that: -/// it could be provided methods on `PartialOrd` instead and work fine. -pub(crate) trait SpecChainingPartialOrd: PartialOrd { - fn spec_chain_lt(&self, other: &Rhs) -> ControlFlow; - fn spec_chain_le(&self, other: &Rhs) -> ControlFlow; - fn spec_chain_gt(&self, other: &Rhs) -> ControlFlow; - fn spec_chain_ge(&self, other: &Rhs) -> ControlFlow; -} - -impl, U> SpecChainingPartialOrd for T { - #[inline] - default fn spec_chain_lt(&self, other: &U) -> ControlFlow { - match PartialOrd::partial_cmp(self, other) { - Some(Equal) => Continue(()), - c => Break(c.is_some_and(Ordering::is_lt)), - } - } - #[inline] - default fn spec_chain_le(&self, other: &U) -> ControlFlow { - match PartialOrd::partial_cmp(self, other) { - Some(Equal) => Continue(()), - c => Break(c.is_some_and(Ordering::is_le)), - } - } - #[inline] - default fn spec_chain_gt(&self, other: &U) -> ControlFlow { - match PartialOrd::partial_cmp(self, other) { - Some(Equal) => Continue(()), - c => Break(c.is_some_and(Ordering::is_gt)), - } - } - #[inline] - default fn spec_chain_ge(&self, other: &U) -> ControlFlow { - match PartialOrd::partial_cmp(self, other) { - Some(Equal) => Continue(()), - c => Break(c.is_some_and(Ordering::is_ge)), - } - } -} - /// Compares and returns the minimum of two values. /// /// Returns the first argument if the comparison determines them to be equal. @@ -1829,32 +1842,31 @@ mod impls { eq_impl! { () bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - macro_rules! chaining_impl { + macro_rules! chaining_methods_impl { ($t:ty) => { // These implementations are the same for `Ord` or `PartialOrd` types // because if either is NAN the `==` test will fail so we end up in // the `Break` case and the comparison will correctly return `false`. - impl super::SpecChainingPartialOrd<$t> for $t { - #[inline] - fn spec_chain_lt(&self, other: &Self) -> ControlFlow { - let (lhs, rhs) = (*self, *other); - if lhs == rhs { Continue(()) } else { Break(lhs < rhs) } - } - #[inline] - fn spec_chain_le(&self, other: &Self) -> ControlFlow { - let (lhs, rhs) = (*self, *other); - if lhs == rhs { Continue(()) } else { Break(lhs <= rhs) } - } - #[inline] - fn spec_chain_gt(&self, other: &Self) -> ControlFlow { - let (lhs, rhs) = (*self, *other); - if lhs == rhs { Continue(()) } else { Break(lhs > rhs) } - } - #[inline] - fn spec_chain_ge(&self, other: &Self) -> ControlFlow { - let (lhs, rhs) = (*self, *other); - if lhs == rhs { Continue(()) } else { Break(lhs >= rhs) } - } + + #[inline] + fn __chaining_lt(&self, other: &Self) -> ControlFlow { + let (lhs, rhs) = (*self, *other); + if lhs == rhs { Continue(()) } else { Break(lhs < rhs) } + } + #[inline] + fn __chaining_le(&self, other: &Self) -> ControlFlow { + let (lhs, rhs) = (*self, *other); + if lhs == rhs { Continue(()) } else { Break(lhs <= rhs) } + } + #[inline] + fn __chaining_gt(&self, other: &Self) -> ControlFlow { + let (lhs, rhs) = (*self, *other); + if lhs == rhs { Continue(()) } else { Break(lhs > rhs) } + } + #[inline] + fn __chaining_ge(&self, other: &Self) -> ControlFlow { + let (lhs, rhs) = (*self, *other); + if lhs == rhs { Continue(()) } else { Break(lhs >= rhs) } } }; } @@ -1880,9 +1892,9 @@ mod impls { fn ge(&self, other: &$t) -> bool { (*self) >= (*other) } #[inline(always)] fn gt(&self, other: &$t) -> bool { (*self) > (*other) } - } - chaining_impl!($t); + chaining_methods_impl!($t); + } )*) } @@ -1920,9 +1932,9 @@ mod impls { fn ge(&self, other: &$t) -> bool { (*self) >= (*other) } #[inline(always)] fn gt(&self, other: &$t) -> bool { (*self) > (*other) } - } - chaining_impl!($t); + chaining_methods_impl!($t); + } #[stable(feature = "rust1", since = "1.0.0")] impl Ord for $t { diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs index 75faaa06ee7f..d754bb903430 100644 --- a/library/core/src/tuple.rs +++ b/library/core/src/tuple.rs @@ -1,7 +1,6 @@ // See core/src/primitive_docs.rs for documentation. use crate::cmp::Ordering::{self, *}; -use crate::cmp::SpecChainingPartialOrd; use crate::marker::{ConstParamTy_, StructuralPartialEq, UnsizedConstParamTy}; use crate::ops::ControlFlow::{Break, Continue}; @@ -82,19 +81,19 @@ macro_rules! tuple_impls { } #[inline] fn lt(&self, other: &($($T,)+)) -> bool { - lexical_ord!(lt, spec_chain_lt, $( ${ignore($T)} self.${index()}, other.${index()} ),+) + lexical_ord!(lt, __chaining_lt, $( ${ignore($T)} self.${index()}, other.${index()} ),+) } #[inline] fn le(&self, other: &($($T,)+)) -> bool { - lexical_ord!(le, spec_chain_le, $( ${ignore($T)} self.${index()}, other.${index()} ),+) + lexical_ord!(le, __chaining_le, $( ${ignore($T)} self.${index()}, other.${index()} ),+) } #[inline] fn ge(&self, other: &($($T,)+)) -> bool { - lexical_ord!(ge, spec_chain_ge, $( ${ignore($T)} self.${index()}, other.${index()} ),+) + lexical_ord!(ge, __chaining_ge, $( ${ignore($T)} self.${index()}, other.${index()} ),+) } #[inline] fn gt(&self, other: &($($T,)+)) -> bool { - lexical_ord!(gt, spec_chain_gt, $( ${ignore($T)} self.${index()}, other.${index()} ),+) + lexical_ord!(gt, __chaining_gt, $( ${ignore($T)} self.${index()}, other.${index()} ),+) } } } @@ -173,11 +172,11 @@ macro_rules! maybe_tuple_doc { // `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, opt_is_lt, a1, b1, // a2, b2, a3, b3)` (and similarly for `lexical_cmp`) // -// `$chain_rel` is the method from `SpecChainingPartialOrd` to use for all but the +// `$chain_rel` is the chaining method from `PartialOrd` to use for all but the // final value, to produce better results for simple primitives. macro_rules! lexical_ord { ($rel: ident, $chain_rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {{ - match SpecChainingPartialOrd::$chain_rel(&$a, &$b) { + match PartialOrd::$chain_rel(&$a, &$b) { Break(val) => val, Continue(()) => lexical_ord!($rel, $chain_rel, $($rest_a, $rest_b),+), } diff --git a/tests/mir-opt/pre-codegen/tuple_ord.demo_ge_partial.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/tuple_ord.demo_ge_partial.PreCodegen.after.mir index 6531683b6445..dd2eebc8f4a1 100644 --- a/tests/mir-opt/pre-codegen/tuple_ord.demo_ge_partial.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/tuple_ord.demo_ge_partial.PreCodegen.after.mir @@ -10,7 +10,7 @@ fn demo_ge_partial(_1: &(f32, f32), _2: &(f32, f32)) -> bool { let _8: bool; scope 3 { } - scope 4 (inlined std::cmp::impls:: for f32>::spec_chain_ge) { + scope 4 (inlined std::cmp::impls::::__chaining_ge) { let mut _3: f32; let mut _4: f32; let mut _5: bool; diff --git a/tests/mir-opt/pre-codegen/tuple_ord.demo_le_total.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/tuple_ord.demo_le_total.PreCodegen.after.mir index d252052f0aef..ea1d164cefaf 100644 --- a/tests/mir-opt/pre-codegen/tuple_ord.demo_le_total.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/tuple_ord.demo_le_total.PreCodegen.after.mir @@ -10,7 +10,7 @@ fn demo_le_total(_1: &(u16, i16), _2: &(u16, i16)) -> bool { let _8: bool; scope 3 { } - scope 4 (inlined std::cmp::impls:: for u16>::spec_chain_le) { + scope 4 (inlined std::cmp::impls::::__chaining_le) { let mut _3: u16; let mut _4: u16; let mut _5: bool; From f390dd7911561f4d377a51c7ef2f423d0e484ea0 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Mon, 24 Mar 2025 01:02:07 +0100 Subject: [PATCH 460/745] Add do_not_recommend typo help --- compiler/rustc_resolve/src/macros.rs | 14 +++++++------- tests/ui/diagnostic_namespace/suggest_typos.rs | 5 +++++ tests/ui/diagnostic_namespace/suggest_typos.stderr | 14 +++++++++++++- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index c4304a7a6df6..34441d313f59 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -28,7 +28,7 @@ use rustc_session::lint::builtin::{ UNUSED_MACRO_RULES, UNUSED_MACROS, }; use rustc_session::parse::feature_err; -use rustc_span::edit_distance::edit_distance; +use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; use rustc_span::hygiene::{self, AstPass, ExpnData, ExpnKind, LocalExpnId, MacroKind}; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; @@ -652,13 +652,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if res == Res::NonMacroAttr(NonMacroAttrKind::Tool) && let [namespace, attribute, ..] = &*path.segments && namespace.ident.name == sym::diagnostic - && !(attribute.ident.name == sym::on_unimplemented - || attribute.ident.name == sym::do_not_recommend) + && ![sym::on_unimplemented, sym::do_not_recommend].contains(&attribute.ident.name) { - let distance = - edit_distance(attribute.ident.name.as_str(), sym::on_unimplemented.as_str(), 5); - - let typo_name = distance.map(|_| sym::on_unimplemented); + let typo_name = find_best_match_for_name( + &[sym::on_unimplemented, sym::do_not_recommend], + attribute.ident.name, + Some(5), + ); self.tcx.sess.psess.buffer_lint( UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, diff --git a/tests/ui/diagnostic_namespace/suggest_typos.rs b/tests/ui/diagnostic_namespace/suggest_typos.rs index 6fa4f800462f..8d1dc6f59da9 100644 --- a/tests/ui/diagnostic_namespace/suggest_typos.rs +++ b/tests/ui/diagnostic_namespace/suggest_typos.rs @@ -16,4 +16,9 @@ trait Y{} //~^^HELP an attribute with a similar name exists trait Z{} +#[diagnostic::dont_recommend] +//~^ERROR unknown diagnostic attribute +//~^^HELP an attribute with a similar name exists +impl X for u8 {} + fn main(){} diff --git a/tests/ui/diagnostic_namespace/suggest_typos.stderr b/tests/ui/diagnostic_namespace/suggest_typos.stderr index 86d778c6ec05..1f19fd4bbcf5 100644 --- a/tests/ui/diagnostic_namespace/suggest_typos.stderr +++ b/tests/ui/diagnostic_namespace/suggest_typos.stderr @@ -37,5 +37,17 @@ help: an attribute with a similar name exists LL | #[diagnostic::on_unimplemented] | ++ -error: aborting due to 3 previous errors +error: unknown diagnostic attribute + --> $DIR/suggest_typos.rs:19:15 + | +LL | #[diagnostic::dont_recommend] + | ^^^^^^^^^^^^^^ + | +help: an attribute with a similar name exists + | +LL - #[diagnostic::dont_recommend] +LL + #[diagnostic::do_not_recommend] + | + +error: aborting due to 4 previous errors From 95181ae170e6961bf541c01dee8320f026e85d0a Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 20 Mar 2025 02:12:40 +0000 Subject: [PATCH 461/745] Update `compiler-builtins` to 0.1.152 Includes the following changes related to unordered atomics: * Remove element_unordered_atomic intrinsics [1] * Remove use of `atomic_load_unordered` and undefined behaviour [2] There are a handful of other small changes, but nothing else user-visible. [1]: https://github.com/rust-lang/compiler-builtins/pull/789 [2]: https://github.com/rust-lang/compiler-builtins/pull/790 --- ...029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch | 4 ++-- library/Cargo.lock | 4 ++-- library/alloc/Cargo.toml | 2 +- library/std/Cargo.toml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index 754025ff49db..34249ea48345 100644 --- a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -16,8 +16,8 @@ index 7165c3e48af..968552ad435 100644 [dependencies] core = { path = "../core", public = true } --compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std', 'no-f16-f128'] } +-compiler_builtins = { version = "=0.1.152", features = ['rustc-dep-of-std'] } ++compiler_builtins = { version = "=0.1.152", features = ['rustc-dep-of-std', 'no-f16-f128'] } [features] compiler-builtins-mem = ['compiler_builtins/mem'] diff --git a/library/Cargo.lock b/library/Cargo.lock index 104e0a3d0107..6b1a0a080551 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -67,9 +67,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.151" +version = "0.1.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abc30f1766d387c35f2405e586d3e7a88230dc728ff78cd1d0bc59ae0b63154b" +checksum = "2153cf213eb259361567720ce55f6446f17acd0ccca87fb6dc05360578228a58" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index 8d0253bd29aa..b729d5e116d2 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -16,7 +16,7 @@ bench = false [dependencies] core = { path = "../core", public = true } -compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "=0.1.152", features = ['rustc-dep-of-std'] } [features] compiler-builtins-mem = ['compiler_builtins/mem'] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 9d9601b79a7e..176da603d58d 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -18,7 +18,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -compiler_builtins = { version = "=0.1.151" } +compiler_builtins = { version = "=0.1.152" } unwind = { path = "../unwind" } hashbrown = { version = "0.15", default-features = false, features = [ 'rustc-dep-of-std', From 0b2acddf01b58ef4825b5ca68f39d9f2ac86072b Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 20 Mar 2025 02:12:40 +0000 Subject: [PATCH 462/745] Update `compiler-builtins` to 0.1.152 Includes the following changes related to unordered atomics: * Remove element_unordered_atomic intrinsics [1] * Remove use of `atomic_load_unordered` and undefined behaviour [2] There are a handful of other small changes, but nothing else user-visible. [1]: https://github.com/rust-lang/compiler-builtins/pull/789 [2]: https://github.com/rust-lang/compiler-builtins/pull/790 --- ...029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index 754025ff49db..34249ea48345 100644 --- a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -16,8 +16,8 @@ index 7165c3e48af..968552ad435 100644 [dependencies] core = { path = "../core", public = true } --compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std', 'no-f16-f128'] } +-compiler_builtins = { version = "=0.1.152", features = ['rustc-dep-of-std'] } ++compiler_builtins = { version = "=0.1.152", features = ['rustc-dep-of-std', 'no-f16-f128'] } [features] compiler-builtins-mem = ['compiler_builtins/mem'] From fbcf7657055a5a562fa7cc176e4bafec9e99c661 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 24 Mar 2025 02:02:10 +0100 Subject: [PATCH 463/745] Revert "resume one waiter at a call" This reverts commit cc1e4ede9388d87750c3751f41e8c6c4f6cae995. --- compiler/rustc_query_system/src/query/job.rs | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 37b305d0a8b5..a8c2aa98cd08 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -477,8 +477,8 @@ fn remove_cycle( /// Detects query cycles by using depth first search over all active query jobs. /// If a query cycle is found it will break the cycle by finding an edge which /// uses a query latch and then resuming that waiter. -/// There may be multiple cycles involved in a deadlock, but we only search -/// one cycle at a call and resume one waiter at once. See `FIXME` below. +/// There may be multiple cycles involved in a deadlock, so this searches +/// all active queries for cycles before finally resuming all the waiters at once. pub fn break_query_cycles(query_map: QueryMap, registry: &rayon_core::Registry) { let mut wakelist = Vec::new(); let mut jobs: Vec = query_map.keys().cloned().collect(); @@ -488,19 +488,6 @@ pub fn break_query_cycles(query_map: QueryMap, registry: &rayon_core::Registry) while jobs.len() > 0 { if remove_cycle(&query_map, &mut jobs, &mut wakelist) { found_cycle = true; - - // FIXME(#137731): Resume all the waiters at once may cause deadlocks, - // so we resume one waiter at a call for now. It's still unclear whether - // it's due to possible issues in rustc-rayon or instead in the handling - // of query cycles. - // This seem to only appear when multiple query cycles errors - // are involved, so this reduction in parallelism, while suboptimal, is not - // universal and only the deadlock handler will encounter these cases. - // The workaround shows loss of potential gains, but there still are big - // improvements in the common case, and no regressions compared to the - // single-threaded case. More investigation is still needed, and once fixed, - // we can wake up all the waiters up. - break; } } From 14786ce645ef96c732f8b30154bc939ee4ba9faf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 24 Mar 2025 02:09:14 +0100 Subject: [PATCH 464/745] Batch mark waiters as unblocked when resuming in the deadlock handler --- compiler/rustc_query_system/src/query/job.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index a8c2aa98cd08..e6ab7c4ef574 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -506,9 +506,15 @@ pub fn break_query_cycles(query_map: QueryMap, registry: &rayon_core::Registry) ); } - // FIXME: Ensure this won't cause a deadlock before we return + // Mark all the thread we're about to wake up as unblocked. This needs to be done before + // we wake the threads up as otherwise Rayon could detect a deadlock if a thread we + // resumed fell asleep and this thread had yet to mark the remaining threads as unblocked. + for _ in 0..wakelist.len() { + rayon_core::mark_unblocked(registry); + } + for waiter in wakelist.into_iter() { - waiter.notify(registry); + waiter.condvar.notify_one(); } } From b672659472e792198390d94f926be61f894547b6 Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Sun, 23 Mar 2025 19:32:20 -0700 Subject: [PATCH 465/745] Trusty: Fix build for anonymous pipes and std::sys::process PRs #136842 (Add libstd support for Trusty targets), #137793 (Stablize anonymous pipe), and #136929 (std: move process implementations to `sys`) merged around the same time, so update Trusty to take them into account. --- library/std/src/os/fd/owned.rs | 9 +++++++-- library/std/src/os/fd/raw.rs | 9 +++++++-- library/std/src/sys/pal/trusty/mod.rs | 2 -- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index 2dcbfc966189..be73e7dee9c7 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -15,9 +15,8 @@ use crate::mem::ManuallyDrop; target_os = "trusty" )))] use crate::sys::cvt; -use crate::sys_common::FromInner; #[cfg(not(target_os = "trusty"))] -use crate::sys_common::{AsInner, IntoInner}; +use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::{fmt, io}; type ValidRawFd = core::num::niche_types::NotAllOnes; @@ -507,6 +506,7 @@ impl<'a> AsFd for io::StderrLock<'a> { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl AsFd for io::PipeReader { fn as_fd(&self) -> BorrowedFd<'_> { self.0.as_fd() @@ -514,6 +514,7 @@ impl AsFd for io::PipeReader { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl From for OwnedFd { fn from(pipe: io::PipeReader) -> Self { pipe.0.into_inner() @@ -521,6 +522,7 @@ impl From for OwnedFd { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl AsFd for io::PipeWriter { fn as_fd(&self) -> BorrowedFd<'_> { self.0.as_fd() @@ -528,6 +530,7 @@ impl AsFd for io::PipeWriter { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl From for OwnedFd { fn from(pipe: io::PipeWriter) -> Self { pipe.0.into_inner() @@ -535,6 +538,7 @@ impl From for OwnedFd { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl From for io::PipeReader { fn from(owned_fd: OwnedFd) -> Self { Self(FromInner::from_inner(owned_fd)) @@ -542,6 +546,7 @@ impl From for io::PipeReader { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl From for io::PipeWriter { fn from(owned_fd: OwnedFd) -> Self { Self(FromInner::from_inner(owned_fd)) diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index 596b21a52044..c800c1489ad2 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -18,9 +18,8 @@ use crate::os::unix::io::AsFd; use crate::os::unix::io::OwnedFd; #[cfg(target_os = "wasi")] use crate::os::wasi::io::OwnedFd; -use crate::sys_common::FromInner; #[cfg(not(target_os = "trusty"))] -use crate::sys_common::{AsInner, IntoInner}; +use crate::sys_common::{AsInner, FromInner, IntoInner}; /// Raw file descriptors. #[stable(feature = "rust1", since = "1.0.0")] @@ -287,6 +286,7 @@ impl AsRawFd for Box { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl AsRawFd for io::PipeReader { fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() @@ -294,6 +294,7 @@ impl AsRawFd for io::PipeReader { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl FromRawFd for io::PipeReader { unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { Self::from_inner(unsafe { FromRawFd::from_raw_fd(raw_fd) }) @@ -301,6 +302,7 @@ impl FromRawFd for io::PipeReader { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl IntoRawFd for io::PipeReader { fn into_raw_fd(self) -> RawFd { self.0.into_raw_fd() @@ -308,6 +310,7 @@ impl IntoRawFd for io::PipeReader { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl AsRawFd for io::PipeWriter { fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() @@ -315,6 +318,7 @@ impl AsRawFd for io::PipeWriter { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl FromRawFd for io::PipeWriter { unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { Self::from_inner(unsafe { FromRawFd::from_raw_fd(raw_fd) }) @@ -322,6 +326,7 @@ impl FromRawFd for io::PipeWriter { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl IntoRawFd for io::PipeWriter { fn into_raw_fd(self) -> RawFd { self.0.into_raw_fd() diff --git a/library/std/src/sys/pal/trusty/mod.rs b/library/std/src/sys/pal/trusty/mod.rs index 7034b643d8e8..5295d3fdc914 100644 --- a/library/std/src/sys/pal/trusty/mod.rs +++ b/library/std/src/sys/pal/trusty/mod.rs @@ -11,8 +11,6 @@ pub mod env; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; -#[path = "../unsupported/process.rs"] -pub mod process; #[path = "../unsupported/thread.rs"] pub mod thread; #[path = "../unsupported/time.rs"] From 38c39ffc6c6e19867f450c7204f341aeb0c495ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 24 Mar 2025 03:53:19 +0100 Subject: [PATCH 466/745] Remove `QueryWaiter::notify` --- compiler/rustc_query_system/src/query/job.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index e6ab7c4ef574..5ed8fb5393fe 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -163,13 +163,6 @@ struct QueryWaiter { cycle: Mutex>, } -impl QueryWaiter { - fn notify(&self, registry: &rayon_core::Registry) { - rayon_core::mark_unblocked(registry); - self.condvar.notify_one(); - } -} - #[derive(Debug)] struct QueryLatchInfo { complete: bool, @@ -232,7 +225,8 @@ impl QueryLatch { info.complete = true; let registry = rayon_core::Registry::current(); for waiter in info.waiters.drain(..) { - waiter.notify(®istry); + rayon_core::mark_unblocked(®istry); + waiter.condvar.notify_one(); } } From 0cd1d516aee85608a695d0376cdef059cc50e00a Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Tue, 18 Mar 2025 18:09:22 +0530 Subject: [PATCH 467/745] std: fs: uefi: Implement canonicalize - Should be same as absolute in UEFI since there are no symlinks. - Also each absolute path representation should be unique according to the UEFI specification. Signed-off-by: Ayush Singh --- library/std/src/sys/fs/uefi.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/fs/uefi.rs b/library/std/src/sys/fs/uefi.rs index 54acd4c27b33..f7c33b7c40f0 100644 --- a/library/std/src/sys/fs/uefi.rs +++ b/library/std/src/sys/fs/uefi.rs @@ -315,8 +315,8 @@ pub fn lstat(_p: &Path) -> io::Result { unsupported() } -pub fn canonicalize(_p: &Path) -> io::Result { - unsupported() +pub fn canonicalize(p: &Path) -> io::Result { + crate::path::absolute(p) } pub fn copy(_from: &Path, _to: &Path) -> io::Result { From fc0cf52e28cdbc5de45b650797365c91d0c8de76 Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Tue, 18 Mar 2025 18:11:18 +0530 Subject: [PATCH 468/745] std: fs: uefi: Make lstat call stat - UEFI does not have symlinks. So lstat and stat should behave the same. Signed-off-by: Ayush Singh --- library/std/src/sys/fs/uefi.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/fs/uefi.rs b/library/std/src/sys/fs/uefi.rs index f7c33b7c40f0..e1d61aaa309e 100644 --- a/library/std/src/sys/fs/uefi.rs +++ b/library/std/src/sys/fs/uefi.rs @@ -311,8 +311,8 @@ pub fn stat(_p: &Path) -> io::Result { unsupported() } -pub fn lstat(_p: &Path) -> io::Result { - unsupported() +pub fn lstat(p: &Path) -> io::Result { + stat(p) } pub fn canonicalize(p: &Path) -> io::Result { From 021d23b64ee58b6d4d7f8803729182ad02a567c2 Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Tue, 18 Mar 2025 18:26:00 +0530 Subject: [PATCH 469/745] std: fs: uefi: Implement OpenOptions UEFI does not have specific modes for create_new, truncate and append. So those need to to be simulated after opening the file. Signed-off-by: Ayush Singh --- library/std/src/sys/fs/uefi.rs | 66 +++++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 8 deletions(-) diff --git a/library/std/src/sys/fs/uefi.rs b/library/std/src/sys/fs/uefi.rs index e1d61aaa309e..d6ae86bd3d26 100644 --- a/library/std/src/sys/fs/uefi.rs +++ b/library/std/src/sys/fs/uefi.rs @@ -1,3 +1,5 @@ +use r_efi::protocols::file; + use crate::ffi::OsString; use crate::fmt; use crate::hash::Hash; @@ -22,7 +24,12 @@ pub struct ReadDir(!); pub struct DirEntry(!); #[derive(Clone, Debug)] -pub struct OpenOptions {} +pub struct OpenOptions { + mode: u64, + append: bool, + truncate: bool, + create_new: bool, +} #[derive(Copy, Clone, Debug, Default)] pub struct FileTimes {} @@ -141,15 +148,58 @@ impl DirEntry { impl OpenOptions { pub fn new() -> OpenOptions { - OpenOptions {} + OpenOptions { mode: 0, append: false, create_new: false, truncate: false } } - pub fn read(&mut self, _read: bool) {} - pub fn write(&mut self, _write: bool) {} - pub fn append(&mut self, _append: bool) {} - pub fn truncate(&mut self, _truncate: bool) {} - pub fn create(&mut self, _create: bool) {} - pub fn create_new(&mut self, _create_new: bool) {} + pub fn read(&mut self, read: bool) { + if read { + self.mode |= file::MODE_READ; + } else { + self.mode &= !file::MODE_READ; + } + } + + pub fn write(&mut self, write: bool) { + if write { + // Valid Combinations: Read, Read/Write, Read/Write/Create + self.read(true); + self.mode |= file::MODE_WRITE; + } else { + self.mode &= !file::MODE_WRITE; + } + } + + pub fn append(&mut self, append: bool) { + // Docs state that `.write(true).append(true)` has the same effect as `.append(true)` + if append { + self.write(true); + } + self.append = append; + } + + pub fn truncate(&mut self, truncate: bool) { + self.truncate = truncate; + } + + pub fn create(&mut self, create: bool) { + if create { + self.mode |= file::MODE_CREATE; + } else { + self.mode &= !file::MODE_CREATE; + } + } + + pub fn create_new(&mut self, create_new: bool) { + self.create_new = create_new; + } + + #[expect(dead_code)] + const fn is_mode_valid(&self) -> bool { + // Valid Combinations: Read, Read/Write, Read/Write/Create + self.mode == file::MODE_READ + || self.mode == (file::MODE_READ | file::MODE_WRITE) + || self.mode == (file::MODE_READ | file::MODE_WRITE | file::MODE_CREATE) + } } impl File { From c71569a765fdd9364ea215ae01442a026e127ab9 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Mon, 24 Mar 2025 14:09:06 +0800 Subject: [PATCH 470/745] Revert "Rollup merge of #137593 - RalfJung:subtree-sync-download-llvm, r=Mark-Simulacrum" Looks like unfortunately the `--diff-merges` flag is a `git show`-only command, not `git rev-list`. This reverts commit 95994f94ff5c9335426af4dec19afb5024f82fab, reversing changes made to 7290b04b0a46de2118968aa556bfc0970aac6661. --- src/build_helper/src/git.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/build_helper/src/git.rs b/src/build_helper/src/git.rs index f47d5663fc94..693e0fc8f46d 100644 --- a/src/build_helper/src/git.rs +++ b/src/build_helper/src/git.rs @@ -140,7 +140,6 @@ pub fn get_closest_merge_commit( // cd \"/checkout\" && \"git\" \"merge-base\" \"origin/master\" \"HEAD\"\nexpected success, got: exit status: 1\n" // ``` // Investigate and resolve this issue instead of skipping it like this. - // NOTE (2025-03): this is probably caused by CI using a sparse checkout. (channel == "nightly" || !CiEnv::is_rust_lang_managed_ci_job()) { git_upstream_merge_base(config, git_dir).unwrap() @@ -151,18 +150,11 @@ pub fn get_closest_merge_commit( } }; - // Now that rust-lang/rust is the only repo using bors, we can search the entire - // history for a bors commit, not just "first parents". This is crucial to make - // this logic work when the user has currently checked out a subtree sync branch. - // At the same time, we use this logic in CI where only a tiny part of the history - // is even checked out, making this kind of history search very fragile. It turns - // out that by adding `--diff-merges=first-parent`, we get a usable reply - // even for sparse checkouts: it will just return the most recent bors commit. git.args([ "rev-list", &format!("--author={}", config.git_merge_commit_email), "-n1", - "--diff-merges=first-parent", + "--first-parent", &merge_base, ]); From 9dd5340d3cbbd3acbe6cc9dfcbcea07e7eb4355e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 12 Mar 2025 16:14:32 +1100 Subject: [PATCH 471/745] Remove `is_any_keyword` methods. They're dodgy, covering all the keywords, including weak ones, and edition-specific ones without considering the edition. They have a single use in rustfmt. This commit changes that use to `is_reserved_ident`, which is a much more widely used alternative and is good enough, judging by the lack of effect on the test suite. --- compiler/rustc_ast/src/token.rs | 5 ----- compiler/rustc_span/src/symbol.rs | 24 +++++++---------------- src/tools/rustfmt/src/parse/macros/mod.rs | 2 +- 3 files changed, 8 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index f7cd63aaaf82..6e6f0f1b2660 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -928,11 +928,6 @@ impl Token { self.is_non_raw_ident_where(Ident::is_path_segment_keyword) } - /// Don't use this unless you're doing something very loose and heuristic-y. - pub fn is_any_keyword(&self) -> bool { - self.is_non_raw_ident_where(Ident::is_any_keyword) - } - /// Returns true for reserved identifiers used internally for elided lifetimes, /// unnamed method parameters, crate root module, error recovery etc. pub fn is_special_ident(&self) -> bool { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 210966bed627..5f81d36a74e7 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -32,7 +32,7 @@ symbols! { Keywords { // Special reserved identifiers used internally for elided lifetimes, // unnamed method parameters, crate root module, error recovery etc. - // Matching predicates: `is_any_keyword`, `is_special`/`is_reserved` + // Matching predicates: `is_special`/`is_reserved` // // Notes about `kw::Empty`: // - Its use can blur the lines between "empty symbol" and "no symbol". @@ -48,7 +48,7 @@ symbols! { Underscore: "_", // Keywords that are used in stable Rust. - // Matching predicates: `is_any_keyword`, `is_used_keyword_always`/`is_reserved` + // Matching predicates: `is_used_keyword_always`/`is_reserved` As: "as", Break: "break", Const: "const", @@ -86,7 +86,7 @@ symbols! { While: "while", // Keywords that are used in unstable Rust or reserved for future use. - // Matching predicates: `is_any_keyword`, `is_unused_keyword_always`/`is_reserved` + // Matching predicates: `is_unused_keyword_always`/`is_reserved` Abstract: "abstract", Become: "become", Box: "box", @@ -101,14 +101,14 @@ symbols! { Yield: "yield", // Edition-specific keywords that are used in stable Rust. - // Matching predicates: `is_any_keyword`, `is_used_keyword_conditional`/`is_reserved` (if + // Matching predicates: `is_used_keyword_conditional`/`is_reserved` (if // the edition suffices) Async: "async", // >= 2018 Edition only Await: "await", // >= 2018 Edition only Dyn: "dyn", // >= 2018 Edition only // Edition-specific keywords that are used in unstable Rust or reserved for future use. - // Matching predicates: `is_any_keyword`, `is_unused_keyword_conditional`/`is_reserved` (if + // Matching predicates: `is_unused_keyword_conditional`/`is_reserved` (if // the edition suffices) Gen: "gen", // >= 2024 Edition only Try: "try", // >= 2018 Edition only @@ -116,12 +116,12 @@ symbols! { // NOTE: When adding new keywords, consider adding them to the ui/parser/raw/raw-idents.rs test. // "Lifetime keywords": regular keywords with a leading `'`. - // Matching predicates: `is_any_keyword` + // Matching predicates: none UnderscoreLifetime: "'_", StaticLifetime: "'static", // Weak keywords, have special meaning only in specific contexts. - // Matching predicates: `is_any_keyword` + // Matching predicates: none Auto: "auto", Builtin: "builtin", Catch: "catch", @@ -2677,11 +2677,6 @@ pub mod sym { } impl Symbol { - /// Don't use this unless you're doing something very loose and heuristic-y. - pub fn is_any_keyword(self) -> bool { - self >= kw::As && self <= kw::Yeet - } - fn is_special(self) -> bool { self <= kw::Underscore } @@ -2738,11 +2733,6 @@ impl Symbol { } impl Ident { - /// Don't use this unless you're doing something very loose and heuristic-y. - pub fn is_any_keyword(self) -> bool { - self.name.is_any_keyword() - } - /// Returns `true` for reserved identifiers used internally for elided lifetimes, /// unnamed method parameters, crate root module, error recovery etc. pub fn is_special(self) -> bool { diff --git a/src/tools/rustfmt/src/parse/macros/mod.rs b/src/tools/rustfmt/src/parse/macros/mod.rs index 680a35f7e03a..d7964484b261 100644 --- a/src/tools/rustfmt/src/parse/macros/mod.rs +++ b/src/tools/rustfmt/src/parse/macros/mod.rs @@ -81,7 +81,7 @@ pub(crate) struct ParsedMacroArgs { } fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { - if parser.token.is_any_keyword() + if parser.token.is_reserved_ident() && parser.look_ahead(1, |t| *t == TokenKind::Eof || *t == TokenKind::Comma) { let keyword = parser.token.ident().unwrap().0.name; From a28d5092e9da9973fd56a4de5e85a632400c85f0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 12 Mar 2025 16:18:20 +1100 Subject: [PATCH 472/745] Improve keyword comments a little. --- compiler/rustc_span/src/symbol.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 5f81d36a74e7..11f271af0b73 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -26,9 +26,10 @@ symbols! { // documents (such as the Rust Reference) about whether it is a keyword // (e.g. `_`). // - // If you modify this list, adjust any relevant `Symbol::{is,can_be}_*` predicates and - // `used_keywords`. - // But this should rarely be necessary if the keywords are kept in alphabetic order. + // If you modify this list, adjust any relevant `Symbol::{is,can_be}_*` + // predicates and `used_keywords`. (This should rarely be necessary if + // the keywords are kept in alphabetic order.) Also consider adding new + // keywords to the `ui/parser/raw/raw-idents.rs` test. Keywords { // Special reserved identifiers used internally for elided lifetimes, // unnamed method parameters, crate root module, error recovery etc. @@ -113,8 +114,6 @@ symbols! { Gen: "gen", // >= 2024 Edition only Try: "try", // >= 2018 Edition only - // NOTE: When adding new keywords, consider adding them to the ui/parser/raw/raw-idents.rs test. - // "Lifetime keywords": regular keywords with a leading `'`. // Matching predicates: none UnderscoreLifetime: "'_", From 3aaa12f622f294fd0d5f86a31415eb1fb4669bdd Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 12 Mar 2025 16:18:40 +1100 Subject: [PATCH 473/745] Fix some formatting. --- compiler/rustc_span/src/symbol.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 11f271af0b73..394774b57646 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -128,8 +128,8 @@ symbols! { MacroRules: "macro_rules", Raw: "raw", Reuse: "reuse", - ContractEnsures: "contract_ensures", - ContractRequires: "contract_requires", + ContractEnsures: "contract_ensures", + ContractRequires: "contract_requires", Safe: "safe", Union: "union", Yeet: "yeet", From 10236fbe7bea988dd94509e437c63b855fd1ec00 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 12 Mar 2025 16:26:24 +1100 Subject: [PATCH 474/745] Alphabetize the keywords list. --- compiler/rustc_span/src/symbol.rs | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 394774b57646..33ffa00a3691 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -27,9 +27,8 @@ symbols! { // (e.g. `_`). // // If you modify this list, adjust any relevant `Symbol::{is,can_be}_*` - // predicates and `used_keywords`. (This should rarely be necessary if - // the keywords are kept in alphabetic order.) Also consider adding new - // keywords to the `ui/parser/raw/raw-idents.rs` test. + // predicates and `used_keywords`. Also consider adding new keywords to the + // `ui/parser/raw/raw-idents.rs` test. Keywords { // Special reserved identifiers used internally for elided lifetimes, // unnamed method parameters, crate root module, error recovery etc. @@ -43,13 +42,16 @@ symbols! { // present, it's better to use `sym::dummy` than `kw::Empty`, because // it's clearer that it's intended as a dummy value, and more likely // to be detected if it accidentally does get used. + // tidy-alphabetical-start + DollarCrate: "$crate", Empty: "", PathRoot: "{{root}}", - DollarCrate: "$crate", Underscore: "_", + // tidy-alphabetical-end // Keywords that are used in stable Rust. // Matching predicates: `is_used_keyword_always`/`is_reserved` + // tidy-alphabetical-start As: "as", Break: "break", Const: "const", @@ -85,9 +87,11 @@ symbols! { Use: "use", Where: "where", While: "while", + // tidy-alphabetical-end // Keywords that are used in unstable Rust or reserved for future use. // Matching predicates: `is_unused_keyword_always`/`is_reserved` + // tidy-alphabetical-start Abstract: "abstract", Become: "become", Box: "box", @@ -100,39 +104,48 @@ symbols! { Unsized: "unsized", Virtual: "virtual", Yield: "yield", + // tidy-alphabetical-end // Edition-specific keywords that are used in stable Rust. // Matching predicates: `is_used_keyword_conditional`/`is_reserved` (if // the edition suffices) + // tidy-alphabetical-start Async: "async", // >= 2018 Edition only Await: "await", // >= 2018 Edition only Dyn: "dyn", // >= 2018 Edition only + // tidy-alphabetical-end // Edition-specific keywords that are used in unstable Rust or reserved for future use. // Matching predicates: `is_unused_keyword_conditional`/`is_reserved` (if // the edition suffices) + // tidy-alphabetical-start Gen: "gen", // >= 2024 Edition only Try: "try", // >= 2018 Edition only + // tidy-alphabetical-end // "Lifetime keywords": regular keywords with a leading `'`. // Matching predicates: none - UnderscoreLifetime: "'_", + // tidy-alphabetical-start StaticLifetime: "'static", + UnderscoreLifetime: "'_", + // tidy-alphabetical-end // Weak keywords, have special meaning only in specific contexts. // Matching predicates: none + // tidy-alphabetical-start Auto: "auto", Builtin: "builtin", Catch: "catch", + ContractEnsures: "contract_ensures", + ContractRequires: "contract_requires", Default: "default", MacroRules: "macro_rules", Raw: "raw", Reuse: "reuse", - ContractEnsures: "contract_ensures", - ContractRequires: "contract_requires", Safe: "safe", Union: "union", Yeet: "yeet", + // tidy-alphabetical-end } // Pre-interned symbols that can be referred to with `rustc_span::sym::*`. @@ -2781,7 +2794,7 @@ impl Ident { /// *Note:* Please update this if a new keyword is added beyond the current /// range. pub fn used_keywords(edition: impl Copy + FnOnce() -> Edition) -> Vec { - (kw::Empty.as_u32()..kw::Yeet.as_u32()) + (kw::DollarCrate.as_u32()..kw::Yeet.as_u32()) .filter_map(|kw| { let kw = Symbol::new(kw); if kw.is_used_keyword_always() || kw.is_used_keyword_conditional(edition) { From a29e875b63542b1809ae6beb6fabbdacbb16971f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 12 Mar 2025 16:28:15 +1100 Subject: [PATCH 475/745] Move `is_used_keyword_conditional`. So the order of the `Symbol::is_*` predicates match the order of the keywords list. --- compiler/rustc_span/src/symbol.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 33ffa00a3691..3e4742439655 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2697,14 +2697,14 @@ impl Symbol { self >= kw::As && self <= kw::While } - fn is_used_keyword_conditional(self, edition: impl FnOnce() -> Edition) -> bool { - (self >= kw::Async && self <= kw::Dyn) && edition() >= Edition::Edition2018 - } - fn is_unused_keyword_always(self) -> bool { self >= kw::Abstract && self <= kw::Yield } + fn is_used_keyword_conditional(self, edition: impl FnOnce() -> Edition) -> bool { + (self >= kw::Async && self <= kw::Dyn) && edition() >= Edition::Edition2018 + } + fn is_unused_keyword_conditional(self, edition: impl Copy + FnOnce() -> Edition) -> bool { self == kw::Gen && edition().at_least_rust_2024() || self == kw::Try && edition().at_least_rust_2018() From 2d3115f61f40b43855bbf252cfb1f4d480c1ccc9 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 24 Mar 2025 09:39:02 +0000 Subject: [PATCH 476/745] `with_scope` is only ever used for ast modules --- compiler/rustc_resolve/src/late.rs | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 6056a69ee71f..e04d0083548b 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1544,20 +1544,17 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ret } - fn with_scope(&mut self, id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T { - if let Some(module) = self.r.get_module(self.r.local_def_id(id).to_def_id()) { - // Move down in the graph. - let orig_module = replace(&mut self.parent_scope.module, module); - self.with_rib(ValueNS, RibKind::Module(module), |this| { - this.with_rib(TypeNS, RibKind::Module(module), |this| { - let ret = f(this); - this.parent_scope.module = orig_module; - ret - }) + fn with_mod_rib(&mut self, id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T { + let module = self.r.expect_module(self.r.local_def_id(id).to_def_id()); + // Move down in the graph. + let orig_module = replace(&mut self.parent_scope.module, module); + self.with_rib(ValueNS, RibKind::Module(module), |this| { + this.with_rib(TypeNS, RibKind::Module(module), |this| { + let ret = f(this); + this.parent_scope.module = orig_module; + ret }) - } else { - f(self) - } + }) } fn visit_generic_params(&mut self, params: &'ast [GenericParam], add_self_upper: bool) { @@ -2738,7 +2735,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } ItemKind::Mod(..) => { - self.with_scope(item.id, |this| { + self.with_mod_rib(item.id, |this| { if mod_inner_docs { this.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id)); } From d9f250af21dbadcde2113a961132a263392bf091 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 20 Mar 2025 18:23:07 +0100 Subject: [PATCH 477/745] Remove duplicated loop when computing doc cfgs --- src/librustdoc/clean/types.rs | 59 +++++++++++++---------------------- 1 file changed, 21 insertions(+), 38 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 5f80aded9d0b..27eb56a9858b 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1013,7 +1013,6 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet, ) -> Option> { - let sess = tcx.sess; let doc_cfg_active = tcx.features().doc_cfg(); let doc_auto_cfg_active = tcx.features().doc_auto_cfg(); @@ -1034,9 +1033,27 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator .filter(|attr| attr.has_name(sym::cfg)) .peekable(); if doc_cfg.peek().is_some() && doc_cfg_active { - doc_cfg - .filter_map(|attr| Cfg::parse(&attr).ok()) - .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg) + let sess = tcx.sess; + doc_cfg.fold(Cfg::True, |mut cfg, item| { + if let Some(cfg_mi) = + item.meta_item().and_then(|item| rustc_expand::config::parse_cfg(item, sess)) + { + // The result is unused here but we can gate unstable predicates + rustc_attr_parsing::cfg_matches( + cfg_mi, + tcx.sess, + rustc_ast::CRATE_NODE_ID, + Some(tcx.features()), + ); + match Cfg::parse(cfg_mi) { + Ok(new_cfg) => cfg &= new_cfg, + Err(e) => { + sess.dcx().span_err(e.span, e.msg); + } + } + } + cfg + }) } else if doc_auto_cfg_active { // If there is no `doc(cfg())`, then we retrieve the `cfg()` attributes (because // `doc(cfg())` overrides `cfg()`). @@ -1053,40 +1070,6 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator Cfg::True }; - for attr in attrs.clone() { - // #[doc] - if attr.doc_str().is_none() && attr.has_name(sym::doc) { - // #[doc(...)] - if let Some(list) = attr.meta_item_list() { - for item in list { - // #[doc(hidden)] - if !item.has_name(sym::cfg) { - continue; - } - // #[doc(cfg(...))] - if let Some(cfg_mi) = item - .meta_item() - .and_then(|item| rustc_expand::config::parse_cfg(item, sess)) - { - // The result is unused here but we can gate unstable predicates - rustc_attr_parsing::cfg_matches( - cfg_mi, - tcx.sess, - rustc_ast::CRATE_NODE_ID, - Some(tcx.features()), - ); - match Cfg::parse(cfg_mi) { - Ok(new_cfg) => cfg &= new_cfg, - Err(e) => { - sess.dcx().span_err(e.span, e.msg); - } - } - } - } - } - } - } - // treat #[target_feature(enable = "feat")] attributes as if they were // #[doc(cfg(target_feature = "feat"))] attributes as well for attr in hir_attr_lists(attrs, sym::target_feature) { From f5659f28f8a426d16c2c6f7b0ab7461958b4f0a6 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Mon, 24 Mar 2025 11:33:56 +0100 Subject: [PATCH 478/745] ignore tests broken while cross compiling --- tests/run-make/doctests-keep-binaries/rmake.rs | 2 ++ tests/run-make/target-cpu-native/rmake.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tests/run-make/doctests-keep-binaries/rmake.rs b/tests/run-make/doctests-keep-binaries/rmake.rs index 246539bcf823..a05223994df4 100644 --- a/tests/run-make/doctests-keep-binaries/rmake.rs +++ b/tests/run-make/doctests-keep-binaries/rmake.rs @@ -1,3 +1,5 @@ +//@ ignore-cross-compile attempts to run the doctests + // Check that valid binaries are persisted by running them, regardless of whether the // --run or --no-run option is used. diff --git a/tests/run-make/target-cpu-native/rmake.rs b/tests/run-make/target-cpu-native/rmake.rs index fd5fb6193fe0..7b7974f30978 100644 --- a/tests/run-make/target-cpu-native/rmake.rs +++ b/tests/run-make/target-cpu-native/rmake.rs @@ -3,6 +3,8 @@ // warnings when used, and that binaries produced by it can also be successfully executed. // See https://github.com/rust-lang/rust/pull/23238 +//@ ignore-cross-compile target-cpu=native doesn't work well when cross compiling + use run_make_support::{run, rustc}; fn main() { From 02e1f118cd5adb995c3801cc7703faaba8910ccc Mon Sep 17 00:00:00 2001 From: Eduard Stefes Date: Mon, 24 Mar 2025 11:54:44 +0100 Subject: [PATCH 479/745] Fix ui pattern_types test for big-endian platforms The newly added pattern types validity tests fail on s390x and presumably other big-endian systems, due to print of raw values with padding bytes. To fix the tests remove the raw output values in the error note by `normalize-stderr`. --- tests/ui/type/pattern_types/validity.rs | 2 ++ tests/ui/type/pattern_types/validity.stderr | 26 ++++++++++----------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/tests/ui/type/pattern_types/validity.rs b/tests/ui/type/pattern_types/validity.rs index 5a6a688e1b30..c61bb71ac252 100644 --- a/tests/ui/type/pattern_types/validity.rs +++ b/tests/ui/type/pattern_types/validity.rs @@ -1,4 +1,6 @@ //! Check that pattern types have their validity checked +// Strip out raw byte dumps to make tests platform-independent: +//@ normalize-stderr: "([[:xdigit:]]{2}\s){4,8}\s+│\s.{4,8}" -> "HEX_DUMP" #![feature(pattern_types, const_trait_impl, pattern_type_range_trait)] #![feature(pattern_type_macro)] diff --git a/tests/ui/type/pattern_types/validity.stderr b/tests/ui/type/pattern_types/validity.stderr index 5bc18cfba3f7..b990ec2d3682 100644 --- a/tests/ui/type/pattern_types/validity.stderr +++ b/tests/ui/type/pattern_types/validity.stderr @@ -1,22 +1,22 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/validity.rs:8:1 + --> $DIR/validity.rs:10:1 | LL | const BAD: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - 00 00 00 00 │ .... + HEX_DUMP } error[E0080]: evaluation of constant value failed - --> $DIR/validity.rs:11:1 + --> $DIR/validity.rs:13:1 | LL | const BAD_UNINIT: pattern_type!(u32 is 1..) = | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory error[E0080]: evaluation of constant value failed - --> $DIR/validity.rs:15:1 + --> $DIR/validity.rs:17:1 | LL | const BAD_PTR: pattern_type!(usize is 1..) = unsafe { std::mem::transmute(&42) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer @@ -25,53 +25,53 @@ LL | const BAD_PTR: pattern_type!(usize is 1..) = unsafe { std::mem::transmute(& = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: it is undefined behavior to use this value - --> $DIR/validity.rs:18:1 + --> $DIR/validity.rs:20:1 | LL | const BAD_AGGREGATE: (pattern_type!(u32 is 1..), u32) = (unsafe { std::mem::transmute(0) }, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - 00 00 00 00 00 00 00 00 │ ........ + HEX_DUMP } error[E0080]: it is undefined behavior to use this value - --> $DIR/validity.rs:24:1 + --> $DIR/validity.rs:26:1 | LL | const BAD_FOO: Foo = Foo(Bar(unsafe { std::mem::transmute(0) })); | ^^^^^^^^^^^^^^^^^^ constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - 00 00 00 00 │ .... + HEX_DUMP } error[E0080]: evaluation of constant value failed - --> $DIR/validity.rs:27:1 + --> $DIR/validity.rs:29:1 | LL | const CHAR_UNINIT: pattern_type!(char is 'A'..'Z') = | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory error[E0080]: it is undefined behavior to use this value - --> $DIR/validity.rs:31:1 + --> $DIR/validity.rs:33:1 | LL | const CHAR_OOB_PAT: pattern_type!(char is 'A'..'Z') = unsafe { std::mem::transmute('a') }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 97, but expected something in the range 65..=89 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - 61 00 00 00 │ a... + HEX_DUMP } error[E0080]: it is undefined behavior to use this value - --> $DIR/validity.rs:34:1 + --> $DIR/validity.rs:36:1 | LL | const CHAR_OOB: pattern_type!(char is 'A'..'Z') = unsafe { std::mem::transmute(u32::MAX) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ff ff ff ff │ .... + HEX_DUMP } error: aborting due to 8 previous errors From 856a181570371e1622bcb42ef94fc23090f93a12 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Mon, 24 Mar 2025 11:53:09 +0100 Subject: [PATCH 480/745] =?UTF-8?q?Fix=20autofix=20for=20`self`=20and=20`s?= =?UTF-8?q?elf=20as=20=E2=80=A6`=20in=20`unused=5Fimports`=20lint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes two problems with the autofixes for the `unused_imports` lint: - `use std::collections::{HashMap, self as coll};` would suggest, when `HashMap` is unused, the incorrect `use std::collections::self as coll;` which does not compile. - `use std::borrow::{self, Cow};` would suggest, when `self` is unused, `use std::borrow::{Cow};`, which contains unnecessary brackets. --- compiler/rustc_resolve/src/check_unused.rs | 3 +- .../lint-unused-imports-self-single.fixed | 29 ++++++++++++ .../unused/lint-unused-imports-self-single.rs | 30 +++++++++++++ .../lint-unused-imports-self-single.stderr | 44 +++++++++++++++++++ 4 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 tests/ui/lint/unused/lint-unused-imports-self-single.fixed create mode 100644 tests/ui/lint/unused/lint-unused-imports-self-single.rs create mode 100644 tests/ui/lint/unused/lint-unused-imports-self-single.stderr diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 1c1e8494ffc7..51ff4aa834ba 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -337,7 +337,8 @@ fn calc_unused_spans( } } contains_self |= use_tree.prefix == kw::SelfLower - && matches!(use_tree.kind, ast::UseTreeKind::Simple(None)); + && matches!(use_tree.kind, ast::UseTreeKind::Simple(_)) + && !unused_import.unused.contains(&use_tree_id); previous_unused = remove.is_some(); } if unused_spans.is_empty() { diff --git a/tests/ui/lint/unused/lint-unused-imports-self-single.fixed b/tests/ui/lint/unused/lint-unused-imports-self-single.fixed new file mode 100644 index 000000000000..361548bfdc12 --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-imports-self-single.fixed @@ -0,0 +1,29 @@ +//@ run-rustfix + +#![deny(unused_imports)] +#![allow(unreachable_code)] + +use std::collections::{self as coll}; +//~^ ERROR unused import: `HashMap` + +//~^ ERROR unused import: `self as std_io` + +use std::sync::Mutex; +//~^ ERROR unused import: `self as std_sync` + +use std::sync::mpsc::Sender; +//~^ ERROR unused import: `self as std_sync_mpsc` + +use std::collections::hash_map::{self as std_coll_hm}; +//~^ ERROR unused import: `Keys` + +use std::borrow::Cow; +//~^ ERROR unused import: `self` + +fn main() { + let _ = coll::BTreeSet::::default(); + let _ = Mutex::new(String::new()); + let _: Cow<'static, str> = "foo".into(); + let _: Sender = todo!(); + let _: std_coll_hm::Entry<'static, u32, u32> = todo!(); +} diff --git a/tests/ui/lint/unused/lint-unused-imports-self-single.rs b/tests/ui/lint/unused/lint-unused-imports-self-single.rs new file mode 100644 index 000000000000..d03d3822e04e --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-imports-self-single.rs @@ -0,0 +1,30 @@ +//@ run-rustfix + +#![deny(unused_imports)] +#![allow(unreachable_code)] + +use std::collections::{HashMap, self as coll}; +//~^ ERROR unused import: `HashMap` + +use std::io::{self as std_io}; +//~^ ERROR unused import: `self as std_io` + +use std::sync::{Mutex, self as std_sync}; +//~^ ERROR unused import: `self as std_sync` + +use std::sync::{mpsc::{self as std_sync_mpsc, Sender}}; +//~^ ERROR unused import: `self as std_sync_mpsc` + +use std::collections::{hash_map::{self as std_coll_hm, Keys}}; +//~^ ERROR unused import: `Keys` + +use std::borrow::{self, Cow}; +//~^ ERROR unused import: `self` + +fn main() { + let _ = coll::BTreeSet::::default(); + let _ = Mutex::new(String::new()); + let _: Cow<'static, str> = "foo".into(); + let _: Sender = todo!(); + let _: std_coll_hm::Entry<'static, u32, u32> = todo!(); +} diff --git a/tests/ui/lint/unused/lint-unused-imports-self-single.stderr b/tests/ui/lint/unused/lint-unused-imports-self-single.stderr new file mode 100644 index 000000000000..70a9b78a6640 --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-imports-self-single.stderr @@ -0,0 +1,44 @@ +error: unused import: `HashMap` + --> $DIR/lint-unused-imports-self-single.rs:6:24 + | +LL | use std::collections::{HashMap, self as coll}; + | ^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-unused-imports-self-single.rs:3:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: unused import: `self as std_io` + --> $DIR/lint-unused-imports-self-single.rs:9:15 + | +LL | use std::io::{self as std_io}; + | ^^^^^^^^^^^^^^ + +error: unused import: `self as std_sync` + --> $DIR/lint-unused-imports-self-single.rs:12:24 + | +LL | use std::sync::{Mutex, self as std_sync}; + | ^^^^^^^^^^^^^^^^ + +error: unused import: `self as std_sync_mpsc` + --> $DIR/lint-unused-imports-self-single.rs:15:24 + | +LL | use std::sync::{mpsc::{self as std_sync_mpsc, Sender}}; + | ^^^^^^^^^^^^^^^^^^^^^ + +error: unused import: `Keys` + --> $DIR/lint-unused-imports-self-single.rs:18:56 + | +LL | use std::collections::{hash_map::{self as std_coll_hm, Keys}}; + | ^^^^ + +error: unused import: `self` + --> $DIR/lint-unused-imports-self-single.rs:21:19 + | +LL | use std::borrow::{self, Cow}; + | ^^^^ + +error: aborting due to 6 previous errors + From 67e0b899f0db3f20ad29481b16703d81a896e749 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 24 Mar 2025 15:23:25 +0000 Subject: [PATCH 481/745] Add a helper for building an owner id in ast lowering --- compiler/rustc_ast_lowering/src/item.rs | 17 +++++++---------- compiler/rustc_ast_lowering/src/lib.rs | 16 ++++++++++------ 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index bd011d59aaa7..83b2001d5c5b 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -132,8 +132,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> { - let mut node_ids = - smallvec![hir::ItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }]; + let mut node_ids = smallvec![hir::ItemId { owner_id: self.owner_id(i.id) }]; if let ItemKind::Use(use_tree) = &i.kind { self.lower_item_id_use_tree(use_tree, &mut node_ids); } @@ -144,9 +143,7 @@ impl<'hir> LoweringContext<'_, 'hir> { match &tree.kind { UseTreeKind::Nested { items, .. } => { for &(ref nested, id) in items { - vec.push(hir::ItemId { - owner_id: hir::OwnerId { def_id: self.local_def_id(id) }, - }); + vec.push(hir::ItemId { owner_id: self.owner_id(id) }); self.lower_item_id_use_tree(nested, vec); } } @@ -585,7 +582,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // Add all the nested `PathListItem`s to the HIR. for &(ref use_tree, id) in trees { - let new_hir_id = self.local_def_id(id); + let owner_id = self.owner_id(id); // Each `use` import is an item and thus are owners of the // names in the path. Up to this point the nested import is @@ -602,7 +599,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } let item = hir::Item { - owner_id: hir::OwnerId { def_id: new_hir_id }, + owner_id, kind, vis_span, span: this.lower_span(use_tree.span), @@ -710,7 +707,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef { hir::ForeignItemRef { - id: hir::ForeignItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }, + id: hir::ForeignItemId { owner_id: self.owner_id(i.id) }, ident: self.lower_ident(i.ident), span: self.lower_span(i.span), } @@ -931,7 +928,7 @@ impl<'hir> LoweringContext<'_, 'hir> { panic!("macros should have been expanded by now") } }; - let id = hir::TraitItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }; + let id = hir::TraitItemId { owner_id: self.owner_id(i.id) }; hir::TraitItemRef { id, ident: self.lower_ident(i.ident), @@ -1046,7 +1043,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef { hir::ImplItemRef { - id: hir::ImplItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }, + id: hir::ImplItemId { owner_id: self.owner_id(i.id) }, ident: self.lower_ident(i.ident), span: self.lower_span(i.span), kind: match &i.kind { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e24b45c5b194..32eb5e225ab7 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -536,6 +536,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`")) } + /// Given the id of an owner node in the AST, returns the corresponding `OwnerId`. + fn owner_id(&self, node: NodeId) -> hir::OwnerId { + hir::OwnerId { def_id: self.local_def_id(node) } + } + /// Freshen the `LoweringContext` and ready it to lower a nested item. /// The lowered item is registered into `self.children`. /// @@ -547,7 +552,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { owner: NodeId, f: impl FnOnce(&mut Self) -> hir::OwnerNode<'hir>, ) { - let def_id = self.local_def_id(owner); + let owner_id = self.owner_id(owner); let current_attrs = std::mem::take(&mut self.attrs); let current_bodies = std::mem::take(&mut self.bodies); @@ -558,8 +563,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { #[cfg(debug_assertions)] let current_node_id_to_local_id = std::mem::take(&mut self.node_id_to_local_id); let current_trait_map = std::mem::take(&mut self.trait_map); - let current_owner = - std::mem::replace(&mut self.current_hir_id_owner, hir::OwnerId { def_id }); + let current_owner = std::mem::replace(&mut self.current_hir_id_owner, owner_id); let current_local_counter = std::mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1)); let current_impl_trait_defs = std::mem::take(&mut self.impl_trait_defs); @@ -577,7 +581,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } let item = f(self); - debug_assert_eq!(def_id, item.def_id().def_id); + debug_assert_eq!(owner_id, item.def_id()); // `f` should have consumed all the elements in these vectors when constructing `item`. debug_assert!(self.impl_trait_defs.is_empty()); debug_assert!(self.impl_trait_bounds.is_empty()); @@ -598,8 +602,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.impl_trait_defs = current_impl_trait_defs; self.impl_trait_bounds = current_impl_trait_bounds; - debug_assert!(!self.children.iter().any(|(id, _)| id == &def_id)); - self.children.push((def_id, hir::MaybeOwner::Owner(info))); + debug_assert!(!self.children.iter().any(|(id, _)| id == &owner_id.def_id)); + self.children.push((owner_id.def_id, hir::MaybeOwner::Owner(info))); } fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> { From 724a5a430bf14de79d2fe64543a1103fe250a57e Mon Sep 17 00:00:00 2001 From: klensy Date: Mon, 24 Mar 2025 19:38:16 +0300 Subject: [PATCH 482/745] bump thorin to drop duped deps --- Cargo.lock | 54 ++++++-------------------- compiler/rustc_codegen_llvm/Cargo.toml | 2 +- compiler/rustc_codegen_ssa/Cargo.toml | 2 +- 3 files changed, 13 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 651895714320..01d7e0beea61 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -34,18 +34,6 @@ dependencies = [ "cpufeatures", ] -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy 0.7.35", -] - [[package]] name = "aho-corasick" version = "1.1.3" @@ -1425,17 +1413,6 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" -[[package]] -name = "gimli" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e1d97fbe9722ba9bbd0c97051c2956e726562b61f86a25a4360398a40edfc9" -dependencies = [ - "fallible-iterator", - "indexmap", - "stable_deref_trait", -] - [[package]] name = "gimli" version = "0.31.1" @@ -1475,16 +1452,6 @@ dependencies = [ "serde", ] -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", - "allocator-api2", -] - [[package]] name = "hashbrown" version = "0.15.2" @@ -1492,6 +1459,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "allocator-api2", + "equivalent", "foldhash", "serde", ] @@ -1815,7 +1783,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown", "serde", ] @@ -2470,7 +2438,7 @@ checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "crc32fast", "flate2", - "hashbrown 0.15.2", + "hashbrown", "indexmap", "memchr", "ruzstd", @@ -3413,7 +3381,7 @@ name = "rustc_codegen_llvm" version = "0.0.0" dependencies = [ "bitflags", - "gimli 0.30.0", + "gimli 0.31.1", "itertools", "libc", "measureme 12.0.1", @@ -3527,7 +3495,7 @@ dependencies = [ "either", "elsa", "ena", - "hashbrown 0.15.2", + "hashbrown", "indexmap", "jobserver", "libc", @@ -4306,7 +4274,7 @@ dependencies = [ name = "rustc_query_system" version = "0.0.0" dependencies = [ - "hashbrown 0.15.2", + "hashbrown", "parking_lot", "rustc-rayon-core", "rustc_abi", @@ -5241,12 +5209,12 @@ dependencies = [ [[package]] name = "thorin-dwp" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "813ba76597db32dc4f6992fd8bf8f394715b88d352fd97401da67dab6283b4c6" +checksum = "9e9c1e705f82a260173f3eec93f2ff6d7807f23ad5a8cc2e7316a891733ea7a1" dependencies = [ - "gimli 0.30.0", - "hashbrown 0.14.5", + "gimli 0.31.1", + "hashbrown", "object 0.36.7", "tracing", ] @@ -5972,7 +5940,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5a99faceb1a5a84dd6084ec4bfa4b2ab153b5793b43fd8f58b89232634afc35" dependencies = [ "bitflags", - "hashbrown 0.15.2", + "hashbrown", "indexmap", "semver", "serde", diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index ec1fd4b641a2..3185993c2076 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -11,7 +11,7 @@ test = false bitflags = "2.4.1" # To avoid duplicate dependencies, this should match the version of gimli used # by `rustc_codegen_ssa` via its `thorin-dwp` dependency. -gimli = "0.30" +gimli = "0.31" itertools = "0.12" libc = "0.2" measureme = "12.0.1" diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 0a2f1d5bb678..97eebffd1fe8 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -42,7 +42,7 @@ serde_json = "1.0.59" smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tempfile = "3.2" thin-vec = "0.2.12" -thorin-dwp = "0.8" +thorin-dwp = "0.9" tracing = "0.1" wasm-encoder = "0.219" # tidy-alphabetical-end From e06d50cf327aed841de4394b7183aa815bb3ed9e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 24 Mar 2025 16:21:31 +0000 Subject: [PATCH 483/745] Revert "Rollup merge of #136127 - WaffleLapkin:dyn_ptr_unwrap_cast, r=compiler-errors" This reverts commit 84c2050bf63f734246572345aedca9edb2abe96e, reversing changes made to a96fa317d78c78a9de996afd317603c6970efc0d. --- compiler/rustc_hir_typeck/src/coercion.rs | 68 +-------- .../ui/cast/ptr-to-trait-obj-wrap-add-auto.rs | 36 ----- .../ptr-to-trait-obj-wrap-add-auto.stderr | 48 ------ .../ptr-to-trait-obj-wrap-different-args.rs | 36 ----- ...tr-to-trait-obj-wrap-different-args.stderr | 43 ------ ...ptr-to-trait-obj-wrap-different-regions.rs | 41 ----- ...to-trait-obj-wrap-different-regions.stderr | 140 ------------------ tests/ui/cast/ptr-to-trait-obj-wrap.rs | 32 ---- 8 files changed, 8 insertions(+), 436 deletions(-) delete mode 100644 tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.rs delete mode 100644 tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.stderr delete mode 100644 tests/ui/cast/ptr-to-trait-obj-wrap-different-args.rs delete mode 100644 tests/ui/cast/ptr-to-trait-obj-wrap-different-args.stderr delete mode 100644 tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.rs delete mode 100644 tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.stderr delete mode 100644 tests/ui/cast/ptr-to-trait-obj-wrap.rs diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 4cbc42b99ea3..f42ca3af2b35 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -41,8 +41,8 @@ use rustc_abi::ExternAbi; use rustc_attr_parsing::InlineAttr; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, struct_span_code_err}; +use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{self as hir, LangItem}; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; use rustc_infer::infer::relate::RelateResult; use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult}; @@ -55,7 +55,7 @@ use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion, }; use rustc_middle::ty::error::TypeError; -use rustc_middle::ty::{self, AliasTy, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Span}; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; @@ -592,63 +592,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Create an obligation for `Source: CoerceUnsized`. let cause = self.cause(self.cause.span, ObligationCauseCode::Coercion { source, target }); - let root_obligation = Obligation::new( - self.tcx, - cause.clone(), - self.fcx.param_env, - ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target]), - ); - - // If the root `Source: CoerceUnsized` obligation can't possibly hold, - // we don't have to assume that this is unsizing coercion (it will always lead to an error) - // - // However, we don't want to bail early all the time, since the unholdable obligations - // may be interesting for diagnostics (such as trying to coerce `&T` to `&dyn Id`), - // so we only bail if there (likely) is another way to convert the types. - if !self.infcx.predicate_may_hold(&root_obligation) { - if let Some(dyn_metadata_adt_def_id) = self.tcx.lang_items().get(LangItem::DynMetadata) - && let Some(metadata_type_def_id) = self.tcx.lang_items().get(LangItem::Metadata) - { - self.probe(|_| { - let ocx = ObligationCtxt::new(&self.infcx); - - // returns `true` if `::Metadata` is `DynMetadata<_>` - let has_dyn_trait_metadata = |ty| { - let metadata_ty: Result<_, _> = ocx.structurally_normalize_ty( - &ObligationCause::dummy(), - self.fcx.param_env, - Ty::new_alias( - self.tcx, - ty::AliasTyKind::Projection, - AliasTy::new(self.tcx, metadata_type_def_id, [ty]), - ), - ); - - metadata_ty.is_ok_and(|metadata_ty| { - metadata_ty - .ty_adt_def() - .is_some_and(|d| d.did() == dyn_metadata_adt_def_id) - }) - }; - - // If both types are raw pointers to a (wrapper over a) trait object, - // this might be a cast like `*const W -> *const dyn Trait`. - // So it's better to bail and try that. (even if the cast is not possible, for - // example due to vtables not matching, cast diagnostic will likely still be better) - // - // N.B. use `target`, not `coerce_target` (the latter is a var) - if let &ty::RawPtr(source_pointee, _) = coerce_source.kind() - && let &ty::RawPtr(target_pointee, _) = target.kind() - && has_dyn_trait_metadata(source_pointee) - && has_dyn_trait_metadata(target_pointee) - { - return Err(TypeError::Mismatch); - } - - Ok(()) - })?; - } - } // Use a FIFO queue for this custom fulfillment procedure. // @@ -657,7 +600,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // and almost never more than 3. By using a SmallVec we avoid an // allocation, at the (very small) cost of (occasionally) having to // shift subsequent elements down when removing the front element. - let mut queue: SmallVec<[PredicateObligation<'tcx>; 4]> = smallvec![root_obligation]; + let mut queue: SmallVec<[PredicateObligation<'tcx>; 4]> = smallvec![Obligation::new( + self.tcx, + cause, + self.fcx.param_env, + ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target]) + )]; // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.rs b/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.rs deleted file mode 100644 index cfc0a97989dc..000000000000 --- a/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Combination of `ptr-to-trait-obj-wrap.rs` and `ptr-to-trait-obj-add-auto.rs`. -// -// Checks that you *can't* add auto traits to trait object in pointer casts involving wrapping said -// traits structures. - -trait A {} - -struct W(T); -struct X(T); - -fn unwrap(a: *const W) -> *const (dyn A + Send) { - a as _ - //~^ error: cannot add auto trait `Send` to dyn bound via pointer cast -} - -fn unwrap_nested(a: *const W>) -> *const W { - a as _ - //~^ error: cannot add auto trait `Send` to dyn bound via pointer cast -} - -fn rewrap(a: *const W) -> *const X { - a as _ - //~^ error: cannot add auto trait `Send` to dyn bound via pointer cast -} - -fn rewrap_nested(a: *const W>) -> *const W> { - a as _ - //~^ error: cannot add auto trait `Send` to dyn bound via pointer cast -} - -fn wrap(a: *const dyn A) -> *const W { - a as _ - //~^ error: cannot add auto trait `Send` to dyn bound via pointer cast -} - -fn main() {} diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.stderr b/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.stderr deleted file mode 100644 index 42cdbc34ee82..000000000000 --- a/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.stderr +++ /dev/null @@ -1,48 +0,0 @@ -error[E0804]: cannot add auto trait `Send` to dyn bound via pointer cast - --> $DIR/ptr-to-trait-obj-wrap-add-auto.rs:12:5 - | -LL | a as _ - | ^^^^^^ unsupported cast - | - = note: this could allow UB elsewhere - = help: use `transmute` if you're sure this is sound - -error[E0804]: cannot add auto trait `Send` to dyn bound via pointer cast - --> $DIR/ptr-to-trait-obj-wrap-add-auto.rs:17:5 - | -LL | a as _ - | ^^^^^^ unsupported cast - | - = note: this could allow UB elsewhere - = help: use `transmute` if you're sure this is sound - -error[E0804]: cannot add auto trait `Send` to dyn bound via pointer cast - --> $DIR/ptr-to-trait-obj-wrap-add-auto.rs:22:5 - | -LL | a as _ - | ^^^^^^ unsupported cast - | - = note: this could allow UB elsewhere - = help: use `transmute` if you're sure this is sound - -error[E0804]: cannot add auto trait `Send` to dyn bound via pointer cast - --> $DIR/ptr-to-trait-obj-wrap-add-auto.rs:27:5 - | -LL | a as _ - | ^^^^^^ unsupported cast - | - = note: this could allow UB elsewhere - = help: use `transmute` if you're sure this is sound - -error[E0804]: cannot add auto trait `Send` to dyn bound via pointer cast - --> $DIR/ptr-to-trait-obj-wrap-add-auto.rs:32:5 - | -LL | a as _ - | ^^^^^^ unsupported cast - | - = note: this could allow UB elsewhere - = help: use `transmute` if you're sure this is sound - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0804`. diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.rs b/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.rs deleted file mode 100644 index ebe7a06a7a15..000000000000 --- a/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Combination of `ptr-to-trait-obj-different-args.rs` and `ptr-to-trait-obj-wrap.rs`. -// -// Checks that you *can't* change type arguments of trait objects in pointer casts involving -// wrapping said traits structures. - -trait A {} - -struct W(T); -struct X(T); - -fn unwrap(a: *const W>) -> *const dyn A { - a as _ - //~^ error casting `*const W<(dyn A + 'static)>` as `*const dyn A` is invalid -} - -fn unwrap_nested(a: *const W>>) -> *const W> { - a as _ - //~^ error casting `*const W + 'static)>>` as `*const W>` is invalid -} - -fn rewrap(a: *const W>) -> *const X> { - a as _ - //~^ error: casting `*const W<(dyn A + 'static)>` as `*const X>` is invalid -} - -fn rewrap_nested(a: *const W>>) -> *const W>> { - a as _ - //~^ error: casting `*const W + 'static)>>` as `*const W>>` is invalid -} - -fn wrap(a: *const dyn A) -> *const W> { - a as _ - //~^ error: casting `*const (dyn A + 'static)` as `*const W>` is invalid -} - -fn main() {} diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.stderr b/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.stderr deleted file mode 100644 index 4f85b208d05a..000000000000 --- a/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.stderr +++ /dev/null @@ -1,43 +0,0 @@ -error[E0606]: casting `*const W<(dyn A + 'static)>` as `*const dyn A` is invalid - --> $DIR/ptr-to-trait-obj-wrap-different-args.rs:12:5 - | -LL | a as _ - | ^^^^^^ - | - = note: the trait objects may have different vtables - -error[E0606]: casting `*const W + 'static)>>` as `*const W>` is invalid - --> $DIR/ptr-to-trait-obj-wrap-different-args.rs:17:5 - | -LL | a as _ - | ^^^^^^ - | - = note: the trait objects may have different vtables - -error[E0606]: casting `*const W<(dyn A + 'static)>` as `*const X>` is invalid - --> $DIR/ptr-to-trait-obj-wrap-different-args.rs:22:5 - | -LL | a as _ - | ^^^^^^ - | - = note: the trait objects may have different vtables - -error[E0606]: casting `*const W + 'static)>>` as `*const W>>` is invalid - --> $DIR/ptr-to-trait-obj-wrap-different-args.rs:27:5 - | -LL | a as _ - | ^^^^^^ - | - = note: the trait objects may have different vtables - -error[E0606]: casting `*const (dyn A + 'static)` as `*const W>` is invalid - --> $DIR/ptr-to-trait-obj-wrap-different-args.rs:32:5 - | -LL | a as _ - | ^^^^^^ - | - = note: the trait objects may have different vtables - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.rs b/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.rs deleted file mode 100644 index b0941277d01d..000000000000 --- a/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Combination of `ptr-to-trait-obj-different-regions-misc.rs` and `ptr-to-trait-obj-wrap.rs`. -// -// Checks that you *can't* change lifetime arguments of trait objects in pointer casts involving -// wrapping said traits structures. - -trait A<'a> {} - -struct W(T); -struct X(T); - -fn unwrap<'a, 'b>(a: *const W>) -> *const dyn A<'b> { - a as _ - //~^ error - //~| error -} - -fn unwrap_nested<'a, 'b>(a: *const W>>) -> *const W> { - a as _ - //~^ error - //~| error -} - -fn rewrap<'a, 'b>(a: *const W>) -> *const X> { - a as _ - //~^ error: lifetime may not live long enough - //~| error: lifetime may not live long enough -} - -fn rewrap_nested<'a, 'b>(a: *const W>>) -> *const W>> { - a as _ - //~^ error: lifetime may not live long enough - //~| error: lifetime may not live long enough -} - -fn wrap<'a, 'b>(a: *const dyn A<'a>) -> *const W> { - a as _ - //~^ error: lifetime may not live long enough - //~| error: lifetime may not live long enough -} - -fn main() {} diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.stderr b/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.stderr deleted file mode 100644 index 17a0ca3c34fc..000000000000 --- a/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.stderr +++ /dev/null @@ -1,140 +0,0 @@ -error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:12:5 - | -LL | fn unwrap<'a, 'b>(a: *const W>) -> *const dyn A<'b> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | a as _ - | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` - | - = help: consider adding the following bound: `'b: 'a` - -error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:12:5 - | -LL | fn unwrap<'a, 'b>(a: *const W>) -> *const dyn A<'b> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | a as _ - | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` - | - = help: consider adding the following bound: `'a: 'b` - -help: `'b` and `'a` must be the same: replace one with the other - -error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:18:5 - | -LL | fn unwrap_nested<'a, 'b>(a: *const W>>) -> *const W> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | a as _ - | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` - | - = help: consider adding the following bound: `'b: 'a` - -error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:18:5 - | -LL | fn unwrap_nested<'a, 'b>(a: *const W>>) -> *const W> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | a as _ - | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` - | - = help: consider adding the following bound: `'a: 'b` - -help: `'b` and `'a` must be the same: replace one with the other - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:24:5 - | -LL | fn rewrap<'a, 'b>(a: *const W>) -> *const X> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | a as _ - | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` - | - = help: consider adding the following bound: `'b: 'a` - -error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:24:5 - | -LL | fn rewrap<'a, 'b>(a: *const W>) -> *const X> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | a as _ - | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` - | - = help: consider adding the following bound: `'a: 'b` - -help: `'b` and `'a` must be the same: replace one with the other - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:30:5 - | -LL | fn rewrap_nested<'a, 'b>(a: *const W>>) -> *const W>> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | a as _ - | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` - | - = help: consider adding the following bound: `'b: 'a` - -error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:30:5 - | -LL | fn rewrap_nested<'a, 'b>(a: *const W>>) -> *const W>> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | a as _ - | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` - | - = help: consider adding the following bound: `'a: 'b` - -help: `'b` and `'a` must be the same: replace one with the other - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:36:5 - | -LL | fn wrap<'a, 'b>(a: *const dyn A<'a>) -> *const W> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | a as _ - | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` - | - = help: consider adding the following bound: `'b: 'a` - -error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:36:5 - | -LL | fn wrap<'a, 'b>(a: *const dyn A<'a>) -> *const W> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | a as _ - | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` - | - = help: consider adding the following bound: `'a: 'b` - -help: `'b` and `'a` must be the same: replace one with the other - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 10 previous errors - diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap.rs b/tests/ui/cast/ptr-to-trait-obj-wrap.rs deleted file mode 100644 index 9809ea80f95c..000000000000 --- a/tests/ui/cast/ptr-to-trait-obj-wrap.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Checks that various casts of pointers to trait objects wrapped in structures -// work. Note that the metadata doesn't change when a DST is wrapped in a -// structure, so these casts *are* fine. -// -//@ check-pass - -trait A {} - -struct W(T); -struct X(T); - -fn unwrap(a: *const W) -> *const dyn A { - a as _ -} - -fn unwrap_nested(a: *const W>) -> *const W { - a as _ -} - -fn rewrap(a: *const W) -> *const X { - a as _ -} - -fn rewrap_nested(a: *const W>) -> *const W> { - a as _ -} - -fn wrap(a: *const dyn A) -> *const W { - a as _ -} - -fn main() {} From 75f283e40b02b63ecebeac53138fb94c76cb27df Mon Sep 17 00:00:00 2001 From: klensy Date: Mon, 24 Mar 2025 19:40:52 +0300 Subject: [PATCH 484/745] happy tidy --- src/tools/tidy/src/deps.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 81c55ecaa7a2..1a6550691ee3 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -240,7 +240,6 @@ const PERMITTED_DEPS_LOCATION: &str = concat!(file!(), ":", line!()); const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ // tidy-alphabetical-start "adler2", - "ahash", "aho-corasick", "allocator-api2", // FIXME: only appears in Cargo.lock due to https://github.com/rust-lang/cargo/issues/10801 "annotate-snippets", From 251455bcc5b3652d2af2eed29a317d0afd907e48 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 23 Mar 2025 18:56:34 +0000 Subject: [PATCH 485/745] Allow WellFormed goals to be returned from relating in new solver --- .../src/solve/eval_ctxt/mod.rs | 16 ++++++----- .../next-solver/well-formed-in-relate.rs | 21 +++++++++++++++ .../next-solver/well-formed-in-relate.stderr | 27 +++++++++++++++++++ 3 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 tests/ui/traits/next-solver/well-formed-in-relate.rs create mode 100644 tests/ui/traits/next-solver/well-formed-in-relate.stderr diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 0322c9e4ab01..7ef36d0e9ae3 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -971,15 +971,17 @@ where rhs: T, ) -> Result<(), NoSolution> { let goals = self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)?; - if cfg!(debug_assertions) { - for g in goals.iter() { - match g.predicate.kind().skip_binder() { - ty::PredicateKind::Subtype { .. } | ty::PredicateKind::AliasRelate(..) => {} - p => unreachable!("unexpected nested goal in `relate`: {p:?}"), + for &goal in goals.iter() { + let source = match goal.predicate.kind().skip_binder() { + ty::PredicateKind::Subtype { .. } | ty::PredicateKind::AliasRelate(..) => { + GoalSource::TypeRelating } - } + // FIXME(-Znext-solver=coinductive): should these WF goals also be unproductive? + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => GoalSource::Misc, + p => unreachable!("unexpected nested goal in `relate`: {p:?}"), + }; + self.add_goal(source, goal); } - self.add_goals(GoalSource::TypeRelating, goals); Ok(()) } diff --git a/tests/ui/traits/next-solver/well-formed-in-relate.rs b/tests/ui/traits/next-solver/well-formed-in-relate.rs new file mode 100644 index 000000000000..eec1ddef228c --- /dev/null +++ b/tests/ui/traits/next-solver/well-formed-in-relate.rs @@ -0,0 +1,21 @@ +fn main() { + let x; + //~^ ERROR type annotations needed for `Map<_, _>` + higher_ranked(); + x = unconstrained_map(); +} + +fn higher_ranked() where for<'a> &'a (): Sized {} + +struct Map where T: Fn() -> U { + t: T, +} + +trait Mirror { + type Assoc; +} +impl Mirror for T { + type Assoc = T; +} + +fn unconstrained_map U, U>() -> as Mirror>::Assoc { todo!() } diff --git a/tests/ui/traits/next-solver/well-formed-in-relate.stderr b/tests/ui/traits/next-solver/well-formed-in-relate.stderr new file mode 100644 index 000000000000..5294a072d312 --- /dev/null +++ b/tests/ui/traits/next-solver/well-formed-in-relate.stderr @@ -0,0 +1,27 @@ +error[E0283]: type annotations needed for `Map<_, _>` + --> $DIR/well-formed-in-relate.rs:2:9 + | +LL | let x; + | ^ +... +LL | x = unconstrained_map(); + | ------------------- type must be known at this point + | + = note: multiple `impl`s satisfying `_: Fn()` found in the following crates: `alloc`, `core`: + - impl Fn for &F + where A: Tuple, F: Fn, F: ?Sized; + - impl Fn for Box + where Args: Tuple, F: Fn, A: Allocator, F: ?Sized; +note: required by a bound in `unconstrained_map` + --> $DIR/well-formed-in-relate.rs:21:25 + | +LL | fn unconstrained_map U, U>() -> as Mirror>::Assoc { todo!() } + | ^^^^^^^^^ required by this bound in `unconstrained_map` +help: consider giving `x` an explicit type, where the type for type parameter `T` is specified + | +LL | let x: Map; + | +++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. From aba23fd5003cf75aa524847d88d9d1337edd5f8e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 21 Mar 2025 19:28:35 +0000 Subject: [PATCH 486/745] Don't mark privacy test as needing GCE --- .../where-pub-type-impls-priv-trait.rs | 1 - .../where-pub-type-impls-priv-trait.stderr | 20 +++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/tests/ui/privacy/where-pub-type-impls-priv-trait.rs b/tests/ui/privacy/where-pub-type-impls-priv-trait.rs index 1ebc396cdf5b..57548f75d5e4 100644 --- a/tests/ui/privacy/where-pub-type-impls-priv-trait.rs +++ b/tests/ui/privacy/where-pub-type-impls-priv-trait.rs @@ -3,7 +3,6 @@ // priv-in-pub lint tests where the private trait bounds a public type #![crate_type = "lib"] -#![feature(generic_const_exprs)] #![allow(incomplete_features)] struct PrivTy; diff --git a/tests/ui/privacy/where-pub-type-impls-priv-trait.stderr b/tests/ui/privacy/where-pub-type-impls-priv-trait.stderr index ee79ce3f5d75..33f82a3a4fec 100644 --- a/tests/ui/privacy/where-pub-type-impls-priv-trait.stderr +++ b/tests/ui/privacy/where-pub-type-impls-priv-trait.stderr @@ -1,30 +1,30 @@ warning: trait `PrivTr` is more private than the item `S` - --> $DIR/where-pub-type-impls-priv-trait.rs:20:1 + --> $DIR/where-pub-type-impls-priv-trait.rs:19:1 | LL | pub struct S | ^^^^^^^^^^^^ struct `S` is reachable at visibility `pub` | note: but trait `PrivTr` is only usable at visibility `pub(crate)` - --> $DIR/where-pub-type-impls-priv-trait.rs:10:1 + --> $DIR/where-pub-type-impls-priv-trait.rs:9:1 | LL | trait PrivTr {} | ^^^^^^^^^^^^ = note: `#[warn(private_bounds)]` on by default warning: trait `PrivTr` is more private than the item `E` - --> $DIR/where-pub-type-impls-priv-trait.rs:27:1 + --> $DIR/where-pub-type-impls-priv-trait.rs:26:1 | LL | pub enum E | ^^^^^^^^^^ enum `E` is reachable at visibility `pub` | note: but trait `PrivTr` is only usable at visibility `pub(crate)` - --> $DIR/where-pub-type-impls-priv-trait.rs:10:1 + --> $DIR/where-pub-type-impls-priv-trait.rs:9:1 | LL | trait PrivTr {} | ^^^^^^^^^^^^ warning: trait `PrivTr` is more private than the item `f` - --> $DIR/where-pub-type-impls-priv-trait.rs:34:1 + --> $DIR/where-pub-type-impls-priv-trait.rs:33:1 | LL | / pub fn f() LL | | @@ -33,13 +33,13 @@ LL | | PubTy: PrivTr | |_________________^ function `f` is reachable at visibility `pub` | note: but trait `PrivTr` is only usable at visibility `pub(crate)` - --> $DIR/where-pub-type-impls-priv-trait.rs:10:1 + --> $DIR/where-pub-type-impls-priv-trait.rs:9:1 | LL | trait PrivTr {} | ^^^^^^^^^^^^ warning: trait `PrivTr` is more private than the item `S` - --> $DIR/where-pub-type-impls-priv-trait.rs:41:1 + --> $DIR/where-pub-type-impls-priv-trait.rs:40:1 | LL | / impl S LL | | @@ -48,13 +48,13 @@ LL | | PubTy: PrivTr | |_________________^ implementation `S` is reachable at visibility `pub` | note: but trait `PrivTr` is only usable at visibility `pub(crate)` - --> $DIR/where-pub-type-impls-priv-trait.rs:10:1 + --> $DIR/where-pub-type-impls-priv-trait.rs:9:1 | LL | trait PrivTr {} | ^^^^^^^^^^^^ warning: trait `PrivTr` is more private than the item `S::f` - --> $DIR/where-pub-type-impls-priv-trait.rs:46:5 + --> $DIR/where-pub-type-impls-priv-trait.rs:45:5 | LL | / pub fn f() LL | | @@ -63,7 +63,7 @@ LL | | PubTy: PrivTr | |_____________________^ associated function `S::f` is reachable at visibility `pub` | note: but trait `PrivTr` is only usable at visibility `pub(crate)` - --> $DIR/where-pub-type-impls-priv-trait.rs:10:1 + --> $DIR/where-pub-type-impls-priv-trait.rs:9:1 | LL | trait PrivTr {} | ^^^^^^^^^^^^ From c80d9b8d67a78ed19be86f9d129a57922c7dc86e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 22 Mar 2025 18:51:33 +0000 Subject: [PATCH 487/745] Don't ICE when encountering placeholders in layout computation --- compiler/rustc_ty_utils/src/layout.rs | 8 ++------ ...e.stderr => too_generic_eval_ice.current.stderr} | 8 ++++---- tests/ui/consts/too_generic_eval_ice.next.stderr | 9 +++++++++ tests/ui/consts/too_generic_eval_ice.rs | 13 +++++++++---- 4 files changed, 24 insertions(+), 14 deletions(-) rename tests/ui/consts/{too_generic_eval_ice.stderr => too_generic_eval_ice.current.stderr} (90%) create mode 100644 tests/ui/consts/too_generic_eval_ice.next.stderr diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 7334beb52c9d..0017186c1b08 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -611,7 +611,7 @@ fn layout_of_uncached<'tcx>( } // Types with no meaningful known layout. - ty::Param(_) => { + ty::Param(_) | ty::Placeholder(..) => { return Err(error(cx, LayoutError::TooGeneric(ty))); } @@ -628,11 +628,7 @@ fn layout_of_uncached<'tcx>( return Err(error(cx, err)); } - ty::Placeholder(..) - | ty::Bound(..) - | ty::CoroutineWitness(..) - | ty::Infer(_) - | ty::Error(_) => { + ty::Bound(..) | ty::CoroutineWitness(..) | ty::Infer(_) | ty::Error(_) => { // `ty::Error` is handled at the top of this function. bug!("layout_of: unexpected type `{ty}`") } diff --git a/tests/ui/consts/too_generic_eval_ice.stderr b/tests/ui/consts/too_generic_eval_ice.current.stderr similarity index 90% rename from tests/ui/consts/too_generic_eval_ice.stderr rename to tests/ui/consts/too_generic_eval_ice.current.stderr index 3cc4377514a2..02bcaee80154 100644 --- a/tests/ui/consts/too_generic_eval_ice.stderr +++ b/tests/ui/consts/too_generic_eval_ice.current.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/too_generic_eval_ice.rs:7:13 + --> $DIR/too_generic_eval_ice.rs:11:13 | LL | [5; Self::HOST_SIZE] == [6; 0] | ^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | [5; Self::HOST_SIZE] == [6; 0] = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter - --> $DIR/too_generic_eval_ice.rs:7:9 + --> $DIR/too_generic_eval_ice.rs:11:9 | LL | [5; Self::HOST_SIZE] == [6; 0] | ^^^^^^^^^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | [5; Self::HOST_SIZE] == [6; 0] = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter - --> $DIR/too_generic_eval_ice.rs:7:30 + --> $DIR/too_generic_eval_ice.rs:11:30 | LL | [5; Self::HOST_SIZE] == [6; 0] | ^^ @@ -23,7 +23,7 @@ LL | [5; Self::HOST_SIZE] == [6; 0] = note: this may fail depending on what value the parameter takes error[E0277]: can't compare `[{integer}; Self::HOST_SIZE]` with `[{integer}; 0]` - --> $DIR/too_generic_eval_ice.rs:7:30 + --> $DIR/too_generic_eval_ice.rs:11:30 | LL | [5; Self::HOST_SIZE] == [6; 0] | ^^ no implementation for `[{integer}; Self::HOST_SIZE] == [{integer}; 0]` diff --git a/tests/ui/consts/too_generic_eval_ice.next.stderr b/tests/ui/consts/too_generic_eval_ice.next.stderr new file mode 100644 index 000000000000..01da33241c81 --- /dev/null +++ b/tests/ui/consts/too_generic_eval_ice.next.stderr @@ -0,0 +1,9 @@ +error[E0284]: type annotations needed: cannot satisfy `the constant `Self::HOST_SIZE` can be evaluated` + --> $DIR/too_generic_eval_ice.rs:11:13 + | +LL | [5; Self::HOST_SIZE] == [6; 0] + | ^^^^^^^^^^^^^^^ cannot satisfy `the constant `Self::HOST_SIZE` can be evaluated` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/consts/too_generic_eval_ice.rs b/tests/ui/consts/too_generic_eval_ice.rs index 0d46a4c8276d..ff741cdcf20b 100644 --- a/tests/ui/consts/too_generic_eval_ice.rs +++ b/tests/ui/consts/too_generic_eval_ice.rs @@ -1,3 +1,7 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + pub struct Foo(A, B); impl Foo { @@ -5,10 +9,11 @@ impl Foo { pub fn crash() -> bool { [5; Self::HOST_SIZE] == [6; 0] - //~^ ERROR constant expression depends on a generic parameter - //~| ERROR constant expression depends on a generic parameter - //~| ERROR constant expression depends on a generic parameter - //~| ERROR can't compare `[{integer}; Self::HOST_SIZE]` with `[{integer}; 0]` + //[current]~^ ERROR constant expression depends on a generic parameter + //[current]~| ERROR constant expression depends on a generic parameter + //[current]~| ERROR constant expression depends on a generic parameter + //[current]~| ERROR can't compare `[{integer}; Self::HOST_SIZE]` with `[{integer}; 0]` + //[next]~^^^^^ ERROR type annotations needed } } From 484362e3f809ec77eae394603e587ec49a9348e7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 21 Mar 2025 18:04:34 +0000 Subject: [PATCH 488/745] Mark a fixed test --- ...err => dedup-normalized-2-higher-ranked.current.stderr} | 4 ++-- .../dedup-normalized-2-higher-ranked.rs | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) rename tests/ui/associated-type-bounds/{dedup-normalized-2-higher-ranked.stderr => dedup-normalized-2-higher-ranked.current.stderr} (86%) diff --git a/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.stderr b/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.current.stderr similarity index 86% rename from tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.stderr rename to tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.current.stderr index 372d379de5a4..64304be9d6b1 100644 --- a/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.stderr +++ b/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.current.stderr @@ -1,12 +1,12 @@ error[E0283]: type annotations needed - --> $DIR/dedup-normalized-2-higher-ranked.rs:23:5 + --> $DIR/dedup-normalized-2-higher-ranked.rs:28:5 | LL | impls(rigid); | ^^^^^ cannot infer type of the type parameter `U` declared on the function `impls` | = note: cannot satisfy `for<'b>

::Rigid: Bound<'b, _>` note: required by a bound in `impls` - --> $DIR/dedup-normalized-2-higher-ranked.rs:20:13 + --> $DIR/dedup-normalized-2-higher-ranked.rs:25:13 | LL | fn impls Bound<'b, U>, U>(_: T) {} | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `impls` diff --git a/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.rs b/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.rs index 9224d47d30fd..32b8c689248f 100644 --- a/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.rs +++ b/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.rs @@ -1,3 +1,8 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass + // We try to prove `for<'b> T::Rigid: Bound<'b, ?0>` and have 2 candidates from where-clauses: // // - `for<'a> Bound<'a, String>` @@ -21,7 +26,7 @@ fn impls Bound<'b, U>, U>(_: T) {} fn test(rigid: P::Rigid) { impls(rigid); - //~^ ERROR type annotations needed + //[current]~^ ERROR type annotations needed } fn main() {} From 41d68e098c29d59714165fef30f705fac9baf8a0 Mon Sep 17 00:00:00 2001 From: rustbot <47979223+rustbot@users.noreply.github.com> Date: Mon, 24 Mar 2025 18:00:58 +0100 Subject: [PATCH 489/745] Update books --- src/doc/book | 2 +- src/doc/reference | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/book b/src/doc/book index 81a976a237f8..45f05367360f 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 81a976a237f84b8392c4ce1bd5fd076eb757a2eb +Subproject commit 45f05367360f033f89235eacbbb54e8d73ce6b70 diff --git a/src/doc/reference b/src/doc/reference index dda31c85f2ef..e95ebdfee025 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit dda31c85f2ef2e5d2f0f2f643c9231690a30a626 +Subproject commit e95ebdfee02514d93f79ec92ae310a804e87f01f From 60e4a1b8f37c48cfc4c8c78aaafc5ff2f8d02ca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 19 Mar 2025 02:31:12 +0100 Subject: [PATCH 490/745] Remove `prev_index_to_index` field from `CurrentDepGraph` --- .../rustc_query_system/src/dep_graph/graph.rs | 291 +++++++----------- .../src/dep_graph/serialized.rs | 38 ++- 2 files changed, 144 insertions(+), 185 deletions(-) diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index de5bbacf2740..495f34733f70 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -66,7 +66,7 @@ pub struct MarkFrame<'a> { parent: Option<&'a MarkFrame<'a>>, } -enum DepNodeColor { +pub(super) enum DepNodeColor { Red, Green(DepNodeIndex), } @@ -140,7 +140,7 @@ impl DepGraph { let colors = DepNodeColorMap::new(prev_graph_node_count); // Instantiate a dependy-less node only once for anonymous queries. - let _green_node_index = current.alloc_new_node( + let _green_node_index = current.alloc_node( DepNode { kind: D::DEP_KIND_NULL, hash: current.anon_id_seed.into() }, EdgesVec::new(), Fingerprint::ZERO, @@ -148,26 +148,17 @@ impl DepGraph { assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_DEPENDENCYLESS_ANON_NODE); // Instantiate a dependy-less red node only once for anonymous queries. - let (red_node_index, red_node_prev_index_and_color) = current.intern_node( - &prev_graph, + let red_node_index = current.alloc_node( DepNode { kind: D::DEP_KIND_RED, hash: Fingerprint::ZERO.into() }, EdgesVec::new(), - None, + Fingerprint::ZERO, ); assert_eq!(red_node_index, DepNodeIndex::FOREVER_RED_NODE); - match red_node_prev_index_and_color { - None => { - // This is expected when we have no previous compilation session. - assert!(prev_graph_node_count == 0); - } - Some((prev_red_node_index, DepNodeColor::Red)) => { - assert_eq!(prev_red_node_index.as_usize(), red_node_index.as_usize()); - colors.insert(prev_red_node_index, DepNodeColor::Red); - } - Some((_, DepNodeColor::Green(_))) => { - // There must be a logic error somewhere if we hit this branch. - panic!("DepNodeIndex::FOREVER_RED_NODE evaluated to DepNodeColor::Green") - } + if prev_graph_node_count > 0 { + colors.insert( + SerializedDepNodeIndex::from_u32(DepNodeIndex::FOREVER_RED_NODE.as_u32()), + DepNodeColor::Red, + ); } DepGraph { @@ -376,8 +367,7 @@ impl DepGraphData { }; let dcx = cx.dep_context(); - let dep_node_index = - self.hash_result_and_intern_node(dcx, key, edges, &result, hash_result); + let dep_node_index = self.hash_result_and_alloc_node(dcx, key, edges, &result, hash_result); (result, dep_node_index) } @@ -447,7 +437,7 @@ impl DepGraphData { // memory impact of this `anon_node_to_index` map remains tolerable, and helps // us avoid useless growth of the graph with almost-equivalent nodes. self.current.anon_node_to_index.get_or_insert_with(target_dep_node, || { - self.current.alloc_new_node(target_dep_node, task_deps, Fingerprint::ZERO) + self.current.alloc_node(target_dep_node, task_deps, Fingerprint::ZERO) }) } }; @@ -456,7 +446,7 @@ impl DepGraphData { } /// Intern the new `DepNode` with the dependencies up-to-now. - fn hash_result_and_intern_node, R>( + fn hash_result_and_alloc_node, R>( &self, cx: &Ctxt, node: DepNode, @@ -468,22 +458,8 @@ impl DepGraphData { let current_fingerprint = hash_result.map(|hash_result| { cx.with_stable_hashing_context(|mut hcx| hash_result(&mut hcx, result)) }); - - // Intern the new `DepNode` with the dependencies up-to-now. - let (dep_node_index, prev_and_color) = - self.current.intern_node(&self.previous, node, edges, current_fingerprint); - + let dep_node_index = self.alloc_and_color_node(node, edges, current_fingerprint); hashing_timer.finish_with_query_invocation_id(dep_node_index.into()); - - if let Some((prev_index, color)) = prev_and_color { - debug_assert!( - self.colors.get(prev_index).is_none(), - "DepGraph::with_task() - Duplicate DepNodeColor insertion for {node:?}", - ); - - self.colors.insert(prev_index, color); - } - dep_node_index } } @@ -601,7 +577,7 @@ impl DepGraph { // // For sanity, we still check that the loaded stable hash and the new one match. if let Some(prev_index) = data.previous.node_to_index_opt(&node) { - let dep_node_index = data.current.prev_index_to_index.lock()[prev_index]; + let dep_node_index = data.colors.current(prev_index); if let Some(dep_node_index) = dep_node_index { crate::query::incremental_verify_ich( cx, @@ -637,7 +613,7 @@ impl DepGraph { } }); - data.hash_result_and_intern_node(&cx, node, edges, result, hash_result) + data.hash_result_and_alloc_node(&cx, node, edges, result, hash_result) } else { // Incremental compilation is turned off. We just execute the task // without tracking. We still provide a dep-node index that uniquely @@ -655,13 +631,11 @@ impl DepGraphData { msg: impl FnOnce() -> S, ) { if let Some(prev_index) = self.previous.node_to_index_opt(dep_node) { - let current = self.current.prev_index_to_index.lock()[prev_index]; + let current = self.colors.get(prev_index); assert!(current.is_none(), "{}", msg()) - } else if let Some(nodes_newly_allocated_in_current_session) = - &self.current.nodes_newly_allocated_in_current_session - { + } else if let Some(nodes_in_current_session) = &self.current.nodes_in_current_session { outline(|| { - let seen = nodes_newly_allocated_in_current_session.lock().contains_key(dep_node); + let seen = nodes_in_current_session.lock().contains_key(dep_node); assert!(!seen, "{}", msg()); }); } @@ -738,15 +712,77 @@ impl DepGraphData { } } - // Promote the previous diagnostics to the current session. - let index = self.current.promote_node_and_deps_to_current(&self.previous, prev_index); - // FIXME: Can this race with a parallel compiler? - qcx.store_side_effect(index, side_effect); + // Manually recreate the node as `promote_node_and_deps_to_current` expects all + // green dependencies. + let dep_node_index = self.current.encoder.send( + DepNode { + kind: D::DEP_KIND_SIDE_EFFECT, + hash: PackedFingerprint::from(Fingerprint::ZERO), + }, + Fingerprint::ZERO, + std::iter::once(DepNodeIndex::FOREVER_RED_NODE).collect(), + ); + qcx.store_side_effect(dep_node_index, side_effect); // Mark the node as green. - self.colors.insert(prev_index, DepNodeColor::Green(index)); + self.colors.insert(prev_index, DepNodeColor::Green(dep_node_index)); }) } + + fn alloc_and_color_node( + &self, + key: DepNode, + edges: EdgesVec, + fingerprint: Option, + ) -> DepNodeIndex { + let dep_node_index = + self.current.alloc_node(key, edges, fingerprint.unwrap_or(Fingerprint::ZERO)); + + if let Some(prev_index) = self.previous.node_to_index_opt(&key) { + // Determine the color and index of the new `DepNode`. + let color = if let Some(fingerprint) = fingerprint { + if fingerprint == self.previous.fingerprint_by_index(prev_index) { + // This is a green node: it existed in the previous compilation, + // its query was re-executed, and it has the same result as before. + DepNodeColor::Green(dep_node_index) + } else { + // This is a red node: it existed in the previous compilation, its query + // was re-executed, but it has a different result from before. + DepNodeColor::Red + } + } else { + // This is a red node, effectively: it existed in the previous compilation + // session, its query was re-executed, but it doesn't compute a result hash + // (i.e. it represents a `no_hash` query), so we have no way of determining + // whether or not the result was the same as before. + DepNodeColor::Red + }; + + debug_assert!( + self.colors.get(prev_index).is_none(), + "DepGraph::with_task() - Duplicate DepNodeColor insertion for {key:?}", + ); + + self.colors.insert(prev_index, color); + } + + dep_node_index + } + + fn promote_node_and_deps_to_current(&self, prev_index: SerializedDepNodeIndex) -> DepNodeIndex { + self.current.debug_assert_not_in_new_nodes(&self.previous, prev_index); + + let dep_node_index = self.current.encoder.send_promoted(prev_index, &self.colors); + + #[cfg(debug_assertions)] + self.current.record_edge( + dep_node_index, + self.previous.index_to_node(prev_index), + self.previous.fingerprint_by_index(prev_index), + ); + + dep_node_index + } } impl DepGraph { @@ -948,14 +984,10 @@ impl DepGraphData { // We allocating an entry for the node in the current dependency graph and // adding all the appropriate edges imported from the previous graph - let dep_node_index = - self.current.promote_node_and_deps_to_current(&self.previous, prev_dep_node_index); - - // ... emitting any stored diagnostic ... + let dep_node_index = self.promote_node_and_deps_to_current(prev_dep_node_index); // ... and finally storing a "Green" entry in the color map. // Multiple threads can all write the same color here - self.colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index)); debug!("successfully marked {dep_node:?} as green"); Some(dep_node_index) @@ -1106,7 +1138,6 @@ rustc_index::newtype_index! { /// first, and `data` second. pub(super) struct CurrentDepGraph { encoder: GraphEncoder, - prev_index_to_index: Lock>>, anon_node_to_index: ShardedHashMap, /// This is used to verify that fingerprints do not change between the creation of a node @@ -1123,9 +1154,8 @@ pub(super) struct CurrentDepGraph { /// This field is only `Some` if the `-Z incremental_verify_ich` option is present /// or if `debug_assertions` are enabled. /// - /// The map contains all DepNodes that have been allocated in the current session so far and - /// for which there is no equivalent in the previous session. - nodes_newly_allocated_in_current_session: Option>>, + /// The map contains all DepNodes that have been allocated in the current session so far. + nodes_in_current_session: Option>>, /// Anonymous `DepNode`s are nodes whose IDs we compute from the list of /// their edges. This has the beneficial side-effect that multiple anonymous @@ -1190,13 +1220,12 @@ impl CurrentDepGraph { // FIXME: The count estimate is off as anon nodes are only a portion of the nodes. new_node_count_estimate / sharded::shards(), ), - prev_index_to_index: Lock::new(IndexVec::from_elem_n(None, prev_graph_node_count)), anon_id_seed, #[cfg(debug_assertions)] forbidden_edge, #[cfg(debug_assertions)] fingerprints: Lock::new(IndexVec::from_elem_n(None, new_node_count_estimate)), - nodes_newly_allocated_in_current_session: new_node_dbg.then(|| { + nodes_in_current_session: new_node_dbg.then(|| { Lock::new(FxHashMap::with_capacity_and_hasher( new_node_count_estimate, Default::default(), @@ -1219,7 +1248,7 @@ impl CurrentDepGraph { /// Writes the node to the current dep-graph and allocates a `DepNodeIndex` for it. /// Assumes that this is a node that has no equivalent in the previous dep-graph. #[inline(always)] - fn alloc_new_node( + fn alloc_node( &self, key: DepNode, edges: EdgesVec, @@ -1230,15 +1259,9 @@ impl CurrentDepGraph { #[cfg(debug_assertions)] self.record_edge(dep_node_index, key, current_fingerprint); - if let Some(ref nodes_newly_allocated_in_current_session) = - self.nodes_newly_allocated_in_current_session - { + if let Some(ref nodes_in_current_session) = self.nodes_in_current_session { outline(|| { - if nodes_newly_allocated_in_current_session - .lock() - .insert(key, dep_node_index) - .is_some() - { + if nodes_in_current_session.lock().insert(key, dep_node_index).is_some() { panic!("Found duplicate dep-node {key:?}"); } }); @@ -1247,102 +1270,20 @@ impl CurrentDepGraph { dep_node_index } - fn intern_node( - &self, - prev_graph: &SerializedDepGraph, - key: DepNode, - edges: EdgesVec, - fingerprint: Option, - ) -> (DepNodeIndex, Option<(SerializedDepNodeIndex, DepNodeColor)>) { - if let Some(prev_index) = prev_graph.node_to_index_opt(&key) { - let get_dep_node_index = |fingerprint| { - let mut prev_index_to_index = self.prev_index_to_index.lock(); - - let dep_node_index = match prev_index_to_index[prev_index] { - Some(dep_node_index) => dep_node_index, - None => { - let dep_node_index = self.encoder.send(key, fingerprint, edges); - prev_index_to_index[prev_index] = Some(dep_node_index); - dep_node_index - } - }; - - #[cfg(debug_assertions)] - self.record_edge(dep_node_index, key, fingerprint); - - dep_node_index - }; - - // Determine the color and index of the new `DepNode`. - if let Some(fingerprint) = fingerprint { - if fingerprint == prev_graph.fingerprint_by_index(prev_index) { - // This is a green node: it existed in the previous compilation, - // its query was re-executed, and it has the same result as before. - let dep_node_index = get_dep_node_index(fingerprint); - (dep_node_index, Some((prev_index, DepNodeColor::Green(dep_node_index)))) - } else { - // This is a red node: it existed in the previous compilation, its query - // was re-executed, but it has a different result from before. - let dep_node_index = get_dep_node_index(fingerprint); - (dep_node_index, Some((prev_index, DepNodeColor::Red))) - } - } else { - // This is a red node, effectively: it existed in the previous compilation - // session, its query was re-executed, but it doesn't compute a result hash - // (i.e. it represents a `no_hash` query), so we have no way of determining - // whether or not the result was the same as before. - let dep_node_index = get_dep_node_index(Fingerprint::ZERO); - (dep_node_index, Some((prev_index, DepNodeColor::Red))) - } - } else { - let fingerprint = fingerprint.unwrap_or(Fingerprint::ZERO); - - // This is a new node: it didn't exist in the previous compilation session. - let dep_node_index = self.alloc_new_node(key, edges, fingerprint); - - (dep_node_index, None) - } - } - - fn promote_node_and_deps_to_current( - &self, - prev_graph: &SerializedDepGraph, - prev_index: SerializedDepNodeIndex, - ) -> DepNodeIndex { - self.debug_assert_not_in_new_nodes(prev_graph, prev_index); - - let mut prev_index_to_index = self.prev_index_to_index.lock(); - - match prev_index_to_index[prev_index] { - Some(dep_node_index) => dep_node_index, - None => { - let dep_node_index = self.encoder.send_promoted(prev_index, &*prev_index_to_index); - prev_index_to_index[prev_index] = Some(dep_node_index); - #[cfg(debug_assertions)] - self.record_edge( - dep_node_index, - prev_graph.index_to_node(prev_index), - prev_graph.fingerprint_by_index(prev_index), - ); - dep_node_index - } - } - } - #[inline] fn debug_assert_not_in_new_nodes( &self, prev_graph: &SerializedDepGraph, prev_index: SerializedDepNodeIndex, ) { - let node = &prev_graph.index_to_node(prev_index); - debug_assert!( - !self - .nodes_newly_allocated_in_current_session - .as_ref() - .map_or(false, |set| set.lock().contains_key(node)), - "node from previous graph present in new node collection" - ); + if let Some(ref nodes_in_current_session) = self.nodes_in_current_session { + debug_assert!( + !nodes_in_current_session + .lock() + .contains_key(&prev_graph.index_to_node(prev_index)), + "node from previous graph present in new node collection" + ); + } } } @@ -1389,36 +1330,40 @@ impl Default for TaskDeps { } // A data structure that stores Option values as a contiguous // array, using one u32 per entry. -struct DepNodeColorMap { +pub(super) struct DepNodeColorMap { values: IndexVec, } -const COMPRESSED_NONE: u32 = 0; -const COMPRESSED_RED: u32 = 1; -const COMPRESSED_FIRST_GREEN: u32 = 2; +const COMPRESSED_NONE: u32 = u32::MAX; +const COMPRESSED_RED: u32 = u32::MAX - 1; impl DepNodeColorMap { fn new(size: usize) -> DepNodeColorMap { + debug_assert!(COMPRESSED_RED > DepNodeIndex::MAX_AS_U32); DepNodeColorMap { values: (0..size).map(|_| AtomicU32::new(COMPRESSED_NONE)).collect() } } #[inline] - fn get(&self, index: SerializedDepNodeIndex) -> Option { + pub(super) fn current(&self, index: SerializedDepNodeIndex) -> Option { + let value = self.values[index].load(Ordering::Relaxed); + if value <= DepNodeIndex::MAX_AS_U32 { Some(DepNodeIndex::from_u32(value)) } else { None } + } + + #[inline] + pub(super) fn get(&self, index: SerializedDepNodeIndex) -> Option { match self.values[index].load(Ordering::Acquire) { COMPRESSED_NONE => None, COMPRESSED_RED => Some(DepNodeColor::Red), - value => { - Some(DepNodeColor::Green(DepNodeIndex::from_u32(value - COMPRESSED_FIRST_GREEN))) - } + value => Some(DepNodeColor::Green(DepNodeIndex::from_u32(value))), } } #[inline] - fn insert(&self, index: SerializedDepNodeIndex, color: DepNodeColor) { + pub(super) fn insert(&self, index: SerializedDepNodeIndex, color: DepNodeColor) { self.values[index].store( match color { DepNodeColor::Red => COMPRESSED_RED, - DepNodeColor::Green(index) => index.as_u32() + COMPRESSED_FIRST_GREEN, + DepNodeColor::Green(index) => index.as_u32(), }, Ordering::Release, ) @@ -1454,16 +1399,16 @@ fn panic_on_forbidden_read(data: &DepGraphData, dep_node_index: DepN let mut dep_node = None; // First try to find the dep node among those that already existed in the - // previous session - for (prev_index, index) in data.current.prev_index_to_index.lock().iter_enumerated() { - if index == &Some(dep_node_index) { + // previous session and has been marked green + for prev_index in data.colors.values.indices() { + if data.colors.current(prev_index) == Some(dep_node_index) { dep_node = Some(data.previous.index_to_node(prev_index)); break; } } if dep_node.is_none() - && let Some(nodes) = &data.current.nodes_newly_allocated_in_current_session + && let Some(nodes) = &data.current.nodes_in_current_session { // Try to find it among the nodes allocated so far in this session if let Some((node, _)) = nodes.lock().iter().find(|&(_, index)| *index == dep_node_index) { diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index f4b2cf631ed7..7750d6d1fef4 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -50,6 +50,7 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixed use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use tracing::{debug, instrument}; +use super::graph::{DepNodeColor, DepNodeColorMap}; use super::query::DepGraphQuery; use super::{DepKind, DepNode, DepNodeIndex, Deps}; use crate::dep_graph::edges::EdgesVec; @@ -441,7 +442,7 @@ impl NodeInfo { node: DepNode, fingerprint: Fingerprint, prev_index: SerializedDepNodeIndex, - prev_index_to_index: &IndexVec>, + colors: &DepNodeColorMap, previous: &SerializedDepGraph, ) -> usize { let edges = previous.edge_targets_from(prev_index); @@ -449,7 +450,7 @@ impl NodeInfo { // Find the highest edge in the new dep node indices let edge_max = - edges.clone().map(|i| prev_index_to_index[i].unwrap().as_u32()).max().unwrap_or(0); + edges.clone().map(|i| colors.current(i).unwrap().as_u32()).max().unwrap_or(0); let header = SerializedNodeHeader::::new(node, fingerprint, edge_max, edge_count); e.write_array(header.bytes); @@ -460,7 +461,7 @@ impl NodeInfo { let bytes_per_index = header.bytes_per_index(); for node_index in edges { - let node_index = prev_index_to_index[node_index].unwrap(); + let node_index = colors.current(node_index).unwrap(); e.write_with(|dest| { *dest = node_index.as_u32().to_le_bytes(); bytes_per_index @@ -565,7 +566,7 @@ impl EncoderState { &mut self, prev_index: SerializedDepNodeIndex, record_graph: &Option>, - prev_index_to_index: &IndexVec>, + colors: &DepNodeColorMap, ) -> DepNodeIndex { let node = self.previous.index_to_node(prev_index); @@ -575,7 +576,7 @@ impl EncoderState { node, fingerprint, prev_index, - prev_index_to_index, + colors, &self.previous, ); @@ -585,7 +586,7 @@ impl EncoderState { |this| { this.previous .edge_targets_from(prev_index) - .map(|i| prev_index_to_index[i].unwrap()) + .map(|i| colors.current(i).unwrap()) .collect() }, record_graph, @@ -719,18 +720,31 @@ impl GraphEncoder { /// Encodes a node that was promoted from the previous graph. It reads the information directly from /// the previous dep graph and expects all edges to already have a new dep node index assigned. + /// + /// This will also ensure the dep node is marked green. #[inline] pub(crate) fn send_promoted( &self, prev_index: SerializedDepNodeIndex, - prev_index_to_index: &IndexVec>, + colors: &DepNodeColorMap, ) -> DepNodeIndex { let _prof_timer = self.profiler.generic_activity("incr_comp_encode_dep_graph"); - self.status.lock().as_mut().unwrap().encode_promoted_node( - prev_index, - &self.record_graph, - prev_index_to_index, - ) + + let mut status = self.status.lock(); + let status = status.as_mut().unwrap(); + + // Check colors inside the lock to avoid racing when `send_promoted` is called concurrently + // on the same index. + match colors.get(prev_index) { + None => { + let dep_node_index = + status.encode_promoted_node(prev_index, &self.record_graph, colors); + colors.insert(prev_index, DepNodeColor::Green(dep_node_index)); + dep_node_index + } + Some(DepNodeColor::Green(dep_node_index)) => dep_node_index, + Some(DepNodeColor::Red) => panic!(), + } } pub(crate) fn finish(&self) -> FileEncodeResult { From 848b0da34fa20d0ff5d12d1d4f506affc765534b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sun, 23 Mar 2025 22:00:39 +0100 Subject: [PATCH 491/745] Remove fields that are dead since the removal of type ascription syntax Since `{ ident: ident }` is a parse error, these fields are dead. --- compiler/rustc_ast/src/ast.rs | 8 ------ compiler/rustc_ast/src/mut_visit.rs | 2 +- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_builtin_macros/src/autodiff.rs | 1 - .../rustc_builtin_macros/src/deriving/mod.rs | 1 - compiler/rustc_expand/src/build.rs | 1 - .../rustc_parse/src/parser/diagnostics.rs | 25 ++++++++----------- compiler/rustc_parse/src/parser/stmt.rs | 9 +------ compiler/rustc_resolve/src/late.rs | 13 ---------- .../rustc_resolve/src/late/diagnostics.rs | 14 ----------- src/tools/rustfmt/src/closures.rs | 1 - src/tools/rustfmt/src/macros.rs | 1 - tests/ui-fulldeps/pprust-expr-roundtrip.rs | 1 - 13 files changed, 13 insertions(+), 66 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 5b7545b33966..cc2fa8810d69 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -545,14 +545,6 @@ pub struct Block { pub rules: BlockCheckMode, pub span: Span, pub tokens: Option, - /// The following *isn't* a parse error, but will cause multiple errors in following stages. - /// ```compile_fail - /// let x = { - /// foo: var - /// }; - /// ``` - /// #34255 - pub could_be_bare_literal: bool, } /// A match pattern. diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 4edd08643000..c898a60fbe69 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1225,7 +1225,7 @@ fn walk_mt(vis: &mut T, MutTy { ty, mutbl: _ }: &mut MutTy) { } pub fn walk_block(vis: &mut T, block: &mut P) { - let Block { id, stmts, rules: _, span, tokens, could_be_bare_literal: _ } = block.deref_mut(); + let Block { id, stmts, rules: _, span, tokens } = block.deref_mut(); vis.visit_id(id); stmts.flat_map_in_place(|stmt| vis.flat_map_stmt(stmt)); visit_lazy_tts(vis, tokens); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index ce8d6df75afb..50d8aa293c5c 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -1035,7 +1035,7 @@ pub fn walk_field_def<'a, V: Visitor<'a>>(visitor: &mut V, field: &'a FieldDef) } pub fn walk_block<'a, V: Visitor<'a>>(visitor: &mut V, block: &'a Block) -> V::Result { - let Block { stmts, id: _, rules: _, span: _, tokens: _, could_be_bare_literal: _ } = block; + let Block { stmts, id: _, rules: _, span: _, tokens: _ } = block; walk_list!(visitor, visit_stmt, stmts); V::Result::output() } diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index 6591ed151cf6..f3a40b8c6829 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -395,7 +395,6 @@ mod llvm_enzyme { tokens: None, rules: unsf, span, - could_be_bare_literal: false, }; let unsf_expr = ecx.expr_block(P(unsf_block)); let blackbox_call_expr = ecx.expr_path(ecx.path(span, blackbox_path)); diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index c112589b1319..50e7b989ed8a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -110,7 +110,6 @@ fn call_unreachable(cx: &ExtCtxt<'_>, span: Span) -> P { rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated), span, tokens: None, - could_be_bare_literal: false, })) } diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index ee7f68cc2f01..99b336969e47 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -286,7 +286,6 @@ impl<'a> ExtCtxt<'a> { rules: BlockCheckMode::Default, span, tokens: None, - could_be_bare_literal: false, }) } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index c1cca1186af4..daa27b146690 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -971,18 +971,8 @@ impl<'a> Parser<'a> { // fn foo() -> Foo { // field: value, // } - // Suggest: - // fn foo() -> Foo { Path { - // field: value, - // } } let guar = err.delay_as_bug(); self.restore_snapshot(snapshot); - let mut tail = self.mk_block( - thin_vec![self.mk_stmt_err(expr.span, guar)], - s, - lo.to(self.prev_token.span), - ); - tail.could_be_bare_literal = true; if maybe_struct_name.is_ident() && can_be_struct_literal { // Account for `if Example { a: one(), }.is_pos() {}`. // expand `before` so that we take care of module path such as: @@ -1004,6 +994,10 @@ impl<'a> Parser<'a> { return None; } } else { + // Suggest: + // fn foo() -> Foo { Path { + // field: value, + // } } self.dcx().emit_err(StructLiteralBodyWithoutPath { span: expr.span, sugg: StructLiteralBodyWithoutPathSugg { @@ -1011,7 +1005,11 @@ impl<'a> Parser<'a> { after: expr.span.shrink_to_hi(), }, }); - Ok(tail) + Ok(self.mk_block( + thin_vec![self.mk_stmt_err(expr.span, guar)], + s, + lo.to(self.prev_token.span), + )) } } (Err(err), Ok(tail)) => { @@ -1025,10 +1023,7 @@ impl<'a> Parser<'a> { self.consume_block(exp!(OpenBrace), exp!(CloseBrace), ConsumeClosingDelim::Yes); Err(err) } - (Ok(_), Ok(mut tail)) => { - tail.could_be_bare_literal = true; - Ok(tail) - } + (Ok(_), Ok(tail)) => Ok(tail), }); } None diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 0fe247078d51..368366c60d65 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -1043,14 +1043,7 @@ impl<'a> Parser<'a> { rules: BlockCheckMode, span: Span, ) -> P { - P(Block { - stmts, - id: DUMMY_NODE_ID, - rules, - span, - tokens: None, - could_be_bare_literal: false, - }) + P(Block { stmts, id: DUMMY_NODE_ID, rules, span, tokens: None }) } pub(super) fn mk_stmt(&self, span: Span, kind: StmtKind) -> Stmt { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 6056a69ee71f..b4d9d5a8a0ec 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -674,11 +674,6 @@ struct DiagMetadata<'ast> { /// they are used (in a `break` or `continue` statement) unused_labels: FxHashMap, - /// Only used for better errors on `let x = { foo: bar };`. - /// In the case of a parse error with `let x = { foo: bar, };`, this isn't needed, it's only - /// needed for cases where this parses as a correct type ascription. - current_block_could_be_bare_struct_literal: Option, - /// Only used for better errors on `let : ;`. current_let_binding: Option<(Span, Option, Option)>, @@ -4650,13 +4645,6 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.ribs[ValueNS].push(Rib::new(RibKind::Normal)); } - let prev = self.diag_metadata.current_block_could_be_bare_struct_literal.take(); - if let (true, [Stmt { kind: StmtKind::Expr(expr), .. }]) = - (block.could_be_bare_literal, &block.stmts[..]) - && let ExprKind::Type(..) = expr.kind - { - self.diag_metadata.current_block_could_be_bare_struct_literal = Some(block.span); - } // Descend into the block. for stmt in &block.stmts { if let StmtKind::Item(ref item) = stmt.kind @@ -4670,7 +4658,6 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.visit_stmt(stmt); } - self.diag_metadata.current_block_could_be_bare_struct_literal = prev; // Move back up. self.parent_scope.module = orig_module; diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 3d666055a94f..dff9b4786985 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -450,7 +450,6 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { err.span_suggestion_verbose(sugg.0, sugg.1, &sugg.2, Applicability::MaybeIncorrect); } - self.suggest_bare_struct_literal(&mut err); self.suggest_changing_type_to_const_param(&mut err, res, source, span); self.explain_functions_in_pattern(&mut err, res, source); @@ -1281,19 +1280,6 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } } - fn suggest_bare_struct_literal(&mut self, err: &mut Diag<'_>) { - if let Some(span) = self.diag_metadata.current_block_could_be_bare_struct_literal { - err.multipart_suggestion( - "you might have meant to write a `struct` literal", - vec![ - (span.shrink_to_lo(), "{ SomeStruct ".to_string()), - (span.shrink_to_hi(), "}".to_string()), - ], - Applicability::HasPlaceholders, - ); - } - } - fn explain_functions_in_pattern( &mut self, err: &mut Diag<'_>, diff --git a/src/tools/rustfmt/src/closures.rs b/src/tools/rustfmt/src/closures.rs index a37b47e3bc95..61e148cdf188 100644 --- a/src/tools/rustfmt/src/closures.rs +++ b/src/tools/rustfmt/src/closures.rs @@ -176,7 +176,6 @@ fn rewrite_closure_with_block( .first() .map(|attr| attr.span.to(body.span)) .unwrap_or(body.span), - could_be_bare_literal: false, }; let block = crate::expr::rewrite_block_with_visitor( context, diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs index 664c90b991a9..e239ff47c043 100644 --- a/src/tools/rustfmt/src/macros.rs +++ b/src/tools/rustfmt/src/macros.rs @@ -423,7 +423,6 @@ fn rewrite_empty_macro_def_body( rules: ast::BlockCheckMode::Default, span, tokens: None, - could_be_bare_literal: false, }; block.rewrite_result(context, shape) } diff --git a/tests/ui-fulldeps/pprust-expr-roundtrip.rs b/tests/ui-fulldeps/pprust-expr-roundtrip.rs index 37e328a315f1..4a866560e798 100644 --- a/tests/ui-fulldeps/pprust-expr-roundtrip.rs +++ b/tests/ui-fulldeps/pprust-expr-roundtrip.rs @@ -114,7 +114,6 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P)) { rules: BlockCheckMode::Default, span: DUMMY_SP, tokens: None, - could_be_bare_literal: false, }); iter_exprs(depth - 1, &mut |e| g(ExprKind::If(e, block.clone(), None))); } From 1aed58ceb6fc2bdbd4d323fb18fd6d7c9ee21630 Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Sat, 22 Mar 2025 22:29:23 +0100 Subject: [PATCH 492/745] Emit `unused_attributes` for `#[inline]` on exported functions I saw someone post a code sample that contained these two attributes, which immediately made me suspicious. My suspicions were confirmed when I did a small test and checked the compiler source code to confirm that in these cases, `#[inline]` is indeed ignored (because you can't exactly `LocalCopy`an unmangled symbol since that would lead to duplicate symbols, and doing a mix of an unmangled `GloballyShared` and mangled `LocalCopy` instantiation is too complicated for our current instatiation mode logic, which I don't want to change right now). So instead, emit the usual unused attribute lint with a message saying that the attribute is ignored in this position. I think this is not 100% true, since I expect LLVM `inlinehint` to still be applied to such a function, but that's not why people use this attribute, they use it for the `LocalCopy` instantiation mode, where it doesn't work. --- .../src/middle/codegen_fn_attrs.rs | 2 ++ compiler/rustc_middle/src/mir/mono.rs | 1 + compiler/rustc_passes/messages.ftl | 4 +++ compiler/rustc_passes/src/check_attr.rs | 17 ++++++++++ compiler/rustc_passes/src/errors.rs | 5 +++ tests/ui/lint/inline-exported.rs | 30 ++++++++++++++++++ tests/ui/lint/inline-exported.stderr | 31 +++++++++++++++++++ .../target-feature/invalid-attribute.stderr | 12 +++---- 8 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 tests/ui/lint/inline-exported.rs create mode 100644 tests/ui/lint/inline-exported.stderr diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index 311bc60c3cd3..a33b1fe283b8 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -172,6 +172,8 @@ impl CodegenFnAttrs { /// * `#[no_mangle]` is present /// * `#[export_name(...)]` is present /// * `#[linkage]` is present + /// + /// Keep this in sync with the logic for the unused_attributes for `#[inline]` lint. pub fn contains_extern_indicator(&self) -> bool { self.flags.contains(CodegenFnAttrFlags::NO_MANGLE) || self.export_name.is_some() diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 58d5c94d0332..2aa31761178f 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -117,6 +117,7 @@ impl<'tcx> MonoItem<'tcx> { // If the function is #[naked] or contains any other attribute that requires exactly-once // instantiation: + // We emit an unused_attributes lint for this case, which should be kept in sync if possible. let codegen_fn_attrs = tcx.codegen_fn_attrs(instance.def_id()); if codegen_fn_attrs.contains_extern_indicator() || codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index b65430c34802..22631cc96d28 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -383,6 +383,10 @@ passes_inline_ignored_constants = .warn = {-passes_previously_accepted} .note = {-passes_see_issue(issue: "65833")} +passes_inline_ignored_for_exported = + `#[inline]` is ignored on externally exported functions + .help = externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]` + passes_inline_ignored_function_prototype = `#[inline]` is ignored on function prototypes diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 5ada289cc209..5a76f7c586d4 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -445,6 +445,23 @@ impl<'tcx> CheckAttrVisitor<'tcx> { }); } } + + // `#[inline]` is ignored if the symbol must be codegened upstream because it's exported. + if let Some(did) = hir_id.as_owner() + && self.tcx.def_kind(did).has_codegen_attrs() + && !matches!(attr.meta_item_list().as_deref(), Some([item]) if item.has_name(sym::never)) + { + let attrs = self.tcx.codegen_fn_attrs(did); + // Not checking naked as `#[inline]` is forbidden for naked functions anyways. + if attrs.contains_extern_indicator() { + self.tcx.emit_node_span_lint( + UNUSED_ATTRIBUTES, + hir_id, + attr.span(), + errors::InlineIgnoredForExported {}, + ); + } + } } /// Checks that `#[coverage(..)]` is applied to a function/closure/method, diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 9bb9b2353dc8..b282828a8ae9 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1435,6 +1435,11 @@ pub(crate) struct OnlyHasEffectOn { pub target_name: String, } +#[derive(LintDiagnostic)] +#[diag(passes_inline_ignored_for_exported)] +#[help] +pub(crate) struct InlineIgnoredForExported {} + #[derive(Diagnostic)] #[diag(passes_object_lifetime_err)] pub(crate) struct ObjectLifetimeErr { diff --git a/tests/ui/lint/inline-exported.rs b/tests/ui/lint/inline-exported.rs new file mode 100644 index 000000000000..69e322ef513a --- /dev/null +++ b/tests/ui/lint/inline-exported.rs @@ -0,0 +1,30 @@ +//! Ensure the unused_attributes lint fires for externally exported functions with `#[inline]`, +//! because `#[inline]` is ignored for such functions. + +#![crate_type = "lib"] + +#![feature(linkage)] +#![feature(naked_functions)] +#![deny(unused_attributes)] + +#[inline] +//~^ ERROR: `#[inline]` is ignored on externally exported functions +#[no_mangle] +fn no_mangle() {} + +#[inline] +//~^ ERROR: `#[inline]` is ignored on externally exported functions +#[export_name = "export_name"] +fn export_name() {} + +#[inline] +//~^ ERROR: `#[inline]` is ignored on externally exported functions +#[linkage = "external"] +fn external_linkage() {} + +#[inline] +fn normal() {} + +#[inline] +#[linkage = "internal"] // not exported +fn internal_linkage() {} diff --git a/tests/ui/lint/inline-exported.stderr b/tests/ui/lint/inline-exported.stderr new file mode 100644 index 000000000000..dcf63cc4090e --- /dev/null +++ b/tests/ui/lint/inline-exported.stderr @@ -0,0 +1,31 @@ +error: `#[inline]` is ignored on externally exported functions + --> $DIR/inline-exported.rs:10:1 + | +LL | #[inline] + | ^^^^^^^^^ + | + = help: externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]` +note: the lint level is defined here + --> $DIR/inline-exported.rs:8:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: `#[inline]` is ignored on externally exported functions + --> $DIR/inline-exported.rs:15:1 + | +LL | #[inline] + | ^^^^^^^^^ + | + = help: externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]` + +error: `#[inline]` is ignored on externally exported functions + --> $DIR/inline-exported.rs:20:1 + | +LL | #[inline] + | ^^^^^^^^^ + | + = help: externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/target-feature/invalid-attribute.stderr b/tests/ui/target-feature/invalid-attribute.stderr index dc8a53041640..05ae49d6b0dd 100644 --- a/tests/ui/target-feature/invalid-attribute.stderr +++ b/tests/ui/target-feature/invalid-attribute.stderr @@ -98,6 +98,12 @@ LL | LL | trait Baz {} | ------------ not a function definition +error: cannot use `#[inline(always)]` with `#[target_feature]` + --> $DIR/invalid-attribute.rs:69:1 + | +LL | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ + error: attribute should be applied to a function definition --> $DIR/invalid-attribute.rs:74:1 | @@ -163,12 +169,6 @@ error: malformed `target_feature` attribute input LL | #[target_feature(disable = "baz")] | ^^^^^^^^^^^^^^^ help: must be of the form: `enable = ".."` -error: cannot use `#[inline(always)]` with `#[target_feature]` - --> $DIR/invalid-attribute.rs:69:1 - | -LL | #[inline(always)] - | ^^^^^^^^^^^^^^^^^ - error[E0046]: not all trait items implemented, missing: `foo` --> $DIR/invalid-attribute.rs:81:1 | From ba4190cf7e919d7cc31c366906ded41874ef0439 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 17 Mar 2025 01:34:46 +0300 Subject: [PATCH 493/745] resolve: Avoid some unstable iteration 2 --- compiler/rustc_resolve/src/build_reduced_graph.rs | 1 - compiler/rustc_resolve/src/diagnostics.rs | 1 - compiler/rustc_resolve/src/ident.rs | 1 - compiler/rustc_resolve/src/imports.rs | 8 ++++---- compiler/rustc_resolve/src/late.rs | 5 ++--- compiler/rustc_resolve/src/late/diagnostics.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 2 +- compiler/rustc_resolve/src/macros.rs | 3 +-- 8 files changed, 9 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 763e9207a126..42fe01b1c84c 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -1115,7 +1115,6 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } }); } else { - #[allow(rustc::potential_query_instability)] // FIXME for ident in single_imports.iter().cloned() { let result = self.r.maybe_resolve_ident_in_module( ModuleOrUniformRoot::Module(module), diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 5361af98f3c7..7decc2a09721 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1468,7 +1468,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return; } - #[allow(rustc::potential_query_instability)] // FIXME let unused_macro = self.unused_macros.iter().find_map(|(def_id, (_, unused_ident))| { if unused_ident.name == ident.name { Some((def_id, unused_ident)) } else { None } }); diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 27d63198836a..5f0a2a597e9b 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -946,7 +946,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Check if one of single imports can still define the name, // if it can then our result is not determined and can be invalidated. - #[allow(rustc::potential_query_instability)] // FIXME for single_import in &resolution.single_imports { if ignore_import == Some(*single_import) { // This branch handles a cycle in single imports. diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 89b9a0743518..454460e10dc9 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -4,7 +4,7 @@ use std::cell::Cell; use std::mem; use rustc_ast::NodeId; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_errors::codes::*; use rustc_errors::{Applicability, MultiSpan, pluralize, struct_span_code_err}; @@ -233,7 +233,7 @@ impl<'ra> ImportData<'ra> { pub(crate) struct NameResolution<'ra> { /// Single imports that may define the name in the namespace. /// Imports are arena-allocated, so it's ok to use pointers as keys. - pub single_imports: FxHashSet>, + pub single_imports: FxIndexSet>, /// The least shadowable known binding for this name, or None if there are no known bindings. pub binding: Option>, pub shadowed_glob: Option>, @@ -494,7 +494,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let key = BindingKey::new(target, ns); let _ = this.try_define(import.parent_scope.module, key, dummy_binding, false); this.update_resolution(import.parent_scope.module, key, false, |_, resolution| { - resolution.single_imports.remove(&import); + resolution.single_imports.swap_remove(&import); }) }); self.record_use(target, dummy_binding, Used::Other); @@ -862,7 +862,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } let key = BindingKey::new(target, ns); this.update_resolution(parent, key, false, |_, resolution| { - resolution.single_imports.remove(&import); + resolution.single_imports.swap_remove(&import); }); } } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 6056a69ee71f..dd663ce057e2 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -672,7 +672,7 @@ struct DiagMetadata<'ast> { /// A list of labels as of yet unused. Labels will be removed from this map when /// they are used (in a `break` or `continue` statement) - unused_labels: FxHashMap, + unused_labels: FxIndexMap, /// Only used for better errors on `let x = { foo: bar };`. /// In the case of a parse error with `let x = { foo: bar, };`, this isn't needed, it's only @@ -4779,7 +4779,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { Ok((node_id, _)) => { // Since this res is a label, it is never read. self.r.label_res_map.insert(expr.id, node_id); - self.diag_metadata.unused_labels.remove(&node_id); + self.diag_metadata.unused_labels.swap_remove(&node_id); } Err(error) => { self.report_error(label.ident.span, error); @@ -5201,7 +5201,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let mut late_resolution_visitor = LateResolutionVisitor::new(self); late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID)); visit::walk_crate(&mut late_resolution_visitor, krate); - #[allow(rustc::potential_query_instability)] // FIXME for (id, span) in late_resolution_visitor.diag_metadata.unused_labels.iter() { self.lint_buffer.buffer_lint( lint::builtin::UNUSED_LABELS, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 3d666055a94f..69a7c81956aa 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1036,7 +1036,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { Applicability::MaybeIncorrect, ); // Do not lint against unused label when we suggest them. - self.diag_metadata.unused_labels.remove(node_id); + self.diag_metadata.unused_labels.swap_remove(node_id); } } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index ff31af0025b5..78153fd41740 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1137,7 +1137,7 @@ pub struct Resolver<'ra, 'tcx> { non_macro_attr: MacroData, local_macro_def_scopes: FxHashMap>, ast_transform_scopes: FxHashMap>, - unused_macros: FxHashMap, + unused_macros: FxIndexMap, /// A map from the macro to all its potentially unused arms. unused_macro_rules: FxIndexMap>, proc_macro_stubs: FxHashSet, diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index c4304a7a6df6..d577d7e80792 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -323,7 +323,6 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { } fn check_unused_macros(&mut self) { - #[allow(rustc::potential_query_instability)] // FIXME for (_, &(node_id, ident)) in self.unused_macros.iter() { self.lint_buffer.buffer_lint( UNUSED_MACROS, @@ -576,7 +575,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { match res { Res::Def(DefKind::Macro(_), def_id) => { if let Some(def_id) = def_id.as_local() { - self.unused_macros.remove(&def_id); + self.unused_macros.swap_remove(&def_id); if self.proc_macro_stubs.contains(&def_id) { self.dcx().emit_err(errors::ProcMacroSameCrate { span: path.span, From 7f2cb4c206510943fe87cae19e2f4e1b43f605e9 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Sat, 22 Mar 2025 18:22:45 +0800 Subject: [PATCH 494/745] Slightly reword triagebot ping message for `relnotes-interest-group` Now that there's also a meta relnotes tracking issue. --- triagebot.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index 53cdd8b585b4..89986dffb4ab 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -174,8 +174,8 @@ label = "O-emscripten" [ping.relnotes-interest-group] message = """\ -Hi relnotes-interest-group, this PR adds release notes. Could you review this PR -if you have time? Thanks <3 +Hi relnotes-interest-group, this issue/PR could use some help in reviewing / +adjusting release notes. Could you take a look if available? Thanks <3 """ [prioritize] From c123adf860b008f703b325d013e7c7c0cc707d56 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 15:57:07 -0500 Subject: [PATCH 495/745] rustdoc js: add nonundef and use it to remove a ts-expect-error --- src/librustdoc/html/static/js/rustdoc.d.ts | 4 +++- src/librustdoc/html/static/js/search.js | 7 +++---- src/librustdoc/html/static/js/storage.js | 22 ++++++++++++++++++++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index e94c6beabea3..e2ebb1391837 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -6,8 +6,10 @@ declare global { /** Map from crate name to directory structure, for source view */ declare var srcIndex: Map; - /** Defined and documented in `main.js` */ + /** Defined and documented in `storage.js` */ declare function nonnull(x: T|null, msg: string|undefined); + /** Defined and documented in `storage.js` */ + declare function nonundef(x: T|undefined, msg: string|undefined); interface Window { /** Make the current theme easy to find */ currentTheme: HTMLLinkElement|null; diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index c275127997ab..decb4807e884 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1,5 +1,5 @@ // ignore-tidy-filelength -/* global addClass, getNakedUrl, getSettingValue, getVar */ +/* global addClass, getNakedUrl, getSettingValue, getVar, nonnull, nonundef */ /* global onEachLazy, removeClass, searchState, browserSupportsHistoryApi, exports */ "use strict"; @@ -338,9 +338,8 @@ function getFilteredNextElem(query, parserState, elems, isInGenerics) { // The type filter doesn't count as an element since it's a modifier. const typeFilterElem = elems.pop(); checkExtraTypeFilterCharacters(start, parserState); - // typeFilterElem is not null. If it was, the elems.length check would have fired. - // @ts-expect-error - parserState.typeFilter = typeFilterElem.normalizedPathLast; + // typeFilterElem is not undefined. If it was, the elems.length check would have fired. + parserState.typeFilter = nonundef(typeFilterElem).normalizedPathLast; parserState.pos += 1; parserState.totalElems -= 1; query.literalSearch = false; diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index 748d2ef33c32..761137268947 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -43,6 +43,28 @@ function nonnull(x, msg) { } } +/** + * Assert that the passed value is not undefined, then return it. + * + * Takes an optional error message argument. + * + * Must be defined in this file, as it is loaded before all others. + * + * @template T + * @param {T|undefined} x + * @param {string=} msg + * @returns T + */ +// used in other files, not yet used in this one. +// eslint-disable-next-line no-unused-vars +function nonundef(x, msg) { + if (x === undefined) { + throw (msg || "unexpected null value!"); + } else { + return x; + } +} + /** * Get a configuration value. If it's not set, get the default. * From 43653c1835d59de69c6a5977b52df4708e6fddca Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 23 Mar 2025 22:13:52 +0300 Subject: [PATCH 496/745] linker: Fix staticlib naming for UEFI It uses `libname.a` instead of the standard MSVC naming `name.lib`. Naming for import libraries isn't touched. --- compiler/rustc_codegen_ssa/src/back/link.rs | 7 ++++++- compiler/rustc_codegen_ssa/src/back/linker.rs | 10 +++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 74597f6263d4..99b4591051af 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1494,7 +1494,12 @@ fn print_native_static_libs( | NativeLibKind::Unspecified => { let verbatim = lib.verbatim; if sess.target.is_like_msvc { - Some(format!("{}{}", name, if verbatim { "" } else { ".lib" })) + let (prefix, suffix) = if verbatim { + ("", "") + } else { + (&*sess.target.staticlib_prefix, &*sess.target.staticlib_suffix) + }; + Some(format!("{prefix}{name}{suffix}")) } else if sess.target.linker_flavor.is_gnu() { Some(format!("-l{}{}", if verbatim { ":" } else { "" }, name)) } else { diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 3f5e0c1bce9c..7f24d79b83b2 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -958,9 +958,13 @@ impl<'a> Linker for MsvcLinker<'a> { if let Some(path) = try_find_native_static_library(self.sess, name, verbatim) { self.link_staticlib_by_path(&path, whole_archive); } else { - let prefix = if whole_archive { "/WHOLEARCHIVE:" } else { "" }; - let suffix = if verbatim { "" } else { ".lib" }; - self.link_arg(format!("{prefix}{name}{suffix}")); + let opts = if whole_archive { "/WHOLEARCHIVE:" } else { "" }; + let (prefix, suffix) = if verbatim { + ("", "") + } else { + (&*self.sess.target.staticlib_prefix, &*self.sess.target.staticlib_suffix) + }; + self.link_arg(format!("{opts}{prefix}{name}{suffix}")); } } From 27e95f95e6dfcc1effa1f106c90fe53ab2236b76 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 23 Mar 2025 22:18:21 +0300 Subject: [PATCH 497/745] linker: Avoid calling `linker_and_flavor` twice --- compiler/rustc_codegen_ssa/src/back/link.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 99b4591051af..360f6d82dbc3 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -670,7 +670,7 @@ fn link_natively( ) { info!("preparing {:?} to {:?}", crate_type, out_filename); let (linker_path, flavor) = linker_and_flavor(sess); - let self_contained_components = self_contained_components(sess, crate_type); + let self_contained_components = self_contained_components(sess, crate_type, &linker_path); // On AIX, we ship all libraries as .a big_af archive // the expected format is lib.a(libname.so) for the actual @@ -1788,8 +1788,7 @@ fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind { } // Returns true if linker is located within sysroot -fn detect_self_contained_mingw(sess: &Session) -> bool { - let (linker, _) = linker_and_flavor(sess); +fn detect_self_contained_mingw(sess: &Session, linker: &Path) -> bool { // Assume `-C linker=rust-lld` as self-contained mode if linker == Path::new("rust-lld") { return true; @@ -1797,7 +1796,7 @@ fn detect_self_contained_mingw(sess: &Session) -> bool { let linker_with_extension = if cfg!(windows) && linker.extension().is_none() { linker.with_extension("exe") } else { - linker + linker.to_path_buf() }; for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) { let full_path = dir.join(&linker_with_extension); @@ -1812,7 +1811,11 @@ fn detect_self_contained_mingw(sess: &Session) -> bool { /// Various toolchain components used during linking are used from rustc distribution /// instead of being found somewhere on the host system. /// We only provide such support for a very limited number of targets. -fn self_contained_components(sess: &Session, crate_type: CrateType) -> LinkSelfContainedComponents { +fn self_contained_components( + sess: &Session, + crate_type: CrateType, + linker: &Path, +) -> LinkSelfContainedComponents { // Turn the backwards compatible bool values for `self_contained` into fully inferred // `LinkSelfContainedComponents`. let self_contained = @@ -1841,7 +1844,7 @@ fn self_contained_components(sess: &Session, crate_type: CrateType) -> LinkSelfC LinkSelfContainedDefault::InferredForMingw => { sess.host == sess.target && sess.target.vendor != "uwp" - && detect_self_contained_mingw(sess) + && detect_self_contained_mingw(sess, linker) } } }; From 7c55782e0c1d01dfd7ceab3b4e682c12e24308d8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 25 Mar 2025 00:00:10 +0300 Subject: [PATCH 498/745] rustc_session: Add a helper function for obtaining staticlib prefix and suffix --- compiler/rustc_codegen_ssa/src/back/link.rs | 6 +----- compiler/rustc_codegen_ssa/src/back/linker.rs | 11 ++++------ compiler/rustc_metadata/src/native_libs.rs | 21 +++++++++---------- compiler/rustc_session/src/output.rs | 2 +- compiler/rustc_session/src/session.rs | 8 +++++++ 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 360f6d82dbc3..a564e0e391fe 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1494,11 +1494,7 @@ fn print_native_static_libs( | NativeLibKind::Unspecified => { let verbatim = lib.verbatim; if sess.target.is_like_msvc { - let (prefix, suffix) = if verbatim { - ("", "") - } else { - (&*sess.target.staticlib_prefix, &*sess.target.staticlib_suffix) - }; + let (prefix, suffix) = sess.staticlib_components(verbatim); Some(format!("{prefix}{name}{suffix}")) } else if sess.target.linker_flavor.is_gnu() { Some(format!("-l{}{}", if verbatim { ":" } else { "" }, name)) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 7f24d79b83b2..bcf18cf57be2 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -450,9 +450,10 @@ impl<'a> GccLinker<'a> { // The output filename already contains `dll_suffix` so // the resulting import library will have a name in the // form of libfoo.dll.a - let mut implib_name = OsString::from(&*self.sess.target.staticlib_prefix); + let (prefix, suffix) = self.sess.staticlib_components(false); + let mut implib_name = OsString::from(prefix); implib_name.push(name); - implib_name.push(&*self.sess.target.staticlib_suffix); + implib_name.push(suffix); let mut out_implib = OsString::from("--out-implib="); out_implib.push(out_filename.with_file_name(implib_name)); self.link_arg(out_implib); @@ -959,11 +960,7 @@ impl<'a> Linker for MsvcLinker<'a> { self.link_staticlib_by_path(&path, whole_archive); } else { let opts = if whole_archive { "/WHOLEARCHIVE:" } else { "" }; - let (prefix, suffix) = if verbatim { - ("", "") - } else { - (&*self.sess.target.staticlib_prefix, &*self.sess.target.staticlib_suffix) - }; + let (prefix, suffix) = self.sess.staticlib_components(verbatim); self.link_arg(format!("{opts}{prefix}{name}{suffix}")); } } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 1671b7e06b0a..f63ae8079dcd 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -95,14 +95,14 @@ pub fn try_find_native_static_library( name: &str, verbatim: bool, ) -> Option { + let default = sess.staticlib_components(verbatim); let formats = if verbatim { - vec![("".into(), "".into())] + vec![default] } else { - let os = (sess.target.staticlib_prefix.clone(), sess.target.staticlib_suffix.clone()); // On Windows, static libraries sometimes show up as libfoo.a and other // times show up as foo.lib - let unix = ("lib".into(), ".a".into()); - if os == unix { vec![os] } else { vec![os, unix] } + let unix = ("lib", ".a"); + if default == unix { vec![default] } else { vec![default, unix] } }; walk_native_lib_search_dirs(sess, None, |dir, is_framework| { @@ -124,18 +124,17 @@ pub fn try_find_native_dynamic_library( name: &str, verbatim: bool, ) -> Option { + let default = sess.staticlib_components(verbatim); let formats = if verbatim { - vec![("".into(), "".into())] + vec![default] } else { // While the official naming convention for MSVC import libraries - // is foo.lib... - let os = (sess.target.staticlib_prefix.clone(), sess.target.staticlib_suffix.clone()); - // ... Meson follows the libfoo.dll.a convention to + // is foo.lib, Meson follows the libfoo.dll.a convention to // disambiguate .a for static libraries - let meson = ("lib".into(), ".dll.a".into()); + let meson = ("lib", ".dll.a"); // and MinGW uses .a altogether - let mingw = ("lib".into(), ".a".into()); - vec![os, meson, mingw] + let mingw = ("lib", ".a"); + vec![default, meson, mingw] }; walk_native_lib_search_dirs(sess, None, |dir, is_framework| { diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs index b37a80274c0c..a24919e434cc 100644 --- a/compiler/rustc_session/src/output.rs +++ b/compiler/rustc_session/src/output.rs @@ -103,7 +103,7 @@ pub fn filename_for_input( OutFileName::Real(outputs.out_directory.join(&format!("{prefix}{libname}{suffix}"))) } CrateType::Staticlib => { - let (prefix, suffix) = (&sess.target.staticlib_prefix, &sess.target.staticlib_suffix); + let (prefix, suffix) = sess.staticlib_components(false); OutFileName::Real(outputs.out_directory.join(&format!("{prefix}{libname}{suffix}"))) } CrateType::Executable => { diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 1c9adea281dc..a87b1961a995 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -586,6 +586,14 @@ impl Session { .or(self.target.options.default_visibility) .unwrap_or(SymbolVisibility::Interposable) } + + pub fn staticlib_components(&self, verbatim: bool) -> (&str, &str) { + if verbatim { + ("", "") + } else { + (&*self.target.staticlib_prefix, &*self.target.staticlib_suffix) + } + } } // JUSTIFICATION: defn of the suggested wrapper fns From ccd95ac7fde43d6a0380895086efca3a75e1ac35 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 16:19:05 -0500 Subject: [PATCH 499/745] search.js: improve typechecking by avoiding Map.has --- src/librustdoc/html/static/js/search.js | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index decb4807e884..a8c6193a4c13 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1310,10 +1310,9 @@ class NameTrie { let sste; if (substart >= 2) { const tail = name.substring(substart - 2, substart + 1); - if (tailTable.has(tail)) { - // it's not undefined - // @ts-expect-error - sste = tailTable.get(tail); + const entry = tailTable.get(tail); + if (entry !== undefined) { + sste = entry; } else { sste = []; tailTable.set(tail, sste); @@ -1337,10 +1336,9 @@ class NameTrie { new Lev1TParametricDescription(name.length); this.searchLev(name, 0, levParams, results); const tail = name.substring(0, 3); - if (tailTable.has(tail)) { - // it's not undefined - // @ts-expect-error - for (const entry of tailTable.get(tail)) { + const list = tailTable.get(tail); + if (list !== undefined) { + for (const entry of list) { entry.searchSubstringPrefix(name, 3, results); } } @@ -1599,10 +1597,8 @@ class DocSearch { return null; } - if (this.typeNameIdMap.has(name)) { - /** @type {{id: number, assocOnly: boolean}} */ - // @ts-expect-error - const obj = this.typeNameIdMap.get(name); + const obj = this.typeNameIdMap.get(name); + if (obj !== undefined) { obj.assocOnly = !!(isAssocType && obj.assocOnly); return obj.id; } else { @@ -2145,7 +2141,6 @@ class DocSearch { const name = elem[1]; let path = null; if (elem.length > 2 && elem[2] !== null) { - // @ts-expect-error path = itemPaths.has(elem[2]) ? itemPaths.get(elem[2]) : lastPath; lastPath = path; } From e9a5470aabcf9dbfd8c463b3156332d75a3881ea Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 16:56:55 -0500 Subject: [PATCH 500/745] search.js: refactor handling of rawPaths in buildIndex --- src/librustdoc/html/static/js/search.js | 42 +++++++++++++------------ 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index a8c6193a4c13..bac174869f57 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2077,7 +2077,8 @@ class DocSearch { descIndex += 1; } - // a String of one character item type codes + // see `RawSearchIndexCrate` in `rustdoc.d.ts` for a more + // up to date description of these fields const itemTypes = crateCorpus.t; // an array of (String) item names const itemNames = crateCorpus.n; @@ -2094,8 +2095,6 @@ class DocSearch { const itemParentIdxDecoder = new VlqHexDecoder(crateCorpus.i, noop => noop); // a map Number, string for impl disambiguators const implDisambiguator = new Map(crateCorpus.b); - // an array of [(Number) item type, - // (String) name] const rawPaths = crateCorpus.p; const aliases = crateCorpus.a; // an array of [(Number) item index, @@ -2134,29 +2133,32 @@ class DocSearch { // convert `rawPaths` entries into object form // generate normalizedPaths for function search mode let len = rawPaths.length; - let lastPath = itemPaths.get(0); + const lastPathU = itemPaths.get(0); + let lastPath = lastPathU === undefined ? null : lastPathU; for (let i = 0; i < len; ++i) { const elem = rawPaths[i]; const ty = elem[0]; const name = elem[1]; - let path = null; - if (elem.length > 2 && elem[2] !== null) { - path = itemPaths.has(elem[2]) ? itemPaths.get(elem[2]) : lastPath; - lastPath = path; - } - let exactPath = elem.length > 3 && elem[3] !== null ? - // @ts-expect-error - itemPaths.get(elem[3]) : - path; + /** + * @param {2|3} idx + * @param {string|null} if_null + * @param {string|null} if_not_found + * @returns {string|null} + */ + const elemPath = (idx, if_null, if_not_found) => { + if (elem.length > idx && elem[idx] !== undefined) { + const p = itemPaths.get(elem[idx]); + if (p !== undefined) { + return p; + } + return if_not_found; + } + return if_null; + }; + const path = elemPath(2, lastPath, null); + const exactPath = elemPath(3, path, path); const unboxFlag = elem.length > 4 && !!elem[4]; - if (path === undefined) { - path = null; - } - if (exactPath === undefined) { - exactPath = null; - } - lowercasePaths.push({ ty, name: name.toLowerCase(), path, exactPath, unboxFlag }); paths[i] = { ty, name, path, exactPath, unboxFlag }; } From 49bf6ca79eb7379e367578cba910d1e1cbacc7d1 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 17:05:35 -0500 Subject: [PATCH 501/745] search.js: add undef2null and eliminate more @ts-expect-error --- src/librustdoc/html/static/js/search.js | 31 +++++++++++++++++-------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index bac174869f57..1817d91af79a 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -33,6 +33,20 @@ function onEachBtwn(arr, func, funcBtwn) { } } +/** + * Convert any `undefined` to `null`. + * + * @template T + * @param {T|undefined} x + * @returns {T|null} + */ +function undef2null(x) { + if (x !== undefined) { + return x; + } + return null; +} + // ==================== Core search logic begin ==================== // This mapping table should match the discriminants of // `rustdoc::formats::item_type::ItemType` type in Rust. @@ -2133,8 +2147,7 @@ class DocSearch { // convert `rawPaths` entries into object form // generate normalizedPaths for function search mode let len = rawPaths.length; - const lastPathU = itemPaths.get(0); - let lastPath = lastPathU === undefined ? null : lastPathU; + let lastPath = undef2null(itemPaths.get(0)); for (let i = 0; i < len; ++i) { const elem = rawPaths[i]; const ty = elem[0]; @@ -2192,12 +2205,11 @@ class DocSearch { } const name = itemNames[i] === "" ? lastName : itemNames[i]; const word = itemNames[i] === "" ? lastWord : itemNames[i].toLowerCase(); - /** @type {string} */ - // @ts-expect-error - const path = itemPaths.has(i) ? itemPaths.get(i) : lastPath; - const paramNames = itemParamNames.has(i) ? - // @ts-expect-error - itemParamNames.get(i).split(",") : + const pathU = itemPaths.get(i); + const path = pathU !== undefined ? pathU : lastPath; + const paramNameString = itemParamNames.get(i); + const paramNames = paramNameString !== undefined ? + paramNameString.split(",") : lastParamNames; const type = itemFunctionDecoder.next(); if (type !== null) { @@ -2239,8 +2251,7 @@ class DocSearch { word, normalizedName, bitIndex, - implDisambiguator: implDisambiguator.has(i) ? - implDisambiguator.get(i) : null, + implDisambiguator: undef2null(implDisambiguator.get(i)), }; this.nameTrie.insert(normalizedName, id, this.tailTable); id += 1; From 1a8ddee65c2a36941d8fe3806beff727a3834d1e Mon Sep 17 00:00:00 2001 From: Jens Reidel Date: Mon, 24 Mar 2025 23:01:11 +0100 Subject: [PATCH 502/745] Add target maintainer information for powerpc64-unknown-linux-musl We intend to fix the outstanding issues on the target and eventually promote it to tier 2. We have the capacity to maintain this target in the future and already perform regular builds of rustc for this target. Currently, all host tools except miri build fine, but I have a patch for libffi-sys to make miri also compile fine for this target that is pending review [1]. While at it, add an option for the musl root for this target. [1]: https://github.com/tov/libffi-rs/pull/100 Signed-off-by: Jens Reidel --- src/bootstrap/configure.py | 5 ++ src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/platform-support.md | 2 +- .../powerpc64-unknown-linux-musl.md | 52 +++++++++++++++++++ 4 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/doc/rustc/src/platform-support/powerpc64-unknown-linux-musl.md diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index f6afe0967240..0d4d6e0ff54c 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -249,6 +249,11 @@ v( "target.mips64el-unknown-linux-muslabi64.musl-root", "mips64el-unknown-linux-muslabi64 install directory", ) +v( + "musl-root-powerpc64", + "target.powerpc64-unknown-linux-musl.musl-root", + "powerpc64-unknown-linux-musl install directory", +) v( "musl-root-powerpc64le", "target.powerpc64le-unknown-linux-musl.musl-root", diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 542ee9fffce3..fee61933f5cf 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -72,6 +72,7 @@ - [powerpc-unknown-linux-gnuspe](platform-support/powerpc-unknown-linux-gnuspe.md) - [powerpc-unknown-linux-muslspe](platform-support/powerpc-unknown-linux-muslspe.md) - [powerpc64-ibm-aix](platform-support/aix.md) + - [powerpc64-unknown-linux-musl](platform-support/powerpc64-unknown-linux-musl.md) - [powerpc64le-unknown-linux-gnu](platform-support/powerpc64le-unknown-linux-gnu.md) - [powerpc64le-unknown-linux-musl](platform-support/powerpc64le-unknown-linux-musl.md) - [riscv32e\*-unknown-none-elf](platform-support/riscv32e-unknown-none-elf.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index e8f8684740ac..3a8f84069ccc 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -356,7 +356,7 @@ target | std | host | notes [`powerpc-wrs-vxworks-spe`](platform-support/vxworks.md) | ✓ | | [`powerpc64-ibm-aix`](platform-support/aix.md) | ? | | 64-bit AIX (7.2 and newer) [`powerpc64-unknown-freebsd`](platform-support/freebsd.md) | ✓ | ✓ | PPC64 FreeBSD (ELFv2) -`powerpc64-unknown-linux-musl` | ? | | 64-bit PowerPC Linux with musl 1.2.3 +[`powerpc64-unknown-linux-musl`](platform-support/powerpc64-unknown-linux-musl.md) | ✓ | ✓ | PPC64 Linux (kernel 4.19, musl 1.2.3) [`powerpc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/powerpc64 [`powerpc64-wrs-vxworks`](platform-support/vxworks.md) | ✓ | | [`powerpc64le-unknown-freebsd`](platform-support/freebsd.md) | ✓ | ✓ | PPC64LE FreeBSD diff --git a/src/doc/rustc/src/platform-support/powerpc64-unknown-linux-musl.md b/src/doc/rustc/src/platform-support/powerpc64-unknown-linux-musl.md new file mode 100644 index 000000000000..0f78dcc089cc --- /dev/null +++ b/src/doc/rustc/src/platform-support/powerpc64-unknown-linux-musl.md @@ -0,0 +1,52 @@ +# powerpc64-unknown-linux-musl + +**Tier: 3** + +Target for 64-bit big endian PowerPC Linux programs using musl libc. +This target uses the ELF v2 ABI. + +## Target maintainers + +- [@Gelbpunkt](https://github.com/Gelbpunkt) +- [@famfo](https://github.com/famfo) +- [@neuschaefer](https://github.com/neuschaefer) + +## Requirements + +Building the target itself requires a 64-bit big endian PowerPC compiler that +is supported by `cc-rs`. + +## Building the target + +The target can be built by enabling it for a `rustc` build. + +```toml +[build] +target = ["powerpc64-unknown-linux-musl"] +``` + +Make sure your C compiler is included in `$PATH`, then add it to the +`bootstrap.toml`: + +```toml +[target.powerpc64-unknown-linux-musl] +cc = "powerpc64-linux-musl-gcc" +cxx = "powerpc64-linux-musl-g++" +ar = "powerpc64-linux-musl-ar" +linker = "powerpc64-linux-musl-gcc" +``` + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. To compile for +this target, you will first need to build Rust with the target enabled (see +"Building the target" above). + +## Cross-compilation + +This target can be cross-compiled from any host. + +## Testing + +This target can be tested as normal with `x.py` on a 64-bit big endian PowerPC +host or via QEMU emulation. From 1af16cd135dd4e62f8e68abfb0587b57eb16ce6e Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 17:31:39 -0500 Subject: [PATCH 503/745] search.js(query parser): rethrow error if it isn't a string array only errors that are string arrays are intended to be shown to the user, other errors are bugs, and will be shown in the console as usual. --- src/librustdoc/html/static/js/search.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 1817d91af79a..15bb3816f0b5 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2489,9 +2489,13 @@ class DocSearch { } } catch (err) { query = newParsedQuery(userQuery); - // is string list - // @ts-expect-error - query.error = err; + if (Array.isArray(err) && err.every((elem) => typeof elem == 'string')) { + query.error = err; + } else { + // rethrow the error if it isn't a string array + throw err; + } + return query; } if (!query.literalSearch) { From 8af647c04dbd300518f85619c9e9ce7a94d558c4 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 17:36:16 -0500 Subject: [PATCH 504/745] search.js: remove another Map.has() and @ts-expect-error --- src/librustdoc/html/static/js/search.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 15bb3816f0b5..2317f157bb93 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2583,9 +2583,9 @@ class DocSearch { if ((elem.id === null && parsedQuery.totalElems > 1 && elem.typeFilter === -1 && elem.generics.length === 0 && elem.bindings.size === 0) || elem.typeFilter === TY_GENERIC) { - if (genericSymbols.has(elem.normalizedPathLast)) { - // @ts-expect-error - elem.id = genericSymbols.get(elem.normalizedPathLast); + const id = genericSymbols.get(elem.normalizedPathLast); + if (id !== undefined) { + elem.id = id; } else { elem.id = -(genericSymbols.size + 1); genericSymbols.set(elem.normalizedPathLast, elem.id); From 714be45b974ae16a010503587e4628bc72fd107b Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 18:11:43 -0500 Subject: [PATCH 505/745] search.js: refactor transformResults --- src/librustdoc/html/static/js/rustdoc.d.ts | 12 +++++++-- src/librustdoc/html/static/js/search.js | 29 +++++++++++++--------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index e2ebb1391837..91a58fab86ef 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -257,12 +257,20 @@ declare namespace rustdoc { ty: number, type?: FunctionSearchType, paramNames?: string[], - displayType: Promise>>|null, - displayTypeMappedNames: Promise]>>|null, + displayTypeSignature: Promise | null, item: Row, dontValidate?: boolean, } + /** + * output of `formatDisplayTypeSignature` + */ + interface DisplayTypeSignature { + type: Array, + mappedNames: Map, + whereClause: Map>, + } + /** * A pair of [inputs, outputs], or 0 for null. This is stored in the search index. * The JavaScript deserializes this into FunctionSearchType. diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 2317f157bb93..bd09631d487b 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2777,15 +2777,28 @@ class DocSearch { for (const result of results) { if (result.id !== -1) { const res = buildHrefAndPath(this.searchIndex[result.id]); + // many of these properties don't strictly need to be + // copied over, but copying them over satisfies tsc, + // and hopefully plays nice with the shape optimization + // of the browser engine. + /** @type {rustdoc.ResultObject} */ const obj = Object.assign({ + parent: result.parent, + type: result.type, dist: result.dist, + path_dist: result.path_dist, + index: result.index, + desc: result.desc, + item: result.item, displayPath: pathSplitter(res[0]), + fullPath: "", + href: "", + displayTypeSignature: null, }, this.searchIndex[result.id]); // To be sure than it some items aren't considered as duplicate. - // @ts-expect-error - obj.fullPath = res[2] + "|" + obj.ty; - // @ts-expect-error + obj.fullPath = res[2] + "|" + obj.ty + if (duplicates.has(obj.fullPath)) { continue; } @@ -2798,18 +2811,15 @@ class DocSearch { if (duplicates.has(res[2] + "|" + TY_IMPORT)) { continue; } - // @ts-expect-error duplicates.add(obj.fullPath); duplicates.add(res[2]); if (typeInfo !== null) { - // @ts-expect-error obj.displayTypeSignature = // @ts-expect-error this.formatDisplayTypeSignature(obj, typeInfo); } - // @ts-expect-error obj.href = res[1]; out.push(obj); if (out.length >= MAX_RESULTS) { @@ -2817,7 +2827,6 @@ class DocSearch { } } } - // @ts-expect-error return out; }; @@ -2830,11 +2839,7 @@ class DocSearch { * * @param {rustdoc.ResultObject} obj * @param {"sig"|"elems"|"returned"|null} typeInfo - * @returns {Promise<{ - * "type": Array, - * "mappedNames": Map, - * "whereClause": Map>, - * }>} + * @returns {Promise} */ this.formatDisplayTypeSignature = async(obj, typeInfo) => { const objType = obj.type; From ca514c1a13b419606fe051ec897a25a07dc7aa26 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 18:20:51 -0500 Subject: [PATCH 506/745] search.js: fix signature of pushText --- src/librustdoc/html/static/js/search.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index bd09631d487b..f714f361d4b9 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2901,7 +2901,7 @@ class DocSearch { const whereClause = new Map(); const fnParamNames = obj.paramNames || []; - // @ts-expect-error + /** @type {string[]} */ const queryParamNames = []; /** * Recursively writes a map of IDs to query generic names, @@ -2934,7 +2934,7 @@ class DocSearch { * index 2 is not highlighted, etc. * * @param {{name?: string, highlighted?: boolean}} fnType - input - * @param {[string]} result + * @param {string[]} result */ const pushText = (fnType, result) => { // If !!(result.length % 2) == false, then pushing a new slot starts an even @@ -2946,7 +2946,6 @@ class DocSearch { // needs coerced to a boolean. if (!!(result.length % 2) === !!fnType.highlighted) { result.push(""); - // @ts-expect-error } else if (result.length === 0 && !!fnType.highlighted) { result.push(""); result.push(""); @@ -2960,7 +2959,7 @@ class DocSearch { * or a trait bound on Fn, FnMut, or FnOnce. * * @param {rustdoc.HighlightedFunctionType} fnType - input - * @param {[string]} result + * @param {string[]} result */ const writeHof = (fnType, result) => { const hofOutput = fnType.bindings.get(this.typeNameIdOfOutput) || []; @@ -3000,7 +2999,7 @@ class DocSearch { * Returns `false` if the supplied type isn't special. * * @param {rustdoc.HighlightedFunctionType} fnType - * @param {[string]} result + * @param {string[]} result */ const writeSpecialPrimitive = (fnType, result) => { if (fnType.id === this.typeNameIdOfArray || fnType.id === this.typeNameIdOfSlice || @@ -3047,7 +3046,7 @@ class DocSearch { * updating the where clause and generic type param map. * * @param {rustdoc.HighlightedFunctionType} fnType - * @param {[string]} result + * @param {string[]} result */ const writeFn = (fnType, result) => { if (fnType.id !== null && fnType.id < 0) { @@ -3065,7 +3064,6 @@ class DocSearch { for (const [queryId, fnId] of mgens) { if (fnId === fnType.id) { mappedNames.set( - // @ts-expect-error queryParamNames[-1 - queryId], fnParamNames[-1 - fnType.id], ); @@ -3080,7 +3078,6 @@ class DocSearch { const where = []; onEachBtwn( fnType.generics, - // @ts-expect-error nested => writeFn(nested, where), // @ts-expect-error () => pushText({ name: " + ", highlighted: false }, where), @@ -3115,7 +3112,6 @@ class DocSearch { // shown in the where clause and name mapping output, but is // redundant in this spot for (const value of values) { - // @ts-expect-error writeFn(value, []); } return true; From 7f141985ff337926639db092b2ecb5b05a763cd7 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 18:24:07 -0500 Subject: [PATCH 507/745] search.js: use @type instead of @ts-expect-error --- src/librustdoc/html/static/js/search.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index f714f361d4b9..5dda3d34e104 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -3153,26 +3153,22 @@ class DocSearch { } } }; - // @ts-expect-error + /** @type {string[]} */ const type = []; onEachBtwn( fnInputs, - // @ts-expect-error fnType => writeFn(fnType, type), // @ts-expect-error () => pushText({ name: ", ", highlighted: false }, type), ); - // @ts-expect-error pushText({ name: " -> ", highlighted: false }, type); onEachBtwn( fnOutput, - // @ts-expect-error fnType => writeFn(fnType, type), // @ts-expect-error () => pushText({ name: ", ", highlighted: false }, type), ); - // @ts-expect-error return {type, mappedNames, whereClause}; }; From 3245e7b069b52d16e82065f05c7c968fab7b3f2b Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 18:27:42 -0500 Subject: [PATCH 508/745] search.js: fix return type of unifyFunctionTypes --- src/librustdoc/html/static/js/search.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 5dda3d34e104..ba672ffb7a41 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -3483,8 +3483,7 @@ class DocSearch { } } } - // @ts-expect-error - return false; + return null; } // Multiple element recursive case From 4a00a8449e3603823f5d0c5d01afc4425ed4b448 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 18:29:21 -0500 Subject: [PATCH 509/745] search.js: give type to unifiedGenericsMgens --- src/librustdoc/html/static/js/search.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index ba672ffb7a41..1ba34027a0af 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -3539,7 +3539,7 @@ class DocSearch { } /** @type {rustdoc.HighlightedFunctionType[]|null} */ let unifiedGenerics = []; - // @ts-expect-error + /** @type {null|Map} */ let unifiedGenericsMgens = null; /** @type {rustdoc.HighlightedFunctionType[]|null} */ const passesUnification = unifyFunctionTypes( @@ -3593,7 +3593,6 @@ class DocSearch { // @ts-expect-error queryElem.bindings.get(k), whereClause, - // @ts-expect-error unifiedGenericsMgens, solutionCb, unboxingDepth, From 523f413a738822d0312ea82ea69b21b6900af68a Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 18:40:06 -0500 Subject: [PATCH 510/745] search.js: give type annotation to newSolutions --- src/librustdoc/html/static/js/search.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 1ba34027a0af..a54104c3809e 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -3990,7 +3990,7 @@ class DocSearch { } const fnTypeBindings = fnType.bindings.get(name); mgensSolutionSet = mgensSolutionSet.flatMap(mgens => { - // @ts-expect-error + /** @type{Array | null>} */ const newSolutions = []; unifyFunctionTypes( // @ts-expect-error @@ -4006,7 +4006,6 @@ class DocSearch { }, unboxingDepth, ); - // @ts-expect-error return newSolutions; }); } @@ -4254,6 +4253,7 @@ class DocSearch { return false; } + // this does not yet have a type in `rustdoc.d.ts`. // @ts-expect-error function createAliasFromItem(item) { return { From 93b3be33001d15e85b38d99560eaa337812ee90a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 24 Mar 2025 17:09:48 +0000 Subject: [PATCH 511/745] Instantiate binder before registering nested obligations for auto/built-in traits --- .../src/traits/select/confirmation.rs | 37 +++++++------------ .../src/traits/select/mod.rs | 11 ++---- 2 files changed, 16 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 4404324d5cd7..a66c958c1097 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -266,9 +266,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } else { bug!("unexpected builtin trait {:?}", trait_def) }; - let BuiltinImplConditions::Where(nested) = conditions else { + let BuiltinImplConditions::Where(types) = conditions else { bug!("obligation {:?} had matched a builtin impl but now doesn't", obligation); }; + let types = self.infcx.enter_forall_and_leak_universe(types); let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived); self.collect_predicates_for_types( @@ -276,7 +277,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { cause, obligation.recursion_depth + 1, trait_def, - nested, + types, ) } else { PredicateObligations::new() @@ -444,37 +445,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, ) -> Result, SelectionError<'tcx>> { - debug!(?obligation, "confirm_auto_impl_candidate"); - - let self_ty = obligation.predicate.self_ty().map_bound(|ty| self.infcx.shallow_resolve(ty)); - let types = self.constituent_types_for_ty(self_ty)?; - Ok(self.vtable_auto_impl(obligation, obligation.predicate.def_id(), types)) - } - - /// See `confirm_auto_impl_candidate`. - fn vtable_auto_impl( - &mut self, - obligation: &PolyTraitObligation<'tcx>, - trait_def_id: DefId, - nested: ty::Binder<'tcx, Vec>>, - ) -> PredicateObligations<'tcx> { - debug!(?nested, "vtable_auto_impl"); ensure_sufficient_stack(|| { - let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived); - assert_eq!(obligation.predicate.polarity(), ty::PredicatePolarity::Positive); + let self_ty = + obligation.predicate.self_ty().map_bound(|ty| self.infcx.shallow_resolve(ty)); + + let types = self.constituent_types_for_ty(self_ty)?; + let types = self.infcx.enter_forall_and_leak_universe(types); + + let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived); let obligations = self.collect_predicates_for_types( obligation.param_env, cause, obligation.recursion_depth + 1, - trait_def_id, - nested, + obligation.predicate.def_id(), + types, ); - debug!(?obligations, "vtable_auto_impl"); - - obligations + Ok(obligations) }) } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index e1adabbeaa66..e439df76cd4b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2370,7 +2370,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { cause: ObligationCause<'tcx>, recursion_depth: usize, trait_def_id: DefId, - types: ty::Binder<'tcx, Vec>>, + types: Vec>, ) -> PredicateObligations<'tcx> { // Because the types were potentially derived from // higher-ranked obligations they may reference late-bound @@ -2387,13 +2387,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // 3. Re-bind the regions back to `for<'a> &'a i32 : Copy` types - .as_ref() - .skip_binder() // binder moved -\ - .iter() - .flat_map(|ty| { - let ty: ty::Binder<'tcx, Ty<'tcx>> = types.rebind(*ty); // <----/ - - let placeholder_ty = self.infcx.enter_forall_and_leak_universe(ty); + .into_iter() + .flat_map(|placeholder_ty| { let Normalized { value: normalized_ty, mut obligations } = ensure_sufficient_stack(|| { normalize_with_depth( From 1b8b09a01d6b0acf24b070cd997bff6cb739dfec Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 19:11:55 -0500 Subject: [PATCH 512/745] search.js: fix whitespace --- src/librustdoc/html/static/js/search.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index a54104c3809e..651d12bb2e90 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2798,7 +2798,7 @@ class DocSearch { // To be sure than it some items aren't considered as duplicate. obj.fullPath = res[2] + "|" + obj.ty - + if (duplicates.has(obj.fullPath)) { continue; } From 817e2c598d01c1c4abc7ae67731432df2cf1047c Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sat, 1 Feb 2025 17:46:40 -0500 Subject: [PATCH 513/745] Remove InstanceKind::generates_cgu_internal_copy --- .../src/back/symbol_export.rs | 13 +--- compiler/rustc_middle/src/mir/mono.rs | 75 ++++++++++++++++--- compiler/rustc_middle/src/ty/instance.rs | 44 ----------- 3 files changed, 68 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index f8f7bb2dbc69..76b0a566f8e7 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -93,16 +93,11 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap { GlobalAsm(ItemId), } +fn opt_incr_drop_glue_mode<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> InstantiationMode { + // Non-ADTs can't have a Drop impl. This case is mostly hit by closures whose captures require + // dropping. + let ty::Adt(adt_def, _) = ty.kind() else { + return InstantiationMode::LocalCopy; + }; + + // Types that don't have a direct Drop impl, but have fields that require dropping. + let Some(dtor) = adt_def.destructor(tcx) else { + // We use LocalCopy for drops of enums only; this code is inherited from + // https://github.com/rust-lang/rust/pull/67332 and the theory is that we get to optimize + // out code like drop_in_place(Option::None) before crate-local ThinLTO, which improves + // compile time. At the time of writing, simply removing this entire check does seem to + // regress incr-opt compile times. But it sure seems like a more sophisticated check could + // do better here. + if adt_def.is_enum() { + return InstantiationMode::LocalCopy; + } else { + return InstantiationMode::GloballyShared { may_conflict: true }; + } + }; + + // We've gotten to a drop_in_place for a type that directly implements Drop. + // The drop glue is a wrapper for the Drop::drop impl, and we are an optimized build, so in an + // effort to coordinate with the mode that the actual impl will get, we make the glue also + // LocalCopy. + if tcx.cross_crate_inlinable(dtor.did) { + InstantiationMode::LocalCopy + } else { + InstantiationMode::GloballyShared { may_conflict: true } + } +} + impl<'tcx> MonoItem<'tcx> { /// Returns `true` if the mono item is user-defined (i.e. not compiler-generated, like shims). pub fn is_user_defined(&self) -> bool { @@ -123,16 +156,36 @@ impl<'tcx> MonoItem<'tcx> { return InstantiationMode::GloballyShared { may_conflict: false }; } - // FIXME: The logic for which functions are permitted to get LocalCopy is actually spread - // across 4 functions: - // * cross_crate_inlinable(def_id) - // * InstanceKind::requires_inline - // * InstanceKind::generate_cgu_internal_copy - // * MonoItem::instantiation_mode - // Since reachable_non_generics calls InstanceKind::generates_cgu_internal_copy to decide - // which symbols this crate exports, we are obligated to only generate LocalCopy when - // generates_cgu_internal_copy returns true. - if !instance.def.generates_cgu_internal_copy(tcx) { + // This is technically a heuristic even though it's in the "not a heuristic" part of + // instantiation mode selection. + // It is surely possible to untangle this; the root problem is that the way we instantiate + // InstanceKind other than Item is very complicated. + // + // The fallback case is to give everything else GloballyShared at OptLevel::No and + // LocalCopy at all other opt levels. This is a good default, except for one specific build + // configuration: Optimized incremental builds. + // In the current compiler architecture there is a fundamental tension between + // optimizations (which want big CGUs with as many things LocalCopy as possible) and + // incrementality (which wants small CGUs with as many things GloballyShared as possible). + // The heuristics implemented here do better than a completely naive approach in the + // compiler benchmark suite, but there is no reason to believe they are optimal. + if let InstanceKind::DropGlue(_, Some(ty)) = instance.def { + if tcx.sess.opts.optimize == OptLevel::No { + return InstantiationMode::GloballyShared { may_conflict: false }; + } + if tcx.sess.opts.incremental.is_none() { + return InstantiationMode::LocalCopy; + } + return opt_incr_drop_glue_mode(tcx, ty); + } + + // We need to ensure that we do not decide the InstantiationMode of an exported symbol is + // LocalCopy. Since exported symbols are computed based on the output of + // cross_crate_inlinable, we are beholden to our previous decisions. + // + // Note that just like above, this check for requires_inline is technically a heuristic + // even though it's in the "not a heuristic" part of instantiation mode selection. + if !tcx.cross_crate_inlinable(instance.def_id()) && !instance.def.requires_inline(tcx) { return InstantiationMode::GloballyShared { may_conflict: false }; } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index b7a648aae3f1..c557178096ef 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -301,50 +301,6 @@ impl<'tcx> InstanceKind<'tcx> { ) } - /// Returns `true` if the machine code for this instance is instantiated in - /// each codegen unit that references it. - /// Note that this is only a hint! The compiler can globally decide to *not* - /// do this in order to speed up compilation. CGU-internal copies are - /// only exist to enable inlining. If inlining is not performed (e.g. at - /// `-Copt-level=0`) then the time for generating them is wasted and it's - /// better to create a single copy with external linkage. - pub fn generates_cgu_internal_copy(&self, tcx: TyCtxt<'tcx>) -> bool { - if self.requires_inline(tcx) { - return true; - } - if let ty::InstanceKind::DropGlue(.., Some(ty)) - | ty::InstanceKind::AsyncDropGlueCtorShim(.., Some(ty)) = *self - { - // Drop glue generally wants to be instantiated at every codegen - // unit, but without an #[inline] hint. We should make this - // available to normal end-users. - if tcx.sess.opts.incremental.is_none() { - return true; - } - // When compiling with incremental, we can generate a *lot* of - // codegen units. Including drop glue into all of them has a - // considerable compile time cost. - // - // We include enums without destructors to allow, say, optimizing - // drops of `Option::None` before LTO. We also respect the intent of - // `#[inline]` on `Drop::drop` implementations. - return ty.ty_adt_def().is_none_or(|adt_def| { - match *self { - ty::InstanceKind::DropGlue(..) => adt_def.destructor(tcx).map(|dtor| dtor.did), - ty::InstanceKind::AsyncDropGlueCtorShim(..) => { - adt_def.async_destructor(tcx).map(|dtor| dtor.ctor) - } - _ => unreachable!(), - } - .map_or_else(|| adt_def.is_enum(), |did| tcx.cross_crate_inlinable(did)) - }); - } - if let ty::InstanceKind::ThreadLocalShim(..) = *self { - return false; - } - tcx.cross_crate_inlinable(self.def_id()) - } - pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool { match *self { InstanceKind::Item(def_id) | InstanceKind::Virtual(def_id, _) => { From 1a6266340e53e3f663b49f71a14461dafa47de47 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Mar 2025 10:51:42 +1100 Subject: [PATCH 514/745] Add a test with an empty crate name. This error was untested. --- tests/ui/attributes/crate-name-empty.rs | 5 +++++ tests/ui/attributes/crate-name-empty.stderr | 8 ++++++++ 2 files changed, 13 insertions(+) create mode 100644 tests/ui/attributes/crate-name-empty.rs create mode 100644 tests/ui/attributes/crate-name-empty.stderr diff --git a/tests/ui/attributes/crate-name-empty.rs b/tests/ui/attributes/crate-name-empty.rs new file mode 100644 index 000000000000..dfba77a52def --- /dev/null +++ b/tests/ui/attributes/crate-name-empty.rs @@ -0,0 +1,5 @@ +// Ensure we reject `#![crate_name = ""]`. + +#![crate_name = ""] //~ ERROR crate name must not be empty + +fn main() {} diff --git a/tests/ui/attributes/crate-name-empty.stderr b/tests/ui/attributes/crate-name-empty.stderr new file mode 100644 index 000000000000..509a42d05f71 --- /dev/null +++ b/tests/ui/attributes/crate-name-empty.stderr @@ -0,0 +1,8 @@ +error: crate name must not be empty + --> $DIR/crate-name-empty.rs:3:1 + | +LL | #![crate_name = ""] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + From bd61e0129f4ff393ad350f05442a9f1ac3ddbd44 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 24 Mar 2025 18:58:18 +1100 Subject: [PATCH 515/745] Use `Ident::dummy()` in `dummy_annotatable`. This is exactly the kind of case `Ident::dummy()` is for. --- compiler/rustc_builtin_macros/src/derive.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index 2653a9f48b9b..e259f5b3955b 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -103,7 +103,7 @@ impl MultiItemModifier for Expander { fn dummy_annotatable() -> Annotatable { Annotatable::GenericParam(ast::GenericParam { id: ast::DUMMY_NODE_ID, - ident: Ident::empty(), + ident: Ident::dummy(), attrs: Default::default(), bounds: Default::default(), is_placeholder: false, From 2469ab195a558b3a09b5ef4319ea8a3f989b621f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 24 Mar 2025 18:59:44 +1100 Subject: [PATCH 516/745] Use `Option` in `panic_call`. Instead of `kw::Empty`. It makes it clearer that this is a name that is searched for and might not be found. --- compiler/rustc_lint/src/non_fmt_panic.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index ac9f8d92dacb..16c061008085 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -7,7 +7,7 @@ use rustc_parse_format::{ParseMode, Parser, Piece}; use rustc_session::lint::FutureIncompatibilityReason; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::edition::Edition; -use rustc_span::{InnerSpan, Span, Symbol, hygiene, kw, sym}; +use rustc_span::{InnerSpan, Span, Symbol, hygiene, sym}; use rustc_trait_selection::infer::InferCtxtExt; use crate::lints::{NonFmtPanicBraces, NonFmtPanicUnused}; @@ -167,7 +167,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc .get_diagnostic_item(sym::Debug) .is_some_and(|t| infcx.type_implements_trait(t, [ty], param_env).may_apply()); - let suggest_panic_any = !is_str && panic == sym::std_panic_macro; + let suggest_panic_any = !is_str && panic == Some(sym::std_panic_macro); let fmt_applicability = if suggest_panic_any { // If we can use panic_any, use that as the MachineApplicable suggestion. @@ -297,10 +297,13 @@ fn find_delimiters(cx: &LateContext<'_>, span: Span) -> Option<(Span, Span, char )) } -fn panic_call<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>) -> (Span, Symbol, Symbol) { +fn panic_call<'tcx>( + cx: &LateContext<'tcx>, + f: &'tcx hir::Expr<'tcx>, +) -> (Span, Option, Symbol) { let mut expn = f.span.ctxt().outer_expn_data(); - let mut panic_macro = kw::Empty; + let mut panic_macro = None; // Unwrap more levels of macro expansion, as panic_2015!() // was likely expanded from panic!() and possibly from @@ -320,7 +323,7 @@ fn panic_call<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>) -> (Span, break; } expn = parent; - panic_macro = name; + panic_macro = Some(name); } let macro_symbol = From 3f32a321bc0962cd3c700a5625dca4e4967918e4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Mar 2025 09:09:01 +1100 Subject: [PATCH 517/745] Use `Option` in `ModuleKind::Def`. This way, `None` represents "crate root without a name" instead of `kw::Empty`. This changes makes it impossible to forget to handle the exceptional case. --- compiler/rustc_resolve/src/build_reduced_graph.rs | 10 +++++----- compiler/rustc_resolve/src/diagnostics.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 15 ++++++++------- compiler/rustc_resolve/src/macros.rs | 11 ++++++----- 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 763e9207a126..08648a164ab7 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -131,7 +131,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let expn_id = self.cstore().expn_that_defined_untracked(def_id, self.tcx.sess); return Some(self.new_module( parent, - ModuleKind::Def(def_kind, def_id, self.tcx.item_name(def_id)), + ModuleKind::Def(def_kind, def_id, Some(self.tcx.item_name(def_id))), expn_id, self.def_span(def_id), // FIXME: Account for `#[no_implicit_prelude]` attributes. @@ -594,7 +594,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { // HACK(eddyb) unclear how good this is, but keeping `$crate` // in `source` breaks `tests/ui/imports/import-crate-var.rs`, // while the current crate doesn't have a valid `crate_name`. - if crate_name != kw::Empty { + if let Some(crate_name) = crate_name { // `crate_name` should not be interpreted as relative. module_path.push(Segment::from_ident_and_id( Ident { name: kw::PathRoot, span: source.ident.span }, @@ -603,7 +603,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { source.ident.name = crate_name; } if rename.is_none() { - ident.name = crate_name; + ident.name = sym::dummy; } self.r.dcx().emit_err(errors::CrateImported { span: item.span }); @@ -775,7 +775,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { ItemKind::Mod(.., ref mod_kind) => { let module = self.r.new_module( Some(parent), - ModuleKind::Def(def_kind, def_id, ident.name), + ModuleKind::Def(def_kind, def_id, Some(ident.name)), expansion.to_expn_id(), item.span, parent.no_implicit_prelude @@ -811,7 +811,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { ItemKind::Enum(_, _) | ItemKind::Trait(..) => { let module = self.r.new_module( Some(parent), - ModuleKind::Def(def_kind, def_id, ident.name), + ModuleKind::Def(def_kind, def_id, Some(ident.name)), expansion.to_expn_id(), item.span, parent.no_implicit_prelude, diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 5361af98f3c7..d683fd98bd21 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -2439,7 +2439,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() else { return None; }; - let module_name = crate_module.kind.name().unwrap(); + let module_name = crate_module.kind.name().unwrap_or(kw::Empty); let import_snippet = match import.kind { ImportKind::Single { source, target, .. } if source != target => { format!("{source} as {target}") diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index ff31af0025b5..d5fd03e5f412 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -503,18 +503,18 @@ enum ModuleKind { /// /// * A normal module – either `mod from_file;` or `mod from_block { }` – /// or the crate root (which is conceptually a top-level module). - /// Note that the crate root's [name][Self::name] will be [`kw::Empty`]. + /// The crate root will have `None` for the symbol. /// * A trait or an enum (it implicitly contains associated types, methods and variant /// constructors). - Def(DefKind, DefId, Symbol), + Def(DefKind, DefId, Option), } impl ModuleKind { /// Get name of the module. fn name(&self) -> Option { - match self { + match *self { ModuleKind::Block => None, - ModuleKind::Def(.., name) => Some(*name), + ModuleKind::Def(.., name) => name, } } } @@ -1402,7 +1402,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let mut module_self_bindings = FxHashMap::default(); let graph_root = arenas.new_module( None, - ModuleKind::Def(DefKind::Mod, root_def_id, kw::Empty), + ModuleKind::Def(DefKind::Mod, root_def_id, None), ExpnId::root(), crate_span, attr::contains_name(attrs, sym::no_implicit_prelude), @@ -1411,7 +1411,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ); let empty_module = arenas.new_module( None, - ModuleKind::Def(DefKind::Mod, root_def_id, kw::Empty), + ModuleKind::Def(DefKind::Mod, root_def_id, None), ExpnId::root(), DUMMY_SP, true, @@ -2286,7 +2286,8 @@ fn module_to_string(mut module: Module<'_>) -> Option { loop { if let ModuleKind::Def(.., name) = module.kind { if let Some(parent) = module.parent { - names.push(name); + // `unwrap` is safe: the presence of a parent means it's not the crate root. + names.push(name.unwrap()); module = parent } else { break; diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index c4304a7a6df6..967cb5a0ec62 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -168,7 +168,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { hygiene::update_dollar_crate_names(|ctxt| { let ident = Ident::new(kw::DollarCrate, DUMMY_SP.with_ctxt(ctxt)); match self.resolve_crate_root(ident).kind { - ModuleKind::Def(.., name) if name != kw::Empty => name, + ModuleKind::Def(.., name) if let Some(name) = name => name, _ => kw::Crate, } }); @@ -1068,11 +1068,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ); if fallback_binding.ok().and_then(|b| b.res().opt_def_id()) != Some(def_id) { let location = match parent_scope.module.kind { - ModuleKind::Def(_, _, name) if name == kw::Empty => { - "the crate root".to_string() - } ModuleKind::Def(kind, def_id, name) => { - format!("{} `{name}`", kind.descr(def_id)) + if let Some(name) = name { + format!("{} `{name}`", kind.descr(def_id)) + } else { + "the crate root".to_string() + } } ModuleKind::Block => "this scope".to_string(), }; From e576d8850de702f6c712eaca77f758f72ef13419 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Mar 2025 11:10:45 +1100 Subject: [PATCH 518/745] Use `Option` in `DuplicateLangItem`. For the the symbols that might not be present, instead of `kw::Empty`. --- compiler/rustc_passes/src/errors.rs | 20 +++++++++++++------- compiler/rustc_passes/src/lang_items.rs | 14 +++++++------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index a72f40cd843a..0ee17430aab8 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1348,12 +1348,12 @@ pub(crate) struct DuplicateLangItem { pub local_span: Option, pub lang_item_name: Symbol, pub crate_name: Symbol, - pub dependency_of: Symbol, + pub dependency_of: Option, pub is_local: bool, pub path: String, pub first_defined_span: Option, - pub orig_crate_name: Symbol, - pub orig_dependency_of: Symbol, + pub orig_crate_name: Option, + pub orig_dependency_of: Option, pub orig_is_local: bool, pub orig_path: String, pub(crate) duplicate: Duplicate, @@ -1374,10 +1374,16 @@ impl Diagnostic<'_, G> for DuplicateLangItem { diag.code(E0152); diag.arg("lang_item_name", self.lang_item_name); diag.arg("crate_name", self.crate_name); - diag.arg("dependency_of", self.dependency_of); + if let Some(dependency_of) = self.dependency_of { + diag.arg("dependency_of", dependency_of); + } diag.arg("path", self.path); - diag.arg("orig_crate_name", self.orig_crate_name); - diag.arg("orig_dependency_of", self.orig_dependency_of); + if let Some(orig_crate_name) = self.orig_crate_name { + diag.arg("orig_crate_name", orig_crate_name); + } + if let Some(orig_dependency_of) = self.orig_dependency_of { + diag.arg("orig_dependency_of", orig_dependency_of); + } diag.arg("orig_path", self.orig_path); if let Some(span) = self.local_span { diag.span(span); @@ -1385,7 +1391,7 @@ impl Diagnostic<'_, G> for DuplicateLangItem { if let Some(span) = self.first_defined_span { diag.span_note(span, fluent::passes_first_defined_span); } else { - if self.orig_dependency_of.is_empty() { + if self.orig_dependency_of.is_none() { diag.note(fluent::passes_first_defined_crate); } else { diag.note(fluent::passes_first_defined_crate_depends); diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index fe1140d893e3..9d4b46cd3066 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -16,7 +16,7 @@ use rustc_hir::{LangItem, LanguageItems, MethodKind, Target}; use rustc_middle::query::Providers; use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_session::cstore::ExternCrate; -use rustc_span::{Span, kw}; +use rustc_span::Span; use crate::errors::{ DuplicateLangItem, IncorrectTarget, LangItemOnIncorrectTarget, UnknownLangItem, @@ -98,7 +98,7 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> { { let lang_item_name = lang_item.name(); let crate_name = self.tcx.crate_name(item_def_id.krate); - let mut dependency_of = kw::Empty; + let mut dependency_of = None; let is_local = item_def_id.is_local(); let path = if is_local { String::new() @@ -112,8 +112,8 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> { }; let first_defined_span = self.item_spans.get(&original_def_id).copied(); - let mut orig_crate_name = kw::Empty; - let mut orig_dependency_of = kw::Empty; + let mut orig_crate_name = None; + let mut orig_dependency_of = None; let orig_is_local = original_def_id.is_local(); let orig_path = if orig_is_local { String::new() @@ -127,11 +127,11 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> { }; if first_defined_span.is_none() { - orig_crate_name = self.tcx.crate_name(original_def_id.krate); + orig_crate_name = Some(self.tcx.crate_name(original_def_id.krate)); if let Some(ExternCrate { dependency_of: inner_dependency_of, .. }) = self.tcx.extern_crate(original_def_id.krate) { - orig_dependency_of = self.tcx.crate_name(*inner_dependency_of); + orig_dependency_of = Some(self.tcx.crate_name(*inner_dependency_of)); } } @@ -140,7 +140,7 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> { } else { match self.tcx.extern_crate(item_def_id.krate) { Some(ExternCrate { dependency_of: inner_dependency_of, .. }) => { - dependency_of = self.tcx.crate_name(*inner_dependency_of); + dependency_of = Some(self.tcx.crate_name(*inner_dependency_of)); Duplicate::CrateDepends } _ => Duplicate::Crate, From 79b9664091e90c08a7abeab2bbc4a941bcdc3863 Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Wed, 13 Nov 2024 13:13:03 -0800 Subject: [PATCH 519/745] Reduce visibility of most items in `rustc_codegen_llvm` --- compiler/rustc_codegen_llvm/src/back/lto.rs | 2 +- compiler/rustc_codegen_llvm/src/lib.rs | 6 +- .../rustc_codegen_llvm/src/llvm/archive_ro.rs | 6 +- .../rustc_codegen_llvm/src/llvm/diagnostic.rs | 20 +- .../rustc_codegen_llvm/src/llvm/enzyme_ffi.rs | 44 ++--- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 182 +++++++++--------- compiler/rustc_codegen_llvm/src/llvm/mod.rs | 20 +- 7 files changed, 144 insertions(+), 136 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 668795191a29..f083cfbd7d30 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -728,7 +728,7 @@ impl ThinBuffer { } } - pub unsafe fn from_raw_ptr(ptr: *mut llvm::ThinLTOBuffer) -> ThinBuffer { + pub(crate) unsafe fn from_raw_ptr(ptr: *mut llvm::ThinLTOBuffer) -> ThinBuffer { let mut ptr = NonNull::new(ptr).unwrap(); ThinBuffer(unsafe { ptr.as_mut() }) } diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index f622646a5d9d..425381b0ffab 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -29,7 +29,7 @@ use back::owned_target_machine::OwnedTargetMachine; use back::write::{create_informational_target_machine, create_target_machine}; use context::SimpleCx; use errors::{AutoDiffWithoutLTO, ParseTargetMachineConfig}; -pub(crate) use llvm_util::target_features_cfg; +use llvm_util::target_features_cfg; use rustc_ast::expand::allocator::AllocatorKind; use rustc_ast::expand::autodiff_attrs::AutoDiffItem; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule}; @@ -71,9 +71,7 @@ mod debuginfo; mod declare; mod errors; mod intrinsic; -// FIXME(Zalathar): Fix all the unreachable-pub warnings that would occur if -// this isn't pub, then make it not pub. -pub mod llvm; +mod llvm; mod llvm_util; mod mono_item; mod type_; diff --git a/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs b/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs index 63b2b15c5145..51bcc4d123d3 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs @@ -5,17 +5,17 @@ use std::{slice, str}; use rustc_fs_util::path_to_c_string; -pub struct ArchiveRO { +pub(crate) struct ArchiveRO { pub raw: &'static mut super::Archive, } unsafe impl Send for ArchiveRO {} -pub struct Iter<'a> { +pub(crate) struct Iter<'a> { raw: &'a mut super::ArchiveIterator<'a>, } -pub struct Child<'a> { +pub(crate) struct Child<'a> { pub raw: &'a mut super::ArchiveChild<'a>, } diff --git a/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs b/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs index 11043b664f52..0e0f2b0eab01 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs @@ -3,13 +3,13 @@ use libc::c_uint; use rustc_span::InnerSpan; -pub use self::Diagnostic::*; -pub use self::OptimizationDiagnosticKind::*; +pub(crate) use self::Diagnostic::*; +use self::OptimizationDiagnosticKind::*; use super::{DiagnosticInfo, SMDiagnostic}; use crate::value::Value; #[derive(Copy, Clone, Debug)] -pub enum OptimizationDiagnosticKind { +pub(crate) enum OptimizationDiagnosticKind { OptimizationRemark, OptimizationMissed, OptimizationAnalysis, @@ -19,9 +19,10 @@ pub enum OptimizationDiagnosticKind { OptimizationRemarkOther, } -pub struct OptimizationDiagnostic<'ll> { +pub(crate) struct OptimizationDiagnostic<'ll> { pub kind: OptimizationDiagnosticKind, pub pass_name: String, + #[expect(dead_code)] pub function: &'ll Value, pub line: c_uint, pub column: c_uint, @@ -73,14 +74,14 @@ impl<'ll> OptimizationDiagnostic<'ll> { } } -pub struct SrcMgrDiagnostic { +pub(crate) struct SrcMgrDiagnostic { pub level: super::DiagnosticLevel, pub message: String, pub source: Option<(String, Vec)>, } impl SrcMgrDiagnostic { - pub unsafe fn unpack(diag: &SMDiagnostic) -> SrcMgrDiagnostic { + pub(crate) unsafe fn unpack(diag: &SMDiagnostic) -> SrcMgrDiagnostic { // Recover the post-substitution assembly code from LLVM for better // diagnostics. let mut have_source = false; @@ -120,7 +121,7 @@ impl SrcMgrDiagnostic { } #[derive(Clone)] -pub struct InlineAsmDiagnostic { +pub(crate) struct InlineAsmDiagnostic { pub level: super::DiagnosticLevel, pub cookie: u64, pub message: String, @@ -158,7 +159,7 @@ impl InlineAsmDiagnostic { } } -pub enum Diagnostic<'ll> { +pub(crate) enum Diagnostic<'ll> { Optimization(OptimizationDiagnostic<'ll>), InlineAsm(InlineAsmDiagnostic), PGO(&'ll DiagnosticInfo), @@ -166,11 +167,12 @@ pub enum Diagnostic<'ll> { Unsupported(&'ll DiagnosticInfo), /// LLVM has other types that we do not wrap here. + #[expect(dead_code)] UnknownDiagnostic(&'ll DiagnosticInfo), } impl<'ll> Diagnostic<'ll> { - pub unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self { + pub(crate) unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self { use super::DiagnosticKind as Dk; unsafe { diff --git a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs index f6b238629075..79e4cc8aa774 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs @@ -31,20 +31,20 @@ unsafe extern "C" { #[repr(C)] #[derive(Copy, Clone, PartialEq)] -pub enum LLVMRustVerifierFailureAction { +pub(crate) enum LLVMRustVerifierFailureAction { LLVMAbortProcessAction = 0, LLVMPrintMessageAction = 1, LLVMReturnStatusAction = 2, } #[cfg(llvm_enzyme)] -pub use self::Enzyme_AD::*; +pub(crate) use self::Enzyme_AD::*; #[cfg(llvm_enzyme)] -pub mod Enzyme_AD { +pub(crate) mod Enzyme_AD { use libc::c_void; unsafe extern "C" { - pub fn EnzymeSetCLBool(arg1: *mut ::std::os::raw::c_void, arg2: u8); + pub(crate) fn EnzymeSetCLBool(arg1: *mut ::std::os::raw::c_void, arg2: u8); } unsafe extern "C" { static mut EnzymePrintPerf: c_void; @@ -56,42 +56,42 @@ pub mod Enzyme_AD { static mut EnzymeInline: c_void; static mut RustTypeRules: c_void; } - pub fn set_print_perf(print: bool) { + pub(crate) fn set_print_perf(print: bool) { unsafe { EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymePrintPerf), print as u8); } } - pub fn set_print_activity(print: bool) { + pub(crate) fn set_print_activity(print: bool) { unsafe { EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymePrintActivity), print as u8); } } - pub fn set_print_type(print: bool) { + pub(crate) fn set_print_type(print: bool) { unsafe { EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymePrintType), print as u8); } } - pub fn set_print(print: bool) { + pub(crate) fn set_print(print: bool) { unsafe { EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymePrint), print as u8); } } - pub fn set_strict_aliasing(strict: bool) { + pub(crate) fn set_strict_aliasing(strict: bool) { unsafe { EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymeStrictAliasing), strict as u8); } } - pub fn set_loose_types(loose: bool) { + pub(crate) fn set_loose_types(loose: bool) { unsafe { EnzymeSetCLBool(std::ptr::addr_of_mut!(looseTypeAnalysis), loose as u8); } } - pub fn set_inline(val: bool) { + pub(crate) fn set_inline(val: bool) { unsafe { EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymeInline), val as u8); } } - pub fn set_rust_rules(val: bool) { + pub(crate) fn set_rust_rules(val: bool) { unsafe { EnzymeSetCLBool(std::ptr::addr_of_mut!(RustTypeRules), val as u8); } @@ -99,34 +99,34 @@ pub mod Enzyme_AD { } #[cfg(not(llvm_enzyme))] -pub use self::Fallback_AD::*; +pub(crate) use self::Fallback_AD::*; #[cfg(not(llvm_enzyme))] -pub mod Fallback_AD { +pub(crate) mod Fallback_AD { #![allow(unused_variables)] - pub fn set_inline(val: bool) { + pub(crate) fn set_inline(val: bool) { unimplemented!() } - pub fn set_print_perf(print: bool) { + pub(crate) fn set_print_perf(print: bool) { unimplemented!() } - pub fn set_print_activity(print: bool) { + pub(crate) fn set_print_activity(print: bool) { unimplemented!() } - pub fn set_print_type(print: bool) { + pub(crate) fn set_print_type(print: bool) { unimplemented!() } - pub fn set_print(print: bool) { + pub(crate) fn set_print(print: bool) { unimplemented!() } - pub fn set_strict_aliasing(strict: bool) { + pub(crate) fn set_strict_aliasing(strict: bool) { unimplemented!() } - pub fn set_loose_types(loose: bool) { + pub(crate) fn set_loose_types(loose: bool) { unimplemented!() } - pub fn set_rust_rules(val: bool) { + pub(crate) fn set_rust_rules(val: bool) { unimplemented!() } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 83efb3ea6603..3ce3761944b3 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -32,10 +32,10 @@ use crate::llvm; /// In the LLVM-C API, boolean values are passed as `typedef int LLVMBool`, /// which has a different ABI from Rust or C++ `bool`. -pub type Bool = c_int; +pub(crate) type Bool = c_int; -pub const True: Bool = 1 as Bool; -pub const False: Bool = 0 as Bool; +pub(crate) const True: Bool = 1 as Bool; +pub(crate) const False: Bool = 0 as Bool; /// Wrapper for a raw enum value returned from LLVM's C APIs. /// @@ -44,7 +44,7 @@ pub const False: Bool = 0 as Bool; /// value and returns it. Instead, return this raw wrapper, then convert to the /// Rust-side enum explicitly. #[repr(transparent)] -pub struct RawEnum { +pub(crate) struct RawEnum { value: u32, /// We don't own or consume a `T`, but we can produce one. _rust_side_type: PhantomData T>, @@ -64,7 +64,7 @@ impl> RawEnum { #[derive(Copy, Clone, PartialEq)] #[repr(C)] #[allow(dead_code)] // Variants constructed by C++. -pub enum LLVMRustResult { +pub(crate) enum LLVMRustResult { Success, Failure, } @@ -83,7 +83,7 @@ pub enum LLVMRustResult { /// C++ API. #[derive(Copy, Clone, PartialEq)] #[repr(C)] -pub enum ModuleFlagMergeBehavior { +pub(crate) enum ModuleFlagMergeBehavior { Error = 1, Warning = 2, Require = 3, @@ -101,7 +101,7 @@ pub enum ModuleFlagMergeBehavior { /// See #[derive(Copy, Clone, PartialEq, Debug, TryFromU32)] #[repr(C)] -pub enum CallConv { +pub(crate) enum CallConv { CCallConv = 0, FastCallConv = 8, ColdCallConv = 9, @@ -126,7 +126,7 @@ pub enum CallConv { /// Must match the layout of `LLVMLinkage`. #[derive(Copy, Clone, PartialEq, TryFromU32)] #[repr(C)] -pub enum Linkage { +pub(crate) enum Linkage { ExternalLinkage = 0, AvailableExternallyLinkage = 1, LinkOnceAnyLinkage = 2, @@ -153,7 +153,7 @@ pub enum Linkage { /// Must match the layout of `LLVMVisibility`. #[repr(C)] #[derive(Copy, Clone, PartialEq, TryFromU32)] -pub enum Visibility { +pub(crate) enum Visibility { Default = 0, Hidden = 1, Protected = 2, @@ -171,8 +171,9 @@ impl Visibility { /// LLVMUnnamedAddr #[repr(C)] -pub enum UnnamedAddr { +pub(crate) enum UnnamedAddr { No, + #[expect(dead_code)] Local, Global, } @@ -180,7 +181,7 @@ pub enum UnnamedAddr { /// LLVMDLLStorageClass #[derive(Copy, Clone)] #[repr(C)] -pub enum DLLStorageClass { +pub(crate) enum DLLStorageClass { #[allow(dead_code)] Default = 0, DllImport = 1, // Function to be imported from DLL. @@ -193,7 +194,8 @@ pub enum DLLStorageClass { /// though it is not ABI compatible (since it's a C++ enum) #[repr(C)] #[derive(Copy, Clone, Debug)] -pub enum AttributeKind { +#[expect(dead_code, reason = "Some variants are unused, but are kept to match the C++")] +pub(crate) enum AttributeKind { AlwaysInline = 0, ByVal = 1, Cold = 2, @@ -241,7 +243,7 @@ pub enum AttributeKind { /// LLVMIntPredicate #[derive(Copy, Clone)] #[repr(C)] -pub enum IntPredicate { +pub(crate) enum IntPredicate { IntEQ = 32, IntNE = 33, IntUGT = 34, @@ -275,7 +277,7 @@ impl IntPredicate { /// LLVMRealPredicate #[derive(Copy, Clone)] #[repr(C)] -pub enum RealPredicate { +pub(crate) enum RealPredicate { RealPredicateFalse = 0, RealOEQ = 1, RealOGT = 2, @@ -321,7 +323,8 @@ impl RealPredicate { /// LLVMTypeKind #[derive(Copy, Clone, PartialEq, Debug)] #[repr(C)] -pub enum TypeKind { +#[expect(dead_code, reason = "Some variants are unused, but are kept to match LLVM-C")] +pub(crate) enum TypeKind { Void = 0, Half = 1, Float = 2, @@ -373,7 +376,7 @@ impl TypeKind { /// LLVMAtomicRmwBinOp #[derive(Copy, Clone)] #[repr(C)] -pub enum AtomicRmwBinOp { +pub(crate) enum AtomicRmwBinOp { AtomicXchg = 0, AtomicAdd = 1, AtomicSub = 2, @@ -409,7 +412,7 @@ impl AtomicRmwBinOp { /// LLVMAtomicOrdering #[derive(Copy, Clone)] #[repr(C)] -pub enum AtomicOrdering { +pub(crate) enum AtomicOrdering { #[allow(dead_code)] NotAtomic = 0, Unordered = 1, @@ -438,7 +441,7 @@ impl AtomicOrdering { /// LLVMRustFileType #[derive(Copy, Clone)] #[repr(C)] -pub enum FileType { +pub(crate) enum FileType { AssemblyFile, ObjectFile, } @@ -446,7 +449,8 @@ pub enum FileType { /// LLVMMetadataType #[derive(Copy, Clone)] #[repr(C)] -pub enum MetadataType { +#[expect(dead_code, reason = "Some variants are unused, but are kept to match LLVM-C")] +pub(crate) enum MetadataType { MD_dbg = 0, MD_tbaa = 1, MD_prof = 2, @@ -470,7 +474,7 @@ pub enum MetadataType { /// LLVMRustAsmDialect #[derive(Copy, Clone, PartialEq)] #[repr(C)] -pub enum AsmDialect { +pub(crate) enum AsmDialect { Att, Intel, } @@ -478,7 +482,7 @@ pub enum AsmDialect { /// LLVMRustCodeGenOptLevel #[derive(Copy, Clone, PartialEq)] #[repr(C)] -pub enum CodeGenOptLevel { +pub(crate) enum CodeGenOptLevel { None, Less, Default, @@ -487,7 +491,7 @@ pub enum CodeGenOptLevel { /// LLVMRustPassBuilderOptLevel #[repr(C)] -pub enum PassBuilderOptLevel { +pub(crate) enum PassBuilderOptLevel { O0, O1, O2, @@ -499,7 +503,7 @@ pub enum PassBuilderOptLevel { /// LLVMRustOptStage #[derive(PartialEq)] #[repr(C)] -pub enum OptStage { +pub(crate) enum OptStage { PreLinkNoLTO, PreLinkThinLTO, PreLinkFatLTO, @@ -509,7 +513,7 @@ pub enum OptStage { /// LLVMRustSanitizerOptions #[repr(C)] -pub struct SanitizerOptions { +pub(crate) struct SanitizerOptions { pub sanitize_address: bool, pub sanitize_address_recover: bool, pub sanitize_cfi: bool, @@ -530,7 +534,7 @@ pub struct SanitizerOptions { /// LLVMRustRelocModel #[derive(Copy, Clone, PartialEq)] #[repr(C)] -pub enum RelocModel { +pub(crate) enum RelocModel { Static, PIC, DynamicNoPic, @@ -542,7 +546,7 @@ pub enum RelocModel { /// LLVMRustFloatABI #[derive(Copy, Clone, PartialEq)] #[repr(C)] -pub enum FloatAbi { +pub(crate) enum FloatAbi { Default, Soft, Hard, @@ -551,7 +555,7 @@ pub enum FloatAbi { /// LLVMRustCodeModel #[derive(Copy, Clone)] #[repr(C)] -pub enum CodeModel { +pub(crate) enum CodeModel { Tiny, Small, Kernel, @@ -564,7 +568,7 @@ pub enum CodeModel { #[derive(Copy, Clone)] #[repr(C)] #[allow(dead_code)] // Variants constructed by C++. -pub enum DiagnosticKind { +pub(crate) enum DiagnosticKind { Other, InlineAsm, StackSize, @@ -587,7 +591,7 @@ pub enum DiagnosticKind { #[derive(Copy, Clone)] #[repr(C)] #[allow(dead_code)] // Variants constructed by C++. -pub enum DiagnosticLevel { +pub(crate) enum DiagnosticLevel { Error, Warning, Note, @@ -597,7 +601,7 @@ pub enum DiagnosticLevel { /// LLVMRustArchiveKind #[derive(Copy, Clone)] #[repr(C)] -pub enum ArchiveKind { +pub(crate) enum ArchiveKind { K_GNU, K_BSD, K_DARWIN, @@ -607,15 +611,15 @@ pub enum ArchiveKind { unsafe extern "C" { // LLVMRustThinLTOData - pub type ThinLTOData; + pub(crate) type ThinLTOData; // LLVMRustThinLTOBuffer - pub type ThinLTOBuffer; + pub(crate) type ThinLTOBuffer; } /// LLVMRustThinLTOModule #[repr(C)] -pub struct ThinLTOModule { +pub(crate) struct ThinLTOModule { pub identifier: *const c_char, pub data: *const u8, pub len: usize, @@ -624,7 +628,8 @@ pub struct ThinLTOModule { /// LLVMThreadLocalMode #[derive(Copy, Clone)] #[repr(C)] -pub enum ThreadLocalMode { +pub(crate) enum ThreadLocalMode { + #[expect(dead_code)] NotThreadLocal, GeneralDynamic, LocalDynamic, @@ -635,7 +640,7 @@ pub enum ThreadLocalMode { /// LLVMRustChecksumKind #[derive(Copy, Clone)] #[repr(C)] -pub enum ChecksumKind { +pub(crate) enum ChecksumKind { None, MD5, SHA1, @@ -645,7 +650,7 @@ pub enum ChecksumKind { /// LLVMRustMemoryEffects #[derive(Copy, Clone)] #[repr(C)] -pub enum MemoryEffects { +pub(crate) enum MemoryEffects { None, ReadOnly, InaccessibleMemOnly, @@ -654,7 +659,8 @@ pub enum MemoryEffects { /// LLVMOpcode #[derive(Copy, Clone, PartialEq, Eq)] #[repr(C)] -pub enum Opcode { +#[expect(dead_code, reason = "Some variants are unused, but are kept to match LLVM-C")] +pub(crate) enum Opcode { Ret = 1, Br = 2, Switch = 3, @@ -735,48 +741,48 @@ struct InvariantOpaque<'a> { // Opaque pointer types unsafe extern "C" { - pub type Module; - pub type Context; - pub type Type; - pub type Value; - pub type ConstantInt; - pub type Attribute; - pub type Metadata; - pub type BasicBlock; - pub type Comdat; + pub(crate) type Module; + pub(crate) type Context; + pub(crate) type Type; + pub(crate) type Value; + pub(crate) type ConstantInt; + pub(crate) type Attribute; + pub(crate) type Metadata; + pub(crate) type BasicBlock; + pub(crate) type Comdat; } #[repr(C)] -pub struct Builder<'a>(InvariantOpaque<'a>); +pub(crate) struct Builder<'a>(InvariantOpaque<'a>); #[repr(C)] -pub struct PassManager<'a>(InvariantOpaque<'a>); +pub(crate) struct PassManager<'a>(InvariantOpaque<'a>); unsafe extern "C" { pub type TargetMachine; - pub type Archive; + pub(crate) type Archive; } #[repr(C)] -pub struct ArchiveIterator<'a>(InvariantOpaque<'a>); +pub(crate) struct ArchiveIterator<'a>(InvariantOpaque<'a>); #[repr(C)] -pub struct ArchiveChild<'a>(InvariantOpaque<'a>); +pub(crate) struct ArchiveChild<'a>(InvariantOpaque<'a>); unsafe extern "C" { - pub type Twine; - pub type DiagnosticInfo; - pub type SMDiagnostic; + pub(crate) type Twine; + pub(crate) type DiagnosticInfo; + pub(crate) type SMDiagnostic; } #[repr(C)] -pub struct RustArchiveMember<'a>(InvariantOpaque<'a>); +pub(crate) struct RustArchiveMember<'a>(InvariantOpaque<'a>); /// Opaque pointee of `LLVMOperandBundleRef`. #[repr(C)] pub(crate) struct OperandBundle<'a>(InvariantOpaque<'a>); #[repr(C)] -pub struct Linker<'a>(InvariantOpaque<'a>); +pub(crate) struct Linker<'a>(InvariantOpaque<'a>); unsafe extern "C" { - pub type DiagnosticHandler; + pub(crate) type DiagnosticHandler; } -pub type DiagnosticHandlerTy = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void); +pub(crate) type DiagnosticHandlerTy = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void); -pub mod debuginfo { +pub(crate) mod debuginfo { use std::ptr; use bitflags::bitflags; @@ -793,7 +799,7 @@ pub mod debuginfo { /// builder reference typically has a shorter lifetime than the LLVM /// session (`'ll`) that it participates in. #[repr(C)] - pub struct DIBuilder<'ll>(InvariantOpaque<'ll>); + pub(crate) struct DIBuilder<'ll>(InvariantOpaque<'ll>); /// Owning pointer to a `DIBuilder<'ll>` that will dispose of the builder /// when dropped. Use `.as_ref()` to get the underlying `&DIBuilder` @@ -822,22 +828,22 @@ pub mod debuginfo { } } - pub type DIDescriptor = Metadata; - pub type DILocation = Metadata; - pub type DIScope = DIDescriptor; - pub type DIFile = DIScope; - pub type DILexicalBlock = DIScope; - pub type DISubprogram = DIScope; - pub type DIType = DIDescriptor; - pub type DIBasicType = DIType; - pub type DIDerivedType = DIType; - pub type DICompositeType = DIDerivedType; - pub type DIVariable = DIDescriptor; - pub type DIGlobalVariableExpression = DIDescriptor; - pub type DIArray = DIDescriptor; - pub type DISubrange = DIDescriptor; - pub type DIEnumerator = DIDescriptor; - pub type DITemplateTypeParameter = DIDescriptor; + pub(crate) type DIDescriptor = Metadata; + pub(crate) type DILocation = Metadata; + pub(crate) type DIScope = DIDescriptor; + pub(crate) type DIFile = DIScope; + pub(crate) type DILexicalBlock = DIScope; + pub(crate) type DISubprogram = DIScope; + pub(crate) type DIType = DIDescriptor; + pub(crate) type DIBasicType = DIType; + pub(crate) type DIDerivedType = DIType; + pub(crate) type DICompositeType = DIDerivedType; + pub(crate) type DIVariable = DIDescriptor; + pub(crate) type DIGlobalVariableExpression = DIDescriptor; + pub(crate) type DIArray = DIDescriptor; + pub(crate) type DISubrange = DIDescriptor; + pub(crate) type DIEnumerator = DIDescriptor; + pub(crate) type DITemplateTypeParameter = DIDescriptor; bitflags! { /// Must match the layout of `LLVMDIFlags` in the LLVM-C API. @@ -846,7 +852,7 @@ pub mod debuginfo { /// assertions in `RustWrapper.cpp` used by `fromRust(LLVMDIFlags)`. #[repr(transparent)] #[derive(Clone, Copy, Default)] - pub struct DIFlags: u32 { + pub(crate) struct DIFlags: u32 { const FlagZero = 0; const FlagPrivate = 1; const FlagProtected = 2; @@ -886,7 +892,7 @@ pub mod debuginfo { bitflags! { #[repr(transparent)] #[derive(Clone, Copy, Default)] - pub struct DISPFlags: u32 { + pub(crate) struct DISPFlags: u32 { const SPFlagZero = 0; const SPFlagVirtual = 1; const SPFlagPureVirtual = 2; @@ -900,7 +906,7 @@ pub mod debuginfo { /// LLVMRustDebugEmissionKind #[derive(Copy, Clone)] #[repr(C)] - pub enum DebugEmissionKind { + pub(crate) enum DebugEmissionKind { NoDebug, FullDebug, LineTablesOnly, @@ -932,8 +938,9 @@ pub mod debuginfo { /// LLVMRustDebugNameTableKind #[derive(Clone, Copy)] #[repr(C)] - pub enum DebugNameTableKind { + pub(crate) enum DebugNameTableKind { Default, + #[expect(dead_code)] Gnu, None, } @@ -943,7 +950,7 @@ pub mod debuginfo { bitflags! { #[repr(transparent)] #[derive(Default)] - pub struct AllocKindFlags : u64 { + pub(crate) struct AllocKindFlags : u64 { const Unknown = 0; const Alloc = 1; const Realloc = 1 << 1; @@ -966,19 +973,20 @@ bitflags! { } unsafe extern "C" { - pub type ModuleBuffer; + pub(crate) type ModuleBuffer; } -pub type SelfProfileBeforePassCallback = +pub(crate) type SelfProfileBeforePassCallback = unsafe extern "C" fn(*mut c_void, *const c_char, *const c_char); -pub type SelfProfileAfterPassCallback = unsafe extern "C" fn(*mut c_void); +pub(crate) type SelfProfileAfterPassCallback = unsafe extern "C" fn(*mut c_void); -pub type GetSymbolsCallback = unsafe extern "C" fn(*mut c_void, *const c_char) -> *mut c_void; -pub type GetSymbolsErrorCallback = unsafe extern "C" fn(*const c_char) -> *mut c_void; +pub(crate) type GetSymbolsCallback = + unsafe extern "C" fn(*mut c_void, *const c_char) -> *mut c_void; +pub(crate) type GetSymbolsErrorCallback = unsafe extern "C" fn(*const c_char) -> *mut c_void; #[derive(Copy, Clone)] #[repr(transparent)] -pub struct MetadataKindId(c_uint); +pub(crate) struct MetadataKindId(c_uint); impl From for MetadataKindId { fn from(value: MetadataType) -> Self { diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index a36226b25a24..6ca81c651ed4 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -9,18 +9,18 @@ use libc::c_uint; use rustc_abi::{Align, Size, WrappingRange}; use rustc_llvm::RustString; -pub use self::CallConv::*; -pub use self::CodeGenOptSize::*; -pub use self::MetadataType::*; -pub use self::ffi::*; +pub(crate) use self::CallConv::*; +pub(crate) use self::CodeGenOptSize::*; +pub(crate) use self::MetadataType::*; +pub(crate) use self::ffi::*; use crate::common::AsCCharPtr; -pub mod archive_ro; -pub mod diagnostic; -pub mod enzyme_ffi; +pub(crate) mod archive_ro; +pub(crate) mod diagnostic; +pub(crate) mod enzyme_ffi; mod ffi; -pub use self::enzyme_ffi::*; +pub(crate) use self::enzyme_ffi::*; impl LLVMRustResult { pub(crate) fn into_result(self) -> Result<(), ()> { @@ -127,7 +127,7 @@ pub(crate) fn CreateRangeAttr(llcx: &Context, size: Size, range: WrappingRange) } #[derive(Copy, Clone)] -pub enum AttributePlace { +pub(crate) enum AttributePlace { ReturnValue, Argument(u32), Function, @@ -145,7 +145,7 @@ impl AttributePlace { #[derive(Copy, Clone, PartialEq)] #[repr(C)] -pub enum CodeGenOptSize { +pub(crate) enum CodeGenOptSize { CodeGenOptSizeNone = 0, CodeGenOptSizeDefault = 1, CodeGenOptSizeAggressive = 2, From 867da30cc71017597d9ed731b03a45c79accd873 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Mar 2025 15:50:31 +1100 Subject: [PATCH 520/745] Avoid `kw::Empty` when dealing with `rustc_allowed_through_unstable_modules`. The existing code produces `Some(kw::Empty)` for these invalid forms: - a non-name-value, e.g. `#[rustc_allowed_through_unstable_modules]` - a non-string arg, e.g. `#[rustc_allowed_through_unstable_modules = 3]` The new code avoids the `kw::Empty` and is a little shorter. It will produce `None` in those cases, which means E0789 won't be produced if the `stable` attribute is missing for these invalid forms. This doesn't matter, because these invalid forms will trigger an "malformed `rustc_allowed_through_unstable_modules` attribute" anyway. --- compiler/rustc_attr_parsing/src/attributes/stability.rs | 8 ++------ compiler/rustc_error_codes/src/error_codes/E0789.md | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index 6d76456e83c8..bdad6b50186d 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -5,7 +5,7 @@ use rustc_attr_data_structures::{ StableSince, UnstableReason, VERSION_PLACEHOLDER, }; use rustc_errors::ErrorGuaranteed; -use rustc_span::{Span, Symbol, kw, sym}; +use rustc_span::{Span, Symbol, sym}; use super::util::parse_version; use super::{AcceptMapping, AttributeParser, SingleAttributeParser}; @@ -61,11 +61,7 @@ impl AttributeParser for StabilityParser { }), (&[sym::rustc_allowed_through_unstable_modules], |this, cx, args| { reject_outside_std!(cx); - this.allowed_through_unstable_modules = - Some(match args.name_value().and_then(|i| i.value_as_str()) { - Some(msg) => msg, - None => kw::Empty, - }); + this.allowed_through_unstable_modules = args.name_value().and_then(|i| i.value_as_str()) }), ]; diff --git a/compiler/rustc_error_codes/src/error_codes/E0789.md b/compiler/rustc_error_codes/src/error_codes/E0789.md index 2c0018cc799f..c7bc6cfde513 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0789.md +++ b/compiler/rustc_error_codes/src/error_codes/E0789.md @@ -14,7 +14,7 @@ Erroneous code example: #![unstable(feature = "foo_module", reason = "...", issue = "123")] -#[rustc_allowed_through_unstable_modules] +#[rustc_allowed_through_unstable_modules = "deprecation message"] // #[stable(feature = "foo", since = "1.0")] struct Foo; // ^^^ error: `rustc_allowed_through_unstable_modules` attribute must be From 90c541d637c0857c6d5b1c3bf835e2f02f7175a9 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Mon, 24 Mar 2025 13:56:45 +0900 Subject: [PATCH 521/745] ignore doctests only in specified targets add necessary lines fix ui test error --- src/librustdoc/html/markdown.rs | 9 +++++---- tests/rustdoc-ui/doctest/per-target-ignores.rs | 14 ++++++++++++++ tests/rustdoc-ui/doctest/per-target-ignores.stdout | 6 ++++++ 3 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 tests/rustdoc-ui/doctest/per-target-ignores.rs create mode 100644 tests/rustdoc-ui/doctest/per-target-ignores.stdout diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 5aab4199d43b..0d547a6a0d92 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -1201,11 +1201,12 @@ impl LangString { seen_rust_tags = !seen_other_tags; } LangStringToken::LangToken(x) - if let Some(ignore) = x.strip_prefix("ignore-") - && enable_per_target_ignores => + if let Some(ignore) = x.strip_prefix("ignore-") => { - ignores.push(ignore.to_owned()); - seen_rust_tags = !seen_other_tags; + if enable_per_target_ignores { + ignores.push(ignore.to_owned()); + seen_rust_tags = !seen_other_tags; + } } LangStringToken::LangToken("rust") => { data.rust = true; diff --git a/tests/rustdoc-ui/doctest/per-target-ignores.rs b/tests/rustdoc-ui/doctest/per-target-ignores.rs new file mode 100644 index 000000000000..3dea7099b4be --- /dev/null +++ b/tests/rustdoc-ui/doctest/per-target-ignores.rs @@ -0,0 +1,14 @@ +//@ only-aarch64 +//@ compile-flags:--test +//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ check-pass + +///```ignore-x86_64 +/// assert!(cfg!(not(target_arch = "x86_64"))); +///``` +pub fn foo() -> u8 { + 4 +} + +fn main() {} diff --git a/tests/rustdoc-ui/doctest/per-target-ignores.stdout b/tests/rustdoc-ui/doctest/per-target-ignores.stdout new file mode 100644 index 000000000000..fe7282144dd8 --- /dev/null +++ b/tests/rustdoc-ui/doctest/per-target-ignores.stdout @@ -0,0 +1,6 @@ + +running 1 test +test $DIR/per-target-ignores.rs - foo (line 7) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + From 501945a22e314bad511e08a187c0aa029df51038 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Mar 2025 18:00:14 +1100 Subject: [PATCH 522/745] Use `sym::dummy` for a dummy arg in `parse_fn_params`. --- compiler/rustc_parse/src/parser/item.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index f4df4044dd2e..123234fedceb 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2871,7 +2871,7 @@ impl<'a> Parser<'a> { // Skip every token until next possible arg or end. p.eat_to_tokens(&[exp!(Comma), exp!(CloseParen)]); // Create a placeholder argument for proper arg count (issue #34264). - Ok(dummy_arg(Ident::new(kw::Empty, lo.to(p.prev_token.span)), guar)) + Ok(dummy_arg(Ident::new(sym::dummy, lo.to(p.prev_token.span)), guar)) }); // ...now that we've parsed the first argument, `self` is no longer allowed. first_param = false; From c961d123d2df8d9fec6d997a6725b88eabe8d5de Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 17 Mar 2025 12:10:43 +0100 Subject: [PATCH 523/745] add FCW to warn about wasm ABI transition --- compiler/rustc_lint_defs/src/builtin.rs | 46 ++++++++++ compiler/rustc_monomorphize/messages.ftl | 7 ++ compiler/rustc_monomorphize/src/errors.rs | 9 ++ .../src/mono_checks/abi_check.rs | 80 ++++++++++++++--- compiler/rustc_target/src/callconv/wasm.rs | 3 + tests/ui/abi/compatibility.rs | 1 - tests/ui/lint/wasm_c_abi_transition.rs | 41 +++++++++ tests/ui/lint/wasm_c_abi_transition.stderr | 85 +++++++++++++++++++ 8 files changed, 259 insertions(+), 13 deletions(-) create mode 100644 tests/ui/lint/wasm_c_abi_transition.rs create mode 100644 tests/ui/lint/wasm_c_abi_transition.stderr diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 592c934997c0..8a761a0a0969 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -143,6 +143,7 @@ declare_lint_pass! { UNUSED_VARIABLES, USELESS_DEPRECATED, WARNINGS, + WASM_C_ABI, // tidy-alphabetical-end ] } @@ -5082,6 +5083,8 @@ declare_lint! { /// } /// ``` /// + /// This will produce: + /// /// ```text /// warning: ABI error: this function call uses a avx vector type, which is not enabled in the caller /// --> lint_example.rs:18:12 @@ -5125,3 +5128,46 @@ declare_lint! { reference: "issue #116558 ", }; } + +declare_lint! { + /// The `wasm_c_abi` lint detects usage of the `extern "C"` ABI of wasm that is affected + /// by a planned ABI change that has the goal of aligning Rust with the standard C ABI + /// of this target. + /// + /// ### Example + /// + /// ```rust,ignore (needs wasm32-unknown-unknown) + /// #[repr(C)] + /// struct MyType(i32, i32); + /// + /// extern "C" my_fun(x: MyType) {} + /// ``` + /// + /// This will produce: + /// + /// ```text + /// error: this function function definition is affected by the wasm ABI transition: it passes an argument of non-scalar type `MyType` + /// --> $DIR/wasm_c_abi_transition.rs:17:1 + /// | + /// | pub extern "C" fn my_fun(_x: MyType) {} + /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + /// | + /// = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + /// = note: for more information, see issue #138762 + /// = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target + /// ``` + /// + /// ### Explanation + /// + /// Rust has historically implemented a non-spec-compliant C ABI on wasm32-unknown-unknown. This + /// has caused incompatibilities with other compilers and Wasm targets. In a future version + /// of Rust, this will be fixed, and therefore code relying on the non-spec-compliant C ABI will + /// stop functioning. + pub WASM_C_ABI, + Warn, + "detects code relying on rustc's non-spec-compliant wasm C ABI", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, + reference: "issue #138762 ", + }; +} diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl index bdeab12ab503..aae2d79c1610 100644 --- a/compiler/rustc_monomorphize/messages.ftl +++ b/compiler/rustc_monomorphize/messages.ftl @@ -63,4 +63,11 @@ monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined monomorphize_unknown_cgu_collection_mode = unknown codegen-item collection mode '{$mode}', falling back to 'lazy' mode +monomorphize_wasm_c_abi_transition = + this function {$is_call -> + [true] call + *[false] definition + } involves an argument of type `{$ty}` which is affected by the wasm ABI transition + .help = the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target + monomorphize_written_to_path = the full type name has been written to '{$path}' diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index 8dafbbca905f..dffa372279f9 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -103,3 +103,12 @@ pub(crate) struct AbiRequiredTargetFeature<'a> { /// Whether this is a problem at a call site or at a declaration. pub is_call: bool, } + +#[derive(LintDiagnostic)] +#[diag(monomorphize_wasm_c_abi_transition)] +#[help] +pub(crate) struct WasmCAbiTransition<'a> { + pub ty: Ty<'a>, + /// Whether this is a problem at a call site or at a declaration. + pub is_call: bool, +} diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs index 06d6c3ab8050..f17f7261df58 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs @@ -3,11 +3,13 @@ use rustc_abi::{BackendRepr, RegKind}; use rustc_hir::CRATE_HIR_ID; use rustc_middle::mir::{self, traversal}; -use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt}; -use rustc_session::lint::builtin::ABI_UNSUPPORTED_VECTOR_TYPES; +use rustc_middle::ty::layout::LayoutCx; +use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypingEnv}; +use rustc_session::lint::builtin::{ABI_UNSUPPORTED_VECTOR_TYPES, WASM_C_ABI}; use rustc_span::def_id::DefId; use rustc_span::{DUMMY_SP, Span, Symbol, sym}; -use rustc_target::callconv::{Conv, FnAbi, PassMode}; +use rustc_target::callconv::{ArgAbi, Conv, FnAbi, PassMode}; +use rustc_target::spec::{HasWasmCAbiOpt, WasmCAbi}; use crate::errors; @@ -26,13 +28,15 @@ fn uses_vector_registers(mode: &PassMode, repr: &BackendRepr) -> bool { /// for a certain function. /// `is_call` indicates whether this is a call-site check or a definition-site check; /// this is only relevant for the wording in the emitted error. -fn do_check_abi<'tcx>( +fn do_check_simd_vector_abi<'tcx>( tcx: TyCtxt<'tcx>, abi: &FnAbi<'tcx, Ty<'tcx>>, def_id: DefId, is_call: bool, span: impl Fn() -> Span, ) { + // We check this on all functions, including those using the "Rust" ABI. + // For the "Rust" ABI it would be a bug if the lint ever triggered, but better safe than sorry. let feature_def = tcx.sess.target.features_for_correct_vector_abi(); let codegen_attrs = tcx.codegen_fn_attrs(def_id); let have_feature = |feat: Symbol| { @@ -88,6 +92,60 @@ fn do_check_abi<'tcx>( } } +fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool { + if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) { + return true; + } + + // This matches `unwrap_trivial_aggregate` in the wasm ABI logic. + if arg.layout.is_aggregate() { + let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized()); + if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) { + let size = arg.layout.size; + // Ensure there's just a single `unit` element in `arg`. + if unit.size == size { + return true; + } + } + } + + false +} + +/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the +/// ABI transition. +fn do_check_wasm_abi<'tcx>( + tcx: TyCtxt<'tcx>, + abi: &FnAbi<'tcx, Ty<'tcx>>, + is_call: bool, + span: impl Fn() -> Span, +) { + // Only proceed for `extern "C" fn` on wasm32-unknown-unknown (same check as what `adjust_for_foreign_abi` uses to call `compute_wasm_abi_info`). + if !(tcx.sess.target.arch == "wasm32" + && tcx.sess.target.os == "unknown" + && tcx.wasm_c_abi_opt() == WasmCAbi::Legacy + && abi.conv == Conv::C) + { + return; + } + // Warn against all types whose ABI will change. That's all arguments except for things passed as scalars. + // Return values are not affected by this change. + for arg_abi in abi.args.iter() { + if wasm_abi_safe(tcx, arg_abi) { + continue; + } + let span = span(); + tcx.emit_node_span_lint( + WASM_C_ABI, + CRATE_HIR_ID, + span, + errors::WasmCAbiTransition { ty: arg_abi.layout.ty, is_call }, + ); + // Let's only warn once per function. + break; + } +} + /// Checks that the ABI of a given instance of a function does not contain vector-passed arguments /// or return values for which the corresponding target feature is not enabled. fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { @@ -98,13 +156,10 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { // function. return; }; - do_check_abi( - tcx, - abi, - instance.def_id(), - /*is_call*/ false, - || tcx.def_span(instance.def_id()), - ) + do_check_simd_vector_abi(tcx, abi, instance.def_id(), /*is_call*/ false, || { + tcx.def_span(instance.def_id()) + }); + do_check_wasm_abi(tcx, abi, /*is_call*/ false, || tcx.def_span(instance.def_id())); } /// Checks that a call expression does not try to pass a vector-passed argument which requires a @@ -141,7 +196,8 @@ fn check_call_site_abi<'tcx>( // ABI failed to compute; this will not get through codegen. return; }; - do_check_abi(tcx, callee_abi, caller.def_id(), /*is_call*/ true, || span); + do_check_simd_vector_abi(tcx, callee_abi, caller.def_id(), /*is_call*/ true, || span); + do_check_wasm_abi(tcx, callee_abi, /*is_call*/ true, || span); } fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &mir::Body<'tcx>) { diff --git a/compiler/rustc_target/src/callconv/wasm.rs b/compiler/rustc_target/src/callconv/wasm.rs index 364a65511311..881168c98c32 100644 --- a/compiler/rustc_target/src/callconv/wasm.rs +++ b/compiler/rustc_target/src/callconv/wasm.rs @@ -10,6 +10,9 @@ where if val.layout.is_aggregate() { if let Some(unit) = val.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()) { let size = val.layout.size; + // This size check also catches over-aligned scalars as `size` will be rounded up to a + // multiple of the alignment, and the default alignment of all scalar types on wasm + // equals their size. if unit.size == size { val.cast_to(unit); return true; diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index 64e65ece85d6..be649029c863 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -62,7 +62,6 @@ //@[nvptx64] needs-llvm-components: nvptx #![feature(no_core, rustc_attrs, lang_items)] #![feature(unsized_fn_params, transparent_unions)] -#![no_std] #![no_core] #![allow(unused, improper_ctypes_definitions, internal_features)] diff --git a/tests/ui/lint/wasm_c_abi_transition.rs b/tests/ui/lint/wasm_c_abi_transition.rs new file mode 100644 index 000000000000..1fe81679e65d --- /dev/null +++ b/tests/ui/lint/wasm_c_abi_transition.rs @@ -0,0 +1,41 @@ +//@ compile-flags: --target wasm32-unknown-unknown +//@ needs-llvm-components: webassembly +//@ add-core-stubs +//@ build-fail + +#![feature(no_core)] +#![no_core] +#![crate_type = "lib"] +#![deny(wasm_c_abi)] + +extern crate minicore; +use minicore::*; + +pub extern "C" fn my_fun_trivial(_x: i32, _y: f32) {} + +#[repr(C)] +pub struct MyType(i32, i32); +pub extern "C" fn my_fun(_x: MyType) {} //~ERROR: wasm ABI transition +//~^WARN: previously accepted + +// This one is ABI-safe as it only wraps a single field, +// and the return type can be anything. +#[repr(C)] +pub struct MySafeType(i32); +pub extern "C" fn my_fun_safe(_x: MySafeType) -> MyType { loop {} } + +// This one not ABI-safe due to the alignment. +#[repr(C, align(16))] +pub struct MyAlignedType(i32); +pub extern "C" fn my_fun_aligned(_x: MyAlignedType) {} //~ERROR: wasm ABI transition +//~^WARN: previously accepted + +// Check call-site warning +extern "C" { + fn other_fun(x: MyType); +} + +pub fn call_other_fun(x: MyType) { + unsafe { other_fun(x) } //~ERROR: wasm ABI transition + //~^WARN: previously accepted +} diff --git a/tests/ui/lint/wasm_c_abi_transition.stderr b/tests/ui/lint/wasm_c_abi_transition.stderr new file mode 100644 index 000000000000..389710d5cb3a --- /dev/null +++ b/tests/ui/lint/wasm_c_abi_transition.stderr @@ -0,0 +1,85 @@ +error: this function definition involves an argument of type `MyType` which is affected by the wasm ABI transition + --> $DIR/wasm_c_abi_transition.rs:18:1 + | +LL | pub extern "C" fn my_fun(_x: MyType) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #138762 + = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target +note: the lint level is defined here + --> $DIR/wasm_c_abi_transition.rs:9:9 + | +LL | #![deny(wasm_c_abi)] + | ^^^^^^^^^^ + +error: this function definition involves an argument of type `MyAlignedType` which is affected by the wasm ABI transition + --> $DIR/wasm_c_abi_transition.rs:30:1 + | +LL | pub extern "C" fn my_fun_aligned(_x: MyAlignedType) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #138762 + = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target + +error: this function call involves an argument of type `MyType` which is affected by the wasm ABI transition + --> $DIR/wasm_c_abi_transition.rs:39:14 + | +LL | unsafe { other_fun(x) } + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #138762 + = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target + +error: aborting due to 3 previous errors + +Future incompatibility report: Future breakage diagnostic: +error: this function definition involves an argument of type `MyType` which is affected by the wasm ABI transition + --> $DIR/wasm_c_abi_transition.rs:18:1 + | +LL | pub extern "C" fn my_fun(_x: MyType) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #138762 + = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target +note: the lint level is defined here + --> $DIR/wasm_c_abi_transition.rs:9:9 + | +LL | #![deny(wasm_c_abi)] + | ^^^^^^^^^^ + +Future breakage diagnostic: +error: this function definition involves an argument of type `MyAlignedType` which is affected by the wasm ABI transition + --> $DIR/wasm_c_abi_transition.rs:30:1 + | +LL | pub extern "C" fn my_fun_aligned(_x: MyAlignedType) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #138762 + = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target +note: the lint level is defined here + --> $DIR/wasm_c_abi_transition.rs:9:9 + | +LL | #![deny(wasm_c_abi)] + | ^^^^^^^^^^ + +Future breakage diagnostic: +error: this function call involves an argument of type `MyType` which is affected by the wasm ABI transition + --> $DIR/wasm_c_abi_transition.rs:39:14 + | +LL | unsafe { other_fun(x) } + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #138762 + = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target +note: the lint level is defined here + --> $DIR/wasm_c_abi_transition.rs:9:9 + | +LL | #![deny(wasm_c_abi)] + | ^^^^^^^^^^ + From 072ccce553dd83ebfdf0aaf99eb24f65133c368b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 17 Mar 2025 22:59:56 +0100 Subject: [PATCH 524/745] make -Zwasm-c-abi=legacy suppress the lint --- compiler/rustc_codegen_ssa/src/mir/naked_asm.rs | 4 ++-- compiler/rustc_monomorphize/src/mono_checks/abi_check.rs | 9 +++++---- compiler/rustc_session/src/options.rs | 5 +++-- compiler/rustc_target/src/callconv/mod.rs | 2 +- compiler/rustc_target/src/spec/mod.rs | 5 ++++- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index bc9cde1b2a15..3a6b1f8d4efc 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -332,7 +332,7 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id // please also add `wasm32-unknown-unknown` back in `tests/assembly/wasm32-naked-fn.rs` // basically the commit introducing this comment should be reverted if let PassMode::Pair { .. } = fn_abi.ret.mode { - let _ = WasmCAbi::Legacy; + let _ = WasmCAbi::Legacy { with_lint: true }; span_bug!( tcx.def_span(def_id), "cannot return a pair (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666" @@ -384,7 +384,7 @@ fn wasm_type<'tcx>( BackendRepr::SimdVector { .. } => "v128", BackendRepr::Memory { .. } => { // FIXME: remove this branch once the wasm32-unknown-unknown ABI is fixed - let _ = WasmCAbi::Legacy; + let _ = WasmCAbi::Legacy { with_lint: true }; span_bug!( tcx.def_span(def_id), "cannot use memory args (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666" diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs index f17f7261df58..40740c3fdf65 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs @@ -92,6 +92,7 @@ fn do_check_simd_vector_abi<'tcx>( } } +/// Determines whether the given argument is passed the same way on the old and new wasm ABIs. fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool { if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) { return true; @@ -120,16 +121,16 @@ fn do_check_wasm_abi<'tcx>( is_call: bool, span: impl Fn() -> Span, ) { - // Only proceed for `extern "C" fn` on wasm32-unknown-unknown (same check as what `adjust_for_foreign_abi` uses to call `compute_wasm_abi_info`). + // Only proceed for `extern "C" fn` on wasm32-unknown-unknown (same check as what `adjust_for_foreign_abi` uses to call `compute_wasm_abi_info`), + // and only proceed if `wasm_c_abi_opt` indicates we should emit the lint. if !(tcx.sess.target.arch == "wasm32" && tcx.sess.target.os == "unknown" - && tcx.wasm_c_abi_opt() == WasmCAbi::Legacy + && tcx.wasm_c_abi_opt() == WasmCAbi::Legacy { with_lint: true } && abi.conv == Conv::C) { return; } - // Warn against all types whose ABI will change. That's all arguments except for things passed as scalars. - // Return values are not affected by this change. + // Warn against all types whose ABI will change. Return values are not affected by this change. for arg_abi in abi.args.iter() { if wasm_abi_safe(tcx, arg_abi) { continue; diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index b3be4b611f03..828230f2fe66 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1886,7 +1886,8 @@ pub mod parse { pub(crate) fn parse_wasm_c_abi(slot: &mut WasmCAbi, v: Option<&str>) -> bool { match v { Some("spec") => *slot = WasmCAbi::Spec, - Some("legacy") => *slot = WasmCAbi::Legacy, + // Explicitly setting the `-Z` flag suppresses the lint. + Some("legacy") => *slot = WasmCAbi::Legacy { with_lint: false }, _ => return false, } true @@ -2599,7 +2600,7 @@ written to standard error output)"), Requires `-Clto[=[fat,yes]]`"), wasi_exec_model: Option = (None, parse_wasi_exec_model, [TRACKED], "whether to build a wasi command or reactor"), - wasm_c_abi: WasmCAbi = (WasmCAbi::Legacy, parse_wasm_c_abi, [TRACKED], + wasm_c_abi: WasmCAbi = (WasmCAbi::Legacy { with_lint: true }, parse_wasm_c_abi, [TRACKED], "use spec-compliant C ABI for `wasm32-unknown-unknown` (default: legacy)"), write_long_types_to_disk: bool = (true, parse_bool, [UNTRACKED], "whether long type names should be written to files instead of being printed in errors"), diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 6d0ee3c7ee58..a52b2b76bc1e 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -705,7 +705,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { "xtensa" => xtensa::compute_abi_info(cx, self), "riscv32" | "riscv64" => riscv::compute_abi_info(cx, self), "wasm32" => { - if spec.os == "unknown" && cx.wasm_c_abi_opt() == WasmCAbi::Legacy { + if spec.os == "unknown" && matches!(cx.wasm_c_abi_opt(), WasmCAbi::Legacy { .. }) { wasm::compute_wasm_abi_info(self) } else { wasm::compute_c_abi_info(cx, self) diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 1887134c5757..1a823f47d9d9 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2234,7 +2234,10 @@ pub enum WasmCAbi { /// Spec-compliant C ABI. Spec, /// Legacy ABI. Which is non-spec-compliant. - Legacy, + Legacy { + /// Indicates whether the `wasm_c_abi` lint should be emitted. + with_lint: bool, + }, } pub trait HasWasmCAbiOpt { From 61e24e630d5eea7bbff63e46051de509ceb46c33 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 22 Mar 2025 18:42:01 +0100 Subject: [PATCH 525/745] allow wasm_c_abi in proc_macro bridge --- library/proc_macro/src/bridge/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 03c3e697cfe2..52cc8fba0438 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -7,6 +7,10 @@ //! Rust ABIs (e.g., stage0/bin/rustc vs stage1/bin/rustc during bootstrap). #![deny(unsafe_code)] +// proc_macros anyway don't work on wasm hosts so while both sides of this bridge can +// be built with different versions of rustc, the wasm ABI changes don't really matter. +#![cfg_attr(bootstrap, allow(unknown_lints))] +#![allow(wasm_c_abi)] use std::hash::Hash; use std::ops::{Bound, Range}; From f756304655b8604327f7a906c9e55b74a5fedfd1 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 10 Mar 2025 18:24:54 +0300 Subject: [PATCH 526/745] privacy: Visit types and traits in impls in type privacy lints --- compiler/rustc_privacy/src/lib.rs | 40 ++++++++++++++----- tests/ui/privacy/pub-priv-dep/pub-priv1.rs | 7 ++-- .../ui/privacy/pub-priv-dep/pub-priv1.stderr | 22 +++++++++- 3 files changed, 55 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index ed00d97c31da..643b82f47530 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -72,7 +72,9 @@ impl<'tcx> fmt::Display for LazyDefPathStr<'tcx> { pub trait DefIdVisitor<'tcx> { type Result: VisitorResult = (); const SHALLOW: bool = false; - const SKIP_ASSOC_TYS: bool = false; + fn skip_assoc_tys(&self) -> bool { + false + } fn tcx(&self) -> TyCtxt<'tcx>; fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) @@ -213,7 +215,7 @@ where } } ty::Alias(kind @ (ty::Inherent | ty::Weak | ty::Projection), data) => { - if V::SKIP_ASSOC_TYS { + if self.def_id_visitor.skip_assoc_tys() { // Visitors searching for minimal visibility/reachability want to // conservatively approximate associated types like `Type::Alias` // as visible/reachable even if `Type` is private. @@ -324,7 +326,9 @@ impl<'a, 'tcx, VL: VisibilityLike, const SHALLOW: bool> DefIdVisitor<'tcx> for FindMin<'a, 'tcx, VL, SHALLOW> { const SHALLOW: bool = SHALLOW; - const SKIP_ASSOC_TYS: bool = true; + fn skip_assoc_tys(&self) -> bool { + true + } fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -342,7 +346,7 @@ trait VisibilityLike: Sized { def_id: LocalDefId, ) -> Self; - // Returns an over-approximation (`SKIP_ASSOC_TYS` = true) of visibility due to + // Returns an over-approximation (`skip_assoc_tys()` = true) of visibility due to // associated types for which we can't determine visibility precisely. fn of_impl( def_id: LocalDefId, @@ -1352,6 +1356,7 @@ struct SearchInterfaceForPrivateItemsVisitor<'tcx> { required_effective_vis: Option, in_assoc_ty: bool, in_primary_interface: bool, + skip_assoc_tys: bool, } impl SearchInterfaceForPrivateItemsVisitor<'_> { @@ -1398,6 +1403,14 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { self } + fn trait_ref(&mut self) -> &mut Self { + self.in_primary_interface = true; + if let Some(trait_ref) = self.tcx.impl_trait_ref(self.item_def_id) { + let _ = self.visit_trait(trait_ref.instantiate_identity()); + } + self + } + fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool { if self.leaks_private_dep(def_id) { self.tcx.emit_node_span_lint( @@ -1495,6 +1508,9 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> { type Result = ControlFlow<()>; + fn skip_assoc_tys(&self) -> bool { + self.skip_assoc_tys + } fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -1531,6 +1547,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> { required_effective_vis, in_assoc_ty: false, in_primary_interface: true, + skip_assoc_tys: false, } } @@ -1726,13 +1743,18 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> { self.effective_visibilities, ); - // check that private components do not appear in the generics or predicates of inherent impls - // this check is intentionally NOT performed for impls of traits, per #90586 + let mut check = self.check(item.owner_id.def_id, impl_vis, Some(impl_ev)); + // Generics and predicates of trait impls are intentionally not checked + // for private components (#90586). if impl_.of_trait.is_none() { - self.check(item.owner_id.def_id, impl_vis, Some(impl_ev)) - .generics() - .predicates(); + check.generics().predicates(); } + // Skip checking private components in associated types, due to lack of full + // normalization they produce very ridiculous false positives. + // FIXME: Remove this when full normalization is implemented. + check.skip_assoc_tys = true; + check.ty().trait_ref(); + for impl_item_ref in impl_.items { let impl_item_vis = if impl_.of_trait.is_none() { min( diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs index 112eaf528be2..877029f3de37 100644 --- a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs +++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs @@ -77,15 +77,14 @@ pub type Alias = OtherType; pub struct PublicWithPrivateImpl; -// FIXME: This should trigger. -// See https://github.com/rust-lang/rust/issues/71043 impl OtherTrait for PublicWithPrivateImpl {} +//~^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface pub trait PubTraitOnPrivate {} -// FIXME: This should trigger. -// See https://github.com/rust-lang/rust/issues/71043 impl PubTraitOnPrivate for OtherType {} +//~^ ERROR type `OtherType` from private dependency 'priv_dep' in public interface +//~| ERROR type `OtherType` from private dependency 'priv_dep' in public interface pub struct AllowedPrivType { #[allow(exported_private_dependencies)] diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr index 53d461a5774a..adfe13424cdf 100644 --- a/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr +++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr @@ -70,5 +70,25 @@ error: type `OtherType` from private dependency 'priv_dep' in public interface LL | pub type Alias = OtherType; | ^^^^^^^^^^^^^^ -error: aborting due to 11 previous errors +error: trait `OtherTrait` from private dependency 'priv_dep' in public interface + --> $DIR/pub-priv1.rs:80:1 + | +LL | impl OtherTrait for PublicWithPrivateImpl {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: type `OtherType` from private dependency 'priv_dep' in public interface + --> $DIR/pub-priv1.rs:85:1 + | +LL | impl PubTraitOnPrivate for OtherType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: type `OtherType` from private dependency 'priv_dep' in public interface + --> $DIR/pub-priv1.rs:85:1 + | +LL | impl PubTraitOnPrivate for OtherType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 14 previous errors From 502d57cb78082efa16ed661ddfb501c189f18321 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 25 Mar 2025 09:02:28 +0000 Subject: [PATCH 527/745] Deduplicate assoc item cfg handling --- compiler/rustc_builtin_macros/src/cfg_eval.rs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index 5788966b6e7b..b3ba90731184 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -121,18 +121,11 @@ impl CfgEval<'_> { let item = parser.parse_item(ForceCollect::Yes)?.unwrap(); Annotatable::Item(self.flat_map_item(item).pop().unwrap()) } - Annotatable::AssocItem(_, AssocCtxt::Trait) => { + Annotatable::AssocItem(_, ctxt) => { let item = parser.parse_trait_item(ForceCollect::Yes)?.unwrap().unwrap(); Annotatable::AssocItem( - self.flat_map_assoc_item(item, AssocCtxt::Trait).pop().unwrap(), - AssocCtxt::Trait, - ) - } - Annotatable::AssocItem(_, AssocCtxt::Impl) => { - let item = parser.parse_impl_item(ForceCollect::Yes)?.unwrap().unwrap(); - Annotatable::AssocItem( - self.flat_map_assoc_item(item, AssocCtxt::Impl).pop().unwrap(), - AssocCtxt::Impl, + self.flat_map_assoc_item(item, ctxt).pop().unwrap(), + ctxt, ) } Annotatable::ForeignItem(_) => { From 7cdc456727fb663bf53232ec414a9001410ac843 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 25 Mar 2025 09:00:35 +0000 Subject: [PATCH 528/745] Track whether an assoc item is in a trait impl or an inherent impl --- compiler/rustc_ast/src/mut_visit.rs | 4 +- compiler/rustc_ast/src/visit.rs | 9 +- compiler/rustc_ast_lowering/src/item.rs | 31 ++---- .../rustc_ast_passes/src/ast_validation.rs | 6 +- compiler/rustc_builtin_macros/src/autodiff.rs | 6 +- compiler/rustc_expand/src/base.rs | 15 ++- compiler/rustc_expand/src/expand.rs | 101 +++++++++++++++--- compiler/rustc_expand/src/placeholders.rs | 14 ++- compiler/rustc_lint/src/early.rs | 4 +- .../rustc_resolve/src/build_reduced_graph.rs | 15 ++- compiler/rustc_resolve/src/late.rs | 4 +- compiler/rustc_resolve/src/lib.rs | 5 - compiler/rustc_resolve/src/macros.rs | 2 +- src/tools/rustfmt/src/visitor.rs | 3 +- 14 files changed, 151 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 4edd08643000..604555e2df74 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1318,7 +1318,9 @@ impl WalkItemKind for ItemKind { visit_polarity(vis, polarity); visit_opt(of_trait, |trait_ref| vis.visit_trait_ref(trait_ref)); vis.visit_ty(self_ty); - items.flat_map_in_place(|item| vis.flat_map_assoc_item(item, AssocCtxt::Impl)); + items.flat_map_in_place(|item| { + vis.flat_map_assoc_item(item, AssocCtxt::Impl { of_trait: of_trait.is_some() }) + }); } ItemKind::Trait(box Trait { safety, is_auto: _, generics, bounds, items }) => { visit_safety(vis, safety); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index ce8d6df75afb..9f6a53248089 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -23,7 +23,7 @@ use crate::ptr::P; #[derive(Copy, Clone, Debug, PartialEq)] pub enum AssocCtxt { Trait, - Impl, + Impl { of_trait: bool }, } #[derive(Copy, Clone, Debug, PartialEq)] @@ -422,7 +422,12 @@ impl WalkItemKind for ItemKind { try_visit!(visitor.visit_generics(generics)); visit_opt!(visitor, visit_trait_ref, of_trait); try_visit!(visitor.visit_ty(self_ty)); - walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Impl); + walk_list!( + visitor, + visit_assoc_item, + items, + AssocCtxt::Impl { of_trait: of_trait.is_some() } + ); } ItemKind::Struct(struct_definition, generics) | ItemKind::Union(struct_definition, generics) => { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 518349343b3a..cf7ffde83613 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -7,7 +7,6 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; use rustc_hir::{self as hir, HirId, PredicateOrigin}; use rustc_index::{IndexSlice, IndexVec}; -use rustc_middle::span_bug; use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, sym}; @@ -104,10 +103,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { } fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) { - let def_id = self.resolver.node_id_to_def_id[&item.id]; - let parent_id = self.tcx.local_parent(def_id); - let parent_hir = self.lower_node(parent_id).unwrap(); - self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt, parent_hir)) + self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt)) } fn lower_foreign_item(&mut self, item: &ForeignItem) { @@ -631,29 +627,18 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - fn lower_assoc_item( - &mut self, - item: &AssocItem, - ctxt: AssocCtxt, - parent_hir: &'hir hir::OwnerInfo<'hir>, - ) -> hir::OwnerNode<'hir> { - let parent_item = parent_hir.node().expect_item(); - match parent_item.kind { - hir::ItemKind::Impl(impl_) => { - self.is_in_trait_impl = impl_.of_trait.is_some(); - } - hir::ItemKind::Trait(..) => {} - kind => { - span_bug!(item.span, "assoc item has unexpected kind of parent: {}", kind.descr()) - } - } - + fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) -> hir::OwnerNode<'hir> { // Evaluate with the lifetimes in `params` in-scope. // This is used to track which lifetimes have already been defined, // and which need to be replicated when lowering an async fn. match ctxt { AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item)), - AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item)), + AssocCtxt::Impl { of_trait } => { + if of_trait { + self.is_in_trait_impl = of_trait; + } + hir::OwnerNode::ImplItem(self.lower_impl_item(item)) + } } } diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 75839e86b8d3..a1487ca74be8 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -860,7 +860,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { this.visit_trait_ref(t); this.visit_ty(self_ty); - walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl); + walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl { of_trait: true }); }); walk_list!(self, visit_attribute, &item.attrs); return; // Avoid visiting again. @@ -913,7 +913,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { |this| this.visit_generics(generics), ); this.visit_ty(self_ty); - walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl); + walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl { of_trait: false }); }); walk_list!(self, visit_attribute, &item.attrs); return; // Avoid visiting again. @@ -1414,7 +1414,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_defaultness(item.span, item.kind.defaultness()); } - if ctxt == AssocCtxt::Impl { + if let AssocCtxt::Impl { .. } = ctxt { match &item.kind { AssocItemKind::Const(box ConstItem { expr: None, .. }) => { self.dcx().emit_err(errors::AssocConstWithoutBody { diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index 6591ed151cf6..5cd653c79456 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -157,7 +157,7 @@ mod llvm_enzyme { }; (sig.clone(), false) } - Annotatable::AssocItem(assoc_item, _) => { + Annotatable::AssocItem(assoc_item, Impl { of_trait: false }) => { let sig = match &assoc_item.kind { ast::AssocItemKind::Fn(box ast::Fn { sig, .. }) => sig, _ => { @@ -296,7 +296,7 @@ mod llvm_enzyme { } Annotatable::Item(iitem.clone()) } - Annotatable::AssocItem(ref mut assoc_item, i @ Impl) => { + Annotatable::AssocItem(ref mut assoc_item, i @ Impl { of_trait: false }) => { if !assoc_item.attrs.iter().any(|a| same_attribute(&a.kind, &attr.kind)) { assoc_item.attrs.push(attr); } @@ -327,7 +327,7 @@ mod llvm_enzyme { kind: assoc_item, tokens: None, }); - Annotatable::AssocItem(d_fn, Impl) + Annotatable::AssocItem(d_fn, Impl { of_trait: false }) } else { let mut d_fn = ecx.item(span, d_ident, thin_vec![d_attr, inline_never], ItemKind::Fn(asdf)); diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 1dd152beb475..990d0f2e028a 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -153,7 +153,7 @@ impl Annotatable { pub fn expect_impl_item(self) -> P { match self { - Annotatable::AssocItem(i, AssocCtxt::Impl) => i, + Annotatable::AssocItem(i, AssocCtxt::Impl { .. }) => i, _ => panic!("expected Item"), } } @@ -403,6 +403,11 @@ pub trait MacResult { None } + /// Creates zero or more impl items. + fn make_trait_impl_items(self: Box) -> Option; 1]>> { + None + } + /// Creates zero or more trait items. fn make_trait_items(self: Box) -> Option; 1]>> { None @@ -516,6 +521,10 @@ impl MacResult for MacEager { self.impl_items } + fn make_trait_impl_items(self: Box) -> Option; 1]>> { + self.impl_items + } + fn make_trait_items(self: Box) -> Option; 1]>> { self.trait_items } @@ -613,6 +622,10 @@ impl MacResult for DummyResult { Some(SmallVec::new()) } + fn make_trait_impl_items(self: Box) -> Option; 1]>> { + Some(SmallVec::new()) + } + fn make_trait_items(self: Box) -> Option; 1]>> { Some(SmallVec::new()) } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index e2a557528504..d0bd8a89d9bd 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -188,9 +188,15 @@ ast_fragments! { ImplItems(SmallVec<[P; 1]>) { "impl item"; many fn flat_map_assoc_item; - fn visit_assoc_item(AssocCtxt::Impl); + fn visit_assoc_item(AssocCtxt::Impl { of_trait: false }); fn make_impl_items; } + TraitImplItems(SmallVec<[P; 1]>) { + "impl item"; + many fn flat_map_assoc_item; + fn visit_assoc_item(AssocCtxt::Impl { of_trait: true }); + fn make_trait_impl_items; + } ForeignItems(SmallVec<[P; 1]>) { "foreign item"; many fn flat_map_foreign_item; @@ -257,6 +263,7 @@ impl AstFragmentKind { AstFragmentKind::Items | AstFragmentKind::TraitItems | AstFragmentKind::ImplItems + | AstFragmentKind::TraitImplItems | AstFragmentKind::ForeignItems | AstFragmentKind::Crate => SupportsMacroExpansion::Yes { supports_inner_attrs: true }, AstFragmentKind::Arms @@ -306,6 +313,9 @@ impl AstFragmentKind { AstFragmentKind::ImplItems => { AstFragment::ImplItems(items.map(Annotatable::expect_impl_item).collect()) } + AstFragmentKind::TraitImplItems => { + AstFragment::TraitImplItems(items.map(Annotatable::expect_impl_item).collect()) + } AstFragmentKind::TraitItems => { AstFragment::TraitItems(items.map(Annotatable::expect_trait_item).collect()) } @@ -347,10 +357,10 @@ pub enum InvocationKind { }, Attr { attr: ast::Attribute, - // Re-insertion position for inert attributes. + /// Re-insertion position for inert attributes. pos: usize, item: Annotatable, - // Required for resolving derive helper attributes. + /// Required for resolving derive helper attributes. derives: Vec, }, Derive { @@ -360,6 +370,8 @@ pub enum InvocationKind { }, GlobDelegation { item: P, + /// Whether this is a trait impl or an inherent impl + of_trait: bool, }, } @@ -388,7 +400,7 @@ impl Invocation { InvocationKind::Bang { span, .. } => *span, InvocationKind::Attr { attr, .. } => attr.span, InvocationKind::Derive { path, .. } => path.span, - InvocationKind::GlobDelegation { item } => item.span, + InvocationKind::GlobDelegation { item, .. } => item.span, } } @@ -397,7 +409,7 @@ impl Invocation { InvocationKind::Bang { span, .. } => span, InvocationKind::Attr { attr, .. } => &mut attr.span, InvocationKind::Derive { path, .. } => &mut path.span, - InvocationKind::GlobDelegation { item } => &mut item.span, + InvocationKind::GlobDelegation { item, .. } => &mut item.span, } } } @@ -820,7 +832,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } _ => unreachable!(), }, - InvocationKind::GlobDelegation { item } => { + InvocationKind::GlobDelegation { item, of_trait } => { let AssocItemKind::DelegationMac(deleg) = &item.kind else { unreachable!() }; let suffixes = match ext { SyntaxExtensionKind::GlobDelegation(expander) => match expander.expand(self.cx) @@ -829,7 +841,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { ExpandResult::Retry(()) => { // Reassemble the original invocation for retrying. return ExpandResult::Retry(Invocation { - kind: InvocationKind::GlobDelegation { item }, + kind: InvocationKind::GlobDelegation { item, of_trait }, ..invoc }); } @@ -847,7 +859,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx, deleg, &item, &suffixes, item.span, true, ); fragment_kind.expect_from_annotatables( - single_delegations.map(|item| Annotatable::AssocItem(P(item), AssocCtxt::Impl)), + single_delegations + .map(|item| Annotatable::AssocItem(P(item), AssocCtxt::Impl { of_trait })), ) } }) @@ -973,6 +986,13 @@ pub fn parse_ast_fragment<'a>( } AstFragment::ImplItems(items) } + AstFragmentKind::TraitImplItems => { + let mut items = SmallVec::new(); + while let Some(item) = this.parse_impl_item(ForceCollect::No)? { + items.extend(item); + } + AstFragment::TraitImplItems(items) + } AstFragmentKind::ForeignItems => { let mut items = SmallVec::new(); while let Some(item) = this.parse_foreign_item(ForceCollect::No)? { @@ -1355,13 +1375,13 @@ impl InvocationCollectorNode for AstNodeWrapper, ImplItemTag> type ItemKind = AssocItemKind; const KIND: AstFragmentKind = AstFragmentKind::ImplItems; fn to_annotatable(self) -> Annotatable { - Annotatable::AssocItem(self.wrapped, AssocCtxt::Impl) + Annotatable::AssocItem(self.wrapped, AssocCtxt::Impl { of_trait: false }) } fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { fragment.make_impl_items() } fn walk_flat_map(self, visitor: &mut V) -> Self::OutputTy { - walk_flat_map_assoc_item(visitor, self.wrapped, AssocCtxt::Impl) + walk_flat_map_assoc_item(visitor, self.wrapped, AssocCtxt::Impl { of_trait: false }) } fn is_mac_call(&self) -> bool { matches!(self.wrapped.kind, AssocItemKind::MacCall(..)) @@ -1390,6 +1410,47 @@ impl InvocationCollectorNode for AstNodeWrapper, ImplItemTag> } } +struct TraitImplItemTag; +impl InvocationCollectorNode for AstNodeWrapper, TraitImplItemTag> { + type OutputTy = SmallVec<[P; 1]>; + type ItemKind = AssocItemKind; + const KIND: AstFragmentKind = AstFragmentKind::TraitImplItems; + fn to_annotatable(self) -> Annotatable { + Annotatable::AssocItem(self.wrapped, AssocCtxt::Impl { of_trait: true }) + } + fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { + fragment.make_trait_impl_items() + } + fn walk_flat_map(self, visitor: &mut V) -> Self::OutputTy { + walk_flat_map_assoc_item(visitor, self.wrapped, AssocCtxt::Impl { of_trait: true }) + } + fn is_mac_call(&self) -> bool { + matches!(self.wrapped.kind, AssocItemKind::MacCall(..)) + } + fn take_mac_call(self) -> (P, Self::AttrsTy, AddSemicolon) { + let item = self.wrapped.into_inner(); + match item.kind { + AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No), + _ => unreachable!(), + } + } + fn delegation(&self) -> Option<(&ast::DelegationMac, &ast::Item)> { + match &self.wrapped.kind { + AssocItemKind::DelegationMac(deleg) => Some((deleg, &self.wrapped)), + _ => None, + } + } + fn delegation_item_kind(deleg: Box) -> Self::ItemKind { + AssocItemKind::Delegation(deleg) + } + fn from_item(item: ast::Item) -> Self { + AstNodeWrapper::new(P(item), TraitImplItemTag) + } + fn flatten_outputs(items: impl Iterator) -> Self::OutputTy { + items.flatten().collect() + } +} + impl InvocationCollectorNode for P { const KIND: AstFragmentKind = AstFragmentKind::ForeignItems; fn to_annotatable(self) -> Annotatable { @@ -1855,9 +1916,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { fn collect_glob_delegation( &mut self, item: P, + of_trait: bool, kind: AstFragmentKind, ) -> AstFragment { - self.collect(kind, InvocationKind::GlobDelegation { item }) + self.collect(kind, InvocationKind::GlobDelegation { item, of_trait }) } /// If `item` is an attribute invocation, remove the attribute and return it together with @@ -2030,8 +2092,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { let Some(suffixes) = &deleg.suffixes else { let traitless_qself = matches!(&deleg.qself, Some(qself) if qself.position == 0); - let item = match node.to_annotatable() { - Annotatable::AssocItem(item, AssocCtxt::Impl) => item, + let (item, of_trait) = match node.to_annotatable() { + Annotatable::AssocItem(item, AssocCtxt::Impl { of_trait }) => { + (item, of_trait) + } ann @ (Annotatable::Item(_) | Annotatable::AssocItem(..) | Annotatable::Stmt(_)) => { @@ -2046,7 +2110,9 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { self.cx.dcx().emit_err(GlobDelegationTraitlessQpath { span }); return Default::default(); } - return self.collect_glob_delegation(item, Node::KIND).make_ast::(); + return self + .collect_glob_delegation(item, of_trait, Node::KIND) + .make_ast::(); }; let single_delegations = build_single_delegations::( @@ -2126,7 +2192,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { ) -> SmallVec<[P; 1]> { match ctxt { AssocCtxt::Trait => self.flat_map_node(AstNodeWrapper::new(node, TraitItemTag)), - AssocCtxt::Impl => self.flat_map_node(AstNodeWrapper::new(node, ImplItemTag)), + AssocCtxt::Impl { of_trait: false } => { + self.flat_map_node(AstNodeWrapper::new(node, ImplItemTag)) + } + AssocCtxt::Impl { of_trait: true } => { + self.flat_map_node(AstNodeWrapper::new(node, TraitImplItemTag)) + } } } diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 3a470924c7f6..a60a87244cc6 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -86,6 +86,17 @@ pub(crate) fn placeholder( kind: ast::AssocItemKind::MacCall(mac_placeholder()), tokens: None, })]), + AstFragmentKind::TraitImplItems => { + AstFragment::TraitImplItems(smallvec![P(ast::AssocItem { + id, + span, + ident, + vis, + attrs, + kind: ast::AssocItemKind::MacCall(mac_placeholder()), + tokens: None, + })]) + } AstFragmentKind::ForeignItems => { AstFragment::ForeignItems(smallvec![P(ast::ForeignItem { id, @@ -308,7 +319,8 @@ impl MutVisitor for PlaceholderExpander { let it = self.remove(item.id); match ctxt { AssocCtxt::Trait => it.make_trait_items(), - AssocCtxt::Impl => it.make_impl_items(), + AssocCtxt::Impl { of_trait: false } => it.make_impl_items(), + AssocCtxt::Impl { of_trait: true } => it.make_trait_impl_items(), } } _ => walk_flat_map_assoc_item(self, item, ctxt), diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 723b894c43bc..f9601fa5ef1d 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -241,7 +241,7 @@ impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast> ast_visit::AssocCtxt::Trait => { lint_callback!(cx, check_trait_item, item); } - ast_visit::AssocCtxt::Impl => { + ast_visit::AssocCtxt::Impl { .. } => { lint_callback!(cx, check_impl_item, item); } } @@ -250,7 +250,7 @@ impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast> ast_visit::AssocCtxt::Trait => { lint_callback!(cx, check_trait_item_post, item); } - ast_visit::AssocCtxt::Impl => { + ast_visit::AssocCtxt::Impl { .. } => { lint_callback!(cx, check_impl_item_post, item); } } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 763e9207a126..2e70019ba8ad 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -884,10 +884,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } // These items do not add names to modules. - ItemKind::Impl(box Impl { of_trait: Some(..), .. }) => { - self.r.trait_impl_items.insert(local_def_id); - } - ItemKind::Impl { .. } | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {} + ItemKind::Impl(box Impl { of_trait: Some(..), .. }) + | ItemKind::Impl { .. } + | ItemKind::ForeignMod(..) + | ItemKind::GlobalAsm(..) => {} ItemKind::MacroDef(..) | ItemKind::MacCall(_) | ItemKind::DelegationMac(..) => { unreachable!() @@ -1378,7 +1378,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { AssocCtxt::Trait => { self.visit_invoc_in_module(item.id); } - AssocCtxt::Impl => { + AssocCtxt::Impl { .. } => { let invoc_id = item.id.placeholder_to_expn_id(); if !self.r.glob_delegation_invoc_ids.contains(&invoc_id) { self.r @@ -1398,9 +1398,8 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { let local_def_id = feed.key(); let def_id = local_def_id.to_def_id(); - if !(ctxt == AssocCtxt::Impl - && matches!(item.vis.kind, ast::VisibilityKind::Inherited) - && self.r.trait_impl_items.contains(&self.r.tcx.local_parent(local_def_id))) + if !(matches!(ctxt, AssocCtxt::Impl { of_trait: true }) + && matches!(item.vis.kind, ast::VisibilityKind::Inherited)) { // Trait impl item visibility is inherited from its trait when not specified // explicitly. In that case we cannot determine it here in early resolve, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index e04d0083548b..177a2d00ac3c 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3376,7 +3376,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { |i, s, c| MethodNotMemberOfTrait(i, s, c), ); - visit::walk_assoc_item(this, item, AssocCtxt::Impl) + visit::walk_assoc_item(this, item, AssocCtxt::Impl { of_trait: true }) }, ); @@ -3410,7 +3410,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { |i, s, c| TypeNotMemberOfTrait(i, s, c), ); - visit::walk_assoc_item(this, item, AssocCtxt::Impl) + visit::walk_assoc_item(this, item, AssocCtxt::Impl { of_trait: true }) }); }, ); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index ff31af0025b5..e37acdd1ce72 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1191,10 +1191,6 @@ pub struct Resolver<'ra, 'tcx> { /// and how the `impl Trait` fragments were introduced. invocation_parents: FxHashMap, - /// Some way to know that we are in a *trait* impl in `visit_assoc_item`. - /// FIXME: Replace with a more general AST map (together with some other fields). - trait_impl_items: FxHashSet, - legacy_const_generic_args: FxHashMap>>, /// Amount of lifetime parameters for each item in the crate. item_generics_num_lifetimes: FxHashMap, @@ -1558,7 +1554,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { def_id_to_node_id, placeholder_field_indices: Default::default(), invocation_parents, - trait_impl_items: Default::default(), legacy_const_generic_args: Default::default(), item_generics_num_lifetimes: Default::default(), main_def: Default::default(), diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 34441d313f59..aef98330e17e 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -264,7 +264,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { } InvocationKind::Bang { ref mac, .. } => (&mac.path, MacroKind::Bang), InvocationKind::Derive { ref path, .. } => (path, MacroKind::Derive), - InvocationKind::GlobDelegation { ref item } => { + InvocationKind::GlobDelegation { ref item, .. } => { let ast::AssocItemKind::DelegationMac(deleg) = &item.kind else { unreachable!() }; deleg_impl = Some(self.invocation_parent(invoc_id)); // It is sufficient to consider glob delegation a bang macro for now. diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index a5cfc542a17c..5749d8c63faf 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -624,7 +624,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // TODO(calebcartwright): Not sure the skip spans are correct let (ai, skip_span, assoc_ctxt) = match visitor_kind { AssocTraitItem(ai) => (*ai, ai.span(), visit::AssocCtxt::Trait), - AssocImplItem(ai) => (*ai, ai.span, visit::AssocCtxt::Impl), + // There is no difference between trait and inherent assoc item formatting + AssocImplItem(ai) => (*ai, ai.span, visit::AssocCtxt::Impl { of_trait: false }), _ => unreachable!(), }; skip_out_of_file_lines_range_visitor!(self, ai.span); From e88c49c454b965c4c60edf19d1305087c9758a29 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 25 Mar 2025 11:28:16 +0100 Subject: [PATCH 529/745] acquire more accurate HirId for ABI check lints --- .../src/mono_checks/abi_check.rs | 56 ++++++++++++------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs index 40740c3fdf65..0f5bdc8d7683 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs @@ -1,8 +1,8 @@ //! This module ensures that if a function's ABI requires a particular target feature, //! that target feature is enabled both on the callee and all callers. use rustc_abi::{BackendRepr, RegKind}; -use rustc_hir::CRATE_HIR_ID; -use rustc_middle::mir::{self, traversal}; +use rustc_hir::{CRATE_HIR_ID, HirId}; +use rustc_middle::mir::{self, Location, traversal}; use rustc_middle::ty::layout::LayoutCx; use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypingEnv}; use rustc_session::lint::builtin::{ABI_UNSUPPORTED_VECTOR_TYPES, WASM_C_ABI}; @@ -33,7 +33,7 @@ fn do_check_simd_vector_abi<'tcx>( abi: &FnAbi<'tcx, Ty<'tcx>>, def_id: DefId, is_call: bool, - span: impl Fn() -> Span, + loc: impl Fn() -> (Span, HirId), ) { // We check this on all functions, including those using the "Rust" ABI. // For the "Rust" ABI it would be a bug if the lint ever triggered, but better safe than sorry. @@ -50,10 +50,10 @@ fn do_check_simd_vector_abi<'tcx>( let feature = match feature_def.iter().find(|(bits, _)| size.bits() <= *bits) { Some((_, feature)) => feature, None => { - let span = span(); + let (span, hir_id) = loc(); tcx.emit_node_span_lint( ABI_UNSUPPORTED_VECTOR_TYPES, - CRATE_HIR_ID, + hir_id, span, errors::AbiErrorUnsupportedVectorType { span, @@ -66,10 +66,10 @@ fn do_check_simd_vector_abi<'tcx>( }; if !have_feature(Symbol::intern(feature)) { // Emit error. - let span = span(); + let (span, hir_id) = loc(); tcx.emit_node_span_lint( ABI_UNSUPPORTED_VECTOR_TYPES, - CRATE_HIR_ID, + hir_id, span, errors::AbiErrorDisabledVectorType { span, @@ -83,8 +83,9 @@ fn do_check_simd_vector_abi<'tcx>( } // The `vectorcall` ABI is special in that it requires SSE2 no matter which types are being passed. if abi.conv == Conv::X86VectorCall && !have_feature(sym::sse2) { + let (span, _hir_id) = loc(); tcx.dcx().emit_err(errors::AbiRequiredTargetFeature { - span: span(), + span, required_feature: "sse2", abi: "vectorcall", is_call, @@ -119,7 +120,7 @@ fn do_check_wasm_abi<'tcx>( tcx: TyCtxt<'tcx>, abi: &FnAbi<'tcx, Ty<'tcx>>, is_call: bool, - span: impl Fn() -> Span, + loc: impl Fn() -> (Span, HirId), ) { // Only proceed for `extern "C" fn` on wasm32-unknown-unknown (same check as what `adjust_for_foreign_abi` uses to call `compute_wasm_abi_info`), // and only proceed if `wasm_c_abi_opt` indicates we should emit the lint. @@ -135,10 +136,10 @@ fn do_check_wasm_abi<'tcx>( if wasm_abi_safe(tcx, arg_abi) { continue; } - let span = span(); + let (span, hir_id) = loc(); tcx.emit_node_span_lint( WASM_C_ABI, - CRATE_HIR_ID, + hir_id, span, errors::WasmCAbiTransition { ty: arg_abi.layout.ty, is_call }, ); @@ -157,10 +158,15 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { // function. return; }; - do_check_simd_vector_abi(tcx, abi, instance.def_id(), /*is_call*/ false, || { - tcx.def_span(instance.def_id()) - }); - do_check_wasm_abi(tcx, abi, /*is_call*/ false, || tcx.def_span(instance.def_id())); + let loc = || { + let def_id = instance.def_id(); + ( + tcx.def_span(def_id), + def_id.as_local().map(|did| tcx.local_def_id_to_hir_id(did)).unwrap_or(CRATE_HIR_ID), + ) + }; + do_check_simd_vector_abi(tcx, abi, instance.def_id(), /*is_call*/ false, loc); + do_check_wasm_abi(tcx, abi, /*is_call*/ false, loc); } /// Checks that a call expression does not try to pass a vector-passed argument which requires a @@ -168,8 +174,8 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { fn check_call_site_abi<'tcx>( tcx: TyCtxt<'tcx>, callee: Ty<'tcx>, - span: Span, caller: InstanceKind<'tcx>, + loc: impl Fn() -> (Span, HirId) + Copy, ) { if callee.fn_sig(tcx).abi().is_rustic_abi() { // we directly handle the soundness of Rust ABIs @@ -197,8 +203,8 @@ fn check_call_site_abi<'tcx>( // ABI failed to compute; this will not get through codegen. return; }; - do_check_simd_vector_abi(tcx, callee_abi, caller.def_id(), /*is_call*/ true, || span); - do_check_wasm_abi(tcx, callee_abi, /*is_call*/ true, || span); + do_check_simd_vector_abi(tcx, callee_abi, caller.def_id(), /*is_call*/ true, loc); + do_check_wasm_abi(tcx, callee_abi, /*is_call*/ true, loc); } fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &mir::Body<'tcx>) { @@ -214,7 +220,19 @@ fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &m ty::TypingEnv::fully_monomorphized(), ty::EarlyBinder::bind(callee_ty), ); - check_call_site_abi(tcx, callee_ty, *fn_span, body.source.instance); + check_call_site_abi(tcx, callee_ty, body.source.instance, || { + let loc = Location { + block: bb, + statement_index: body.basic_blocks[bb].statements.len(), + }; + ( + *fn_span, + body.source_info(loc) + .scope + .lint_root(&body.source_scopes) + .unwrap_or(CRATE_HIR_ID), + ) + }); } _ => {} } From 8524a7c4b7faab823f7e03d012b365bb05b82654 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Tue, 25 Mar 2025 10:31:05 +0000 Subject: [PATCH 530/745] Fix UWP reparse point check --- library/std/src/sys/fs/windows.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index 06bba019393a..15727c996837 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -547,7 +547,7 @@ impl File { ))?; attr.file_size = info.AllocationSize as u64; attr.number_of_links = Some(info.NumberOfLinks); - if attr.file_type().is_reparse_point() { + if attr.attributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 { let mut attr_tag: c::FILE_ATTRIBUTE_TAG_INFO = mem::zeroed(); cvt(c::GetFileInformationByHandleEx( self.handle.as_raw_handle(), From 59e3380744d84c16c23e8d74438c515839306f99 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 25 Mar 2025 10:17:44 +0000 Subject: [PATCH 531/745] Avoid some more global state --- compiler/rustc_ast_lowering/src/delegation.rs | 16 ++++++-- compiler/rustc_ast_lowering/src/item.rs | 39 +++++++++++-------- compiler/rustc_ast_lowering/src/lib.rs | 2 - 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index efc1fa05c5f9..f7640c602d6f 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -61,8 +61,14 @@ pub(crate) struct DelegationResults<'hir> { impl<'hir> LoweringContext<'_, 'hir> { /// Defines whether the delegatee is an associated function whose first parameter is `self`. - pub(crate) fn delegatee_is_method(&self, item_id: NodeId, path_id: NodeId, span: Span) -> bool { - let sig_id = self.get_delegation_sig_id(item_id, path_id, span); + pub(crate) fn delegatee_is_method( + &self, + item_id: NodeId, + path_id: NodeId, + span: Span, + is_in_trait_impl: bool, + ) -> bool { + let sig_id = self.get_delegation_sig_id(item_id, path_id, span, is_in_trait_impl); let Ok(sig_id) = sig_id else { return false; }; @@ -88,9 +94,10 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, delegation: &Delegation, item_id: NodeId, + is_in_trait_impl: bool, ) -> DelegationResults<'hir> { let span = self.lower_span(delegation.path.segments.last().unwrap().ident.span); - let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span); + let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span, is_in_trait_impl); match sig_id { Ok(sig_id) => { let (param_count, c_variadic) = self.param_count(sig_id); @@ -110,8 +117,9 @@ impl<'hir> LoweringContext<'_, 'hir> { item_id: NodeId, path_id: NodeId, span: Span, + is_in_trait_impl: bool, ) -> Result { - let sig_id = if self.is_in_trait_impl { item_id } else { path_id }; + let sig_id = if is_in_trait_impl { item_id } else { path_id }; self.get_resolution_id(sig_id, span) } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index cf7ffde83613..2b4b379525bc 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -404,10 +404,11 @@ impl<'hir> LoweringContext<'_, 'hir> { (trait_ref, lowered_ty) }); - self.is_in_trait_impl = trait_ref.is_some(); - let new_impl_items = self - .arena - .alloc_from_iter(impl_items.iter().map(|item| self.lower_impl_item_ref(item))); + let new_impl_items = self.arena.alloc_from_iter( + impl_items + .iter() + .map(|item| self.lower_impl_item_ref(item, trait_ref.is_some())), + ); // `defaultness.has_value()` is never called for an `impl`, always `true` in order // to not cause an assertion failure inside the `lower_defaultness` function. @@ -484,7 +485,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ItemKind::Delegation(box delegation) => { debug_assert_ne!(ident.name, kw::Empty); let ident = self.lower_ident(ident); - let delegation_results = self.lower_delegation(delegation, id); + let delegation_results = self.lower_delegation(delegation, id, false); hir::ItemKind::Fn { ident, sig: delegation_results.sig, @@ -634,10 +635,7 @@ impl<'hir> LoweringContext<'_, 'hir> { match ctxt { AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item)), AssocCtxt::Impl { of_trait } => { - if of_trait { - self.is_in_trait_impl = of_trait; - } - hir::OwnerNode::ImplItem(self.lower_impl_item(item)) + hir::OwnerNode::ImplItem(self.lower_impl_item(item, of_trait)) } } } @@ -879,7 +877,7 @@ impl<'hir> LoweringContext<'_, 'hir> { (generics, kind, ty.is_some()) } AssocItemKind::Delegation(box delegation) => { - let delegation_results = self.lower_delegation(delegation, i.id); + let delegation_results = self.lower_delegation(delegation, i.id, false); let item_kind = hir::TraitItemKind::Fn( delegation_results.sig, hir::TraitFn::Provided(delegation_results.body_id), @@ -910,7 +908,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::AssocItemKind::Fn { has_self: sig.decl.has_self() } } AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn { - has_self: self.delegatee_is_method(i.id, delegation.id, i.span), + has_self: self.delegatee_is_method(i.id, delegation.id, i.span, false), }, AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => { panic!("macros should have been expanded by now") @@ -930,7 +928,11 @@ impl<'hir> LoweringContext<'_, 'hir> { self.expr(span, hir::ExprKind::Err(guar)) } - fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> { + fn lower_impl_item( + &mut self, + i: &AssocItem, + is_in_trait_impl: bool, + ) -> &'hir hir::ImplItem<'hir> { debug_assert_ne!(i.ident.name, kw::Empty); // Since `default impl` is not yet implemented, this is always true in impls. let has_value = true; @@ -966,7 +968,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, sig, i.id, - if self.is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent }, + if is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent }, sig.header.coroutine_kind, attrs, ); @@ -1006,7 +1008,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) } AssocItemKind::Delegation(box delegation) => { - let delegation_results = self.lower_delegation(delegation, i.id); + let delegation_results = self.lower_delegation(delegation, i.id, is_in_trait_impl); ( delegation_results.generics, hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id), @@ -1029,7 +1031,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.arena.alloc(item) } - fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef { + fn lower_impl_item_ref(&mut self, i: &AssocItem, is_in_trait_impl: bool) -> hir::ImplItemRef { hir::ImplItemRef { id: hir::ImplItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }, ident: self.lower_ident(i.ident), @@ -1041,7 +1043,12 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::AssocItemKind::Fn { has_self: sig.decl.has_self() } } AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn { - has_self: self.delegatee_is_method(i.id, delegation.id, i.span), + has_self: self.delegatee_is_method( + i.id, + delegation.id, + i.span, + is_in_trait_impl, + ), }, AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => { panic!("macros should have been expanded by now") diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e08850da4a7a..32e20f3f6f25 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -121,7 +121,6 @@ struct LoweringContext<'a, 'hir> { catch_scope: Option, loop_scope: Option, is_in_loop_condition: bool, - is_in_trait_impl: bool, is_in_dyn_type: bool, current_hir_id_owner: hir::OwnerId, @@ -173,7 +172,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { catch_scope: None, loop_scope: None, is_in_loop_condition: false, - is_in_trait_impl: false, is_in_dyn_type: false, coroutine_kind: None, task_context: None, From 6bea9c7a5465e27efbadced28322e6faf78bb174 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Mar 2025 12:50:47 +1100 Subject: [PATCH 532/745] rustdoc: remove useless `Symbol::is_empty` checks. There are a number of `is_empty` checks that can never fail. This commit removes them. --- src/librustdoc/clean/inline.rs | 12 +----- src/librustdoc/formats/cache.rs | 2 +- src/librustdoc/html/render/sidebar.rs | 62 ++++++++++++++++----------- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index e973b89b2375..4fd669ab6d13 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -211,17 +211,7 @@ pub(crate) fn load_attrs<'hir>(cx: &DocContext<'hir>, did: DefId) -> &'hir [hir: } pub(crate) fn item_relative_path(tcx: TyCtxt<'_>, def_id: DefId) -> Vec { - tcx.def_path(def_id) - .data - .into_iter() - .filter_map(|elem| { - // extern blocks (and a few others things) have an empty name. - match elem.data.get_opt_name() { - Some(s) if !s.is_empty() => Some(s), - _ => None, - } - }) - .collect() + tcx.def_path(def_id).data.into_iter().filter_map(|elem| elem.data.get_opt_name()).collect() } /// Record an external fully qualified name in the external_paths cache. diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 2648641e53e7..e74fd67fbdaf 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -288,7 +288,7 @@ impl DocFolder for CacheBuilder<'_, '_> { // Keep track of the fully qualified path for this item. let pushed = match item.name { - Some(n) if !n.is_empty() => { + Some(n) => { self.cache.stack.push(n); true } diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 3130815af0bd..79719f008645 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -731,20 +731,20 @@ fn get_methods<'a>( ) -> Vec> { i.items .iter() - .filter_map(|item| match item.name { - Some(ref name) if !name.is_empty() && item.is_method() => { - if !for_deref || super::should_render_item(item, deref_mut, tcx) { - Some(Link::new( - get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::Method)), - name.as_str(), - )) - } else { - None - } + .filter_map(|item| { + if let Some(ref name) = item.name + && item.is_method() + && (!for_deref || super::should_render_item(item, deref_mut, tcx)) + { + Some(Link::new( + get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::Method)), + name.as_str(), + )) + } else { + None } - _ => None, }) - .collect::>() + .collect() } fn get_associated_constants<'a>( @@ -753,14 +753,19 @@ fn get_associated_constants<'a>( ) -> Vec> { i.items .iter() - .filter_map(|item| match item.name { - Some(ref name) if !name.is_empty() && item.is_associated_const() => Some(Link::new( - get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::AssocConst)), - name.as_str(), - )), - _ => None, + .filter_map(|item| { + if let Some(ref name) = item.name + && item.is_associated_const() + { + Some(Link::new( + get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::AssocConst)), + name.as_str(), + )) + } else { + None + } }) - .collect::>() + .collect() } fn get_associated_types<'a>( @@ -769,12 +774,17 @@ fn get_associated_types<'a>( ) -> Vec> { i.items .iter() - .filter_map(|item| match item.name { - Some(ref name) if !name.is_empty() && item.is_associated_type() => Some(Link::new( - get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::AssocType)), - name.as_str(), - )), - _ => None, + .filter_map(|item| { + if let Some(ref name) = item.name + && item.is_associated_type() + { + Some(Link::new( + get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::AssocType)), + name.as_str(), + )) + } else { + None + } }) - .collect::>() + .collect() } From 6df2d589338945e663a3a798a60db17db5f805b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 25 Mar 2025 12:37:52 +0100 Subject: [PATCH 533/745] Add function for linearizing `BuildStep` substeps --- src/build_helper/src/metrics.rs | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/build_helper/src/metrics.rs b/src/build_helper/src/metrics.rs index b6daac32a441..4ab61245c16b 100644 --- a/src/build_helper/src/metrics.rs +++ b/src/build_helper/src/metrics.rs @@ -156,25 +156,30 @@ impl BuildStep { child.find_by_type(r#type, result); } } + + /// Returns a Vec with all substeps, ordered by their hierarchical order. + /// The first element of the tuple is the depth of a given step. + fn linearize_steps(&self) -> Vec<(u32, &BuildStep)> { + let mut substeps: Vec<(u32, &BuildStep)> = Vec::new(); + + fn visit<'a>(step: &'a BuildStep, level: u32, substeps: &mut Vec<(u32, &'a BuildStep)>) { + substeps.push((level, step)); + for child in &step.children { + visit(child, level + 1, substeps); + } + } + + visit(self, 0, &mut substeps); + substeps + } } /// Writes build steps into a nice indented table. pub fn format_build_steps(root: &BuildStep) -> String { use std::fmt::Write; - let mut substeps: Vec<(u32, &BuildStep)> = Vec::new(); - - fn visit<'a>(step: &'a BuildStep, level: u32, substeps: &mut Vec<(u32, &'a BuildStep)>) { - substeps.push((level, step)); - for child in &step.children { - visit(child, level + 1, substeps); - } - } - - visit(root, 0, &mut substeps); - let mut output = String::new(); - for (level, step) in substeps { + for (level, step) in root.linearize_steps() { let label = format!( "{}{}", ".".repeat(level as usize), From 82796dd8585c0c160fe2a50b12f77455a7e0f8d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Mon, 24 Mar 2025 00:01:30 +0100 Subject: [PATCH 534/745] Brace-ident-colon can certainly no longer start a block thanks to the removal of type ascription. --- compiler/rustc_parse/src/parser/expr.rs | 14 +--- tests/ui/parser/issues/issue-111692.rs | 10 ++- tests/ui/parser/issues/issue-111692.stderr | 30 +++---- ...-call-on-struct-literal-in-if-condition.rs | 2 +- ...l-on-struct-literal-in-if-condition.stderr | 4 +- tests/ui/parser/type-ascription-in-pattern.rs | 9 +-- .../parser/type-ascription-in-pattern.stderr | 80 ++++++++++++++----- 7 files changed, 88 insertions(+), 61 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index c48f91643e88..79d12ed4bbed 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -3474,19 +3474,9 @@ impl<'a> Parser<'a> { } fn is_certainly_not_a_block(&self) -> bool { + // `{ ident, ` and `{ ident: ` cannot start a block. self.look_ahead(1, |t| t.is_ident()) - && ( - // `{ ident, ` cannot start a block. - self.look_ahead(2, |t| t == &token::Comma) - || self.look_ahead(2, |t| t == &token::Colon) - && ( - // `{ ident: token, ` cannot start a block. - self.look_ahead(4, |t| t == &token::Comma) - // `{ ident: ` cannot start a block unless it's a type ascription - // `ident: Type`. - || self.look_ahead(3, |t| !t.can_begin_type()) - ) - ) + && self.look_ahead(2, |t| t == &token::Comma || t == &token::Colon) } fn maybe_parse_struct_expr( diff --git a/tests/ui/parser/issues/issue-111692.rs b/tests/ui/parser/issues/issue-111692.rs index 56096f706a8a..de6de2227549 100644 --- a/tests/ui/parser/issues/issue-111692.rs +++ b/tests/ui/parser/issues/issue-111692.rs @@ -9,23 +9,25 @@ mod module { } fn test(x: module::Type) { - if x == module::Type { x: module::C, y: 1 } { //~ ERROR invalid struct literal + if x == module::Type { x: module::C, y: 1 } { //~ ERROR struct literals are not allowed here } } fn test2(x: module::Type) { - if x ==module::Type { x: module::C, y: 1 } { //~ ERROR invalid struct literal + if x ==module::Type { x: module::C, y: 1 } { //~ ERROR struct literals are not allowed here } } fn test3(x: module::Type) { - if x == Type { x: module::C, y: 1 } { //~ ERROR invalid struct literal + use module::Type; + if x == Type { x: module::C, y: 1 } { //~ ERROR struct literals are not allowed here } } fn test4(x: module::Type) { - if x == demo_module::Type { x: module::C, y: 1 } { //~ ERROR invalid struct literal + use module as demo_module; + if x == demo_module::Type { x: module::C, y: 1 } { //~ ERROR struct literals are not allowed here } } diff --git a/tests/ui/parser/issues/issue-111692.stderr b/tests/ui/parser/issues/issue-111692.stderr index 068b0483b0fd..979dfade1ba2 100644 --- a/tests/ui/parser/issues/issue-111692.stderr +++ b/tests/ui/parser/issues/issue-111692.stderr @@ -1,43 +1,43 @@ -error: invalid struct literal - --> $DIR/issue-111692.rs:12:21 +error: struct literals are not allowed here + --> $DIR/issue-111692.rs:12:13 | LL | if x == module::Type { x: module::C, y: 1 } { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: you might need to surround the struct literal with parentheses +help: surround the struct literal with parentheses | LL | if x == (module::Type { x: module::C, y: 1 }) { | + + -error: invalid struct literal - --> $DIR/issue-111692.rs:17:20 +error: struct literals are not allowed here + --> $DIR/issue-111692.rs:17:12 | LL | if x ==module::Type { x: module::C, y: 1 } { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: you might need to surround the struct literal with parentheses +help: surround the struct literal with parentheses | LL | if x ==(module::Type { x: module::C, y: 1 }) { | + + -error: invalid struct literal - --> $DIR/issue-111692.rs:23:13 +error: struct literals are not allowed here + --> $DIR/issue-111692.rs:24:13 | LL | if x == Type { x: module::C, y: 1 } { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: you might need to surround the struct literal with parentheses +help: surround the struct literal with parentheses | LL | if x == (Type { x: module::C, y: 1 }) { | + + -error: invalid struct literal - --> $DIR/issue-111692.rs:28:26 +error: struct literals are not allowed here + --> $DIR/issue-111692.rs:30:13 | LL | if x == demo_module::Type { x: module::C, y: 1 } { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: you might need to surround the struct literal with parentheses +help: surround the struct literal with parentheses | LL | if x == (demo_module::Type { x: module::C, y: 1 }) { | + + diff --git a/tests/ui/parser/method-call-on-struct-literal-in-if-condition.rs b/tests/ui/parser/method-call-on-struct-literal-in-if-condition.rs index 8be7c9ee8ac3..3211b6c7bb9d 100644 --- a/tests/ui/parser/method-call-on-struct-literal-in-if-condition.rs +++ b/tests/ui/parser/method-call-on-struct-literal-in-if-condition.rs @@ -7,7 +7,7 @@ impl Example { fn one() -> i32 { 1 } fn main() { - if Example { a: one(), }.is_pos() { //~ ERROR invalid struct literal + if Example { a: one(), }.is_pos() { //~ ERROR struct literals are not allowed here println!("Positive!"); } } diff --git a/tests/ui/parser/method-call-on-struct-literal-in-if-condition.stderr b/tests/ui/parser/method-call-on-struct-literal-in-if-condition.stderr index f7822ba11246..8eba2230f8fb 100644 --- a/tests/ui/parser/method-call-on-struct-literal-in-if-condition.stderr +++ b/tests/ui/parser/method-call-on-struct-literal-in-if-condition.stderr @@ -1,10 +1,10 @@ -error: invalid struct literal +error: struct literals are not allowed here --> $DIR/method-call-on-struct-literal-in-if-condition.rs:10:8 | LL | if Example { a: one(), }.is_pos() { | ^^^^^^^^^^^^^^^^^^^^^ | -help: you might need to surround the struct literal with parentheses +help: surround the struct literal with parentheses | LL | if (Example { a: one(), }).is_pos() { | + + diff --git a/tests/ui/parser/type-ascription-in-pattern.rs b/tests/ui/parser/type-ascription-in-pattern.rs index fec168afba1d..18d7061d69c8 100644 --- a/tests/ui/parser/type-ascription-in-pattern.rs +++ b/tests/ui/parser/type-ascription-in-pattern.rs @@ -1,11 +1,10 @@ fn foo(x: bool) -> i32 { - match x { + match x { //~ ERROR struct literals are not allowed here x: i32 => x, //~ ERROR expected - //~^ ERROR mismatched types - true => 42., - false => 0.333, + true => 42., //~ ERROR expected identifier + false => 0.333, //~ ERROR expected identifier } -} +} //~ ERROR expected one of fn main() { match foo(true) { diff --git a/tests/ui/parser/type-ascription-in-pattern.stderr b/tests/ui/parser/type-ascription-in-pattern.stderr index 091907549936..135879f208b2 100644 --- a/tests/ui/parser/type-ascription-in-pattern.stderr +++ b/tests/ui/parser/type-ascription-in-pattern.stderr @@ -1,18 +1,64 @@ -error: expected one of `@` or `|`, found `:` - --> $DIR/type-ascription-in-pattern.rs:3:10 +error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, `}`, or an operator, found `=>` + --> $DIR/type-ascription-in-pattern.rs:3:16 | +LL | match x { + | - while parsing this struct LL | x: i32 => x, - | ^ --- specifying the type of a pattern isn't supported - | | - | expected one of `@` or `|` + | -^^ expected one of 8 possible tokens + | | + | help: try adding a comma: `,` + +error: expected identifier, found keyword `true` + --> $DIR/type-ascription-in-pattern.rs:4:9 | -help: maybe write a path separator here +LL | match x { + | - while parsing this struct +LL | x: i32 => x, +LL | true => 42., + | ^^^^ expected identifier, found keyword + +error: expected identifier, found keyword `false` + --> $DIR/type-ascription-in-pattern.rs:5:9 | -LL | x::i32 => x, - | ~~ +LL | match x { + | - while parsing this struct +... +LL | false => 0.333, + | ^^^^^ expected identifier, found keyword + +error: struct literals are not allowed here + --> $DIR/type-ascription-in-pattern.rs:2:11 + | +LL | match x { + | ___________^ +LL | | x: i32 => x, +LL | | true => 42., +LL | | false => 0.333, +LL | | } + | |_____^ + | +help: surround the struct literal with parentheses + | +LL ~ match (x { +LL | x: i32 => x, +LL | true => 42., +LL | false => 0.333, +LL ~ }) + | + +error: expected one of `.`, `?`, `{`, or an operator, found `}` + --> $DIR/type-ascription-in-pattern.rs:7:1 + | +LL | match x { + | ----- while parsing this `match` expression +... +LL | } + | - expected one of `.`, `?`, `{`, or an operator +LL | } + | ^ unexpected token error: expected one of `...`, `..=`, `..`, or `|`, found `:` - --> $DIR/type-ascription-in-pattern.rs:12:11 + --> $DIR/type-ascription-in-pattern.rs:11:11 | LL | 42: i32 => (), | ^ --- specifying the type of a pattern isn't supported @@ -20,7 +66,7 @@ LL | 42: i32 => (), | expected one of `...`, `..=`, `..`, or `|` error: expected `|`, found `:` - --> $DIR/type-ascription-in-pattern.rs:13:10 + --> $DIR/type-ascription-in-pattern.rs:12:10 | LL | _: f64 => (), | ^ --- specifying the type of a pattern isn't supported @@ -28,7 +74,7 @@ LL | _: f64 => (), | expected `|` error: expected one of `@` or `|`, found `:` - --> $DIR/type-ascription-in-pattern.rs:14:10 + --> $DIR/type-ascription-in-pattern.rs:13:10 | LL | x: i32 => (), | ^ --- specifying the type of a pattern isn't supported @@ -40,15 +86,5 @@ help: maybe write a path separator here LL | x::i32 => (), | ~~ -error[E0308]: mismatched types - --> $DIR/type-ascription-in-pattern.rs:3:19 - | -LL | fn foo(x: bool) -> i32 { - | --- expected `i32` because of return type -LL | match x { -LL | x: i32 => x, - | ^ expected `i32`, found `bool` +error: aborting due to 8 previous errors -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0308`. From 9f336ce2eb0ba04de7f1ddd2e1b0958e7df15c42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Mon, 24 Mar 2025 00:12:53 +0100 Subject: [PATCH 535/745] Remove now unreachable parse recovery code StructLiteralNeedingParens is no longer reachable always giving precedence to StructLiteralNotAllowedHere. As an aside: The former error struct shouldn't've existed in the first place. We should've just used the latter in this branch. --- compiler/rustc_parse/messages.ftl | 4 -- compiler/rustc_parse/src/errors.rs | 18 ------ .../rustc_parse/src/parser/diagnostics.rs | 64 ++++++------------- compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 2 +- compiler/rustc_parse/src/parser/stmt.rs | 10 +-- 6 files changed, 24 insertions(+), 76 deletions(-) diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 6d4308cda1a6..3253222b8f23 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -757,10 +757,6 @@ parse_struct_literal_body_without_path = struct literal body without path .suggestion = you might have forgotten to add the struct literal inside the block -parse_struct_literal_needing_parens = - invalid struct literal - .suggestion = you might need to surround the struct literal with parentheses - parse_struct_literal_not_allowed_here = struct literals are not allowed here .suggestion = surround the struct literal with parentheses diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index e090d9cf7600..f813c3380fcb 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1272,24 +1272,6 @@ pub(crate) struct StructLiteralBodyWithoutPathSugg { pub after: Span, } -#[derive(Diagnostic)] -#[diag(parse_struct_literal_needing_parens)] -pub(crate) struct StructLiteralNeedingParens { - #[primary_span] - pub span: Span, - #[subdiagnostic] - pub sugg: StructLiteralNeedingParensSugg, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] -pub(crate) struct StructLiteralNeedingParensSugg { - #[suggestion_part(code = "(")] - pub before: Span, - #[suggestion_part(code = ")")] - pub after: Span, -} - #[derive(Diagnostic)] #[diag(parse_unmatched_angle_brackets)] pub(crate) struct UnmatchedAngleBrackets { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index daa27b146690..ef044fe9d638 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -40,9 +40,8 @@ use crate::errors::{ HelpIdentifierStartsWithNumber, HelpUseLatestEdition, InInTypo, IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, IncorrectUseOfUse, PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg, SelfParamNotFirst, StructLiteralBodyWithoutPath, - StructLiteralBodyWithoutPathSugg, StructLiteralNeedingParens, StructLiteralNeedingParensSugg, - SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator, - UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration, + StructLiteralBodyWithoutPathSugg, SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma, + TernaryOperator, UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, WrapType, }; use crate::parser::attr::InnerAttrPolicy; @@ -949,7 +948,6 @@ impl<'a> Parser<'a> { lo: Span, s: BlockCheckMode, maybe_struct_name: token::Token, - can_be_struct_literal: bool, ) -> Option>> { if self.token.is_ident() && self.look_ahead(1, |t| t == &token::Colon) { // We might be having a struct literal where people forgot to include the path: @@ -971,49 +969,27 @@ impl<'a> Parser<'a> { // fn foo() -> Foo { // field: value, // } - let guar = err.delay_as_bug(); + // Suggest: + // fn foo() -> Foo { Path { + // field: value, + // } } + err.cancel(); self.restore_snapshot(snapshot); - if maybe_struct_name.is_ident() && can_be_struct_literal { - // Account for `if Example { a: one(), }.is_pos() {}`. - // expand `before` so that we take care of module path such as: - // `foo::Bar { ... } ` - // we expect to suggest `(foo::Bar { ... })` instead of `foo::(Bar { ... })` - let sm = self.psess.source_map(); - let before = maybe_struct_name.span.shrink_to_lo(); - if let Ok(extend_before) = sm.span_extend_prev_while(before, |t| { - t.is_alphanumeric() || t == ':' || t == '_' - }) { - Err(self.dcx().create_err(StructLiteralNeedingParens { - span: maybe_struct_name.span.to(expr.span), - sugg: StructLiteralNeedingParensSugg { - before: extend_before.shrink_to_lo(), - after: expr.span.shrink_to_hi(), - }, - })) - } else { - return None; - } - } else { - // Suggest: - // fn foo() -> Foo { Path { - // field: value, - // } } - self.dcx().emit_err(StructLiteralBodyWithoutPath { - span: expr.span, - sugg: StructLiteralBodyWithoutPathSugg { - before: expr.span.shrink_to_lo(), - after: expr.span.shrink_to_hi(), - }, - }); - Ok(self.mk_block( - thin_vec![self.mk_stmt_err(expr.span, guar)], - s, - lo.to(self.prev_token.span), - )) - } + let guar = self.dcx().emit_err(StructLiteralBodyWithoutPath { + span: expr.span, + sugg: StructLiteralBodyWithoutPathSugg { + before: expr.span.shrink_to_lo(), + after: expr.span.shrink_to_hi(), + }, + }); + Ok(self.mk_block( + thin_vec![self.mk_stmt_err(expr.span, guar)], + s, + lo.to(self.prev_token.span), + )) } (Err(err), Ok(tail)) => { - // We have a block tail that contains a somehow valid type ascription expr. + // We have a block tail that contains a somehow valid expr. err.cancel(); Ok(tail) } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 79d12ed4bbed..92e83577f1b1 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2296,7 +2296,7 @@ impl<'a> Parser<'a> { }); } - let (attrs, blk) = self.parse_block_common(lo, blk_mode, true, None)?; + let (attrs, blk) = self.parse_block_common(lo, blk_mode, None)?; Ok(self.mk_expr_with_attrs(blk.span, ExprKind::Block(blk, opt_label), attrs)) } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index f4df4044dd2e..77e675ea91f2 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2529,7 +2529,7 @@ impl<'a> Parser<'a> { *sig_hi = self.prev_token.span; (AttrVec::new(), None) } else if self.check(exp!(OpenBrace)) || self.token.is_whole_block() { - self.parse_block_common(self.token.span, BlockCheckMode::Default, false, None) + self.parse_block_common(self.token.span, BlockCheckMode::Default, None) .map(|(attrs, body)| (attrs, Some(body)))? } else if self.token == token::Eq { // Recover `fn foo() = $expr;`. diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 368366c60d65..97cd4d2117f8 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -668,7 +668,7 @@ impl<'a> Parser<'a> { &mut self, loop_header: Option, ) -> PResult<'a, (AttrVec, P)> { - self.parse_block_common(self.token.span, BlockCheckMode::Default, true, loop_header) + self.parse_block_common(self.token.span, BlockCheckMode::Default, loop_header) } /// Parses a block. Inner attributes are allowed, block labels are not. @@ -679,7 +679,6 @@ impl<'a> Parser<'a> { &mut self, lo: Span, blk_mode: BlockCheckMode, - can_be_struct_literal: bool, loop_header: Option, ) -> PResult<'a, (AttrVec, P)> { maybe_whole!(self, NtBlock, |block| (AttrVec::new(), block)); @@ -691,12 +690,7 @@ impl<'a> Parser<'a> { } let attrs = self.parse_inner_attributes()?; - let tail = match self.maybe_suggest_struct_literal( - lo, - blk_mode, - maybe_ident, - can_be_struct_literal, - ) { + let tail = match self.maybe_suggest_struct_literal(lo, blk_mode, maybe_ident) { Some(tail) => tail?, None => self.parse_block_tail(lo, blk_mode, AttemptLocalParseRecovery::Yes)?, }; From 598f8658744db0dc0215545d2193accd3a1ce8c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Mon, 24 Mar 2025 17:16:26 +0100 Subject: [PATCH 536/745] Combine several test files into one This makes it a lot easier to add smaller regression tests related to "incorrectly placed" struct literals. --- ...-call-on-struct-literal-in-if-condition.rs | 13 -- ...l-on-struct-literal-in-if-condition.stderr | 13 -- tests/ui/parser/struct-literal-in-for.rs | 17 -- tests/ui/parser/struct-literal-in-for.stderr | 31 --- tests/ui/parser/struct-literal-in-if.rs | 22 -- tests/ui/parser/struct-literal-in-if.stderr | 34 ---- .../struct-literal-in-match-discriminant.rs | 13 -- ...truct-literal-in-match-discriminant.stderr | 18 -- tests/ui/parser/struct-literal-in-while.rs | 22 -- .../ui/parser/struct-literal-in-while.stderr | 34 ---- .../struct-literal-restrictions-in-lamda.rs | 17 -- ...truct-literal-restrictions-in-lamda.stderr | 37 ---- .../ui/parser/struct-literal-variant-in-if.rs | 25 --- .../struct-literal-variant-in-if.stderr | 76 ------- .../struct-literals-in-invalid-places.rs | 72 +++++++ .../struct-literals-in-invalid-places.stderr | 191 ++++++++++++++++++ 16 files changed, 263 insertions(+), 372 deletions(-) delete mode 100644 tests/ui/parser/method-call-on-struct-literal-in-if-condition.rs delete mode 100644 tests/ui/parser/method-call-on-struct-literal-in-if-condition.stderr delete mode 100644 tests/ui/parser/struct-literal-in-for.rs delete mode 100644 tests/ui/parser/struct-literal-in-for.stderr delete mode 100644 tests/ui/parser/struct-literal-in-if.rs delete mode 100644 tests/ui/parser/struct-literal-in-if.stderr delete mode 100644 tests/ui/parser/struct-literal-in-match-discriminant.rs delete mode 100644 tests/ui/parser/struct-literal-in-match-discriminant.stderr delete mode 100644 tests/ui/parser/struct-literal-in-while.rs delete mode 100644 tests/ui/parser/struct-literal-in-while.stderr delete mode 100644 tests/ui/parser/struct-literal-restrictions-in-lamda.rs delete mode 100644 tests/ui/parser/struct-literal-restrictions-in-lamda.stderr delete mode 100644 tests/ui/parser/struct-literal-variant-in-if.rs delete mode 100644 tests/ui/parser/struct-literal-variant-in-if.stderr create mode 100644 tests/ui/parser/struct-literals-in-invalid-places.rs create mode 100644 tests/ui/parser/struct-literals-in-invalid-places.stderr diff --git a/tests/ui/parser/method-call-on-struct-literal-in-if-condition.rs b/tests/ui/parser/method-call-on-struct-literal-in-if-condition.rs deleted file mode 100644 index 3211b6c7bb9d..000000000000 --- a/tests/ui/parser/method-call-on-struct-literal-in-if-condition.rs +++ /dev/null @@ -1,13 +0,0 @@ -pub struct Example { a: i32 } - -impl Example { - fn is_pos(&self) -> bool { self.a > 0 } -} - -fn one() -> i32 { 1 } - -fn main() { - if Example { a: one(), }.is_pos() { //~ ERROR struct literals are not allowed here - println!("Positive!"); - } -} diff --git a/tests/ui/parser/method-call-on-struct-literal-in-if-condition.stderr b/tests/ui/parser/method-call-on-struct-literal-in-if-condition.stderr deleted file mode 100644 index 8eba2230f8fb..000000000000 --- a/tests/ui/parser/method-call-on-struct-literal-in-if-condition.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error: struct literals are not allowed here - --> $DIR/method-call-on-struct-literal-in-if-condition.rs:10:8 - | -LL | if Example { a: one(), }.is_pos() { - | ^^^^^^^^^^^^^^^^^^^^^ - | -help: surround the struct literal with parentheses - | -LL | if (Example { a: one(), }).is_pos() { - | + + - -error: aborting due to 1 previous error - diff --git a/tests/ui/parser/struct-literal-in-for.rs b/tests/ui/parser/struct-literal-in-for.rs deleted file mode 100644 index 3227ae37bfd0..000000000000 --- a/tests/ui/parser/struct-literal-in-for.rs +++ /dev/null @@ -1,17 +0,0 @@ -struct Foo { - x: isize, -} - -impl Foo { - fn hi(&self) -> bool { - true - } -} - -fn main() { - for x in Foo { //~ ERROR struct literals are not allowed here - x: 3 //~^ ERROR `bool` is not an iterator - }.hi() { - println!("yo"); - } -} diff --git a/tests/ui/parser/struct-literal-in-for.stderr b/tests/ui/parser/struct-literal-in-for.stderr deleted file mode 100644 index 1c91eba68e39..000000000000 --- a/tests/ui/parser/struct-literal-in-for.stderr +++ /dev/null @@ -1,31 +0,0 @@ -error: struct literals are not allowed here - --> $DIR/struct-literal-in-for.rs:12:14 - | -LL | for x in Foo { - | ______________^ -LL | | x: 3 -LL | | }.hi() { - | |_____^ - | -help: surround the struct literal with parentheses - | -LL ~ for x in (Foo { -LL | x: 3 -LL ~ }).hi() { - | - -error[E0277]: `bool` is not an iterator - --> $DIR/struct-literal-in-for.rs:12:14 - | -LL | for x in Foo { - | ______________^ -LL | | x: 3 -LL | | }.hi() { - | |__________^ `bool` is not an iterator - | - = help: the trait `Iterator` is not implemented for `bool` - = note: required for `bool` to implement `IntoIterator` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/parser/struct-literal-in-if.rs b/tests/ui/parser/struct-literal-in-if.rs deleted file mode 100644 index c4a253c3da25..000000000000 --- a/tests/ui/parser/struct-literal-in-if.rs +++ /dev/null @@ -1,22 +0,0 @@ -struct Foo { - x: isize, -} - -impl Foo { - fn hi(&self) -> bool { - true - } -} - -fn main() { - if Foo { //~ ERROR struct literals are not allowed here - x: 3 - }.hi() { - println!("yo"); - } - if let true = Foo { //~ ERROR struct literals are not allowed here - x: 3 - }.hi() { - println!("yo"); - } -} diff --git a/tests/ui/parser/struct-literal-in-if.stderr b/tests/ui/parser/struct-literal-in-if.stderr deleted file mode 100644 index 8b72469fcf58..000000000000 --- a/tests/ui/parser/struct-literal-in-if.stderr +++ /dev/null @@ -1,34 +0,0 @@ -error: struct literals are not allowed here - --> $DIR/struct-literal-in-if.rs:12:8 - | -LL | if Foo { - | ________^ -LL | | x: 3 -LL | | }.hi() { - | |_____^ - | -help: surround the struct literal with parentheses - | -LL ~ if (Foo { -LL | x: 3 -LL ~ }).hi() { - | - -error: struct literals are not allowed here - --> $DIR/struct-literal-in-if.rs:17:19 - | -LL | if let true = Foo { - | ___________________^ -LL | | x: 3 -LL | | }.hi() { - | |_____^ - | -help: surround the struct literal with parentheses - | -LL ~ if let true = (Foo { -LL | x: 3 -LL ~ }).hi() { - | - -error: aborting due to 2 previous errors - diff --git a/tests/ui/parser/struct-literal-in-match-discriminant.rs b/tests/ui/parser/struct-literal-in-match-discriminant.rs deleted file mode 100644 index ce132df5a888..000000000000 --- a/tests/ui/parser/struct-literal-in-match-discriminant.rs +++ /dev/null @@ -1,13 +0,0 @@ -struct Foo { - x: isize, -} - -fn main() { - match Foo { //~ ERROR struct literals are not allowed here - x: 3 - } { - Foo { - x: x - } => {} - } -} diff --git a/tests/ui/parser/struct-literal-in-match-discriminant.stderr b/tests/ui/parser/struct-literal-in-match-discriminant.stderr deleted file mode 100644 index 5177f5f126e0..000000000000 --- a/tests/ui/parser/struct-literal-in-match-discriminant.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: struct literals are not allowed here - --> $DIR/struct-literal-in-match-discriminant.rs:6:11 - | -LL | match Foo { - | ___________^ -LL | | x: 3 -LL | | } { - | |_____^ - | -help: surround the struct literal with parentheses - | -LL ~ match (Foo { -LL | x: 3 -LL ~ }) { - | - -error: aborting due to 1 previous error - diff --git a/tests/ui/parser/struct-literal-in-while.rs b/tests/ui/parser/struct-literal-in-while.rs deleted file mode 100644 index 86931f7888dd..000000000000 --- a/tests/ui/parser/struct-literal-in-while.rs +++ /dev/null @@ -1,22 +0,0 @@ -struct Foo { - x: isize, -} - -impl Foo { - fn hi(&self) -> bool { - true - } -} - -fn main() { - while Foo { //~ ERROR struct literals are not allowed here - x: 3 - }.hi() { - println!("yo"); - } - while let true = Foo { //~ ERROR struct literals are not allowed here - x: 3 - }.hi() { - println!("yo"); - } -} diff --git a/tests/ui/parser/struct-literal-in-while.stderr b/tests/ui/parser/struct-literal-in-while.stderr deleted file mode 100644 index 13d003608a1b..000000000000 --- a/tests/ui/parser/struct-literal-in-while.stderr +++ /dev/null @@ -1,34 +0,0 @@ -error: struct literals are not allowed here - --> $DIR/struct-literal-in-while.rs:12:11 - | -LL | while Foo { - | ___________^ -LL | | x: 3 -LL | | }.hi() { - | |_____^ - | -help: surround the struct literal with parentheses - | -LL ~ while (Foo { -LL | x: 3 -LL ~ }).hi() { - | - -error: struct literals are not allowed here - --> $DIR/struct-literal-in-while.rs:17:22 - | -LL | while let true = Foo { - | ______________________^ -LL | | x: 3 -LL | | }.hi() { - | |_____^ - | -help: surround the struct literal with parentheses - | -LL ~ while let true = (Foo { -LL | x: 3 -LL ~ }).hi() { - | - -error: aborting due to 2 previous errors - diff --git a/tests/ui/parser/struct-literal-restrictions-in-lamda.rs b/tests/ui/parser/struct-literal-restrictions-in-lamda.rs deleted file mode 100644 index e185153dcf62..000000000000 --- a/tests/ui/parser/struct-literal-restrictions-in-lamda.rs +++ /dev/null @@ -1,17 +0,0 @@ -struct Foo { - x: isize, -} - -impl Foo { - fn hi(&self) -> bool { - true - } -} - -fn main() { - while || Foo { //~ ERROR struct literals are not allowed here - x: 3 //~^ ERROR mismatched types - }.hi() { - println!("yo"); - } -} diff --git a/tests/ui/parser/struct-literal-restrictions-in-lamda.stderr b/tests/ui/parser/struct-literal-restrictions-in-lamda.stderr deleted file mode 100644 index c715486e2da9..000000000000 --- a/tests/ui/parser/struct-literal-restrictions-in-lamda.stderr +++ /dev/null @@ -1,37 +0,0 @@ -error: struct literals are not allowed here - --> $DIR/struct-literal-restrictions-in-lamda.rs:12:14 - | -LL | while || Foo { - | ______________^ -LL | | x: 3 -LL | | }.hi() { - | |_____^ - | -help: surround the struct literal with parentheses - | -LL ~ while || (Foo { -LL | x: 3 -LL ~ }).hi() { - | - -error[E0308]: mismatched types - --> $DIR/struct-literal-restrictions-in-lamda.rs:12:11 - | -LL | while || Foo { - | ___________^ -LL | | x: 3 -LL | | }.hi() { - | |__________^ expected `bool`, found closure - | - = note: expected type `bool` - found closure `{closure@$DIR/struct-literal-restrictions-in-lamda.rs:12:11: 12:13}` -help: use parentheses to call this closure - | -LL ~ while (|| Foo { -LL | x: 3 -LL ~ }.hi())() { - | - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/struct-literal-variant-in-if.rs b/tests/ui/parser/struct-literal-variant-in-if.rs deleted file mode 100644 index 4ef8effaf1f5..000000000000 --- a/tests/ui/parser/struct-literal-variant-in-if.rs +++ /dev/null @@ -1,25 +0,0 @@ -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] -enum E { - V { field: bool }, - I { field1: bool, field2: usize }, - J { field: isize }, - K { field: &'static str}, -} -fn test_E(x: E) { - let field = true; - if x == E::V { field } {} - //~^ ERROR expected value, found struct variant `E::V` - //~| ERROR mismatched types - if x == E::I { field1: true, field2: 42 } {} - //~^ ERROR struct literals are not allowed here - if x == E::V { field: false } {} - //~^ ERROR struct literals are not allowed here - if x == E::J { field: -42 } {} - //~^ ERROR struct literals are not allowed here - if x == E::K { field: "" } {} - //~^ ERROR struct literals are not allowed here - let y: usize = (); - //~^ ERROR mismatched types -} - -fn main() {} diff --git a/tests/ui/parser/struct-literal-variant-in-if.stderr b/tests/ui/parser/struct-literal-variant-in-if.stderr deleted file mode 100644 index 15f059f145bb..000000000000 --- a/tests/ui/parser/struct-literal-variant-in-if.stderr +++ /dev/null @@ -1,76 +0,0 @@ -error: struct literals are not allowed here - --> $DIR/struct-literal-variant-in-if.rs:13:13 - | -LL | if x == E::I { field1: true, field2: 42 } {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: surround the struct literal with parentheses - | -LL | if x == (E::I { field1: true, field2: 42 }) {} - | + + - -error: struct literals are not allowed here - --> $DIR/struct-literal-variant-in-if.rs:15:13 - | -LL | if x == E::V { field: false } {} - | ^^^^^^^^^^^^^^^^^^^^^ - | -help: surround the struct literal with parentheses - | -LL | if x == (E::V { field: false }) {} - | + + - -error: struct literals are not allowed here - --> $DIR/struct-literal-variant-in-if.rs:17:13 - | -LL | if x == E::J { field: -42 } {} - | ^^^^^^^^^^^^^^^^^^^ - | -help: surround the struct literal with parentheses - | -LL | if x == (E::J { field: -42 }) {} - | + + - -error: struct literals are not allowed here - --> $DIR/struct-literal-variant-in-if.rs:19:13 - | -LL | if x == E::K { field: "" } {} - | ^^^^^^^^^^^^^^^^^^ - | -help: surround the struct literal with parentheses - | -LL | if x == (E::K { field: "" }) {} - | + + - -error[E0533]: expected value, found struct variant `E::V` - --> $DIR/struct-literal-variant-in-if.rs:10:13 - | -LL | if x == E::V { field } {} - | ^^^^ not a value - | -help: you might have meant to create a new value of the struct - | -LL | if x == (E::V { field }) {} - | + + - -error[E0308]: mismatched types - --> $DIR/struct-literal-variant-in-if.rs:10:20 - | -LL | if x == E::V { field } {} - | ---------------^^^^^-- - | | | - | | expected `()`, found `bool` - | expected this to be `()` - -error[E0308]: mismatched types - --> $DIR/struct-literal-variant-in-if.rs:21:20 - | -LL | let y: usize = (); - | ----- ^^ expected `usize`, found `()` - | | - | expected due to this - -error: aborting due to 7 previous errors - -Some errors have detailed explanations: E0308, E0533. -For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/struct-literals-in-invalid-places.rs b/tests/ui/parser/struct-literals-in-invalid-places.rs new file mode 100644 index 000000000000..89cdb30fc046 --- /dev/null +++ b/tests/ui/parser/struct-literals-in-invalid-places.rs @@ -0,0 +1,72 @@ +fn main() { + if Foo { x: 3 }.hi() { //~ ERROR struct literals are not allowed here + println!("yo"); + } + if let true = Foo { x: 3 }.hi() { //~ ERROR struct literals are not allowed here + println!("yo"); + } + + for x in Foo { x: 3 }.hi() { //~ ERROR struct literals are not allowed here + //~^ ERROR `bool` is not an iterator + println!("yo"); + } + + while Foo { x: 3 }.hi() { //~ ERROR struct literals are not allowed here + println!("yo"); + } + while let true = Foo { x: 3 }.hi() { //~ ERROR struct literals are not allowed here + println!("yo"); + } + + match Foo { x: 3 } { //~ ERROR struct literals are not allowed here + Foo { x: x } => {} + } + + let _ = |x: E| { + let field = true; + if x == E::V { field } {} + //~^ ERROR expected value, found struct variant `E::V` + //~| ERROR mismatched types + if x == E::I { field1: true, field2: 42 } {} + //~^ ERROR struct literals are not allowed here + if x == E::V { field: false } {} + //~^ ERROR struct literals are not allowed here + if x == E::J { field: -42 } {} + //~^ ERROR struct literals are not allowed here + if x == E::K { field: "" } {} + //~^ ERROR struct literals are not allowed here + let y: usize = (); + //~^ ERROR mismatched types + }; + + // Regression test for . + while || Foo { x: 3 }.hi() { //~ ERROR struct literals are not allowed here + //~^ ERROR mismatched types + println!("yo"); + } + + // Regression test for . + if Foo { x: one(), }.hi() { //~ ERROR struct literals are not allowed here + println!("Positive!"); + } +} + +struct Foo { + x: isize, +} + +impl Foo { + fn hi(&self) -> bool { + true + } +} + +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +enum E { + V { field: bool }, + I { field1: bool, field2: usize }, + J { field: isize }, + K { field: &'static str}, +} + +fn one() -> isize { 1 } diff --git a/tests/ui/parser/struct-literals-in-invalid-places.stderr b/tests/ui/parser/struct-literals-in-invalid-places.stderr new file mode 100644 index 000000000000..ed094fc3e157 --- /dev/null +++ b/tests/ui/parser/struct-literals-in-invalid-places.stderr @@ -0,0 +1,191 @@ +error: struct literals are not allowed here + --> $DIR/struct-literals-in-invalid-places.rs:2:8 + | +LL | if Foo { x: 3 }.hi() { + | ^^^^^^^^^^^^ + | +help: surround the struct literal with parentheses + | +LL | if (Foo { x: 3 }).hi() { + | + + + +error: struct literals are not allowed here + --> $DIR/struct-literals-in-invalid-places.rs:5:19 + | +LL | if let true = Foo { x: 3 }.hi() { + | ^^^^^^^^^^^^ + | +help: surround the struct literal with parentheses + | +LL | if let true = (Foo { x: 3 }).hi() { + | + + + +error: struct literals are not allowed here + --> $DIR/struct-literals-in-invalid-places.rs:9:14 + | +LL | for x in Foo { x: 3 }.hi() { + | ^^^^^^^^^^^^ + | +help: surround the struct literal with parentheses + | +LL | for x in (Foo { x: 3 }).hi() { + | + + + +error: struct literals are not allowed here + --> $DIR/struct-literals-in-invalid-places.rs:14:11 + | +LL | while Foo { x: 3 }.hi() { + | ^^^^^^^^^^^^ + | +help: surround the struct literal with parentheses + | +LL | while (Foo { x: 3 }).hi() { + | + + + +error: struct literals are not allowed here + --> $DIR/struct-literals-in-invalid-places.rs:17:22 + | +LL | while let true = Foo { x: 3 }.hi() { + | ^^^^^^^^^^^^ + | +help: surround the struct literal with parentheses + | +LL | while let true = (Foo { x: 3 }).hi() { + | + + + +error: struct literals are not allowed here + --> $DIR/struct-literals-in-invalid-places.rs:21:11 + | +LL | match Foo { x: 3 } { + | ^^^^^^^^^^^^ + | +help: surround the struct literal with parentheses + | +LL | match (Foo { x: 3 }) { + | + + + +error: struct literals are not allowed here + --> $DIR/struct-literals-in-invalid-places.rs:30:17 + | +LL | if x == E::I { field1: true, field2: 42 } {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: surround the struct literal with parentheses + | +LL | if x == (E::I { field1: true, field2: 42 }) {} + | + + + +error: struct literals are not allowed here + --> $DIR/struct-literals-in-invalid-places.rs:32:17 + | +LL | if x == E::V { field: false } {} + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: surround the struct literal with parentheses + | +LL | if x == (E::V { field: false }) {} + | + + + +error: struct literals are not allowed here + --> $DIR/struct-literals-in-invalid-places.rs:34:17 + | +LL | if x == E::J { field: -42 } {} + | ^^^^^^^^^^^^^^^^^^^ + | +help: surround the struct literal with parentheses + | +LL | if x == (E::J { field: -42 }) {} + | + + + +error: struct literals are not allowed here + --> $DIR/struct-literals-in-invalid-places.rs:36:17 + | +LL | if x == E::K { field: "" } {} + | ^^^^^^^^^^^^^^^^^^ + | +help: surround the struct literal with parentheses + | +LL | if x == (E::K { field: "" }) {} + | + + + +error: struct literals are not allowed here + --> $DIR/struct-literals-in-invalid-places.rs:43:14 + | +LL | while || Foo { x: 3 }.hi() { + | ^^^^^^^^^^^^ + | +help: surround the struct literal with parentheses + | +LL | while || (Foo { x: 3 }).hi() { + | + + + +error: struct literals are not allowed here + --> $DIR/struct-literals-in-invalid-places.rs:49:8 + | +LL | if Foo { x: one(), }.hi() { + | ^^^^^^^^^^^^^^^^^ + | +help: surround the struct literal with parentheses + | +LL | if (Foo { x: one(), }).hi() { + | + + + +error[E0277]: `bool` is not an iterator + --> $DIR/struct-literals-in-invalid-places.rs:9:14 + | +LL | for x in Foo { x: 3 }.hi() { + | ^^^^^^^^^^^^^^^^^ `bool` is not an iterator + | + = help: the trait `Iterator` is not implemented for `bool` + = note: required for `bool` to implement `IntoIterator` + +error[E0533]: expected value, found struct variant `E::V` + --> $DIR/struct-literals-in-invalid-places.rs:27:17 + | +LL | if x == E::V { field } {} + | ^^^^ not a value + | +help: you might have meant to create a new value of the struct + | +LL | if x == (E::V { field }) {} + | + + + +error[E0308]: mismatched types + --> $DIR/struct-literals-in-invalid-places.rs:27:24 + | +LL | if x == E::V { field } {} + | ---------------^^^^^-- + | | | + | | expected `()`, found `bool` + | expected this to be `()` + | +help: you might have meant to return this value + | +LL | if x == E::V { return field; } {} + | ++++++ + + +error[E0308]: mismatched types + --> $DIR/struct-literals-in-invalid-places.rs:38:24 + | +LL | let y: usize = (); + | ----- ^^ expected `usize`, found `()` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/struct-literals-in-invalid-places.rs:43:11 + | +LL | while || Foo { x: 3 }.hi() { + | ^^^^^^^^^^^^^^^^^^^^ expected `bool`, found closure + | + = note: expected type `bool` + found closure `{closure@$DIR/struct-literals-in-invalid-places.rs:43:11: 43:13}` +help: use parentheses to call this closure + | +LL | while (|| Foo { x: 3 }.hi())() { + | + +++ + +error: aborting due to 17 previous errors + +Some errors have detailed explanations: E0277, E0308, E0533. +For more information about an error, try `rustc --explain E0277`. From b501e58c2e8aa42c0b6f4f568c90f70e34a11170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Mon, 24 Mar 2025 17:39:38 +0100 Subject: [PATCH 537/745] Incorporate issue-111692.rs into the larger test file and add more test cases Note that issue-111692.rs was incorrectly named: It's a regression test for issue [#]112278, not for [#]111692. That's been addressed, too. --- src/tools/tidy/src/issues.txt | 1 - tests/ui/parser/issues/issue-111692.rs | 34 ------------- tests/ui/parser/issues/issue-111692.stderr | 46 ----------------- .../struct-literals-in-invalid-places.rs | 20 ++++++++ .../struct-literals-in-invalid-places.stderr | 49 +++++++++++++++++-- 5 files changed, 66 insertions(+), 84 deletions(-) delete mode 100644 tests/ui/parser/issues/issue-111692.rs delete mode 100644 tests/ui/parser/issues/issue-111692.stderr diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 4a929a376d78..a33e03d5861e 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -3189,7 +3189,6 @@ ui/parser/issues/issue-108495-dec.rs ui/parser/issues/issue-110014.rs ui/parser/issues/issue-111148.rs ui/parser/issues/issue-111416.rs -ui/parser/issues/issue-111692.rs ui/parser/issues/issue-112188.rs ui/parser/issues/issue-112458.rs ui/parser/issues/issue-113110-non-item-at-module-root.rs diff --git a/tests/ui/parser/issues/issue-111692.rs b/tests/ui/parser/issues/issue-111692.rs deleted file mode 100644 index de6de2227549..000000000000 --- a/tests/ui/parser/issues/issue-111692.rs +++ /dev/null @@ -1,34 +0,0 @@ -mod module { - #[derive(Eq, PartialEq)] - pub struct Type { - pub x: u8, - pub y: u8, - } - - pub const C: u8 = 32u8; -} - -fn test(x: module::Type) { - if x == module::Type { x: module::C, y: 1 } { //~ ERROR struct literals are not allowed here - } -} - -fn test2(x: module::Type) { - if x ==module::Type { x: module::C, y: 1 } { //~ ERROR struct literals are not allowed here - } -} - - -fn test3(x: module::Type) { - use module::Type; - if x == Type { x: module::C, y: 1 } { //~ ERROR struct literals are not allowed here - } -} - -fn test4(x: module::Type) { - use module as demo_module; - if x == demo_module::Type { x: module::C, y: 1 } { //~ ERROR struct literals are not allowed here - } -} - -fn main() { } diff --git a/tests/ui/parser/issues/issue-111692.stderr b/tests/ui/parser/issues/issue-111692.stderr deleted file mode 100644 index 979dfade1ba2..000000000000 --- a/tests/ui/parser/issues/issue-111692.stderr +++ /dev/null @@ -1,46 +0,0 @@ -error: struct literals are not allowed here - --> $DIR/issue-111692.rs:12:13 - | -LL | if x == module::Type { x: module::C, y: 1 } { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: surround the struct literal with parentheses - | -LL | if x == (module::Type { x: module::C, y: 1 }) { - | + + - -error: struct literals are not allowed here - --> $DIR/issue-111692.rs:17:12 - | -LL | if x ==module::Type { x: module::C, y: 1 } { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: surround the struct literal with parentheses - | -LL | if x ==(module::Type { x: module::C, y: 1 }) { - | + + - -error: struct literals are not allowed here - --> $DIR/issue-111692.rs:24:13 - | -LL | if x == Type { x: module::C, y: 1 } { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: surround the struct literal with parentheses - | -LL | if x == (Type { x: module::C, y: 1 }) { - | + + - -error: struct literals are not allowed here - --> $DIR/issue-111692.rs:30:13 - | -LL | if x == demo_module::Type { x: module::C, y: 1 } { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: surround the struct literal with parentheses - | -LL | if x == (demo_module::Type { x: module::C, y: 1 }) { - | + + - -error: aborting due to 4 previous errors - diff --git a/tests/ui/parser/struct-literals-in-invalid-places.rs b/tests/ui/parser/struct-literals-in-invalid-places.rs index 89cdb30fc046..eed51b945831 100644 --- a/tests/ui/parser/struct-literals-in-invalid-places.rs +++ b/tests/ui/parser/struct-literals-in-invalid-places.rs @@ -45,12 +45,30 @@ fn main() { println!("yo"); } + // This uses `one()` over `1` as token `one` may begin a type and thus back when type ascription + // `$expr : $ty` still existed, `{ x: one` could've been the start of a block expr which used to + // make the compiler take a different execution path. Now it no longer makes a difference tho. + // Regression test for . if Foo { x: one(), }.hi() { //~ ERROR struct literals are not allowed here println!("Positive!"); } + + const FOO: Foo = Foo { x: 1 }; + // Below, test that we correctly parenthesize the struct literals. + + // Regression test for . + if FOO == self::Foo { x: one() } {} //~ ERROR struct literals are not allowed here + + if FOO == Foo::<> { x: one() } {} //~ ERROR struct literals are not allowed here + + fn env>() { + if FOO == ::Out { x: one() } {} //~ ERROR struct literals are not allowed here + //~^ ERROR usage of qualified paths in this context is experimental + } } +#[derive(PartialEq, Eq)] struct Foo { x: isize, } @@ -70,3 +88,5 @@ enum E { } fn one() -> isize { 1 } + +trait Trait { type Out; } diff --git a/tests/ui/parser/struct-literals-in-invalid-places.stderr b/tests/ui/parser/struct-literals-in-invalid-places.stderr index ed094fc3e157..39dc2d2efb75 100644 --- a/tests/ui/parser/struct-literals-in-invalid-places.stderr +++ b/tests/ui/parser/struct-literals-in-invalid-places.stderr @@ -120,7 +120,7 @@ LL | while || (Foo { x: 3 }).hi() { | + + error: struct literals are not allowed here - --> $DIR/struct-literals-in-invalid-places.rs:49:8 + --> $DIR/struct-literals-in-invalid-places.rs:53:8 | LL | if Foo { x: one(), }.hi() { | ^^^^^^^^^^^^^^^^^ @@ -130,6 +130,49 @@ help: surround the struct literal with parentheses LL | if (Foo { x: one(), }).hi() { | + + +error: struct literals are not allowed here + --> $DIR/struct-literals-in-invalid-places.rs:61:15 + | +LL | if FOO == self::Foo { x: one() } {} + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: surround the struct literal with parentheses + | +LL | if FOO == (self::Foo { x: one() }) {} + | + + + +error: struct literals are not allowed here + --> $DIR/struct-literals-in-invalid-places.rs:63:15 + | +LL | if FOO == Foo::<> { x: one() } {} + | ^^^^^^^^^^^^^^^^^^^^ + | +help: surround the struct literal with parentheses + | +LL | if FOO == (Foo::<> { x: one() }) {} + | + + + +error: struct literals are not allowed here + --> $DIR/struct-literals-in-invalid-places.rs:66:19 + | +LL | if FOO == ::Out { x: one() } {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: surround the struct literal with parentheses + | +LL | if FOO == (::Out { x: one() }) {} + | + + + +error[E0658]: usage of qualified paths in this context is experimental + --> $DIR/struct-literals-in-invalid-places.rs:66:19 + | +LL | if FOO == ::Out { x: one() } {} + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #86935 for more information + = help: add `#![feature(more_qualified_paths)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error[E0277]: `bool` is not an iterator --> $DIR/struct-literals-in-invalid-places.rs:9:14 | @@ -185,7 +228,7 @@ help: use parentheses to call this closure LL | while (|| Foo { x: 3 }.hi())() { | + +++ -error: aborting due to 17 previous errors +error: aborting due to 21 previous errors -Some errors have detailed explanations: E0277, E0308, E0533. +Some errors have detailed explanations: E0277, E0308, E0533, E0658. For more information about an error, try `rustc --explain E0277`. From 8d5109aa6ea1b54a560774eb95ba7c1b8d404faa Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 23 Mar 2025 15:50:51 +0300 Subject: [PATCH 538/745] compiletest: Support matching on diagnostics without a span --- src/doc/rustc-dev-guide/src/tests/ui.md | 26 +++++- src/tools/compiletest/src/errors.rs | 55 +++++------- src/tools/compiletest/src/json.rs | 88 +++++++++++-------- src/tools/compiletest/src/runtest.rs | 4 +- src/tools/compiletest/src/runtest/ui.rs | 2 +- tests/rustdoc-ui/coverage/html.rs | 2 + tests/rustdoc-ui/deprecated-attrs.rs | 4 + tests/rustdoc-ui/doctest-output.rs | 2 + .../generate-link-to-definition-opt.rs | 2 + tests/rustdoc-ui/include-str-bare-urls.rs | 2 + tests/rustdoc-ui/lints/check.rs | 2 + tests/rustdoc-ui/remap-path-prefix-lint.rs | 2 + .../scrape-examples-fail-if-type-error.rs | 2 + .../scrape-examples-wrong-options-1.rs | 2 + .../scrape-examples-wrong-options-2.rs | 2 + .../use_both_out_dir_and_output_options.rs | 2 + tests/ui/asm/inline-syntax.rs | 5 ++ tests/ui/cfg/disallowed-cli-cfgs.rs | 2 + tests/ui/check-cfg/invalid-arguments.rs | 2 + tests/ui/codegen/duplicated-path-in-error.rs | 2 + tests/ui/consts/const-eval/const_fn_ptr.rs | 2 + .../ui/consts/const-eval/const_fn_ptr_fail.rs | 2 + .../consts/const-eval/const_fn_ptr_fail2.rs | 2 + tests/ui/consts/const-eval/issue-85155.rs | 3 + .../ui/consts/miri_unleashed/abi-mismatch.rs | 2 + tests/ui/consts/miri_unleashed/assoc_const.rs | 2 + tests/ui/consts/miri_unleashed/box.rs | 2 + .../miri_unleashed/const_refers_to_static.rs | 2 + tests/ui/consts/miri_unleashed/inline_asm.rs | 2 + .../miri_unleashed/mutable_references.rs | 2 + .../ui/consts/miri_unleashed/non_const_fn.rs | 2 + tests/ui/consts/miri_unleashed/ptr_arith.rs | 2 + .../miri_unleashed/static-no-inner-mut.rs | 2 + tests/ui/consts/miri_unleashed/tls.rs | 2 + tests/ui/dep-graph/dep-graph-dump.rs | 2 + tests/ui/deprecation/deprecated_ar.rs | 2 + .../deprecated_inline_threshold.rs | 6 ++ .../deprecated_no_stack_check_opt.rs | 2 + .../ui/did_you_mean/recursion_limit_deref.rs | 3 + .../edition-keywords-2018-2015-parsing.rs | 2 + .../edition-keywords-2018-2018-parsing.rs | 2 + ...orted_main_from_extern_crate_wrong_type.rs | 2 + tests/ui/errors/wrong-target-spec.rs | 2 + .../feature-gate-link-arg-attribute.rs | 2 + ...re-gate-native_link_modifiers_as_needed.rs | 2 + tests/ui/fmt/fmt_debug/invalid.rs | 2 + tests/ui/infinite/infinite-struct.rs | 2 + tests/ui/instrument-coverage/bad-value.rs | 3 + .../instrument-coverage/coverage-options.rs | 2 + .../branch-protection-missing-pac-ret.rs | 4 + .../invalid-llvm-passes.rs | 2 + .../need-crate-arg-ignore-tidy$x.rs | 3 + tests/ui/invalid-compile-flags/print.rs | 2 + .../invalid-module-declaration.rs | 2 + .../lang-item-generic-requirements.rs | 2 + tests/ui/link-native-libs/modifiers-bad.rs | 5 ++ .../link-native-libs/modifiers-override-2.rs | 2 + .../link-native-libs/msvc-non-utf8-output.rs | 2 + .../link-self-contained-consistency.rs | 3 + ...-detect-extern-generated-name-collision.rs | 2 + .../raw-dylib/windows/dlltool-failed.rs | 2 + .../raw-dylib/windows/invalid-dlltool.rs | 2 + tests/ui/lint/expansion-time.rs | 2 + tests/ui/lint/lint-unexported-no-mangle.rs | 7 ++ tests/ui/lto/lto-and-no-bitcode-in-rlib.rs | 2 + tests/ui/macros/include-single-expr.rs | 4 +- tests/ui/mir-dataflow/inits-1.rs | 2 + tests/ui/mir-dataflow/liveness-enum.rs | 2 + tests/ui/mir-dataflow/liveness-projection.rs | 2 + tests/ui/mir-dataflow/liveness-ptr.rs | 2 + tests/ui/mir-dataflow/uninits-1.rs | 2 + tests/ui/mir-dataflow/uninits-2.rs | 2 + tests/ui/mir/enable_passes_validation.rs | 3 + tests/ui/missing/missing-allocator.rs | 2 + .../missing_non_modrs_mod.rs | 2 + .../missing_non_modrs_mod_inline.rs | 2 + .../panic-handler-wrong-location.rs | 2 + tests/ui/parser/issues/issue-94340.rs | 3 + tests/ui/parser/unclosed-delimiter-in-dep.rs | 2 + .../patchable-function-entry-flags.rs | 3 + tests/ui/print-request/invalid-target.rs | 2 + .../proc-macro/inner-attr-non-inline-mod.rs | 5 +- .../inner-attr-non-inline-mod.stderr | 4 +- .../inner-attr-non-inline-mod.stdout | 30 +++---- tests/ui/proc-macro/pretty-print-hack-show.rs | 2 + tests/ui/resolve/parse-error-resolve.rs | 2 + .../caller-location-fnptr-rt-ctfe-equiv.rs | 2 + tests/ui/rmeta/no_optitimized_mir.rs | 2 + tests/ui/runtime/on-broken-pipe/default.rs | 2 + .../ui/runtime/on-broken-pipe/no-flag-arg.rs | 2 + .../runtime/on-broken-pipe/wrong-flag-arg.rs | 2 + tests/ui/rustc-env/min-stack-banana.rs | 3 + .../cfi/canonical-jump-tables-requires-cfi.rs | 2 + .../cfi/generalize-pointers-requires-cfi.rs | 2 + .../cfi/is-incompatible-with-kcfi.rs | 3 + .../cfi/normalize-integers-requires-cfi.rs | 2 + tests/ui/sanitizer/cfi/requires-lto.rs | 2 + ...-rustc-lto-requires-single-codegen-unit.rs | 2 + tests/ui/sanitizer/crt-static.rs | 2 + .../sanitizer/split-lto-unit-requires-lto.rs | 2 + .../warn-stack-protector-unsupported.rs | 4 + tests/ui/symbol-mangling-version/bad-value.rs | 4 + tests/ui/symbol-mangling-version/unstable.rs | 3 + ...d-softfloat-target-feature-flag-disable.rs | 2 + .../ui/target-feature/missing-plusminus-2.rs | 2 + tests/ui/target-feature/missing-plusminus.rs | 2 + .../similar-feature-suggestion.rs | 2 + tests/ui/target-feature/tied-features-cli.rs | 4 + .../tied-features-no-implication-1.rs | 2 + tests/ui/target-feature/unstable-feature.rs | 2 + .../target_modifiers/incompatible_regparm.rs | 2 + .../tool-attributes/duplicate-diagnostic.rs | 7 +- .../duplicate-diagnostic.stderr | 2 +- tests/ui/type/pattern_types/literals.rs | 3 + tests/ui/type/pattern_types/range_patterns.rs | 4 + tests/ui/unpretty/avoid-crash.rs | 2 + 116 files changed, 371 insertions(+), 105 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index c8536b0045cf..98bb9dee76c5 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -202,6 +202,9 @@ several ways to match the message with the line (see the examples below): * `~|`: Associates the error level and message with the *same* line as the *previous comment*. This is more convenient than using multiple carets when there are multiple messages associated with the same line. +* `~?`: Used to match error levels and messages with errors not having line + information. These can be placed on any line in the test file, but are + conventionally placed at the end. Example: @@ -270,10 +273,23 @@ fn main() { //~| ERROR this pattern has 1 field, but the corresponding tuple struct has 3 fields [E0023] ``` +#### Error without line information + +Use `//~?` to match an error without line information. +`//~?` is precise and will not match errors if their line information is available. +It should be preferred to using `error-pattern`, which is imprecise and non-exhaustive. + +```rust,ignore +//@ compile-flags: --print yyyy + +//~? ERROR unknown print request: `yyyy` +``` + ### `error-pattern` -The `error-pattern` [directive](directives.md) can be used for messages that don't -have a specific span. +The `error-pattern` [directive](directives.md) can be used for runtime messages, which don't +have a specific span, or for compile time messages if imprecise matching is required due to +multi-line platform specific diagnostics. Let's think about this test: @@ -300,7 +316,9 @@ fn main() { } ``` -But for strict testing, try to use the `ERROR` annotation as much as possible. +But for strict testing, try to use the `ERROR` annotation as much as possible, +including `//~?` annotations for diagnostics without span. +For compile time diagnostics `error-pattern` should very rarely be necessary. ### Error levels @@ -353,7 +371,7 @@ would be a `.mir.stderr` and `.thir.stderr` file with the different outputs of the different revisions. > Note: cfg revisions also work inside the source code with `#[cfg]` attributes. -> +> > By convention, the `FALSE` cfg is used to have an always-false config. ## Controlling pass/fail expectations diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index 37ef63ae42ea..c0566ef93b92 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -9,8 +9,6 @@ use std::sync::OnceLock; use regex::Regex; use tracing::*; -use self::WhichLine::*; - #[derive(Copy, Clone, Debug, PartialEq)] pub enum ErrorKind { Help, @@ -50,7 +48,7 @@ impl fmt::Display for ErrorKind { #[derive(Debug)] pub struct Error { - pub line_num: usize, + pub line_num: Option, /// What kind of message we expect (e.g., warning, error, suggestion). /// `None` if not specified or unknown message kind. pub kind: Option, @@ -63,17 +61,14 @@ impl Error { format!( "{: <10}line {: >3}: {}", self.kind.map(|kind| kind.to_string()).unwrap_or_default().to_uppercase(), - self.line_num, + self.line_num_str(), self.msg.cyan(), ) } -} -#[derive(PartialEq, Debug)] -enum WhichLine { - ThisLine, - FollowPrevious(usize), - AdjustBackward(usize), + pub fn line_num_str(&self) -> String { + self.line_num.map_or("?".to_string(), |line_num| line_num.to_string()) + } } /// Looks for either "//~| KIND MESSAGE" or "//~^^... KIND MESSAGE" @@ -105,12 +100,10 @@ pub fn load_errors(testfile: &Path, revision: Option<&str>) -> Vec { .filter(|(_, line)| line.is_ok()) .filter_map(|(line_num, line)| { parse_expected(last_nonfollow_error, line_num + 1, &line.unwrap(), revision).map( - |(which, error)| { - match which { - FollowPrevious(_) => {} - _ => last_nonfollow_error = Some(error.line_num), + |(follow_prev, error)| { + if !follow_prev { + last_nonfollow_error = error.line_num; } - error }, ) @@ -123,18 +116,19 @@ fn parse_expected( line_num: usize, line: &str, test_revision: Option<&str>, -) -> Option<(WhichLine, Error)> { +) -> Option<(bool, Error)> { // Matches comments like: // //~ // //~| // //~^ // //~^^^^^ + // //~? // //[rev1]~ // //[rev1,rev2]~^^ static RE: OnceLock = OnceLock::new(); let captures = RE - .get_or_init(|| Regex::new(r"//(?:\[(?P[\w\-,]+)])?~(?P\||\^*)").unwrap()) + .get_or_init(|| Regex::new(r"//(?:\[(?P[\w\-,]+)])?~(?P\?|\||\^*)").unwrap()) .captures(line)?; match (test_revision, captures.name("revs")) { @@ -151,11 +145,6 @@ fn parse_expected( (Some(_), None) | (None, None) => {} } - let (follow, adjusts) = match &captures["adjust"] { - "|" => (true, 0), - circumflexes => (false, circumflexes.len()), - }; - // Get the part of the comment after the sigil (e.g. `~^^` or ~|). let whole_match = captures.get(0).unwrap(); let (_, mut msg) = line.split_at(whole_match.end()); @@ -170,28 +159,24 @@ fn parse_expected( let msg = msg.trim().to_owned(); - let (which, line_num) = if follow { - assert_eq!(adjusts, 0, "use either //~| or //~^, not both."); - let line_num = last_nonfollow_error.expect( - "encountered //~| without \ - preceding //~^ line.", - ); - (FollowPrevious(line_num), line_num) + let line_num_adjust = &captures["adjust"]; + let (follow_prev, line_num) = if line_num_adjust == "|" { + (true, Some(last_nonfollow_error.expect("encountered //~| without preceding //~^ line"))) + } else if line_num_adjust == "?" { + (false, None) } else { - let which = if adjusts > 0 { AdjustBackward(adjusts) } else { ThisLine }; - let line_num = line_num - adjusts; - (which, line_num) + (false, Some(line_num - line_num_adjust.len())) }; debug!( - "line={} tag={:?} which={:?} kind={:?} msg={:?}", + "line={:?} tag={:?} follow_prev={:?} kind={:?} msg={:?}", line_num, whole_match.as_str(), - which, + follow_prev, kind, msg ); - Some((which, Error { line_num, kind, msg })) + Some((follow_prev, Error { line_num, kind, msg })) } #[cfg(test)] diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs index 0da93dcafa20..9bc26fedf8f4 100644 --- a/src/tools/compiletest/src/json.rs +++ b/src/tools/compiletest/src/json.rs @@ -2,7 +2,9 @@ use std::path::{Path, PathBuf}; use std::str::FromStr; +use std::sync::OnceLock; +use regex::Regex; use serde::Deserialize; use crate::errors::{Error, ErrorKind}; @@ -213,36 +215,24 @@ fn push_expected_errors( // also ensure that `//~ ERROR E123` *always* works. The // assumption is that these multi-line error messages are on their // way out anyhow. - let with_code = |span: &DiagnosticSpan, text: &str| { - match diagnostic.code { - Some(ref code) => - // FIXME(#33000) -- it'd be better to use a dedicated - // UI harness than to include the line/col number like - // this, but some current tests rely on it. - // - // Note: Do NOT include the filename. These can easily - // cause false matches where the expected message - // appears in the filename, and hence the message - // changes but the test still passes. - { - format!( - "{}:{}: {}:{}: {} [{}]", - span.line_start, - span.column_start, - span.line_end, - span.column_end, - text, - code.code.clone() - ) - } - None => - // FIXME(#33000) -- it'd be better to use a dedicated UI harness - { - format!( - "{}:{}: {}:{}: {}", - span.line_start, span.column_start, span.line_end, span.column_end, text - ) + let with_code = |span: Option<&DiagnosticSpan>, text: &str| { + // FIXME(#33000) -- it'd be better to use a dedicated + // UI harness than to include the line/col number like + // this, but some current tests rely on it. + // + // Note: Do NOT include the filename. These can easily + // cause false matches where the expected message + // appears in the filename, and hence the message + // changes but the test still passes. + let span_str = match span { + Some(DiagnosticSpan { line_start, column_start, line_end, column_end, .. }) => { + format!("{line_start}:{column_start}: {line_end}:{column_end}") } + None => format!("?:?: ?:?"), + }; + match &diagnostic.code { + Some(code) => format!("{span_str}: {text} [{}]", code.code), + None => format!("{span_str}: {text}"), } }; @@ -251,19 +241,41 @@ fn push_expected_errors( // more structured shortly anyhow. let mut message_lines = diagnostic.message.lines(); if let Some(first_line) = message_lines.next() { - for span in primary_spans { - let msg = with_code(span, first_line); + let ignore = |s| { + static RE: OnceLock = OnceLock::new(); + RE.get_or_init(|| { + Regex::new(r"aborting due to \d+ previous errors?|\d+ warnings? emitted").unwrap() + }) + .is_match(s) + }; + + if primary_spans.is_empty() && !ignore(first_line) { + let msg = with_code(None, first_line); let kind = ErrorKind::from_str(&diagnostic.level).ok(); - expected_errors.push(Error { line_num: span.line_start, kind, msg }); + expected_errors.push(Error { line_num: None, kind, msg }); + } else { + for span in primary_spans { + let msg = with_code(Some(span), first_line); + let kind = ErrorKind::from_str(&diagnostic.level).ok(); + expected_errors.push(Error { line_num: Some(span.line_start), kind, msg }); + } } } for next_line in message_lines { - for span in primary_spans { + if primary_spans.is_empty() { expected_errors.push(Error { - line_num: span.line_start, + line_num: None, kind: None, - msg: with_code(span, next_line), + msg: with_code(None, next_line), }); + } else { + for span in primary_spans { + expected_errors.push(Error { + line_num: Some(span.line_start), + kind: None, + msg: with_code(Some(span), next_line), + }); + } } } @@ -272,7 +284,7 @@ fn push_expected_errors( if let Some(ref suggested_replacement) = span.suggested_replacement { for (index, line) in suggested_replacement.lines().enumerate() { expected_errors.push(Error { - line_num: span.line_start + index, + line_num: Some(span.line_start + index), kind: Some(ErrorKind::Suggestion), msg: line.to_string(), }); @@ -290,7 +302,7 @@ fn push_expected_errors( // Add notes for any labels that appear in the message. for span in spans_in_this_file.iter().filter(|span| span.label.is_some()) { expected_errors.push(Error { - line_num: span.line_start, + line_num: Some(span.line_start), kind: Some(ErrorKind::Note), msg: span.label.clone().unwrap(), }); @@ -309,7 +321,7 @@ fn push_backtrace( ) { if Path::new(&expansion.span.file_name) == Path::new(&file_name) { expected_errors.push(Error { - line_num: expansion.span.line_start, + line_num: Some(expansion.span.line_start), kind: Some(ErrorKind::Note), msg: format!("in this expansion of {}", expansion.macro_decl_name), }); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 6e250ca12c93..c8a60b68da8b 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -747,7 +747,7 @@ impl<'test> TestCx<'test> { self.error(&format!( "{}:{}: unexpected {}: '{}'", file_name, - actual_error.line_num, + actual_error.line_num_str(), actual_error .kind .as_ref() @@ -767,7 +767,7 @@ impl<'test> TestCx<'test> { self.error(&format!( "{}:{}: expected {} not found: {}", file_name, - expected_error.line_num, + expected_error.line_num_str(), expected_error.kind.as_ref().map_or("message".into(), |k| k.to_string()), expected_error.msg )); diff --git a/src/tools/compiletest/src/runtest/ui.rs b/src/tools/compiletest/src/runtest/ui.rs index 3329e10745f8..9b5b8b56b600 100644 --- a/src/tools/compiletest/src/runtest/ui.rs +++ b/src/tools/compiletest/src/runtest/ui.rs @@ -182,7 +182,7 @@ impl TestCx<'_> { } else if explicit && !expected_errors.is_empty() { let msg = format!( "line {}: cannot combine `--error-format` with {} annotations; use `error-pattern` instead", - expected_errors[0].line_num, + expected_errors[0].line_num_str(), expected_errors[0].kind.unwrap_or(ErrorKind::Error), ); self.fatal(&msg); diff --git a/tests/rustdoc-ui/coverage/html.rs b/tests/rustdoc-ui/coverage/html.rs index 41e1ce1609dc..7fd080f07582 100644 --- a/tests/rustdoc-ui/coverage/html.rs +++ b/tests/rustdoc-ui/coverage/html.rs @@ -2,3 +2,5 @@ /// Foo pub struct Xo; + +//~? ERROR `--output-format=html` is not supported for the `--show-coverage` option diff --git a/tests/rustdoc-ui/deprecated-attrs.rs b/tests/rustdoc-ui/deprecated-attrs.rs index 3b59e05a012e..0ae65a5eaf7c 100644 --- a/tests/rustdoc-ui/deprecated-attrs.rs +++ b/tests/rustdoc-ui/deprecated-attrs.rs @@ -19,3 +19,7 @@ //~| NOTE see issue #44136 //~| NOTE no longer functions //~| NOTE `doc(plugins)` is now a no-op + +//~? WARN the `passes` flag no longer functions +//~? NOTE see issue #44136 +//~? HELP you may want to use --document-private-items diff --git a/tests/rustdoc-ui/doctest-output.rs b/tests/rustdoc-ui/doctest-output.rs index 720f2952980e..28364c3a3ea5 100644 --- a/tests/rustdoc-ui/doctest-output.rs +++ b/tests/rustdoc-ui/doctest-output.rs @@ -1 +1,3 @@ //@ compile-flags:-Z unstable-options --show-coverage --output-format=doctest + +//~? ERROR `--output-format=doctest` is not supported for the `--show-coverage` option diff --git a/tests/rustdoc-ui/generate-link-to-definition/generate-link-to-definition-opt.rs b/tests/rustdoc-ui/generate-link-to-definition/generate-link-to-definition-opt.rs index babdbd0a6921..9d6ec0caf9f4 100644 --- a/tests/rustdoc-ui/generate-link-to-definition/generate-link-to-definition-opt.rs +++ b/tests/rustdoc-ui/generate-link-to-definition/generate-link-to-definition-opt.rs @@ -5,3 +5,5 @@ //@ check-pass pub fn f() {} + +//~? WARN `--generate-link-to-definition` option can only be used with HTML output format diff --git a/tests/rustdoc-ui/include-str-bare-urls.rs b/tests/rustdoc-ui/include-str-bare-urls.rs index c452c88cdd3d..f80e28e8ca70 100644 --- a/tests/rustdoc-ui/include-str-bare-urls.rs +++ b/tests/rustdoc-ui/include-str-bare-urls.rs @@ -13,3 +13,5 @@ #![deny(rustdoc::bare_urls)] #![doc=include_str!("auxiliary/include-str-bare-urls.md")] + +//~? ERROR this URL is not a hyperlink diff --git a/tests/rustdoc-ui/lints/check.rs b/tests/rustdoc-ui/lints/check.rs index 61c9f1889529..0943f9f6053e 100644 --- a/tests/rustdoc-ui/lints/check.rs +++ b/tests/rustdoc-ui/lints/check.rs @@ -12,3 +12,5 @@ pub fn foo() {} //~^ WARN //~^^ WARN + +//~? WARN no documentation found for this crate's top-level module diff --git a/tests/rustdoc-ui/remap-path-prefix-lint.rs b/tests/rustdoc-ui/remap-path-prefix-lint.rs index f27863e825d9..d003e19f200d 100644 --- a/tests/rustdoc-ui/remap-path-prefix-lint.rs +++ b/tests/rustdoc-ui/remap-path-prefix-lint.rs @@ -8,3 +8,5 @@ /// pub struct Bar; + +//~? ERROR unopened HTML tag `script` diff --git a/tests/rustdoc-ui/scrape-examples/scrape-examples-fail-if-type-error.rs b/tests/rustdoc-ui/scrape-examples/scrape-examples-fail-if-type-error.rs index 4fb5c9ab36fa..c8e82d3a20b5 100644 --- a/tests/rustdoc-ui/scrape-examples/scrape-examples-fail-if-type-error.rs +++ b/tests/rustdoc-ui/scrape-examples/scrape-examples-fail-if-type-error.rs @@ -5,3 +5,5 @@ pub fn foo() { INVALID_FUNC(); //~^ ERROR could not resolve path } + +//~? ERROR Compilation failed, aborting rustdoc diff --git a/tests/rustdoc-ui/scrape-examples/scrape-examples-wrong-options-1.rs b/tests/rustdoc-ui/scrape-examples/scrape-examples-wrong-options-1.rs index df7b41e20f6f..3db7924dbe14 100644 --- a/tests/rustdoc-ui/scrape-examples/scrape-examples-wrong-options-1.rs +++ b/tests/rustdoc-ui/scrape-examples/scrape-examples-wrong-options-1.rs @@ -1 +1,3 @@ //@ compile-flags: -Z unstable-options --scrape-examples-target-crate foobar + +//~? ERROR must use --scrape-examples-output-path and --scrape-examples-target-crate together diff --git a/tests/rustdoc-ui/scrape-examples/scrape-examples-wrong-options-2.rs b/tests/rustdoc-ui/scrape-examples/scrape-examples-wrong-options-2.rs index ef270a08f48b..7b6a30291ce8 100644 --- a/tests/rustdoc-ui/scrape-examples/scrape-examples-wrong-options-2.rs +++ b/tests/rustdoc-ui/scrape-examples/scrape-examples-wrong-options-2.rs @@ -1 +1,3 @@ //@ compile-flags: -Z unstable-options --scrape-examples-output-path ex.calls + +//~? ERROR must use --scrape-examples-output-path and --scrape-examples-target-crate together diff --git a/tests/rustdoc-ui/use_both_out_dir_and_output_options.rs b/tests/rustdoc-ui/use_both_out_dir_and_output_options.rs index 62d3d955855e..42847203d489 100644 --- a/tests/rustdoc-ui/use_both_out_dir_and_output_options.rs +++ b/tests/rustdoc-ui/use_both_out_dir_and_output_options.rs @@ -1 +1,3 @@ //@ compile-flags: --output ./foo + +//~? ERROR cannot use both 'out-dir' and 'output' at once diff --git a/tests/ui/asm/inline-syntax.rs b/tests/ui/asm/inline-syntax.rs index adbda369b6a7..78f30d50d8c0 100644 --- a/tests/ui/asm/inline-syntax.rs +++ b/tests/ui/asm/inline-syntax.rs @@ -58,3 +58,8 @@ pub fn main() { global_asm!(".intel_syntax noprefix", "nop"); //[x86_64]~^ WARN avoid using `.intel_syntax` // Global assembly errors don't have line numbers, so no error on ARM. + +//[arm_llvm_18]~? ERROR unknown directive +//[arm_llvm_18]~? ERROR unknown directive +//[arm]~? ERROR unknown directive +//[arm]~? ERROR unknown directive diff --git a/tests/ui/cfg/disallowed-cli-cfgs.rs b/tests/ui/cfg/disallowed-cli-cfgs.rs index cae9c65cb45a..e9661abf3abe 100644 --- a/tests/ui/cfg/disallowed-cli-cfgs.rs +++ b/tests/ui/cfg/disallowed-cli-cfgs.rs @@ -37,3 +37,5 @@ //@ [emscripten_wasm_eh_]compile-flags: --cfg emscripten_wasm_eh fn main() {} + +//~? ERROR unexpected `--cfg diff --git a/tests/ui/check-cfg/invalid-arguments.rs b/tests/ui/check-cfg/invalid-arguments.rs index c6b1218ce27c..3bea128e3e42 100644 --- a/tests/ui/check-cfg/invalid-arguments.rs +++ b/tests/ui/check-cfg/invalid-arguments.rs @@ -36,3 +36,5 @@ //@ [unsafe_attr]compile-flags: --check-cfg=unsafe(cfg(foo)) fn main() {} + +//~? ERROR invalid `--check-cfg` argument diff --git a/tests/ui/codegen/duplicated-path-in-error.rs b/tests/ui/codegen/duplicated-path-in-error.rs index cff20dd9bd63..a446395de208 100644 --- a/tests/ui/codegen/duplicated-path-in-error.rs +++ b/tests/ui/codegen/duplicated-path-in-error.rs @@ -5,3 +5,5 @@ // the path of the dylib. fn main() {} + +//~? ERROR couldn't load codegen backend /non-existing-one.so diff --git a/tests/ui/consts/const-eval/const_fn_ptr.rs b/tests/ui/consts/const-eval/const_fn_ptr.rs index f8a2658f31e6..1d65eedb93d0 100644 --- a/tests/ui/consts/const-eval/const_fn_ptr.rs +++ b/tests/ui/consts/const-eval/const_fn_ptr.rs @@ -34,3 +34,5 @@ fn main() { let z = foo(double, 2); assert_eq!(z, 4); } + +//~? WARN skipping const checks diff --git a/tests/ui/consts/const-eval/const_fn_ptr_fail.rs b/tests/ui/consts/const-eval/const_fn_ptr_fail.rs index a0f804722dbb..00bf0ed0eba0 100644 --- a/tests/ui/consts/const-eval/const_fn_ptr_fail.rs +++ b/tests/ui/consts/const-eval/const_fn_ptr_fail.rs @@ -10,3 +10,5 @@ const fn bar(x: usize) -> usize { } fn main() {} + +//~? WARN skipping const checks diff --git a/tests/ui/consts/const-eval/const_fn_ptr_fail2.rs b/tests/ui/consts/const-eval/const_fn_ptr_fail2.rs index 7db8c6e81ab5..c6ae3af44270 100644 --- a/tests/ui/consts/const-eval/const_fn_ptr_fail2.rs +++ b/tests/ui/consts/const-eval/const_fn_ptr_fail2.rs @@ -24,3 +24,5 @@ fn main() { assert_eq!(Y, 4); assert_eq!(Z, 4); } + +//~? WARN skipping const checks diff --git a/tests/ui/consts/const-eval/issue-85155.rs b/tests/ui/consts/const-eval/issue-85155.rs index 95253a0b288f..cb5b3a08375d 100644 --- a/tests/ui/consts/const-eval/issue-85155.rs +++ b/tests/ui/consts/const-eval/issue-85155.rs @@ -19,3 +19,6 @@ fn main() { post_monomorphization_error::stdarch_intrinsic::<2>(); //~^ NOTE the above error was encountered while instantiating } + +//~? ERROR evaluation of `post_monomorphization_error::ValidateConstImm::<2, 0, 1>::VALID` failed +//~? NOTE erroneous constant encountered diff --git a/tests/ui/consts/miri_unleashed/abi-mismatch.rs b/tests/ui/consts/miri_unleashed/abi-mismatch.rs index ea640ae78d55..0a2b3f3abd62 100644 --- a/tests/ui/consts/miri_unleashed/abi-mismatch.rs +++ b/tests/ui/consts/miri_unleashed/abi-mismatch.rs @@ -13,3 +13,5 @@ static VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn //~| NOTE calling a function with calling convention C using calling convention Rust fn main() {} + +//~? WARN skipping const checks diff --git a/tests/ui/consts/miri_unleashed/assoc_const.rs b/tests/ui/consts/miri_unleashed/assoc_const.rs index 96b47ff4e5e2..812207ee8090 100644 --- a/tests/ui/consts/miri_unleashed/assoc_const.rs +++ b/tests/ui/consts/miri_unleashed/assoc_const.rs @@ -28,3 +28,5 @@ fn main() { // this test only causes errors due to the line below, so post-monomorphization let y = , String>>::F; } + +//~? WARN skipping const checks diff --git a/tests/ui/consts/miri_unleashed/box.rs b/tests/ui/consts/miri_unleashed/box.rs index 89df4526b077..1539083f09c2 100644 --- a/tests/ui/consts/miri_unleashed/box.rs +++ b/tests/ui/consts/miri_unleashed/box.rs @@ -9,3 +9,5 @@ static TEST_BAD: &mut i32 = { //~^ ERROR could not evaluate static initializer //~| NOTE calling non-const function `Box::::new` }; + +//~? WARN skipping const checks diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static.rs b/tests/ui/consts/miri_unleashed/const_refers_to_static.rs index a6691fa2a2f1..fdccc17ab49a 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static.rs +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static.rs @@ -31,3 +31,5 @@ const REF_IMMUT: &u8 = &MY_STATIC; const READ_IMMUT: u8 = *REF_IMMUT; fn main() {} + +//~? WARN skipping const checks diff --git a/tests/ui/consts/miri_unleashed/inline_asm.rs b/tests/ui/consts/miri_unleashed/inline_asm.rs index 8627a6bf8870..f1ce613b16e8 100644 --- a/tests/ui/consts/miri_unleashed/inline_asm.rs +++ b/tests/ui/consts/miri_unleashed/inline_asm.rs @@ -11,3 +11,5 @@ static TEST_BAD: () = { //~^ ERROR could not evaluate static initializer //~| NOTE inline assembly is not supported }; + +//~? WARN skipping const checks diff --git a/tests/ui/consts/miri_unleashed/mutable_references.rs b/tests/ui/consts/miri_unleashed/mutable_references.rs index 039d0fadfcc4..e7fc5699236e 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references.rs +++ b/tests/ui/consts/miri_unleashed/mutable_references.rs @@ -114,3 +114,5 @@ fn main() { } *OH_YES = 99; //~ ERROR cannot assign to `*OH_YES`, as `OH_YES` is an immutable static item } + +//~? WARN skipping const checks diff --git a/tests/ui/consts/miri_unleashed/non_const_fn.rs b/tests/ui/consts/miri_unleashed/non_const_fn.rs index d3ffb61af118..201647ac8d88 100644 --- a/tests/ui/consts/miri_unleashed/non_const_fn.rs +++ b/tests/ui/consts/miri_unleashed/non_const_fn.rs @@ -9,3 +9,5 @@ static C: () = foo(); //~| NOTE calling non-const function `foo` fn main() {} + +//~? WARN skipping const checks diff --git a/tests/ui/consts/miri_unleashed/ptr_arith.rs b/tests/ui/consts/miri_unleashed/ptr_arith.rs index 6dd8ab11e7cf..4e1183220792 100644 --- a/tests/ui/consts/miri_unleashed/ptr_arith.rs +++ b/tests/ui/consts/miri_unleashed/ptr_arith.rs @@ -21,3 +21,5 @@ static PTR_INT_TRANSMUTE: () = unsafe { // their `PartialEq` impl is non-`const`. fn main() {} + +//~? WARN skipping const checks diff --git a/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs b/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs index 126d78158fe0..7fa173d8d9d8 100644 --- a/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs +++ b/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs @@ -38,3 +38,5 @@ static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; //~^ ERROR mutable pointer in final value fn main() {} + +//~? WARN skipping const checks diff --git a/tests/ui/consts/miri_unleashed/tls.rs b/tests/ui/consts/miri_unleashed/tls.rs index b0c6c088361c..ab23a5249988 100644 --- a/tests/ui/consts/miri_unleashed/tls.rs +++ b/tests/ui/consts/miri_unleashed/tls.rs @@ -23,3 +23,5 @@ static TEST_BAD_REF: () = { }; fn main() {} + +//~? WARN skipping const checks diff --git a/tests/ui/dep-graph/dep-graph-dump.rs b/tests/ui/dep-graph/dep-graph-dump.rs index 7aede27d125c..5dc05045e828 100644 --- a/tests/ui/dep-graph/dep-graph-dump.rs +++ b/tests/ui/dep-graph/dep-graph-dump.rs @@ -4,3 +4,5 @@ //@ compile-flags: -Z dump-dep-graph fn main() {} + +//~? ERROR can't dump dependency graph without `-Z query-dep-graph` diff --git a/tests/ui/deprecation/deprecated_ar.rs b/tests/ui/deprecation/deprecated_ar.rs index 404d062e6a44..00862d2c00a2 100644 --- a/tests/ui/deprecation/deprecated_ar.rs +++ b/tests/ui/deprecation/deprecated_ar.rs @@ -2,3 +2,5 @@ //@ compile-flags: -Car=foo fn main() {} + +//~? WARN `-C ar`: this option is deprecated and does nothing diff --git a/tests/ui/deprecation/deprecated_inline_threshold.rs b/tests/ui/deprecation/deprecated_inline_threshold.rs index b54fa36397af..284a6d6798e4 100644 --- a/tests/ui/deprecation/deprecated_inline_threshold.rs +++ b/tests/ui/deprecation/deprecated_inline_threshold.rs @@ -6,3 +6,9 @@ //@[no_val] compile-flags: -Cinline-threshold fn main() {} + +//[good_val]~? WARN `-C inline-threshold`: this option is deprecated and does nothing +//[bad_val]~? WARN `-C inline-threshold`: this option is deprecated and does nothing +//[bad_val]~? ERROR incorrect value `asd` for codegen option `inline-threshold` +//[no_val]~? WARN `-C inline-threshold`: this option is deprecated and does nothing +//[no_val]~? ERROR codegen option `inline-threshold` requires a number diff --git a/tests/ui/deprecation/deprecated_no_stack_check_opt.rs b/tests/ui/deprecation/deprecated_no_stack_check_opt.rs index 62584ec23e33..e014c7e80aff 100644 --- a/tests/ui/deprecation/deprecated_no_stack_check_opt.rs +++ b/tests/ui/deprecation/deprecated_no_stack_check_opt.rs @@ -2,3 +2,5 @@ //@ compile-flags: -Cno-stack-check fn main() {} + +//~? WARN `-C no-stack-check`: this option is deprecated and does nothing diff --git a/tests/ui/did_you_mean/recursion_limit_deref.rs b/tests/ui/did_you_mean/recursion_limit_deref.rs index af4c4ddda69a..e53007388af2 100644 --- a/tests/ui/did_you_mean/recursion_limit_deref.rs +++ b/tests/ui/did_you_mean/recursion_limit_deref.rs @@ -51,3 +51,6 @@ fn main() { let x: &Bottom = &t; //~ ERROR mismatched types //~^ error recursion limit } + +//~? ERROR reached the recursion limit finding the struct tail for `K` +//~? ERROR reached the recursion limit finding the struct tail for `Bottom` diff --git a/tests/ui/editions/edition-keywords-2018-2015-parsing.rs b/tests/ui/editions/edition-keywords-2018-2015-parsing.rs index c3dfcfb19cb4..f8d2755b9d79 100644 --- a/tests/ui/editions/edition-keywords-2018-2015-parsing.rs +++ b/tests/ui/editions/edition-keywords-2018-2015-parsing.rs @@ -28,3 +28,5 @@ pub fn check_async() { let _recovery_witness: () = 0; //~ ERROR mismatched types } + +//~? ERROR macro expansion ends with an incomplete expression diff --git a/tests/ui/editions/edition-keywords-2018-2018-parsing.rs b/tests/ui/editions/edition-keywords-2018-2018-parsing.rs index 1447c49ef717..f4438472a0e6 100644 --- a/tests/ui/editions/edition-keywords-2018-2018-parsing.rs +++ b/tests/ui/editions/edition-keywords-2018-2018-parsing.rs @@ -39,3 +39,5 @@ pub fn check_async() { let _recovery_witness: () = 0; //~ ERROR mismatched types } + +//~? ERROR macro expansion ends with an incomplete expression diff --git a/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.rs b/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.rs index d8ae12d200f4..0b527baaafe7 100644 --- a/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.rs +++ b/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.rs @@ -2,3 +2,5 @@ extern crate bad_main_functions; pub use bad_main_functions::boilerplate as main; + +//~? ERROR `main` function has wrong type diff --git a/tests/ui/errors/wrong-target-spec.rs b/tests/ui/errors/wrong-target-spec.rs index bc9038c1fab5..9b31c943e3e9 100644 --- a/tests/ui/errors/wrong-target-spec.rs +++ b/tests/ui/errors/wrong-target-spec.rs @@ -6,3 +6,5 @@ //@ compile-flags: --target x86_64_unknown-linux-musl fn main() {} + +//~? ERROR Error loading target specification: Could not find specification for target "x86_64_unknown-linux-musl" diff --git a/tests/ui/feature-gates/feature-gate-link-arg-attribute.rs b/tests/ui/feature-gates/feature-gate-link-arg-attribute.rs index c12ff5b04dc3..8e11a05c89be 100644 --- a/tests/ui/feature-gates/feature-gate-link-arg-attribute.rs +++ b/tests/ui/feature-gates/feature-gate-link-arg-attribute.rs @@ -7,3 +7,5 @@ extern "C" {} fn main() {} + +//[in_flag]~? ERROR unknown linking modifier `link-arg` diff --git a/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs b/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs index c2965e42f276..c5859eec8db5 100644 --- a/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs +++ b/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs @@ -7,3 +7,5 @@ extern "C" {} fn main() {} + +//[in_flag]~? ERROR linking modifier `as-needed` is unstable diff --git a/tests/ui/fmt/fmt_debug/invalid.rs b/tests/ui/fmt/fmt_debug/invalid.rs index 09cb46f1ea6e..f2652fe277d1 100644 --- a/tests/ui/fmt/fmt_debug/invalid.rs +++ b/tests/ui/fmt/fmt_debug/invalid.rs @@ -2,3 +2,5 @@ //@ failure-status: 1 fn main() { } + +//~? ERROR incorrect value `invalid-value` for unstable option `fmt-debug` diff --git a/tests/ui/infinite/infinite-struct.rs b/tests/ui/infinite/infinite-struct.rs index 62f9702b9f41..fd47a4ec9cc6 100644 --- a/tests/ui/infinite/infinite-struct.rs +++ b/tests/ui/infinite/infinite-struct.rs @@ -15,3 +15,5 @@ struct Foo { //~ ERROR has infinite size struct Bar([T; 1]); fn main() {} + +//~? ERROR reached the recursion limit finding the struct tail for `Take` diff --git a/tests/ui/instrument-coverage/bad-value.rs b/tests/ui/instrument-coverage/bad-value.rs index 344173852916..d44f982ea46f 100644 --- a/tests/ui/instrument-coverage/bad-value.rs +++ b/tests/ui/instrument-coverage/bad-value.rs @@ -3,3 +3,6 @@ //@ [bad] compile-flags: -Cinstrument-coverage=bad-value fn main() {} + +//[blank]~? ERROR incorrect value `` for codegen option `instrument-coverage` +//[bad]~? ERROR incorrect value `bad-value` for codegen option `instrument-coverage` diff --git a/tests/ui/instrument-coverage/coverage-options.rs b/tests/ui/instrument-coverage/coverage-options.rs index 7615a0fb2751..c3eae9625da9 100644 --- a/tests/ui/instrument-coverage/coverage-options.rs +++ b/tests/ui/instrument-coverage/coverage-options.rs @@ -17,3 +17,5 @@ //@ [bad] compile-flags: -Zcoverage-options=bad fn main() {} + +//[bad]~? ERROR incorrect value `bad` for unstable option `coverage-options` diff --git a/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.rs b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.rs index b4025080034a..2a39d579c51f 100644 --- a/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.rs +++ b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.rs @@ -15,3 +15,7 @@ #[lang = "sized"] trait Sized {} + +//[BADFLAGS]~? ERROR incorrect value `leaf` for unstable option `branch-protection` +//[BADFLAGSPC]~? ERROR incorrect value `pc` for unstable option `branch-protection` +//[BADTARGET]~? ERROR `-Zbranch-protection` is only supported on aarch64 diff --git a/tests/ui/invalid-compile-flags/invalid-llvm-passes.rs b/tests/ui/invalid-compile-flags/invalid-llvm-passes.rs index ddb46e597111..832821c9c883 100644 --- a/tests/ui/invalid-compile-flags/invalid-llvm-passes.rs +++ b/tests/ui/invalid-compile-flags/invalid-llvm-passes.rs @@ -2,3 +2,5 @@ //@ compile-flags: -Cpasses=unknown-pass fn main() {} + +//~? ERROR failed to run LLVM passes: unknown pass name 'unknown-pass' diff --git a/tests/ui/invalid-compile-flags/need-crate-arg-ignore-tidy$x.rs b/tests/ui/invalid-compile-flags/need-crate-arg-ignore-tidy$x.rs index b1ac4a4ae216..0e80b1dd178b 100644 --- a/tests/ui/invalid-compile-flags/need-crate-arg-ignore-tidy$x.rs +++ b/tests/ui/invalid-compile-flags/need-crate-arg-ignore-tidy$x.rs @@ -1,2 +1,5 @@ // issue: 113981 + pub fn main() {} + +//~? ERROR invalid character '$' in crate name: `need_crate_arg_ignore_tidy$x` diff --git a/tests/ui/invalid-compile-flags/print.rs b/tests/ui/invalid-compile-flags/print.rs index 0d0a9d22750d..4665bb2c5368 100644 --- a/tests/ui/invalid-compile-flags/print.rs +++ b/tests/ui/invalid-compile-flags/print.rs @@ -1 +1,3 @@ //@ compile-flags: --print yyyy + +//~? ERROR unknown print request: `yyyy` diff --git a/tests/ui/invalid-module-declaration/invalid-module-declaration.rs b/tests/ui/invalid-module-declaration/invalid-module-declaration.rs index 254d810d79db..1c6c282f4b7e 100644 --- a/tests/ui/invalid-module-declaration/invalid-module-declaration.rs +++ b/tests/ui/invalid-module-declaration/invalid-module-declaration.rs @@ -3,3 +3,5 @@ mod auxiliary { } fn main() {} + +//~? ERROR file not found for module `baz` diff --git a/tests/ui/lang-items/lang-item-generic-requirements.rs b/tests/ui/lang-items/lang-item-generic-requirements.rs index 0f982df61e8e..90ed5f3f0efd 100644 --- a/tests/ui/lang-items/lang-item-generic-requirements.rs +++ b/tests/ui/lang-items/lang-item-generic-requirements.rs @@ -59,3 +59,5 @@ fn ice() { // use `start` fn main() {} + +//~? ERROR requires `copy` lang_item diff --git a/tests/ui/link-native-libs/modifiers-bad.rs b/tests/ui/link-native-libs/modifiers-bad.rs index 185201e0d842..4d6c8a278d4c 100644 --- a/tests/ui/link-native-libs/modifiers-bad.rs +++ b/tests/ui/link-native-libs/modifiers-bad.rs @@ -9,3 +9,8 @@ // Tests various illegal values for the "modifier" part of an `-l` flag. fn main() {} + +//[blank]~? ERROR invalid linking modifier syntax, expected '+' or '-' prefix +//[no-prefix]~? ERROR invalid linking modifier syntax, expected '+' or '-' prefix +//[prefix-only]~? ERROR unknown linking modifier `` +//[unknown]~? ERROR unknown linking modifier `ferris` diff --git a/tests/ui/link-native-libs/modifiers-override-2.rs b/tests/ui/link-native-libs/modifiers-override-2.rs index a462a741ac61..d132f2419d81 100644 --- a/tests/ui/link-native-libs/modifiers-override-2.rs +++ b/tests/ui/link-native-libs/modifiers-override-2.rs @@ -1,3 +1,5 @@ //@ compile-flags:-lstatic:+whole-archive,-whole-archive=foo fn main() {} + +//~? ERROR multiple `whole-archive` modifiers in a single `-l` option diff --git a/tests/ui/link-native-libs/msvc-non-utf8-output.rs b/tests/ui/link-native-libs/msvc-non-utf8-output.rs index 03b1f6516ab9..5cc4cd9a3d6d 100644 --- a/tests/ui/link-native-libs/msvc-non-utf8-output.rs +++ b/tests/ui/link-native-libs/msvc-non-utf8-output.rs @@ -3,3 +3,5 @@ //@ only-msvc //@ normalize-stderr: "(?:.|\n)*(⦺ⅈ⽯⭏⽽◃⡽⚞)(?:.|\n)*" -> "$1" pub fn main() {} + +//~? ERROR linking with ` diff --git a/tests/ui/linkage-attr/link-self-contained-consistency.rs b/tests/ui/linkage-attr/link-self-contained-consistency.rs index def63233e941..082274338916 100644 --- a/tests/ui/linkage-attr/link-self-contained-consistency.rs +++ b/tests/ui/linkage-attr/link-self-contained-consistency.rs @@ -8,3 +8,6 @@ // ignore-tidy-linelength fn main() {} + +//[one]~? ERROR some `-C link-self-contained` components were both enabled and disabled: linker +//[many]~? ERROR some `-C link-self-contained` components were both enabled and disabled: crto, linker diff --git a/tests/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs b/tests/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs index b43df6341121..23848056ee1a 100644 --- a/tests/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs +++ b/tests/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs @@ -22,3 +22,5 @@ fn main() { println!("{:p}", &dep1::collision); } } + +//~? ERROR symbol `collision` is already defined diff --git a/tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.rs b/tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.rs index e69a45379352..92cb60bb16d4 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.rs +++ b/tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.rs @@ -19,3 +19,5 @@ extern "C" { pub fn lib_main() { unsafe { f(42); } } + +//~? ERROR Dlltool could not create import library with diff --git a/tests/ui/linkage-attr/raw-dylib/windows/invalid-dlltool.rs b/tests/ui/linkage-attr/raw-dylib/windows/invalid-dlltool.rs index 057242246f0e..0c78d799bad2 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/invalid-dlltool.rs +++ b/tests/ui/linkage-attr/raw-dylib/windows/invalid-dlltool.rs @@ -10,3 +10,5 @@ extern "C" { pub fn lib_main() { unsafe { f(42); } } + +//~? ERROR Error calling dlltool 'does_not_exist.exe': program not found diff --git a/tests/ui/lint/expansion-time.rs b/tests/ui/lint/expansion-time.rs index d0f26a87385c..3cb4b91ff2b8 100644 --- a/tests/ui/lint/expansion-time.rs +++ b/tests/ui/lint/expansion-time.rs @@ -31,3 +31,5 @@ fn main() { // WARN see in the stderr file, the warning points to the included file. include!("expansion-time-include.rs"); } + +//~? WARN include macro expected single expression in source diff --git a/tests/ui/lint/lint-unexported-no-mangle.rs b/tests/ui/lint/lint-unexported-no-mangle.rs index 63eeb3374d22..65a7fd9d7696 100644 --- a/tests/ui/lint/lint-unexported-no-mangle.rs +++ b/tests/ui/lint/lint-unexported-no-mangle.rs @@ -27,3 +27,10 @@ fn main() { foo(); bar(); } + +//~? WARN lint `private_no_mangle_fns` has been removed +//~? WARN lint `private_no_mangle_statics` has been removed +//~? WARN lint `private_no_mangle_fns` has been removed +//~? WARN lint `private_no_mangle_statics` has been removed +//~? WARN lint `private_no_mangle_fns` has been removed +//~? WARN lint `private_no_mangle_statics` has been removed diff --git a/tests/ui/lto/lto-and-no-bitcode-in-rlib.rs b/tests/ui/lto/lto-and-no-bitcode-in-rlib.rs index f742cd78697f..2f0aeb0b7ba9 100644 --- a/tests/ui/lto/lto-and-no-bitcode-in-rlib.rs +++ b/tests/ui/lto/lto-and-no-bitcode-in-rlib.rs @@ -1,3 +1,5 @@ //@ compile-flags: -C lto -C embed-bitcode=no fn main() {} + +//~? ERROR options `-C embed-bitcode=no` and `-C lto` are incompatible diff --git a/tests/ui/macros/include-single-expr.rs b/tests/ui/macros/include-single-expr.rs index c501f5d97ca5..e3ab1257b42a 100644 --- a/tests/ui/macros/include-single-expr.rs +++ b/tests/ui/macros/include-single-expr.rs @@ -1,6 +1,6 @@ -//@ error-pattern include macro expected single expression - fn main() { include!("include-single-expr-helper.rs"); include!("include-single-expr-helper-1.rs"); } + +//~? ERROR include macro expected single expression diff --git a/tests/ui/mir-dataflow/inits-1.rs b/tests/ui/mir-dataflow/inits-1.rs index 8fb1d4bc736d..3331809f3594 100644 --- a/tests/ui/mir-dataflow/inits-1.rs +++ b/tests/ui/mir-dataflow/inits-1.rs @@ -51,3 +51,5 @@ fn main() { foo(true, &mut S(13), S(14), S(15)); foo(false, &mut S(13), S(14), S(15)); } + +//~? ERROR stop_after_dataflow ended compilation diff --git a/tests/ui/mir-dataflow/liveness-enum.rs b/tests/ui/mir-dataflow/liveness-enum.rs index 5eb04ae8c8d3..515f36698fb4 100644 --- a/tests/ui/mir-dataflow/liveness-enum.rs +++ b/tests/ui/mir-dataflow/liveness-enum.rs @@ -20,3 +20,5 @@ fn foo() -> Option { } fn main() {} + +//~? ERROR stop_after_dataflow ended compilation diff --git a/tests/ui/mir-dataflow/liveness-projection.rs b/tests/ui/mir-dataflow/liveness-projection.rs index 486f31b635dc..edea6ee60f64 100644 --- a/tests/ui/mir-dataflow/liveness-projection.rs +++ b/tests/ui/mir-dataflow/liveness-projection.rs @@ -30,3 +30,5 @@ fn foo() { } fn main() {} + +//~? ERROR stop_after_dataflow ended compilation diff --git a/tests/ui/mir-dataflow/liveness-ptr.rs b/tests/ui/mir-dataflow/liveness-ptr.rs index 786da523a339..704949aa9c89 100644 --- a/tests/ui/mir-dataflow/liveness-ptr.rs +++ b/tests/ui/mir-dataflow/liveness-ptr.rs @@ -26,3 +26,5 @@ fn foo() -> i32 { } fn main() {} + +//~? ERROR stop_after_dataflow ended compilation diff --git a/tests/ui/mir-dataflow/uninits-1.rs b/tests/ui/mir-dataflow/uninits-1.rs index c2b4284a7b4f..c689512833d8 100644 --- a/tests/ui/mir-dataflow/uninits-1.rs +++ b/tests/ui/mir-dataflow/uninits-1.rs @@ -49,3 +49,5 @@ fn main() { foo(true, &mut S(13), S(14), S(15)); foo(false, &mut S(13), S(14), S(15)); } + +//~? ERROR stop_after_dataflow ended compilation diff --git a/tests/ui/mir-dataflow/uninits-2.rs b/tests/ui/mir-dataflow/uninits-2.rs index c584ee74afb4..04daf78e56f7 100644 --- a/tests/ui/mir-dataflow/uninits-2.rs +++ b/tests/ui/mir-dataflow/uninits-2.rs @@ -22,3 +22,5 @@ fn main() { foo(&mut S(13)); foo(&mut S(13)); } + +//~? ERROR stop_after_dataflow ended compilation diff --git a/tests/ui/mir/enable_passes_validation.rs b/tests/ui/mir/enable_passes_validation.rs index 957e7d4d96df..405ada77183b 100644 --- a/tests/ui/mir/enable_passes_validation.rs +++ b/tests/ui/mir/enable_passes_validation.rs @@ -19,3 +19,6 @@ //@[mixed] error-pattern: warning: MIR pass `ThisPassDoesNotExist` is unknown and will be ignored fn main() {} + +//[empty]~? ERROR incorrect value `` for unstable option `mir-enable-passes` +//[unprefixed]~? ERROR incorrect value `CheckAlignment` for unstable option `mir-enable-passes` diff --git a/tests/ui/missing/missing-allocator.rs b/tests/ui/missing/missing-allocator.rs index 3a65e657d0bc..60aa9fcc898b 100644 --- a/tests/ui/missing/missing-allocator.rs +++ b/tests/ui/missing/missing-allocator.rs @@ -16,3 +16,5 @@ fn oom(_: core::alloc::Layout) -> ! { } extern crate alloc; + +//~? ERROR no global memory allocator found but one is required diff --git a/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.rs b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.rs index 4ff975af67d7..b1ac0756688f 100644 --- a/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.rs +++ b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.rs @@ -1,2 +1,4 @@ mod foo; fn main() {} + +//~? ERROR file not found for module `missing` diff --git a/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.rs b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.rs index 9ebb4f1bdbdb..987fe1166d74 100644 --- a/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.rs +++ b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.rs @@ -1,2 +1,4 @@ mod foo_inline; fn main() {} + +//~? ERROR file not found for module `missing` diff --git a/tests/ui/panic-handler/panic-handler-wrong-location.rs b/tests/ui/panic-handler/panic-handler-wrong-location.rs index 49685ee45926..c91580ae0c4c 100644 --- a/tests/ui/panic-handler/panic-handler-wrong-location.rs +++ b/tests/ui/panic-handler/panic-handler-wrong-location.rs @@ -6,3 +6,5 @@ #[panic_handler] //~ ERROR `panic_impl` lang item must be applied to a function #[no_mangle] static X: u32 = 42; + +//~? ERROR `#[panic_handler]` function required, but not found diff --git a/tests/ui/parser/issues/issue-94340.rs b/tests/ui/parser/issues/issue-94340.rs index d0fb84a689a3..4f3dbc6acdd7 100644 --- a/tests/ui/parser/issues/issue-94340.rs +++ b/tests/ui/parser/issues/issue-94340.rs @@ -6,3 +6,6 @@ include!("auxiliary/issue-94340-inc.rs"); fn main() {} + +//~? ERROR an inner attribute is not permitted in this context +//~? ERROR an inner attribute is not permitted in this context diff --git a/tests/ui/parser/unclosed-delimiter-in-dep.rs b/tests/ui/parser/unclosed-delimiter-in-dep.rs index 4de83ee640a7..40f517f317ef 100644 --- a/tests/ui/parser/unclosed-delimiter-in-dep.rs +++ b/tests/ui/parser/unclosed-delimiter-in-dep.rs @@ -3,3 +3,5 @@ mod unclosed_delim_mod; fn main() { let _: usize = unclosed_delim_mod::new(); } + +//~? ERROR mismatched closing delimiter: `}` diff --git a/tests/ui/patchable-function-entry/patchable-function-entry-flags.rs b/tests/ui/patchable-function-entry/patchable-function-entry-flags.rs index cb5bc62b6b34..2d5a0b0a7715 100644 --- a/tests/ui/patchable-function-entry/patchable-function-entry-flags.rs +++ b/tests/ui/patchable-function-entry/patchable-function-entry-flags.rs @@ -1,2 +1,5 @@ //@ compile-flags: -Z patchable-function-entry=1,2 + fn main() {} + +//~? ERROR incorrect value `1,2` for unstable option `patchable-function-entry` diff --git a/tests/ui/print-request/invalid-target.rs b/tests/ui/print-request/invalid-target.rs index 52f09ea73d73..573d5493b25c 100644 --- a/tests/ui/print-request/invalid-target.rs +++ b/tests/ui/print-request/invalid-target.rs @@ -2,3 +2,5 @@ //@ needs-llvm-components: x86 fn main() {} + +//~? ERROR only Apple targets currently support deployment version info diff --git a/tests/ui/proc-macro/inner-attr-non-inline-mod.rs b/tests/ui/proc-macro/inner-attr-non-inline-mod.rs index d4336a7f3e1e..2dcdbf3c4022 100644 --- a/tests/ui/proc-macro/inner-attr-non-inline-mod.rs +++ b/tests/ui/proc-macro/inner-attr-non-inline-mod.rs @@ -1,6 +1,4 @@ //@ compile-flags: -Z span-debug -//@ error-pattern:custom inner attributes are unstable -//@ error-pattern:inner macro attributes are unstable //@ proc-macro: test-macros.rs #![no_std] // Don't load unnecessary hygiene information from std @@ -15,3 +13,6 @@ mod module_with_attrs; //~| ERROR custom inner attributes are unstable fn main() {} + +//~? ERROR custom inner attributes are unstable +//~? ERROR inner macro attributes are unstable diff --git a/tests/ui/proc-macro/inner-attr-non-inline-mod.stderr b/tests/ui/proc-macro/inner-attr-non-inline-mod.stderr index 025eec248188..c0a9385f4c68 100644 --- a/tests/ui/proc-macro/inner-attr-non-inline-mod.stderr +++ b/tests/ui/proc-macro/inner-attr-non-inline-mod.stderr @@ -19,7 +19,7 @@ LL | #![print_attr] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: non-inline modules in proc macro input are unstable - --> $DIR/inner-attr-non-inline-mod.rs:13:1 + --> $DIR/inner-attr-non-inline-mod.rs:11:1 | LL | mod module_with_attrs; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -29,7 +29,7 @@ LL | mod module_with_attrs; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: custom inner attributes are unstable - --> $DIR/inner-attr-non-inline-mod.rs:13:1 + --> $DIR/inner-attr-non-inline-mod.rs:11:1 | LL | mod module_with_attrs; | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/proc-macro/inner-attr-non-inline-mod.stdout b/tests/ui/proc-macro/inner-attr-non-inline-mod.stdout index 450542f68c65..219794a8eb8c 100644 --- a/tests/ui/proc-macro/inner-attr-non-inline-mod.stdout +++ b/tests/ui/proc-macro/inner-attr-non-inline-mod.stdout @@ -4,35 +4,35 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0), + span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "deny", - span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0), + span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "unused_attributes", - span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0), + span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), }, ], - span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0), + span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), }, ], - span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0), + span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), }, Ident { ident: "mod", - span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0), + span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), }, Ident { ident: "module_with_attrs", - span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0), + span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), }, Group { delimiter: Brace, @@ -40,38 +40,38 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Joint, - span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0), + span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), }, Punct { ch: '!', spacing: Alone, - span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0), + span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "rustfmt", - span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0), + span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), }, Punct { ch: ':', spacing: Joint, - span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0), + span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), }, Punct { ch: ':', spacing: Alone, - span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0), + span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), }, Ident { ident: "skip", - span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0), + span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), }, ], - span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0), + span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), }, ], - span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0), + span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), }, ] diff --git a/tests/ui/proc-macro/pretty-print-hack-show.rs b/tests/ui/proc-macro/pretty-print-hack-show.rs index de6453c6a821..70f0d5f6ea97 100644 --- a/tests/ui/proc-macro/pretty-print-hack-show.rs +++ b/tests/ui/proc-macro/pretty-print-hack-show.rs @@ -18,3 +18,5 @@ mod second { } fn main() {} + +//~? ERROR using an old version of `rental` diff --git a/tests/ui/resolve/parse-error-resolve.rs b/tests/ui/resolve/parse-error-resolve.rs index 1e0772648afe..cb15ec764036 100644 --- a/tests/ui/resolve/parse-error-resolve.rs +++ b/tests/ui/resolve/parse-error-resolve.rs @@ -5,3 +5,5 @@ fn main() { let _ = "" + 1; //~ ERROR E0369 parse_error::Canonical.foo(); // ok, `parse_error.rs` had parse errors } + +//~? ERROR expected one of `+`, `,`, `::`, `=`, or `>`, found `From` diff --git a/tests/ui/rfcs/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs b/tests/ui/rfcs/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs index ef970ebd14bc..2b21d3987b9c 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs +++ b/tests/ui/rfcs/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs @@ -30,3 +30,5 @@ fn main() { (CONSTANT.file(), CONSTANT.line(), CONSTANT.column()), ); } + +//~? WARN skipping const checks diff --git a/tests/ui/rmeta/no_optitimized_mir.rs b/tests/ui/rmeta/no_optitimized_mir.rs index 7d2e1b87215f..708cdfc803fa 100644 --- a/tests/ui/rmeta/no_optitimized_mir.rs +++ b/tests/ui/rmeta/no_optitimized_mir.rs @@ -9,3 +9,5 @@ extern crate rmeta_meta; fn main() { rmeta_meta::missing_optimized_mir(); } + +//~? ERROR missing optimized MIR for an item in the crate `rmeta_meta` diff --git a/tests/ui/runtime/on-broken-pipe/default.rs b/tests/ui/runtime/on-broken-pipe/default.rs index c10d1cfacc0c..61b7810e2a18 100644 --- a/tests/ui/runtime/on-broken-pipe/default.rs +++ b/tests/ui/runtime/on-broken-pipe/default.rs @@ -2,3 +2,5 @@ //@ check-fail fn main() {} + +//~? ERROR incorrect value `default` for unstable option `on-broken-pipe` diff --git a/tests/ui/runtime/on-broken-pipe/no-flag-arg.rs b/tests/ui/runtime/on-broken-pipe/no-flag-arg.rs index 2273291bfa77..bb49533c0231 100644 --- a/tests/ui/runtime/on-broken-pipe/no-flag-arg.rs +++ b/tests/ui/runtime/on-broken-pipe/no-flag-arg.rs @@ -2,3 +2,5 @@ //@ check-fail fn main() {} + +//~? ERROR unstable option `on-broken-pipe` requires either `kill`, `error`, or `inherit` diff --git a/tests/ui/runtime/on-broken-pipe/wrong-flag-arg.rs b/tests/ui/runtime/on-broken-pipe/wrong-flag-arg.rs index 14d0ac56b5a3..c4a07932bc20 100644 --- a/tests/ui/runtime/on-broken-pipe/wrong-flag-arg.rs +++ b/tests/ui/runtime/on-broken-pipe/wrong-flag-arg.rs @@ -2,3 +2,5 @@ //@ check-fail fn main() {} + +//~? ERROR incorrect value `wrong` for unstable option `on-broken-pipe` diff --git a/tests/ui/rustc-env/min-stack-banana.rs b/tests/ui/rustc-env/min-stack-banana.rs index abbb68437100..dfde277714b9 100644 --- a/tests/ui/rustc-env/min-stack-banana.rs +++ b/tests/ui/rustc-env/min-stack-banana.rs @@ -1,2 +1,5 @@ //@ rustc-env:RUST_MIN_STACK=banana + fn main() {} + +//~? ERROR `RUST_MIN_STACK` should be a number of bytes, but was "banana" diff --git a/tests/ui/sanitizer/cfi/canonical-jump-tables-requires-cfi.rs b/tests/ui/sanitizer/cfi/canonical-jump-tables-requires-cfi.rs index 10c5bf6ea5e1..36f6e3bc95e1 100644 --- a/tests/ui/sanitizer/cfi/canonical-jump-tables-requires-cfi.rs +++ b/tests/ui/sanitizer/cfi/canonical-jump-tables-requires-cfi.rs @@ -6,3 +6,5 @@ #![feature(no_core)] #![no_core] #![no_main] + +//~? ERROR `-Zsanitizer-cfi-canonical-jump-tables` requires `-Zsanitizer=cfi` diff --git a/tests/ui/sanitizer/cfi/generalize-pointers-requires-cfi.rs b/tests/ui/sanitizer/cfi/generalize-pointers-requires-cfi.rs index 8ba13bd3639b..83277da528c9 100644 --- a/tests/ui/sanitizer/cfi/generalize-pointers-requires-cfi.rs +++ b/tests/ui/sanitizer/cfi/generalize-pointers-requires-cfi.rs @@ -7,3 +7,5 @@ #![feature(no_core)] #![no_core] #![no_main] + +//~? ERROR `-Zsanitizer-cfi-generalize-pointers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi` diff --git a/tests/ui/sanitizer/cfi/is-incompatible-with-kcfi.rs b/tests/ui/sanitizer/cfi/is-incompatible-with-kcfi.rs index c628709d7a1c..db8d11616440 100644 --- a/tests/ui/sanitizer/cfi/is-incompatible-with-kcfi.rs +++ b/tests/ui/sanitizer/cfi/is-incompatible-with-kcfi.rs @@ -10,3 +10,6 @@ #![feature(no_core)] #![no_core] #![no_main] + +//~? ERROR cfi sanitizer is not supported for this target +//~? ERROR `-Zsanitizer=cfi` is incompatible with `-Zsanitizer=kcfi` diff --git a/tests/ui/sanitizer/cfi/normalize-integers-requires-cfi.rs b/tests/ui/sanitizer/cfi/normalize-integers-requires-cfi.rs index a7ecefbf7efb..b9d5b9623d5f 100644 --- a/tests/ui/sanitizer/cfi/normalize-integers-requires-cfi.rs +++ b/tests/ui/sanitizer/cfi/normalize-integers-requires-cfi.rs @@ -7,3 +7,5 @@ #![feature(no_core)] #![no_core] #![no_main] + +//~? ERROR `-Zsanitizer-cfi-normalize-integers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi` diff --git a/tests/ui/sanitizer/cfi/requires-lto.rs b/tests/ui/sanitizer/cfi/requires-lto.rs index 5a34f696e054..db83f5f6bf02 100644 --- a/tests/ui/sanitizer/cfi/requires-lto.rs +++ b/tests/ui/sanitizer/cfi/requires-lto.rs @@ -6,3 +6,5 @@ #![feature(no_core)] #![no_core] #![no_main] + +//~? ERROR `-Zsanitizer=cfi` requires `-Clto` or `-Clinker-plugin-lto` diff --git a/tests/ui/sanitizer/cfi/with-rustc-lto-requires-single-codegen-unit.rs b/tests/ui/sanitizer/cfi/with-rustc-lto-requires-single-codegen-unit.rs index 954e4ec3b853..4ef5b6756a49 100644 --- a/tests/ui/sanitizer/cfi/with-rustc-lto-requires-single-codegen-unit.rs +++ b/tests/ui/sanitizer/cfi/with-rustc-lto-requires-single-codegen-unit.rs @@ -6,3 +6,5 @@ #![feature(no_core)] #![no_core] #![no_main] + +//~? ERROR `-Zsanitizer=cfi` with `-Clto` requires `-Ccodegen-units=1` diff --git a/tests/ui/sanitizer/crt-static.rs b/tests/ui/sanitizer/crt-static.rs index c24faeca3dc8..b8bdf28351c3 100644 --- a/tests/ui/sanitizer/crt-static.rs +++ b/tests/ui/sanitizer/crt-static.rs @@ -4,3 +4,5 @@ #![feature(no_core)] #![no_core] #![no_main] + +//~? ERROR sanitizer is incompatible with statically linked libc diff --git a/tests/ui/sanitizer/split-lto-unit-requires-lto.rs b/tests/ui/sanitizer/split-lto-unit-requires-lto.rs index 35e610f03076..1d08ca7423fd 100644 --- a/tests/ui/sanitizer/split-lto-unit-requires-lto.rs +++ b/tests/ui/sanitizer/split-lto-unit-requires-lto.rs @@ -6,3 +6,5 @@ #![feature(no_core)] #![no_core] #![no_main] + +//~? ERROR `-Zsplit-lto-unit` requires `-Clto`, `-Clto=thin`, or `-Clinker-plugin-lto` diff --git a/tests/ui/stack-protector/warn-stack-protector-unsupported.rs b/tests/ui/stack-protector/warn-stack-protector-unsupported.rs index 9205d4052ad4..dc61e35a089a 100644 --- a/tests/ui/stack-protector/warn-stack-protector-unsupported.rs +++ b/tests/ui/stack-protector/warn-stack-protector-unsupported.rs @@ -17,3 +17,7 @@ trait Sized {} trait Copy {} pub fn main(){} + +//[all]~? WARN `-Z stack-protector=all` is not supported for target nvptx64-nvidia-cuda and will be ignored +//[strong]~? WARN `-Z stack-protector=strong` is not supported for target nvptx64-nvidia-cuda and will be ignored +//[basic]~? WARN `-Z stack-protector=basic` is not supported for target nvptx64-nvidia-cuda and will be ignored diff --git a/tests/ui/symbol-mangling-version/bad-value.rs b/tests/ui/symbol-mangling-version/bad-value.rs index f6fa5c85f338..b0875f3a23cd 100644 --- a/tests/ui/symbol-mangling-version/bad-value.rs +++ b/tests/ui/symbol-mangling-version/bad-value.rs @@ -4,3 +4,7 @@ //@ [bad] compile-flags: -Csymbol-mangling-version=bad-value fn main() {} + +//[no-value]~? ERROR codegen option `symbol-mangling-version` requires one of +//[blank]~? ERROR incorrect value `` for codegen option `symbol-mangling-version` +//[bad]~? ERROR incorrect value `bad-value` for codegen option `symbol-mangling-version` diff --git a/tests/ui/symbol-mangling-version/unstable.rs b/tests/ui/symbol-mangling-version/unstable.rs index d5af8542996b..d79320ccccd5 100644 --- a/tests/ui/symbol-mangling-version/unstable.rs +++ b/tests/ui/symbol-mangling-version/unstable.rs @@ -7,3 +7,6 @@ //@ [hashed-ok] compile-flags: -Zunstable-options -Csymbol-mangling-version=hashed fn main() {} + +//[legacy]~? ERROR `-C symbol-mangling-version=legacy` requires `-Z unstable-options` +//[hashed]~? ERROR `-C symbol-mangling-version=hashed` requires `-Z unstable-options` diff --git a/tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.rs b/tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.rs index e34faf5a983c..7368ef120fa6 100644 --- a/tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.rs +++ b/tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.rs @@ -7,3 +7,5 @@ #[lang = "sized"] pub trait Sized {} + +//~? WARN unstable feature specified for `-Ctarget-feature`: `x87` diff --git a/tests/ui/target-feature/missing-plusminus-2.rs b/tests/ui/target-feature/missing-plusminus-2.rs index 19f4bc6e7244..06291ab23ad5 100644 --- a/tests/ui/target-feature/missing-plusminus-2.rs +++ b/tests/ui/target-feature/missing-plusminus-2.rs @@ -4,3 +4,5 @@ #![feature(no_core)] #![no_core] + +//~? WARN unknown feature specified for `-Ctarget-feature`: `rdrand` diff --git a/tests/ui/target-feature/missing-plusminus.rs b/tests/ui/target-feature/missing-plusminus.rs index eb3e93c2ef7f..e8356e0fa355 100644 --- a/tests/ui/target-feature/missing-plusminus.rs +++ b/tests/ui/target-feature/missing-plusminus.rs @@ -1,2 +1,4 @@ //@ compile-flags: -Ctarget-feature=banana --crate-type=rlib //@ build-pass + +//~? WARN unknown feature specified for `-Ctarget-feature`: `banana` diff --git a/tests/ui/target-feature/similar-feature-suggestion.rs b/tests/ui/target-feature/similar-feature-suggestion.rs index 242d472b794e..b82d7e408c7c 100644 --- a/tests/ui/target-feature/similar-feature-suggestion.rs +++ b/tests/ui/target-feature/similar-feature-suggestion.rs @@ -4,3 +4,5 @@ #![feature(no_core)] #![no_core] + +//~? WARN unknown and unstable feature specified for `-Ctarget-feature`: `rdrnd` diff --git a/tests/ui/target-feature/tied-features-cli.rs b/tests/ui/target-feature/tied-features-cli.rs index 17c13826ce9e..ce1dc3224a19 100644 --- a/tests/ui/target-feature/tied-features-cli.rs +++ b/tests/ui/target-feature/tied-features-cli.rs @@ -18,3 +18,7 @@ trait Sized {} fn main() {} + +//[one]~? ERROR the target features paca, pacg must all be either enabled or disabled together +//[two]~? ERROR the target features paca, pacg must all be either enabled or disabled together +//[three]~? ERROR the target features paca, pacg must all be either enabled or disabled together diff --git a/tests/ui/target-feature/tied-features-no-implication-1.rs b/tests/ui/target-feature/tied-features-no-implication-1.rs index 0473ca319b8f..0a98a7eeccf4 100644 --- a/tests/ui/target-feature/tied-features-no-implication-1.rs +++ b/tests/ui/target-feature/tied-features-no-implication-1.rs @@ -18,3 +18,5 @@ trait Sized {} #[cfg(target_feature = "pacg")] pub unsafe fn foo() { } + +//~? ERROR the target features paca, pacg must all be either enabled or disabled together diff --git a/tests/ui/target-feature/unstable-feature.rs b/tests/ui/target-feature/unstable-feature.rs index c74c5ad5d779..f62c4dd938a0 100644 --- a/tests/ui/target-feature/unstable-feature.rs +++ b/tests/ui/target-feature/unstable-feature.rs @@ -4,3 +4,5 @@ #![feature(no_core)] #![no_core] + +//~? WARN unstable feature specified for `-Ctarget-feature`: `vaes` diff --git a/tests/ui/target_modifiers/incompatible_regparm.rs b/tests/ui/target_modifiers/incompatible_regparm.rs index befe573b276c..395c26fc2c02 100644 --- a/tests/ui/target_modifiers/incompatible_regparm.rs +++ b/tests/ui/target_modifiers/incompatible_regparm.rs @@ -14,3 +14,5 @@ #![no_core] extern crate wrong_regparm; + +//[allow_no_value]~? ERROR codegen option `unsafe-allow-abi-mismatch` requires a comma-separated list of strings diff --git a/tests/ui/tool-attributes/duplicate-diagnostic.rs b/tests/ui/tool-attributes/duplicate-diagnostic.rs index 5061bcb9e444..c36179611afc 100644 --- a/tests/ui/tool-attributes/duplicate-diagnostic.rs +++ b/tests/ui/tool-attributes/duplicate-diagnostic.rs @@ -1,13 +1,14 @@ //@ aux-build: p1.rs //@ aux-build: p2.rs -//@ error-pattern: duplicate diagnostic item in crate `p2` -//@ error-pattern: note: the diagnostic item is first defined in crate `p1` - #![feature(rustc_attrs)] extern crate p1; extern crate p2; #[rustc_diagnostic_item = "Foo"] pub struct Foo {} //~ ERROR duplicate diagnostic item in crate `duplicate_diagnostic`: `Foo` + //~^ NOTE the diagnostic item is first defined in crate `p2` fn main() {} + +//~? ERROR duplicate diagnostic item in crate `p2` +//~? NOTE the diagnostic item is first defined in crate `p1` diff --git a/tests/ui/tool-attributes/duplicate-diagnostic.stderr b/tests/ui/tool-attributes/duplicate-diagnostic.stderr index 3cd438004c8e..16d78d03ae95 100644 --- a/tests/ui/tool-attributes/duplicate-diagnostic.stderr +++ b/tests/ui/tool-attributes/duplicate-diagnostic.stderr @@ -3,7 +3,7 @@ error: duplicate diagnostic item in crate `p2`: `Foo` = note: the diagnostic item is first defined in crate `p1` error: duplicate diagnostic item in crate `duplicate_diagnostic`: `Foo` - --> $DIR/duplicate-diagnostic.rs:12:1 + --> $DIR/duplicate-diagnostic.rs:9:1 | LL | pub struct Foo {} | ^^^^^^^^^^^^^^ diff --git a/tests/ui/type/pattern_types/literals.rs b/tests/ui/type/pattern_types/literals.rs index 97a918645f3e..7fd630dab3ad 100644 --- a/tests/ui/type/pattern_types/literals.rs +++ b/tests/ui/type/pattern_types/literals.rs @@ -134,3 +134,6 @@ fn lit_at_wraparound_range_start() -> pattern_type!(u32 is 2..1) { } fn main() {} + +//~? ERROR pattern type ranges cannot wrap: 1..=0 +//~? ERROR pattern type ranges cannot wrap: 2..=0 diff --git a/tests/ui/type/pattern_types/range_patterns.rs b/tests/ui/type/pattern_types/range_patterns.rs index dda7eb0ae4ec..21c1454d6cd5 100644 --- a/tests/ui/type/pattern_types/range_patterns.rs +++ b/tests/ui/type/pattern_types/range_patterns.rs @@ -40,3 +40,7 @@ type SignedWrap = pattern_type!(i8 is 120..=-120); //~ ERROR unknown layout fn main() { let x: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(42_u32) }; } + +//~? ERROR pattern type ranges cannot wrap: 1..=0 +//~? ERROR pattern type ranges cannot wrap: 5..=1 +//~? ERROR pattern type ranges cannot wrap: 120..=-120 diff --git a/tests/ui/unpretty/avoid-crash.rs b/tests/ui/unpretty/avoid-crash.rs index 7fcabfe6a8d4..64fa778bed47 100644 --- a/tests/ui/unpretty/avoid-crash.rs +++ b/tests/ui/unpretty/avoid-crash.rs @@ -2,3 +2,5 @@ //@ compile-flags: -o. -Zunpretty=ast-tree fn main() {} + +//~? ERROR failed to write `.` due to error From 813783e7115c58b5e70034f31be02201dac55407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 25 Mar 2025 13:43:25 +0100 Subject: [PATCH 539/745] Add diff of bootstrap steps --- src/build_helper/src/metrics.rs | 34 ++++++---- src/ci/citool/Cargo.lock | 7 ++ src/ci/citool/Cargo.toml | 1 + src/ci/citool/src/analysis.rs | 114 ++++++++++++++++++++++++++++++-- src/ci/citool/src/main.rs | 44 ++++++------ 5 files changed, 161 insertions(+), 39 deletions(-) diff --git a/src/build_helper/src/metrics.rs b/src/build_helper/src/metrics.rs index 4ab61245c16b..fdff9cd18cea 100644 --- a/src/build_helper/src/metrics.rs +++ b/src/build_helper/src/metrics.rs @@ -109,6 +109,8 @@ pub struct BuildStep { pub r#type: String, pub children: Vec, pub duration: Duration, + // Full name of the step, including all parent names + pub full_name: String, } impl BuildStep { @@ -116,7 +118,7 @@ impl BuildStep { /// The most important thing is that the build step aggregates the /// durations of all children, so that it can be easily accessed. pub fn from_invocation(invocation: &JsonInvocation) -> Self { - fn parse(node: &JsonNode) -> Option { + fn parse(node: &JsonNode, parent_name: &str) -> Option { match node { JsonNode::RustbuildStep { type_: kind, @@ -124,11 +126,14 @@ impl BuildStep { duration_excluding_children_sec, .. } => { - let children: Vec<_> = children.into_iter().filter_map(parse).collect(); + let full_name = format!("{parent_name}-{kind}"); + let children: Vec<_> = + children.into_iter().filter_map(|s| parse(s, &full_name)).collect(); let children_duration = children.iter().map(|c| c.duration).sum::(); Some(BuildStep { r#type: kind.to_string(), children, + full_name, duration: children_duration + Duration::from_secs_f64(*duration_excluding_children_sec), }) @@ -138,8 +143,13 @@ impl BuildStep { } let duration = Duration::from_secs_f64(invocation.duration_including_children_sec); - let children: Vec<_> = invocation.children.iter().filter_map(parse).collect(); - Self { r#type: "total".to_string(), children, duration } + + // The root "total" step is kind of a virtual step that encompasses all other steps, + // but it is not a real parent of the other steps. + // We thus start the parent name hierarchy here and use an empty string + // as the parent name of the top-level steps. + let children: Vec<_> = invocation.children.iter().filter_map(|s| parse(s, "")).collect(); + Self { r#type: "total".to_string(), children, duration, full_name: "total".to_string() } } pub fn find_all_by_type(&self, r#type: &str) -> Vec<&Self> { @@ -159,7 +169,7 @@ impl BuildStep { /// Returns a Vec with all substeps, ordered by their hierarchical order. /// The first element of the tuple is the depth of a given step. - fn linearize_steps(&self) -> Vec<(u32, &BuildStep)> { + pub fn linearize_steps(&self) -> Vec<(u32, &BuildStep)> { let mut substeps: Vec<(u32, &BuildStep)> = Vec::new(); fn visit<'a>(step: &'a BuildStep, level: u32, substeps: &mut Vec<(u32, &'a BuildStep)>) { @@ -180,14 +190,14 @@ pub fn format_build_steps(root: &BuildStep) -> String { let mut output = String::new(); for (level, step) in root.linearize_steps() { - let label = format!( - "{}{}", - ".".repeat(level as usize), - // Bootstrap steps can be generic and thus contain angle brackets (<...>). - // However, Markdown interprets these as HTML, so we need to escap ethem. - step.r#type.replace('<', "<").replace('>', ">") - ); + let label = format!("{}{}", ".".repeat(level as usize), escape_step_name(step)); writeln!(output, "{label:.<65}{:>8.2}s", step.duration.as_secs_f64()).unwrap(); } output } + +/// Bootstrap steps can be generic and thus contain angle brackets (<...>). +/// However, Markdown interprets these as HTML, so we need to escap ethem. +pub fn escape_step_name(step: &BuildStep) -> String { + step.r#type.replace('<', "<").replace('>', ">") +} diff --git a/src/ci/citool/Cargo.lock b/src/ci/citool/Cargo.lock index c061ec6ebdce..800eaae07665 100644 --- a/src/ci/citool/Cargo.lock +++ b/src/ci/citool/Cargo.lock @@ -107,6 +107,7 @@ dependencies = [ "build_helper", "clap", "csv", + "diff", "glob-match", "insta", "serde", @@ -241,6 +242,12 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + [[package]] name = "displaydoc" version = "0.2.5" diff --git a/src/ci/citool/Cargo.toml b/src/ci/citool/Cargo.toml index dde09224afe8..f18436a12635 100644 --- a/src/ci/citool/Cargo.toml +++ b/src/ci/citool/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" anyhow = "1" clap = { version = "4.5", features = ["derive"] } csv = "1" +diff = "0.1" glob-match = "0.2" serde = { version = "1", features = ["derive"] } serde_yaml = "0.9" diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 2088ce296209..ccc030511cbb 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -1,33 +1,134 @@ use std::collections::{BTreeMap, HashMap, HashSet}; +use std::fmt::Debug; use build_helper::metrics::{ - BuildStep, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, format_build_steps, + BuildStep, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, escape_step_name, + format_build_steps, }; use crate::metrics; use crate::metrics::{JobMetrics, JobName, get_test_suites}; use crate::utils::{output_details, pluralize}; -pub fn output_bootstrap_stats(metrics: &JsonRoot) { +/// Outputs durations of individual bootstrap steps from the gathered bootstrap invocations, +/// and also a table with summarized information about executed tests. +pub fn output_bootstrap_stats(metrics: &JsonRoot, parent_metrics: Option<&JsonRoot>) { if !metrics.invocations.is_empty() { println!("# Bootstrap steps"); - record_bootstrap_step_durations(&metrics); + record_bootstrap_step_durations(&metrics, parent_metrics); record_test_suites(&metrics); } } -fn record_bootstrap_step_durations(metrics: &JsonRoot) { +fn record_bootstrap_step_durations(metrics: &JsonRoot, parent_metrics: Option<&JsonRoot>) { + let parent_steps: HashMap = parent_metrics + .map(|metrics| { + metrics + .invocations + .iter() + .map(|invocation| { + (invocation.cmdline.clone(), BuildStep::from_invocation(invocation)) + }) + .collect() + }) + .unwrap_or_default(); + for invocation in &metrics.invocations { let step = BuildStep::from_invocation(invocation); let table = format_build_steps(&step); eprintln!("Step `{}`\n{table}\n", invocation.cmdline); - output_details(&invocation.cmdline, || { + output_details(&format!("{} (steps)", invocation.cmdline), || { println!("

{table}
"); }); + + // If there was a parent bootstrap invocation with the same cmdline, diff it + if let Some(parent_step) = parent_steps.get(&invocation.cmdline) { + let table = format_build_step_diffs(&step, parent_step); + + let duration_before = parent_step.duration.as_secs(); + let duration_after = step.duration.as_secs(); + output_details( + &format!("{} (diff) ({duration_before}s -> {duration_after}s)", invocation.cmdline), + || { + println!("{table}"); + }, + ); + } } eprintln!("Recorded {} bootstrap invocation(s)", metrics.invocations.len()); } +/// Creates a table that displays a diff between the durations of steps between +/// two bootstrap invocations. +/// It also shows steps that were missing before/after. +fn format_build_step_diffs(current: &BuildStep, parent: &BuildStep) -> String { + use std::fmt::Write; + + // Helper struct that compares steps by their full name + struct StepByName<'a>((u32, &'a BuildStep)); + + impl<'a> PartialEq for StepByName<'a> { + fn eq(&self, other: &Self) -> bool { + self.0.1.full_name.eq(&other.0.1.full_name) + } + } + + fn get_steps(step: &BuildStep) -> Vec { + step.linearize_steps().into_iter().map(|v| StepByName(v)).collect() + } + + let steps_before = get_steps(parent); + let steps_after = get_steps(current); + + let mut table = "| Step | Before | After | Change |\n".to_string(); + writeln!(table, "|:-----|-------:|------:|-------:|").unwrap(); + + // Try to match removed, added and same steps using a classic diff algorithm + for result in diff::slice(&steps_before, &steps_after) { + let (step, before, after, change) = match result { + // The step was found both before and after + diff::Result::Both(before, after) => { + let duration_before = before.0.1.duration; + let duration_after = after.0.1.duration; + let pct_change = duration_after.as_secs_f64() / duration_before.as_secs_f64(); + let pct_change = pct_change * 100.0; + // Normalize around 100, to get + for regression and - for improvements + let pct_change = pct_change - 100.0; + ( + before, + format!("{:.2}s", duration_before.as_secs_f64()), + format!("{:.2}s", duration_after.as_secs_f64()), + format!("{pct_change:.1}%"), + ) + } + // The step was only found in the parent, so it was likely removed + diff::Result::Left(removed) => ( + removed, + format!("{:.2}s", removed.0.1.duration.as_secs_f64()), + "".to_string(), + "(removed)".to_string(), + ), + // The step was only found in the current commit, so it was likely added + diff::Result::Right(added) => ( + added, + "".to_string(), + format!("{:.2}s", added.0.1.duration.as_secs_f64()), + "(added)".to_string(), + ), + }; + + let prefix = ".".repeat(step.0.0 as usize); + writeln!( + table, + "| {prefix}{} | {before} | {after} | {change} |", + escape_step_name(step.0.1), + ) + .unwrap(); + } + + table +} + fn record_test_suites(metrics: &JsonRoot) { let suites = metrics::get_test_suites(&metrics); @@ -82,8 +183,7 @@ fn render_table(suites: BTreeMap) -> String { table } -/// Computes a post merge CI analysis report of test differences -/// between the `parent` and `current` commits. +/// Outputs a report of test differences between the `parent` and `current` commits. pub fn output_test_diffs(job_metrics: HashMap) { let aggregated_test_diffs = aggregate_test_diffs(&job_metrics); report_test_diffs(aggregated_test_diffs); diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs index 5a84ecb5e47e..5f5c50dc43a0 100644 --- a/src/ci/citool/src/main.rs +++ b/src/ci/citool/src/main.rs @@ -144,31 +144,35 @@ fn postprocess_metrics( job_name: Option, ) -> anyhow::Result<()> { let metrics = load_metrics(&metrics_path)?; - output_bootstrap_stats(&metrics); - let (Some(parent), Some(job_name)) = (parent, job_name) else { - return Ok(()); - }; + if let (Some(parent), Some(job_name)) = (parent, job_name) { + // This command is executed also on PR builds, which might not have parent metrics + // available, because some PR jobs don't run on auto builds, and PR jobs do not upload metrics + // due to missing permissions. + // To avoid having to detect if this is a PR job, and to avoid having failed steps in PR jobs, + // we simply print an error if the parent metrics were not found, but otherwise exit + // successfully. + match download_job_metrics(&job_name, &parent).context("cannot download parent metrics") { + Ok(parent_metrics) => { + output_bootstrap_stats(&metrics, Some(&parent_metrics)); - // This command is executed also on PR builds, which might not have parent metrics - // available, because some PR jobs don't run on auto builds, and PR jobs do not upload metrics - // due to missing permissions. - // To avoid having to detect if this is a PR job, and to avoid having failed steps in PR jobs, - // we simply print an error if the parent metrics were not found, but otherwise exit - // successfully. - match download_job_metrics(&job_name, &parent).context("cannot download parent metrics") { - Ok(parent_metrics) => { - let job_metrics = HashMap::from([( - job_name, - JobMetrics { parent: Some(parent_metrics), current: metrics }, - )]); - output_test_diffs(job_metrics); - } - Err(error) => { - eprintln!("Metrics for job `{job_name}` and commit `{parent}` not found: {error:?}"); + let job_metrics = HashMap::from([( + job_name, + JobMetrics { parent: Some(parent_metrics), current: metrics }, + )]); + output_test_diffs(job_metrics); + return Ok(()); + } + Err(error) => { + eprintln!( + "Metrics for job `{job_name}` and commit `{parent}` not found: {error:?}" + ); + } } } + output_bootstrap_stats(&metrics, None); + Ok(()) } From 2bf0c2df147e98ead4297ccc6a62b2f7f6c48c3e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 24 Mar 2025 22:43:44 +0000 Subject: [PATCH 540/745] Make printing define_opaque less goofy --- .../rustc_ast_pretty/src/pprust/state/item.rs | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 6236f8ecfb52..8486e8093781 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -652,13 +652,7 @@ impl<'a> State<'a> { ) { let ast::Fn { defaultness, generics, sig, contract, body, define_opaque } = func; - if let Some(define_opaque) = define_opaque { - for (_, path) in define_opaque { - self.word("define opaques from "); - self.print_path(path, false, 0); - self.word(","); - } - } + self.print_define_opaques(define_opaque); if body.is_some() { self.head(""); @@ -678,6 +672,24 @@ impl<'a> State<'a> { } } + fn print_define_opaques( + &mut self, + define_opaque: Option<&[(ast::NodeId, ast::Path)]>, + ) { + if let Some(define_opaque) = define_opaque { + self.word("#[define_opaque("); + for (i, (_, path)) in define_opaque.iter().enumerate() { + if i != 0 { + self.word_space(","); + } + + self.print_path(path, false, 0); + } + self.word(")]"); + } + self.hardbreak_if_not_bol(); + } + fn print_contract(&mut self, contract: &ast::FnContract) { if let Some(pred) = &contract.requires { self.word("rustc_requires"); From f8df298d74ad4a385ca0b14e65ae154a9b8fa5c5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 24 Mar 2025 23:19:18 +0000 Subject: [PATCH 541/745] Allow defining opaques in statics and consts --- compiler/rustc_ast/src/ast.rs | 2 + compiler/rustc_ast/src/mut_visit.rs | 54 +++++++++----- compiler/rustc_ast/src/visit.rs | 53 ++++++++++++-- compiler/rustc_ast_lowering/src/item.rs | 70 ++++++++++++++----- .../rustc_ast_pretty/src/pprust/state/item.rs | 65 +++++++++++------ .../rustc_builtin_macros/src/define_opaque.rs | 5 ++ compiler/rustc_builtin_macros/src/test.rs | 1 + compiler/rustc_expand/src/build.rs | 11 ++- compiler/rustc_parse/src/parser/item.rs | 13 +++- compiler/rustc_resolve/src/def_collector.rs | 8 ++- compiler/rustc_resolve/src/late.rs | 51 ++++++++++---- .../clippy/clippy_utils/src/ast_utils/mod.rs | 8 +++ tests/ui/impl-trait/define-via-const.rs | 12 ++++ .../ui/type-alias-impl-trait/issue-53092-2.rs | 5 +- .../issue-53092-2.stderr | 51 +++++++++----- .../type-alias-impl-trait-const.rs | 10 +-- .../type-alias-impl-trait-const.stderr | 57 --------------- 17 files changed, 314 insertions(+), 162 deletions(-) create mode 100644 tests/ui/impl-trait/define-via-const.rs delete mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 5b7545b33966..fd27be213261 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3535,6 +3535,7 @@ pub struct StaticItem { pub safety: Safety, pub mutability: Mutability, pub expr: Option>, + pub define_opaque: Option>, } #[derive(Clone, Encodable, Decodable, Debug)] @@ -3543,6 +3544,7 @@ pub struct ConstItem { pub generics: Generics, pub ty: P, pub expr: Option>, + pub define_opaque: Option>, } // Adding a new variant? Please update `test_item` in `tests/ui/macros/stringify.rs`. diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 4edd08643000..b8d85958bfd7 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -987,10 +987,7 @@ fn walk_fn(vis: &mut T, kind: FnKind<'_>) { } vis.visit_span(span); - for (id, path) in define_opaque.iter_mut().flatten() { - vis.visit_id(id); - vis.visit_path(path) - } + walk_define_opaques(vis, define_opaque); } FnKind::Closure(binder, coroutine_kind, decl, body) => { vis.visit_closure_binder(binder); @@ -1258,12 +1255,19 @@ impl WalkItemKind for ItemKind { match self { ItemKind::ExternCrate(_orig_name) => {} ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree), - ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => { + ItemKind::Static(box StaticItem { + ty, + safety: _, + mutability: _, + expr, + define_opaque, + }) => { vis.visit_ty(ty); visit_opt(expr, |expr| vis.visit_expr(expr)); + walk_define_opaques(vis, define_opaque); } ItemKind::Const(item) => { - visit_const_item(item, vis); + walk_const_item(vis, item); } ItemKind::Fn(func) => { vis.visit_fn(FnKind::Fn(FnCtxt::Free, ident, visibility, &mut *func), span, id); @@ -1382,7 +1386,7 @@ impl WalkItemKind for AssocItemKind { ) { match self { AssocItemKind::Const(item) => { - visit_const_item(item, visitor); + walk_const_item(visitor, item); } AssocItemKind::Fn(func) => { visitor.visit_fn( @@ -1442,14 +1446,13 @@ impl WalkItemKind for AssocItemKind { } } -fn visit_const_item( - ConstItem { defaultness, generics, ty, expr }: &mut ConstItem, - visitor: &mut T, -) { - visit_defaultness(visitor, defaultness); - visitor.visit_generics(generics); - visitor.visit_ty(ty); - visit_opt(expr, |expr| visitor.visit_expr(expr)); +fn walk_const_item(vis: &mut T, item: &mut ConstItem) { + let ConstItem { defaultness, generics, ty, expr, define_opaque } = item; + visit_defaultness(vis, defaultness); + vis.visit_generics(generics); + vis.visit_ty(ty); + visit_opt(expr, |expr| vis.visit_expr(expr)); + walk_define_opaques(vis, define_opaque); } fn walk_fn_header(vis: &mut T, header: &mut FnHeader) { @@ -1526,9 +1529,16 @@ impl WalkItemKind for ForeignItemKind { visitor: &mut impl MutVisitor, ) { match self { - ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => { + ForeignItemKind::Static(box StaticItem { + ty, + mutability: _, + expr, + safety: _, + define_opaque, + }) => { visitor.visit_ty(ty); visit_opt(expr, |expr| visitor.visit_expr(expr)); + walk_define_opaques(visitor, define_opaque); } ForeignItemKind::Fn(func) => { visitor.visit_fn( @@ -1929,6 +1939,18 @@ fn walk_capture_by(vis: &mut T, capture_by: &mut CaptureBy) { } } +fn walk_define_opaques( + vis: &mut T, + define_opaque: &mut Option>, +) { + if let Some(define_opaque) = define_opaque { + for (id, path) in define_opaque { + vis.visit_id(id); + vis.visit_path(path) + } + } +} + /// Some value for the AST node that is valid but possibly meaningless. Similar /// to `Default` but not intended for wide use. The value will never be used /// meaningfully, it exists just to support unwinding in `visit_clobber` in the diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index ce8d6df75afb..8c0be6f48399 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -16,6 +16,7 @@ pub use rustc_ast_ir::visit::VisitorResult; pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list}; use rustc_span::{Ident, Span}; +use thin_vec::ThinVec; use crate::ast::*; use crate::ptr::P; @@ -371,14 +372,28 @@ impl WalkItemKind for ItemKind { match self { ItemKind::ExternCrate(_rename) => {} ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, id, false)), - ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => { + ItemKind::Static(box StaticItem { + ty, + safety: _, + mutability: _, + expr, + define_opaque, + }) => { try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); + try_visit!(walk_define_opaques(visitor, define_opaque)); } - ItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => { + ItemKind::Const(box ConstItem { + defaultness: _, + generics, + ty, + expr, + define_opaque, + }) => { try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); + try_visit!(walk_define_opaques(visitor, define_opaque)); } ItemKind::Fn(func) => { let kind = FnKind::Fn(FnCtxt::Free, ident, vis, &*func); @@ -729,9 +744,16 @@ impl WalkItemKind for ForeignItemKind { visitor: &mut V, ) -> V::Result { match self { - ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => { + ForeignItemKind::Static(box StaticItem { + ty, + mutability: _, + expr, + safety: _, + define_opaque, + }) => { try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); + try_visit!(walk_define_opaques(visitor, define_opaque)); } ForeignItemKind::Fn(func) => { let kind = FnKind::Fn(FnCtxt::Foreign, ident, vis, &*func); @@ -907,9 +929,7 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu try_visit!(visitor.visit_fn_decl(decl)); visit_opt!(visitor, visit_contract, contract); visit_opt!(visitor, visit_block, body); - for (id, path) in define_opaque.iter().flatten() { - try_visit!(visitor.visit_path(path, *id)) - } + try_visit!(walk_define_opaques(visitor, define_opaque)); } FnKind::Closure(binder, coroutine_kind, decl, body) => { try_visit!(visitor.visit_closure_binder(binder)); @@ -933,10 +953,17 @@ impl WalkItemKind for AssocItemKind { visitor: &mut V, ) -> V::Result { match self { - AssocItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => { + AssocItemKind::Const(box ConstItem { + defaultness: _, + generics, + ty, + expr, + define_opaque, + }) => { try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); + try_visit!(walk_define_opaques(visitor, define_opaque)); } AssocItemKind::Fn(func) => { let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, vis, &*func); @@ -1337,3 +1364,15 @@ pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) - } V::Result::output() } + +fn walk_define_opaques<'a, V: Visitor<'a>>( + visitor: &mut V, + define_opaque: &'a Option>, +) -> V::Result { + if let Some(define_opaque) = define_opaque { + for (id, path) in define_opaque { + try_visit!(visitor.visit_path(path, *id)); + } + } + V::Result::output() +} diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 219bf62c916d..c3031a65dd21 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -188,14 +188,21 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_use_tree(use_tree, &prefix, id, vis_span, attrs) } - ItemKind::Static(box ast::StaticItem { ty: t, safety: _, mutability: m, expr: e }) => { + ItemKind::Static(box ast::StaticItem { + ty: t, + safety: _, + mutability: m, + expr: e, + define_opaque, + }) => { debug_assert_ne!(ident.name, kw::Empty); let ident = self.lower_ident(ident); let (ty, body_id) = self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy); + self.lower_define_opaque(hir_id, define_opaque); hir::ItemKind::Static(ident, ty, *m, body_id) } - ItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => { + ItemKind::Const(box ast::ConstItem { generics, ty, expr, define_opaque, .. }) => { debug_assert_ne!(ident.name, kw::Empty); let ident = self.lower_ident(ident); let (generics, (ty, body_id)) = self.lower_generics( @@ -206,6 +213,7 @@ impl<'hir> LoweringContext<'_, 'hir> { this.lower_const_item(ty, span, expr.as_deref(), ImplTraitPosition::ConstTy) }, ); + self.lower_define_opaque(hir_id, &define_opaque); hir::ItemKind::Const(ident, ty, generics, body_id) } ItemKind::Fn(box Fn { @@ -243,7 +251,7 @@ impl<'hir> LoweringContext<'_, 'hir> { header: this.lower_fn_header(*header, hir::Safety::Safe, attrs), span: this.lower_span(*fn_sig_span), }; - this.lower_define_opaque(hir_id, &define_opaque); + this.lower_define_opaque(hir_id, define_opaque); let ident = this.lower_ident(ident); hir::ItemKind::Fn { ident, @@ -662,7 +670,7 @@ impl<'hir> LoweringContext<'_, 'hir> { owner_id, ident: self.lower_ident(i.ident), kind: match &i.kind { - ForeignItemKind::Fn(box Fn { sig, generics, .. }) => { + ForeignItemKind::Fn(box Fn { sig, generics, define_opaque, .. }) => { let fdec = &sig.decl; let itctx = ImplTraitContext::Universal; let (generics, (decl, fn_args)) = @@ -683,17 +691,31 @@ impl<'hir> LoweringContext<'_, 'hir> { // Unmarked safety in unsafe block defaults to unsafe. let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe, attrs); + if define_opaque.is_some() { + self.dcx().span_err(i.span, "foreign functions cannot define opaque types"); + } + hir::ForeignItemKind::Fn( hir::FnSig { header, decl, span: self.lower_span(sig.span) }, fn_args, generics, ) } - ForeignItemKind::Static(box StaticItem { ty, mutability, expr: _, safety }) => { + ForeignItemKind::Static(box StaticItem { + ty, + mutability, + expr: _, + safety, + define_opaque, + }) => { let ty = self .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy)); let safety = self.lower_safety(*safety, hir::Safety::Unsafe); + if define_opaque.is_some() { + self.dcx().span_err(i.span, "foreign statics cannot define opaque types"); + } + hir::ForeignItemKind::Static(ty, *mutability, safety) } ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, @@ -801,7 +823,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let trait_item_def_id = hir_id.expect_owner(); let (generics, kind, has_default) = match &i.kind { - AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => { + AssocItemKind::Const(box ConstItem { generics, ty, expr, define_opaque, .. }) => { let (generics, kind) = self.lower_generics( generics, i.id, @@ -814,6 +836,18 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::TraitItemKind::Const(ty, body) }, ); + + if define_opaque.is_some() { + if expr.is_some() { + self.lower_define_opaque(hir_id, &define_opaque); + } else { + self.dcx().span_err( + i.span, + "only trait consts with default bodies can define opaque types", + ); + } + } + (generics, kind, expr.is_some()) } AssocItemKind::Fn(box Fn { sig, generics, body: None, define_opaque, .. }) => { @@ -951,18 +985,20 @@ impl<'hir> LoweringContext<'_, 'hir> { let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); let (generics, kind) = match &i.kind { - AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics( - generics, - i.id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), - |this| { - let ty = - this.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); - let body = this.lower_const_body(i.span, expr.as_deref()); + AssocItemKind::Const(box ConstItem { generics, ty, expr, define_opaque, .. }) => self + .lower_generics( + generics, + i.id, + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + |this| { + let ty = this + .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); + let body = this.lower_const_body(i.span, expr.as_deref()); + this.lower_define_opaque(hir_id, &define_opaque); - hir::ImplItemKind::Const(ty, body) - }, - ), + hir::ImplItemKind::Const(ty, body) + }, + ), AssocItemKind::Fn(box Fn { sig, generics, body, contract, define_opaque, .. }) => { let body_id = self.lower_maybe_coroutine_body( sig.span, diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 8486e8093781..d406a56c05da 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -37,18 +37,23 @@ impl<'a> State<'a> { ast::ForeignItemKind::Fn(func) => { self.print_fn_full(ident, vis, attrs, &*func); } - ast::ForeignItemKind::Static(box ast::StaticItem { ty, mutability, expr, safety }) => { - self.print_item_const( - ident, - Some(*mutability), - &ast::Generics::default(), - ty, - expr.as_deref(), - vis, - *safety, - ast::Defaultness::Final, - ) - } + ast::ForeignItemKind::Static(box ast::StaticItem { + ty, + mutability, + expr, + safety, + define_opaque, + }) => self.print_item_const( + ident, + Some(*mutability), + &ast::Generics::default(), + ty, + expr.as_deref(), + vis, + *safety, + ast::Defaultness::Final, + define_opaque.as_deref(), + ), ast::ForeignItemKind::TyAlias(box ast::TyAlias { defaultness, generics, @@ -86,7 +91,9 @@ impl<'a> State<'a> { vis: &ast::Visibility, safety: ast::Safety, defaultness: ast::Defaultness, + define_opaque: Option<&[(ast::NodeId, ast::Path)]>, ) { + self.print_define_opaques(define_opaque); self.head(""); self.print_visibility(vis); self.print_safety(safety); @@ -174,7 +181,13 @@ impl<'a> State<'a> { self.print_use_tree(tree); self.word(";"); } - ast::ItemKind::Static(box StaticItem { ty, safety, mutability: mutbl, expr: body }) => { + ast::ItemKind::Static(box StaticItem { + ty, + safety, + mutability: mutbl, + expr: body, + define_opaque, + }) => { self.print_safety(*safety); self.print_item_const( item.ident, @@ -185,9 +198,16 @@ impl<'a> State<'a> { &item.vis, ast::Safety::Default, ast::Defaultness::Final, + define_opaque.as_deref(), ); } - ast::ItemKind::Const(box ast::ConstItem { defaultness, generics, ty, expr }) => { + ast::ItemKind::Const(box ast::ConstItem { + defaultness, + generics, + ty, + expr, + define_opaque, + }) => { self.print_item_const( item.ident, None, @@ -197,6 +217,7 @@ impl<'a> State<'a> { &item.vis, ast::Safety::Default, *defaultness, + define_opaque.as_deref(), ); } ast::ItemKind::Fn(func) => { @@ -537,7 +558,13 @@ impl<'a> State<'a> { ast::AssocItemKind::Fn(func) => { self.print_fn_full(ident, vis, attrs, &*func); } - ast::AssocItemKind::Const(box ast::ConstItem { defaultness, generics, ty, expr }) => { + ast::AssocItemKind::Const(box ast::ConstItem { + defaultness, + generics, + ty, + expr, + define_opaque, + }) => { self.print_item_const( ident, None, @@ -547,6 +574,7 @@ impl<'a> State<'a> { vis, ast::Safety::Default, *defaultness, + define_opaque.as_deref(), ); } ast::AssocItemKind::Type(box ast::TyAlias { @@ -652,7 +680,7 @@ impl<'a> State<'a> { ) { let ast::Fn { defaultness, generics, sig, contract, body, define_opaque } = func; - self.print_define_opaques(define_opaque); + self.print_define_opaques(define_opaque.as_deref()); if body.is_some() { self.head(""); @@ -672,10 +700,7 @@ impl<'a> State<'a> { } } - fn print_define_opaques( - &mut self, - define_opaque: Option<&[(ast::NodeId, ast::Path)]>, - ) { + fn print_define_opaques(&mut self, define_opaque: Option<&[(ast::NodeId, ast::Path)]>) { if let Some(define_opaque) = define_opaque { self.word("#[define_opaque("); for (i, (_, path)) in define_opaque.iter().enumerate() { diff --git a/compiler/rustc_builtin_macros/src/define_opaque.rs b/compiler/rustc_builtin_macros/src/define_opaque.rs index 9777e772cf20..bd5c48e3d346 100644 --- a/compiler/rustc_builtin_macros/src/define_opaque.rs +++ b/compiler/rustc_builtin_macros/src/define_opaque.rs @@ -11,15 +11,20 @@ pub(crate) fn expand( let define_opaque = match &mut item { Annotatable::Item(p) => match &mut p.kind { ast::ItemKind::Fn(f) => Some(&mut f.define_opaque), + ast::ItemKind::Const(ct) => Some(&mut ct.define_opaque), + ast::ItemKind::Static(si) => Some(&mut si.define_opaque), _ => None, }, Annotatable::AssocItem(i, _assoc_ctxt) => match &mut i.kind { ast::AssocItemKind::Fn(func) => Some(&mut func.define_opaque), + ast::AssocItemKind::Const(ct) => Some(&mut ct.define_opaque), _ => None, }, Annotatable::Stmt(s) => match &mut s.kind { ast::StmtKind::Item(p) => match &mut p.kind { ast::ItemKind::Fn(f) => Some(&mut f.define_opaque), + ast::ItemKind::Const(ct) => Some(&mut ct.define_opaque), + ast::ItemKind::Static(si) => Some(&mut si.define_opaque), _ => None, }, _ => None, diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index a05fff2dcd1c..239f8657284d 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -285,6 +285,7 @@ pub(crate) fn expand_test_or_bench( defaultness: ast::Defaultness::Final, generics: ast::Generics::default(), ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))), + define_opaque: None, // test::TestDescAndFn { expr: Some( cx.expr_struct( diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index ee7f68cc2f01..2c9b5f40d0df 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -698,8 +698,14 @@ impl<'a> ExtCtxt<'a> { name, AttrVec::new(), ast::ItemKind::Static( - ast::StaticItem { ty, safety: ast::Safety::Default, mutability, expr: Some(expr) } - .into(), + ast::StaticItem { + ty, + safety: ast::Safety::Default, + mutability, + expr: Some(expr), + define_opaque: None, + } + .into(), ), ) } @@ -723,6 +729,7 @@ impl<'a> ExtCtxt<'a> { generics: ast::Generics::default(), ty, expr: Some(expr), + define_opaque: None, } .into(), ), diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index f4df4044dd2e..38a2eab5544f 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -265,6 +265,7 @@ impl<'a> Parser<'a> { generics, ty, expr, + define_opaque: None, })), ) } @@ -980,13 +981,20 @@ impl<'a> Parser<'a> { let kind = match AssocItemKind::try_from(kind) { Ok(kind) => kind, Err(kind) => match kind { - ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => { + ItemKind::Static(box StaticItem { + ty, + safety: _, + mutability: _, + expr, + define_opaque, + }) => { self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span }); AssocItemKind::Const(Box::new(ConstItem { defaultness: Defaultness::Final, generics: Generics::default(), ty, expr, + define_opaque, })) } _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"), @@ -1254,6 +1262,7 @@ impl<'a> Parser<'a> { mutability: Mutability::Not, expr, safety: Safety::Default, + define_opaque: None, })) } _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"), @@ -1397,7 +1406,7 @@ impl<'a> Parser<'a> { self.expect_semi()?; - Ok((ident, StaticItem { ty, safety, mutability, expr })) + Ok((ident, StaticItem { ty, safety, mutability, expr, define_opaque: None })) } /// Parse a constant item with the prefix `"const"` already parsed. diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 33f529851ae4..fcb638a117e3 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -244,7 +244,13 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { let def_kind = match fi.kind { - ForeignItemKind::Static(box StaticItem { ty: _, mutability, expr: _, safety }) => { + ForeignItemKind::Static(box StaticItem { + ty: _, + mutability, + expr: _, + safety, + define_opaque: _, + }) => { let safety = match safety { ast::Safety::Unsafe(_) | ast::Safety::Default => hir::Safety::Unsafe, ast::Safety::Safe(_) => hir::Safety::Safe, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index f8808582353a..9cbdb83a30fa 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -36,6 +36,7 @@ use rustc_session::parse::feature_err; use rustc_span::source_map::{Spanned, respan}; use rustc_span::{BytePos, Ident, Span, Symbol, SyntaxContext, kw, sym}; use smallvec::{SmallVec, smallvec}; +use thin_vec::ThinVec; use tracing::{debug, instrument, trace}; use crate::{ @@ -2662,10 +2663,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { }, |this| visit::walk_item(this, item), ); - - for (id, path) in define_opaque.iter().flatten() { - self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques); - } + self.resolve_define_opaques(define_opaque); } ItemKind::Enum(_, ref generics) @@ -2751,7 +2749,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { }); } - ItemKind::Static(box ast::StaticItem { ref ty, ref expr, .. }) => { + ItemKind::Static(box ast::StaticItem { + ref ty, ref expr, ref define_opaque, .. + }) => { self.with_static_rib(def_kind, |this| { this.with_lifetime_rib( LifetimeRibKind::Elided(LifetimeRes::Static { @@ -2767,9 +2767,16 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { this.resolve_const_body(expr, Some((item.ident, ConstantItemKind::Static))); } }); + self.resolve_define_opaques(define_opaque); } - ItemKind::Const(box ast::ConstItem { ref generics, ref ty, ref expr, .. }) => { + ItemKind::Const(box ast::ConstItem { + ref generics, + ref ty, + ref expr, + ref define_opaque, + .. + }) => { self.with_generic_param_rib( &generics.params, RibKind::Item( @@ -2803,6 +2810,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } }, ); + self.resolve_define_opaques(define_opaque); } ItemKind::Use(ref use_tree) => { @@ -3102,7 +3110,13 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { for item in trait_items { self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id)); match &item.kind { - AssocItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => { + AssocItemKind::Const(box ast::ConstItem { + generics, + ty, + expr, + define_opaque, + .. + }) => { self.with_generic_param_rib( &generics.params, RibKind::AssocItem, @@ -3135,13 +3149,13 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ) }, ); + + self.resolve_define_opaques(define_opaque); } AssocItemKind::Fn(box Fn { generics, define_opaque, .. }) => { walk_assoc_item(self, generics, LifetimeBinderKind::Function, item); - for (id, path) in define_opaque.iter().flatten() { - self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques); - } + self.resolve_define_opaques(define_opaque); } AssocItemKind::Delegation(delegation) => { self.with_generic_param_rib( @@ -3306,7 +3320,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { use crate::ResolutionError::*; self.resolve_doc_links(&item.attrs, MaybeExported::ImplItem(trait_id.ok_or(&item.vis))); match &item.kind { - AssocItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => { + AssocItemKind::Const(box ast::ConstItem { + generics, ty, expr, define_opaque, .. + }) => { debug!("resolve_implementation AssocItemKind::Const"); self.with_generic_param_rib( &generics.params, @@ -3350,6 +3366,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); }, ); + self.resolve_define_opaques(define_opaque); } AssocItemKind::Fn(box Fn { generics, define_opaque, .. }) => { debug!("resolve_implementation AssocItemKind::Fn"); @@ -3379,9 +3396,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { }, ); - for (id, path) in define_opaque.iter().flatten() { - self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques); - } + self.resolve_define_opaques(define_opaque); } AssocItemKind::Type(box TyAlias { generics, .. }) => { self.diag_metadata.in_non_gat_assoc_type = Some(generics.params.is_empty()); @@ -5103,6 +5118,14 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { }); } } + + fn resolve_define_opaques(&mut self, define_opaque: &Option>) { + if let Some(define_opaque) = define_opaque { + for (id, path) in define_opaque { + self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques); + } + } + } } /// Walks the whole crate in DFS order, visiting each item, counting the declared number of diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs index 54261079fcad..6023ae9cc7b1 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs @@ -336,12 +336,14 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { mutability: lm, expr: le, safety: ls, + define_opaque: _, }), Static(box StaticItem { ty: rt, mutability: rm, expr: re, safety: rs, + define_opaque: _, }), ) => lm == rm && ls == rs && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()), ( @@ -350,12 +352,14 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { generics: lg, ty: lt, expr: le, + define_opaque: _, }), Const(box ConstItem { defaultness: rd, generics: rg, ty: rt, expr: re, + define_opaque: _, }), ) => eq_defaultness(*ld, *rd) && eq_generics(lg, rg) && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()), ( @@ -490,12 +494,14 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { mutability: lm, expr: le, safety: ls, + define_opaque: _, }), Static(box StaticItem { ty: rt, mutability: rm, expr: re, safety: rs, + define_opaque: _, }), ) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()) && ls == rs, ( @@ -557,12 +563,14 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { generics: lg, ty: lt, expr: le, + define_opaque: _, }), Const(box ConstItem { defaultness: rd, generics: rg, ty: rt, expr: re, + define_opaque: _, }), ) => eq_defaultness(*ld, *rd) && eq_generics(lg, rg) && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()), ( diff --git a/tests/ui/impl-trait/define-via-const.rs b/tests/ui/impl-trait/define-via-const.rs new file mode 100644 index 000000000000..a4b9123654c4 --- /dev/null +++ b/tests/ui/impl-trait/define-via-const.rs @@ -0,0 +1,12 @@ +//@ check-pass + +#![feature(type_alias_impl_trait)] + +type Closure = impl Fn(u32) -> u32; + +#[define_opaque(Closure)] +const ADDER: Closure = |x| x + 1; + +fn main() { + let z = (ADDER)(1); +} diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.rs b/tests/ui/type-alias-impl-trait/issue-53092-2.rs index 5f44a9aa2dfa..1a530d27971a 100644 --- a/tests/ui/type-alias-impl-trait/issue-53092-2.rs +++ b/tests/ui/type-alias-impl-trait/issue-53092-2.rs @@ -2,14 +2,15 @@ #![allow(dead_code)] type Bug = impl Fn(T) -> U + Copy; +//~^ ERROR cycle detected when computing type of `Bug::{opaque#0}` #[define_opaque(Bug)] -//~^ ERROR: only functions and methods can define opaque types const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; +//~^ ERROR item does not constrain `Bug::{opaque#0}` #[define_opaque(Bug)] fn make_bug>() -> Bug { - |x| x.into() //~ ERROR is not satisfied + |x| x.into() } fn main() { diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr index 5739662ff80b..3062e55dc490 100644 --- a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr +++ b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr @@ -1,25 +1,42 @@ -error: only functions and methods can define opaque types - --> $DIR/issue-53092-2.rs:6:1 +error[E0391]: cycle detected when computing type of `Bug::{opaque#0}` + --> $DIR/issue-53092-2.rs:4:18 | -LL | #[define_opaque(Bug)] - | ^^^^^^^^^^^^^^^^^^^^^ +LL | type Bug = impl Fn(T) -> U + Copy; + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires computing type of opaque `Bug::{opaque#0}`... + --> $DIR/issue-53092-2.rs:4:18 + | +LL | type Bug = impl Fn(T) -> U + Copy; + | ^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires type-checking `CONST_BUG`... + --> $DIR/issue-53092-2.rs:8:1 + | +LL | const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires computing layout of `Bug`... + = note: ...which requires normalizing `Bug`... + = note: ...which again requires computing type of `Bug::{opaque#0}`, completing the cycle +note: cycle used when checking that `Bug::{opaque#0}` is well-formed + --> $DIR/issue-53092-2.rs:4:18 + | +LL | type Bug = impl Fn(T) -> U + Copy; + | ^^^^^^^^^^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error[E0277]: the trait bound `U: From` is not satisfied - --> $DIR/issue-53092-2.rs:12:5 +error: item does not constrain `Bug::{opaque#0}` + --> $DIR/issue-53092-2.rs:8:7 | -LL | |x| x.into() - | ^^^^^^^^^^^^ the trait `From` is not implemented for `U` +LL | const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; + | ^^^^^^^^^ | -note: required by a bound in `make_bug` - --> $DIR/issue-53092-2.rs:11:19 + = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]` +note: this opaque type is supposed to be constrained + --> $DIR/issue-53092-2.rs:4:18 | -LL | fn make_bug>() -> Bug { - | ^^^^^^^ required by this bound in `make_bug` -help: consider restricting type parameter `U` with trait `From` - | -LL | type Bug> = impl Fn(T) -> U + Copy; - | +++++++++++++++++++++++ +LL | type Bug = impl Fn(T) -> U + Copy; + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs index b5533eeecba5..e21627e14b09 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs @@ -1,19 +1,15 @@ +//@ check-pass + #![feature(type_alias_impl_trait)] -// Ensures that `const` items can not constrain an opaque `impl Trait`. use std::fmt::Debug; pub type Foo = impl Debug; -//~^ ERROR unconstrained opaque type #[define_opaque(Foo)] -//~^ ERROR only functions and methods can define opaque types const _FOO: Foo = 5; -//~^ ERROR mismatched types #[define_opaque(Foo)] -//~^ ERROR only functions and methods can define opaque types -static _BAR: Foo = 22_u32; -//~^ ERROR mismatched types +static _BAR: Foo = 22_i32; fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr deleted file mode 100644 index dc15da665f32..000000000000 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr +++ /dev/null @@ -1,57 +0,0 @@ -error: only functions and methods can define opaque types - --> $DIR/type-alias-impl-trait-const.rs:9:1 - | -LL | #[define_opaque(Foo)] - | ^^^^^^^^^^^^^^^^^^^^^ - -error: only functions and methods can define opaque types - --> $DIR/type-alias-impl-trait-const.rs:14:1 - | -LL | #[define_opaque(Foo)] - | ^^^^^^^^^^^^^^^^^^^^^ - -error: unconstrained opaque type - --> $DIR/type-alias-impl-trait-const.rs:6:16 - | -LL | pub type Foo = impl Debug; - | ^^^^^^^^^^ - | - = note: `Foo` must be used in combination with a concrete type within the same crate - -error[E0308]: mismatched types - --> $DIR/type-alias-impl-trait-const.rs:11:19 - | -LL | pub type Foo = impl Debug; - | ---------- the expected opaque type -... -LL | const _FOO: Foo = 5; - | ^ expected opaque type, found integer - | - = note: expected opaque type `Foo` - found type `{integer}` -note: this item must have a `#[define_opaque(Foo)]` attribute to be able to define hidden types - --> $DIR/type-alias-impl-trait-const.rs:11:7 - | -LL | const _FOO: Foo = 5; - | ^^^^ - -error[E0308]: mismatched types - --> $DIR/type-alias-impl-trait-const.rs:16:20 - | -LL | pub type Foo = impl Debug; - | ---------- the expected opaque type -... -LL | static _BAR: Foo = 22_u32; - | ^^^^^^ expected opaque type, found `u32` - | - = note: expected opaque type `Foo` - found type `u32` -note: this item must have a `#[define_opaque(Foo)]` attribute to be able to define hidden types - --> $DIR/type-alias-impl-trait-const.rs:16:8 - | -LL | static _BAR: Foo = 22_u32; - | ^^^^ - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0308`. From 0827f765864a17ac6354cc12ff353043cba62286 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 24 Mar 2025 23:19:33 +0000 Subject: [PATCH 542/745] Test define opaques in extern items --- .../rustc_builtin_macros/src/define_opaque.rs | 5 ++++- tests/ui/impl-trait/define-via-extern.rs | 16 ++++++++++++++++ tests/ui/impl-trait/define-via-extern.stderr | 14 ++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 tests/ui/impl-trait/define-via-extern.rs create mode 100644 tests/ui/impl-trait/define-via-extern.stderr diff --git a/compiler/rustc_builtin_macros/src/define_opaque.rs b/compiler/rustc_builtin_macros/src/define_opaque.rs index bd5c48e3d346..cd02e81f5689 100644 --- a/compiler/rustc_builtin_macros/src/define_opaque.rs +++ b/compiler/rustc_builtin_macros/src/define_opaque.rs @@ -52,7 +52,10 @@ pub(crate) fn expand( .collect(), ); } else { - ecx.dcx().span_err(meta_item.span, "only functions and methods can define opaque types"); + ecx.dcx().span_err( + meta_item.span, + "only functions, statics, and consts can define opaque types", + ); } vec![item] diff --git a/tests/ui/impl-trait/define-via-extern.rs b/tests/ui/impl-trait/define-via-extern.rs new file mode 100644 index 000000000000..599c31ff917f --- /dev/null +++ b/tests/ui/impl-trait/define-via-extern.rs @@ -0,0 +1,16 @@ +#![feature(type_alias_impl_trait)] + +type Hi = impl Sized; + +extern "C" { + #[define_opaque(Hi)] fn foo(); + //~^ ERROR only functions, statics, and consts can define opaque types + + #[define_opaque(Hi)] static HI: Hi; + //~^ ERROR only functions, statics, and consts can define opaque types +} + +#[define_opaque(Hi)] +fn main() { + let _: Hi = 0; +} diff --git a/tests/ui/impl-trait/define-via-extern.stderr b/tests/ui/impl-trait/define-via-extern.stderr new file mode 100644 index 000000000000..4a0ca5edd47d --- /dev/null +++ b/tests/ui/impl-trait/define-via-extern.stderr @@ -0,0 +1,14 @@ +error: only functions, statics, and consts can define opaque types + --> $DIR/define-via-extern.rs:6:5 + | +LL | #[define_opaque(Hi)] fn foo(); + | ^^^^^^^^^^^^^^^^^^^^ + +error: only functions, statics, and consts can define opaque types + --> $DIR/define-via-extern.rs:9:5 + | +LL | #[define_opaque(Hi)] static HI: Hi; + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From 1875905a94f72e043eb356efe30d40fe165fea20 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 25 Mar 2025 17:14:58 +0000 Subject: [PATCH 543/745] Rustup to rustc 1.87.0-nightly (f8c27dfe1 2025-03-24) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index a6b0bf5fba1a..ab650c05d357 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-03-23" +channel = "nightly-2025-03-25" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From 2df6252bd61464c27b0f2612ac4749b02c31cade Mon Sep 17 00:00:00 2001 From: apiraino Date: Tue, 25 Mar 2025 18:28:19 +0100 Subject: [PATCH 544/745] update wg-prio triagebot config --- triagebot.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index ebbcfa4516b9..6dfae8b16a3e 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -581,12 +581,12 @@ trigger_files = [ ] [notify-zulip."I-prioritize"] -zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts +zulip_stream = 245100 # #t-compiler/prioritization/alerts topic = "#{number} {title}" message_on_add = """\ @*WG-prioritization/alerts* issue #{number} has been requested for prioritization. -# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#assign-priority-to-unprioritized-issues-with-i-prioritize-label) +# [Procedure](https://forge.rust-lang.org/compiler/prioritization.html) - Priority? - Regression? - Notify people/groups? From ffee55c18c19c551d58a6d68e1b3feb7618d0455 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Mar 2025 20:52:17 +1100 Subject: [PATCH 545/745] rustdoc: Rearrange `Item`/`ItemInner`. The `Item` struct is 48 bytes and contains a `Box`; `ItemInner` is 104 bytes. This is an odd arrangement. Normally you'd have one of the following. - A single large struct, which avoids the allocation for the `Box`, but can result in lots of wasted space in unused parts of a container like `Vec`, `HashSet`, etc. - Or, something like `struct Item(Box)`, which requires the `Box` allocation but gives a very small Item size, which is good for containers like `Vec`. `Item`/`ItemInner` currently gets the worst of both worlds: it always requires a `Box`, but `Item` is also pretty big and so wastes space in containers. It would make sense to push it in one direction or the other. #138916 showed that the first option is a regression for rustdoc, so this commit does the second option, which improves speed and reduces memory usage. --- src/librustdoc/clean/auto_trait.rs | 8 ++-- src/librustdoc/clean/blanket_impl.rs | 8 ++-- src/librustdoc/clean/inline.rs | 14 +++---- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/clean/types.rs | 46 +++++++++++++--------- src/librustdoc/formats/cache.rs | 1 - src/librustdoc/json/conversions.rs | 2 +- src/librustdoc/passes/propagate_doc_cfg.rs | 6 +-- 8 files changed, 48 insertions(+), 39 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 6ace626fdcd9..a48f5c623cd2 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -114,8 +114,8 @@ fn synthesize_auto_trait_impl<'tcx>( }; Some(clean::Item { - name: None, inner: Box::new(clean::ItemInner { + name: None, attrs: Default::default(), stability: None, kind: clean::ImplItem(Box::new(clean::Impl { @@ -127,10 +127,10 @@ fn synthesize_auto_trait_impl<'tcx>( polarity, kind: clean::ImplKind::Auto, })), + item_id: clean::ItemId::Auto { trait_: trait_def_id, for_: item_def_id }, + cfg: None, + inline_stmt_id: None, }), - item_id: clean::ItemId::Auto { trait_: trait_def_id, for_: item_def_id }, - cfg: None, - inline_stmt_id: None, }) } diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index a6d9676dd84a..89245fee5155 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -83,9 +83,9 @@ pub(crate) fn synthesize_blanket_impls( cx.generated_synthetics.insert((ty.skip_binder(), trait_def_id)); blanket_impls.push(clean::Item { - name: None, - item_id: clean::ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id }, inner: Box::new(clean::ItemInner { + name: None, + item_id: clean::ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id }, attrs: Default::default(), stability: None, kind: clean::ImplItem(Box::new(clean::Impl { @@ -122,9 +122,9 @@ pub(crate) fn synthesize_blanket_impls( None, ))), })), + cfg: None, + inline_stmt_id: None, }), - cfg: None, - inline_stmt_id: None, }); } } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index e973b89b2375..d9cef28b3d80 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -151,7 +151,7 @@ pub(crate) fn try_inline( let mut item = crate::clean::generate_item_with_correct_attrs(cx, kind, did, name, import_def_id, None); // The visibility needs to reflect the one from the reexport and not from the "source" DefId. - item.inline_stmt_id = import_def_id; + item.inner.inline_stmt_id = import_def_id; ret.push(item); Some(ret) } @@ -665,11 +665,11 @@ fn build_module_items( // Primitive types can't be inlined so generate an import instead. let prim_ty = clean::PrimitiveType::from(p); items.push(clean::Item { - name: None, - // We can use the item's `DefId` directly since the only information ever used - // from it is `DefId.krate`. - item_id: ItemId::DefId(did), inner: Box::new(clean::ItemInner { + name: None, + // We can use the item's `DefId` directly since the only information ever + // used from it is `DefId.krate`. + item_id: ItemId::DefId(did), attrs: Default::default(), stability: None, kind: clean::ImportItem(clean::Import::new_simple( @@ -689,9 +689,9 @@ fn build_module_items( }, true, )), + cfg: None, + inline_stmt_id: None, }), - cfg: None, - inline_stmt_id: None, }); } else if let Some(i) = try_inline(cx, res, item.ident.name, attrs, visited) { items.extend(i) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index de6dc088176f..ada370a8d52e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -210,7 +210,7 @@ fn generate_item_with_correct_attrs( let name = renamed.or(Some(name)); let mut item = Item::from_def_id_and_attrs_and_parts(def_id, name, kind, attrs, cfg); - item.inline_stmt_id = import_id; + item.inner.inline_stmt_id = import_id; item } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 1207f2f0360f..356691e71b83 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -311,26 +311,31 @@ pub(crate) enum ExternalLocation { /// directly to the AST's concept of an item; it's a strict superset. #[derive(Clone)] pub(crate) struct Item { + pub(crate) inner: Box, +} + +// Why does the `Item`/`ItemInner` split exist? `Vec`s are common, and +// without the split `Item` would be a large type (100+ bytes) which results in +// lots of wasted space in the unused parts of a `Vec`. With the split, +// `Item` is just 8 bytes, and the wasted space is avoided, at the cost of an +// extra allocation per item. This is a performance win. +#[derive(Clone)] +pub(crate) struct ItemInner { /// The name of this item. /// Optional because not every item has a name, e.g. impls. pub(crate) name: Option, - pub(crate) inner: Box, - pub(crate) item_id: ItemId, - /// This is the `LocalDefId` of the `use` statement if the item was inlined. - /// The crate metadata doesn't hold this information, so the `use` statement - /// always belongs to the current crate. - pub(crate) inline_stmt_id: Option, - pub(crate) cfg: Option>, -} - -#[derive(Clone)] -pub(crate) struct ItemInner { /// Information about this item that is specific to what kind of item it is. /// E.g., struct vs enum vs function. pub(crate) kind: ItemKind, pub(crate) attrs: Attributes, /// The effective stability, filled out by the `propagate-stability` pass. pub(crate) stability: Option, + pub(crate) item_id: ItemId, + /// This is the `LocalDefId` of the `use` statement if the item was inlined. + /// The crate metadata doesn't hold this information, so the `use` statement + /// always belongs to the current crate. + pub(crate) inline_stmt_id: Option, + pub(crate) cfg: Option>, } impl std::ops::Deref for Item { @@ -488,11 +493,15 @@ impl Item { trace!("name={name:?}, def_id={def_id:?} cfg={cfg:?}"); Item { - item_id: def_id.into(), - inner: Box::new(ItemInner { kind, attrs, stability: None }), - name, - cfg, - inline_stmt_id: None, + inner: Box::new(ItemInner { + item_id: def_id.into(), + kind, + attrs, + stability: None, + name, + cfg, + inline_stmt_id: None, + }), } } @@ -2618,13 +2627,14 @@ mod size_asserts { use super::*; // tidy-alphabetical-start - static_assert_size!(Crate, 56); // frequently moved by-value + static_assert_size!(Crate, 16); // frequently moved by-value static_assert_size!(DocFragment, 32); static_assert_size!(GenericArg, 32); static_assert_size!(GenericArgs, 24); static_assert_size!(GenericParamDef, 40); static_assert_size!(Generics, 16); - static_assert_size!(Item, 48); + static_assert_size!(Item, 8); + static_assert_size!(ItemInner, 136); static_assert_size!(ItemKind, 48); static_assert_size!(PathSegment, 32); static_assert_size!(Type, 32); diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 2648641e53e7..f8f7816f5a67 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -385,7 +385,6 @@ impl DocFolder for CacheBuilder<'_, '_> { // implementations elsewhere. let ret = if let clean::Item { inner: box clean::ItemInner { kind: clean::ImplItem(ref i), .. }, - .. } = item { // Figure out the id of this impl. This may map to a diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index a5351b350dd5..9d8eb70fbe07 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -43,7 +43,7 @@ impl JsonRenderer<'_> { let attrs = item.attributes(self.tcx, self.cache(), true); let span = item.span(self.tcx); let visibility = item.visibility(self.tcx); - let clean::Item { name, item_id, .. } = item; + let clean::ItemInner { name, item_id, .. } = *item.inner; let id = self.id_from_item(&item); let inner = match item.kind { clean::KeywordItem => return None, diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs index 572c9bf7552f..eddafa9ba8e4 100644 --- a/src/librustdoc/passes/propagate_doc_cfg.rs +++ b/src/librustdoc/passes/propagate_doc_cfg.rs @@ -61,7 +61,7 @@ impl CfgPropagator<'_, '_> { let (_, cfg) = merge_attrs(self.cx, item.attrs.other_attrs.as_slice(), Some((&attrs, None))); - item.cfg = cfg; + item.inner.cfg = cfg; } } @@ -71,7 +71,7 @@ impl DocFolder for CfgPropagator<'_, '_> { self.merge_with_parent_attributes(&mut item); - let new_cfg = match (self.parent_cfg.take(), item.cfg.take()) { + let new_cfg = match (self.parent_cfg.take(), item.inner.cfg.take()) { (None, None) => None, (Some(rc), None) | (None, Some(rc)) => Some(rc), (Some(mut a), Some(b)) => { @@ -81,7 +81,7 @@ impl DocFolder for CfgPropagator<'_, '_> { } }; self.parent_cfg = new_cfg.clone(); - item.cfg = new_cfg; + item.inner.cfg = new_cfg; let old_parent = if let Some(def_id) = item.item_id.as_def_id().and_then(|def_id| def_id.as_local()) { From 154cb083e705feca7509143352887dd293db61b2 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Tue, 25 Mar 2025 21:02:54 +0100 Subject: [PATCH 546/745] Override PartialOrd methods for bool I noticed that `PartialOrd` implementation for `bool` does not override the individual operator methods, unlike the other primitive types like `char` and integers. This commit extracts these `PartialOrd` overrides shared by the other primitive types into a macro and calls it on `bool` too. --- library/core/src/cmp.rs | 46 +++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 0b0dbf723b65..0dc2cc72e06c 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -1810,9 +1810,9 @@ mod impls { #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for $t { #[inline] - fn eq(&self, other: &$t) -> bool { (*self) == (*other) } + fn eq(&self, other: &Self) -> bool { *self == *other } #[inline] - fn ne(&self, other: &$t) -> bool { (*self) != (*other) } + fn ne(&self, other: &Self) -> bool { *self != *other } } )*) } @@ -1842,8 +1842,18 @@ mod impls { eq_impl! { () bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - macro_rules! chaining_methods_impl { - ($t:ty) => { + #[rustfmt::skip] + macro_rules! partial_ord_methods_primitive_impl { + () => { + #[inline(always)] + fn lt(&self, other: &Self) -> bool { *self < *other } + #[inline(always)] + fn le(&self, other: &Self) -> bool { *self <= *other } + #[inline(always)] + fn gt(&self, other: &Self) -> bool { *self > *other } + #[inline(always)] + fn ge(&self, other: &Self) -> bool { *self >= *other } + // These implementations are the same for `Ord` or `PartialOrd` types // because if either is NAN the `==` test will fail so we end up in // the `Break` case and the comparison will correctly return `false`. @@ -1876,7 +1886,7 @@ mod impls { #[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for $t { #[inline] - fn partial_cmp(&self, other: &$t) -> Option { + fn partial_cmp(&self, other: &Self) -> Option { match (*self <= *other, *self >= *other) { (false, false) => None, (false, true) => Some(Greater), @@ -1884,16 +1894,8 @@ mod impls { (true, true) => Some(Equal), } } - #[inline(always)] - fn lt(&self, other: &$t) -> bool { (*self) < (*other) } - #[inline(always)] - fn le(&self, other: &$t) -> bool { (*self) <= (*other) } - #[inline(always)] - fn ge(&self, other: &$t) -> bool { (*self) >= (*other) } - #[inline(always)] - fn gt(&self, other: &$t) -> bool { (*self) > (*other) } - chaining_methods_impl!($t); + partial_ord_methods_primitive_impl!(); } )*) } @@ -1912,6 +1914,8 @@ mod impls { fn partial_cmp(&self, other: &bool) -> Option { Some(self.cmp(other)) } + + partial_ord_methods_primitive_impl!(); } partial_ord_impl! { f16 f32 f64 f128 } @@ -1921,25 +1925,17 @@ mod impls { #[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for $t { #[inline] - fn partial_cmp(&self, other: &$t) -> Option { + fn partial_cmp(&self, other: &Self) -> Option { Some(crate::intrinsics::three_way_compare(*self, *other)) } - #[inline(always)] - fn lt(&self, other: &$t) -> bool { (*self) < (*other) } - #[inline(always)] - fn le(&self, other: &$t) -> bool { (*self) <= (*other) } - #[inline(always)] - fn ge(&self, other: &$t) -> bool { (*self) >= (*other) } - #[inline(always)] - fn gt(&self, other: &$t) -> bool { (*self) > (*other) } - chaining_methods_impl!($t); + partial_ord_methods_primitive_impl!(); } #[stable(feature = "rust1", since = "1.0.0")] impl Ord for $t { #[inline] - fn cmp(&self, other: &$t) -> Ordering { + fn cmp(&self, other: &Self) -> Ordering { crate::intrinsics::three_way_compare(*self, *other) } } From cd4439952224f402e8d66aabdcbcc4d07fbc6115 Mon Sep 17 00:00:00 2001 From: Urgau Date: Tue, 25 Mar 2025 21:05:08 +0100 Subject: [PATCH 547/745] Move Platform Support section to the bottom of rustc chapter book --- src/doc/rustc/src/SUMMARY.md | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index e258b0a76ffd..6e3056751855 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -14,6 +14,22 @@ - [Deny-by-default Lints](lints/listing/deny-by-default.md) - [JSON Output](json.md) - [Tests](tests/index.md) +- [Targets](targets/index.md) + - [Built-in Targets](targets/built-in.md) + - [Custom Targets](targets/custom.md) + - [Known Issues](targets/known-issues.md) +- [Profile-guided Optimization](profile-guided-optimization.md) +- [Instrumentation-based Code Coverage](instrument-coverage.md) +- [Linker-plugin-based LTO](linker-plugin-lto.md) +- [Checking Conditional Configurations](check-cfg.md) + - [Cargo Specifics](check-cfg/cargo-specifics.md) +- [Exploit Mitigations](exploit-mitigations.md) +- [Symbol Mangling](symbol-mangling/index.md) + - [v0 Symbol Format](symbol-mangling/v0.md) +- [Contributing to `rustc`](contributing.md) + +-------- + - [Platform Support](platform-support.md) - [Target Tier Policy](target-tier-policy.md) - [Template for Target-specific Documentation](platform-support/TEMPLATE.md) @@ -113,16 +129,3 @@ - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md) - [xtensa-\*-none-elf](platform-support/xtensa.md) - [\*-nuttx-\*](platform-support/nuttx.md) -- [Targets](targets/index.md) - - [Built-in Targets](targets/built-in.md) - - [Custom Targets](targets/custom.md) - - [Known Issues](targets/known-issues.md) -- [Profile-guided Optimization](profile-guided-optimization.md) -- [Instrumentation-based Code Coverage](instrument-coverage.md) -- [Linker-plugin-based LTO](linker-plugin-lto.md) -- [Checking Conditional Configurations](check-cfg.md) - - [Cargo Specifics](check-cfg/cargo-specifics.md) -- [Exploit Mitigations](exploit-mitigations.md) -- [Symbol Mangling](symbol-mangling/index.md) - - [v0 Symbol Format](symbol-mangling/v0.md) -- [Contributing to `rustc`](contributing.md) From 4b22ac5296a7a40aebfc997eec122fbfe50164da Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 26 Mar 2025 00:15:24 +0000 Subject: [PATCH 548/745] Ensure define_opaque is accounted for in HIR hash --- compiler/rustc_ast_lowering/src/lib.rs | 2 +- compiler/rustc_middle/src/hir/mod.rs | 7 ++++++- compiler/rustc_middle/src/ty/context.rs | 3 ++- tests/incremental/define-opaques.rs | 19 +++++++++++++++++++ 4 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 tests/incremental/define-opaques.rs diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 6c380d77b493..a946f9562258 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -625,7 +625,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Don't hash unless necessary, because it's expensive. let (opt_hash_including_bodies, attrs_hash) = - self.tcx.hash_owner_nodes(node, &bodies, &attrs); + self.tcx.hash_owner_nodes(node, &bodies, &attrs, define_opaque); let num_nodes = self.item_local_id_counter.as_usize(); let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies, num_nodes); let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies }; diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 68b9a4f56b96..347bc5ea3128 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -14,7 +14,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::*; use rustc_macros::{Decodable, Encodable, HashStable}; -use rustc_span::{ErrorGuaranteed, ExpnId}; +use rustc_span::{ErrorGuaranteed, ExpnId, Span}; use crate::query::Providers; use crate::ty::{EarlyBinder, ImplSubject, TyCtxt}; @@ -157,6 +157,7 @@ impl<'tcx> TyCtxt<'tcx> { node: OwnerNode<'_>, bodies: &SortedMap>, attrs: &SortedMap, + define_opaque: Option<&[(Span, LocalDefId)]>, ) -> (Option, Option) { if self.needs_crate_hash() { self.with_stable_hashing_context(|mut hcx| { @@ -168,6 +169,10 @@ impl<'tcx> TyCtxt<'tcx> { let mut stable_hasher = StableHasher::new(); attrs.hash_stable(&mut hcx, &mut stable_hasher); + + // Hash the defined opaque types, which are not present in the attrs. + define_opaque.hash_stable(&mut hcx, &mut stable_hasher); + let h2 = stable_hasher.finish(); (Some(h1), Some(h2)) }) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index f54dd2b0040a..834d1f2a4a8d 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1288,7 +1288,8 @@ impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> { let bodies = Default::default(); let attrs = hir::AttributeMap::EMPTY; - let (opt_hash_including_bodies, _) = self.tcx.hash_owner_nodes(node, &bodies, &attrs.map); + let (opt_hash_including_bodies, _) = + self.tcx.hash_owner_nodes(node, &bodies, &attrs.map, attrs.define_opaque); let node = node.into(); self.opt_hir_owner_nodes(Some(self.tcx.arena.alloc(hir::OwnerNodes { opt_hash_including_bodies, diff --git a/tests/incremental/define-opaques.rs b/tests/incremental/define-opaques.rs new file mode 100644 index 000000000000..d6eae2383412 --- /dev/null +++ b/tests/incremental/define-opaques.rs @@ -0,0 +1,19 @@ +//@ revisions: rpass1 cfail2 + +#![feature(type_alias_impl_trait)] + +pub type Foo = impl Sized; + +#[cfg_attr(rpass1, define_opaque())] +#[cfg_attr(cfail2, define_opaque(Foo))] +fn a() { + //[cfail2]~^ ERROR item does not constrain `Foo::{opaque#0}` + let _: Foo = b(); +} + +#[define_opaque(Foo)] +fn b() -> Foo { + () +} + +fn main() {} From ca9988ec49debec4cd567d0aa719e2ee108c038b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Mar 2025 20:17:29 +1100 Subject: [PATCH 549/745] Remove `kw::Empty` uses from `rustc_middle`. There are several places in `rustc_middle` that check for an empty lifetime name. These checks appear to be totally unnecessary, because empty lifetime names aren't produced here. (Empty lifetime names *are* possible in `hir::Lifetime`. Perhaps there was some confusion between it and the `rustc_middle` types?) This commit removes the `kw::Empty` checks. --- compiler/rustc_middle/src/ty/generics.rs | 4 +--- compiler/rustc_middle/src/ty/mod.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 10 ++++------ compiler/rustc_middle/src/ty/region.rs | 6 ++---- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 85d9db7ee747..d4cc562e70cc 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -73,9 +73,7 @@ impl GenericParamDef { pub fn is_anonymous_lifetime(&self) -> bool { match self.kind { - GenericParamDefKind::Lifetime => { - self.name == kw::UnderscoreLifetime || self.name == kw::Empty - } + GenericParamDefKind::Lifetime => self.name == kw::UnderscoreLifetime, _ => false, } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 6bdd0a0647d3..ac98cbc8d6cb 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -457,7 +457,7 @@ impl EarlyParamRegion { /// Does this early bound region have a name? Early bound regions normally /// always have names except when using anonymous lifetimes (`'_`). pub fn has_name(&self) -> bool { - self.name != kw::UnderscoreLifetime && self.name != kw::Empty + self.name != kw::UnderscoreLifetime } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 3ef8ecc59e40..3281cb4135a0 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2591,11 +2591,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { // to fit that into a short string. Hence the recommendation to use // `explain_region()` or `note_and_explain_region()`. match *region { - ty::ReEarlyParam(ref data) => { - if data.name != kw::Empty { - p!(write("{}", data.name)); - return Ok(()); - } + ty::ReEarlyParam(data) => { + p!(write("{}", data.name)); + return Ok(()); } ty::ReLateParam(ty::LateParamRegion { kind, .. }) => { if let Some(name) = kind.get_name() { @@ -2834,7 +2832,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { (name, ty::BoundRegionKind::Named(CRATE_DEF_ID.to_def_id(), name)) } - ty::BoundRegionKind::Named(def_id, kw::UnderscoreLifetime | kw::Empty) => { + ty::BoundRegionKind::Named(def_id, kw::UnderscoreLifetime) => { let name = next_name(self); if let Some(lt_idx) = lifetime_idx { diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index fb52cf96b029..c78306f2ca37 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -400,9 +400,7 @@ impl LateParamRegionKind { pub fn is_named(&self) -> bool { match *self { - LateParamRegionKind::Named(_, name) => { - name != kw::UnderscoreLifetime && name != kw::Empty - } + LateParamRegionKind::Named(_, name) => name != kw::UnderscoreLifetime, _ => false, } } @@ -475,7 +473,7 @@ impl core::fmt::Debug for BoundRegion { impl BoundRegionKind { pub fn is_named(&self) -> bool { match *self { - BoundRegionKind::Named(_, name) => name != kw::UnderscoreLifetime && name != kw::Empty, + BoundRegionKind::Named(_, name) => name != kw::UnderscoreLifetime, _ => false, } } From 0c162b19ec0bcf1488a2f797404de594e347e053 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Wed, 26 Mar 2025 02:09:13 +0100 Subject: [PATCH 550/745] Revert "Make `MatchPairTree::place` non-optional" This reverts commit e3e74bc89a958e36c658fa809d98b4dd66d53cf8. The comment that was used to justify the change was outdated. --- .../src/builder/matches/match_pair.rs | 3 +-- compiler/rustc_mir_build/src/builder/matches/mod.rs | 12 ++++++++++-- compiler/rustc_mir_build/src/builder/matches/test.rs | 9 ++++++--- compiler/rustc_mir_build/src/builder/matches/util.rs | 8 ++++++-- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index f2ce0c46dd33..29d400a957b4 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -115,7 +115,6 @@ impl<'tcx> MatchPairTree<'tcx> { place_builder = place_builder.project(ProjectionElem::OpaqueCast(pattern.ty)); } - // Place can be none if the pattern refers to a non-captured place in a closure. let place = place_builder.try_to_place(cx); let mut subpairs = Vec::new(); let test_case = match pattern.kind { @@ -321,7 +320,7 @@ impl<'tcx> MatchPairTree<'tcx> { if let Some(test_case) = test_case { // This pattern is refutable, so push a new match-pair node. match_pairs.push(MatchPairTree { - place: place.expect("refutable patterns should always have a place to inspect"), + place, test_case, subpairs, pattern_ty: pattern.ty, diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index ea341b604e0b..56671763977b 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -1279,7 +1279,13 @@ impl<'tcx> TestCase<'tcx> { #[derive(Debug, Clone)] pub(crate) struct MatchPairTree<'tcx> { /// This place... - place: Place<'tcx>, + /// + /// --- + /// This can be `None` if it referred to a non-captured place in a closure. + /// + /// Invariant: Can only be `None` when `test_case` is `Irrefutable`. + /// Therefore this must be `Some(_)` after simplification. + place: Option>, /// ... must pass this test... test_case: TestCase<'tcx>, @@ -2099,9 +2105,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Extract the match-pair from the highest priority candidate let match_pair = &candidates[0].match_pairs[0]; let test = self.pick_test_for_match_pair(match_pair); + // Unwrap is ok after simplification. + let match_place = match_pair.place.unwrap(); debug!(?test, ?match_pair); - (match_pair.place, test) + (match_place, test) } /// Given a test, we partition the input candidates into several buckets. diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs index e5d61bc9e556..f92036a83e1e 100644 --- a/compiler/rustc_mir_build/src/builder/matches/test.rs +++ b/compiler/rustc_mir_build/src/builder/matches/test.rs @@ -540,8 +540,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // than one, but it'd be very unusual to have two sides that // both require tests; you'd expect one side to be simplified // away.) - let (match_pair_index, match_pair) = - candidate.match_pairs.iter().enumerate().find(|&(_, mp)| mp.place == test_place)?; + let (match_pair_index, match_pair) = candidate + .match_pairs + .iter() + .enumerate() + .find(|&(_, mp)| mp.place == Some(test_place))?; // If true, the match pair is completely entailed by its corresponding test // branch, so it can be removed. If false, the match pair is _compatible_ @@ -584,7 +587,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { candidate .match_pairs .iter() - .any(|mp| mp.place == test_place && is_covering_range(&mp.test_case)) + .any(|mp| mp.place == Some(test_place) && is_covering_range(&mp.test_case)) }; if sorted_candidates .get(&TestBranch::Failure) diff --git a/compiler/rustc_mir_build/src/builder/matches/util.rs b/compiler/rustc_mir_build/src/builder/matches/util.rs index ed3b652e4ef5..589e350a03fc 100644 --- a/compiler/rustc_mir_build/src/builder/matches/util.rs +++ b/compiler/rustc_mir_build/src/builder/matches/util.rs @@ -173,10 +173,14 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> { // } // ``` // Hence we fake borrow using a deep borrow. - self.fake_borrow(match_pair.place, FakeBorrowKind::Deep); + if let Some(place) = match_pair.place { + self.fake_borrow(place, FakeBorrowKind::Deep); + } } else { // Insert a Shallow borrow of any place that is switched on. - self.fake_borrow(match_pair.place, FakeBorrowKind::Shallow); + if let Some(place) = match_pair.place { + self.fake_borrow(place, FakeBorrowKind::Shallow); + } for subpair in &match_pair.subpairs { self.visit_match_pair(subpair); From c8a5b3677be3749b9f3eb9fafd912f8c4be5912e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Wed, 26 Mar 2025 02:18:13 +0100 Subject: [PATCH 551/745] MatchPairTree: update invariant comment --- compiler/rustc_mir_build/src/builder/matches/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index 56671763977b..fb1d067865cf 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -1283,8 +1283,8 @@ pub(crate) struct MatchPairTree<'tcx> { /// --- /// This can be `None` if it referred to a non-captured place in a closure. /// - /// Invariant: Can only be `None` when `test_case` is `Irrefutable`. - /// Therefore this must be `Some(_)` after simplification. + /// Invariant: Can only be `None` when `test_case` is `Or`. + /// Therefore this must be `Some(_)` after or-pattern expansion. place: Option>, /// ... must pass this test... From 1524060da6f65332917b6c62f7b68eadd0be2032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Wed, 26 Mar 2025 02:23:13 +0100 Subject: [PATCH 552/745] Add a regression test for TestCase::Or without place --- tests/ui/closures/upvar-or-pattern-issue-138958.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 tests/ui/closures/upvar-or-pattern-issue-138958.rs diff --git a/tests/ui/closures/upvar-or-pattern-issue-138958.rs b/tests/ui/closures/upvar-or-pattern-issue-138958.rs new file mode 100644 index 000000000000..fe9ebc0a7e69 --- /dev/null +++ b/tests/ui/closures/upvar-or-pattern-issue-138958.rs @@ -0,0 +1,11 @@ +//@ edition:2024 +//@ check-pass + +pub fn f(x: (u32, u32)) { + let _ = || { + let ((0, a) | (a, _)) = x; + a + }; +} + +fn main() {} From ca6dad3eaba54b5bf6e587991055d89c7cd029e4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 26 Mar 2025 03:51:41 +0000 Subject: [PATCH 553/745] hir::-ify internal lints --- compiler/rustc_lint/src/internal.rs | 89 ++++++++++++++++------------- 1 file changed, 50 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index b359ee790a50..c0d9290a08e0 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -1,18 +1,15 @@ //! Some lints that are only useful in the compiler or crates that use compiler internals, such as //! Clippy. -use rustc_ast as ast; +use rustc_hir::HirId; use rustc_hir::def::Res; use rustc_hir::def_id::DefId; -use rustc_hir::{ - AmbigArg, BinOp, BinOpKind, Expr, ExprKind, GenericArg, HirId, Impl, Item, ItemKind, Node, Pat, - PatExpr, PatExprKind, PatKind, Path, PathSegment, QPath, Ty, TyKind, -}; use rustc_middle::ty::{self, GenericArgsRef, Ty as MiddleTy}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::{Span, sym}; use tracing::debug; +use {rustc_ast as ast, rustc_hir as hir}; use crate::lints::{ BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, @@ -37,9 +34,12 @@ declare_tool_lint! { declare_lint_pass!(DefaultHashTypes => [DEFAULT_HASH_TYPES]); impl LateLintPass<'_> for DefaultHashTypes { - fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, hir_id: HirId) { + fn check_path(&mut self, cx: &LateContext<'_>, path: &hir::Path<'_>, hir_id: HirId) { let Res::Def(rustc_hir::def::DefKind::Struct, def_id) = path.res else { return }; - if matches!(cx.tcx.hir_node(hir_id), Node::Item(Item { kind: ItemKind::Use(..), .. })) { + if matches!( + cx.tcx.hir_node(hir_id), + hir::Node::Item(hir::Item { kind: hir::ItemKind::Use(..), .. }) + ) { // Don't lint imports, only actual usages. return; } @@ -60,10 +60,10 @@ impl LateLintPass<'_> for DefaultHashTypes { /// get the `DefId` and `GenericArgsRef` of the function. fn typeck_results_of_method_fn<'tcx>( cx: &LateContext<'tcx>, - expr: &Expr<'_>, + expr: &hir::Expr<'_>, ) -> Option<(Span, DefId, ty::GenericArgsRef<'tcx>)> { match expr.kind { - ExprKind::MethodCall(segment, ..) + hir::ExprKind::MethodCall(segment, ..) if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) => { Some((segment.ident.span, def_id, cx.typeck_results().node_args(expr.hir_id))) @@ -102,7 +102,7 @@ declare_tool_lint! { declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY, UNTRACKED_QUERY_INFORMATION]); impl LateLintPass<'_> for QueryStability { - fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) { let Some((span, def_id, args)) = typeck_results_of_method_fn(cx, expr) else { return }; if let Ok(Some(instance)) = ty::Instance::try_resolve(cx.tcx, cx.typing_env(), def_id, args) { @@ -164,21 +164,25 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind { } } - fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx Ty<'tcx, AmbigArg>) { + fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx, hir::AmbigArg>) { match &ty.kind { - TyKind::Path(QPath::Resolved(_, path)) => { + hir::TyKind::Path(hir::QPath::Resolved(_, path)) => { if lint_ty_kind_usage(cx, &path.res) { let span = match cx.tcx.parent_hir_node(ty.hir_id) { - Node::PatExpr(PatExpr { kind: PatExprKind::Path(qpath), .. }) - | Node::Pat(Pat { - kind: PatKind::TupleStruct(qpath, ..) | PatKind::Struct(qpath, ..), + hir::Node::PatExpr(hir::PatExpr { + kind: hir::PatExprKind::Path(qpath), .. }) - | Node::Expr( - Expr { kind: ExprKind::Path(qpath), .. } - | &Expr { kind: ExprKind::Struct(qpath, ..), .. }, + | hir::Node::Pat(hir::Pat { + kind: + hir::PatKind::TupleStruct(qpath, ..) | hir::PatKind::Struct(qpath, ..), + .. + }) + | hir::Node::Expr( + hir::Expr { kind: hir::ExprKind::Path(qpath), .. } + | &hir::Expr { kind: hir::ExprKind::Struct(qpath, ..), .. }, ) => { - if let QPath::TypeRelative(qpath_ty, ..) = qpath + if let hir::QPath::TypeRelative(qpath_ty, ..) = qpath && qpath_ty.hir_id == ty.hir_id { Some(path.span) @@ -223,7 +227,7 @@ fn lint_ty_kind_usage(cx: &LateContext<'_>, res: &Res) -> bool { } } -fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &Path<'_>) -> Option { +fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &hir::Path<'_>) -> Option { match &path.res { Res::Def(_, def_id) => { if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(*def_id) { @@ -244,13 +248,17 @@ fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &Path<'_>) -> Option { None } -fn gen_args(segment: &PathSegment<'_>) -> String { +fn gen_args(segment: &hir::PathSegment<'_>) -> String { if let Some(args) = &segment.args { let lifetimes = args .args .iter() .filter_map(|arg| { - if let GenericArg::Lifetime(lt) = arg { Some(lt.ident.to_string()) } else { None } + if let hir::GenericArg::Lifetime(lt) = arg { + Some(lt.ident.to_string()) + } else { + None + } }) .collect::>(); @@ -284,7 +292,7 @@ declare_tool_lint! { declare_lint_pass!(TypeIr => [NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_INHERENT]); impl<'tcx> LateLintPass<'tcx> for TypeIr { - fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { let rustc_hir::ItemKind::Use(path, kind) = item.kind else { return }; let is_mod_inherent = |def_id| cx.tcx.is_diagnostic_item(sym::type_ir_inherent, def_id); @@ -394,15 +402,15 @@ declare_tool_lint! { declare_lint_pass!(Diagnostics => [UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE_OF_IMPL]); impl LateLintPass<'_> for Diagnostics { - fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { - let collect_args_tys_and_spans = |args: &[Expr<'_>], reserve_one_extra: bool| { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) { + let collect_args_tys_and_spans = |args: &[hir::Expr<'_>], reserve_one_extra: bool| { let mut result = Vec::with_capacity(args.len() + usize::from(reserve_one_extra)); result.extend(args.iter().map(|arg| (cx.typeck_results().expr_ty(arg), arg.span))); result }; // Only check function calls and method calls. let (span, def_id, fn_gen_args, arg_tys_and_spans) = match expr.kind { - ExprKind::Call(callee, args) => { + hir::ExprKind::Call(callee, args) => { match cx.typeck_results().node_type(callee.hir_id).kind() { &ty::FnDef(def_id, fn_gen_args) => { (callee.span, def_id, fn_gen_args, collect_args_tys_and_spans(args, false)) @@ -410,7 +418,7 @@ impl LateLintPass<'_> for Diagnostics { _ => return, // occurs for fns passed as args } } - ExprKind::MethodCall(_segment, _recv, args, _span) => { + hir::ExprKind::MethodCall(_segment, _recv, args, _span) => { let Some((span, def_id, fn_gen_args)) = typeck_results_of_method_fn(cx, expr) else { return; @@ -514,8 +522,8 @@ impl Diagnostics { let mut is_inside_appropriate_impl = false; for (_hir_id, parent) in cx.tcx.hir_parent_iter(current_id) { debug!(?parent); - if let Node::Item(Item { kind: ItemKind::Impl(impl_), .. }) = parent - && let Impl { of_trait: Some(of_trait), .. } = impl_ + if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) = parent + && let hir::Impl { of_trait: Some(of_trait), .. } = impl_ && let Some(def_id) = of_trait.trait_def_id() && let Some(name) = cx.tcx.get_diagnostic_name(def_id) && matches!(name, sym::Diagnostic | sym::Subdiagnostic | sym::LintDiagnostic) @@ -543,8 +551,8 @@ declare_tool_lint! { declare_lint_pass!(BadOptAccess => [BAD_OPT_ACCESS]); impl LateLintPass<'_> for BadOptAccess { - fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { - let ExprKind::Field(base, target) = expr.kind else { return }; + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) { + let hir::ExprKind::Field(base, target) = expr.kind else { return }; let Some(adt_def) = cx.typeck_results().expr_ty(base).ty_adt_def() else { return }; // Skip types without `#[rustc_lint_opt_ty]` - only so that the rest of the lint can be // avoided. @@ -581,9 +589,12 @@ declare_tool_lint! { declare_lint_pass!(SpanUseEqCtxt => [SPAN_USE_EQ_CTXT]); impl<'tcx> LateLintPass<'tcx> for SpanUseEqCtxt { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { - if let ExprKind::Binary(BinOp { node: BinOpKind::Eq | BinOpKind::Ne, .. }, lhs, rhs) = - expr.kind + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) { + if let hir::ExprKind::Binary( + hir::BinOp { node: hir::BinOpKind::Eq | hir::BinOpKind::Ne, .. }, + lhs, + rhs, + ) = expr.kind { if is_span_ctxt_call(cx, lhs) && is_span_ctxt_call(cx, rhs) { cx.emit_span_lint(SPAN_USE_EQ_CTXT, expr.span, SpanUseEqCtxtDiag); @@ -592,9 +603,9 @@ impl<'tcx> LateLintPass<'tcx> for SpanUseEqCtxt { } } -fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { +fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { match &expr.kind { - ExprKind::MethodCall(..) => cx + hir::ExprKind::MethodCall(..) => cx .typeck_results() .type_dependent_def_id(expr.hir_id) .is_some_and(|call_did| cx.tcx.is_diagnostic_item(sym::SpanCtxt, call_did)), @@ -617,11 +628,11 @@ declare_lint_pass!(SymbolInternStringLiteral => [SYMBOL_INTERN_STRING_LITERAL]); impl<'tcx> LateLintPass<'tcx> for SymbolInternStringLiteral { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) { - if let ExprKind::Call(path, [arg]) = expr.kind - && let ExprKind::Path(ref qpath) = path.kind + if let hir::ExprKind::Call(path, [arg]) = expr.kind + && let hir::ExprKind::Path(ref qpath) = path.kind && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() && cx.tcx.is_diagnostic_item(sym::SymbolIntern, def_id) - && let ExprKind::Lit(kind) = arg.kind + && let hir::ExprKind::Lit(kind) = arg.kind && let rustc_ast::LitKind::Str(_, _) = kind.node { cx.emit_span_lint( From 14804d1ed156604c52d5dd4a1ac4710f7ad31fa6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 26 Mar 2025 04:09:07 +0000 Subject: [PATCH 554/745] Implement lint against using Interner and InferCtxtLike in random compiler crates --- compiler/rustc_lint/messages.ftl | 3 ++ compiler/rustc_lint/src/internal.rs | 39 +++++++++++++++++-- compiler/rustc_lint/src/lib.rs | 1 + compiler/rustc_lint/src/lints.rs | 5 +++ compiler/rustc_next_trait_solver/src/lib.rs | 1 + compiler/rustc_span/src/symbol.rs | 2 + compiler/rustc_type_ir/src/infer_ctxt.rs | 1 + compiler/rustc_type_ir/src/interner.rs | 1 + compiler/rustc_type_ir/src/lib.rs | 1 + .../import-of-type-ir-traits.rs | 16 ++++++++ .../import-of-type-ir-traits.stderr | 15 +++++++ 11 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.rs create mode 100644 tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.stderr diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index d51865810b9a..0a3eb434d3f1 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -799,6 +799,9 @@ lint_tykind_kind = usage of `ty::TyKind::` lint_type_ir_inherent_usage = do not use `rustc_type_ir::inherent` unless you're inside of the trait solver .note = the method or struct you're looking for is likely defined somewhere else downstream in the compiler +lint_type_ir_trait_usage = do not use `rustc_type_ir::Interner` or `rustc_type_ir::InferCtxtLike` unless you're inside of the trait solver + .note = the method or struct you're looking for is likely defined somewhere else downstream in the compiler + lint_undropped_manually_drops = calls to `std::mem::drop` with `std::mem::ManuallyDrop` instead of the inner value does nothing .label = argument has type `{$arg_ty}` .suggestion = use `std::mem::ManuallyDrop::into_inner` to get the inner value diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index c0d9290a08e0..1d4be24ea9fa 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -15,7 +15,7 @@ use crate::lints::{ BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag, SymbolInternStringLiteralDiag, TyQualified, TykindDiag, TykindKind, TypeIrInherentUsage, - UntranslatableDiag, + TypeIrTraitUsage, UntranslatableDiag, }; use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; @@ -280,7 +280,7 @@ declare_tool_lint! { } declare_tool_lint! { - /// The `usage_of_type_ir_inherent` lint detects usage `rustc_type_ir::inherent`. + /// The `usage_of_type_ir_inherent` lint detects usage of `rustc_type_ir::inherent`. /// /// This module should only be used within the trait solver. pub rustc::USAGE_OF_TYPE_IR_INHERENT, @@ -289,9 +289,42 @@ declare_tool_lint! { report_in_external_macro: true } -declare_lint_pass!(TypeIr => [NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_INHERENT]); +declare_tool_lint! { + /// The `usage_of_type_ir_traits` lint detects usage of `rustc_type_ir::Interner`, + /// or `rustc_infer::InferCtxtLike`. + /// + /// Methods of this trait should only be used within the type system abstraction layer, + /// and in the generic next trait solver implementation. Look for an analogously named + /// method on `TyCtxt` or `InferCtxt` (respectively). + pub rustc::USAGE_OF_TYPE_IR_TRAITS, + Allow, + "usage `rustc_type_ir`-specific abstraction traits outside of trait system", + report_in_external_macro: true +} + +declare_lint_pass!(TypeIr => [NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_TRAITS]); impl<'tcx> LateLintPass<'tcx> for TypeIr { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { + let res_def_id = match expr.kind { + hir::ExprKind::Path(hir::QPath::Resolved(_, path)) => path.res.opt_def_id(), + hir::ExprKind::Path(hir::QPath::TypeRelative(..)) | hir::ExprKind::MethodCall(..) => { + cx.typeck_results().type_dependent_def_id(expr.hir_id) + } + _ => return, + }; + let Some(res_def_id) = res_def_id else { + return; + }; + if let Some(assoc_item) = cx.tcx.opt_associated_item(res_def_id) + && let Some(trait_def_id) = assoc_item.trait_container(cx.tcx) + && (cx.tcx.is_diagnostic_item(sym::type_ir_interner, trait_def_id) + | cx.tcx.is_diagnostic_item(sym::type_ir_infer_ctxt_like, trait_def_id)) + { + cx.emit_span_lint(USAGE_OF_TYPE_IR_TRAITS, expr.span, TypeIrTraitUsage); + } + } + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { let rustc_hir::ItemKind::Use(path, kind) = item.kind else { return }; diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index c38a75400181..cd474f1b7db2 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -645,6 +645,7 @@ fn register_internals(store: &mut LintStore) { LintId::of(USAGE_OF_QUALIFIED_TY), LintId::of(NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT), LintId::of(USAGE_OF_TYPE_IR_INHERENT), + LintId::of(USAGE_OF_TYPE_IR_TRAITS), LintId::of(BAD_OPT_ACCESS), LintId::of(SPAN_USE_EQ_CTXT), ], diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 005863095729..036d68d13fa4 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -943,6 +943,11 @@ pub(crate) struct TyQualified { #[note] pub(crate) struct TypeIrInherentUsage; +#[derive(LintDiagnostic)] +#[diag(lint_type_ir_trait_usage)] +#[note] +pub(crate) struct TypeIrTraitUsage; + #[derive(LintDiagnostic)] #[diag(lint_non_glob_import_type_ir_inherent)] pub(crate) struct NonGlobImportTypeIrInherent { diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs index f6963a790675..f575fe03019e 100644 --- a/compiler/rustc_next_trait_solver/src/lib.rs +++ b/compiler/rustc_next_trait_solver/src/lib.rs @@ -6,6 +6,7 @@ // tidy-alphabetical-start #![allow(rustc::usage_of_type_ir_inherent)] +#![cfg_attr(not(bootstrap), allow(rustc::usage_of_type_ir_traits))] // tidy-alphabetical-end pub mod canonicalizer; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3e4742439655..555764c26a63 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2118,7 +2118,9 @@ symbols! { type_changing_struct_update, type_const, type_id, + type_ir_infer_ctxt_like, type_ir_inherent, + type_ir_interner, type_length_limit, type_macros, type_name, diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 26c495106962..e512e8fc838f 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -102,6 +102,7 @@ impl TypingMode { } } +#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_infer_ctxt_like")] pub trait InferCtxtLike: Sized { type Interner: Interner; fn cx(&self) -> Self::Interner; diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index e765cb66d00a..8f86270d7dce 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -15,6 +15,7 @@ use crate::solve::{CanonicalInput, ExternalConstraintsData, PredefinedOpaquesDat use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; use crate::{self as ty, search_graph}; +#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_interner")] pub trait Interner: Sized + Copy diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 629121895091..4e2baca27854 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -6,6 +6,7 @@ feature(associated_type_defaults, never_type, rustc_attrs, negative_impls) )] #![cfg_attr(feature = "nightly", allow(internal_features))] +#![cfg_attr(not(bootstrap), allow(rustc::usage_of_type_ir_traits))] // tidy-alphabetical-end extern crate self as rustc_type_ir; diff --git a/tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.rs b/tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.rs new file mode 100644 index 000000000000..3fdd65d6c87f --- /dev/null +++ b/tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.rs @@ -0,0 +1,16 @@ +//@ compile-flags: -Z unstable-options +//@ ignore-stage1 + +#![feature(rustc_private)] +#![deny(rustc::usage_of_type_ir_traits)] + +extern crate rustc_type_ir; + +use rustc_type_ir::Interner; + +fn foo(cx: I, did: I::DefId) { + let _ = cx.trait_is_unsafe(did); + //~^ ERROR do not use `rustc_type_ir::Interner` or `rustc_type_ir::InferCtxtLike` unless you're inside of the trait solver +} + +fn main() {} diff --git a/tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.stderr b/tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.stderr new file mode 100644 index 000000000000..df29a4945582 --- /dev/null +++ b/tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.stderr @@ -0,0 +1,15 @@ +error: do not use `rustc_type_ir::Interner` or `rustc_type_ir::InferCtxtLike` unless you're inside of the trait solver + --> $DIR/import-of-type-ir-traits.rs:12:13 + | +LL | let _ = cx.trait_is_unsafe(did); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the method or struct you're looking for is likely defined somewhere else downstream in the compiler +note: the lint level is defined here + --> $DIR/import-of-type-ir-traits.rs:5:9 + | +LL | #![deny(rustc::usage_of_type_ir_traits)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + From 5f1e36f8ad96dadaf181cbb17294612316181a1e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 26 Mar 2025 04:10:00 +0000 Subject: [PATCH 555/745] Stop using Interner in the compiler randomly --- compiler/rustc_monomorphize/src/collector.rs | 6 +++--- .../src/traits/select/candidate_assembly.rs | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 67fca1d7c294..679c614e9fa9 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -225,8 +225,8 @@ use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCoercion}; use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::print::{shrunk_instance_name, with_no_trimmed_paths}; use rustc_middle::ty::{ - self, GenericArgs, GenericParamDefKind, Instance, InstanceKind, Interner, Ty, TyCtxt, - TypeFoldable, TypeVisitableExt, VtblEntry, + self, GenericArgs, GenericParamDefKind, Instance, InstanceKind, Ty, TyCtxt, TypeFoldable, + TypeVisitableExt, VtblEntry, }; use rustc_middle::util::Providers; use rustc_middle::{bug, span_bug}; @@ -967,7 +967,7 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> { // `#[rustc_force_inline]` items should never be codegened. This should be caught by // the MIR validator. - tcx.delay_bug("attempt to codegen `#[rustc_force_inline]` item"); + tcx.dcx().delayed_bug("attempt to codegen `#[rustc_force_inline]` item"); } if def_id.is_local() { diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index fc352499146e..4cfd8149b1e9 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -16,7 +16,7 @@ use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError}; use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::{self, Ty, TypeVisitableExt, TypingMode}; use rustc_middle::{bug, span_bug}; -use rustc_type_ir::{Interner, elaborate}; +use rustc_type_ir::elaborate; use tracing::{debug, instrument, trace}; use super::SelectionCandidate::*; @@ -802,7 +802,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::UnsafeBinder(_) => { // Only consider auto impls of unsafe traits when there are // no unsafe fields. - if self.tcx().trait_is_unsafe(def_id) && self_ty.has_unsafe_fields() { + if self.tcx().trait_def(def_id).safety.is_unsafe() + && self_ty.has_unsafe_fields() + { return; } From a475f5d18169c5333a97d9a5583be61f249b8f22 Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Sun, 16 Mar 2025 16:47:26 -0700 Subject: [PATCH 556/745] Fix typo in error message --- library/std/src/sys/net/connection/xous/tcpstream.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/net/connection/xous/tcpstream.rs b/library/std/src/sys/net/connection/xous/tcpstream.rs index 283b1fe9a33b..e8aea8b706a5 100644 --- a/library/std/src/sys/net/connection/xous/tcpstream.rs +++ b/library/std/src/sys/net/connection/xous/tcpstream.rs @@ -324,7 +324,7 @@ impl TcpStream { } Ok(SocketAddr::V6(SocketAddrV6::new(new_addr.into(), self.local_port, 0, 0))) } - _ => Err(io::const_error!(io::ErrorKind::InvalidInput, "tnternal error")), + _ => Err(io::const_error!(io::ErrorKind::InvalidInput, "internal error")), } } From 6319bb38ccb316b193e35720c9df953e5ab01c22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 18 Mar 2025 17:01:14 +0100 Subject: [PATCH 557/745] Avoiding calling queries when collecting active queries --- compiler/rustc_interface/src/util.rs | 44 +++--- compiler/rustc_middle/src/query/mod.rs | 4 +- compiler/rustc_middle/src/query/plumbing.rs | 2 +- compiler/rustc_middle/src/values.rs | 4 +- compiler/rustc_query_impl/src/lib.rs | 11 +- compiler/rustc_query_impl/src/plumbing.rs | 97 ++++++++---- .../rustc_query_system/src/query/config.rs | 5 +- compiler/rustc_query_system/src/query/job.rs | 147 +++++++++++------- compiler/rustc_query_system/src/query/mod.rs | 100 ++++++++++-- .../rustc_query_system/src/query/plumbing.rs | 61 ++++---- 10 files changed, 313 insertions(+), 162 deletions(-) diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 333786f0ca38..83d80938b4e3 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -18,7 +18,7 @@ use rustc_session::{EarlyDiagCtxt, Session, filesearch}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; use rustc_span::source_map::SourceMapInputs; -use rustc_span::{Symbol, sym}; +use rustc_span::{SessionGlobals, Symbol, sym}; use rustc_target::spec::Target; use tracing::info; @@ -188,26 +188,11 @@ pub(crate) fn run_in_thread_pool_with_globals R + Send, // On deadlock, creates a new thread and forwards information in thread // locals to it. The new thread runs the deadlock handler. - // Get a `GlobalCtxt` reference from `CurrentGcx` as we cannot rely on having a - // `TyCtxt` TLS reference here. - let query_map = current_gcx2.access(|gcx| { - tls::enter_context(&tls::ImplicitCtxt::new(gcx), || { - tls::with(|tcx| { - match QueryCtxt::new(tcx).collect_active_jobs() { - Ok(query_map) => query_map, - Err(_) => { - // There was an unexpected error collecting all active jobs, which we need - // to find cycles to break. - // We want to avoid panicking in the deadlock handler, so we abort instead. - eprintln!("internal compiler error: failed to get query map in deadlock handler, aborting process"); - process::abort(); - } - } - }) - }) - }); - let query_map = FromDyn::from(query_map); + let current_gcx2 = current_gcx2.clone(); let registry = rayon_core::Registry::current(); + let session_globals = rustc_span::with_session_globals(|session_globals| { + session_globals as *const SessionGlobals as usize + }); thread::Builder::new() .name("rustc query cycle handler".to_string()) .spawn(move || { @@ -217,7 +202,24 @@ pub(crate) fn run_in_thread_pool_with_globals R + Send, // otherwise the compiler could just hang, process::abort(); }); - break_query_cycles(query_map.into_inner(), ®istry); + + // Get a `GlobalCtxt` reference from `CurrentGcx` as we cannot rely on having a + // `TyCtxt` TLS reference here. + current_gcx2.access(|gcx| { + tls::enter_context(&tls::ImplicitCtxt::new(gcx), || { + tls::with(|tcx| { + // Accessing session globals is sound as they outlive `GlobalCtxt`. + // They are needed to hash query keys containing spans or symbols. + let query_map = rustc_span::set_session_globals_then(unsafe { &*(session_globals as *const SessionGlobals) }, || { + // Ensure there was no errors collecting all active jobs. + // We need the complete map to ensure we find a cycle to break. + QueryCtxt::new(tcx).collect_active_jobs().ok().expect("failed to collect active queries in deadlock handler") + }); + break_query_cycles(query_map, ®istry); + }) + }) + }); + on_panic.disable(); }) .unwrap(); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 527c18addbe1..6093d0c6e844 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -30,7 +30,9 @@ use rustc_index::IndexVec; use rustc_lint_defs::LintId; use rustc_macros::rustc_queries; use rustc_query_system::ich::StableHashingContext; -use rustc_query_system::query::{QueryCache, QueryMode, QueryState, try_get_cached}; +use rustc_query_system::query::{ + QueryCache, QueryMode, QueryStackDeferred, QueryState, try_get_cached, +}; use rustc_session::Limits; use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; use rustc_session::cstore::{ diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 4834444ed1d7..a099f7704170 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -488,7 +488,7 @@ macro_rules! define_callbacks { #[derive(Default)] pub struct QueryStates<'tcx> { $( - pub $name: QueryState<$($K)*>, + pub $name: QueryState<$($K)*, QueryStackDeferred<'tcx>>, )* } diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index 9450ce7ec444..39fcc686c555 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -88,7 +88,7 @@ impl<'tcx> Value> for Representability { if info.query.dep_kind == dep_kinds::representability && let Some(field_id) = info.query.def_id && let Some(field_id) = field_id.as_local() - && let Some(DefKind::Field) = info.query.def_kind + && let Some(DefKind::Field) = info.query.info.def_kind { let parent_id = tcx.parent(field_id.to_def_id()); let item_id = match tcx.def_kind(parent_id) { @@ -216,7 +216,7 @@ impl<'tcx, T> Value> for Result> continue; }; let frame_span = - frame.query.default_span(cycle[(i + 1) % cycle.len()].span); + frame.query.info.default_span(cycle[(i + 1) % cycle.len()].span); if frame_span.is_dummy() { continue; } diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index a83c388c747b..30a9e718d236 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -26,8 +26,8 @@ use rustc_middle::ty::TyCtxt; use rustc_query_system::dep_graph::SerializedDepNodeIndex; use rustc_query_system::ich::StableHashingContext; use rustc_query_system::query::{ - CycleError, HashResult, QueryCache, QueryConfig, QueryMap, QueryMode, QueryState, - get_query_incr, get_query_non_incr, + CycleError, HashResult, QueryCache, QueryConfig, QueryMap, QueryMode, QueryStackDeferred, + QueryState, get_query_incr, get_query_non_incr, }; use rustc_query_system::{HandleCycleError, Value}; use rustc_span::{ErrorGuaranteed, Span}; @@ -84,7 +84,10 @@ where } #[inline(always)] - fn query_state<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a QueryState + fn query_state<'a>( + self, + qcx: QueryCtxt<'tcx>, + ) -> &'a QueryState> where QueryCtxt<'tcx>: 'a, { @@ -93,7 +96,7 @@ where unsafe { &*(&qcx.tcx.query_system.states as *const QueryStates<'tcx>) .byte_add(self.dynamic.query_state) - .cast::>() + .cast::>>() } } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 55281cd5ac70..7f1d466b8692 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -3,8 +3,10 @@ //! manage the caches, and so forth. use std::num::NonZero; +use std::sync::Arc; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_data_structures::unord::UnordMap; use rustc_hashes::Hash64; use rustc_index::Idx; @@ -24,8 +26,8 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext}; use rustc_query_system::ich::StableHashingContext; use rustc_query_system::query::{ - QueryCache, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffect, QueryStackFrame, - force_query, + QueryCache, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffect, + QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra, force_query, }; use rustc_query_system::{QueryOverflow, QueryOverflowNote}; use rustc_serialize::{Decodable, Encodable}; @@ -65,7 +67,9 @@ impl<'tcx> HasDepContext for QueryCtxt<'tcx> { } } -impl QueryContext for QueryCtxt<'_> { +impl<'tcx> QueryContext for QueryCtxt<'tcx> { + type QueryInfo = QueryStackDeferred<'tcx>; + #[inline] fn next_job_id(self) -> QueryJobId { QueryJobId( @@ -82,7 +86,9 @@ impl QueryContext for QueryCtxt<'_> { /// Returns a query map representing active query jobs. /// It returns an incomplete map as an error if it fails /// to take locks. - fn collect_active_jobs(self) -> Result { + fn collect_active_jobs( + self, + ) -> Result>, QueryMap>> { let mut jobs = QueryMap::default(); let mut complete = true; @@ -95,6 +101,13 @@ impl QueryContext for QueryCtxt<'_> { if complete { Ok(jobs) } else { Err(jobs) } } + fn lift_query_info( + self, + info: &QueryStackDeferred<'tcx>, + ) -> rustc_query_system::query::QueryStackFrameExtra { + info.extract() + } + // Interactions with on_disk_cache fn load_side_effect( self, @@ -159,7 +172,10 @@ impl QueryContext for QueryCtxt<'_> { self.sess.dcx().emit_fatal(QueryOverflow { span: info.job.span, - note: QueryOverflowNote { desc: info.query.description, depth }, + note: QueryOverflowNote { + desc: self.lift_query_info(&info.query.info).description, + depth, + }, suggested_limit, crate_name: self.crate_name(LOCAL_CRATE), }); @@ -298,39 +314,45 @@ macro_rules! should_ever_cache_on_disk { pub(crate) fn create_query_frame< 'tcx, - K: Copy + Key + for<'a> HashStable>, + K: Copy + DynSend + DynSync + Key + for<'a> HashStable> + 'tcx, >( tcx: TyCtxt<'tcx>, do_describe: fn(TyCtxt<'tcx>, K) -> String, key: K, kind: DepKind, name: &'static str, -) -> QueryStackFrame { - // If reduced queries are requested, we may be printing a query stack due - // to a panic. Avoid using `default_span` and `def_kind` in that case. - let reduce_queries = with_reduced_queries(); - - // Avoid calling queries while formatting the description - let description = ty::print::with_no_queries!(do_describe(tcx, key)); - let description = if tcx.sess.verbose_internals() { - format!("{description} [{name:?}]") - } else { - description - }; - let span = if kind == dep_graph::dep_kinds::def_span || reduce_queries { - // The `def_span` query is used to calculate `default_span`, - // so exit to avoid infinite recursion. - None - } else { - Some(key.default_span(tcx)) - }; +) -> QueryStackFrame> { let def_id = key.key_as_def_id(); - let def_kind = if kind == dep_graph::dep_kinds::def_kind || reduce_queries { - // Try to avoid infinite recursion. - None - } else { - def_id.and_then(|def_id| def_id.as_local()).map(|def_id| tcx.def_kind(def_id)) + + let extra = move || { + // If reduced queries are requested, we may be printing a query stack due + // to a panic. Avoid using `default_span` and `def_kind` in that case. + let reduce_queries = with_reduced_queries(); + + // Avoid calling queries while formatting the description + let description = ty::print::with_no_queries!(do_describe(tcx, key)); + let description = if tcx.sess.verbose_internals() { + format!("{description} [{name:?}]") + } else { + description + }; + let span = if kind == dep_graph::dep_kinds::def_span || reduce_queries { + // The `def_span` query is used to calculate `default_span`, + // so exit to avoid infinite recursion. + None + } else { + Some(key.default_span(tcx)) + }; + + let def_kind = if kind == dep_graph::dep_kinds::def_kind || reduce_queries { + // Try to avoid infinite recursion. + None + } else { + def_id.and_then(|def_id| def_id.as_local()).map(|def_id| tcx.def_kind(def_id)) + }; + QueryStackFrameExtra::new(description, span, def_kind) }; + let hash = || { tcx.with_stable_hashing_context(|mut hcx| { let mut hasher = StableHasher::new(); @@ -341,7 +363,11 @@ pub(crate) fn create_query_frame< }; let def_id_for_ty_in_cycle = key.def_id_for_ty_in_cycle(); - QueryStackFrame::new(description, span, def_id, def_kind, kind, def_id_for_ty_in_cycle, hash) + // SAFETY: None of the captures in `extra` have destructors that access 'tcx + // as they don't have destructors. + let info = unsafe { QueryStackDeferred::new(Arc::new(extra)) }; + + QueryStackFrame::new(info, kind, hash, def_id, def_id_for_ty_in_cycle) } pub(crate) fn encode_query_results<'a, 'tcx, Q>( @@ -688,7 +714,10 @@ macro_rules! define_queries { } } - pub(crate) fn try_collect_active_jobs<'tcx>(tcx: TyCtxt<'tcx>, qmap: &mut QueryMap) -> Option<()> { + pub(crate) fn try_collect_active_jobs<'tcx>( + tcx: TyCtxt<'tcx>, + qmap: &mut QueryMap>, + ) -> Option<()> { let make_query = |tcx, key| { let kind = rustc_middle::dep_graph::dep_kinds::$name; let name = stringify!($name); @@ -768,7 +797,9 @@ macro_rules! define_queries { // These arrays are used for iteration and can't be indexed by `DepKind`. - const TRY_COLLECT_ACTIVE_JOBS: &[for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap) -> Option<()>] = + const TRY_COLLECT_ACTIVE_JOBS: &[ + for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap>) -> Option<()> + ] = &[$(query_impl::$name::try_collect_active_jobs),*]; const ALLOC_SELF_PROFILE_QUERY_STRINGS: &[ diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs index 371b896400a5..e508eadb73b0 100644 --- a/compiler/rustc_query_system/src/query/config.rs +++ b/compiler/rustc_query_system/src/query/config.rs @@ -6,6 +6,7 @@ use std::hash::Hash; use rustc_data_structures::fingerprint::Fingerprint; use rustc_span::ErrorGuaranteed; +use super::QueryStackFrameExtra; use crate::dep_graph::{DepKind, DepNode, DepNodeParams, SerializedDepNodeIndex}; use crate::error::HandleCycleError; use crate::ich::StableHashingContext; @@ -27,7 +28,7 @@ pub trait QueryConfig: Copy { fn format_value(self) -> fn(&Self::Value) -> String; // Don't use this method to access query results, instead use the methods on TyCtxt - fn query_state<'a>(self, tcx: Qcx) -> &'a QueryState + fn query_state<'a>(self, tcx: Qcx) -> &'a QueryState where Qcx: 'a; @@ -57,7 +58,7 @@ pub trait QueryConfig: Copy { fn value_from_cycle_error( self, tcx: Qcx::DepContext, - cycle_error: &CycleError, + cycle_error: &CycleError, guar: ErrorGuaranteed, ) -> Self::Value; diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 402c78314729..de35cd79ea27 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -1,3 +1,4 @@ +use std::fmt::Debug; use std::hash::Hash; use std::io::Write; use std::iter; @@ -12,6 +13,7 @@ use rustc_hir::def::DefKind; use rustc_session::Session; use rustc_span::{DUMMY_SP, Span}; +use super::QueryStackFrameExtra; use crate::dep_graph::DepContext; use crate::error::CycleStack; use crate::query::plumbing::CycleError; @@ -19,45 +21,54 @@ use crate::query::{QueryContext, QueryStackFrame}; /// Represents a span and a query key. #[derive(Clone, Debug)] -pub struct QueryInfo { +pub struct QueryInfo { /// The span corresponding to the reason for which this query was required. pub span: Span, - pub query: QueryStackFrame, + pub query: QueryStackFrame, } -pub type QueryMap = FxHashMap; +impl QueryInfo { + pub(crate) fn lift>( + &self, + qcx: Qcx, + ) -> QueryInfo { + QueryInfo { span: self.span, query: self.query.lift(qcx) } + } +} + +pub type QueryMap = FxHashMap>; /// A value uniquely identifying an active query job. #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct QueryJobId(pub NonZero); impl QueryJobId { - fn query(self, map: &QueryMap) -> QueryStackFrame { + fn query(self, map: &QueryMap) -> QueryStackFrame { map.get(&self).unwrap().query.clone() } - fn span(self, map: &QueryMap) -> Span { + fn span(self, map: &QueryMap) -> Span { map.get(&self).unwrap().job.span } - fn parent(self, map: &QueryMap) -> Option { + fn parent(self, map: &QueryMap) -> Option { map.get(&self).unwrap().job.parent } - fn latch(self, map: &QueryMap) -> Option<&QueryLatch> { + fn latch(self, map: &QueryMap) -> Option<&QueryLatch> { map.get(&self).unwrap().job.latch.as_ref() } } #[derive(Clone, Debug)] -pub struct QueryJobInfo { - pub query: QueryStackFrame, - pub job: QueryJob, +pub struct QueryJobInfo { + pub query: QueryStackFrame, + pub job: QueryJob, } /// Represents an active query job. -#[derive(Clone, Debug)] -pub struct QueryJob { +#[derive(Debug)] +pub struct QueryJob { pub id: QueryJobId, /// The span corresponding to the reason for which this query was required. @@ -67,17 +78,23 @@ pub struct QueryJob { pub parent: Option, /// The latch that is used to wait on this job. - latch: Option, + latch: Option>, } -impl QueryJob { +impl Clone for QueryJob { + fn clone(&self) -> Self { + Self { id: self.id, span: self.span, parent: self.parent, latch: self.latch.clone() } + } +} + +impl QueryJob { /// Creates a new query job. #[inline] pub fn new(id: QueryJobId, span: Span, parent: Option) -> Self { QueryJob { id, span, parent, latch: None } } - pub(super) fn latch(&mut self) -> QueryLatch { + pub(super) fn latch(&mut self) -> QueryLatch { if self.latch.is_none() { self.latch = Some(QueryLatch::new()); } @@ -97,12 +114,12 @@ impl QueryJob { } impl QueryJobId { - pub(super) fn find_cycle_in_stack( + pub(super) fn find_cycle_in_stack( &self, - query_map: QueryMap, + query_map: QueryMap, current_job: &Option, span: Span, - ) -> CycleError { + ) -> CycleError { // Find the waitee amongst `current_job` parents let mut cycle = Vec::new(); let mut current_job = Option::clone(current_job); @@ -136,7 +153,7 @@ impl QueryJobId { #[cold] #[inline(never)] - pub fn find_dep_kind_root(&self, query_map: QueryMap) -> (QueryJobInfo, usize) { + pub fn find_dep_kind_root(&self, query_map: QueryMap) -> (QueryJobInfo, usize) { let mut depth = 1; let info = query_map.get(&self).unwrap(); let dep_kind = info.query.dep_kind; @@ -156,25 +173,31 @@ impl QueryJobId { } #[derive(Debug)] -struct QueryWaiter { +struct QueryWaiter { query: Option, condvar: Condvar, span: Span, - cycle: Mutex>, + cycle: Mutex>>, } #[derive(Debug)] -struct QueryLatchInfo { +struct QueryLatchInfo { complete: bool, - waiters: Vec>, + waiters: Vec>>, } -#[derive(Clone, Debug)] -pub(super) struct QueryLatch { - info: Arc>, +#[derive(Debug)] +pub(super) struct QueryLatch { + info: Arc>>, } -impl QueryLatch { +impl Clone for QueryLatch { + fn clone(&self) -> Self { + Self { info: Arc::clone(&self.info) } + } +} + +impl QueryLatch { fn new() -> Self { QueryLatch { info: Arc::new(Mutex::new(QueryLatchInfo { complete: false, waiters: Vec::new() })), @@ -182,7 +205,11 @@ impl QueryLatch { } /// Awaits for the query job to complete. - pub(super) fn wait_on(&self, query: Option, span: Span) -> Result<(), CycleError> { + pub(super) fn wait_on( + &self, + query: Option, + span: Span, + ) -> Result<(), CycleError> { let waiter = Arc::new(QueryWaiter { query, span, cycle: Mutex::new(None), condvar: Condvar::new() }); self.wait_on_inner(&waiter); @@ -197,7 +224,7 @@ impl QueryLatch { } /// Awaits the caller on this latch by blocking the current thread. - fn wait_on_inner(&self, waiter: &Arc) { + fn wait_on_inner(&self, waiter: &Arc>) { let mut info = self.info.lock(); if !info.complete { // We push the waiter on to the `waiters` list. It can be accessed inside @@ -232,7 +259,7 @@ impl QueryLatch { /// Removes a single waiter from the list of waiters. /// This is used to break query cycles. - fn extract_waiter(&self, waiter: usize) -> Arc { + fn extract_waiter(&self, waiter: usize) -> Arc> { let mut info = self.info.lock(); debug_assert!(!info.complete); // Remove the waiter from the list of waiters @@ -252,7 +279,11 @@ type Waiter = (QueryJobId, usize); /// For visits of resumable waiters it returns Some(Some(Waiter)) which has the /// required information to resume the waiter. /// If all `visit` calls returns None, this function also returns None. -fn visit_waiters(query_map: &QueryMap, query: QueryJobId, mut visit: F) -> Option> +fn visit_waiters( + query_map: &QueryMap, + query: QueryJobId, + mut visit: F, +) -> Option> where F: FnMut(Span, QueryJobId) -> Option>, { @@ -282,8 +313,8 @@ where /// `span` is the reason for the `query` to execute. This is initially DUMMY_SP. /// If a cycle is detected, this initial value is replaced with the span causing /// the cycle. -fn cycle_check( - query_map: &QueryMap, +fn cycle_check( + query_map: &QueryMap, query: QueryJobId, span: Span, stack: &mut Vec<(Span, QueryJobId)>, @@ -322,8 +353,8 @@ fn cycle_check( /// Finds out if there's a path to the compiler root (aka. code which isn't in a query) /// from `query` without going through any of the queries in `visited`. /// This is achieved with a depth first search. -fn connected_to_root( - query_map: &QueryMap, +fn connected_to_root( + query_map: &QueryMap, query: QueryJobId, visited: &mut FxHashSet, ) -> bool { @@ -344,7 +375,7 @@ fn connected_to_root( } // Deterministically pick an query from a list -fn pick_query<'a, T, F>(query_map: &QueryMap, queries: &'a [T], f: F) -> &'a T +fn pick_query<'a, I: Clone, T, F>(query_map: &QueryMap, queries: &'a [T], f: F) -> &'a T where F: Fn(&T) -> (Span, QueryJobId), { @@ -369,10 +400,10 @@ where /// the function return true. /// If a cycle was not found, the starting query is removed from `jobs` and /// the function returns false. -fn remove_cycle( - query_map: &QueryMap, +fn remove_cycle( + query_map: &QueryMap, jobs: &mut Vec, - wakelist: &mut Vec>, + wakelist: &mut Vec>>, ) -> bool { let mut visited = FxHashSet::default(); let mut stack = Vec::new(); @@ -473,7 +504,10 @@ fn remove_cycle( /// uses a query latch and then resuming that waiter. /// There may be multiple cycles involved in a deadlock, so this searches /// all active queries for cycles before finally resuming all the waiters at once. -pub fn break_query_cycles(query_map: QueryMap, registry: &rayon_core::Registry) { +pub fn break_query_cycles( + query_map: QueryMap, + registry: &rayon_core::Registry, +) { let mut wakelist = Vec::new(); let mut jobs: Vec = query_map.keys().cloned().collect(); @@ -520,7 +554,7 @@ pub fn report_cycle<'a>( ) -> Diag<'a> { assert!(!stack.is_empty()); - let span = stack[0].query.default_span(stack[1 % stack.len()].span); + let span = stack[0].query.info.default_span(stack[1 % stack.len()].span); let mut cycle_stack = Vec::new(); @@ -529,31 +563,31 @@ pub fn report_cycle<'a>( for i in 1..stack.len() { let query = &stack[i].query; - let span = query.default_span(stack[(i + 1) % stack.len()].span); - cycle_stack.push(CycleStack { span, desc: query.description.to_owned() }); + let span = query.info.default_span(stack[(i + 1) % stack.len()].span); + cycle_stack.push(CycleStack { span, desc: query.info.description.to_owned() }); } let mut cycle_usage = None; if let Some((span, ref query)) = *usage { cycle_usage = Some(crate::error::CycleUsage { - span: query.default_span(span), - usage: query.description.to_string(), + span: query.info.default_span(span), + usage: query.info.description.to_string(), }); } - let alias = if stack.iter().all(|entry| matches!(entry.query.def_kind, Some(DefKind::TyAlias))) - { - Some(crate::error::Alias::Ty) - } else if stack.iter().all(|entry| entry.query.def_kind == Some(DefKind::TraitAlias)) { - Some(crate::error::Alias::Trait) - } else { - None - }; + let alias = + if stack.iter().all(|entry| matches!(entry.query.info.def_kind, Some(DefKind::TyAlias))) { + Some(crate::error::Alias::Ty) + } else if stack.iter().all(|entry| entry.query.info.def_kind == Some(DefKind::TraitAlias)) { + Some(crate::error::Alias::Trait) + } else { + None + }; let cycle_diag = crate::error::Cycle { span, cycle_stack, - stack_bottom: stack[0].query.description.to_owned(), + stack_bottom: stack[0].query.info.description.to_owned(), alias, cycle_usage, stack_count, @@ -589,6 +623,7 @@ pub fn print_query_stack( let Some(query_info) = query_map.get(&query) else { break; }; + let query_extra = qcx.lift_query_info(&query_info.query.info); if Some(count_printed) < limit_frames || limit_frames.is_none() { // Only print to stderr as many stack frames as `num_frames` when present. // FIXME: needs translation @@ -596,7 +631,7 @@ pub fn print_query_stack( #[allow(rustc::untranslatable_diagnostic)] dcx.struct_failure_note(format!( "#{} [{:?}] {}", - count_printed, query_info.query.dep_kind, query_info.query.description + count_printed, query_info.query.dep_kind, query_extra.description )) .with_span(query_info.job.span) .emit(); @@ -609,7 +644,7 @@ pub fn print_query_stack( "#{} [{}] {}", count_total, qcx.dep_context().dep_kind_info(query_info.query.dep_kind).name, - query_info.query.description + query_extra.description ); } diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 0d0c66aa978e..d9ee65328313 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -1,4 +1,9 @@ mod plumbing; +use std::fmt::Debug; +use std::marker::PhantomData; +use std::mem::transmute; +use std::sync::Arc; + pub use self::plumbing::*; mod job; @@ -11,6 +16,7 @@ mod caches; pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCache}; mod config; +use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_errors::DiagInner; use rustc_hashes::Hash64; use rustc_hir::def::DefKind; @@ -25,31 +31,59 @@ use crate::dep_graph::{DepKind, DepNodeIndex, HasDepContext, SerializedDepNodeIn /// /// This is mostly used in case of cycles for error reporting. #[derive(Clone, Debug)] -pub struct QueryStackFrame { - pub description: String, - span: Option, - pub def_id: Option, - pub def_kind: Option, - /// A def-id that is extracted from a `Ty` in a query key - pub def_id_for_ty_in_cycle: Option, +pub struct QueryStackFrame { + /// This field initially stores a `QueryStackDeferred` during collection, + /// but can later be changed to `QueryStackFrameExtra` containing concrete information + /// by calling `lift`. This is done so that collecting query does not need to invoke + /// queries, instead `lift` will call queries in a more appropriate location. + pub info: I, + pub dep_kind: DepKind, /// This hash is used to deterministically pick /// a query to remove cycles in the parallel compiler. hash: Hash64, + pub def_id: Option, + /// A def-id that is extracted from a `Ty` in a query key + pub def_id_for_ty_in_cycle: Option, } -impl QueryStackFrame { +impl QueryStackFrame { #[inline] pub fn new( - description: String, - span: Option, - def_id: Option, - def_kind: Option, + info: I, dep_kind: DepKind, - def_id_for_ty_in_cycle: Option, hash: impl FnOnce() -> Hash64, + def_id: Option, + def_id_for_ty_in_cycle: Option, ) -> Self { - Self { description, span, def_id, def_kind, def_id_for_ty_in_cycle, dep_kind, hash: hash() } + Self { info, def_id, dep_kind, hash: hash(), def_id_for_ty_in_cycle } + } + + fn lift>( + &self, + qcx: Qcx, + ) -> QueryStackFrame { + QueryStackFrame { + info: qcx.lift_query_info(&self.info), + dep_kind: self.dep_kind, + hash: self.hash, + def_id: self.def_id, + def_id_for_ty_in_cycle: self.def_id_for_ty_in_cycle, + } + } +} + +#[derive(Clone, Debug)] +pub struct QueryStackFrameExtra { + pub description: String, + span: Option, + pub def_kind: Option, +} + +impl QueryStackFrameExtra { + #[inline] + pub fn new(description: String, span: Option, def_kind: Option) -> Self { + Self { description, span, def_kind } } // FIXME(eddyb) Get more valid `Span`s on queries. @@ -62,7 +96,37 @@ impl QueryStackFrame { } } -/// Track a 'side effects' for a particular query. +/// Track a 'side effect' for a particular query. +/// This is used to hold a closure which can create `QueryStackFrameExtra`. +#[derive(Clone)] +pub struct QueryStackDeferred<'tcx> { + _dummy: PhantomData<&'tcx ()>, + + // `extract` may contain references to 'tcx, but we can't tell drop checking that it won't + // access it in the destructor. + extract: Arc QueryStackFrameExtra + DynSync + DynSend>, +} + +impl<'tcx> QueryStackDeferred<'tcx> { + /// SAFETY: `extract` may not access 'tcx in its destructor. + pub unsafe fn new( + extract: Arc QueryStackFrameExtra + DynSync + DynSend + 'tcx>, + ) -> Self { + Self { _dummy: PhantomData, extract: unsafe { transmute(extract) } } + } + + pub fn extract(&self) -> QueryStackFrameExtra { + (self.extract)() + } +} + +impl<'tcx> Debug for QueryStackDeferred<'tcx> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str("QueryStackDeferred") + } +} + +/// Tracks 'side effects' for a particular query. /// This struct is saved to disk along with the query result, /// and loaded from disk if we mark the query as green. /// This allows us to 'replay' changes to global state @@ -81,12 +145,16 @@ pub enum QuerySideEffect { } pub trait QueryContext: HasDepContext { + type QueryInfo: Clone; + fn next_job_id(self) -> QueryJobId; /// Get the query information from the TLS context. fn current_query_job(self) -> Option; - fn collect_active_jobs(self) -> Result; + fn collect_active_jobs(self) -> Result, QueryMap>; + + fn lift_query_info(self, info: &Self::QueryInfo) -> QueryStackFrameExtra; /// Load a side effect associated to the node in the previous session. fn load_side_effect( diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 3a9d80280c26..6ea8e3b92008 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -16,7 +16,7 @@ use rustc_errors::{Diag, FatalError, StashKey}; use rustc_span::{DUMMY_SP, Span}; use tracing::instrument; -use super::QueryConfig; +use super::{QueryConfig, QueryStackFrameExtra}; use crate::HandleCycleError; use crate::dep_graph::{DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeParams}; use crate::ich::StableHashingContext; @@ -29,23 +29,23 @@ fn equivalent_key(k: &K) -> impl Fn(&(K, V)) -> bool + '_ { move |x| x.0 == *k } -pub struct QueryState { - active: Sharded>, +pub struct QueryState { + active: Sharded)>>, } /// Indicates the state of a query for a given key in a query map. -enum QueryResult { +enum QueryResult { /// An already executing query. The query job can be used to await for its completion. - Started(QueryJob), + Started(QueryJob), /// The query panicked. Queries trying to wait on this will raise a fatal error which will /// silently panic. Poisoned, } -impl QueryResult { +impl QueryResult { /// Unwraps the query job expecting that it has started. - fn expect_job(self) -> QueryJob { + fn expect_job(self) -> QueryJob { match self { Self::Started(job) => job, Self::Poisoned => { @@ -55,7 +55,7 @@ impl QueryResult { } } -impl QueryState +impl QueryState where K: Eq + Hash + Copy + Debug, { @@ -66,8 +66,8 @@ where pub fn try_collect_active_jobs( &self, qcx: Qcx, - make_query: fn(Qcx, K) -> QueryStackFrame, - jobs: &mut QueryMap, + make_query: fn(Qcx, K) -> QueryStackFrame, + jobs: &mut QueryMap, ) -> Option<()> { let mut active = Vec::new(); @@ -76,7 +76,7 @@ where for shard in self.active.try_lock_shards() { for (k, v) in shard?.iter() { if let QueryResult::Started(ref job) = *v { - active.push((*k, job.clone())); + active.push((*k, (*job).clone())); } } } @@ -92,19 +92,19 @@ where } } -impl Default for QueryState { - fn default() -> QueryState { +impl Default for QueryState { + fn default() -> QueryState { QueryState { active: Default::default() } } } /// A type representing the responsibility to execute the job in the `job` field. /// This will poison the relevant query if dropped. -struct JobOwner<'tcx, K> +struct JobOwner<'tcx, K, I> where K: Eq + Hash + Copy, { - state: &'tcx QueryState, + state: &'tcx QueryState, key: K, } @@ -146,7 +146,7 @@ where } Stash => { let guar = if let Some(root) = cycle_error.cycle.first() - && let Some(span) = root.query.span + && let Some(span) = root.query.info.span { error.stash(span, StashKey::Cycle).unwrap() } else { @@ -157,7 +157,7 @@ where } } -impl<'tcx, K> JobOwner<'tcx, K> +impl<'tcx, K, I> JobOwner<'tcx, K, I> where K: Eq + Hash + Copy, { @@ -194,7 +194,7 @@ where } } -impl<'tcx, K> Drop for JobOwner<'tcx, K> +impl<'tcx, K, I> Drop for JobOwner<'tcx, K, I> where K: Eq + Hash + Copy, { @@ -222,10 +222,19 @@ where } #[derive(Clone, Debug)] -pub struct CycleError { +pub struct CycleError { /// The query and related span that uses the cycle. - pub usage: Option<(Span, QueryStackFrame)>, - pub cycle: Vec, + pub usage: Option<(Span, QueryStackFrame)>, + pub cycle: Vec>, +} + +impl CycleError { + fn lift>(&self, qcx: Qcx) -> CycleError { + CycleError { + usage: self.usage.as_ref().map(|(span, frame)| (*span, frame.lift(qcx))), + cycle: self.cycle.iter().map(|info| info.lift(qcx)).collect(), + } + } } /// Checks whether there is already a value for this key in the in-memory @@ -262,10 +271,10 @@ where { // Ensure there was no errors collecting all active jobs. // We need the complete map to ensure we find a cycle to break. - let query_map = qcx.collect_active_jobs().expect("failed to collect active queries"); + let query_map = qcx.collect_active_jobs().ok().expect("failed to collect active queries"); let error = try_execute.find_cycle_in_stack(query_map, &qcx.current_query_job(), span); - (mk_cycle(query, qcx, error), None) + (mk_cycle(query, qcx, error.lift(qcx)), None) } #[inline(always)] @@ -274,7 +283,7 @@ fn wait_for_query( qcx: Qcx, span: Span, key: Q::Key, - latch: QueryLatch, + latch: QueryLatch, current: Option, ) -> (Q::Value, Option) where @@ -314,7 +323,7 @@ where (v, Some(index)) } - Err(cycle) => (mk_cycle(query, qcx, cycle), None), + Err(cycle) => (mk_cycle(query, qcx, cycle.lift(qcx)), None), } } @@ -392,7 +401,7 @@ where fn execute_job( query: Q, qcx: Qcx, - state: &QueryState, + state: &QueryState, key: Q::Key, key_hash: u64, id: QueryJobId, From 781785d2b65f59295997272946be04182646bb39 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Mar 2025 09:36:23 +0000 Subject: [PATCH 558/745] Don't deaggregate InvocationParent just to reaggregate it again --- compiler/rustc_resolve/src/def_collector.rs | 39 ++++++++------------- 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index fcb638a117e3..6f48a75d6174 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -19,18 +19,15 @@ pub(crate) fn collect_definitions( fragment: &AstFragment, expansion: LocalExpnId, ) { - let InvocationParent { parent_def, impl_trait_context, in_attr } = - resolver.invocation_parents[&expansion]; - let mut visitor = DefCollector { resolver, parent_def, expansion, impl_trait_context, in_attr }; + let invocation_parent = resolver.invocation_parents[&expansion]; + let mut visitor = DefCollector { resolver, expansion, invocation_parent }; fragment.visit_with(&mut visitor); } /// Creates `DefId`s for nodes in the AST. struct DefCollector<'a, 'ra, 'tcx> { resolver: &'a mut Resolver<'ra, 'tcx>, - parent_def: LocalDefId, - impl_trait_context: ImplTraitContext, - in_attr: bool, + invocation_parent: InvocationParent, expansion: LocalExpnId, } @@ -42,7 +39,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { def_kind: DefKind, span: Span, ) -> LocalDefId { - let parent_def = self.parent_def; + let parent_def = self.invocation_parent.parent_def; debug!( "create_def(node_id={:?}, def_kind={:?}, parent_def={:?})", node_id, def_kind, parent_def @@ -60,9 +57,9 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { } fn with_parent(&mut self, parent_def: LocalDefId, f: F) { - let orig_parent_def = mem::replace(&mut self.parent_def, parent_def); + let orig_parent_def = mem::replace(&mut self.invocation_parent.parent_def, parent_def); f(self); - self.parent_def = orig_parent_def; + self.invocation_parent.parent_def = orig_parent_def; } fn with_impl_trait( @@ -70,9 +67,10 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { impl_trait_context: ImplTraitContext, f: F, ) { - let orig_itc = mem::replace(&mut self.impl_trait_context, impl_trait_context); + let orig_itc = + mem::replace(&mut self.invocation_parent.impl_trait_context, impl_trait_context); f(self); - self.impl_trait_context = orig_itc; + self.invocation_parent.impl_trait_context = orig_itc; } fn collect_field(&mut self, field: &'a FieldDef, index: Option) { @@ -96,14 +94,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { fn visit_macro_invoc(&mut self, id: NodeId) { let id = id.placeholder_to_expn_id(); - let old_parent = self.resolver.invocation_parents.insert( - id, - InvocationParent { - parent_def: self.parent_def, - impl_trait_context: self.impl_trait_context, - in_attr: self.in_attr, - }, - ); + let old_parent = self.resolver.invocation_parents.insert(id, self.invocation_parent); assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation"); } } @@ -367,7 +358,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { self.with_parent(def, |this| visit::walk_anon_const(this, constant)); return; } - _ => self.parent_def, + _ => self.invocation_parent.parent_def, }; self.with_parent(parent_def, |this| visit::walk_expr(this, expr)) @@ -382,13 +373,13 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { // output or built artifacts, so replace them here... // Perhaps we should instead format APITs more robustly. let name = Symbol::intern(&pprust::ty_to_string(ty).replace('\n', " ")); - let kind = match self.impl_trait_context { + let kind = match self.invocation_parent.impl_trait_context { ImplTraitContext::Universal => DefKind::TyParam, ImplTraitContext::Existential => DefKind::OpaqueTy, ImplTraitContext::InBinding => return visit::walk_ty(self, ty), }; let id = self.create_def(*id, Some(name), kind, ty.span); - match self.impl_trait_context { + match self.invocation_parent.impl_trait_context { // Do not nest APIT, as we desugar them as `impl_trait: bounds`, // so the `impl_trait` node is not a parent to `bounds`. ImplTraitContext::Universal => visit::walk_ty(self, ty), @@ -459,9 +450,9 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { } fn visit_attribute(&mut self, attr: &'a Attribute) -> Self::Result { - let orig_in_attr = mem::replace(&mut self.in_attr, true); + let orig_in_attr = mem::replace(&mut self.invocation_parent.in_attr, true); visit::walk_attribute(self, attr); - self.in_attr = orig_in_attr; + self.invocation_parent.in_attr = orig_in_attr; } fn visit_inline_asm(&mut self, asm: &'a InlineAsm) { From b04e5b496323a8e0a7e4028bfb6252f348c10329 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Wed, 26 Mar 2025 10:42:38 +0100 Subject: [PATCH 559/745] Collect items referenced from var_debug_info The collection is limited to full debuginfo builds to match behavior of FunctionCx::compute_per_local_var_debug_info. --- compiler/rustc_monomorphize/src/collector.rs | 7 +++++- tests/ui/mir/var_debug_ref.rs | 24 ++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 tests/ui/mir/var_debug_ref.rs diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 67fca1d7c294..ad9cec6fed90 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -231,7 +231,7 @@ use rustc_middle::ty::{ use rustc_middle::util::Providers; use rustc_middle::{bug, span_bug}; use rustc_session::Limit; -use rustc_session::config::EntryFnType; +use rustc_session::config::{DebugInfo, EntryFnType}; use rustc_span::source_map::{Spanned, dummy_spanned, respan}; use rustc_span::{DUMMY_SP, Span}; use tracing::{debug, instrument, trace}; @@ -1235,6 +1235,11 @@ fn collect_items_of_instance<'tcx>( }; if mode == CollectionMode::UsedItems { + if tcx.sess.opts.debuginfo == DebugInfo::Full { + for var_debug_info in &body.var_debug_info { + collector.visit_var_debug_info(var_debug_info); + } + } for (bb, data) in traversal::mono_reachable(body, tcx, instance) { collector.visit_basic_block_data(bb, data) } diff --git a/tests/ui/mir/var_debug_ref.rs b/tests/ui/mir/var_debug_ref.rs new file mode 100644 index 000000000000..1dcf38b5bb9f --- /dev/null +++ b/tests/ui/mir/var_debug_ref.rs @@ -0,0 +1,24 @@ +// Regression test for #138942, where a function was incorrectly internalized, despite the fact +// that it was referenced by a var debug info from another code generation unit. +// +//@ build-pass +//@ revisions: limited full +//@ compile-flags: -Ccodegen-units=4 +//@[limited] compile-flags: -Cdebuginfo=limited +//@[full] compile-flags: -Cdebuginfo=full +trait Fun { + const FUN: &'static fn(); +} +impl Fun for () { + const FUN: &'static fn() = &(detail::f as fn()); +} +mod detail { + // Place `f` in a distinct module to generate a separate code generation unit. + #[inline(never)] + pub(super) fn f() {} +} +fn main() { + // SingleUseConsts represents "x" using VarDebugInfoContents::Const. + // It is the only reference to `f` remaining. + let x = <() as ::Fun>::FUN; +} From 6ca2af6434ec40ae91207628722fe6e731f6f358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 26 Mar 2025 13:04:06 +0100 Subject: [PATCH 560/745] Use a function to create `QueryStackDeferred` to ensure context is Copy --- compiler/rustc_query_impl/src/plumbing.rs | 74 +++++++++++--------- compiler/rustc_query_system/src/query/mod.rs | 10 ++- 2 files changed, 48 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 7f1d466b8692..3238c7a0912c 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -3,7 +3,6 @@ //! manage the caches, and so forth. use std::num::NonZero; -use std::sync::Arc; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{DynSend, DynSync}; @@ -312,6 +311,45 @@ macro_rules! should_ever_cache_on_disk { }; } +fn create_query_frame_extra<'tcx, K: Key + Copy + 'tcx>( + (tcx, key, kind, name, do_describe): ( + TyCtxt<'tcx>, + K, + DepKind, + &'static str, + fn(TyCtxt<'tcx>, K) -> String, + ), +) -> QueryStackFrameExtra { + let def_id = key.key_as_def_id(); + + // If reduced queries are requested, we may be printing a query stack due + // to a panic. Avoid using `default_span` and `def_kind` in that case. + let reduce_queries = with_reduced_queries(); + + // Avoid calling queries while formatting the description + let description = ty::print::with_no_queries!(do_describe(tcx, key)); + let description = if tcx.sess.verbose_internals() { + format!("{description} [{name:?}]") + } else { + description + }; + let span = if kind == dep_graph::dep_kinds::def_span || reduce_queries { + // The `def_span` query is used to calculate `default_span`, + // so exit to avoid infinite recursion. + None + } else { + Some(key.default_span(tcx)) + }; + + let def_kind = if kind == dep_graph::dep_kinds::def_kind || reduce_queries { + // Try to avoid infinite recursion. + None + } else { + def_id.and_then(|def_id| def_id.as_local()).map(|def_id| tcx.def_kind(def_id)) + }; + QueryStackFrameExtra::new(description, span, def_kind) +} + pub(crate) fn create_query_frame< 'tcx, K: Copy + DynSend + DynSync + Key + for<'a> HashStable> + 'tcx, @@ -324,35 +362,6 @@ pub(crate) fn create_query_frame< ) -> QueryStackFrame> { let def_id = key.key_as_def_id(); - let extra = move || { - // If reduced queries are requested, we may be printing a query stack due - // to a panic. Avoid using `default_span` and `def_kind` in that case. - let reduce_queries = with_reduced_queries(); - - // Avoid calling queries while formatting the description - let description = ty::print::with_no_queries!(do_describe(tcx, key)); - let description = if tcx.sess.verbose_internals() { - format!("{description} [{name:?}]") - } else { - description - }; - let span = if kind == dep_graph::dep_kinds::def_span || reduce_queries { - // The `def_span` query is used to calculate `default_span`, - // so exit to avoid infinite recursion. - None - } else { - Some(key.default_span(tcx)) - }; - - let def_kind = if kind == dep_graph::dep_kinds::def_kind || reduce_queries { - // Try to avoid infinite recursion. - None - } else { - def_id.and_then(|def_id| def_id.as_local()).map(|def_id| tcx.def_kind(def_id)) - }; - QueryStackFrameExtra::new(description, span, def_kind) - }; - let hash = || { tcx.with_stable_hashing_context(|mut hcx| { let mut hasher = StableHasher::new(); @@ -363,9 +372,8 @@ pub(crate) fn create_query_frame< }; let def_id_for_ty_in_cycle = key.def_id_for_ty_in_cycle(); - // SAFETY: None of the captures in `extra` have destructors that access 'tcx - // as they don't have destructors. - let info = unsafe { QueryStackDeferred::new(Arc::new(extra)) }; + let info = + QueryStackDeferred::new((tcx, key, kind, name, do_describe), create_query_frame_extra); QueryStackFrame::new(info, kind, hash, def_id, def_id_for_ty_in_cycle) } diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index d9ee65328313..ef21af7dafba 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -108,10 +108,14 @@ pub struct QueryStackDeferred<'tcx> { } impl<'tcx> QueryStackDeferred<'tcx> { - /// SAFETY: `extract` may not access 'tcx in its destructor. - pub unsafe fn new( - extract: Arc QueryStackFrameExtra + DynSync + DynSend + 'tcx>, + pub fn new( + context: C, + extract: fn(C) -> QueryStackFrameExtra, ) -> Self { + let extract: Arc QueryStackFrameExtra + DynSync + DynSend + 'tcx> = + Arc::new(move || extract(context)); + // SAFETY: The `extract` closure does not access 'tcx in its destructor as the only + // captured variable is `context` which is Copy and cannot have a destructor. Self { _dummy: PhantomData, extract: unsafe { transmute(extract) } } } From 92d802eda669d69481b99139523008df1c456ba8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 22 Mar 2025 21:42:34 +0300 Subject: [PATCH 561/745] expand: Leave traces when expanding `cfg` attributes --- .../rustc_ast_passes/src/ast_validation.rs | 3 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 2 +- compiler/rustc_expand/src/config.rs | 24 ++++++----- compiler/rustc_expand/src/expand.rs | 13 +++--- compiler/rustc_feature/src/builtin_attrs.rs | 12 ++++-- compiler/rustc_parse/src/validate_attr.rs | 9 ++--- compiler/rustc_passes/src/check_attr.rs | 6 +-- compiler/rustc_query_system/src/ich/mod.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 + src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/clean/types.rs | 2 +- .../src/attrs/duplicated_attributes.rs | 3 +- .../clippy/clippy_lints/src/cfg_not_test.rs | 2 +- .../clippy_lints/src/methods/is_empty.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 8 ++-- tests/pretty/tests-are-sorted.pp | 3 -- .../cfg-attr-syntax-validation.rs | 1 - .../cfg-attr-syntax-validation.stderr | 14 +------ .../invalid-node-range-issue-129166.rs | 3 +- .../invalid-node-range-issue-129166.stderr | 8 ---- tests/ui/parser/attribute/attr-bad-meta-4.rs | 2 - .../parser/attribute/attr-bad-meta-4.stderr | 24 +---------- tests/ui/proc-macro/cfg-attr-trace.rs | 10 ++++- tests/ui/proc-macro/cfg-attr-trace.stdout | 40 +++++++++++++------ 24 files changed, 88 insertions(+), 108 deletions(-) delete mode 100644 tests/ui/conditional-compilation/invalid-node-range-issue-129166.stderr diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index a1487ca74be8..da739b0e4532 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -334,8 +334,7 @@ impl<'a> AstValidator<'a> { .filter(|attr| { let arr = [ sym::allow, - sym::cfg, - sym::cfg_attr, + sym::cfg_trace, sym::cfg_attr_trace, sym::deny, sym::expect, diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index cdb181794498..3dbfc191f8f5 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -593,7 +593,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere } fn print_attribute_inline(&mut self, attr: &ast::Attribute, is_inline: bool) -> bool { - if attr.has_name(sym::cfg_attr_trace) { + if attr.has_name(sym::cfg_trace) || attr.has_name(sym::cfg_attr_trace) { // It's not a valid identifier, so avoid printing it // to keep the printed code reasonably parse-able. return false; diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index ada49eef7b2d..bcc2703c39b3 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -156,6 +156,19 @@ pub fn pre_configure_attrs(sess: &Session, attrs: &[Attribute]) -> ast::AttrVec .collect() } +pub(crate) fn attr_into_trace(mut attr: Attribute, trace_name: Symbol) -> Attribute { + match &mut attr.kind { + AttrKind::Normal(normal) => { + let NormalAttr { item, tokens } = &mut **normal; + item.path.segments[0].ident.name = trace_name; + // This makes the trace attributes unobservable to token-based proc macros. + *tokens = Some(LazyAttrTokenStream::new(AttrTokenStream::default())); + } + AttrKind::DocComment(..) => unreachable!(), + } + attr +} + #[macro_export] macro_rules! configure { ($this:ident, $node:ident) => { @@ -280,16 +293,7 @@ impl<'a> StripUnconfigured<'a> { // A trace attribute left in AST in place of the original `cfg_attr` attribute. // It can later be used by lints or other diagnostics. - let mut trace_attr = cfg_attr.clone(); - match &mut trace_attr.kind { - AttrKind::Normal(normal) => { - let NormalAttr { item, tokens } = &mut **normal; - item.path.segments[0].ident.name = sym::cfg_attr_trace; - // This makes the trace attributes unobservable to token-based proc macros. - *tokens = Some(LazyAttrTokenStream::new(AttrTokenStream::default())); - } - AttrKind::DocComment(..) => unreachable!(), - } + let trace_attr = attr_into_trace(cfg_attr.clone(), sym::cfg_attr_trace); let Some((cfg_predicate, expanded_attrs)) = rustc_parse::parse_cfg_attr(cfg_attr, &self.sess.psess) diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index d0bd8a89d9bd..22da1179feb9 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -33,7 +33,7 @@ use rustc_span::{ErrorGuaranteed, FileName, Ident, LocalExpnId, Span, sym}; use smallvec::SmallVec; use crate::base::*; -use crate::config::StripUnconfigured; +use crate::config::{StripUnconfigured, attr_into_trace}; use crate::errors::{ EmptyDelegationMac, GlobDelegationOutsideImpls, GlobDelegationTraitlessQpath, IncompleteParse, RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue, @@ -2003,7 +2003,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { let attr_name = attr.ident().unwrap().name; // `#[cfg]` and `#[cfg_attr]` are special - they are // eagerly evaluated. - if attr_name != sym::cfg && attr_name != sym::cfg_attr_trace { + if attr_name != sym::cfg_trace && attr_name != sym::cfg_attr_trace { self.cx.sess.psess.buffer_lint( UNUSED_ATTRIBUTES, attr.span, @@ -2027,11 +2027,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { ) -> (bool, Option) { let (res, meta_item) = self.cfg().cfg_true(&attr); if res { - // FIXME: `cfg(TRUE)` attributes do not currently remove themselves during expansion, - // and some tools like rustdoc and clippy rely on that. Find a way to remove them - // while keeping the tools working. - self.cx.expanded_inert_attrs.mark(&attr); - node.visit_attrs(|attrs| attrs.insert(pos, attr)); + // A trace attribute left in AST in place of the original `cfg` attribute. + // It can later be used by lints or other diagnostics. + let trace_attr = attr_into_trace(attr, sym::cfg_trace); + node.visit_attrs(|attrs| attrs.insert(pos, trace_attr)); } (res, meta_item) diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index fd936458f111..6fe65c88f712 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -760,10 +760,14 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ template!(Word, List: r#""...""#), DuplicatesOk, EncodeCrossCrate::Yes, INTERNAL_UNSTABLE ), - // Trace that is left when a `cfg_attr` attribute is expanded. - // The attribute is not gated, to avoid stability errors, but it cannot be used in stable or - // unstable code directly because `sym::cfg_attr_trace` is not a valid identifier, it can only - // be generated by the compiler. + // Traces that are left when `cfg` and `cfg_attr` attributes are expanded. + // The attributes are not gated, to avoid stability errors, but they cannot be used in stable + // or unstable code directly because `sym::cfg_(attr_)trace` are not valid identifiers, they + // can only be generated by the compiler. + ungated!( + cfg_trace, Normal, template!(Word /* irrelevant */), DuplicatesOk, + EncodeCrossCrate::No + ), ungated!( cfg_attr_trace, Normal, template!(Word /* irrelevant */), DuplicatesOk, EncodeCrossCrate::No diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 9ecde2a9eb50..6bbd650dcdfe 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -16,7 +16,8 @@ use rustc_span::{Span, Symbol, sym}; use crate::{errors, parse_in}; pub fn check_attr(psess: &ParseSess, attr: &Attribute) { - if attr.is_doc_comment() || attr.has_name(sym::cfg_attr_trace) { + if attr.is_doc_comment() || attr.has_name(sym::cfg_trace) || attr.has_name(sym::cfg_attr_trace) + { return; } @@ -215,11 +216,7 @@ pub fn check_builtin_meta_item( template: AttributeTemplate, deny_unsafety: bool, ) { - // Some special attributes like `cfg` must be checked - // before the generic check, so we skip them here. - let should_skip = |name| name == sym::cfg; - - if !should_skip(name) && !is_attr_template_compatible(&template, &meta.kind) { + if !is_attr_template_compatible(&template, &meta.kind) { emit_malformed_attribute(psess, style, meta.span, name, template); } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 9238c73cdb11..1e1fb42a48fe 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -272,6 +272,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::forbid | sym::cfg | sym::cfg_attr + | sym::cfg_trace | sym::cfg_attr_trace // need to be fixed | sym::cfi_encoding // FIXME(cfi_encoding) @@ -574,8 +575,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // NOTE: when making changes to this list, check that `error_codes/E0736.md` remains accurate const ALLOW_LIST: &[rustc_span::Symbol] = &[ // conditional compilation - sym::cfg, - sym::cfg_attr, + sym::cfg_trace, sym::cfg_attr_trace, // testing (allowed here so better errors can be generated in `rustc_builtin_macros::test`) sym::test, @@ -2656,7 +2656,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { // only `#[cfg]` and `#[cfg_attr]` are allowed, but it should be removed // if we allow more attributes (e.g., tool attributes and `allow/deny/warn`) // in where clauses. After that, only `self.check_attributes` should be enough. - const ATTRS_ALLOWED: &[Symbol] = &[sym::cfg, sym::cfg_attr, sym::cfg_attr_trace]; + const ATTRS_ALLOWED: &[Symbol] = &[sym::cfg_trace, sym::cfg_attr_trace]; let spans = self .tcx .hir_attrs(where_predicate.hir_id) diff --git a/compiler/rustc_query_system/src/ich/mod.rs b/compiler/rustc_query_system/src/ich/mod.rs index 852d93b711f8..25778add60a9 100644 --- a/compiler/rustc_query_system/src/ich/mod.rs +++ b/compiler/rustc_query_system/src/ich/mod.rs @@ -8,7 +8,7 @@ mod hcx; mod impls_syntax; pub const IGNORED_ATTRIBUTES: &[Symbol] = &[ - sym::cfg, + sym::cfg_trace, // FIXME should this really be ignored? sym::rustc_if_this_changed, sym::rustc_then_this_would_need, sym::rustc_dirty, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3e4742439655..171f553e9c1a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -623,6 +623,7 @@ symbols! { cfg_target_has_atomic_equal_alignment, cfg_target_thread_local, cfg_target_vendor, + cfg_trace: "", // must not be a valid identifier cfg_ub_checks, cfg_version, cfi, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index de6dc088176f..6f660df4d7d4 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2773,7 +2773,7 @@ fn add_without_unwanted_attributes<'hir>( if ident == sym::doc { filter_doc_attr(&mut normal.args, is_inline); attrs.push((Cow::Owned(attr), import_parent)); - } else if is_inline || ident != sym::cfg { + } else if is_inline || ident != sym::cfg_trace { // If it's not a `cfg()` attribute, we keep it. attrs.push((Cow::Owned(attr), import_parent)); } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 27eb56a9858b..150b00dbb48a 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1059,7 +1059,7 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator // `doc(cfg())` overrides `cfg()`). attrs .clone() - .filter(|attr| attr.has_name(sym::cfg)) + .filter(|attr| attr.has_name(sym::cfg_trace)) .filter_map(|attr| single(attr.meta_item_list()?)) .filter_map(|attr| Cfg::parse_without(attr.meta_item()?, hidden_cfg).ok().flatten()) .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg) diff --git a/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs index 5c486eb90cc2..4c84e61b1f26 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs @@ -37,7 +37,6 @@ fn check_duplicated_attr( let Some(ident) = attr.ident() else { return }; let name = ident.name; if name == sym::doc - || name == sym::cfg_attr || name == sym::cfg_attr_trace || name == sym::rustc_on_unimplemented || name == sym::reason { @@ -47,7 +46,7 @@ fn check_duplicated_attr( return; } if let Some(direct_parent) = parent.last() - && ["cfg", "cfg_attr"].contains(&direct_parent.as_str()) + && direct_parent == sym::cfg_trace.as_str() && [sym::all, sym::not, sym::any].contains(&name) { // FIXME: We don't correctly check `cfg`s for now, so if it's more complex than just a one diff --git a/src/tools/clippy/clippy_lints/src/cfg_not_test.rs b/src/tools/clippy/clippy_lints/src/cfg_not_test.rs index 84136a2e6c28..7590fe96fd21 100644 --- a/src/tools/clippy/clippy_lints/src/cfg_not_test.rs +++ b/src/tools/clippy/clippy_lints/src/cfg_not_test.rs @@ -32,7 +32,7 @@ declare_lint_pass!(CfgNotTest => [CFG_NOT_TEST]); impl EarlyLintPass for CfgNotTest { fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &rustc_ast::Attribute) { - if attr.has_name(rustc_span::sym::cfg) && contains_not_test(attr.meta_item_list().as_deref(), false) { + if attr.has_name(rustc_span::sym::cfg_trace) && contains_not_test(attr.meta_item_list().as_deref(), false) { span_lint_and_then( cx, CFG_NOT_TEST, diff --git a/src/tools/clippy/clippy_lints/src/methods/is_empty.rs b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs index 7c190e123b72..4c81b22861b4 100644 --- a/src/tools/clippy/clippy_lints/src/methods/is_empty.rs +++ b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs @@ -41,7 +41,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_ fn is_under_cfg(cx: &LateContext<'_>, id: HirId) -> bool { cx.tcx .hir_parent_id_iter(id) - .any(|id| cx.tcx.hir_attrs(id).iter().any(|attr| attr.has_name(sym::cfg))) + .any(|id| cx.tcx.hir_attrs(id).iter().any(|attr| attr.has_name(sym::cfg_trace))) } /// Similar to [`clippy_utils::expr_or_init`], but does not go up the chain if the initialization diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 1307ff79bc5d..668b0cb69e20 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -2629,7 +2629,7 @@ pub fn peel_ref_operators<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir> pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool { if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind { if let Res::Def(_, def_id) = path.res { - return cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr); + return cx.tcx.has_attr(def_id, sym::cfg_trace) || cx.tcx.has_attr(def_id, sym::cfg_attr); } } false @@ -2699,7 +2699,7 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool { /// use [`is_in_cfg_test`] pub fn is_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool { tcx.hir_attrs(id).iter().any(|attr| { - if attr.has_name(sym::cfg) + if attr.has_name(sym::cfg_trace) && let Some(items) = attr.meta_item_list() && let [item] = &*items && item.has_name(sym::test) @@ -2723,11 +2723,11 @@ pub fn is_in_test(tcx: TyCtxt<'_>, hir_id: HirId) -> bool { /// Checks if the item of any of its parents has `#[cfg(...)]` attribute applied. pub fn inherits_cfg(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { - tcx.has_attr(def_id, sym::cfg) + tcx.has_attr(def_id, sym::cfg_trace) || tcx .hir_parent_iter(tcx.local_def_id_to_hir_id(def_id)) .flat_map(|(parent_id, _)| tcx.hir_attrs(parent_id)) - .any(|attr| attr.has_name(sym::cfg)) + .any(|attr| attr.has_name(sym::cfg_trace)) } /// Walks up the HIR tree from the given expression in an attempt to find where the value is diff --git a/tests/pretty/tests-are-sorted.pp b/tests/pretty/tests-are-sorted.pp index 31449b51dc3e..d6a2c0ff9796 100644 --- a/tests/pretty/tests-are-sorted.pp +++ b/tests/pretty/tests-are-sorted.pp @@ -10,7 +10,6 @@ extern crate std; //@ pp-exact:tests-are-sorted.pp extern crate test; -#[cfg(test)] #[rustc_test_marker = "m_test"] #[doc(hidden)] pub const m_test: test::TestDescAndFn = @@ -35,7 +34,6 @@ pub const m_test: test::TestDescAndFn = fn m_test() {} extern crate test; -#[cfg(test)] #[rustc_test_marker = "z_test"] #[doc(hidden)] pub const z_test: test::TestDescAndFn = @@ -61,7 +59,6 @@ pub const z_test: test::TestDescAndFn = fn z_test() {} extern crate test; -#[cfg(test)] #[rustc_test_marker = "a_test"] #[doc(hidden)] pub const a_test: test::TestDescAndFn = diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs index 9a041557c7cc..416145a0c156 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs @@ -29,7 +29,6 @@ macro_rules! generate_s10 { ($expr: expr) => { #[cfg(feature = $expr)] //~^ ERROR expected unsuffixed literal, found expression `concat!("nonexistent")` - //~| ERROR expected unsuffixed literal, found expression `concat!("nonexistent")` struct S10; } } diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr index 21a3712d9391..d02d0d70a8bc 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr @@ -65,19 +65,7 @@ LL | generate_s10!(concat!("nonexistent")); | = note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info) -error: expected unsuffixed literal, found expression `concat!("nonexistent")` - --> $DIR/cfg-attr-syntax-validation.rs:30:25 - | -LL | #[cfg(feature = $expr)] - | ^^^^^ -... -LL | generate_s10!(concat!("nonexistent")); - | ------------------------------------- in this macro invocation - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 11 previous errors +error: aborting due to 10 previous errors Some errors have detailed explanations: E0537, E0565. For more information about an error, try `rustc --explain E0537`. diff --git a/tests/ui/conditional-compilation/invalid-node-range-issue-129166.rs b/tests/ui/conditional-compilation/invalid-node-range-issue-129166.rs index 794e6fad3fc2..7c42be3ed4d6 100644 --- a/tests/ui/conditional-compilation/invalid-node-range-issue-129166.rs +++ b/tests/ui/conditional-compilation/invalid-node-range-issue-129166.rs @@ -1,11 +1,12 @@ // This was triggering an assertion failure in `NodeRange::new`. +//@ check-pass + #![feature(cfg_eval)] #![feature(stmt_expr_attributes)] fn f() -> u32 { #[cfg_eval] #[cfg(not(FALSE))] 0 - //~^ ERROR removing an expression is not supported in this position } fn main() {} diff --git a/tests/ui/conditional-compilation/invalid-node-range-issue-129166.stderr b/tests/ui/conditional-compilation/invalid-node-range-issue-129166.stderr deleted file mode 100644 index 0699e182bd5f..000000000000 --- a/tests/ui/conditional-compilation/invalid-node-range-issue-129166.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: removing an expression is not supported in this position - --> $DIR/invalid-node-range-issue-129166.rs:7:17 - | -LL | #[cfg_eval] #[cfg(not(FALSE))] 0 - | ^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/parser/attribute/attr-bad-meta-4.rs b/tests/ui/parser/attribute/attr-bad-meta-4.rs index 2d0c6dbb50ab..937390a6da5b 100644 --- a/tests/ui/parser/attribute/attr-bad-meta-4.rs +++ b/tests/ui/parser/attribute/attr-bad-meta-4.rs @@ -2,7 +2,6 @@ macro_rules! mac { ($attr_item: meta) => { #[cfg($attr_item)] //~^ ERROR expected unsuffixed literal, found `meta` metavariable - //~| ERROR expected unsuffixed literal, found `meta` metavariable struct S; } } @@ -11,7 +10,6 @@ mac!(an(arbitrary token stream)); #[cfg(feature = -1)] //~^ ERROR expected unsuffixed literal, found `-` -//~| ERROR expected unsuffixed literal, found `-` fn handler() {} fn main() {} diff --git a/tests/ui/parser/attribute/attr-bad-meta-4.stderr b/tests/ui/parser/attribute/attr-bad-meta-4.stderr index dea574fd36d5..9c6ab5adadf7 100644 --- a/tests/ui/parser/attribute/attr-bad-meta-4.stderr +++ b/tests/ui/parser/attribute/attr-bad-meta-4.stderr @@ -1,5 +1,5 @@ error: expected unsuffixed literal, found `-` - --> $DIR/attr-bad-meta-4.rs:12:17 + --> $DIR/attr-bad-meta-4.rs:11:17 | LL | #[cfg(feature = -1)] | ^ @@ -15,25 +15,5 @@ LL | mac!(an(arbitrary token stream)); | = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) -error: expected unsuffixed literal, found `meta` metavariable - --> $DIR/attr-bad-meta-4.rs:3:15 - | -LL | #[cfg($attr_item)] - | ^^^^^^^^^^ -... -LL | mac!(an(arbitrary token stream)); - | -------------------------------- in this macro invocation - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: expected unsuffixed literal, found `-` - --> $DIR/attr-bad-meta-4.rs:12:17 - | -LL | #[cfg(feature = -1)] - | ^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/proc-macro/cfg-attr-trace.rs b/tests/ui/proc-macro/cfg-attr-trace.rs index b4927f7a730b..140dd10a7e04 100644 --- a/tests/ui/proc-macro/cfg-attr-trace.rs +++ b/tests/ui/proc-macro/cfg-attr-trace.rs @@ -3,6 +3,7 @@ //@ check-pass //@ proc-macro: test-macros.rs +#![feature(cfg_boolean_literals)] #![feature(cfg_eval)] #[macro_use] @@ -10,8 +11,13 @@ extern crate test_macros; #[cfg_eval] #[test_macros::print_attr] -#[cfg_attr(FALSE, test_macros::print_attr)] -#[cfg_attr(all(), test_macros::print_attr)] +#[cfg_attr(false, test_macros::print_attr)] +#[cfg_attr(true, test_macros::print_attr)] struct S; +#[cfg_eval] +#[test_macros::print_attr] +#[cfg(true)] +struct Z; + fn main() {} diff --git a/tests/ui/proc-macro/cfg-attr-trace.stdout b/tests/ui/proc-macro/cfg-attr-trace.stdout index 394c3887fe79..52f9ff4e05c5 100644 --- a/tests/ui/proc-macro/cfg-attr-trace.stdout +++ b/tests/ui/proc-macro/cfg-attr-trace.stdout @@ -4,59 +4,75 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: #0 bytes(271..272), + span: #0 bytes(305..306), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "test_macros", - span: #0 bytes(289..300), + span: #0 bytes(322..333), }, Punct { ch: ':', spacing: Joint, - span: #0 bytes(300..301), + span: #0 bytes(333..334), }, Punct { ch: ':', spacing: Alone, - span: #0 bytes(301..302), + span: #0 bytes(334..335), }, Ident { ident: "print_attr", - span: #0 bytes(302..312), + span: #0 bytes(335..345), }, ], - span: #0 bytes(272..314), + span: #0 bytes(306..347), }, Ident { ident: "struct", - span: #0 bytes(315..321), + span: #0 bytes(348..354), }, Ident { ident: "S", - span: #0 bytes(322..323), + span: #0 bytes(355..356), }, Punct { ch: ';', spacing: Alone, - span: #0 bytes(323..324), + span: #0 bytes(356..357), }, ] PRINT-ATTR INPUT (DISPLAY): struct S; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #0 bytes(315..321), + span: #0 bytes(348..354), }, Ident { ident: "S", - span: #0 bytes(322..323), + span: #0 bytes(355..356), }, Punct { ch: ';', spacing: Alone, - span: #0 bytes(323..324), + span: #0 bytes(356..357), + }, +] +PRINT-ATTR INPUT (DISPLAY): struct Z; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: #0 bytes(411..417), + }, + Ident { + ident: "Z", + span: #0 bytes(418..419), + }, + Punct { + ch: ';', + spacing: Alone, + span: #0 bytes(419..420), }, ] From a830c59f242c2e55da8a69cf5807c450b4a12a33 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Mar 2025 12:39:07 +0000 Subject: [PATCH 562/745] Use the correct binder scope for elided lifetimes in assoc consts --- compiler/rustc_resolve/src/late.rs | 60 +++++++++++-------- .../consts/assoc-const-elided-lifetime.stderr | 2 - .../elided-lifetime.rs | 2 +- .../elided-lifetime.stderr | 20 +++---- .../static-trait-impl.rs | 2 +- .../static-trait-impl.stderr | 24 +++----- 6 files changed, 51 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 11d07407aa18..f4502bcee737 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3334,34 +3334,44 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { }, |this| { this.with_lifetime_rib( - LifetimeRibKind::StaticIfNoLifetimeInScope { - lint_id: item.id, - // In impls, it's not a hard error yet due to backcompat. - emit_lint: true, + // Until these are a hard error, we need to create them within the correct binder, + // Otherwise the lifetimes of this assoc const think they are lifetimes of the trait. + LifetimeRibKind::AnonymousCreateParameter { + binder: item.id, + report_in_path: true, }, |this| { - // If this is a trait impl, ensure the const - // exists in trait - this.check_trait_item( - item.id, - item.ident, - &item.kind, - ValueNS, - item.span, - seen_trait_items, - |i, s, c| ConstNotMemberOfTrait(i, s, c), - ); + this.with_lifetime_rib( + LifetimeRibKind::StaticIfNoLifetimeInScope { + lint_id: item.id, + // In impls, it's not a hard error yet due to backcompat. + emit_lint: true, + }, + |this| { + // If this is a trait impl, ensure the const + // exists in trait + this.check_trait_item( + item.id, + item.ident, + &item.kind, + ValueNS, + item.span, + seen_trait_items, + |i, s, c| ConstNotMemberOfTrait(i, s, c), + ); - this.visit_generics(generics); - this.visit_ty(ty); - if let Some(expr) = expr { - // We allow arbitrary const expressions inside of associated consts, - // even if they are potentially not const evaluatable. - // - // Type parameters can already be used and as associated consts are - // not used as part of the type system, this is far less surprising. - this.resolve_const_body(expr, None); - } + this.visit_generics(generics); + this.visit_ty(ty); + if let Some(expr) = expr { + // We allow arbitrary const expressions inside of associated consts, + // even if they are potentially not const evaluatable. + // + // Type parameters can already be used and as associated consts are + // not used as part of the type system, this is far less surprising. + this.resolve_const_body(expr, None); + } + }, + ) }, ); }, diff --git a/tests/ui/consts/assoc-const-elided-lifetime.stderr b/tests/ui/consts/assoc-const-elided-lifetime.stderr index 0c3e455eb2de..958215268357 100644 --- a/tests/ui/consts/assoc-const-elided-lifetime.stderr +++ b/tests/ui/consts/assoc-const-elided-lifetime.stderr @@ -35,8 +35,6 @@ note: cannot automatically infer `'static` because of other lifetimes in scope | LL | impl<'a> Foo<'a> { | ^^ -LL | const FOO: Foo<'_> = Foo { x: PhantomData::<&()> }; - | ^^ help: use the `'static` lifetime | LL | const BAR: &'static () = &(); diff --git a/tests/ui/consts/static-default-lifetime/elided-lifetime.rs b/tests/ui/consts/static-default-lifetime/elided-lifetime.rs index 95d59f9b894e..ccf63f86fcf3 100644 --- a/tests/ui/consts/static-default-lifetime/elided-lifetime.rs +++ b/tests/ui/consts/static-default-lifetime/elided-lifetime.rs @@ -16,7 +16,7 @@ impl Bar for Foo<'_> { const STATIC: &str = ""; //~^ ERROR `&` without an explicit lifetime name cannot be used here //~| WARN this was previously accepted by the compiler but is being phased out - //~| ERROR const not compatible with trait + //~| ERROR lifetime parameters or bounds on const `STATIC` do not match the trait declaration } fn main() {} diff --git a/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr index ec01225c6bfa..33873f5c5a50 100644 --- a/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr +++ b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr @@ -39,21 +39,15 @@ help: use the `'static` lifetime LL | const STATIC: &'static str = ""; | +++++++ -error[E0308]: const not compatible with trait - --> $DIR/elided-lifetime.rs:16:5 +error[E0195]: lifetime parameters or bounds on const `STATIC` do not match the trait declaration + --> $DIR/elided-lifetime.rs:16:17 | +LL | const STATIC: &str; + | - lifetimes in impl do not match this const in trait +... LL | const STATIC: &str = ""; - | ^^^^^^^^^^^^^^^^^^ lifetime mismatch - | - = note: expected reference `&'static _` - found reference `&_` -note: the anonymous lifetime as defined here... - --> $DIR/elided-lifetime.rs:16:19 - | -LL | const STATIC: &str = ""; - | ^ - = note: ...does not necessarily outlive the static lifetime + | ^ lifetimes do not match const in trait error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0195`. diff --git a/tests/ui/consts/static-default-lifetime/static-trait-impl.rs b/tests/ui/consts/static-default-lifetime/static-trait-impl.rs index 025fda4df581..b50bf01453dc 100644 --- a/tests/ui/consts/static-default-lifetime/static-trait-impl.rs +++ b/tests/ui/consts/static-default-lifetime/static-trait-impl.rs @@ -9,7 +9,7 @@ impl Bar<'_> for A { const STATIC: &str = ""; //~^ ERROR `&` without an explicit lifetime name cannot be used here //~| WARN this was previously accepted by the compiler but is being phased out - //~| ERROR const not compatible with trait + //~| ERROR lifetime parameters or bounds on const `STATIC` do not match the trait declaration } struct B; diff --git a/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr index b8e2f412b492..116f28e84847 100644 --- a/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr +++ b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr @@ -21,25 +21,15 @@ help: use the `'static` lifetime LL | const STATIC: &'static str = ""; | +++++++ -error[E0308]: const not compatible with trait - --> $DIR/static-trait-impl.rs:9:5 +error[E0195]: lifetime parameters or bounds on const `STATIC` do not match the trait declaration + --> $DIR/static-trait-impl.rs:9:17 | +LL | const STATIC: &'a str; + | - lifetimes in impl do not match this const in trait +... LL | const STATIC: &str = ""; - | ^^^^^^^^^^^^^^^^^^ lifetime mismatch - | - = note: expected reference `&_` - found reference `&_` -note: the anonymous lifetime as defined here... - --> $DIR/static-trait-impl.rs:9:19 - | -LL | const STATIC: &str = ""; - | ^ -note: ...does not necessarily outlive the anonymous lifetime as defined here - --> $DIR/static-trait-impl.rs:8:10 - | -LL | impl Bar<'_> for A { - | ^^ + | ^ lifetimes do not match const in trait error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0195`. From c772573708cdc863d9fa03ca4973f9ab08ac9d43 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 16 Nov 2024 18:50:44 +0100 Subject: [PATCH 563/745] Test that env! works with incremental compilation This currently works because it's part of expansion, and that isn't yet tracked by the query system. But we want to ensure it continues working, even if that is changed. --- tests/incremental/env/env_macro.rs | 18 ++++++++++++++++++ tests/incremental/env/option_env_macro.rs | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 tests/incremental/env/env_macro.rs create mode 100644 tests/incremental/env/option_env_macro.rs diff --git a/tests/incremental/env/env_macro.rs b/tests/incremental/env/env_macro.rs new file mode 100644 index 000000000000..0c026328874d --- /dev/null +++ b/tests/incremental/env/env_macro.rs @@ -0,0 +1,18 @@ +// Check that changes to environment variables are propagated to `env!`. +// +// This test is intentionally written to not use any `#[cfg(rpass*)]`, to +// _really_ test that we re-compile if the environment variable changes. + +//@ revisions: cfail1 rpass2 rpass3 cfail4 +//@ [cfail1]unset-rustc-env:EXAMPLE_ENV +//@ [rpass2]rustc-env:EXAMPLE_ENV=one +//@ [rpass2]exec-env:EXAMPLE_ENV=one +//@ [rpass3]rustc-env:EXAMPLE_ENV=two +//@ [rpass3]exec-env:EXAMPLE_ENV=two +//@ [cfail4]unset-rustc-env:EXAMPLE_ENV + +fn main() { + assert_eq!(env!("EXAMPLE_ENV"), std::env::var("EXAMPLE_ENV").unwrap()); + //[cfail1]~^ ERROR environment variable `EXAMPLE_ENV` not defined at compile time + //[cfail4]~^^ ERROR environment variable `EXAMPLE_ENV` not defined at compile time +} diff --git a/tests/incremental/env/option_env_macro.rs b/tests/incremental/env/option_env_macro.rs new file mode 100644 index 000000000000..44c3bfd69e05 --- /dev/null +++ b/tests/incremental/env/option_env_macro.rs @@ -0,0 +1,18 @@ +// Check that changes to environment variables are propagated to `option_env!`. +// +// This test is intentionally written to not use any `#[cfg(rpass*)]`, to +// _really_ test that we re-compile if the environment variable changes. + +//@ revisions: rpass1 rpass2 rpass3 rpass4 +//@ [rpass1]unset-rustc-env:EXAMPLE_ENV +//@ [rpass1]unset-exec-env:EXAMPLE_ENV +//@ [rpass2]rustc-env:EXAMPLE_ENV=one +//@ [rpass2]exec-env:EXAMPLE_ENV=one +//@ [rpass3]rustc-env:EXAMPLE_ENV=two +//@ [rpass3]exec-env:EXAMPLE_ENV=two +//@ [rpass4]unset-rustc-env:EXAMPLE_ENV +//@ [rpass4]unset-exec-env:EXAMPLE_ENV + +fn main() { + assert_eq!(option_env!("EXAMPLE_ENV"), std::env::var("EXAMPLE_ENV").ok().as_deref()); +} From 17db054141f909277a0c57b4698f420636a2c511 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 26 Mar 2025 15:46:05 +0100 Subject: [PATCH 564/745] Add `TyCtx::env_var_os` Along with `TyCtx::env_var` helper. These can be used to track environment variable accesses in the query system. Since `TyCtx::env_var_os` uses `OsStr`, this commit also adds the necessary trait implementations for that to work. --- .../src/stable_hasher.rs | 2 ++ compiler/rustc_interface/src/passes.rs | 28 ++++++++++++++++++- compiler/rustc_middle/src/query/erase.rs | 9 ++++++ compiler/rustc_middle/src/query/keys.rs | 10 +++++++ compiler/rustc_middle/src/query/mod.rs | 16 +++++++++++ compiler/rustc_middle/src/ty/context.rs | 11 ++++++++ 6 files changed, 75 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index ffbe54d62061..3a64c924cc22 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -564,6 +564,8 @@ where } } +impl_stable_traits_for_trivial_type!(::std::ffi::OsStr); + impl_stable_traits_for_trivial_type!(::std::path::Path); impl_stable_traits_for_trivial_type!(::std::path::PathBuf); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 8be7ba7455e1..2440f0639c8a 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1,5 +1,5 @@ use std::any::Any; -use std::ffi::OsString; +use std::ffi::{OsStr, OsString}; use std::io::{self, BufWriter, Write}; use std::path::{Path, PathBuf}; use std::sync::{Arc, LazyLock, OnceLock}; @@ -361,6 +361,31 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { ) } +fn env_var_os<'tcx>(tcx: TyCtxt<'tcx>, key: &'tcx OsStr) -> Option<&'tcx OsStr> { + let value = env::var_os(key); + + let value_tcx = value.as_ref().map(|value| { + let encoded_bytes = tcx.arena.alloc_slice(value.as_encoded_bytes()); + debug_assert_eq!(value.as_encoded_bytes(), encoded_bytes); + // SAFETY: The bytes came from `as_encoded_bytes`, and we assume that + // `alloc_slice` is implemented correctly, and passes the same bytes + // back (debug asserted above). + unsafe { OsStr::from_encoded_bytes_unchecked(encoded_bytes) } + }); + + // Also add the variable to Cargo's dependency tracking + // + // NOTE: This only works for passes run before `write_dep_info`. See that + // for extension points for configuring environment variables to be + // properly change-tracked. + tcx.sess.psess.env_depinfo.borrow_mut().insert(( + Symbol::intern(&key.to_string_lossy()), + value.as_ref().and_then(|value| value.to_str()).map(|value| Symbol::intern(&value)), + )); + + value_tcx +} + // Returns all the paths that correspond to generated files. fn generated_output_paths( tcx: TyCtxt<'_>, @@ -725,6 +750,7 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock = LazyLock::new(|| { |tcx, _| tcx.arena.alloc_from_iter(tcx.resolutions(()).stripped_cfg_items.steal()); providers.resolutions = |tcx, ()| tcx.resolver_for_lowering_raw(()).1; providers.early_lint_checks = early_lint_checks; + providers.env_var_os = env_var_os; limits::provide(providers); proc_macro_decls::provide(providers); rustc_const_eval::provide(providers); diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 7bbaa0496d53..6c6b9a5510c6 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -1,3 +1,4 @@ +use std::ffi::OsStr; use std::intrinsics::transmute_unchecked; use std::mem::MaybeUninit; @@ -67,6 +68,10 @@ impl EraseType for &'_ [T] { type Result = [u8; size_of::<&'static [()]>()]; } +impl EraseType for &'_ OsStr { + type Result = [u8; size_of::<&'static OsStr>()]; +} + impl EraseType for &'_ ty::List { type Result = [u8; size_of::<&'static ty::List<()>>()]; } @@ -174,6 +179,10 @@ impl EraseType for Option<&'_ [T]> { type Result = [u8; size_of::>()]; } +impl EraseType for Option<&'_ OsStr> { + type Result = [u8; size_of::>()]; +} + impl EraseType for Option> { type Result = [u8; size_of::>>()]; } diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index 98314b5abfda..c382bcd726ff 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -1,5 +1,7 @@ //! Defines the set of legal keys that can be used in queries. +use std::ffi::OsStr; + use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, ModDefId}; use rustc_hir::hir_id::{HirId, OwnerId}; use rustc_query_system::dep_graph::DepNodeIndex; @@ -498,6 +500,14 @@ impl Key for Option { } } +impl<'tcx> Key for &'tcx OsStr { + type Cache = DefaultCache; + + fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} + /// Canonical query goals correspond to abstract trait operations that /// are not tied to any crate in particular. impl<'tcx, T: Clone> Key for CanonicalQueryInput<'tcx, T> { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 527c18addbe1..850de3f0c2a3 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -6,6 +6,7 @@ #![allow(unused_parens)] +use std::ffi::OsStr; use std::mem; use std::path::PathBuf; use std::sync::Arc; @@ -119,6 +120,21 @@ rustc_queries! { desc { "perform lints prior to AST lowering" } } + /// Tracked access to environment variables. + /// + /// Useful for the implementation of `std::env!`, `proc-macro`s change + /// detection and other changes in the compiler's behaviour that is easier + /// to control with an environment variable than a flag. + /// + /// NOTE: This currently does not work with dependency info in the + /// analysis, codegen and linking passes, place extra code at the top of + /// `rustc_interface::passes::write_dep_info` to make that work. + query env_var_os(key: &'tcx OsStr) -> Option<&'tcx OsStr> { + // Environment variables are global state + eval_always + desc { "get the value of an environment variable" } + } + query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt { no_hash desc { "getting the resolver outputs" } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index f54dd2b0040a..f2003762af34 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -7,6 +7,8 @@ pub mod tls; use std::assert_matches::{assert_matches, debug_assert_matches}; use std::borrow::Borrow; use std::cmp::Ordering; +use std::env::VarError; +use std::ffi::OsStr; use std::hash::{Hash, Hasher}; use std::marker::PhantomData; use std::ops::{Bound, Deref}; @@ -1882,6 +1884,15 @@ impl<'tcx> TyCtxt<'tcx> { } None } + + /// Helper to get a tracked environment variable via. [`TyCtxt::env_var_os`] and converting to + /// UTF-8 like [`std::env::var`]. + pub fn env_var>(self, key: &'tcx K) -> Result<&'tcx str, VarError> { + match self.env_var_os(key.as_ref()) { + Some(value) => value.to_str().ok_or_else(|| VarError::NotUnicode(value.to_os_string())), + None => Err(VarError::NotPresent), + } + } } impl<'tcx> TyCtxtAt<'tcx> { From 632ce38c9a93a6ee890aedd99fcb1a61cabd0a46 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sun, 1 Dec 2024 11:55:46 +0100 Subject: [PATCH 565/745] Add environment variable tracking in places where it was convenient This won't work with Cargo's change tracking, but it should work with incremental. --- compiler/rustc_borrowck/src/nll.rs | 7 +++---- compiler/rustc_lint/src/non_local_def.rs | 6 ++++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index d0bd364425a5..8e7b6f083aca 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -1,9 +1,9 @@ //! The entry point of the NLL borrow checker. +use std::io; use std::path::PathBuf; use std::rc::Rc; use std::str::FromStr; -use std::{env, io}; use polonius_engine::{Algorithm, Output}; use rustc_index::IndexSlice; @@ -162,9 +162,8 @@ pub(crate) fn compute_regions<'a, 'tcx>( } if polonius_output { - let algorithm = - env::var("POLONIUS_ALGORITHM").unwrap_or_else(|_| String::from("Hybrid")); - let algorithm = Algorithm::from_str(&algorithm).unwrap(); + let algorithm = infcx.tcx.env_var("POLONIUS_ALGORITHM").unwrap_or("Hybrid"); + let algorithm = Algorithm::from_str(algorithm).unwrap(); debug!("compute_regions: using polonius algorithm {:?}", algorithm); let _prof_timer = infcx.tcx.prof.generic_activity("polonius_analysis"); Some(Box::new(Output::compute(polonius_facts, algorithm, false))) diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index f8e0a94f9ec2..9ed11d9cc82f 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -104,8 +104,10 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { // determining if we are in a doctest context can't currently be determined // by the code itself (there are no specific attributes), but fortunately rustdoc // sets a perma-unstable env var for libtest so we just reuse that for now - let is_at_toplevel_doctest = - || self.body_depth == 2 && std::env::var("UNSTABLE_RUSTDOC_TEST_PATH").is_ok(); + let is_at_toplevel_doctest = || { + self.body_depth == 2 + && cx.tcx.env_var_os("UNSTABLE_RUSTDOC_TEST_PATH".as_ref()).is_some() + }; match item.kind { ItemKind::Impl(impl_) => { From a7bafc0afc3dba988a7bf85198c493b20523eaa0 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 26 Mar 2025 15:23:47 +0100 Subject: [PATCH 566/745] Change the syntax of the internal `weak!` macro Change the syntax to include parameter names and a trailing semicolon. Motivation: - Mirror the `syscall!` macro. - Allow rustfmt to format it (when wrapped in parentheses). - For better documentation (having the parameter names available in the source code is a bit nicer). - Allow future improvements to this macro where we can sometimes use the symbol directly when it's statically known to be available. --- library/std/src/sys/fs/unix.rs | 16 +++--- library/std/src/sys/pal/unix/fd.rs | 52 ++++++++++++++----- library/std/src/sys/pal/unix/kernel_copy.rs | 16 +++--- .../std/src/sys/pal/unix/stack_overflow.rs | 30 ++++++++--- library/std/src/sys/pal/unix/thread.rs | 13 +++-- library/std/src/sys/pal/unix/time.rs | 7 ++- library/std/src/sys/pal/unix/weak.rs | 40 ++++++++------ library/std/src/sys/process/unix/unix.rs | 42 ++++++++------- library/std/src/sys/random/linux.rs | 8 +-- 9 files changed, 144 insertions(+), 80 deletions(-) diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 7c3ed8029f7d..60e6559fa6b9 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -155,15 +155,15 @@ cfg_has_statx! {{ enum STATX_STATE{ Unknown = 0, Present, Unavailable } static STATX_SAVED_STATE: AtomicU8 = AtomicU8::new(STATX_STATE::Unknown as u8); - syscall! { + syscall!( fn statx( fd: c_int, pathname: *const c_char, flags: c_int, mask: libc::c_uint, - statxbuf: *mut libc::statx - ) -> c_int - } + statxbuf: *mut libc::statx, + ) -> c_int; + ); let statx_availability = STATX_SAVED_STATE.load(Ordering::Relaxed); if statx_availability == STATX_STATE::Unavailable as u8 { @@ -1540,7 +1540,9 @@ impl File { let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?]; // futimens requires Android API level 19 cvt(unsafe { - weak!(fn futimens(c_int, *const libc::timespec) -> c_int); + weak!( + fn futimens(fd: c_int, times: *const libc::timespec) -> c_int; + ); match futimens.get() { Some(futimens) => futimens(self.as_raw_fd(), times.as_ptr()), None => return Err(io::const_error!( @@ -1556,7 +1558,9 @@ impl File { use crate::sys::{time::__timespec64, weak::weak}; // Added in glibc 2.34 - weak!(fn __futimens64(libc::c_int, *const __timespec64) -> libc::c_int); + weak!( + fn __futimens64(fd: c_int, times: *const __timespec64) -> c_int; + ); if let Some(futimens64) = __futimens64.get() { let to_timespec = |time: Option| time.map(|time| time.t.to_timespec64()) diff --git a/library/std/src/sys/pal/unix/fd.rs b/library/std/src/sys/pal/unix/fd.rs index f03c440e30e1..2ec8d01c13f4 100644 --- a/library/std/src/sys/pal/unix/fd.rs +++ b/library/std/src/sys/pal/unix/fd.rs @@ -232,14 +232,14 @@ impl FileDesc { // implementation if `preadv` is not available. #[cfg(all(target_os = "android", target_pointer_width = "64"))] pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { - super::weak::syscall! { + super::weak::syscall!( fn preadv( fd: libc::c_int, iovec: *const libc::iovec, n_iovec: libc::c_int, - offset: off64_t - ) -> isize - } + offset: off64_t, + ) -> isize; + ); let ret = cvt(unsafe { preadv( @@ -257,7 +257,14 @@ impl FileDesc { // and its metadata from LLVM IR. #[no_sanitize(cfi)] pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { - super::weak::weak!(fn preadv64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize); + super::weak::weak!( + fn preadv64( + fd: libc::c_int, + iovec: *const libc::iovec, + n_iovec: libc::c_int, + offset: off64_t, + ) -> isize; + ); match preadv64.get() { Some(preadv) => { @@ -286,7 +293,14 @@ impl FileDesc { // use "weak" linking. #[cfg(target_vendor = "apple")] pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { - super::weak::weak!(fn preadv(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize); + super::weak::weak!( + fn preadv( + fd: libc::c_int, + iovec: *const libc::iovec, + n_iovec: libc::c_int, + offset: off64_t, + ) -> isize; + ); match preadv.get() { Some(preadv) => { @@ -428,14 +442,14 @@ impl FileDesc { // implementation if `pwritev` is not available. #[cfg(all(target_os = "android", target_pointer_width = "64"))] pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { - super::weak::syscall! { + super::weak::syscall!( fn pwritev( fd: libc::c_int, iovec: *const libc::iovec, n_iovec: libc::c_int, - offset: off64_t - ) -> isize - } + offset: off64_t, + ) -> isize; + ); let ret = cvt(unsafe { pwritev( @@ -450,7 +464,14 @@ impl FileDesc { #[cfg(all(target_os = "android", target_pointer_width = "32"))] pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { - super::weak::weak!(fn pwritev64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize); + super::weak::weak!( + fn pwritev64( + fd: libc::c_int, + iovec: *const libc::iovec, + n_iovec: libc::c_int, + offset: off64_t, + ) -> isize; + ); match pwritev64.get() { Some(pwritev) => { @@ -479,7 +500,14 @@ impl FileDesc { // use "weak" linking. #[cfg(target_vendor = "apple")] pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { - super::weak::weak!(fn pwritev(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize); + super::weak::weak!( + fn pwritev( + fd: libc::c_int, + iovec: *const libc::iovec, + n_iovec: libc::c_int, + offset: off64_t, + ) -> isize; + ); match pwritev.get() { Some(pwritev) => { diff --git a/library/std/src/sys/pal/unix/kernel_copy.rs b/library/std/src/sys/pal/unix/kernel_copy.rs index bbf29f325234..d42a7e2a7fc5 100644 --- a/library/std/src/sys/pal/unix/kernel_copy.rs +++ b/library/std/src/sys/pal/unix/kernel_copy.rs @@ -604,16 +604,16 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) -> _ => true, }; - syscall! { + syscall!( fn copy_file_range( fd_in: libc::c_int, off_in: *mut libc::loff_t, fd_out: libc::c_int, off_out: *mut libc::loff_t, len: libc::size_t, - flags: libc::c_uint - ) -> libc::ssize_t - } + flags: libc::c_uint, + ) -> libc::ssize_t; + ); fn probe_copy_file_range_support() -> u8 { // In some cases, we cannot determine availability from the first @@ -727,16 +727,16 @@ fn sendfile_splice(mode: SpliceMode, reader: RawFd, writer: RawFd, len: u64) -> // Android builds use feature level 14, but the libc wrapper for splice is // gated on feature level 21+, so we have to invoke the syscall directly. #[cfg(target_os = "android")] - syscall! { + syscall!( fn splice( srcfd: libc::c_int, src_offset: *const i64, dstfd: libc::c_int, dst_offset: *const i64, len: libc::size_t, - flags: libc::c_int - ) -> libc::ssize_t - } + flags: libc::c_int, + ) -> libc::ssize_t; + ); #[cfg(target_os = "linux")] use libc::splice; diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs index 4bd0cedd44cc..34b3948e3f67 100644 --- a/library/std/src/sys/pal/unix/stack_overflow.rs +++ b/library/std/src/sys/pal/unix/stack_overflow.rs @@ -424,18 +424,32 @@ mod imp { let pages = PAGES.get_or_init(|| { use crate::sys::weak::dlsym; - dlsym!(fn sysctlbyname(*const libc::c_char, *mut libc::c_void, *mut libc::size_t, *const libc::c_void, libc::size_t) -> libc::c_int); + dlsym!( + fn sysctlbyname( + name: *const libc::c_char, + oldp: *mut libc::c_void, + oldlenp: *mut libc::size_t, + newp: *const libc::c_void, + newlen: libc::size_t, + ) -> libc::c_int; + ); let mut guard: usize = 0; let mut size = size_of_val(&guard); let oid = c"security.bsd.stack_guard_page"; match sysctlbyname.get() { - Some(fcn) if unsafe { - fcn(oid.as_ptr(), - (&raw mut guard).cast(), - &raw mut size, - ptr::null_mut(), - 0) == 0 - } => guard, + Some(fcn) + if unsafe { + fcn( + oid.as_ptr(), + (&raw mut guard).cast(), + &raw mut size, + ptr::null_mut(), + 0, + ) == 0 + } => + { + guard + } _ => 1, } }); diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index bb34c2fabe55..9078dd1c2316 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -193,11 +193,12 @@ impl Thread { // and its metadata from LLVM IR. #[no_sanitize(cfi)] pub fn set_name(name: &CStr) { - weak! { + weak!( fn pthread_setname_np( - libc::pthread_t, *const libc::c_char - ) -> libc::c_int - } + thread: libc::pthread_t, + name: *const libc::c_char, + ) -> libc::c_int; + ); if let Some(f) = pthread_setname_np.get() { #[cfg(target_os = "nto")] @@ -762,7 +763,9 @@ unsafe fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize { // We use dlsym to avoid an ELF version dependency on GLIBC_PRIVATE. (#23628) // We shouldn't really be using such an internal symbol, but there's currently // no other way to account for the TLS size. - dlsym!(fn __pthread_get_minstack(*const libc::pthread_attr_t) -> libc::size_t); + dlsym!( + fn __pthread_get_minstack(attr: *const libc::pthread_attr_t) -> libc::size_t; + ); match __pthread_get_minstack.get() { None => libc::PTHREAD_STACK_MIN, diff --git a/library/std/src/sys/pal/unix/time.rs b/library/std/src/sys/pal/unix/time.rs index c0a3044660b7..b8469b1681f0 100644 --- a/library/std/src/sys/pal/unix/time.rs +++ b/library/std/src/sys/pal/unix/time.rs @@ -123,7 +123,12 @@ impl Timespec { // __clock_gettime64 was added to 32-bit arches in glibc 2.34, // and it handles both vDSO calls and ENOSYS fallbacks itself. - weak!(fn __clock_gettime64(libc::clockid_t, *mut __timespec64) -> libc::c_int); + weak!( + fn __clock_gettime64( + clockid: libc::clockid_t, + tp: *mut __timespec64, + ) -> libc::c_int; + ); if let Some(clock_gettime64) = __clock_gettime64.get() { let mut t = MaybeUninit::uninit(); diff --git a/library/std/src/sys/pal/unix/weak.rs b/library/std/src/sys/pal/unix/weak.rs index ce3f66a83748..e7f4e005cc48 100644 --- a/library/std/src/sys/pal/unix/weak.rs +++ b/library/std/src/sys/pal/unix/weak.rs @@ -29,7 +29,7 @@ use crate::{mem, ptr}; // We can use true weak linkage on ELF targets. #[cfg(all(unix, not(target_vendor = "apple")))] pub(crate) macro weak { - (fn $name:ident($($t:ty),*) -> $ret:ty) => ( + (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => ( let ref $name: ExternWeak $ret> = { unsafe extern "C" { #[linkage = "extern_weak"] @@ -62,10 +62,16 @@ impl ExternWeak { } pub(crate) macro dlsym { - (fn $name:ident($($t:ty),*) -> $ret:ty) => ( - dlsym!(fn $name($($t),*) -> $ret, stringify!($name)); + (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => ( + dlsym!( + #[link_name = stringify!($name)] + fn $name($($param : $t),*) -> $ret; + ); ), - (fn $name:ident($($t:ty),*) -> $ret:ty, $sym:expr) => ( + ( + #[link_name = $sym:expr] + fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty; + ) => ( static DLSYM: DlsymWeak $ret> = DlsymWeak::new(concat!($sym, '\0')); let $name = &DLSYM; @@ -143,15 +149,15 @@ unsafe fn fetch(name: &str) -> *mut libc::c_void { #[cfg(not(any(target_os = "linux", target_os = "android")))] pub(crate) macro syscall { - (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( + (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => ( // FIXME(#115199): Rust currently omits weak function definitions // and its metadata from LLVM IR. #[no_sanitize(cfi)] - unsafe fn $name($($arg_name: $t),*) -> $ret { - weak! { fn $name($($t),*) -> $ret } + unsafe fn $name($($param: $t),*) -> $ret { + weak!(fn $name($($param: $t),*) -> $ret;); if let Some(fun) = $name.get() { - fun($($arg_name),*) + fun($($param),*) } else { super::os::set_errno(libc::ENOSYS); -1 @@ -162,16 +168,18 @@ pub(crate) macro syscall { #[cfg(any(target_os = "linux", target_os = "android"))] pub(crate) macro syscall { - (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( - unsafe fn $name($($arg_name:$t),*) -> $ret { - weak! { fn $name($($t),*) -> $ret } + ( + fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty; + ) => ( + unsafe fn $name($($param: $t),*) -> $ret { + weak!(fn $name($($param: $t),*) -> $ret;); // Use a weak symbol from libc when possible, allowing `LD_PRELOAD` // interposition, but if it's not found just use a raw syscall. if let Some(fun) = $name.get() { - fun($($arg_name),*) + fun($($param),*) } else { - libc::syscall(libc::${concat(SYS_, $name)}, $($arg_name),*) as $ret + libc::syscall(libc::${concat(SYS_, $name)}, $($param),*) as $ret } } ) @@ -179,9 +187,9 @@ pub(crate) macro syscall { #[cfg(any(target_os = "linux", target_os = "android"))] pub(crate) macro raw_syscall { - (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( - unsafe fn $name($($arg_name:$t),*) -> $ret { - libc::syscall(libc::${concat(SYS_, $name)}, $($arg_name),*) as $ret + (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => ( + unsafe fn $name($($param: $t),*) -> $ret { + libc::syscall(libc::${concat(SYS_, $name)}, $($param),*) as $ret } ) } diff --git a/library/std/src/sys/process/unix/unix.rs b/library/std/src/sys/process/unix/unix.rs index 42542f81b654..191a09c8da91 100644 --- a/library/std/src/sys/process/unix/unix.rs +++ b/library/std/src/sys/process/unix/unix.rs @@ -461,18 +461,20 @@ impl Command { if #[cfg(target_os = "linux")] { use crate::sys::weak::weak; - weak! { + weak!( fn pidfd_spawnp( - *mut libc::c_int, - *const libc::c_char, - *const libc::posix_spawn_file_actions_t, - *const libc::posix_spawnattr_t, - *const *mut libc::c_char, - *const *mut libc::c_char - ) -> libc::c_int - } + pidfd: *mut libc::c_int, + path: *const libc::c_char, + file_actions: *const libc::posix_spawn_file_actions_t, + attrp: *const libc::posix_spawnattr_t, + argv: *const *mut libc::c_char, + envp: *const *mut libc::c_char, + ) -> libc::c_int; + ); - weak! { fn pidfd_getpid(libc::c_int) -> libc::c_int } + weak!( + fn pidfd_getpid(pidfd: libc::c_int) -> libc::c_int; + ); static PIDFD_SUPPORTED: AtomicU8 = AtomicU8::new(0); const UNKNOWN: u8 = 0; @@ -593,19 +595,19 @@ impl Command { // https://pubs.opengroup.org/onlinepubs/9799919799/functions/posix_spawn_file_actions_addchdir.html. // The _np version is more widely available, though, so try that first. - weak! { + weak!( fn posix_spawn_file_actions_addchdir_np( - *mut libc::posix_spawn_file_actions_t, - *const libc::c_char - ) -> libc::c_int - } + file_actions: *mut libc::posix_spawn_file_actions_t, + path: *const libc::c_char, + ) -> libc::c_int; + ); - weak! { + weak!( fn posix_spawn_file_actions_addchdir( - *mut libc::posix_spawn_file_actions_t, - *const libc::c_char - ) -> libc::c_int - } + file_actions: *mut libc::posix_spawn_file_actions_t, + path: *const libc::c_char, + ) -> libc::c_int; + ); posix_spawn_file_actions_addchdir_np .get() diff --git a/library/std/src/sys/random/linux.rs b/library/std/src/sys/random/linux.rs index e3cb79285cd1..c0591ec0c152 100644 --- a/library/std/src/sys/random/linux.rs +++ b/library/std/src/sys/random/linux.rs @@ -73,13 +73,13 @@ fn getrandom(mut bytes: &mut [u8], insecure: bool) { // A weak symbol allows interposition, e.g. for perf measurements that want to // disable randomness for consistency. Otherwise, we'll try a raw syscall. // (`getrandom` was added in glibc 2.25, musl 1.1.20, android API level 28) - syscall! { + syscall!( fn getrandom( buffer: *mut libc::c_void, length: libc::size_t, - flags: libc::c_uint - ) -> libc::ssize_t - } + flags: libc::c_uint, + ) -> libc::ssize_t; + ); static GETRANDOM_AVAILABLE: AtomicBool = AtomicBool::new(true); static GRND_INSECURE_AVAILABLE: AtomicBool = AtomicBool::new(true); From a86e0dacbce4e9bc624ef1ebd71a575c9dd0aa01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Wed, 26 Feb 2025 03:08:03 +0100 Subject: [PATCH 567/745] doc(hir::Place): clarify that places aren't always place expressions --- compiler/rustc_middle/src/hir/place.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/hir/place.rs b/compiler/rustc_middle/src/hir/place.rs index 316ad80eb985..60ce8544aa0e 100644 --- a/compiler/rustc_middle/src/hir/place.rs +++ b/compiler/rustc_middle/src/hir/place.rs @@ -53,7 +53,10 @@ pub struct Projection<'tcx> { pub kind: ProjectionKind, } -/// A `Place` represents how a value is located in memory. +/// A `Place` represents how a value is located in memory. This does not +/// always correspond to a syntactic place expression. For example, when +/// processing a pattern, a `Place` can be used to refer to the sub-value +/// currently being inspected. /// /// This is an HIR version of [`rustc_middle::mir::Place`]. #[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] @@ -67,7 +70,10 @@ pub struct Place<'tcx> { pub projections: Vec>, } -/// A `PlaceWithHirId` represents how a value is located in memory. +/// A `PlaceWithHirId` represents how a value is located in memory. This does not +/// always correspond to a syntactic place expression. For example, when +/// processing a pattern, a `Place` can be used to refer to the sub-value +/// currently being inspected. /// /// This is an HIR version of [`rustc_middle::mir::Place`]. #[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] From 376c88ee6fb910fa32ac8966788e9b8e3569a74b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Wed, 26 Feb 2025 03:41:10 +0100 Subject: [PATCH 568/745] ExprUseVisitor: add clarifying doc comments --- .../rustc_hir_typeck/src/expr_use_visitor.rs | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index c71a5ea8b976..1b007200549f 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -1,6 +1,9 @@ //! A different sort of visitor for walking fn bodies. Unlike the //! normal visitor, which just walks the entire body in one shot, the //! `ExprUseVisitor` determines how expressions are being used. +//! +//! In the compiler, this is only used for upvar inference, but there +//! are many uses within clippy. use std::cell::{Ref, RefCell}; use std::ops::Deref; @@ -35,11 +38,8 @@ pub trait Delegate<'tcx> { /// The value found at `place` is moved, depending /// on `mode`. Where `diag_expr_id` is the id used for diagnostics for `place`. /// - /// Use of a `Copy` type in a ByValue context is considered a use - /// by `ImmBorrow` and `borrow` is called instead. This is because - /// a shared borrow is the "minimum access" that would be needed - /// to perform a copy. - /// + /// If the value is `Copy`, [`copy`][Self::copy] is called instead, which + /// by default falls back to [`borrow`][Self::borrow]. /// /// The parameter `diag_expr_id` indicates the HIR id that ought to be used for /// diagnostics. Around pattern matching such as `let pat = expr`, the diagnostic @@ -73,6 +73,10 @@ pub trait Delegate<'tcx> { /// The value found at `place` is being copied. /// `diag_expr_id` is the id used for diagnostics (see `consume` for more details). + /// + /// If an implementation is not provided, use of a `Copy` type in a ByValue context is instead + /// considered a use by `ImmBorrow` and `borrow` is called instead. This is because a shared + /// borrow is the "minimum access" that would be needed to perform a copy. fn copy(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) { // In most cases, copying data from `x` is equivalent to doing `*&x`, so by default // we treat a copy of `x` as a borrow of `x`. @@ -141,6 +145,8 @@ impl<'tcx, D: Delegate<'tcx>> Delegate<'tcx> for &mut D { } } +/// This trait makes `ExprUseVisitor` usable with both [`FnCtxt`] +/// and [`LateContext`], depending on where in the compiler it is used. pub trait TypeInformationCtxt<'tcx> { type TypeckResults<'a>: Deref> where @@ -268,9 +274,9 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) { } } -/// The ExprUseVisitor type +/// A visitor that reports how each expression is being used. /// -/// This is the code that actually walks the tree. +/// See [module-level docs][self] and [`Delegate`] for details. pub struct ExprUseVisitor<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> { cx: Cx, /// We use a `RefCell` here so that delegates can mutate themselves, but we can @@ -1285,7 +1291,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx self.pat_ty_unadjusted(pat) } - /// Like `TypeckResults::pat_ty`, but ignores implicit `&` patterns. + /// Like [`Self::pat_ty_adjusted`], but ignores implicit `&` patterns. fn pat_ty_unadjusted(&self, pat: &hir::Pat<'_>) -> Result, Cx::Error> { let base_ty = self.node_ty(pat.hir_id)?; trace!(?base_ty); From aab12930f5b71489f4c27db9d45897a2563a407e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Wed, 26 Feb 2025 03:49:46 +0100 Subject: [PATCH 569/745] ExprUseVisitor: error -> bug in helper names A name like "report_error" suggests that the error in question might be user facing. Use "bug" to make it clear that the error in question will be an ICE. --- .../rustc_hir_typeck/src/expr_use_visitor.rs | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 1b007200549f..58bac159f37d 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -160,7 +160,7 @@ pub trait TypeInformationCtxt<'tcx> { fn try_structurally_resolve_type(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>; - fn report_error(&self, span: Span, msg: impl ToString) -> Self::Error; + fn report_bug(&self, span: Span, msg: impl ToString) -> Self::Error; fn error_reported_in_ty(&self, ty: Ty<'tcx>) -> Result<(), Self::Error>; @@ -195,7 +195,7 @@ impl<'tcx> TypeInformationCtxt<'tcx> for &FnCtxt<'_, 'tcx> { (**self).try_structurally_resolve_type(sp, ty) } - fn report_error(&self, span: Span, msg: impl ToString) -> Self::Error { + fn report_bug(&self, span: Span, msg: impl ToString) -> Self::Error { self.dcx().span_delayed_bug(span, msg.to_string()) } @@ -245,7 +245,7 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) { t } - fn report_error(&self, span: Span, msg: impl ToString) -> ! { + fn report_bug(&self, span: Span, msg: impl ToString) -> ! { span_bug!(span, "{}", msg.to_string()) } @@ -1218,7 +1218,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx /// result of `*x'`, effectively, where `x'` is a `Categorization::Upvar` reference /// tied to `x`. The type of `x'` will be a borrowed pointer. impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx, Cx, D> { - fn resolve_type_vars_or_error( + fn resolve_type_vars_or_bug( &self, id: HirId, ty: Option>, @@ -1228,10 +1228,10 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx let ty = self.cx.resolve_vars_if_possible(ty); self.cx.error_reported_in_ty(ty)?; if ty.is_ty_var() { - debug!("resolve_type_vars_or_error: infer var from {:?}", ty); + debug!("resolve_type_vars_or_bug: infer var from {:?}", ty); Err(self .cx - .report_error(self.cx.tcx().hir().span(id), "encountered type variable")) + .report_bug(self.cx.tcx().hir().span(id), "encountered type variable")) } else { Ok(ty) } @@ -1248,15 +1248,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } fn node_ty(&self, hir_id: HirId) -> Result, Cx::Error> { - self.resolve_type_vars_or_error(hir_id, self.cx.typeck_results().node_type_opt(hir_id)) + self.resolve_type_vars_or_bug(hir_id, self.cx.typeck_results().node_type_opt(hir_id)) } fn expr_ty(&self, expr: &hir::Expr<'_>) -> Result, Cx::Error> { - self.resolve_type_vars_or_error(expr.hir_id, self.cx.typeck_results().expr_ty_opt(expr)) + self.resolve_type_vars_or_bug(expr.hir_id, self.cx.typeck_results().expr_ty_opt(expr)) } fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Result, Cx::Error> { - self.resolve_type_vars_or_error( + self.resolve_type_vars_or_bug( expr.hir_id, self.cx.typeck_results().expr_ty_adjusted_opt(expr), ) @@ -1321,7 +1321,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx debug!("By-ref binding of non-derefable type"); Err(self .cx - .report_error(pat.span, "by-ref binding of non-derefable type")) + .report_bug(pat.span, "by-ref binding of non-derefable type")) } } } else { @@ -1610,7 +1610,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx Some(ty) => ty, None => { debug!("explicit deref of non-derefable type: {:?}", base_curr_ty); - return Err(self.cx.report_error( + return Err(self.cx.report_bug( self.cx.tcx().hir().span(node), "explicit deref of non-derefable type", )); @@ -1635,7 +1635,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx let ty::Adt(adt_def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() else { return Err(self .cx - .report_error(span, "struct or tuple struct pattern not applied to an ADT")); + .report_bug(span, "struct or tuple struct pattern not applied to an ADT")); }; match res { @@ -1681,7 +1681,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx let ty = self.cx.typeck_results().node_type(pat_hir_id); match self.cx.try_structurally_resolve_type(span, ty).kind() { ty::Tuple(args) => Ok(args.len()), - _ => Err(self.cx.report_error(span, "tuple pattern not applied to a tuple")), + _ => Err(self.cx.report_bug(span, "tuple pattern not applied to a tuple")), } } @@ -1860,7 +1860,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx debug!("explicit index of non-indexable type {:?}", place_with_id); return Err(self .cx - .report_error(pat.span, "explicit index of non-indexable type")); + .report_bug(pat.span, "explicit index of non-indexable type")); }; let elt_place = self.cat_projection( pat.hir_id, From f16195382c93e2aac65028618a6d506501229632 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Wed, 26 Feb 2025 10:25:44 +0100 Subject: [PATCH 570/745] ExprUseVisitor: remove leftover mentions of mem-categorization In #124902, mem-categorization got merged into ExprUseVisitor itself. Adjust the comments that have become misleading or confusing following this change. --- .../rustc_hir_typeck/src/expr_use_visitor.rs | 63 ++++--------------- compiler/rustc_hir_typeck/src/upvar.rs | 10 +-- 2 files changed, 16 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 58bac159f37d..806604677fe0 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -867,7 +867,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } /// Walks the autoref `autoref` applied to the autoderef'd - /// `expr`. `base_place` is the mem-categorized form of `expr` + /// `expr`. `base_place` is `expr` represented as a place, /// after all relevant autoderefs have occurred. fn walk_autoref( &self, @@ -1170,53 +1170,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } } -/// The job of the categorization methods is to analyze an expression to -/// determine what kind of memory is used in evaluating it (for example, -/// where dereferences occur and what kind of pointer is dereferenced; -/// whether the memory is mutable, etc.). +/// The job of the methods whose name starts with `cat_` is to analyze +/// expressions and construct the corresponding [`Place`]s. The `cat` +/// stands for "categorize", this is a leftover from long ago when +/// places were called "categorizations". /// -/// Categorization effectively transforms all of our expressions into -/// expressions of the following forms (the actual enum has many more -/// possibilities, naturally, but they are all variants of these base -/// forms): -/// ```ignore (not-rust) -/// E = rvalue // some computed rvalue -/// | x // address of a local variable or argument -/// | *E // deref of a ptr -/// | E.comp // access to an interior component -/// ``` -/// Imagine a routine ToAddr(Expr) that evaluates an expression and returns an -/// address where the result is to be found. If Expr is a place, then this -/// is the address of the place. If `Expr` is an rvalue, this is the address of -/// some temporary spot in memory where the result is stored. -/// -/// Now, `cat_expr()` classifies the expression `Expr` and the address `A = ToAddr(Expr)` -/// as follows: -/// -/// - `cat`: what kind of expression was this? This is a subset of the -/// full expression forms which only includes those that we care about -/// for the purpose of the analysis. -/// - `mutbl`: mutability of the address `A`. -/// - `ty`: the type of data found at the address `A`. -/// -/// The resulting categorization tree differs somewhat from the expressions -/// themselves. For example, auto-derefs are explicit. Also, an index `a[b]` is -/// decomposed into two operations: a dereference to reach the array data and -/// then an index to jump forward to the relevant item. -/// -/// ## By-reference upvars -/// -/// One part of the codegen which may be non-obvious is that we translate -/// closure upvars into the dereference of a borrowed pointer; this more closely -/// resembles the runtime codegen. So, for example, if we had: -/// -/// let mut x = 3; -/// let y = 5; -/// let inc = || x += y; -/// -/// Then when we categorize `x` (*within* the closure) we would yield a -/// result of `*x'`, effectively, where `x'` is a `Categorization::Upvar` reference -/// tied to `x`. The type of `x'` will be a borrowed pointer. +/// Note that a [`Place`] differs somewhat from the expression itself. For +/// example, auto-derefs are explicit. Also, an index `a[b]` is decomposed into +/// two operations: a dereference to reach the array data and then an index to +/// jump forward to the relevant item. impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx, Cx, D> { fn resolve_type_vars_or_bug( &self, @@ -1239,10 +1201,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx None => { // FIXME: We shouldn't be relying on the infcx being tainted. self.cx.tainted_by_errors()?; - bug!( - "no type for node {} in mem_categorization", - self.cx.tcx().hir_id_to_string(id) - ); + bug!("no type for node {} in ExprUseVisitor", self.cx.tcx().hir_id_to_string(id)); } } } @@ -1517,7 +1476,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } } - def => span_bug!(span, "unexpected definition in memory categorization: {:?}", def), + def => span_bug!(span, "unexpected definition in ExprUseVisitor: {:?}", def), } } diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index fc98a603dd85..d07bfade1570 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -18,12 +18,12 @@ //! from there). //! //! The fact that we are inferring borrow kinds as we go results in a -//! semi-hacky interaction with mem-categorization. In particular, -//! mem-categorization will query the current borrow kind as it -//! categorizes, and we'll return the *current* value, but this may get +//! semi-hacky interaction with the way `ExprUseVisitor` is computing +//! `Place`s. In particular, it will query the current borrow kind as it +//! goes, and we'll return the *current* value, but this may get //! adjusted later. Therefore, in this module, we generally ignore the -//! borrow kind (and derived mutabilities) that are returned from -//! mem-categorization, since they may be inaccurate. (Another option +//! borrow kind (and derived mutabilities) that `ExprUseVisitor` returns +//! within `Place`s, since they may be inaccurate. (Another option //! would be to use a unification scheme, where instead of returning a //! concrete borrow kind like `ty::ImmBorrow`, we return a //! `ty::InferBorrow(upvar_id)` or something like that, but this would From 908504ec2865186b2e2963e07d24b8849ba828e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Wed, 26 Mar 2025 16:22:26 +0100 Subject: [PATCH 571/745] ExprUseVisitor: use tracing::instrument as appropriate Replace debug! calls that output a worse version of what #[instrument] does. --- .../rustc_hir_typeck/src/expr_use_visitor.rs | 29 +++++++------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 806604677fe0..6fb289235de9 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -28,7 +28,7 @@ use rustc_middle::ty::{ use rustc_middle::{bug, span_bug}; use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::infer::InferCtxtExt; -use tracing::{debug, trace}; +use tracing::{debug, instrument, trace}; use crate::fn_ctxt::FnCtxt; @@ -320,9 +320,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx Ok(()) } + #[instrument(skip(self), level = "debug")] fn consume_or_copy(&self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) { - debug!("delegate_consume(place_with_id={:?})", place_with_id); - if self.cx.type_is_copy_modulo_regions(place_with_id.place.ty()) { self.delegate.borrow_mut().copy(place_with_id, diag_expr_id); } else { @@ -330,9 +329,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } } + #[instrument(skip(self), level = "debug")] pub fn consume_clone_or_copy(&self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) { - debug!("delegate_consume_or_clone(place_with_id={:?})", place_with_id); - // `x.use` will do one of the following // * if it implements `Copy`, it will be a copy // * if it implements `UseCloned`, it will be a call to `clone` @@ -357,18 +355,16 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } // FIXME: It's suspicious that this is public; clippy should probably use `walk_expr`. + #[instrument(skip(self), level = "debug")] pub fn consume_expr(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> { - debug!("consume_expr(expr={:?})", expr); - let place_with_id = self.cat_expr(expr)?; self.consume_or_copy(&place_with_id, place_with_id.hir_id); self.walk_expr(expr)?; Ok(()) } + #[instrument(skip(self), level = "debug")] pub fn consume_or_clone_expr(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> { - debug!("consume_or_clone_expr(expr={:?})", expr); - let place_with_id = self.cat_expr(expr)?; self.consume_clone_or_copy(&place_with_id, place_with_id.hir_id); self.walk_expr(expr)?; @@ -382,17 +378,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx Ok(()) } + #[instrument(skip(self), level = "debug")] fn borrow_expr(&self, expr: &hir::Expr<'_>, bk: ty::BorrowKind) -> Result<(), Cx::Error> { - debug!("borrow_expr(expr={:?}, bk={:?})", expr, bk); - let place_with_id = self.cat_expr(expr)?; self.delegate.borrow_mut().borrow(&place_with_id, place_with_id.hir_id, bk); self.walk_expr(expr) } + #[instrument(skip(self), level = "debug")] pub fn walk_expr(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> { - debug!("walk_expr(expr={:?})", expr); - self.walk_adjustment(expr)?; match expr.kind { @@ -739,9 +733,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx /// Indicates that the value of `blk` will be consumed, meaning either copied or moved /// depending on its type. + #[instrument(skip(self), level = "debug")] fn walk_block(&self, blk: &hir::Block<'_>) -> Result<(), Cx::Error> { - debug!("walk_block(blk.hir_id={})", blk.hir_id); - for stmt in blk.stmts { self.walk_stmt(stmt)?; } @@ -948,14 +941,13 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } /// The core driver for walking a pattern + #[instrument(skip(self), level = "debug")] fn walk_pat( &self, discr_place: &PlaceWithHirId<'tcx>, pat: &hir::Pat<'_>, has_guard: bool, ) -> Result<(), Cx::Error> { - debug!("walk_pat(discr_place={:?}, pat={:?}, has_guard={:?})", discr_place, pat, has_guard); - let tcx = self.cx.tcx(); self.cat_pattern(discr_place.clone(), pat, &mut |place, pat| { match pat.kind { @@ -1048,6 +1040,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx /// /// - When reporting the Place back to the Delegate, ensure that the UpvarId uses the enclosing /// closure as the DefId. + #[instrument(skip(self), level = "debug")] fn walk_captures(&self, closure_expr: &hir::Closure<'_>) -> Result<(), Cx::Error> { fn upvar_is_local_variable( upvars: Option<&FxIndexMap>, @@ -1057,8 +1050,6 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx upvars.map(|upvars| !upvars.contains_key(&upvar_id)).unwrap_or(body_owner_is_closure) } - debug!("walk_captures({:?})", closure_expr); - let tcx = self.cx.tcx(); let closure_def_id = closure_expr.def_id; // For purposes of this function, coroutine and closures are equivalent. From 1da5e60ac59661bca0d09b50839600fe0deeb0aa Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 26 Mar 2025 14:48:14 +0100 Subject: [PATCH 572/745] Don't record child scopes for patterns. They are unused. --- compiler/rustc_hir_analysis/src/check/region.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 255f5fee52a8..c81f75eb3198 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -221,8 +221,6 @@ fn resolve_arm<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, arm: &'tcx hir: } fn resolve_pat<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, pat: &'tcx hir::Pat<'tcx>) { - visitor.record_child_scope(Scope { local_id: pat.hir_id.local_id, data: ScopeData::Node }); - // If this is a binding then record the lifetime of that binding. if let PatKind::Binding(..) = pat.kind { record_var_lifetime(visitor, pat.hir_id.local_id); From 227f93395a2cc86f6f66d26a68fdbd7955a8ec51 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 26 Mar 2025 14:49:07 +0100 Subject: [PATCH 573/745] Simplify RvalueCandidateType. There is no difference between the Patternand Borrow cases. Reduce it to a simple struct. --- .../rustc_hir_analysis/src/check/region.rs | 10 ++---- .../rustc_hir_typeck/src/rvalue_scopes.rs | 12 +++---- compiler/rustc_middle/src/middle/region.rs | 31 ++++++++----------- 3 files changed, 19 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index c81f75eb3198..a7007c5d831b 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -623,10 +623,7 @@ fn resolve_local<'tcx>( if is_binding_pat(pat) { visitor.scope_tree.record_rvalue_candidate( expr.hir_id, - RvalueCandidateType::Pattern { - target: expr.hir_id.local_id, - lifetime: blk_scope, - }, + RvalueCandidate { target: expr.hir_id.local_id, lifetime: blk_scope }, ); } } @@ -731,10 +728,7 @@ fn resolve_local<'tcx>( record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id); visitor.scope_tree.record_rvalue_candidate( subexpr.hir_id, - RvalueCandidateType::Borrow { - target: subexpr.hir_id.local_id, - lifetime: blk_id, - }, + RvalueCandidate { target: subexpr.hir_id.local_id, lifetime: blk_id }, ); } hir::ExprKind::Struct(_, fields, _) => { diff --git a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs index 98d7f777d6b8..973dc7141e64 100644 --- a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs +++ b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs @@ -2,7 +2,7 @@ use hir::Node; use hir::def_id::DefId; use rustc_hir as hir; use rustc_middle::bug; -use rustc_middle::middle::region::{RvalueCandidateType, Scope, ScopeTree}; +use rustc_middle::middle::region::{RvalueCandidate, Scope, ScopeTree}; use rustc_middle::ty::RvalueScopes; use tracing::debug; @@ -55,15 +55,11 @@ fn record_rvalue_scope_rec( fn record_rvalue_scope( rvalue_scopes: &mut RvalueScopes, expr: &hir::Expr<'_>, - candidate: &RvalueCandidateType, + candidate: &RvalueCandidate, ) { debug!("resolve_rvalue_scope(expr={expr:?}, candidate={candidate:?})"); - match candidate { - RvalueCandidateType::Borrow { lifetime, .. } - | RvalueCandidateType::Pattern { lifetime, .. } => { - record_rvalue_scope_rec(rvalue_scopes, expr, *lifetime) - } // FIXME(@dingxiangfei2009): handle the candidates in the function call arguments - } + record_rvalue_scope_rec(rvalue_scopes, expr, candidate.lifetime) + // FIXME(@dingxiangfei2009): handle the candidates in the function call arguments } pub(crate) fn resolve_rvalue_scopes<'a, 'tcx>( diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index 66861519e17c..66ece8f0e52f 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -224,7 +224,7 @@ pub struct ScopeTree { /// and not the enclosing *statement*. Expressions that are not present in this /// table are not rvalue candidates. The set of rvalue candidates is computed /// during type check based on a traversal of the AST. - pub rvalue_candidates: HirIdMap, + pub rvalue_candidates: HirIdMap, /// Backwards incompatible scoping that will be introduced in future editions. /// This information is used later for linting to identify locals and @@ -308,15 +308,14 @@ pub struct ScopeTree { pub yield_in_scope: UnordMap>, } -/// Identifies the reason that a given expression is an rvalue candidate -/// (see the `rvalue_candidates` field for more information what rvalue -/// candidates in general). In constants, the `lifetime` field is None -/// to indicate that certain expressions escape into 'static and -/// should have no local cleanup scope. +/// See the `rvalue_candidates` field for more information on rvalue +/// candidates in general. +/// The `lifetime` field is None to indicate that certain expressions escape +/// into 'static and should have no local cleanup scope. #[derive(Debug, Copy, Clone, HashStable)] -pub enum RvalueCandidateType { - Borrow { target: hir::ItemLocalId, lifetime: Option }, - Pattern { target: hir::ItemLocalId, lifetime: Option }, +pub struct RvalueCandidate { + pub target: hir::ItemLocalId, + pub lifetime: Option, } #[derive(Debug, Copy, Clone, HashStable)] @@ -344,16 +343,12 @@ impl ScopeTree { self.var_map.insert(var, lifetime); } - pub fn record_rvalue_candidate(&mut self, var: HirId, candidate_type: RvalueCandidateType) { - debug!("record_rvalue_candidate(var={var:?}, type={candidate_type:?})"); - match &candidate_type { - RvalueCandidateType::Borrow { lifetime: Some(lifetime), .. } - | RvalueCandidateType::Pattern { lifetime: Some(lifetime), .. } => { - assert!(var.local_id != lifetime.local_id) - } - _ => {} + pub fn record_rvalue_candidate(&mut self, var: HirId, candidate: RvalueCandidate) { + debug!("record_rvalue_candidate(var={var:?}, candidate={candidate:?})"); + if let Some(lifetime) = &candidate.lifetime { + assert!(var.local_id != lifetime.local_id) } - self.rvalue_candidates.insert(var, candidate_type); + self.rvalue_candidates.insert(var, candidate); } /// Returns the narrowest scope that encloses `id`, if any. From 0ad0142a5be5c6aab4d0b5a897a7d11c78fbea12 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 26 Mar 2025 16:07:14 +0100 Subject: [PATCH 574/745] Don't set cx.parent to None; it seems unnecessary. --- compiler/rustc_hir_analysis/src/check/region.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index a7007c5d831b..4e4b97557365 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -849,13 +849,12 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { self.enter_body(body.value.hir_id, |this| { if this.tcx.hir_body_owner_kind(owner_id).is_fn_or_closure() { // The arguments and `self` are parented to the fn. - this.cx.var_parent = this.cx.parent.take(); + this.cx.var_parent = this.cx.parent; for param in body.params { this.visit_pat(param.pat); } // The body of the every fn is a root scope. - this.cx.parent = this.cx.var_parent; this.visit_expr(body.value) } else { // Only functions have an outer terminating (drop) scope, while From 2cc3fa32ef0ac964c3c99b14d0cbc422a10788bb Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 26 Mar 2025 17:13:49 +0100 Subject: [PATCH 575/745] Remove ScopeDepth from var_parent. It was never used. --- .../rustc_hir_analysis/src/check/region.rs | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 4e4b97557365..ba8124b11fc1 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -25,12 +25,18 @@ use tracing::debug; struct Context { /// The scope that contains any new variables declared, plus its depth in /// the scope tree. - var_parent: Option<(Scope, ScopeDepth)>, + var_parent: Option, /// Region parent of expressions, etc., plus its depth in the scope tree. parent: Option<(Scope, ScopeDepth)>, } +impl Context { + fn set_var_parent(&mut self) { + self.var_parent = self.parent.map(|(p, _)| p); + } +} + struct ScopeResolutionVisitor<'tcx> { tcx: TyCtxt<'tcx>, @@ -78,7 +84,7 @@ fn record_var_lifetime(visitor: &mut ScopeResolutionVisitor<'_>, var_id: hir::It // // extern fn isalnum(c: c_int) -> c_int } - Some((parent_scope, _)) => visitor.scope_tree.record_var_scope(var_id, parent_scope), + Some(parent_scope) => visitor.scope_tree.record_var_scope(var_id, parent_scope), } } @@ -113,7 +119,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi // itself has returned. visitor.enter_node_scope_with_dtor(blk.hir_id.local_id); - visitor.cx.var_parent = visitor.cx.parent; + visitor.cx.set_var_parent(); { // This block should be kept approximately in sync with @@ -132,7 +138,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi local_id: blk.hir_id.local_id, data: ScopeData::Remainder(FirstStatementIndex::new(i)), }); - visitor.cx.var_parent = visitor.cx.parent; + visitor.cx.set_var_parent(); visitor.visit_stmt(statement); // We need to back out temporarily to the last enclosing scope // for the `else` block, so that even the temporaries receiving @@ -157,7 +163,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi local_id: blk.hir_id.local_id, data: ScopeData::Remainder(FirstStatementIndex::new(i)), }); - visitor.cx.var_parent = visitor.cx.parent; + visitor.cx.set_var_parent(); visitor.visit_stmt(statement) } hir::StmtKind::Item(..) => { @@ -207,7 +213,7 @@ fn resolve_arm<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, arm: &'tcx hir: visitor.terminating_scopes.insert(arm.hir_id.local_id); visitor.enter_node_scope_with_dtor(arm.hir_id.local_id); - visitor.cx.var_parent = visitor.cx.parent; + visitor.cx.set_var_parent(); if let Some(expr) = arm.guard && !has_let_expr(expr) @@ -484,7 +490,7 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi ScopeData::IfThen }; visitor.enter_scope(Scope { local_id: then.hir_id.local_id, data }); - visitor.cx.var_parent = visitor.cx.parent; + visitor.cx.set_var_parent(); visitor.visit_expr(cond); visitor.visit_expr(then); visitor.cx = expr_cx; @@ -499,7 +505,7 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi ScopeData::IfThen }; visitor.enter_scope(Scope { local_id: then.hir_id.local_id, data }); - visitor.cx.var_parent = visitor.cx.parent; + visitor.cx.set_var_parent(); visitor.visit_expr(cond); visitor.visit_expr(then); visitor.cx = expr_cx; @@ -558,7 +564,7 @@ fn resolve_local<'tcx>( ) { debug!("resolve_local(pat={:?}, init={:?})", pat, init); - let blk_scope = visitor.cx.var_parent.map(|(p, _)| p); + let blk_scope = visitor.cx.var_parent; // As an exception to the normal rules governing temporary // lifetimes, initializers in a let have a temporary lifetime @@ -849,7 +855,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { self.enter_body(body.value.hir_id, |this| { if this.tcx.hir_body_owner_kind(owner_id).is_fn_or_closure() { // The arguments and `self` are parented to the fn. - this.cx.var_parent = this.cx.parent; + this.cx.set_var_parent(); for param in body.params { this.visit_pat(param.pat); } From 2e5a76cd1e3a88b22fe4a38428cdabcbddfd0b4a Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Wed, 26 Mar 2025 14:32:35 -0400 Subject: [PATCH 576/745] Use cfg_match in core --- library/core/src/ffi/primitives.rs | 28 ++++--- library/core/src/internal_macros.rs | 77 ------------------- library/core/src/lib.rs | 1 + library/core/src/num/f32.rs | 23 +++--- library/core/src/slice/sort/select.rs | 8 +- library/core/src/slice/sort/stable/mod.rs | 16 ++-- library/core/src/slice/sort/unstable/mod.rs | 9 ++- .../core/src/slice/sort/unstable/quicksort.rs | 9 ++- 8 files changed, 53 insertions(+), 118 deletions(-) diff --git a/library/core/src/ffi/primitives.rs b/library/core/src/ffi/primitives.rs index 0a70eb4da552..351bf9f83147 100644 --- a/library/core/src/ffi/primitives.rs +++ b/library/core/src/ffi/primitives.rs @@ -35,7 +35,7 @@ type_alias! { "c_float.md", c_float = f32; } type_alias! { "c_double.md", c_double = f64; } mod c_char_definition { - cfg_if! { + crate::cfg_match! { // These are the targets on which c_char is unsigned. Usually the // signedness is the same for all target_os values on a given architecture // but there are some exceptions (see isSignedCharDefault() in clang). @@ -105,7 +105,7 @@ mod c_char_definition { // architecture defaults). As we only have a target for userspace apps so there are no // special cases for L4Re below. // https://github.com/rust-lang/rust/pull/132975#issuecomment-2484645240 - if #[cfg(all( + all( not(windows), not(target_vendor = "apple"), not(target_os = "vita"), @@ -122,24 +122,27 @@ mod c_char_definition { target_arch = "s390x", target_arch = "xtensa", ) - ))] { + ) => { pub(super) type c_char = u8; - } else { - // On every other target, c_char is signed. + } + // On every other target, c_char is signed. + _ => { pub(super) type c_char = i8; } } } mod c_long_definition { - cfg_if! { - if #[cfg(any( + crate::cfg_match! { + any( all(target_pointer_width = "64", not(windows)), // wasm32 Linux ABI uses 64-bit long - all(target_arch = "wasm32", target_os = "linux")))] { + all(target_arch = "wasm32", target_os = "linux") + ) => { pub(super) type c_long = i64; pub(super) type c_ulong = u64; - } else { + } + _ => { // The minimal size of `long` in the C standard is 32 bits pub(super) type c_long = i32; pub(super) type c_ulong = u32; @@ -169,11 +172,12 @@ pub type c_ptrdiff_t = isize; pub type c_ssize_t = isize; mod c_int_definition { - cfg_if! { - if #[cfg(any(target_arch = "avr", target_arch = "msp430"))] { + crate::cfg_match! { + any(target_arch = "avr", target_arch = "msp430") => { pub(super) type c_int = i16; pub(super) type c_uint = u16; - } else { + } + _ => { pub(super) type c_int = i32; pub(super) type c_uint = u32; } diff --git a/library/core/src/internal_macros.rs b/library/core/src/internal_macros.rs index fe4fa80263c2..2aaefba2468b 100644 --- a/library/core/src/internal_macros.rs +++ b/library/core/src/internal_macros.rs @@ -120,80 +120,3 @@ macro_rules! impl_fn_for_zst { )+ } } - -/// A macro for defining `#[cfg]` if-else statements. -/// -/// `cfg_if` is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade -/// of `#[cfg]` cases, emitting the implementation which matches first. -/// -/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code without having to -/// rewrite each clause multiple times. -/// -/// # Example -/// -/// ```ignore(cannot-test-this-because-non-exported-macro) -/// cfg_if! { -/// if #[cfg(unix)] { -/// fn foo() { /* unix specific functionality */ } -/// } else if #[cfg(target_pointer_width = "32")] { -/// fn foo() { /* non-unix, 32-bit functionality */ } -/// } else { -/// fn foo() { /* fallback implementation */ } -/// } -/// } -/// -/// # fn main() {} -/// ``` -// This is a copy of `cfg_if!` from the `cfg_if` crate. -// The recursive invocations should use $crate if this is ever exported. -macro_rules! cfg_if { - // match if/else chains with a final `else` - ( - $( - if #[cfg( $i_meta:meta )] { $( $i_tokens:tt )* } - ) else+ - else { $( $e_tokens:tt )* } - ) => { - cfg_if! { - @__items () ; - $( - (( $i_meta ) ( $( $i_tokens )* )) , - )+ - (() ( $( $e_tokens )* )) , - } - }; - - // Internal and recursive macro to emit all the items - // - // Collects all the previous cfgs in a list at the beginning, so they can be - // negated. After the semicolon is all the remaining items. - (@__items ( $( $_:meta , )* ) ; ) => {}; - ( - @__items ( $( $no:meta , )* ) ; - (( $( $yes:meta )? ) ( $( $tokens:tt )* )) , - $( $rest:tt , )* - ) => { - // Emit all items within one block, applying an appropriate #[cfg]. The - // #[cfg] will require all `$yes` matchers specified and must also negate - // all previous matchers. - #[cfg(all( - $( $yes , )? - not(any( $( $no ),* )) - ))] - cfg_if! { @__identity $( $tokens )* } - - // Recurse to emit all other items in `$rest`, and when we do so add all - // our `$yes` matchers to the list of `$no` matchers as future emissions - // will have to negate everything we just matched as well. - cfg_if! { - @__items ( $( $no , )* $( $yes , )? ) ; - $( $rest , )* - } - }; - - // Internal macro to make __apply work out right for different match types, - // because of how macros match/expand stuff. - (@__identity $( $tokens:tt )* ) => { - $( $tokens )* - }; -} diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index e1ca69edcbbd..dc06aa4c38d5 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -100,6 +100,7 @@ #![feature(bigint_helper_methods)] #![feature(bstr)] #![feature(bstr_internals)] +#![feature(cfg_match)] #![feature(closure_track_caller)] #![feature(const_carrying_mul_add)] #![feature(const_eval_select)] diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 79d864e1b196..53373584d555 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -14,7 +14,7 @@ use crate::convert::FloatToInt; use crate::num::FpCategory; use crate::panic::const_assert; -use crate::{intrinsics, mem}; +use crate::{cfg_match, intrinsics, mem}; /// The radix or base of the internal representation of `f32`. /// Use [`f32::RADIX`] instead. @@ -996,21 +996,22 @@ impl f32 { #[stable(feature = "num_midpoint", since = "1.85.0")] #[rustc_const_stable(feature = "num_midpoint", since = "1.85.0")] pub const fn midpoint(self, other: f32) -> f32 { - cfg_if! { + cfg_match! { // Allow faster implementation that have known good 64-bit float // implementations. Falling back to the branchy code on targets that don't // have 64-bit hardware floats or buggy implementations. // https://github.com/rust-lang/rust/pull/121062#issuecomment-2123408114 - if #[cfg(any( - target_arch = "x86_64", - target_arch = "aarch64", - all(any(target_arch = "riscv32", target_arch = "riscv64"), target_feature = "d"), - all(target_arch = "arm", target_feature = "vfp2"), - target_arch = "wasm32", - target_arch = "wasm64", - ))] { + any( + target_arch = "x86_64", + target_arch = "aarch64", + all(any(target_arch = "riscv32", target_arch = "riscv64"), target_feature = "d"), + all(target_arch = "arm", target_feature = "vfp2"), + target_arch = "wasm32", + target_arch = "wasm64", + ) => { ((self as f64 + other as f64) / 2.0) as f32 - } else { + } + _ => { const LO: f32 = f32::MIN_POSITIVE * 2.; const HI: f32 = f32::MAX / 2.; diff --git a/library/core/src/slice/sort/select.rs b/library/core/src/slice/sort/select.rs index 3358c03d30a9..c4808b1065d0 100644 --- a/library/core/src/slice/sort/select.rs +++ b/library/core/src/slice/sort/select.rs @@ -6,6 +6,7 @@ //! for pivot selection. Using this as a fallback ensures O(n) worst case running time with //! better performance than one would get using heapsort as fallback. +use crate::cfg_match; use crate::mem::{self, SizedTypeProperties}; #[cfg(not(feature = "optimize_for_size"))] use crate::slice::sort::shared::pivot::choose_pivot; @@ -41,10 +42,11 @@ where let min_idx = min_index(v, &mut is_less).unwrap(); v.swap(min_idx, index); } else { - cfg_if! { - if #[cfg(feature = "optimize_for_size")] { + cfg_match! { + feature = "optimize_for_size" => { median_of_medians(v, &mut is_less, index); - } else { + } + _ => { partition_at_index_loop(v, index, None, &mut is_less); } } diff --git a/library/core/src/slice/sort/stable/mod.rs b/library/core/src/slice/sort/stable/mod.rs index 090367cdabad..a36e5f7801d4 100644 --- a/library/core/src/slice/sort/stable/mod.rs +++ b/library/core/src/slice/sort/stable/mod.rs @@ -2,12 +2,12 @@ #[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))] use crate::cmp; -use crate::intrinsics; use crate::mem::{MaybeUninit, SizedTypeProperties}; #[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))] use crate::slice::sort::shared::smallsort::{ SMALL_SORT_GENERAL_SCRATCH_LEN, StableSmallSortTypeImpl, insertion_sort_shift_left, }; +use crate::{cfg_match, intrinsics}; pub(crate) mod merge; @@ -39,17 +39,18 @@ pub fn sort bool, BufT: BufGuard>(v: &mut [T], is_less return; } - cfg_if! { - if #[cfg(any(feature = "optimize_for_size", target_pointer_width = "16"))] { + cfg_match! { + any(feature = "optimize_for_size", target_pointer_width = "16") => { // Unlike driftsort, mergesort only requires len / 2, // not len - len / 2. let alloc_len = len / 2; - cfg_if! { - if #[cfg(target_pointer_width = "16")] { + cfg_match! { + target_pointer_width = "16" => { let mut heap_buf = BufT::with_capacity(alloc_len); let scratch = heap_buf.as_uninit_slice_mut(); - } else { + } + _ => { // For small inputs 4KiB of stack storage suffices, which allows us to avoid // calling the (de-)allocator. Benchmarks showed this was quite beneficial. let mut stack_buf = AlignedStorage::::new(); @@ -65,7 +66,8 @@ pub fn sort bool, BufT: BufGuard>(v: &mut [T], is_less } tiny::mergesort(v, scratch, is_less); - } else { + } + _ => { // More advanced sorting methods than insertion sort are faster if called in // a hot loop for small inputs, but for general-purpose code the small // binary size of insertion sort is more important. The instruction cache in diff --git a/library/core/src/slice/sort/unstable/mod.rs b/library/core/src/slice/sort/unstable/mod.rs index 2eb653c4601a..b6c2e05a06a0 100644 --- a/library/core/src/slice/sort/unstable/mod.rs +++ b/library/core/src/slice/sort/unstable/mod.rs @@ -1,11 +1,11 @@ //! This module contains the entry points for `slice::sort_unstable`. -use crate::intrinsics; use crate::mem::SizedTypeProperties; #[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))] use crate::slice::sort::shared::find_existing_run; #[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))] use crate::slice::sort::shared::smallsort::insertion_sort_shift_left; +use crate::{cfg_match, intrinsics}; pub(crate) mod heapsort; pub(crate) mod quicksort; @@ -30,10 +30,11 @@ pub fn sort bool>(v: &mut [T], is_less: &mut F) { return; } - cfg_if! { - if #[cfg(any(feature = "optimize_for_size", target_pointer_width = "16"))] { + cfg_match! { + any(feature = "optimize_for_size", target_pointer_width = "16") => { heapsort::heapsort(v, is_less); - } else { + } + _ => { // More advanced sorting methods than insertion sort are faster if called in // a hot loop for small inputs, but for general-purpose code the small // binary size of insertion sort is more important. The instruction cache in diff --git a/library/core/src/slice/sort/unstable/quicksort.rs b/library/core/src/slice/sort/unstable/quicksort.rs index 68a161187169..7e6cfb559905 100644 --- a/library/core/src/slice/sort/unstable/quicksort.rs +++ b/library/core/src/slice/sort/unstable/quicksort.rs @@ -9,7 +9,7 @@ use crate::slice::sort::shared::pivot::choose_pivot; use crate::slice::sort::shared::smallsort::UnstableSmallSortTypeImpl; #[cfg(not(feature = "optimize_for_size"))] use crate::slice::sort::unstable::heapsort; -use crate::{intrinsics, ptr}; +use crate::{cfg_match, intrinsics, ptr}; /// Sorts `v` recursively. /// @@ -142,10 +142,11 @@ const fn inst_partition bool>() -> fn(&mut [T], &T, &mut if size_of::() <= MAX_BRANCHLESS_PARTITION_SIZE { // Specialize for types that are relatively cheap to copy, where branchless optimizations // have large leverage e.g. `u64` and `String`. - cfg_if! { - if #[cfg(feature = "optimize_for_size")] { + cfg_match! { + feature = "optimize_for_size" => { partition_lomuto_branchless_simple:: - } else { + } + _ => { partition_lomuto_branchless_cyclic:: } } From 3d58aec0da0badcfdb9c185d317d6aa1c14ffb6e Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 27 Mar 2025 02:48:53 +0800 Subject: [PATCH 577/745] Report compiletest pass mode if forced This is very non-obvious if it fails in PR CI. --- src/tools/compiletest/src/lib.rs | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 3ec984edacbe..950566b2582a 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -22,6 +22,7 @@ pub mod util; use core::panic; use std::collections::HashSet; use std::ffi::OsString; +use std::fmt::Write; use std::io::{self, ErrorKind}; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; @@ -570,18 +571,22 @@ pub fn run_tests(config: Arc) { // easy to miss which tests failed, and as such fail to reproduce // the failure locally. - println!( - "Some tests failed in compiletest suite={}{} mode={} host={} target={}", - config.suite, - config - .compare_mode - .as_ref() - .map(|c| format!(" compare_mode={:?}", c)) - .unwrap_or_default(), - config.mode, - config.host, - config.target - ); + let mut msg = String::from("Some tests failed in compiletest"); + write!(msg, " suite={}", config.suite).unwrap(); + + if let Some(compare_mode) = config.compare_mode.as_ref() { + write!(msg, " compare_mode={}", compare_mode).unwrap(); + } + + if let Some(pass_mode) = config.force_pass_mode.as_ref() { + write!(msg, " pass_mode={}", pass_mode).unwrap(); + } + + write!(msg, " mode={}", config.mode).unwrap(); + write!(msg, " host={}", config.host).unwrap(); + write!(msg, " target={}", config.target).unwrap(); + + println!("{msg}"); std::process::exit(1); } From d1cd621b55a7def094f5cfecb99d2909b2d0e701 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 17 Feb 2024 04:31:46 +0100 Subject: [PATCH 578/745] Always emit native-static-libs note, even if it is empty --- compiler/rustc_codegen_ssa/src/back/link.rs | 14 +++++--------- .../ui/codegen/empty-static-libs-issue-108825.rs | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 9 deletions(-) create mode 100644 tests/ui/codegen/empty-static-libs-issue-108825.rs diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index a564e0e391fe..2e614a1f06f1 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1560,17 +1560,13 @@ fn print_native_static_libs( match out { OutFileName::Real(path) => { out.overwrite(&lib_args.join(" "), sess); - if !lib_args.is_empty() { - sess.dcx().emit_note(errors::StaticLibraryNativeArtifactsToFile { path }); - } + sess.dcx().emit_note(errors::StaticLibraryNativeArtifactsToFile { path }); } OutFileName::Stdout => { - if !lib_args.is_empty() { - sess.dcx().emit_note(errors::StaticLibraryNativeArtifacts); - // Prefix for greppability - // Note: This must not be translated as tools are allowed to depend on this exact string. - sess.dcx().note(format!("native-static-libs: {}", lib_args.join(" "))); - } + sess.dcx().emit_note(errors::StaticLibraryNativeArtifacts); + // Prefix for greppability + // Note: This must not be translated as tools are allowed to depend on this exact string. + sess.dcx().note(format!("native-static-libs: {}", lib_args.join(" "))); } } } diff --git a/tests/ui/codegen/empty-static-libs-issue-108825.rs b/tests/ui/codegen/empty-static-libs-issue-108825.rs new file mode 100644 index 000000000000..46bd6d6b2da4 --- /dev/null +++ b/tests/ui/codegen/empty-static-libs-issue-108825.rs @@ -0,0 +1,16 @@ +//! Test that linking a no_std application still outputs the +//! `native-static-libs: ` note, even though it is empty. + +//@ compile-flags: -Cpanic=abort --print=native-static-libs +//@ build-pass +//@ error-pattern: note: native-static-libs: +//@ dont-check-compiler-stderr (libcore links `/defaultlib:msvcrt` or `/defaultlib:libcmt` on MSVC) +//@ ignore-pass (the note is emitted later in the compilation pipeline, needs build) + +#![crate_type = "staticlib"] +#![no_std] + +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} From 8f735d0779a84e83a9db2cb4c93c7d0062d535a6 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Wed, 26 Mar 2025 17:32:52 -0400 Subject: [PATCH 579/745] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 307cbfda3119..a6c604d1b8a2 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 307cbfda3119f06600e43cd38283f4a746fe1f8b +Subproject commit a6c604d1b8a2f2a8ff1f3ba6092f9fda42f4b7e9 From af7359ee4fd25ac5fd92fa20c8b37405ac0d0c05 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 26 Mar 2025 12:10:47 -0700 Subject: [PATCH 580/745] Add release notes for 1.86.0 --- RELEASES.md | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 755e73a34c6b..3047a0c366a4 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,125 @@ +Version 1.86.0 (2025-04-03) +========================== + +
+ +Language +-------- +- [Stabilize the ability to upcast a trait object to one of its supertraits.](https://github.com/rust-lang/rust/pull/134367) +- [Allow safe functions to be marked with the `#[target_feature]` attribute.](https://github.com/rust-lang/rust/pull/134090) +- [The `missing_abi` lint now warns-by-default.](https://github.com/rust-lang/rust/pull/132397) +- Rust now lints about double negations, to catch cases that might have intended to be a prefix decrement operator (`--x`) as written in other languages. This was previously a clippy lint, `clippy::double_neg`, and is [now available directly in Rust as `double_negations`.](https://github.com/rust-lang/rust/pull/126604) +- [More pointers are now detected as definitely not-null based on their alignment in const eval.](https://github.com/rust-lang/rust/pull/133700) +- [Empty `repr()` attribute applied to invalid items are now correctly rejected.](https://github.com/rust-lang/rust/pull/133925) +- [Inner attributes `#![test]` and `#![rustfmt::skip]` are no longer accepted in more places than intended.](https://github.com/rust-lang/rust/pull/134276) + + + +Compiler +-------- +- [Debug-assert that raw pointers are non-null on access.](https://github.com/rust-lang/rust/pull/134424) +- [Change `-O` to mean `-C opt-level=3` instead of `-C opt-level=2` to match Cargo's defaults.](https://github.com/rust-lang/rust/pull/135439) +- [Fix emission of `overflowing_literals` under certain macro environments.](https://github.com/rust-lang/rust/pull/136393) + + + +Platform Support +---------------- +- [Replace `i686-unknown-redox` target with `i586-unknown-redox`.](https://github.com/rust-lang/rust/pull/136698) +- [Increase baseline CPU of `i686-unknown-hurd-gnu` to Pentium 4.](https://github.com/rust-lang/rust/pull/136700) +- New tier 3 targets: + - [`{aarch64-unknown,x86_64-pc}-nto-qnx710_iosock`](https://github.com/rust-lang/rust/pull/133631). + For supporting Neutrino QNX 7.1 with `io-socket` network stack. + - [`{aarch64-unknown,x86_64-pc}-nto-qnx800`](https://github.com/rust-lang/rust/pull/133631). + For supporting Neutrino QNX 8.0 (`no_std`-only). + - [`{x86_64,i686}-win7-windows-gnu`](https://github.com/rust-lang/rust/pull/134609). + Intended for backwards compatibility with Windows 7. `{x86_64,i686}-win7-windows-msvc` are the Windows MSVC counterparts that already exist as Tier 3 targets. + - [`amdgcn-amd-amdhsa`](https://github.com/rust-lang/rust/pull/134740). + - [`x86_64-pc-cygwin`](https://github.com/rust-lang/rust/pull/134999). + - [`{mips,mipsel}-mti-none-elf`](https://github.com/rust-lang/rust/pull/135074). + Initial bare-metal support. + - [`m68k-unknown-none-elf`](https://github.com/rust-lang/rust/pull/135085). + - [`armv7a-nuttx-{eabi,eabihf}`, `aarch64-unknown-nuttx`, and `thumbv7a-nuttx-{eabi,eabihf}`](https://github.com/rust-lang/rust/pull/135757). + +Refer to Rust's [platform support page][platform-support-doc] +for more information on Rust's tiered platform support. + + + +Libraries +--------- +- The type of `FromBytesWithNulError` in `CStr::from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError>` was [changed from an opaque struct to an enum](https://github.com/rust-lang/rust/pull/134143), allowing users to examine why the conversion failed. +- [Remove `RustcDecodable` and `RustcEncodable`.](https://github.com/rust-lang/rust/pull/134272) +- [Deprecate libtest's `--logfile` option.](https://github.com/rust-lang/rust/pull/134283) +- [On recent versions of Windows, `std::fs::remove_file` will now remove read-only files.](https://github.com/rust-lang/rust/pull/134679) + + + +Stabilized APIs +--------------- + +- [`{float}::next_down`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.next_down) +- [`{float}::next_up`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.next_up) +- [`<[_]>::get_disjoint_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.get_disjoint_mut) +- [`<[_]>::get_disjoint_unchecked_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.get_disjoint_unchecked_mut) +- [`slice::GetDisjointMutError`](https://doc.rust-lang.org/stable/std/slice/enum.GetDisjointMutError.html) +- [`HashMap::get_disjoint_mut`](https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.get_disjoint_mut) +- [`HashMap::get_disjoint_unchecked_mut`](https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.get_disjoint_unchecked_mut) +- [`NonZero::count_ones`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html#method.count_ones) +- [`Vec::pop_if`](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.pop_if) +- [`sync::Once::wait`](https://doc.rust-lang.org/stable/std/sync/struct.Once.html#method.wait) +- [`sync::Once::wait_force`](https://doc.rust-lang.org/stable/std/sync/struct.Once.html#method.wait_force) +- [`sync::OnceLock::wait`](https://doc.rust-lang.org/stable/std/sync/struct.OnceLock.html#method.wait) + +These APIs are now stable in const contexts: + +- [`hint::black_box`](https://doc.rust-lang.org/stable/std/hint/fn.black_box.html) +- [`io::Cursor::get_mut`](https://doc.rust-lang.org/stable/std/io/struct.Cursor.html#method.get_mut) +- [`io::Cursor::set_position`](https://doc.rust-lang.org/stable/std/io/struct.Cursor.html#method.set_position) +- [`str::is_char_boundary`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.is_char_boundary) +- [`str::split_at`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at) +- [`str::split_at_checked`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at_checked) +- [`str::split_at_mut`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at_mut) +- [`str::split_at_mut_checked`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at_mut_checked) + + + +Cargo +----- +- [When merging, replace rather than combine configuration keys that refer to a program path and its arguments.](https://github.com/rust-lang/cargo/pull/15066/) +- [Error if both `--package` and `--workspace` are passed but the requested package is missing.](https://github.com/rust-lang/cargo/pull/15071/) This was previously silently ignored, which was considered a bug since missing packages should be reported. +- [Deprecate the token argument in `cargo login` to avoid shell history leaks.](https://github.com/rust-lang/cargo/pull/15057/) +- [Simplify the implementation of `SourceID` comparisons.](https://github.com/rust-lang/cargo/pull/14980/) This may potentially change behavior if the canonicalized URL compares differently in alternative registries. + + + +Rustdoc +----- +- [Add a sans-serif font setting.](https://github.com/rust-lang/rust/pull/133636) + + + +Compatibility Notes +------------------- +- [The `wasm_c_abi` future compatibility warning is now a hard error.](https://github.com/rust-lang/rust/pull/133951) + Users of `wasm-bindgen` should upgrade to at least version 0.2.89, otherwise compilation will fail. +- [Remove long-deprecated no-op attributes `#![no_start]` and `#![crate_id]`.](https://github.com/rust-lang/rust/pull/134300) +- The future incompatibility lint `cenum_impl_drop_cast` [has been made into a hard error.](https://github.com/rust-lang/rust/pull/135964) This means it is now an error to cast a field-less enum to an integer if the enum implements `Drop`. +- [SSE2 is now required for "i686" 32-bit x86 hard-float targets; disabling it causes a warning that will become a hard error eventually.](https://github.com/rust-lang/rust/pull/137037) + + + +Internal Changes +---------------- + +These changes do not affect any public interfaces of Rust, but they represent +significant improvements to the performance or internals of rustc and related +tools. + +- [Build the rustc on AArch64 Linux with ThinLTO + PGO.](https://github.com/rust-lang/rust/pull/133807) +The ARM 64-bit compiler (AArch64) on Linux is now optimized with ThinLTO and PGO, similar to the optimizations we have already performed for the x86-64 compiler on Linux. This should make it up to 30% faster. + + Version 1.85.1 (2025-03-18) ========================== From 74b7599230996968c476a5ea9b5e44be545e673e Mon Sep 17 00:00:00 2001 From: binarycat Date: Wed, 26 Mar 2025 19:33:46 -0500 Subject: [PATCH 581/745] satisfy eslint --- src/librustdoc/html/static/js/search.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 651d12bb2e90..f3f4878b1627 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1,5 +1,5 @@ // ignore-tidy-filelength -/* global addClass, getNakedUrl, getSettingValue, getVar, nonnull, nonundef */ +/* global addClass, getNakedUrl, getSettingValue, getVar, nonundef */ /* global onEachLazy, removeClass, searchState, browserSupportsHistoryApi, exports */ "use strict"; @@ -2489,7 +2489,7 @@ class DocSearch { } } catch (err) { query = newParsedQuery(userQuery); - if (Array.isArray(err) && err.every((elem) => typeof elem == 'string')) { + if (Array.isArray(err) && err.every(elem => typeof elem === "string")) { query.error = err; } else { // rethrow the error if it isn't a string array @@ -2797,7 +2797,7 @@ class DocSearch { }, this.searchIndex[result.id]); // To be sure than it some items aren't considered as duplicate. - obj.fullPath = res[2] + "|" + obj.ty + obj.fullPath = res[2] + "|" + obj.ty; if (duplicates.has(obj.fullPath)) { continue; From 713becd7daf6aa2d8b702bacf5681f237f315762 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 26 Mar 2025 18:54:35 +0100 Subject: [PATCH 582/745] refactor: Move Apple SDK names to rustc_codegen_ssa::back::apple --- compiler/rustc_codegen_ssa/messages.ftl | 2 -- compiler/rustc_codegen_ssa/src/back/apple.rs | 18 ++++++++++++ compiler/rustc_codegen_ssa/src/back/link.rs | 30 ++------------------ compiler/rustc_codegen_ssa/src/errors.rs | 7 ----- 4 files changed, 21 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 95912b016007..a33c0aa58349 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -391,8 +391,6 @@ codegen_ssa_unknown_atomic_ordering = unknown ordering in atomic intrinsic codegen_ssa_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified -codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}` - codegen_ssa_unsupported_instruction_set = target does not support `#[instruction_set]` codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs index bfa7635a869f..24995be6f944 100644 --- a/compiler/rustc_codegen_ssa/src/back/apple.rs +++ b/compiler/rustc_codegen_ssa/src/back/apple.rs @@ -11,6 +11,24 @@ use crate::errors::AppleDeploymentTarget; #[cfg(test)] mod tests; +/// The canonical name of the desired SDK for a given target. +pub(super) fn sdk_name(target: &Target) -> &'static str { + match (&*target.os, &*target.abi) { + ("macos", "") => "MacOSX", + ("ios", "") => "iPhoneOS", + ("ios", "sim") => "iPhoneSimulator", + // Mac Catalyst uses the macOS SDK + ("ios", "macabi") => "MacOSX", + ("tvos", "") => "AppleTVOS", + ("tvos", "sim") => "AppleTVSimulator", + ("visionos", "") => "XROS", + ("visionos", "sim") => "XRSimulator", + ("watchos", "") => "WatchOS", + ("watchos", "sim") => "WatchSimulator", + (os, abi) => unreachable!("invalid os '{os}' / abi '{abi}' combination for Apple target"), + } +} + pub(super) fn macho_platform(target: &Target) -> u32 { match (&*target.os, &*target.abi) { ("macos", _) => object::macho::PLATFORM_MACOS, diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 74597f6263d4..776f381ded4f 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -3201,9 +3201,7 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo } fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> Option { - let arch = &sess.target.arch; let os = &sess.target.os; - let llvm_target = &sess.target.llvm_target; if sess.target.vendor != "apple" || !matches!(os.as_ref(), "ios" | "tvos" | "watchos" | "visionos" | "macos") || !matches!(flavor, LinkerFlavor::Darwin(..)) @@ -3215,31 +3213,9 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> return None; } - let sdk_name = match (arch.as_ref(), os.as_ref()) { - ("aarch64", "tvos") if llvm_target.ends_with("-simulator") => "appletvsimulator", - ("aarch64", "tvos") => "appletvos", - ("x86_64", "tvos") => "appletvsimulator", - ("arm", "ios") => "iphoneos", - ("aarch64", "ios") if llvm_target.contains("macabi") => "macosx", - ("aarch64", "ios") if llvm_target.ends_with("-simulator") => "iphonesimulator", - ("aarch64", "ios") => "iphoneos", - ("x86", "ios") => "iphonesimulator", - ("x86_64", "ios") if llvm_target.contains("macabi") => "macosx", - ("x86_64", "ios") => "iphonesimulator", - ("x86_64", "watchos") => "watchsimulator", - ("arm64_32", "watchos") => "watchos", - ("aarch64", "watchos") if llvm_target.ends_with("-simulator") => "watchsimulator", - ("aarch64", "watchos") => "watchos", - ("aarch64", "visionos") if llvm_target.ends_with("-simulator") => "xrsimulator", - ("aarch64", "visionos") => "xros", - ("arm", "watchos") => "watchos", - (_, "macos") => "macosx", - _ => { - sess.dcx().emit_err(errors::UnsupportedArch { arch, os }); - return None; - } - }; - let sdk_root = match get_apple_sdk_root(sdk_name) { + let sdk_name = apple::sdk_name(&sess.target).to_lowercase(); + + let sdk_root = match get_apple_sdk_root(&sdk_name) { Ok(s) => s, Err(e) => { sess.dcx().emit_err(e); diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 0b7cad0c2fd8..9c4c205dfe55 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -738,13 +738,6 @@ pub enum ExtractBundledLibsError<'a> { ExtractSection { rlib: &'a Path, error: Box }, } -#[derive(Diagnostic)] -#[diag(codegen_ssa_unsupported_arch)] -pub(crate) struct UnsupportedArch<'a> { - pub arch: &'a str, - pub os: &'a str, -} - #[derive(Diagnostic)] pub(crate) enum AppleDeploymentTarget { #[diag(codegen_ssa_apple_deployment_target_invalid)] From dffb0dbc3e2f28a82085025aec4aea6a6a28b611 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 27 Mar 2025 03:10:29 +0100 Subject: [PATCH 583/745] Document how the SDK is found if SDKROOT is not set I've intentionally used slightly vague language ("roughly"), as we don't want to guarantee the exact invocation of `xcrun`, just hint that it's close to that. --- src/doc/rustc/src/platform-support/apple-darwin.md | 3 ++- src/doc/rustc/src/platform-support/apple-ios-macabi.md | 3 ++- src/doc/rustc/src/platform-support/apple-ios.md | 3 ++- src/doc/rustc/src/platform-support/apple-tvos.md | 3 ++- src/doc/rustc/src/platform-support/apple-visionos.md | 3 ++- src/doc/rustc/src/platform-support/apple-watchos.md | 3 ++- 6 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/doc/rustc/src/platform-support/apple-darwin.md b/src/doc/rustc/src/platform-support/apple-darwin.md index dba2c4b2aaf0..22c54d04b1eb 100644 --- a/src/doc/rustc/src/platform-support/apple-darwin.md +++ b/src/doc/rustc/src/platform-support/apple-darwin.md @@ -70,4 +70,5 @@ the `-mmacosx-version-min=...`, `-miphoneos-version-min=...` or similar flags to disambiguate. The path to the SDK can be passed to `rustc` using the common `SDKROOT` -environment variable. +environment variable, or will be inferred when compiling on host macOS using +roughly the same logic as `xcrun --sdk macosx --show-sdk-path`. diff --git a/src/doc/rustc/src/platform-support/apple-ios-macabi.md b/src/doc/rustc/src/platform-support/apple-ios-macabi.md index a54656190d1f..79966d908d89 100644 --- a/src/doc/rustc/src/platform-support/apple-ios-macabi.md +++ b/src/doc/rustc/src/platform-support/apple-ios-macabi.md @@ -20,7 +20,8 @@ These targets are cross-compiled, and require the corresponding macOS SDK iOS-specific headers, as provided by Xcode 11 or higher. The path to the SDK can be passed to `rustc` using the common `SDKROOT` -environment variable. +environment variable, or will be inferred when compiling on host macOS using +roughly the same logic as `xcrun --sdk macosx --show-sdk-path`. ### OS version diff --git a/src/doc/rustc/src/platform-support/apple-ios.md b/src/doc/rustc/src/platform-support/apple-ios.md index cfb458fdb737..7f5dc361c49d 100644 --- a/src/doc/rustc/src/platform-support/apple-ios.md +++ b/src/doc/rustc/src/platform-support/apple-ios.md @@ -26,7 +26,8 @@ These targets are cross-compiled, and require the corresponding iOS SDK ARM64 targets, Xcode 12 or higher is required. The path to the SDK can be passed to `rustc` using the common `SDKROOT` -environment variable. +environment variable, or will be inferred when compiling on host macOS using +roughly the same logic as `xcrun --sdk iphoneos --show-sdk-path`. ### OS version diff --git a/src/doc/rustc/src/platform-support/apple-tvos.md b/src/doc/rustc/src/platform-support/apple-tvos.md index 166bb1b6db29..fc46db20074f 100644 --- a/src/doc/rustc/src/platform-support/apple-tvos.md +++ b/src/doc/rustc/src/platform-support/apple-tvos.md @@ -20,7 +20,8 @@ These targets are cross-compiled, and require the corresponding tvOS SDK ARM64 targets, Xcode 12 or higher is required. The path to the SDK can be passed to `rustc` using the common `SDKROOT` -environment variable. +environment variable, or will be inferred when compiling on host macOS using +roughly the same logic as `xcrun --sdk appletvos --show-sdk-path`. ### OS version diff --git a/src/doc/rustc/src/platform-support/apple-visionos.md b/src/doc/rustc/src/platform-support/apple-visionos.md index a7bbae168a4f..7cf9549227d9 100644 --- a/src/doc/rustc/src/platform-support/apple-visionos.md +++ b/src/doc/rustc/src/platform-support/apple-visionos.md @@ -18,7 +18,8 @@ These targets are cross-compiled, and require the corresponding visionOS SDK (`XROS.sdk` or `XRSimulator.sdk`), as provided by Xcode 15 or newer. The path to the SDK can be passed to `rustc` using the common `SDKROOT` -environment variable. +environment variable, or will be inferred when compiling on host macOS using +roughly the same logic as `xcrun --sdk xros --show-sdk-path`. ### OS version diff --git a/src/doc/rustc/src/platform-support/apple-watchos.md b/src/doc/rustc/src/platform-support/apple-watchos.md index 0bf8cdf36142..7b12d9ebfd4b 100644 --- a/src/doc/rustc/src/platform-support/apple-watchos.md +++ b/src/doc/rustc/src/platform-support/apple-watchos.md @@ -24,7 +24,8 @@ These targets are cross-compiled, and require the corresponding watchOS SDK ARM64 targets, Xcode 12 or higher is required. The path to the SDK can be passed to `rustc` using the common `SDKROOT` -environment variable. +environment variable, or will be inferred when compiling on host macOS using +roughly the same logic as `xcrun --sdk watchos --show-sdk-path`. ### OS version From bd1ef0fad2e8172549a07fbf17dc1f9c4ceea078 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 27 Mar 2025 03:10:58 +0100 Subject: [PATCH 584/745] Invoke xcrun inside sess.time It can be a fairly expensive operation when the output is not cached, so it's nice to get some visibility into the runtime cost. --- compiler/rustc_codegen_ssa/src/back/link.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 776f381ded4f..eb6aebf23203 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -3215,7 +3215,7 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> let sdk_name = apple::sdk_name(&sess.target).to_lowercase(); - let sdk_root = match get_apple_sdk_root(&sdk_name) { + let sdk_root = match sess.time("get_apple_sdk_root", || get_apple_sdk_root(&sdk_name)) { Ok(s) => s, Err(e) => { sess.dcx().emit_err(e); From 89348e51e383a6300206e3356143fce812838921 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 27 Mar 2025 03:15:58 +0100 Subject: [PATCH 585/745] Emit better error messages when invoking xcrun Also allow the SDK path to be non-UTF-8. --- compiler/rustc_codegen_ssa/messages.ftl | 19 ++- compiler/rustc_codegen_ssa/src/back/apple.rs | 136 +++++++++++++++++- .../rustc_codegen_ssa/src/back/apple/tests.rs | 68 ++++++++- compiler/rustc_codegen_ssa/src/back/link.rs | 59 +++----- compiler/rustc_codegen_ssa/src/errors.rs | 29 +++- compiler/rustc_codegen_ssa/src/lib.rs | 1 + 6 files changed, 263 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index a33c0aa58349..954a60148093 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -10,8 +10,6 @@ codegen_ssa_apple_deployment_target_invalid = codegen_ssa_apple_deployment_target_too_low = deployment target in {$env_var} was set to {$version}, but the minimum supported by `rustc` is {$os_min} -codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {$error} - codegen_ssa_archive_build_failure = failed to build archive at `{$path}`: {$error} codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering @@ -400,3 +398,20 @@ codegen_ssa_use_cargo_directive = use the `cargo:rustc-link-lib` directive to sp codegen_ssa_version_script_write_failure = failed to write version script: {$error} codegen_ssa_visual_studio_not_installed = you may need to install Visual Studio build tools with the "C++ build tools" workload + +codegen_ssa_xcrun_command_line_tools_insufficient = + when compiling for iOS, tvOS, visionOS or watchOS, you need a full installation of Xcode + +codegen_ssa_xcrun_failed_invoking = invoking `{$command_formatted}` to find {$sdk_name}.sdk failed: {$error} + +codegen_ssa_xcrun_found_developer_dir = found active developer directory at "{$developer_dir}" + +# `xcrun` already outputs a message about missing Xcode installation, so we only augment it with details about env vars. +codegen_ssa_xcrun_no_developer_dir = + pass the path of an Xcode installation via the DEVELOPER_DIR environment variable, or an SDK with the SDKROOT environment variable + +codegen_ssa_xcrun_sdk_path_warning = output of `xcrun` while finding {$sdk_name}.sdk + .note = {$stderr} + +codegen_ssa_xcrun_unsuccessful = failed running `{$command_formatted}` to find {$sdk_name}.sdk + .note = {$stdout}{$stderr} diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs index 24995be6f944..2c8b0ec418dd 100644 --- a/compiler/rustc_codegen_ssa/src/back/apple.rs +++ b/compiler/rustc_codegen_ssa/src/back/apple.rs @@ -1,12 +1,18 @@ use std::env; +use std::ffi::OsString; use std::fmt::{Display, from_fn}; use std::num::ParseIntError; +use std::path::PathBuf; +use std::process::Command; +use itertools::Itertools; use rustc_middle::middle::exported_symbols::SymbolExportKind; use rustc_session::Session; use rustc_target::spec::Target; +use tracing::debug; -use crate::errors::AppleDeploymentTarget; +use crate::errors::{AppleDeploymentTarget, XcrunError, XcrunSdkPathWarning}; +use crate::fluent_generated as fluent; #[cfg(test)] mod tests; @@ -271,3 +277,131 @@ pub(super) fn add_version_to_llvm_target( format!("{arch}-{vendor}-{os}{major}.{minor}.{patch}") } } + +pub(super) fn get_sdk_root(sess: &Session) -> Option { + let sdk_name = sdk_name(&sess.target); + + match xcrun_show_sdk_path(sdk_name, sess.verbose_internals()) { + Ok((path, stderr)) => { + // Emit extra stderr, such as if `-verbose` was passed, or if `xcrun` emitted a warning. + if !stderr.is_empty() { + sess.dcx().emit_warn(XcrunSdkPathWarning { sdk_name, stderr }); + } + Some(path) + } + Err(err) => { + let mut diag = sess.dcx().create_err(err); + + // Recognize common error cases, and give more Rust-specific error messages for those. + if let Some(developer_dir) = xcode_select_developer_dir() { + diag.arg("developer_dir", &developer_dir); + diag.note(fluent::codegen_ssa_xcrun_found_developer_dir); + if developer_dir.as_os_str().to_string_lossy().contains("CommandLineTools") { + if sdk_name != "MacOSX" { + diag.help(fluent::codegen_ssa_xcrun_command_line_tools_insufficient); + } + } + } else { + diag.help(fluent::codegen_ssa_xcrun_no_developer_dir); + } + + diag.emit(); + None + } + } +} + +/// Invoke `xcrun --sdk $sdk_name --show-sdk-path` to get the SDK path. +/// +/// The exact logic that `xcrun` uses is unspecified (see `man xcrun` for a few details), and may +/// change between macOS and Xcode versions, but it roughly boils down to finding the active +/// developer directory, and then invoking `xcodebuild -sdk $sdk_name -version` to get the SDK +/// details. +/// +/// Finding the developer directory is roughly done by looking at, in order: +/// - The `DEVELOPER_DIR` environment variable. +/// - The `/var/db/xcode_select_link` symlink (set by `xcode-select --switch`). +/// - `/Applications/Xcode.app` (hardcoded fallback path). +/// - `/Library/Developer/CommandLineTools` (hardcoded fallback path). +/// +/// Note that `xcrun` caches its result, but with a cold cache this whole operation can be quite +/// slow, especially so the first time it's run after a reboot. +fn xcrun_show_sdk_path( + sdk_name: &'static str, + verbose: bool, +) -> Result<(PathBuf, String), XcrunError> { + let mut cmd = Command::new("xcrun"); + if verbose { + cmd.arg("--verbose"); + } + // The `--sdk` parameter is the same as in xcodebuild, namely either an absolute path to an SDK, + // or the (lowercase) canonical name of an SDK. + cmd.arg("--sdk"); + cmd.arg(&sdk_name.to_lowercase()); + cmd.arg("--show-sdk-path"); + + // We do not stream stdout/stderr lines directly to the user, since whether they are warnings or + // errors depends on the status code at the end. + let output = cmd.output().map_err(|error| XcrunError::FailedInvoking { + sdk_name, + command_formatted: format!("{cmd:?}"), + error, + })?; + + // It is fine to do lossy conversion here, non-UTF-8 paths are quite rare on macOS nowadays + // (only possible with the HFS+ file system), and we only use it for error messages. + let stderr = String::from_utf8_lossy_owned(output.stderr); + if !stderr.is_empty() { + debug!(stderr, "original xcrun stderr"); + } + + // Some versions of `xcodebuild` output beefy errors when invoked via `xcrun`, + // but these are usually red herrings. + let stderr = stderr + .lines() + .filter(|line| { + !line.contains("Writing error result bundle") + && !line.contains("Requested but did not find extension point with identifier") + }) + .join("\n"); + + if output.status.success() { + Ok((stdout_to_path(output.stdout), stderr)) + } else { + // Output both stdout and stderr, since shims of `xcrun` (such as the one provided by + // nixpkgs), do not always use stderr for errors. + let stdout = String::from_utf8_lossy_owned(output.stdout).trim().to_string(); + Err(XcrunError::Unsuccessful { + sdk_name, + command_formatted: format!("{cmd:?}"), + stdout, + stderr, + }) + } +} + +/// Invoke `xcode-select --print-path`, and return the current developer directory. +/// +/// NOTE: We don't do any error handling here, this is only used as a canary in diagnostics (`xcrun` +/// will have already emitted the relevant error information). +fn xcode_select_developer_dir() -> Option { + let mut cmd = Command::new("xcode-select"); + cmd.arg("--print-path"); + let output = cmd.output().ok()?; + if !output.status.success() { + return None; + } + Some(stdout_to_path(output.stdout)) +} + +fn stdout_to_path(mut stdout: Vec) -> PathBuf { + // Remove trailing newline. + if let Some(b'\n') = stdout.last() { + let _ = stdout.pop().unwrap(); + } + #[cfg(unix)] + let path = ::from_vec(stdout); + #[cfg(not(unix))] // Unimportant, this is only used on macOS + let path = OsString::from(String::from_utf8(stdout).unwrap()); + PathBuf::from(path) +} diff --git a/compiler/rustc_codegen_ssa/src/back/apple/tests.rs b/compiler/rustc_codegen_ssa/src/back/apple/tests.rs index 7ccda5a8190c..8df740a4bcf7 100644 --- a/compiler/rustc_codegen_ssa/src/back/apple/tests.rs +++ b/compiler/rustc_codegen_ssa/src/back/apple/tests.rs @@ -1,4 +1,4 @@ -use super::{add_version_to_llvm_target, parse_version}; +use super::*; #[test] fn test_add_version_to_llvm_target() { @@ -19,3 +19,69 @@ fn test_parse_version() { assert_eq!(parse_version("10.12.6"), Ok((10, 12, 6))); assert_eq!(parse_version("9999.99.99"), Ok((9999, 99, 99))); } + +#[test] +#[cfg_attr(not(target_os = "macos"), ignore = "xcode-select is only available on macOS")] +fn lookup_developer_dir() { + let _developer_dir = xcode_select_developer_dir().unwrap(); +} + +#[test] +#[cfg_attr(not(target_os = "macos"), ignore = "xcrun is only available on macOS")] +fn lookup_sdk() { + let (sdk_path, stderr) = xcrun_show_sdk_path("MacOSX", false).unwrap(); + // Check that the found SDK is valid. + assert!(sdk_path.join("SDKSettings.plist").exists()); + assert_eq!(stderr, ""); + + // Test that the SDK root is a subdir of the developer directory. + if let Some(developer_dir) = xcode_select_developer_dir() { + // Only run this test if SDKROOT is not set (otherwise xcrun may look up via. that). + if std::env::var_os("SDKROOT").is_some() { + assert!(sdk_path.starts_with(&developer_dir)); + } + } +} + +#[test] +#[cfg_attr(not(target_os = "macos"), ignore = "xcrun is only available on macOS")] +fn lookup_sdk_verbose() { + let (_, stderr) = xcrun_show_sdk_path("MacOSX", true).unwrap(); + // Newer xcrun versions should emit something like this: + // + // xcrun: note: looking up SDK with 'xcodebuild -sdk macosx -version Path' + // xcrun: note: xcrun_db = '/var/.../xcrun_db' + // xcrun: note: lookup resolved to: '...' + // xcrun: note: database key is: ... + // + // Or if the value is already cached, something like this: + // + // xcrun: note: database key is: ... + // xcrun: note: lookup resolved in '/var/.../xcrun_db' : '...' + assert!( + stderr.contains("xcrun: note: lookup resolved"), + "stderr should contain lookup note: {stderr}", + ); +} + +#[test] +#[cfg_attr(not(target_os = "macos"), ignore = "xcrun is only available on macOS")] +fn try_lookup_invalid_sdk() { + // As a proxy for testing all the different ways that `xcrun` can fail, + // test the case where an SDK was not found. + let err = xcrun_show_sdk_path("invalid", false).unwrap_err(); + let XcrunError::Unsuccessful { stderr, .. } = err else { + panic!("unexpected error kind: {err:?}"); + }; + // Either one of (depending on if using Command Line Tools or full Xcode): + // xcrun: error: SDK "invalid" cannot be located + // xcodebuild: error: SDK "invalid" cannot be located. + assert!( + stderr.contains(r#"error: SDK "invalid" cannot be located"#), + "stderr should contain xcodebuild note: {stderr}", + ); + assert!( + stderr.contains("xcrun: error: unable to lookup item 'Path' in SDK 'invalid'"), + "stderr should contain xcrun note: {stderr}", + ); +} diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index eb6aebf23203..e66d549aabc4 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -3213,15 +3213,7 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> return None; } - let sdk_name = apple::sdk_name(&sess.target).to_lowercase(); - - let sdk_root = match sess.time("get_apple_sdk_root", || get_apple_sdk_root(&sdk_name)) { - Ok(s) => s, - Err(e) => { - sess.dcx().emit_err(e); - return None; - } - }; + let sdk_root = sess.time("get_apple_sdk_root", || get_apple_sdk_root(sess))?; match flavor { LinkerFlavor::Darwin(Cc::Yes, _) => { @@ -3231,28 +3223,32 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> // This is admittedly a bit strange, as on most targets // `-isysroot` only applies to include header files, but on Apple // targets this also applies to libraries and frameworks. - cmd.cc_args(&["-isysroot", &sdk_root]); + cmd.cc_arg("-isysroot"); + cmd.cc_arg(&sdk_root); } LinkerFlavor::Darwin(Cc::No, _) => { - cmd.link_args(&["-syslibroot", &sdk_root]); + cmd.link_arg("-syslibroot"); + cmd.link_arg(&sdk_root); } _ => unreachable!(), } - Some(sdk_root.into()) + Some(sdk_root) } -fn get_apple_sdk_root(sdk_name: &str) -> Result> { - // Following what clang does - // (https://github.com/llvm/llvm-project/blob/ - // 296a80102a9b72c3eda80558fb78a3ed8849b341/clang/lib/Driver/ToolChains/Darwin.cpp#L1661-L1678) - // to allow the SDK path to be set. (For clang, xcrun sets - // SDKROOT; for rustc, the user or build system can set it, or we - // can fall back to checking for xcrun on PATH.) +fn get_apple_sdk_root(sess: &Session) -> Option { if let Ok(sdkroot) = env::var("SDKROOT") { - let p = Path::new(&sdkroot); - match sdk_name { - // Ignore `SDKROOT` if it's clearly set for the wrong platform. + let p = PathBuf::from(&sdkroot); + + // Ignore invalid SDKs, similar to what clang does: + // https://github.com/llvm/llvm-project/blob/llvmorg-19.1.6/clang/lib/Driver/ToolChains/Darwin.cpp#L2212-L2229 + // + // NOTE: Things are complicated here by the fact that `rustc` can be run by Cargo to compile + // build scripts and proc-macros for the host, and thus we need to ignore SDKROOT if it's + // clearly set for the wrong platform. + // + // FIXME(madsmtm): Make this more robust (maybe read `SDKSettings.json` like Clang does?). + match &*apple::sdk_name(&sess.target).to_lowercase() { "appletvos" if sdkroot.contains("TVSimulator.platform") || sdkroot.contains("MacOSX.platform") => {} @@ -3279,26 +3275,11 @@ fn get_apple_sdk_root(sdk_name: &str) -> Result {} // Ignore `SDKROOT` if it's not a valid path. _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {} - _ => return Ok(sdkroot), + _ => return Some(p), } } - let res = - Command::new("xcrun").arg("--show-sdk-path").arg("-sdk").arg(sdk_name).output().and_then( - |output| { - if output.status.success() { - Ok(String::from_utf8(output.stdout).unwrap()) - } else { - let error = String::from_utf8(output.stderr); - let error = format!("process exit with error: {}", error.unwrap()); - Err(io::Error::new(io::ErrorKind::Other, &error[..])) - } - }, - ); - match res { - Ok(output) => Ok(output.trim().to_string()), - Err(error) => Err(errors::AppleSdkRootError::SdkPath { sdk_name, error }), - } + apple::get_sdk_root(sess) } /// When using the linker flavors opting in to `lld`, add the necessary paths and arguments to diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 9c4c205dfe55..f52d29baf9dc 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -746,12 +746,6 @@ pub(crate) enum AppleDeploymentTarget { TooLow { env_var: &'static str, version: String, os_min: String }, } -#[derive(Diagnostic)] -pub(crate) enum AppleSdkRootError<'a> { - #[diag(codegen_ssa_apple_sdk_error_sdk_path)] - SdkPath { sdk_name: &'a str, error: Error }, -} - #[derive(Diagnostic)] #[diag(codegen_ssa_read_file)] pub(crate) struct ReadFileError { @@ -1327,3 +1321,26 @@ pub(crate) struct MixedExportNameAndNoMangle { #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")] pub removal_span: Span, } + +#[derive(Diagnostic, Debug)] +pub(crate) enum XcrunError { + #[diag(codegen_ssa_xcrun_failed_invoking)] + FailedInvoking { sdk_name: &'static str, command_formatted: String, error: std::io::Error }, + + #[diag(codegen_ssa_xcrun_unsuccessful)] + #[note] + Unsuccessful { + sdk_name: &'static str, + command_formatted: String, + stdout: String, + stderr: String, + }, +} + +#[derive(Diagnostic, Debug)] +#[diag(codegen_ssa_xcrun_sdk_path_warning)] +#[note] +pub(crate) struct XcrunSdkPathWarning { + pub sdk_name: &'static str, + pub stderr: String, +} diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 93c34a2f5764..d26d6edf3149 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -13,6 +13,7 @@ #![feature(let_chains)] #![feature(negative_impls)] #![feature(rustdoc_internals)] +#![feature(string_from_utf8_lossy_owned)] #![feature(trait_alias)] #![feature(try_blocks)] // tidy-alphabetical-end From 3237b5092bb2dd6bc72ccf38fd42a226eed09e77 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 27 Mar 2025 08:46:35 +0100 Subject: [PATCH 586/745] Add needs-threads to test. --- tests/ui/thread-local/spawn-hook-atexit.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ui/thread-local/spawn-hook-atexit.rs b/tests/ui/thread-local/spawn-hook-atexit.rs index cc517e8fa4c6..41fcbab1a812 100644 --- a/tests/ui/thread-local/spawn-hook-atexit.rs +++ b/tests/ui/thread-local/spawn-hook-atexit.rs @@ -1,4 +1,5 @@ // Regression test for https://github.com/rust-lang/rust/issues/138696 +//@ needs-threads //@ run-pass #![feature(rustc_private)] From 5a6ed74a6cae1b8bd994a9b2738896b425726c52 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 27 Mar 2025 19:10:14 +1100 Subject: [PATCH 587/745] Remove `kw::Empty` uses from `src/librustdoc`. Much like the ones in the previous commit. --- src/librustdoc/clean/mod.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index de6dc088176f..f72acaae02f2 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1943,14 +1943,11 @@ fn clean_trait_object_lifetime_bound<'tcx>( // latter contrary to `clean_middle_region`. match *region { ty::ReStatic => Some(Lifetime::statik()), - ty::ReEarlyParam(region) if region.name != kw::Empty => Some(Lifetime(region.name)), - ty::ReBound(_, ty::BoundRegion { kind: ty::BoundRegionKind::Named(_, name), .. }) - if name != kw::Empty => - { + ty::ReEarlyParam(region) => Some(Lifetime(region.name)), + ty::ReBound(_, ty::BoundRegion { kind: ty::BoundRegionKind::Named(_, name), .. }) => { Some(Lifetime(name)) } - ty::ReEarlyParam(_) - | ty::ReBound(..) + ty::ReBound(..) | ty::ReLateParam(_) | ty::ReVar(_) | ty::RePlaceholder(_) From 215c2c2f494e18791f9321f072a7c05c2f17238e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 27 Mar 2025 11:05:49 +0100 Subject: [PATCH 588/745] Remove some asserts from the `download_ci_llvm` bootstrap test --- src/bootstrap/src/core/config/tests.rs | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index 068e237c2cdc..6d63709f4740 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -24,31 +24,11 @@ pub(crate) fn parse(config: &str) -> Config { #[test] fn download_ci_llvm() { - let config = parse(""); - let is_available = llvm::is_ci_llvm_available_for_target(&config, config.llvm_assertions); - if is_available { - assert!(config.llvm_from_ci); - } - - let config = Config::parse_inner( - Flags::parse(&[ - "check".to_string(), - "--config=/does/not/exist".to_string(), - "--ci".to_string(), - "false".to_string(), - ]), - |&_| toml::from_str("llvm.download-ci-llvm = true"), - ); - let is_available = llvm::is_ci_llvm_available_for_target(&config, config.llvm_assertions); - if is_available { - assert!(config.llvm_from_ci); - } - let config = parse("llvm.download-ci-llvm = false"); assert!(!config.llvm_from_ci); let if_unchanged_config = parse("llvm.download-ci-llvm = \"if-unchanged\""); - if if_unchanged_config.llvm_from_ci { + if if_unchanged_config.llvm_from_ci && if_unchanged_config.is_running_on_ci { let has_changes = if_unchanged_config .last_modified_commit(LLVM_INVALIDATION_PATHS, "download-ci-llvm", true) .is_none(); From 1f1c630a58297d49e92b79cf072559924b4f1123 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 5 Mar 2025 23:33:54 +0100 Subject: [PATCH 589/745] Greatly simplify doctest parsing and information extraction --- src/librustdoc/doctest/make.rs | 471 ++++++++++----------------------- 1 file changed, 142 insertions(+), 329 deletions(-) diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index 9935074877bc..cb14608b35ae 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -5,11 +5,10 @@ use std::fmt::{self, Write as _}; use std::io; use std::sync::Arc; -use rustc_ast as ast; +use rustc_ast::{self as ast, HasAttrs}; +use rustc_errors::ColorConfig; use rustc_errors::emitter::stderr_destination; -use rustc_errors::{ColorConfig, FatalError}; use rustc_parse::new_parser_from_source_str; -use rustc_parse::parser::attr::InnerAttrPolicy; use rustc_session::parse::ParseSess; use rustc_span::FileName; use rustc_span::edition::Edition; @@ -21,6 +20,19 @@ use super::GlobalTestOptions; use crate::display::Joined as _; use crate::html::markdown::LangString; +#[derive(Default)] +struct ParseSourceInfo { + has_main_fn: bool, + found_extern_crate: bool, + supports_color: bool, + has_global_allocator: bool, + has_macro_def: bool, + everything_else: String, + crates: String, + crate_attrs: String, + maybe_crate_attrs: String, +} + /// This struct contains information about the doctest itself which is then used to generate /// doctest source code appropriately. pub(crate) struct DocTestBuilder { @@ -53,8 +65,23 @@ impl DocTestBuilder { !lang_str.compile_fail && !lang_str.test_harness && !lang_str.standalone_crate }); - let Some(SourceInfo { crate_attrs, maybe_crate_attrs, crates, everything_else }) = - partition_source(source, edition) + let result = rustc_driver::catch_fatal_errors(|| { + rustc_span::create_session_if_not_set_then(edition, |_| { + parse_source(source, &crate_name) + }) + }); + + let Ok(Ok(ParseSourceInfo { + has_main_fn, + found_extern_crate, + supports_color, + has_global_allocator, + has_macro_def, + everything_else, + crates, + crate_attrs, + maybe_crate_attrs, + })) = result else { return Self::invalid( String::new(), @@ -65,35 +92,13 @@ impl DocTestBuilder { ); }; - // Uses librustc_ast to parse the doctest and find if there's a main fn and the extern - // crate already is included. - let Ok(( - ParseSourceInfo { - has_main_fn, - found_extern_crate, - supports_color, - has_global_allocator, - has_macro_def, - .. - }, - failed_ast, - )) = check_for_main_and_extern_crate( - crate_name, - source, - &everything_else, - &crates, - edition, - can_merge_doctests, - ) - else { - // If the parser panicked due to a fatal error, pass the test code through unchanged. - // The error will be reported during compilation. - return Self::invalid(crate_attrs, maybe_crate_attrs, crates, everything_else, test_id); - }; + debug!("crate_attrs:\n{crate_attrs}{maybe_crate_attrs}"); + debug!("crates:\n{crates}"); + debug!("after:\n{everything_else}"); + // If the AST returned an error, we don't want this doctest to be merged with the // others. Same if it contains `#[feature]` or `#[no_std]`. let can_be_merged = can_merge_doctests - && !failed_ast && !has_global_allocator && crate_attrs.is_empty() // If this is a merged doctest and a defined macro uses `$crate`, then the path will @@ -146,6 +151,7 @@ impl DocTestBuilder { if self.failed_ast { // If the AST failed to compile, no need to go generate a complete doctest, the error // will be better this way. + debug!("failed AST:\n{test_code}"); return (test_code.to_string(), 0); } let mut line_offset = 0; @@ -255,13 +261,6 @@ impl DocTestBuilder { } } -#[derive(PartialEq, Eq, Debug)] -enum ParsingResult { - Failed, - AstError, - Ok, -} - fn cancel_error_count(psess: &ParseSess) { // Reset errors so that they won't be reported as compiler bugs when dropping the // dcx. Any errors in the tests will be reported when the test file is compiled, @@ -270,17 +269,20 @@ fn cancel_error_count(psess: &ParseSess) { psess.dcx().reset_err_count(); } -fn parse_source( - source: String, - info: &mut ParseSourceInfo, - crate_name: &Option<&str>, -) -> ParsingResult { +const DOCTEST_CODE_WRAPPER: &str = "fn f(){"; + +fn parse_source(source: &str, crate_name: &Option<&str>) -> Result { use rustc_errors::DiagCtxt; use rustc_errors::emitter::{Emitter, HumanEmitter}; - use rustc_parse::parser::ForceCollect; + // use rustc_parse::parser::ForceCollect; use rustc_span::source_map::FilePathMapping; - let filename = FileName::anon_source_code(&source); + let mut info = + ParseSourceInfo { found_extern_crate: crate_name.is_none(), ..Default::default() }; + + let wrapped_source = format!("{DOCTEST_CODE_WRAPPER}{source}\n}}"); + + let filename = FileName::anon_source_code(&wrapped_source); // Any errors in parsing should also appear when the doctest is compiled for real, so just // send all the errors that librustc_ast emits directly into a `Sink` instead of stderr. @@ -299,15 +301,32 @@ fn parse_source( let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings(); let psess = ParseSess::with_dcx(dcx, sm); - let mut parser = match new_parser_from_source_str(&psess, filename, source) { + let mut parser = match new_parser_from_source_str(&psess, filename, wrapped_source) { Ok(p) => p, Err(errs) => { errs.into_iter().for_each(|err| err.cancel()); cancel_error_count(&psess); - return ParsingResult::Failed; + return Err(()); } }; - let mut parsing_result = ParsingResult::Ok; + + fn push_to_s( + s: &mut String, + source: &str, + span: rustc_span::Span, + prev_span_hi: &mut Option, + ) { + let extra_len = DOCTEST_CODE_WRAPPER.len(); + // We need to shift by 1 because we added `{` at the beginning of the source.we provided + // to the parser. + let lo = prev_span_hi.unwrap_or(span.lo().0 as usize - extra_len); + let mut hi = span.hi().0 as usize - extra_len; + if hi > source.len() { + hi = source.len(); + } + s.push_str(&source[lo..hi]); + *prev_span_hi = Some(hi); + } // Recurse through functions body. It is necessary because the doctest source code is // wrapped in a function to limit the number of AST errors. If we don't recurse into @@ -325,6 +344,8 @@ fn parse_source( } match item.kind { ast::ItemKind::Fn(ref fn_item) if !info.has_main_fn => { + // We only push if it's the top item because otherwise, we would duplicate + // its content since the top-level item was already added. if item.ident.name == sym::main && is_top_level { info.has_main_fn = true; } @@ -334,7 +355,6 @@ fn parse_source( ast::StmtKind::Item(ref item) => { check_item(item, info, crate_name, false) } - ast::StmtKind::MacCall(..) => info.found_macro = true, _ => {} } } @@ -350,295 +370,88 @@ fn parse_source( }; } } - ast::ItemKind::MacCall(..) => info.found_macro = true, - ast::ItemKind::MacroDef(..) => info.has_macro_def = true, + ast::ItemKind::MacroDef(..) => { + info.has_macro_def = true; + } _ => {} } } - loop { - match parser.parse_item(ForceCollect::No) { - Ok(Some(item)) => { - check_item(&item, info, crate_name, true); + let mut prev_span_hi = None; + let not_crate_attrs = [sym::forbid, sym::allow, sym::warn, sym::deny]; + let parsed = parser.parse_item(rustc_parse::parser::ForceCollect::No); - if info.has_main_fn && info.found_extern_crate { - break; + debug!("+++++> {parsed:#?}"); + + let result = match parsed { + Ok(Some(ref item)) + if let ast::ItemKind::Fn(ref fn_item) = item.kind + && let Some(ref body) = fn_item.body => + { + for attr in &item.attrs { + let attr_name = attr.name_or_empty(); + + if attr.style == ast::AttrStyle::Outer || not_crate_attrs.contains(&attr_name) { + // There is one exception to these attributes: + // `#![allow(internal_features)]`. If this attribute is used, we need to + // consider it only as a crate-level attribute. + if attr_name == sym::allow + && let Some(list) = attr.meta_item_list() + && list.iter().any(|sub_attr| { + sub_attr.name_or_empty().as_str() == "internal_features" + }) + { + push_to_s(&mut info.crate_attrs, source, attr.span, &mut prev_span_hi); + } else { + push_to_s( + &mut info.maybe_crate_attrs, + source, + attr.span, + &mut prev_span_hi, + ); + } + } else { + push_to_s(&mut info.crate_attrs, source, attr.span, &mut prev_span_hi); } } - Ok(None) => break, - Err(e) => { - parsing_result = ParsingResult::AstError; - e.cancel(); - break; + for stmt in &body.stmts { + match stmt.kind { + ast::StmtKind::Item(ref item) => check_item(&item, &mut info, crate_name, true), + ast::StmtKind::Expr(ref expr) if matches!(expr.kind, ast::ExprKind::Err(_)) => { + cancel_error_count(&psess); + return Err(()); + } + _ => {} + } + + // Weirdly enough, the `Stmt` span doesn't include its attributes, so we need to + // tweak the span to include the attributes as well. + let mut span = stmt.span; + if let Some(attr) = stmt.kind.attrs().first() { + span = span.with_lo(attr.span.lo()); + } + if info.everything_else.is_empty() + && (!info.maybe_crate_attrs.is_empty() || !info.crate_attrs.is_empty()) + { + // We add potential backlines into attributes if there are some. + push_to_s( + &mut info.maybe_crate_attrs, + source, + span.shrink_to_lo(), + &mut prev_span_hi, + ); + } + push_to_s(&mut info.everything_else, source, span, &mut prev_span_hi); } + Ok(info) } - - // The supplied item is only used for diagnostics, - // which are swallowed here anyway. - parser.maybe_consume_incorrect_semicolon(None); - } - - cancel_error_count(&psess); - parsing_result -} - -#[derive(Default)] -struct ParseSourceInfo { - has_main_fn: bool, - found_extern_crate: bool, - found_macro: bool, - supports_color: bool, - has_global_allocator: bool, - has_macro_def: bool, -} - -fn check_for_main_and_extern_crate( - crate_name: Option<&str>, - original_source_code: &str, - everything_else: &str, - crates: &str, - edition: Edition, - can_merge_doctests: bool, -) -> Result<(ParseSourceInfo, bool), FatalError> { - let result = rustc_driver::catch_fatal_errors(|| { - rustc_span::create_session_if_not_set_then(edition, |_| { - let mut info = - ParseSourceInfo { found_extern_crate: crate_name.is_none(), ..Default::default() }; - - let mut parsing_result = - parse_source(format!("{crates}{everything_else}"), &mut info, &crate_name); - // No need to double-check this if the "merged doctests" feature isn't enabled (so - // before the 2024 edition). - if can_merge_doctests && parsing_result != ParsingResult::Ok { - // If we found an AST error, we want to ensure it's because of an expression being - // used outside of a function. - // - // To do so, we wrap in a function in order to make sure that the doctest AST is - // correct. For example, if your doctest is `foo::bar()`, if we don't wrap it in a - // block, it would emit an AST error, which would be problematic for us since we - // want to filter out such errors which aren't "real" errors. - // - // The end goal is to be able to merge as many doctests as possible as one for much - // faster doctests run time. - parsing_result = parse_source( - format!("{crates}\nfn __doctest_wrap(){{{everything_else}\n}}"), - &mut info, - &crate_name, - ); - } - - (info, parsing_result) - }) - }); - let (mut info, parsing_result) = match result { - Err(..) | Ok((_, ParsingResult::Failed)) => return Err(FatalError), - Ok((info, parsing_result)) => (info, parsing_result), + Err(e) => { + e.cancel(); + Err(()) + } + _ => Err(()), }; - // If a doctest's `fn main` is being masked by a wrapper macro, the parsing loop above won't - // see it. In that case, run the old text-based scan to see if they at least have a main - // function written inside a macro invocation. See - // https://github.com/rust-lang/rust/issues/56898 - if info.found_macro - && !info.has_main_fn - && original_source_code - .lines() - .map(|line| { - let comment = line.find("//"); - if let Some(comment_begins) = comment { &line[0..comment_begins] } else { line } - }) - .any(|code| code.contains("fn main")) - { - info.has_main_fn = true; - } - - Ok((info, parsing_result != ParsingResult::Ok)) -} - -enum AttrKind { - CrateAttr, - Attr, -} - -/// Returns `Some` if the attribute is complete and `Some(true)` if it is an attribute that can be -/// placed at the crate root. -fn check_if_attr_is_complete(source: &str, edition: Edition) -> Option { - if source.is_empty() { - // Empty content so nothing to check in here... - return None; - } - let not_crate_attrs = [sym::forbid, sym::allow, sym::warn, sym::deny]; - - rustc_driver::catch_fatal_errors(|| { - rustc_span::create_session_if_not_set_then(edition, |_| { - use rustc_errors::DiagCtxt; - use rustc_errors::emitter::HumanEmitter; - use rustc_span::source_map::FilePathMapping; - - let filename = FileName::anon_source_code(source); - // Any errors in parsing should also appear when the doctest is compiled for real, so just - // send all the errors that librustc_ast emits directly into a `Sink` instead of stderr. - let sm = Arc::new(SourceMap::new(FilePathMapping::empty())); - let fallback_bundle = rustc_errors::fallback_fluent_bundle( - rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), - false, - ); - - let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle); - - let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings(); - let psess = ParseSess::with_dcx(dcx, sm); - let mut parser = match new_parser_from_source_str(&psess, filename, source.to_owned()) { - Ok(p) => p, - Err(errs) => { - errs.into_iter().for_each(|err| err.cancel()); - // If there is an unclosed delimiter, an error will be returned by the - // tokentrees. - return None; - } - }; - // If a parsing error happened, it's very likely that the attribute is incomplete. - let ret = match parser.parse_attribute(InnerAttrPolicy::Permitted) { - Ok(attr) => { - let attr_name = attr.name_or_empty(); - - if not_crate_attrs.contains(&attr_name) { - // There is one exception to these attributes: - // `#![allow(internal_features)]`. If this attribute is used, we need to - // consider it only as a crate-level attribute. - if attr_name == sym::allow - && let Some(list) = attr.meta_item_list() - && list.iter().any(|sub_attr| { - sub_attr.name_or_empty().as_str() == "internal_features" - }) - { - Some(AttrKind::CrateAttr) - } else { - Some(AttrKind::Attr) - } - } else { - Some(AttrKind::CrateAttr) - } - } - Err(e) => { - e.cancel(); - None - } - }; - ret - }) - }) - .unwrap_or(None) -} - -fn handle_attr(mod_attr_pending: &mut String, source_info: &mut SourceInfo, edition: Edition) { - if let Some(attr_kind) = check_if_attr_is_complete(mod_attr_pending, edition) { - let push_to = match attr_kind { - AttrKind::CrateAttr => &mut source_info.crate_attrs, - AttrKind::Attr => &mut source_info.maybe_crate_attrs, - }; - push_to.push_str(mod_attr_pending); - push_to.push('\n'); - // If it's complete, then we can clear the pending content. - mod_attr_pending.clear(); - } else { - mod_attr_pending.push('\n'); - } -} - -#[derive(Default)] -struct SourceInfo { - crate_attrs: String, - maybe_crate_attrs: String, - crates: String, - everything_else: String, -} - -fn partition_source(s: &str, edition: Edition) -> Option { - #[derive(Copy, Clone, PartialEq)] - enum PartitionState { - Attrs, - Crates, - Other, - } - let mut source_info = SourceInfo::default(); - let mut state = PartitionState::Attrs; - let mut mod_attr_pending = String::new(); - - for line in s.lines() { - let trimline = line.trim(); - - // FIXME(misdreavus): if a doc comment is placed on an extern crate statement, it will be - // shunted into "everything else" - match state { - PartitionState::Attrs => { - state = if trimline.starts_with("#![") { - mod_attr_pending = line.to_owned(); - handle_attr(&mut mod_attr_pending, &mut source_info, edition); - continue; - } else if trimline.chars().all(|c| c.is_whitespace()) - || (trimline.starts_with("//") && !trimline.starts_with("///")) - { - PartitionState::Attrs - } else if trimline.starts_with("extern crate") - || trimline.starts_with("#[macro_use] extern crate") - { - PartitionState::Crates - } else { - // First we check if the previous attribute was "complete"... - if !mod_attr_pending.is_empty() { - // If not, then we append the new line into the pending attribute to check - // if this time it's complete... - mod_attr_pending.push_str(line); - if !trimline.is_empty() { - handle_attr(&mut mod_attr_pending, &mut source_info, edition); - } - continue; - } else { - PartitionState::Other - } - }; - } - PartitionState::Crates => { - state = if trimline.starts_with("extern crate") - || trimline.starts_with("#[macro_use] extern crate") - || trimline.chars().all(|c| c.is_whitespace()) - || (trimline.starts_with("//") && !trimline.starts_with("///")) - { - PartitionState::Crates - } else { - PartitionState::Other - }; - } - PartitionState::Other => {} - } - - match state { - PartitionState::Attrs => { - source_info.crate_attrs.push_str(line); - source_info.crate_attrs.push('\n'); - } - PartitionState::Crates => { - source_info.crates.push_str(line); - source_info.crates.push('\n'); - } - PartitionState::Other => { - source_info.everything_else.push_str(line); - source_info.everything_else.push('\n'); - } - } - } - - if !mod_attr_pending.is_empty() { - debug!("invalid doctest code: {s:?}"); - return None; - } - - source_info.everything_else = source_info.everything_else.trim().to_string(); - - debug!("crate_attrs:\n{}{}", source_info.crate_attrs, source_info.maybe_crate_attrs); - debug!("crates:\n{}", source_info.crates); - debug!("after:\n{}", source_info.everything_else); - - Some(source_info) + cancel_error_count(&psess); + result } From 01fb7c3ac6223ca5657987e73401f7eb64609e01 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 6 Mar 2025 16:44:59 +0100 Subject: [PATCH 590/745] Update rustdoc-ui tests --- tests/rustdoc-ui/extract-doctests.stdout | 2 +- tests/rustdoc-ui/remap-path-prefix-invalid-doctest.stdout | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/rustdoc-ui/extract-doctests.stdout b/tests/rustdoc-ui/extract-doctests.stdout index fa8604cae948..b11531b844ee 100644 --- a/tests/rustdoc-ui/extract-doctests.stdout +++ b/tests/rustdoc-ui/extract-doctests.stdout @@ -1 +1 @@ -{"format_version":1,"doctests":[{"file":"$DIR/extract-doctests.rs","line":8,"doctest_attributes":{"original":"ignore (checking attributes)","should_panic":false,"no_run":false,"ignore":"All","rust":true,"test_harness":false,"compile_fail":false,"standalone_crate":false,"error_codes":[],"edition":null,"added_css_classes":[],"unknown":[]},"original_code":"let x = 12;\nlet y = 14;","doctest_code":"#![allow(unused)]\nfn main() {\nlet x = 12;\nlet y = 14;\n}","name":"$DIR/extract-doctests.rs - (line 8)"},{"file":"$DIR/extract-doctests.rs","line":13,"doctest_attributes":{"original":"edition2018,compile_fail","should_panic":false,"no_run":true,"ignore":"None","rust":true,"test_harness":false,"compile_fail":true,"standalone_crate":false,"error_codes":[],"edition":"2018","added_css_classes":[],"unknown":[]},"original_code":"let","doctest_code":"#![allow(unused)]\nfn main() {\nlet\n}","name":"$DIR/extract-doctests.rs - (line 13)"}]} \ No newline at end of file +{"format_version":1,"doctests":[{"file":"$DIR/extract-doctests.rs","line":8,"doctest_attributes":{"original":"ignore (checking attributes)","should_panic":false,"no_run":false,"ignore":"All","rust":true,"test_harness":false,"compile_fail":false,"standalone_crate":false,"error_codes":[],"edition":null,"added_css_classes":[],"unknown":[]},"original_code":"let x = 12;\nlet y = 14;","doctest_code":"#![allow(unused)]\nfn main() {\nlet x = 12;\nlet y = 14;\n}","name":"$DIR/extract-doctests.rs - (line 8)"},{"file":"$DIR/extract-doctests.rs","line":13,"doctest_attributes":{"original":"edition2018,compile_fail","should_panic":false,"no_run":true,"ignore":"None","rust":true,"test_harness":false,"compile_fail":true,"standalone_crate":false,"error_codes":[],"edition":"2018","added_css_classes":[],"unknown":[]},"original_code":"let","doctest_code":null,"name":"$DIR/extract-doctests.rs - (line 13)"}]} \ No newline at end of file diff --git a/tests/rustdoc-ui/remap-path-prefix-invalid-doctest.stdout b/tests/rustdoc-ui/remap-path-prefix-invalid-doctest.stdout index a05b51699894..c0d2515998f2 100644 --- a/tests/rustdoc-ui/remap-path-prefix-invalid-doctest.stdout +++ b/tests/rustdoc-ui/remap-path-prefix-invalid-doctest.stdout @@ -5,11 +5,11 @@ test remapped_path/remap-path-prefix-invalid-doctest.rs - SomeStruct (line 10) . failures: ---- remapped_path/remap-path-prefix-invalid-doctest.rs - SomeStruct (line 10) stdout ---- -error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `is` +error: expected one of `!` or `::`, found `is` --> remapped_path/remap-path-prefix-invalid-doctest.rs:11:6 | LL | this is not real code - | ^^ expected one of 8 possible tokens + | ^^ expected one of `!` or `::` error: aborting due to 1 previous error From 6f7e8d441a81ed89e14ad5ce53dcbe52ab0af64c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 7 Mar 2025 13:47:21 +0100 Subject: [PATCH 591/745] Correctly handle `fn main` in macro --- src/librustdoc/doctest/make.rs | 43 +++++++++++++++++++++++---------- src/librustdoc/doctest/tests.rs | 10 ++++---- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index cb14608b35ae..810f53636ce4 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -5,15 +5,17 @@ use std::fmt::{self, Write as _}; use std::io; use std::sync::Arc; -use rustc_ast::{self as ast, HasAttrs}; +use rustc_ast::token::{Delimiter, TokenKind}; +use rustc_ast::tokenstream::TokenTree; +use rustc_ast::{self as ast, HasAttrs, StmtKind}; use rustc_errors::ColorConfig; use rustc_errors::emitter::stderr_destination; use rustc_parse::new_parser_from_source_str; use rustc_session::parse::ParseSess; -use rustc_span::FileName; use rustc_span::edition::Edition; use rustc_span::source_map::SourceMap; use rustc_span::symbol::sym; +use rustc_span::{FileName, kw}; use tracing::debug; use super::GlobalTestOptions; @@ -319,7 +321,7 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result source.len() { hi = source.len(); @@ -351,11 +353,8 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result { - check_item(item, info, crate_name, false) - } - _ => {} + if let StmtKind::Item(ref item) = stmt.kind { + check_item(item, info, crate_name, false) } } } @@ -381,8 +380,6 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result {parsed:#?}"); - let result = match parsed { Ok(Some(ref item)) if let ast::ItemKind::Fn(ref fn_item) = item.kind @@ -416,11 +413,31 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result check_item(&item, &mut info, crate_name, true), - ast::StmtKind::Expr(ref expr) if matches!(expr.kind, ast::ExprKind::Err(_)) => { + StmtKind::Item(ref item) => check_item(&item, &mut info, crate_name, true), + StmtKind::Expr(ref expr) if matches!(expr.kind, ast::ExprKind::Err(_)) => { cancel_error_count(&psess); return Err(()); } + StmtKind::MacCall(ref mac_call) if !info.has_main_fn => { + let mut iter = mac_call.mac.args.tokens.iter(); + + while let Some(token) = iter.next() { + if let TokenTree::Token(token, _) = token + && let TokenKind::Ident(name, _) = token.kind + && name == kw::Fn + && let Some(TokenTree::Token(fn_token, _)) = iter.peek() + && let TokenKind::Ident(fn_name, _) = fn_token.kind + && fn_name == sym::main + && let Some(TokenTree::Delimited(_, _, Delimiter::Parenthesis, _)) = { + iter.next(); + iter.peek() + } + { + info.has_main_fn = true; + break; + } + } + } _ => {} } @@ -433,7 +450,7 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result Date: Fri, 7 Mar 2025 15:20:14 +0100 Subject: [PATCH 592/745] Correctly handle line comments in attributes and generate extern crates outside of wrapping function --- src/librustdoc/doctest/make.rs | 50 +++++++++++++------ src/librustdoc/doctest/tests.rs | 30 +++++++++-- tests/run-make/rustdoc-error-lines/rmake.rs | 6 +-- .../rustdoc-ui/doctest/display-output.stdout | 6 +-- tests/rustdoc-ui/doctest/extern-crate.rs | 23 +++++++++ tests/rustdoc-ui/doctest/extern-crate.stdout | 6 +++ tests/rustdoc/playground.rs | 2 +- 7 files changed, 98 insertions(+), 25 deletions(-) create mode 100644 tests/rustdoc-ui/doctest/extern-crate.rs create mode 100644 tests/rustdoc-ui/doctest/extern-crate.stdout diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index 810f53636ce4..0ed2d37f74c1 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -176,9 +176,24 @@ impl DocTestBuilder { // Now push any outer attributes from the example, assuming they // are intended to be crate attributes. - prog.push_str(&self.crate_attrs); - prog.push_str(&self.maybe_crate_attrs); - prog.push_str(&self.crates); + if !self.crate_attrs.is_empty() { + prog.push_str(&self.crate_attrs); + if !self.crate_attrs.ends_with('\n') { + prog.push('\n'); + } + } + if !self.maybe_crate_attrs.is_empty() { + prog.push_str(&self.maybe_crate_attrs); + if !self.maybe_crate_attrs.ends_with('\n') { + prog.push('\n'); + } + } + if !self.crates.is_empty() { + prog.push_str(&self.crates); + if !self.crates.ends_with('\n') { + prog.push('\n'); + } + } // Don't inject `extern crate std` because it's already injected by the // compiler. @@ -276,7 +291,6 @@ const DOCTEST_CODE_WRAPPER: &str = "fn f(){"; fn parse_source(source: &str, crate_name: &Option<&str>) -> Result { use rustc_errors::DiagCtxt; use rustc_errors::emitter::{Emitter, HumanEmitter}; - // use rustc_parse::parser::ForceCollect; use rustc_span::source_map::FilePathMapping; let mut info = @@ -338,7 +352,8 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result, is_top_level: bool, - ) { + ) -> bool { + let mut is_crate = false; if !info.has_global_allocator && item.attrs.iter().any(|attr| attr.name_or_empty() == sym::global_allocator) { @@ -354,12 +369,13 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result { + is_crate = true; if !info.found_extern_crate && let Some(crate_name) = crate_name { @@ -374,6 +390,7 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result {} } + is_crate } let mut prev_span_hi = None; @@ -412,8 +429,11 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result check_item(&item, &mut info, crate_name, true), + StmtKind::Item(ref item) => { + is_crate = check_item(&item, &mut info, crate_name, true); + } StmtKind::Expr(ref expr) if matches!(expr.kind, ast::ExprKind::Err(_)) => { cancel_error_count(&psess); return Err(()); @@ -450,15 +470,15 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result $DIR/display-output.rs:11:5 + --> $DIR/display-output.rs:12:5 | LL | let x = 12; | ^ help: if this is intentional, prefix it with an underscore: `_x` @@ -19,13 +19,13 @@ LL | #![warn(unused)] = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` warning: unused variable: `x` - --> $DIR/display-output.rs:13:8 + --> $DIR/display-output.rs:14:8 | LL | fn foo(x: &dyn std::fmt::Display) {} | ^ help: if this is intentional, prefix it with an underscore: `_x` warning: function `foo` is never used - --> $DIR/display-output.rs:13:4 + --> $DIR/display-output.rs:14:4 | LL | fn foo(x: &dyn std::fmt::Display) {} | ^^^ diff --git a/tests/rustdoc-ui/doctest/extern-crate.rs b/tests/rustdoc-ui/doctest/extern-crate.rs new file mode 100644 index 000000000000..0415d33bb723 --- /dev/null +++ b/tests/rustdoc-ui/doctest/extern-crate.rs @@ -0,0 +1,23 @@ +//@ check-pass +//@ compile-flags:--test --test-args=--test-threads=1 +//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" + +// This test ensures that crate imports are placed outside of the `main` function +// so they work all the time (even in 2015 edition). + +/// ```rust +/// #![feature(test)] +/// +/// extern crate test; +/// use test::Bencher; +/// +/// #[bench] +/// fn bench_xor_1000_ints(b: &mut Bencher) { +/// b.iter(|| { +/// (0..1000).fold(0, |old, new| old ^ new); +/// }); +/// } +/// ``` +/// +pub fn foo() {} diff --git a/tests/rustdoc-ui/doctest/extern-crate.stdout b/tests/rustdoc-ui/doctest/extern-crate.stdout new file mode 100644 index 000000000000..b103343afdd5 --- /dev/null +++ b/tests/rustdoc-ui/doctest/extern-crate.stdout @@ -0,0 +1,6 @@ + +running 1 test +test $DIR/extern-crate.rs - foo (line 9) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc/playground.rs b/tests/rustdoc/playground.rs index db2d1669df60..65dad2a5195d 100644 --- a/tests/rustdoc/playground.rs +++ b/tests/rustdoc/playground.rs @@ -24,4 +24,4 @@ //@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&edition=2015"]' "" //@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&edition=2015"]' "" -//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&version=nightly&edition=2015"]' "" +//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0A%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&version=nightly&edition=2015"]' "" From a3bafca14aa8e6ef1694f416ca00215e49771b0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 25 Mar 2025 22:36:05 +0100 Subject: [PATCH 593/745] Add job duration changes stats in post-merge analysis --- src/ci/citool/src/analysis.rs | 55 +++++++++++++++++++++++++++++++++-- src/ci/citool/src/main.rs | 7 +++-- 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 2b001f28b0eb..fc18e438aab9 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -1,10 +1,11 @@ -use std::collections::{BTreeMap, HashMap, HashSet}; use std::fmt::Debug; use build_helper::metrics::{ BuildStep, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, escape_step_name, format_build_steps, }; +use std::collections::{BTreeMap, HashMap, HashSet}; +use std::time::Duration; use crate::metrics; use crate::metrics::{JobMetrics, JobName, get_test_suites}; @@ -184,11 +185,61 @@ fn render_table(suites: BTreeMap) -> String { } /// Outputs a report of test differences between the `parent` and `current` commits. -pub fn output_test_diffs(job_metrics: HashMap) { +pub fn output_test_diffs(job_metrics: &HashMap) { let aggregated_test_diffs = aggregate_test_diffs(&job_metrics); report_test_diffs(aggregated_test_diffs); } +/// Prints the ten largest differences in bootstrap durations. +pub fn output_largest_duration_changes(job_metrics: &HashMap) { + struct Entry<'a> { + job: &'a JobName, + before: Duration, + after: Duration, + change: f64, + } + + let mut changes: Vec = vec![]; + for (job, metrics) in job_metrics { + if let Some(parent) = &metrics.parent { + let duration_before = parent + .invocations + .iter() + .map(|i| BuildStep::from_invocation(i).duration) + .sum::(); + let duration_after = metrics + .current + .invocations + .iter() + .map(|i| BuildStep::from_invocation(i).duration) + .sum::(); + let pct_change = duration_after.as_secs_f64() / duration_before.as_secs_f64(); + let pct_change = pct_change * 100.0; + // Normalize around 100, to get + for regression and - for improvements + let pct_change = pct_change - 100.0; + changes.push(Entry { + job, + before: duration_before, + after: duration_after, + change: pct_change, + }); + } + } + changes.sort_by(|e1, e2| e1.change.partial_cmp(&e2.change).unwrap().reverse()); + + println!("# Job duration changes"); + for (index, entry) in changes.into_iter().take(10).enumerate() { + println!( + "{}. `{}`: {:.1}s -> {:.1}s ({:.1}%)", + index + 1, + entry.job, + entry.before.as_secs_f64(), + entry.after.as_secs_f64(), + entry.change + ); + } +} + #[derive(Default)] struct TestSuiteRecord { passed: u64, diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs index 5f5c50dc43a0..6db5eab458cc 100644 --- a/src/ci/citool/src/main.rs +++ b/src/ci/citool/src/main.rs @@ -15,7 +15,7 @@ use clap::Parser; use jobs::JobDatabase; use serde_yaml::Value; -use crate::analysis::output_test_diffs; +use crate::analysis::{output_largest_duration_changes, output_test_diffs}; use crate::cpu_usage::load_cpu_usage; use crate::datadog::upload_datadog_metric; use crate::jobs::RunType; @@ -160,7 +160,7 @@ fn postprocess_metrics( job_name, JobMetrics { parent: Some(parent_metrics), current: metrics }, )]); - output_test_diffs(job_metrics); + output_test_diffs(&job_metrics); return Ok(()); } Err(error) => { @@ -180,7 +180,8 @@ fn post_merge_report(db: JobDatabase, current: String, parent: String) -> anyhow let metrics = download_auto_job_metrics(&db, &parent, ¤t)?; println!("\nComparing {parent} (parent) -> {current} (this PR)\n"); - output_test_diffs(metrics); + output_test_diffs(&metrics); + output_largest_duration_changes(&metrics); Ok(()) } From 4a4367535339d119a6a3c4f515c8912667b30be4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 27 Mar 2025 11:25:25 +0100 Subject: [PATCH 594/745] Add cache for job metrics --- src/ci/citool/src/metrics.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/ci/citool/src/metrics.rs b/src/ci/citool/src/metrics.rs index 086aa5009f34..a816fb3c4f16 100644 --- a/src/ci/citool/src/metrics.rs +++ b/src/ci/citool/src/metrics.rs @@ -1,5 +1,5 @@ use std::collections::HashMap; -use std::path::Path; +use std::path::{Path, PathBuf}; use anyhow::Context; use build_helper::metrics::{JsonNode, JsonRoot, TestSuite}; @@ -74,6 +74,17 @@ Maybe it was newly added?"#, } pub fn download_job_metrics(job_name: &str, sha: &str) -> anyhow::Result { + // Best effort cache to speed-up local re-executions of citool + let cache_path = PathBuf::from(".citool-cache").join(sha).join(format!("{job_name}.json")); + if cache_path.is_file() { + if let Ok(metrics) = std::fs::read_to_string(&cache_path) + .map_err(|err| err.into()) + .and_then(|data| anyhow::Ok::(serde_json::from_str::(&data)?)) + { + return Ok(metrics); + } + } + let url = get_metrics_url(job_name, sha); let mut response = ureq::get(&url).call()?; if !response.status().is_success() { @@ -87,6 +98,13 @@ pub fn download_job_metrics(job_name: &str, sha: &str) -> anyhow::Result Date: Thu, 27 Mar 2025 11:29:48 +0100 Subject: [PATCH 595/745] Add a note about interpreting job duration changes --- src/ci/citool/src/analysis.rs | 9 +++++++++ src/ci/citool/src/utils.rs | 1 - 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index fc18e438aab9..2e1ede126dc3 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -238,6 +238,15 @@ pub fn output_largest_duration_changes(job_metrics: &HashMap {summary} - " ); func(); From d0353f5c7ac0c73c6ae97623ac3e01fab1f657ae Mon Sep 17 00:00:00 2001 From: xizheyin Date: Thu, 27 Mar 2025 17:25:22 +0800 Subject: [PATCH 596/745] Add ui test for struct construction by calling syntax Signed-off-by: xizheyin --- ...struct-construct-with-call-issue-138931.rs | 25 +++++++++++ ...ct-construct-with-call-issue-138931.stderr | 45 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 tests/ui/structs/struct-construct-with-call-issue-138931.rs create mode 100644 tests/ui/structs/struct-construct-with-call-issue-138931.stderr diff --git a/tests/ui/structs/struct-construct-with-call-issue-138931.rs b/tests/ui/structs/struct-construct-with-call-issue-138931.rs new file mode 100644 index 000000000000..5d50eb14bff1 --- /dev/null +++ b/tests/ui/structs/struct-construct-with-call-issue-138931.rs @@ -0,0 +1,25 @@ +struct PersonOnlyName { + name: String +} + +struct PersonWithAge { + name: String, + age: u8, + height: u8, +} + + + +fn main() { + let wilfred = PersonOnlyName("Name1".to_owned()); + //~^ ERROR expected function, tuple struct or tuple variant, found struct `PersonOnlyName` [E0423] + + let bill = PersonWithAge( //~ ERROR expected function, tuple struct or tuple variant, found struct `PersonWithAge` [E0423] + "Name2".to_owned(), + 20, + 180, + ); + + let person = PersonWithAge("Name3".to_owned()); + //~^ ERROR expected function, tuple struct or tuple variant, found struct `PersonWithAge` [E0423] +} diff --git a/tests/ui/structs/struct-construct-with-call-issue-138931.stderr b/tests/ui/structs/struct-construct-with-call-issue-138931.stderr new file mode 100644 index 000000000000..af68b37a891e --- /dev/null +++ b/tests/ui/structs/struct-construct-with-call-issue-138931.stderr @@ -0,0 +1,45 @@ +error[E0423]: expected function, tuple struct or tuple variant, found struct `PersonOnlyName` + --> $DIR/struct-construct-with-call-issue-138931.rs:14:19 + | +LL | / struct PersonOnlyName { +LL | | name: String +LL | | } + | |_- `PersonOnlyName` defined here +... +LL | let wilfred = PersonOnlyName("Name1".to_owned()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `PersonOnlyName { name: val }` + +error[E0423]: expected function, tuple struct or tuple variant, found struct `PersonWithAge` + --> $DIR/struct-construct-with-call-issue-138931.rs:17:16 + | +LL | / struct PersonWithAge { +LL | | name: String, +LL | | age: u8, +LL | | height: u8, +LL | | } + | |_- `PersonWithAge` defined here +... +LL | let bill = PersonWithAge( + | ________________^ +LL | | "Name2".to_owned(), +LL | | 20, +LL | | 180, +LL | | ); + | |_____^ help: use struct literal syntax instead: `PersonWithAge { name: val, age: val, height: val }` + +error[E0423]: expected function, tuple struct or tuple variant, found struct `PersonWithAge` + --> $DIR/struct-construct-with-call-issue-138931.rs:23:18 + | +LL | / struct PersonWithAge { +LL | | name: String, +LL | | age: u8, +LL | | height: u8, +LL | | } + | |_- `PersonWithAge` defined here +... +LL | let person = PersonWithAge("Name3".to_owned()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `PersonWithAge { name: val, age: val, height: val }` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0423`. From be13105d737545a4a5f0aa0709342b4db8f2f1e3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 27 Mar 2025 12:55:30 +0100 Subject: [PATCH 597/745] Improve comment and test for generated doctest with code comments --- src/librustdoc/doctest/make.rs | 5 +++-- src/librustdoc/doctest/tests.rs | 24 +++++++++++++++++++++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index 0ed2d37f74c1..512343693bc2 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -85,6 +85,8 @@ impl DocTestBuilder { maybe_crate_attrs, })) = result else { + // If the AST returned an error, we don't want this doctest to be merged with the + // others. return Self::invalid( String::new(), String::new(), @@ -98,8 +100,7 @@ impl DocTestBuilder { debug!("crates:\n{crates}"); debug!("after:\n{everything_else}"); - // If the AST returned an error, we don't want this doctest to be merged with the - // others. Same if it contains `#[feature]` or `#[no_std]`. + // If it contains `#[feature]` or `#[no_std]`, we don't want it to be merged either. let can_be_merged = can_merge_doctests && !has_global_allocator && crate_attrs.is_empty() diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs index 59cc33558ed5..4833ea040515 100644 --- a/src/librustdoc/doctest/tests.rs +++ b/src/librustdoc/doctest/tests.rs @@ -405,7 +405,9 @@ fn check_split_args() { #[test] fn comment_in_attrs() { - // if input already has a fn main, it should insert a space before it + // If there is an inline code comment after attributes, we need to ensure that + // a backline will be added to prevent generating code "inside" it (and thus generating) + // invalid code. let opts = default_global_opts(""); let input = "\ #![feature(rustdoc_internals)] @@ -424,4 +426,24 @@ fn main() { .to_string(); let (output, len) = make_test(input, None, false, &opts, None); assert_eq!((output, len), (expected, 2)); + + // And same, if there is a `main` function provided by the user, we ensure that it's + // correctly separated. + let input = "\ +#![feature(rustdoc_internals)] +#![allow(internal_features)] +#![doc(rust_logo)] +//! This crate has the Rust(tm) branding on it. +fn main() {}"; + let expected = "\ +#![allow(unused)] +#![feature(rustdoc_internals)] +#![allow(internal_features)] +#![doc(rust_logo)] +//! This crate has the Rust(tm) branding on it. + +fn main() {}" + .to_string(); + let (output, len) = make_test(input, None, false, &opts, None); + assert_eq!((output, len), (expected, 1)); } From f333ad8656af7a43559805a9a321da8cf618d0c1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 27 Mar 2025 13:00:49 +0100 Subject: [PATCH 598/745] Improve code comment --- src/librustdoc/doctest/make.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index 512343693bc2..46226a8bc717 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -334,8 +334,8 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result, ) { let extra_len = DOCTEST_CODE_WRAPPER.len(); - // We need to shift by 1 because we added `{` at the beginning of the source.we provided - // to the parser. + // We need to shift by the length of `DOCTEST_CODE_WRAPPER` because we + // added it at the beginning of the source we provided to the parser. let lo = prev_span_hi.unwrap_or(0); let mut hi = span.hi().0 as usize - extra_len; if hi > source.len() { From 8327bb6ad3c6a6975ed7a0a408614b8d90c8d0ad Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 27 Mar 2025 13:01:25 +0100 Subject: [PATCH 599/745] Add `expect` to the list of non-crate attributes for doctest generation --- src/librustdoc/doctest/make.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index 46226a8bc717..abb626025a8c 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -395,7 +395,7 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result Date: Thu, 27 Mar 2025 17:28:15 +0800 Subject: [PATCH 600/745] Improve suggest construct with literal syntax instead of calling Signed-off-by: xizheyin --- .../rustc_resolve/src/late/diagnostics.rs | 106 ++++++++++++------ ...ct-construct-with-call-issue-138931.stderr | 17 ++- 2 files changed, 88 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 3d666055a94f..97dd9faf6dec 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1681,41 +1681,81 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // the struct literal syntax at all, as that will cause a subsequent error. let fields = this.r.field_idents(def_id); let has_fields = fields.as_ref().is_some_and(|f| !f.is_empty()); - let (fields, applicability) = match fields { - Some(fields) => { - let fields = if let Some(old_fields) = old_fields { - fields - .iter() - .enumerate() - .map(|(idx, new)| (new, old_fields.get(idx))) - .map(|(new, old)| { - if let Some(Some(old)) = old - && new.as_str() != old - { - format!("{new}: {old}") - } else { - new.to_string() - } - }) - .collect::>() - } else { - fields - .iter() - .map(|f| format!("{f}{tail}")) - .collect::>() - }; - (fields.join(", "), applicability) - } - None => ("/* fields */".to_string(), Applicability::HasPlaceholders), - }; - let pad = if has_fields { " " } else { "" }; - err.span_suggestion( + if let PathSource::Expr(Some(Expr { + kind: ExprKind::Call(path, args), span, - format!("use struct {descr} syntax instead"), - format!("{path_str} {{{pad}{fields}{pad}}}"), - applicability, - ); + .. + })) = source + && !args.is_empty() + && let Some(fields) = &fields + && args.len() == fields.len() + // Make sure we have same number of args as fields + { + let path_span = path.span; + let mut parts = Vec::new(); + + // Start with the opening brace + parts.push(( + path_span.shrink_to_hi().until(args[0].span), + "{".to_owned(), + )); + + for (field, arg) in fields.iter().zip(args.iter()) { + // Add the field name before the argument + parts.push((arg.span.shrink_to_lo(), format!("{}: ", field))); + } + + // Add the closing brace + parts.push(( + args.last().unwrap().span.shrink_to_hi().until(span.shrink_to_hi()), + "}".to_owned(), + )); + + err.multipart_suggestion_verbose( + format!("use struct {descr} syntax instead of calling"), + parts, + applicability, + ); + } else { + let (fields, applicability) = match fields { + Some(fields) => { + let fields = if let Some(old_fields) = old_fields { + fields + .iter() + .enumerate() + .map(|(idx, new)| (new, old_fields.get(idx))) + .map(|(new, old)| { + if let Some(Some(old)) = old + && new.as_str() != old + { + format!("{new}: {old}") + } else { + new.to_string() + } + }) + .collect::>() + } else { + fields + .iter() + .map(|f| format!("{f}{tail}")) + .collect::>() + }; + + (fields.join(", "), applicability) + } + None => { + ("/* fields */".to_string(), Applicability::HasPlaceholders) + } + }; + let pad = if has_fields { " " } else { "" }; + err.span_suggestion( + span, + format!("use struct {descr} syntax instead"), + format!("{path_str} {{{pad}{fields}{pad}}}"), + applicability, + ); + } } if let PathSource::Expr(Some(Expr { kind: ExprKind::Call(path, args), diff --git a/tests/ui/structs/struct-construct-with-call-issue-138931.stderr b/tests/ui/structs/struct-construct-with-call-issue-138931.stderr index af68b37a891e..acae01df5636 100644 --- a/tests/ui/structs/struct-construct-with-call-issue-138931.stderr +++ b/tests/ui/structs/struct-construct-with-call-issue-138931.stderr @@ -7,7 +7,13 @@ LL | | } | |_- `PersonOnlyName` defined here ... LL | let wilfred = PersonOnlyName("Name1".to_owned()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `PersonOnlyName { name: val }` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use struct literal syntax instead of calling + | +LL - let wilfred = PersonOnlyName("Name1".to_owned()); +LL + let wilfred = PersonOnlyName{name: "Name1".to_owned()}; + | error[E0423]: expected function, tuple struct or tuple variant, found struct `PersonWithAge` --> $DIR/struct-construct-with-call-issue-138931.rs:17:16 @@ -25,7 +31,14 @@ LL | | "Name2".to_owned(), LL | | 20, LL | | 180, LL | | ); - | |_____^ help: use struct literal syntax instead: `PersonWithAge { name: val, age: val, height: val }` + | |_____^ + | +help: use struct literal syntax instead of calling + | +LL ~ let bill = PersonWithAge{name: "Name2".to_owned(), +LL ~ age: 20, +LL ~ height: 180}; + | error[E0423]: expected function, tuple struct or tuple variant, found struct `PersonWithAge` --> $DIR/struct-construct-with-call-issue-138931.rs:23:18 From 6c2161a07c8f54e5b2838087a9a7406a789c98e8 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 27 Mar 2025 14:11:11 +0100 Subject: [PATCH 601/745] Mark test as only-unix. --- tests/ui/thread-local/spawn-hook-atexit.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ui/thread-local/spawn-hook-atexit.rs b/tests/ui/thread-local/spawn-hook-atexit.rs index 41fcbab1a812..b084e0bb3878 100644 --- a/tests/ui/thread-local/spawn-hook-atexit.rs +++ b/tests/ui/thread-local/spawn-hook-atexit.rs @@ -1,4 +1,5 @@ // Regression test for https://github.com/rust-lang/rust/issues/138696 +//@ only-unix //@ needs-threads //@ run-pass From c845ff0d7111ec31a44648a085a3fa3fc0fa7143 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 27 Mar 2025 15:05:37 +0100 Subject: [PATCH 602/745] run a few more concurrency tests on aarch64-linux-android --- src/tools/miri/ci/ci.sh | 2 +- src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh index 3327ad17c44e..7155d692ee5c 100755 --- a/src/tools/miri/ci/ci.sh +++ b/src/tools/miri/ci/ci.sh @@ -166,7 +166,7 @@ case $HOST_TARGET in UNIX="hello panic/panic panic/unwind concurrency/simple atomic libc-mem libc-misc libc-random env num_cpus" # the things that are very similar across all Unixes, and hence easily supported there TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe - TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random sync threadname pthread epoll eventfd + TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random sync concurrency thread epoll eventfd TEST_TARGET=wasm32-wasip2 run_tests_minimal $BASIC wasm TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std empty_main wasm # this target doesn't really have std TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std diff --git a/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs b/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs index 0ca13b5039dd..f8f1c554f0d7 100644 --- a/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs +++ b/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs @@ -64,7 +64,7 @@ fn wait_wrong_val() { ), -1, ); - assert_eq!(*libc::__errno_location(), libc::EAGAIN); + assert_eq!(io::Error::last_os_error().raw_os_error().unwrap(), libc::EAGAIN); } } @@ -85,7 +85,7 @@ fn wait_timeout() { ), -1, ); - assert_eq!(*libc::__errno_location(), libc::ETIMEDOUT); + assert_eq!(io::Error::last_os_error().raw_os_error().unwrap(), libc::ETIMEDOUT); } assert!((200..1000).contains(&start.elapsed().as_millis())); @@ -124,7 +124,7 @@ fn wait_absolute_timeout() { ), -1, ); - assert_eq!(*libc::__errno_location(), libc::ETIMEDOUT); + assert_eq!(io::Error::last_os_error().raw_os_error().unwrap(), libc::ETIMEDOUT); } assert!((200..1000).contains(&start.elapsed().as_millis())); From 2004dacef2fe6e9b75e56db04587579111679b82 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 27 Mar 2025 14:32:29 +0100 Subject: [PATCH 603/745] Improve code --- src/librustdoc/doctest/make.rs | 63 ++++++++++++++++------------------ 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index abb626025a8c..93be35200060 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -25,7 +25,7 @@ use crate::html::markdown::LangString; #[derive(Default)] struct ParseSourceInfo { has_main_fn: bool, - found_extern_crate: bool, + already_has_extern_crate: bool, supports_color: bool, has_global_allocator: bool, has_macro_def: bool, @@ -48,7 +48,7 @@ pub(crate) struct DocTestBuilder { pub(crate) crates: String, pub(crate) everything_else: String, pub(crate) test_id: Option, - pub(crate) failed_ast: bool, + pub(crate) invalid_ast: bool, pub(crate) can_be_merged: bool, } @@ -75,7 +75,7 @@ impl DocTestBuilder { let Ok(Ok(ParseSourceInfo { has_main_fn, - found_extern_crate, + already_has_extern_crate, supports_color, has_global_allocator, has_macro_def, @@ -114,9 +114,9 @@ impl DocTestBuilder { maybe_crate_attrs, crates, everything_else, - already_has_extern_crate: found_extern_crate, + already_has_extern_crate, test_id, - failed_ast: false, + invalid_ast: false, can_be_merged, } } @@ -137,7 +137,7 @@ impl DocTestBuilder { everything_else, already_has_extern_crate: false, test_id, - failed_ast: true, + invalid_ast: true, can_be_merged: false, } } @@ -151,10 +151,10 @@ impl DocTestBuilder { opts: &GlobalTestOptions, crate_name: Option<&str>, ) -> (String, usize) { - if self.failed_ast { + if self.invalid_ast { // If the AST failed to compile, no need to go generate a complete doctest, the error // will be better this way. - debug!("failed AST:\n{test_code}"); + debug!("invalid AST:\n{test_code}"); return (test_code.to_string(), 0); } let mut line_offset = 0; @@ -279,7 +279,7 @@ impl DocTestBuilder { } } -fn cancel_error_count(psess: &ParseSess) { +fn reset_error_count(psess: &ParseSess) { // Reset errors so that they won't be reported as compiler bugs when dropping the // dcx. Any errors in the tests will be reported when the test file is compiled, // Note that we still need to cancel the errors above otherwise `Diag` will panic on @@ -295,7 +295,7 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result) -> Result p, Err(errs) => { errs.into_iter().for_each(|err| err.cancel()); - cancel_error_count(&psess); + reset_error_count(&psess); return Err(()); } }; - fn push_to_s( - s: &mut String, - source: &str, - span: rustc_span::Span, - prev_span_hi: &mut Option, - ) { + fn push_to_s(s: &mut String, source: &str, span: rustc_span::Span, prev_span_hi: &mut usize) { let extra_len = DOCTEST_CODE_WRAPPER.len(); // We need to shift by the length of `DOCTEST_CODE_WRAPPER` because we // added it at the beginning of the source we provided to the parser. - let lo = prev_span_hi.unwrap_or(0); let mut hi = span.hi().0 as usize - extra_len; if hi > source.len() { hi = source.len(); } - s.push_str(&source[lo..hi]); - *prev_span_hi = Some(hi); + s.push_str(&source[*prev_span_hi..hi]); + *prev_span_hi = hi; } // Recurse through functions body. It is necessary because the doctest source code is @@ -354,7 +348,7 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result, is_top_level: bool, ) -> bool { - let mut is_crate = false; + let mut is_extern_crate = false; if !info.has_global_allocator && item.attrs.iter().any(|attr| attr.name_or_empty() == sym::global_allocator) { @@ -370,17 +364,17 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result { - is_crate = true; - if !info.found_extern_crate + is_extern_crate = true; + if !info.already_has_extern_crate && let Some(crate_name) = crate_name { - info.found_extern_crate = match original { + info.already_has_extern_crate = match original { Some(name) => name.as_str() == *crate_name, None => item.ident.as_str() == *crate_name, }; @@ -391,10 +385,10 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result {} } - is_crate + is_extern_crate } - let mut prev_span_hi = None; + let mut prev_span_hi = 0; let not_crate_attrs = [sym::forbid, sym::allow, sym::warn, sym::deny, sym::expect]; let parsed = parser.parse_item(rustc_parse::parser::ForceCollect::No); @@ -430,13 +424,13 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result { - is_crate = check_item(&item, &mut info, crate_name, true); + is_extern_crate = check_item(&item, &mut info, crate_name, true); } StmtKind::Expr(ref expr) if matches!(expr.kind, ast::ExprKind::Err(_)) => { - cancel_error_count(&psess); + reset_error_count(&psess); return Err(()); } StmtKind::MacCall(ref mac_call) if !info.has_main_fn => { @@ -471,11 +465,12 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result) -> Result Err(()), }; - cancel_error_count(&psess); + reset_error_count(&psess); result } From 3371d498b1d6853598b9bedaf1e71d4c3f1d538b Mon Sep 17 00:00:00 2001 From: joboet Date: Thu, 27 Mar 2025 15:41:46 +0100 Subject: [PATCH 604/745] std: get rid of pre-Vista fallback code We haven't had any Windows XP targets for a long while now... --- library/std/src/sys/pal/windows/pipe.rs | 28 ++++++------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/library/std/src/sys/pal/windows/pipe.rs b/library/std/src/sys/pal/windows/pipe.rs index 8521cf4162f5..c78524649226 100644 --- a/library/std/src/sys/pal/windows/pipe.rs +++ b/library/std/src/sys/pal/windows/pipe.rs @@ -74,7 +74,6 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res let ours; let mut name; let mut tries = 0; - let mut reject_remote_clients_flag = c::PIPE_REJECT_REMOTE_CLIENTS; loop { tries += 1; name = format!( @@ -96,7 +95,7 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res c::PIPE_TYPE_BYTE | c::PIPE_READMODE_BYTE | c::PIPE_WAIT - | reject_remote_clients_flag, + | c::PIPE_REJECT_REMOTE_CLIENTS, 1, PIPE_BUFFER_CAPACITY, PIPE_BUFFER_CAPACITY, @@ -112,30 +111,15 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res // // Don't try again too much though as this could also perhaps be a // legit error. - // If `ERROR_INVALID_PARAMETER` is returned, this probably means we're - // running on pre-Vista version where `PIPE_REJECT_REMOTE_CLIENTS` is - // not supported, so we continue retrying without it. This implies - // reduced security on Windows versions older than Vista by allowing - // connections to this pipe from remote machines. - // Proper fix would increase the number of FFI imports and introduce - // significant amount of Windows XP specific code with no clean - // testing strategy - // For more info, see https://github.com/rust-lang/rust/pull/37677. if handle == c::INVALID_HANDLE_VALUE { let error = api::get_last_error(); - if tries < 10 { - if error == WinError::ACCESS_DENIED { - continue; - } else if reject_remote_clients_flag != 0 - && error == WinError::INVALID_PARAMETER - { - reject_remote_clients_flag = 0; - tries -= 1; - continue; - } + if tries < 10 && error == WinError::ACCESS_DENIED { + continue; + } else { + return Err(io::Error::from_raw_os_error(error.code as i32)); } - return Err(io::Error::from_raw_os_error(error.code as i32)); } + ours = Handle::from_raw_handle(handle); break; } From 1494da4ffbfab8d0b7a62dd37d9f4a77f1038840 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 27 Mar 2025 16:23:41 +0100 Subject: [PATCH 605/745] Add new regression test for doctest --- src/librustdoc/doctest/tests.rs | 131 ++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs index 4833ea040515..949ed837db3a 100644 --- a/src/librustdoc/doctest/tests.rs +++ b/src/librustdoc/doctest/tests.rs @@ -447,3 +447,134 @@ fn main() {}" let (output, len) = make_test(input, None, false, &opts, None); assert_eq!((output, len), (expected, 1)); } + +#[test] +fn comments() { + let opts = default_global_opts(""); + let input = r##" +//! A doc comment that applies to the implicit anonymous module of this crate + +pub mod outer_module { + + //! - Inner line doc + //!! - Still an inner line doc (but with a bang at the beginning) + + /*! - Inner block doc */ + /*!! - Still an inner block doc (but with a bang at the beginning) */ + + // - Only a comment + /// - Outer line doc (exactly 3 slashes) + //// - Only a comment + + /* - Only a comment */ + /** - Outer block doc (exactly) 2 asterisks */ + /*** - Only a comment */ + + pub mod inner_module {} + + pub mod nested_comments { + /* In Rust /* we can /* nest comments */ */ */ + + // All three types of block comments can contain or be nested inside + // any other type: + + /* /* */ /** */ /*! */ */ + /*! /* */ /** */ /*! */ */ + /** /* */ /** */ /*! */ */ + pub mod dummy_item {} + } + + pub mod degenerate_cases { + // empty inner line doc + //! + + // empty inner block doc + /*!*/ + + // empty line comment + // + + // empty outer line doc + /// + + // empty block comment + /**/ + + pub mod dummy_item {} + + // empty 2-asterisk block isn't a doc block, it is a block comment + /***/ + + } + + /* The next one isn't allowed because outer doc comments + require an item that will receive the doc */ + + /// Where is my item? +} +"##; + let expected = " +//! A doc comment that applies to the implicit anonymous module of this crate + +pub mod outer_module { + + //! - Inner line doc + //!! - Still an inner line doc (but with a bang at the beginning) + + /*! - Inner block doc */ + /*!! - Still an inner block doc (but with a bang at the beginning) */ + + // - Only a comment + /// - Outer line doc (exactly 3 slashes) + //// - Only a comment + + /* - Only a comment */ + /** - Outer block doc (exactly) 2 asterisks */ + /*** - Only a comment */ + + pub mod inner_module {} + + pub mod nested_comments { + /* In Rust /* we can /* nest comments */ */ */ + + // All three types of block comments can contain or be nested inside + // any other type: + + /* /* */ /** */ /*! */ */ + /*! /* */ /** */ /*! */ */ + /** /* */ /** */ /*! */ */ + pub mod dummy_item {} + } + + pub mod degenerate_cases { + // empty inner line doc + //! + + // empty inner block doc + /*!*/ + + // empty line comment + // + + // empty outer line doc + /// + + // empty block comment + /**/ + + pub mod dummy_item {} + + // empty 2-asterisk block isn't a doc block, it is a block comment + /***/ + + } + + /* The next one isn't allowed because outer doc comments + require an item that will receive the doc */ + + /// Where is my item? +} +".to_string(); + let (output, len) = make_test(input, None, false, &opts, None); + assert_eq!((output, len), (expected, 0)); +} \ No newline at end of file From 49f1e9cd8d31b65416408f4975feb5eded4d6158 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 27 Mar 2025 14:43:11 +0100 Subject: [PATCH 606/745] Remove recursion in `check_item` --- src/librustdoc/doctest/make.rs | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index 93be35200060..55b57292b33a 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -342,12 +342,7 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result, - is_top_level: bool, - ) -> bool { + fn check_item(item: &ast::Item, info: &mut ParseSourceInfo, crate_name: &Option<&str>) -> bool { let mut is_extern_crate = false; if !info.has_global_allocator && item.attrs.iter().any(|attr| attr.name_or_empty() == sym::global_allocator) @@ -355,19 +350,12 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result { + ast::ItemKind::Fn(_) if !info.has_main_fn => { // We only push if it's the top item because otherwise, we would duplicate // its content since the top-level item was already added. - if item.ident.name == sym::main && is_top_level { + if item.ident.name == sym::main { info.has_main_fn = true; } - if let Some(ref body) = fn_item.body { - for stmt in &body.stmts { - if let StmtKind::Item(ref item) = stmt.kind { - is_extern_crate |= check_item(item, info, crate_name, false); - } - } - } } ast::ItemKind::ExternCrate(original) => { is_extern_crate = true; @@ -427,7 +415,7 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result { - is_extern_crate = check_item(&item, &mut info, crate_name, true); + is_extern_crate = check_item(&item, &mut info, crate_name); } StmtKind::Expr(ref expr) if matches!(expr.kind, ast::ExprKind::Err(_)) => { reset_error_count(&psess); From 77eb97d9a983f213cff1df7e02a4a96273653482 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Thu, 27 Mar 2025 11:59:04 -0400 Subject: [PATCH 607/745] librustdoc: also stabilize iteration order here --- src/librustdoc/html/markdown.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index b067dbf750e7..7606128e9e88 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -1726,6 +1726,7 @@ pub(crate) fn markdown_links<'md, R>( md: &'md str, preprocess_link: impl Fn(MarkdownLink) -> Option, ) -> Vec { + use itertools::Itertools; if md.is_empty() { return vec![]; } @@ -1884,7 +1885,7 @@ pub(crate) fn markdown_links<'md, R>( let mut links = Vec::new(); let mut refdefs = FxIndexMap::default(); - for (label, refdef) in event_iter.reference_definitions().iter() { + for (label, refdef) in event_iter.reference_definitions().iter().sorted_by_key(|x| x.0) { refdefs.insert(label.to_string(), (false, refdef.dest.to_string(), refdef.span.clone())); } From 27cca0a161ff913852f8344636e17489ef37672b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 27 Mar 2025 11:36:29 +0100 Subject: [PATCH 608/745] Add CI metadata to bootstrap metrics This will allow us to provide links to CI workflows, jobs and summaries in the post-merge analysis report. --- .github/workflows/ci.yml | 2 ++ src/bootstrap/src/utils/metrics.rs | 22 +++++++++++++++++++--- src/build_helper/src/metrics.rs | 13 +++++++++++++ src/ci/citool/src/analysis.rs | 4 ++-- src/ci/docker/run.sh | 2 ++ 5 files changed, 38 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 25397006ee23..51dd0f81ed14 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,6 +69,8 @@ jobs: env: CI_JOB_NAME: ${{ matrix.name }} CI_JOB_DOC_URL: ${{ matrix.doc_url }} + GITHUB_WORKFLOW_RUN_ID: ${{ github.run_id }} + GITHUB_REPOSITORY: ${{ github.repository }} CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse # commit of PR sha or commit sha. `GITHUB_SHA` is not accurate for PRs. HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }} diff --git a/src/bootstrap/src/utils/metrics.rs b/src/bootstrap/src/utils/metrics.rs index 885fff9c32c5..862c44496241 100644 --- a/src/bootstrap/src/utils/metrics.rs +++ b/src/bootstrap/src/utils/metrics.rs @@ -9,9 +9,10 @@ use std::fs::File; use std::io::BufWriter; use std::time::{Duration, Instant, SystemTime}; +use build_helper::ci::CiEnv; use build_helper::metrics::{ - JsonInvocation, JsonInvocationSystemStats, JsonNode, JsonRoot, JsonStepSystemStats, Test, - TestOutcome, TestSuite, TestSuiteMetadata, + CiMetadata, JsonInvocation, JsonInvocationSystemStats, JsonNode, JsonRoot, JsonStepSystemStats, + Test, TestOutcome, TestSuite, TestSuiteMetadata, }; use sysinfo::{CpuRefreshKind, RefreshKind, System}; @@ -217,7 +218,12 @@ impl BuildMetrics { children: steps.into_iter().map(|step| self.prepare_json_step(step)).collect(), }); - let json = JsonRoot { format_version: CURRENT_FORMAT_VERSION, system_stats, invocations }; + let json = JsonRoot { + format_version: CURRENT_FORMAT_VERSION, + system_stats, + invocations, + ci_metadata: get_ci_metadata(CiEnv::current()), + }; t!(std::fs::create_dir_all(dest.parent().unwrap())); let mut file = BufWriter::new(t!(File::create(&dest))); @@ -245,6 +251,16 @@ impl BuildMetrics { } } +fn get_ci_metadata(ci_env: CiEnv) -> Option { + if ci_env != CiEnv::GitHubActions { + return None; + } + let workflow_run_id = + std::env::var("GITHUB_WORKFLOW_RUN_ID").ok().and_then(|id| id.parse::().ok())?; + let repository = std::env::var("GITHUB_REPOSITORY").ok()?; + Some(CiMetadata { workflow_run_id, repository }) +} + struct MetricsState { finished_steps: Vec, running_steps: Vec, diff --git a/src/build_helper/src/metrics.rs b/src/build_helper/src/metrics.rs index fdff9cd18cea..8b82e62a3277 100644 --- a/src/build_helper/src/metrics.rs +++ b/src/build_helper/src/metrics.rs @@ -9,6 +9,19 @@ pub struct JsonRoot { pub format_version: usize, pub system_stats: JsonInvocationSystemStats, pub invocations: Vec, + #[serde(default)] + pub ci_metadata: Option, +} + +/// Represents metadata about bootstrap's execution in CI. +#[derive(Serialize, Deserialize)] +pub struct CiMetadata { + /// GitHub run ID of the workflow where bootstrap was executed. + /// Note that the run ID will be shared amongst all jobs executed in that workflow. + pub workflow_run_id: u64, + /// Full name of a GitHub repository where bootstrap was executed in CI. + /// e.g. `rust-lang-ci/rust`. + pub repository: String, } #[derive(Serialize, Deserialize)] diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 2e1ede126dc3..7fbfad467c64 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -1,11 +1,11 @@ +use std::collections::{BTreeMap, HashMap, HashSet}; use std::fmt::Debug; +use std::time::Duration; use build_helper::metrics::{ BuildStep, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, escape_step_name, format_build_steps, }; -use std::collections::{BTreeMap, HashMap, HashSet}; -use std::time::Duration; use crate::metrics; use crate::metrics::{JobMetrics, JobName, get_test_suites}; diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 2805bb1118d8..00d791eeb6b3 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -355,6 +355,8 @@ docker \ --env GITHUB_ACTIONS \ --env GITHUB_REF \ --env GITHUB_STEP_SUMMARY="/checkout/obj/${SUMMARY_FILE}" \ + --env GITHUB_WORKFLOW_RUN_ID \ + --env GITHUB_REPOSITORY \ --env RUST_BACKTRACE \ --env TOOLSTATE_REPO_ACCESS_TOKEN \ --env TOOLSTATE_REPO \ From eaa0613e8d767ca7b6527a79e9bdf90e84bb17fa Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Wed, 26 Mar 2025 18:12:21 +0530 Subject: [PATCH 609/745] feat(config): Add ChangeId enum for suppressing warnings Introduces the `ChangeId` enum to allow suppressing `change_id` warnings. Now, `ChangeId` supports both numeric values and the string literal `"ignore"`. Numeric values behave as expected, while `"ignore"` is used to suppress warning messages. --- src/bootstrap/src/bin/main.rs | 90 +++++++++++++------------ src/bootstrap/src/core/config/config.rs | 31 +++++++-- src/bootstrap/src/core/config/tests.rs | 5 +- src/bootstrap/src/lib.rs | 2 +- 4 files changed, 75 insertions(+), 53 deletions(-) diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index 443131dc7f3c..5df9902a9778 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -11,8 +11,8 @@ use std::str::FromStr; use std::{env, process}; use bootstrap::{ - Build, CONFIG_CHANGE_HISTORY, Config, Flags, Subcommand, debug, find_recent_config_change_ids, - human_readable_changes, t, + Build, CONFIG_CHANGE_HISTORY, ChangeId, Config, Flags, Subcommand, debug, + find_recent_config_change_ids, human_readable_changes, t, }; #[cfg(feature = "tracing")] use tracing::instrument; @@ -155,51 +155,53 @@ fn check_version(config: &Config) -> Option { let latest_change_id = CONFIG_CHANGE_HISTORY.last().unwrap().change_id; let warned_id_path = config.out.join("bootstrap").join(".last-warned-change-id"); - if let Some(mut id) = config.change_id { - if id == latest_change_id { - return None; + let mut id = match config.change_id { + Some(ChangeId::Id(id)) if id == latest_change_id => return None, + Some(ChangeId::Ignore) => return None, + Some(ChangeId::Id(id)) => id, + None => { + msg.push_str("WARNING: The `change-id` is missing in the `bootstrap.toml`. This means that you will not be able to track the major changes made to the bootstrap configurations.\n"); + msg.push_str("NOTE: to silence this warning, "); + msg.push_str(&format!( + "add `change-id = {latest_change_id}` at the top of `bootstrap.toml`" + )); + return Some(msg); } - - // Always try to use `change-id` from .last-warned-change-id first. If it doesn't exist, - // then use the one from the bootstrap.toml. This way we never show the same warnings - // more than once. - if let Ok(t) = fs::read_to_string(&warned_id_path) { - let last_warned_id = usize::from_str(&t) - .unwrap_or_else(|_| panic!("{} is corrupted.", warned_id_path.display())); - - // We only use the last_warned_id if it exists in `CONFIG_CHANGE_HISTORY`. - // Otherwise, we may retrieve all the changes if it's not the highest value. - // For better understanding, refer to `change_tracker::find_recent_config_change_ids`. - if CONFIG_CHANGE_HISTORY.iter().any(|config| config.change_id == last_warned_id) { - id = last_warned_id; - } - }; - - let changes = find_recent_config_change_ids(id); - - if changes.is_empty() { - return None; - } - - msg.push_str("There have been changes to x.py since you last updated:\n"); - msg.push_str(&human_readable_changes(&changes)); - - msg.push_str("NOTE: to silence this warning, "); - msg.push_str(&format!( - "update `bootstrap.toml` to use `change-id = {latest_change_id}` instead" - )); - - if io::stdout().is_terminal() { - t!(fs::write(warned_id_path, latest_change_id.to_string())); - } - } else { - msg.push_str("WARNING: The `change-id` is missing in the `bootstrap.toml`. This means that you will not be able to track the major changes made to the bootstrap configurations.\n"); - msg.push_str("NOTE: to silence this warning, "); - msg.push_str(&format!( - "add `change-id = {latest_change_id}` at the top of `bootstrap.toml`" - )); }; + // Always try to use `change-id` from .last-warned-change-id first. If it doesn't exist, + // then use the one from the bootstrap.toml. This way we never show the same warnings + // more than once. + if let Ok(t) = fs::read_to_string(&warned_id_path) { + let last_warned_id = usize::from_str(&t) + .unwrap_or_else(|_| panic!("{} is corrupted.", warned_id_path.display())); + + // We only use the last_warned_id if it exists in `CONFIG_CHANGE_HISTORY`. + // Otherwise, we may retrieve all the changes if it's not the highest value. + // For better understanding, refer to `change_tracker::find_recent_config_change_ids`. + if CONFIG_CHANGE_HISTORY.iter().any(|config| config.change_id == last_warned_id) { + id = last_warned_id; + } + }; + + let changes = find_recent_config_change_ids(id); + + if changes.is_empty() { + return None; + } + + msg.push_str("There have been changes to x.py since you last updated:\n"); + msg.push_str(&human_readable_changes(&changes)); + + msg.push_str("NOTE: to silence this warning, "); + msg.push_str(&format!( + "update `bootstrap.toml` to use `change-id = {latest_change_id}` instead" + )); + + if io::stdout().is_terminal() { + t!(fs::write(warned_id_path, latest_change_id.to_string())); + } + Some(msg) } diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index cf4ef4ee310d..96316d4d0fdb 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -193,7 +193,7 @@ pub enum GccCiMode { /// `bootstrap.example.toml`. #[derive(Default, Clone)] pub struct Config { - pub change_id: Option, + pub change_id: Option, pub bypass_bootstrap_lock: bool, pub ccache: Option, /// Call Build::ninja() instead of this. @@ -700,14 +700,32 @@ pub(crate) struct TomlConfig { profile: Option, } +/// This enum is used for deserializing change IDs from TOML, allowing both numeric values and the string `"ignore"`. +#[derive(Clone, Debug, PartialEq)] +pub enum ChangeId { + Ignore, + Id(usize), +} + /// Since we use `#[serde(deny_unknown_fields)]` on `TomlConfig`, we need a wrapper type /// for the "change-id" field to parse it even if other fields are invalid. This ensures /// that if deserialization fails due to other fields, we can still provide the changelogs /// to allow developers to potentially find the reason for the failure in the logs.. #[derive(Deserialize, Default)] pub(crate) struct ChangeIdWrapper { - #[serde(alias = "change-id")] - pub(crate) inner: Option, + #[serde(alias = "change-id", default, deserialize_with = "deserialize_change_id")] + pub(crate) inner: Option, +} + +fn deserialize_change_id<'de, D: Deserializer<'de>>( + deserializer: D, +) -> Result, D::Error> { + let value = toml::Value::deserialize(deserializer)?; + Ok(match value { + toml::Value::String(s) if s == "ignore" => Some(ChangeId::Ignore), + toml::Value::Integer(i) => Some(ChangeId::Id(i as usize)), + _ => return Err(serde::de::Error::custom("expected \"ignore\" or an integer")), + }) } /// Describes how to handle conflicts in merging two [`TomlConfig`] @@ -1351,10 +1369,11 @@ impl Config { toml::from_str(&contents) .and_then(|table: toml::Value| TomlConfig::deserialize(table)) .inspect_err(|_| { - if let Ok(Some(changes)) = toml::from_str(&contents) - .and_then(|table: toml::Value| ChangeIdWrapper::deserialize(table)) - .map(|change_id| change_id.inner.map(crate::find_recent_config_change_ids)) + if let Ok(ChangeIdWrapper { inner: Some(ChangeId::Id(id)) }) = + toml::from_str::(&contents) + .and_then(|table: toml::Value| ChangeIdWrapper::deserialize(table)) { + let changes = crate::find_recent_config_change_ids(id); if !changes.is_empty() { println!( "WARNING: There have been changes to x.py since you last updated:\n{}", diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index 068e237c2cdc..ac36910c4e05 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -10,6 +10,7 @@ use serde::Deserialize; use super::flags::Flags; use super::{ChangeIdWrapper, Config, RUSTC_IF_UNCHANGED_ALLOWED_PATHS}; +use crate::ChangeId; use crate::core::build_steps::clippy::{LintConfig, get_clippy_rules_in_order}; use crate::core::build_steps::llvm; use crate::core::build_steps::llvm::LLVM_INVALIDATION_PATHS; @@ -171,7 +172,7 @@ runner = "x86_64-runner" ) }, ); - assert_eq!(config.change_id, Some(1), "setting top-level value"); + assert_eq!(config.change_id, Some(ChangeId::Id(1)), "setting top-level value"); assert_eq!( config.rust_lto, crate::core::config::RustcLto::Fat, @@ -311,7 +312,7 @@ fn parse_change_id_with_unknown_field() { "#; let change_id_wrapper: ChangeIdWrapper = toml::from_str(config).unwrap(); - assert_eq!(change_id_wrapper.inner, Some(3461)); + assert_eq!(change_id_wrapper.inner, Some(ChangeId::Id(3461))); } #[test] diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index c47cd8b452f9..843d474f92de 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -45,8 +45,8 @@ mod core; mod utils; pub use core::builder::PathSet; -pub use core::config::Config; pub use core::config::flags::{Flags, Subcommand}; +pub use core::config::{ChangeId, Config}; #[cfg(feature = "tracing")] use tracing::{instrument, span}; From 02444322c0ee0362ae01c35da5495c75232e72da Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Wed, 26 Mar 2025 18:25:47 +0530 Subject: [PATCH 610/745] add changeInfo to change tracker --- src/bootstrap/src/utils/change_tracker.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 1a101b02f709..78887a42a000 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -390,4 +390,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Warning, summary: "The default configuration filename has changed from `config.toml` to `bootstrap.toml`. `config.toml` is deprecated but remains supported for backward compatibility.", }, + ChangeInfo { + change_id: 138986, + severity: ChangeSeverity::Info, + summary: "You can now use `change_id = \"ignore\"` to suppress `change_id` warnings in the console.", + }, ]; From 1437dec79942f1367b4cc7756e2f080261c34f3a Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Thu, 27 Mar 2025 12:39:48 -0400 Subject: [PATCH 611/745] rustc_resolve: prevent iteration of refids for completeness This came up in review, and it should help some future author not introduce non-deterministic output here. --- compiler/rustc_resolve/src/rustdoc.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index 9fda1eb4dc45..a32fe6990160 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -8,7 +8,8 @@ use pulldown_cmark::{ use rustc_ast as ast; use rustc_ast::attr::AttributeExt; use rustc_ast::util::comments::beautify_doc_string; -use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; +use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::unord::UnordSet; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::DefId; use rustc_span::{DUMMY_SP, InnerSpan, Span, Symbol, kw, sym}; @@ -423,7 +424,7 @@ fn parse_links<'md>(doc: &'md str) -> Vec> { ); let mut links = Vec::new(); - let mut refids = FxHashSet::default(); + let mut refids = UnordSet::default(); while let Some(event) = event_iter.next() { match event { From 5d274408d4b8b845f490912dcdadcc717f18fcca Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 27 Mar 2025 17:43:29 +0100 Subject: [PATCH 612/745] Only take outer attributes into account when generating content between first non-crate items and the crate items --- src/librustdoc/doctest/make.rs | 8 +- src/librustdoc/doctest/tests.rs | 131 ++++---------------------------- 2 files changed, 19 insertions(+), 120 deletions(-) diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index 55b57292b33a..56b1e76ae8cf 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -7,7 +7,7 @@ use std::sync::Arc; use rustc_ast::token::{Delimiter, TokenKind}; use rustc_ast::tokenstream::TokenTree; -use rustc_ast::{self as ast, HasAttrs, StmtKind}; +use rustc_ast::{self as ast, AttrStyle, HasAttrs, StmtKind}; use rustc_errors::ColorConfig; use rustc_errors::emitter::stderr_destination; use rustc_parse::new_parser_from_source_str; @@ -388,7 +388,7 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result) -> Result Date: Thu, 27 Mar 2025 17:44:43 +0000 Subject: [PATCH 613/745] Do not trim paths in MIR validator --- compiler/rustc_mir_transform/src/validate.rs | 9 ++++- tests/ui/mir/inline-causes-trimmed-paths.rs | 36 ++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 tests/ui/mir/inline-causes-trimmed-paths.rs diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 231d7c2ef022..ae7aef08fe61 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -12,6 +12,7 @@ use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::adjustment::PointerCoercion; +use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{ self, CoroutineArgsExt, InstanceKind, ScalarInt, Ty, TyCtxt, TypeVisitableExt, Upcast, Variance, }; @@ -543,7 +544,13 @@ pub(super) fn validate_types<'tcx>( caller_body: &Body<'tcx>, ) -> Vec<(Location, String)> { let mut type_checker = TypeChecker { body, caller_body, tcx, typing_env, failures: Vec::new() }; - type_checker.visit_body(body); + // The type checker formats a bunch of strings with type names in it, but these strings + // are not always going to be encountered on the error path since the inliner also uses + // the validator, and there are certain kinds of inlining (even for valid code) that + // can cause validation errors (mostly around where clauses and rigid projections). + with_no_trimmed_paths!({ + type_checker.visit_body(body); + }); type_checker.failures } diff --git a/tests/ui/mir/inline-causes-trimmed-paths.rs b/tests/ui/mir/inline-causes-trimmed-paths.rs new file mode 100644 index 000000000000..d626ab4e1d9c --- /dev/null +++ b/tests/ui/mir/inline-causes-trimmed-paths.rs @@ -0,0 +1,36 @@ +//@ build-pass +//@ compile-flags: -Zinline-mir + +trait Storage { + type Buffer: ?Sized; +} + +struct Array; +impl Storage for Array { + type Buffer = [(); N]; +} + +struct Slice; +impl Storage for Slice { + type Buffer = [()]; +} + +struct Wrap { + _b: S::Buffer, +} + +fn coerce(this: &Wrap>) -> &Wrap +where + Array: Storage, +{ + coerce_again(this) +} + +fn coerce_again(this: &Wrap>) -> &Wrap { + this +} + +fn main() { + let inner: Wrap> = Wrap { _b: [(); 1] }; + let _: &Wrap = coerce(&inner); +} From ed0a7988282e5bac6080197fb7a920c35e300ac3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 27 Mar 2025 17:45:18 +0000 Subject: [PATCH 614/745] Drive-by get rid of a bunch of unnecessary :? --- compiler/rustc_mir_transform/src/validate.rs | 48 ++++++++++---------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index ae7aef08fe61..e7930f0a1e3f 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -57,7 +57,7 @@ impl<'tcx> crate::MirPass<'tcx> for Validator { ty::Coroutine(..) => ExternAbi::Rust, // No need to do MIR validation on error bodies ty::Error(_) => return, - _ => span_bug!(body.span, "unexpected body ty: {body_ty:?}"), + _ => span_bug!(body.span, "unexpected body ty: {body_ty}"), }; ty::layout::fn_can_unwind(tcx, Some(def_id), body_abi) @@ -662,7 +662,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ProjectionElem::Index(index) => { let index_ty = self.body.local_decls[index].ty; if index_ty != self.tcx.types.usize { - self.fail(location, format!("bad index ({index_ty:?} != usize)")) + self.fail(location, format!("bad index ({index_ty} != usize)")) } } ProjectionElem::Deref @@ -671,10 +671,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { let base_ty = place_ref.ty(&self.body.local_decls, self.tcx).ty; if base_ty.is_box() { - self.fail( - location, - format!("{base_ty:?} dereferenced after ElaborateBoxDerefs"), - ) + self.fail(location, format!("{base_ty} dereferenced after ElaborateBoxDerefs")) } } ProjectionElem::Field(f, ty) => { @@ -687,7 +684,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { this.fail( location, format!( - "Field projection `{place_ref:?}.{f:?}` specified type `{ty:?}`, but actual type is `{f_ty:?}`" + "Field projection `{place_ref:?}.{f:?}` specified type `{ty}`, but actual type is `{f_ty}`" ) ) } @@ -813,7 +810,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { self.fail( location, format!( - "Failed subtyping {ty:#?} and {:#?}", + "Failed subtyping {ty} and {}", place_ref.ty(&self.body.local_decls, self.tcx).ty ), ) @@ -833,7 +830,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { self.fail( location, format!( - "Cannot unwrap unsafe binder {binder_ty:?} into type {unwrapped_ty:?}" + "Cannot unwrap unsafe binder {binder_ty:?} into type {unwrapped_ty}" ), ); } @@ -848,7 +845,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if ty.is_union() || ty.is_enum() { self.fail( START_BLOCK.start_location(), - format!("invalid type {ty:?} in debuginfo for {:?}", debuginfo.name), + format!("invalid type {ty} in debuginfo for {:?}", debuginfo.name), ); } if projection.is_empty() { @@ -1071,15 +1068,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if !self.mir_assign_valid_types(a, b) { self.fail( location, - format!("Cannot {op:?} compare incompatible types {a:?} and {b:?}"), + format!("Cannot {op:?} compare incompatible types {a} and {b}"), ); } } else if a != b { self.fail( location, - format!( - "Cannot perform binary op {op:?} on unequal types {a:?} and {b:?}" - ), + format!("Cannot perform binary op {op:?} on unequal types {a} and {b}"), ); } } @@ -1088,7 +1083,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { Offset => { check_kinds!(a, "Cannot offset non-pointer type {:?}", ty::RawPtr(..)); if b != self.tcx.types.isize && b != self.tcx.types.usize { - self.fail(location, format!("Cannot offset by non-isize type {b:?}")); + self.fail(location, format!("Cannot offset by non-isize type {b}")); } } Eq | Lt | Le | Ne | Ge | Gt => { @@ -1320,7 +1315,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { { self.fail( location, - format!("Cannot transmute from non-`Sized` type {op_ty:?}"), + format!("Cannot transmute from non-`Sized` type {op_ty}"), ); } if !self @@ -1347,7 +1342,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } Rvalue::NullaryOp(NullOp::OffsetOf(indices), container) => { let fail_out_of_bounds = |this: &mut Self, location, field, ty| { - this.fail(location, format!("Out of bounds field {field:?} for {ty:?}")); + this.fail(location, format!("Out of bounds field {field:?} for {ty}")); }; let mut current_ty = *container; @@ -1381,7 +1376,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { _ => { self.fail( location, - format!("Cannot get offset ({variant:?}, {field:?}) from type {current_ty:?}"), + format!("Cannot get offset ({variant:?}, {field:?}) from type {current_ty}"), ); return; } @@ -1410,7 +1405,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if !self.mir_assign_valid_types(unwrapped_ty, binder_inner_ty) { self.fail( location, - format!("Cannot wrap {unwrapped_ty:?} into unsafe binder {binder_ty:?}"), + format!("Cannot wrap {unwrapped_ty} into unsafe binder {binder_ty:?}"), ); } } @@ -1496,24 +1491,27 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { // since CopyNonOverlapping is parametrized by 1 type, // we only need to check that they are equal and not keep an extra parameter. if !self.mir_assign_valid_types(op_src_ty, op_dst_ty) { - self.fail(location, format!("bad arg ({op_src_ty:?} != {op_dst_ty:?})")); + self.fail(location, format!("bad arg ({op_src_ty} != {op_dst_ty})")); } let op_cnt_ty = count.ty(&self.body.local_decls, self.tcx); if op_cnt_ty != self.tcx.types.usize { - self.fail(location, format!("bad arg ({op_cnt_ty:?} != usize)")) + self.fail(location, format!("bad arg ({op_cnt_ty} != usize)")) } } StatementKind::SetDiscriminant { place, .. } => { if self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) { self.fail(location, "`SetDiscriminant`is not allowed until deaggregation"); } - let pty = place.ty(&self.body.local_decls, self.tcx).ty.kind(); - if !matches!(pty, ty::Adt(..) | ty::Coroutine(..) | ty::Alias(ty::Opaque, ..)) { + let pty = place.ty(&self.body.local_decls, self.tcx).ty; + if !matches!( + pty.kind(), + ty::Adt(..) | ty::Coroutine(..) | ty::Alias(ty::Opaque, ..) + ) { self.fail( location, format!( - "`SetDiscriminant` is only allowed on ADTs and coroutines, not {pty:?}" + "`SetDiscriminant` is only allowed on ADTs and coroutines, not {pty}" ), ); } @@ -1562,7 +1560,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if ScalarInt::try_from_uint(value, size).is_none() { self.fail( location, - format!("the value {value:#x} is not a proper {switch_ty:?}"), + format!("the value {value:#x} is not a proper {switch_ty}"), ) } } From bec69704c0ee6b3c6b1854b104b964fc17d8c36f Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Thu, 27 Mar 2025 18:29:06 +0000 Subject: [PATCH 615/745] Use `abs_diff` where applicable --- compiler/rustc_errors/src/snippet.rs | 6 +----- compiler/rustc_span/src/edit_distance.rs | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_errors/src/snippet.rs b/compiler/rustc_errors/src/snippet.rs index 8485d7087cfc..f09c2ed5534a 100644 --- a/compiler/rustc_errors/src/snippet.rs +++ b/compiler/rustc_errors/src/snippet.rs @@ -159,11 +159,7 @@ impl Annotation { /// Length of this annotation as displayed in the stderr output pub(crate) fn len(&self) -> usize { // Account for usize underflows - if self.end_col.display > self.start_col.display { - self.end_col.display - self.start_col.display - } else { - self.start_col.display - self.end_col.display - } + self.end_col.display.abs_diff(self.start_col.display) } pub(crate) fn has_label(&self) -> bool { diff --git a/compiler/rustc_span/src/edit_distance.rs b/compiler/rustc_span/src/edit_distance.rs index 8a2baaa42e2a..4f3202b694c1 100644 --- a/compiler/rustc_span/src/edit_distance.rs +++ b/compiler/rustc_span/src/edit_distance.rs @@ -118,7 +118,7 @@ pub fn edit_distance_with_substrings(a: &str, b: &str, limit: usize) -> Option Date: Thu, 27 Mar 2025 15:40:03 -0400 Subject: [PATCH 616/745] saethlin goes on vacation --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index ebbcfa4516b9..7e1e1bc57716 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1098,6 +1098,7 @@ contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" users_on_vacation = [ "jyn514", "ChrisDenton", + "saethlin", ] [[assign.warn_non_default_branch.exceptions]] From 65624d9ea5c2aee3f3c7729f3b8d72c0920df6e6 Mon Sep 17 00:00:00 2001 From: binarycat Date: Wed, 26 Mar 2025 20:32:14 -0500 Subject: [PATCH 617/745] tester.js: ignore displayTypeSignature if it is null --- src/tools/rustdoc-js/tester.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index ea575f27799a..f70fc917770c 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -451,7 +451,7 @@ function loadSearchJS(doc_folder, resource_suffix) { if (!Object.prototype.hasOwnProperty.call(entry, key)) { continue; } - if (key === "displayTypeSignature") { + if (key === "displayTypeSignature" && entry.displayTypeSignature !== null) { const {type, mappedNames, whereClause} = await entry.displayTypeSignature; entry.displayType = arrayToCode(type); From 4924e0a067946d7b810dcc777ffd8370c29da80a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 26 Mar 2025 15:51:41 +1100 Subject: [PATCH 618/745] Add a HIR pretty-printing test focused on lifetimes. HIR printing currently gets very little testing. This increases coverage a bit, with a focus on lifetimes. There are some FIXME comments for cases that are printed in a dubious fashion. This PR won't address those; the point of adding this test is to ensure that the subsequent commits don't hurt pretty-printing. --- tests/pretty/hir-lifetimes.pp | 96 +++++++++++++++++++++++++++++++++++ tests/pretty/hir-lifetimes.rs | 91 +++++++++++++++++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100644 tests/pretty/hir-lifetimes.pp create mode 100644 tests/pretty/hir-lifetimes.rs diff --git a/tests/pretty/hir-lifetimes.pp b/tests/pretty/hir-lifetimes.pp new file mode 100644 index 000000000000..df3aba516b9c --- /dev/null +++ b/tests/pretty/hir-lifetimes.pp @@ -0,0 +1,96 @@ +//@ pretty-compare-only +//@ pretty-mode:hir +//@ pp-exact:hir-lifetimes.pp + +// This tests the pretty-printing of lifetimes in lots of ways. + +#![allow(unused)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +struct Foo<'a> { + x: &'a u32, +} + +impl <'a> Foo<'a> { + fn f<'b>(x: &'b u32) { } +} + +impl Foo<'_> { + fn a(x: &'_ u32) { } + + fn b(x: &'_ u32) { } + + fn c(x: &'_ u32, y: &'static u32) { } + + // FIXME: `'a` before `self` is omitted + fn d<'a>(&self, x: &'a u32) { } + + // FIXME: impl Traits printed as just `/*impl Trait*/`, ugh + fn iter1<'a>(&self) + -> /*impl Trait*/ { #[lang = "Range"]{ start: 0, end: 1,} } + + fn iter2(&self) + -> /*impl Trait*/ { #[lang = "Range"]{ start: 0, end: 1,} } +} + +fn a(x: Foo<'_>) { } + +fn b<'a>(x: Foo<'a>) { } + +struct Bar<'a, 'b, 'c, T> { + x: &'a u32, + y: &'b &'c u32, + z: T, +} + +fn f1<'a, 'b, T>(x: Bar<'a, 'b, '_, T>) { } + +fn f2(x: Bar<'_, '_, '_, u32>) { } + +trait MyTrait<'a, 'b> { + fn f(&self, x: Foo<'a>, y: Foo<'b>); +} + +impl <'a, 'b, 'c, T> MyTrait<'a, 'b> for Bar<'a, 'b, 'c, T> { + fn f(&self, x: Foo<'a>, y: Foo<'b>) { } +} + +fn g(x: &'_ dyn for<'a, 'b> MyTrait<'a, 'b>) { } + +trait Blah { } + +type T<'a> = dyn Blah + 'a; + +type Q<'a> = dyn MyTrait<'a, 'a> + 'a; + +fn h<'b, F>(f: F, y: Foo<'b>) where F: for<'d> MyTrait<'d, 'b> { } + +// FIXME(?): attr printing is weird +#[attr = Repr([ReprC])] +struct S<'a>(&'a u32); + +extern "C" { + unsafe fn g1(s: S<>); + unsafe fn g2(s: S<'_>); + unsafe fn g3<'a>(s: S<'a>); +} + +struct St<'a> { + x: &'a u32, +} + +fn f() { { let _ = St{ x: &0,}; }; { let _ = St{ x: &0,}; }; } + +struct Name<'a>(&'a str); + +const A: Name<> = Name("a"); +const B: &'_ str = ""; +static C: &'_ str = ""; +static D: &'static str = ""; + +fn tr(_: Box) { } + +fn main() { } diff --git a/tests/pretty/hir-lifetimes.rs b/tests/pretty/hir-lifetimes.rs new file mode 100644 index 000000000000..1379be343924 --- /dev/null +++ b/tests/pretty/hir-lifetimes.rs @@ -0,0 +1,91 @@ +//@ pretty-compare-only +//@ pretty-mode:hir +//@ pp-exact:hir-lifetimes.pp + +// This tests the pretty-printing of lifetimes in lots of ways. + +#![allow(unused)] + +struct Foo<'a> { + x: &'a u32, +} + +impl<'a> Foo<'a> { + fn f<'b>(x: &'b u32) {} +} + +impl Foo<'_> { + fn a(x: &u32) {} + + fn b(x: &'_ u32) {} + + fn c(x: &'_ u32, y: &'static u32) {} + + // FIXME: `'a` before `self` is omitted + fn d<'a>(&'a self, x: &'a u32) {} + + // FIXME: impl Traits printed as just `/*impl Trait*/`, ugh + fn iter1<'a>(&self) -> impl Iterator + 'a { 0..1 } + + fn iter2(&self) -> impl Iterator + '_ { 0..1 } +} + +fn a(x: Foo<'_>) {} + +fn b<'a>(x: Foo<'a>) {} + +struct Bar<'a, 'b, 'c, T> { + x: &'a u32, + y: &'b &'c u32, + z: T, +} + +fn f1<'a, 'b, T>(x: Bar<'a, 'b, '_, T>) {} + +fn f2(x: Bar<'_, '_, '_, u32>) {} + +trait MyTrait<'a, 'b> { + fn f(&self, x: Foo<'a>, y: Foo<'b>); +} + +impl<'a, 'b, 'c, T> MyTrait<'a, 'b> for Bar<'a, 'b, 'c, T> { + fn f(&self, x: Foo<'a>, y: Foo<'b>) {} +} + +fn g(x: &dyn for<'a, 'b> MyTrait<'a, 'b>) {} + +trait Blah {} + +type T<'a> = dyn Blah + 'a; + +type Q<'a> = dyn MyTrait<'a, 'a> + 'a; + +fn h<'b, F>(f: F, y: Foo<'b>) where F: for<'d> MyTrait<'d, 'b> {} + +// FIXME(?): attr printing is weird +#[repr(C)] +struct S<'a>(&'a u32); + +extern "C" { + fn g1(s: S); + fn g2(s: S<'_>); + fn g3<'a>(s: S<'a>); +} + +struct St<'a> { x: &'a u32 } + +fn f() { + _ = St { x: &0 }; + _ = St::<'_> { x: &0 }; +} + +struct Name<'a>(&'a str); + +const A: Name = Name("a"); +const B: &str = ""; +static C: &'_ str = ""; +static D: &'static str = ""; + +fn tr(_: Box) {} + +fn main() {} From c6d8d654962768e349b4ed1c80f2e7418b10a092 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Mar 2025 08:56:33 +1100 Subject: [PATCH 619/745] Remove `LifetimeSuggestionPosition` and `Lifetime::suggestion_position`. They both are only used in `Lifetime::suggestion`. This commit inlines and removes them. --- compiler/rustc_hir/src/hir.rs | 57 ++++++++++++----------------------- 1 file changed, 19 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 751c379b21a6..b91fb41cb4d6 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -139,19 +139,6 @@ impl fmt::Display for Lifetime { } } -pub enum LifetimeSuggestionPosition { - /// The user wrote `'a` or `'_`. - Normal, - /// The user wrote `&type` or `&mut type`. - Ampersand, - /// The user wrote `Path` and omitted the `<'_>`. - ElidedPath, - /// The user wrote `Path`, and omitted the `'_,`. - ElidedPathArgument, - /// The user wrote `dyn Trait` and omitted the `+ '_`. - ObjectDefault, -} - impl Lifetime { pub fn is_elided(&self) -> bool { self.res.is_elided() @@ -161,33 +148,27 @@ impl Lifetime { self.ident.name == kw::Empty || self.ident.name == kw::UnderscoreLifetime } - pub fn suggestion_position(&self) -> (LifetimeSuggestionPosition, Span) { - if self.ident.name == kw::Empty { - if self.ident.span.is_empty() { - (LifetimeSuggestionPosition::ElidedPathArgument, self.ident.span) - } else { - (LifetimeSuggestionPosition::ElidedPath, self.ident.span.shrink_to_hi()) - } - } else if self.res == LifetimeName::ImplicitObjectLifetimeDefault { - (LifetimeSuggestionPosition::ObjectDefault, self.ident.span) - } else if self.ident.span.is_empty() { - (LifetimeSuggestionPosition::Ampersand, self.ident.span) - } else { - (LifetimeSuggestionPosition::Normal, self.ident.span) - } - } - pub fn suggestion(&self, new_lifetime: &str) -> (Span, String) { debug_assert!(new_lifetime.starts_with('\'')); - let (pos, span) = self.suggestion_position(); - let code = match pos { - LifetimeSuggestionPosition::Normal => format!("{new_lifetime}"), - LifetimeSuggestionPosition::Ampersand => format!("{new_lifetime} "), - LifetimeSuggestionPosition::ElidedPath => format!("<{new_lifetime}>"), - LifetimeSuggestionPosition::ElidedPathArgument => format!("{new_lifetime}, "), - LifetimeSuggestionPosition::ObjectDefault => format!("+ {new_lifetime}"), - }; - (span, code) + + if self.ident.name == kw::Empty { + if self.ident.span.is_empty() { + // The user wrote `Path`, and omitted the `'_,`. + (self.ident.span, format!("{new_lifetime}, ")) + } else { + // The user wrote `Path` and omitted the `<'_>`. + (self.ident.span.shrink_to_hi(), format!("<{new_lifetime}>")) + } + } else if self.res == LifetimeName::ImplicitObjectLifetimeDefault { + // The user wrote `dyn Trait` and omitted the `+ '_`. + (self.ident.span, format!("+ {new_lifetime}")) + } else if self.ident.span.is_empty() { + // The user wrote `&type` or `&mut type`. + (self.ident.span, format!("{new_lifetime} ")) + } else { + // The user wrote `'a` or `'_`. + (self.ident.span, format!("{new_lifetime}")) + } } } From cfd00f9c16d9b3ab98d6e06125c6baa83dfa4a03 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Mar 2025 18:51:00 +1100 Subject: [PATCH 620/745] Remove `ImplicitObjectLifetimeDefault` case from `suggestion`. It has no effect on anything in the test suite. This means it can also be rewritten as a neater pairwise `match`. --- compiler/rustc_hir/src/hir.rs | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index b91fb41cb4d6..89249eab3510 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -151,23 +151,18 @@ impl Lifetime { pub fn suggestion(&self, new_lifetime: &str) -> (Span, String) { debug_assert!(new_lifetime.starts_with('\'')); - if self.ident.name == kw::Empty { - if self.ident.span.is_empty() { - // The user wrote `Path`, and omitted the `'_,`. - (self.ident.span, format!("{new_lifetime}, ")) - } else { - // The user wrote `Path` and omitted the `<'_>`. - (self.ident.span.shrink_to_hi(), format!("<{new_lifetime}>")) - } - } else if self.res == LifetimeName::ImplicitObjectLifetimeDefault { - // The user wrote `dyn Trait` and omitted the `+ '_`. - (self.ident.span, format!("+ {new_lifetime}")) - } else if self.ident.span.is_empty() { + match (self.ident.name.is_empty(), self.ident.span.is_empty()) { + // The user wrote `Path`, and omitted the `'_,`. + (true, true) => (self.ident.span, format!("{new_lifetime}, ")), + + // The user wrote `Path` and omitted the `<'_>`. + (true, false) => (self.ident.span.shrink_to_hi(), format!("<{new_lifetime}>")), + // The user wrote `&type` or `&mut type`. - (self.ident.span, format!("{new_lifetime} ")) - } else { + (false, true) => (self.ident.span, format!("{new_lifetime} ")), + // The user wrote `'a` or `'_`. - (self.ident.span, format!("{new_lifetime}")) + (false, false) => (self.ident.span, format!("{new_lifetime}")), } } } From d4870874158d70e3f6863412ea729dd70d1baf7b Mon Sep 17 00:00:00 2001 From: binarycat Date: Thu, 27 Mar 2025 17:24:21 -0500 Subject: [PATCH 621/745] search.js: revert usage of nonundef for now (not available under test) specifically, `storage.js` is not loaded during `rustdoc-js` and `rustdoc-js-std` tests. --- src/librustdoc/html/static/js/search.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index f3f4878b1627..dce5fddb3177 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1,5 +1,5 @@ // ignore-tidy-filelength -/* global addClass, getNakedUrl, getSettingValue, getVar, nonundef */ +/* global addClass, getNakedUrl, getSettingValue, getVar */ /* global onEachLazy, removeClass, searchState, browserSupportsHistoryApi, exports */ "use strict"; @@ -353,7 +353,8 @@ function getFilteredNextElem(query, parserState, elems, isInGenerics) { const typeFilterElem = elems.pop(); checkExtraTypeFilterCharacters(start, parserState); // typeFilterElem is not undefined. If it was, the elems.length check would have fired. - parserState.typeFilter = nonundef(typeFilterElem).normalizedPathLast; + // @ts-expect-error + parserState.typeFilter = typeFilterElem.normalizedPathLast; parserState.pos += 1; parserState.totalElems -= 1; query.literalSearch = false; From 8d2c63f514a74752a3186b0bf3e8f3aef57dc12e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Mar 2025 08:21:28 +1100 Subject: [PATCH 622/745] Don't use `kw::Empty` in `hir::Lifetime::ident`. `hir::Lifetime::ident` currently sometimes uses `kw::Empty` for elided lifetimes and sometimes uses `kw::UnderscoreLifetime`, and the distinction is used when creating some error suggestions, e.g. in `Lifetime::suggestion` and `ImplicitLifetimeFinder::visit_ty`. I found this *really* confusing, and it took me a while to understand what was going on. This commit replaces all uses of `kw::Empty` in `hir::Lifetime::ident` with `kw::UnderscoreLifetime`. It adds a new field `hir::Lifetime::is_path_anon` that mostly replaces the old empty/underscore distinction and makes things much clearer. Some other notable changes: - Adds a big comment to `Lifetime` talking about permissable field values. - Adds some assertions in `new_named_lifetime` about what ident values are permissible for the different `LifetimeRes` values. - Adds a `Lifetime::new` constructor that does some checking to make sure the `is_elided` and `is_anonymous` states are valid. - `add_static_impl_trait_suggestion` now looks at `Lifetime::res` instead of the ident when creating the suggestion. This is the one case where `is_path_anon` doesn't replace the old empty/underscore distinction. - A couple of minor pretty-printing improvements. --- compiler/rustc_ast_lowering/src/item.rs | 4 +- compiler/rustc_ast_lowering/src/lib.rs | 47 +++++++--- compiler/rustc_ast_lowering/src/path.rs | 7 +- .../src/diagnostics/region_errors.rs | 6 +- compiler/rustc_hir/src/hir.rs | 93 ++++++++++++++++--- compiler/rustc_hir/src/hir/tests.rs | 1 + compiler/rustc_trait_selection/src/errors.rs | 19 ++-- tests/pretty/hir-lifetimes.pp | 4 +- tests/ui/stats/input-stats.stderr | 6 +- 9 files changed, 136 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index c03d5e53d976..43bf951eddc6 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -5,7 +5,7 @@ use rustc_ast::*; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; -use rustc_hir::{self as hir, HirId, PredicateOrigin}; +use rustc_hir::{self as hir, HirId, IsAnonInPath, PredicateOrigin}; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_span::edit_distance::find_best_match_for_name; @@ -1823,7 +1823,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } GenericParamKind::Lifetime => { let lt_id = self.next_node_id(); - let lifetime = self.new_named_lifetime(id, lt_id, ident); + let lifetime = self.new_named_lifetime(id, lt_id, ident, IsAnonInPath::No); hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate { lifetime, bounds, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index ced9064fd9f4..d5d6dcd8d631 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -55,7 +55,8 @@ use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey}; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId}; use rustc_hir::{ - self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, ParamName, TraitCandidate, + self as hir, ConstArg, GenericArg, HirId, IsAnonInPath, ItemLocalMap, LangItem, ParamName, + TraitCandidate, }; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_macros::extension; @@ -1755,7 +1756,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn lower_lifetime(&mut self, l: &Lifetime) -> &'hir hir::Lifetime { - self.new_named_lifetime(l.id, l.id, l.ident) + self.new_named_lifetime(l.id, l.id, l.ident, IsAnonInPath::No) + } + + fn lower_lifetime_anon_in_path(&mut self, id: NodeId, span: Span) -> &'hir hir::Lifetime { + self.new_named_lifetime(id, id, Ident::new(kw::UnderscoreLifetime, span), IsAnonInPath::Yes) } #[instrument(level = "debug", skip(self))] @@ -1764,28 +1769,43 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { id: NodeId, new_id: NodeId, ident: Ident, + is_anon_in_path: IsAnonInPath, ) -> &'hir hir::Lifetime { + debug_assert_ne!(ident.name, kw::Empty); let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error); let res = match res { LifetimeRes::Param { param, .. } => hir::LifetimeName::Param(param), LifetimeRes::Fresh { param, .. } => { + debug_assert_eq!(ident.name, kw::UnderscoreLifetime); let param = self.local_def_id(param); hir::LifetimeName::Param(param) } - LifetimeRes::Infer => hir::LifetimeName::Infer, - LifetimeRes::Static { .. } => hir::LifetimeName::Static, + LifetimeRes::Infer => { + debug_assert_eq!(ident.name, kw::UnderscoreLifetime); + hir::LifetimeName::Infer + } + LifetimeRes::Static { .. } => { + debug_assert!(matches!(ident.name, kw::StaticLifetime | kw::UnderscoreLifetime)); + hir::LifetimeName::Static + } LifetimeRes::Error => hir::LifetimeName::Error, LifetimeRes::ElidedAnchor { .. } => { panic!("Unexpected `ElidedAnchar` {:?} at {:?}", ident, ident.span); } }; + #[cfg(debug_assertions)] + if is_anon_in_path == IsAnonInPath::Yes { + debug_assert_eq!(ident.name, kw::UnderscoreLifetime); + } + debug!(?res); - self.arena.alloc(hir::Lifetime { - hir_id: self.lower_node_id(new_id), - ident: self.lower_ident(ident), + self.arena.alloc(hir::Lifetime::new( + self.lower_node_id(new_id), + self.lower_ident(ident), res, - }) + is_anon_in_path, + )) } fn lower_generic_params_mut( @@ -2369,11 +2389,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// when the bound is written, even if it is written with `'_` like in /// `Box`. In those cases, `lower_lifetime` is invoked. fn elided_dyn_bound(&mut self, span: Span) -> &'hir hir::Lifetime { - let r = hir::Lifetime { - hir_id: self.next_id(), - ident: Ident::new(kw::Empty, self.lower_span(span)), - res: hir::LifetimeName::ImplicitObjectLifetimeDefault, - }; + let r = hir::Lifetime::new( + self.next_id(), + Ident::new(kw::UnderscoreLifetime, self.lower_span(span)), + hir::LifetimeName::ImplicitObjectLifetimeDefault, + IsAnonInPath::No, + ); debug!("elided_dyn_bound: r={:?}", r); self.arena.alloc(r) } diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index d00c797755f3..c464c159c34c 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -7,7 +7,7 @@ use rustc_hir::def::{DefKind, PartialRes, Res}; use rustc_hir::def_id::DefId; use rustc_middle::span_bug; use rustc_session::parse::add_feature_diagnostics; -use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, sym}; +use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, sym}; use smallvec::{SmallVec, smallvec}; use tracing::{debug, instrument}; @@ -450,10 +450,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { 0, (start.as_u32()..end.as_u32()).map(|i| { let id = NodeId::from_u32(i); - let l = self.lower_lifetime(&Lifetime { - id, - ident: Ident::new(kw::Empty, elided_lifetime_span), - }); + let l = self.lower_lifetime_anon_in_path(id, elided_lifetime_span); GenericArg::Lifetime(l) }), ); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 6b11f1a3681f..50a18b04de4e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -513,14 +513,14 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ty::VarianceDiagInfo::Invariant { ty, param_index } => { let (desc, note) = match ty.kind() { ty::RawPtr(ty, mutbl) => { - assert_eq!(*mutbl, rustc_hir::Mutability::Mut); + assert_eq!(*mutbl, hir::Mutability::Mut); ( format!("a mutable pointer to `{}`", ty), "mutable pointers are invariant over their type parameter".to_string(), ) } ty::Ref(_, inner_ty, mutbl) => { - assert_eq!(*mutbl, rustc_hir::Mutability::Mut); + assert_eq!(*mutbl, hir::Mutability::Mut); ( format!("a mutable reference to `{inner_ty}`"), "mutable references are invariant over their type parameter" @@ -887,7 +887,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // Skip `async` desugaring `impl Future`. } if let TyKind::TraitObject(_, lt) = alias_ty.kind { - if lt.ident.name == kw::Empty { + if lt.res == hir::LifetimeName::ImplicitObjectLifetimeDefault { spans_suggs.push((lt.ident.span.shrink_to_hi(), " + 'a".to_string())); } else { spans_suggs.push((lt.ident.span, "'a".to_string())); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 89249eab3510..e3e96894ed1f 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -35,20 +35,60 @@ use crate::def_id::{DefId, LocalDefIdMap}; pub(crate) use crate::hir_id::{HirId, ItemLocalId, ItemLocalMap, OwnerId}; use crate::intravisit::{FnKind, VisitorExt}; +#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable_Generic)] +pub enum IsAnonInPath { + No, + Yes, +} + +/// A lifetime. The valid field combinations are non-obvious. The following +/// example shows some of them. See also the comments on `LifetimeName`. +/// ``` +/// #[repr(C)] +/// struct S<'a>(&'a u32); // res=Param, name='a, IsAnonInPath::No +/// unsafe extern "C" { +/// fn f1(s: S); // res=Param, name='_, IsAnonInPath::Yes +/// fn f2(s: S<'_>); // res=Param, name='_, IsAnonInPath::No +/// fn f3<'a>(s: S<'a>); // res=Param, name='a, IsAnonInPath::No +/// } +/// +/// struct St<'a> { x: &'a u32 } // res=Param, name='a, IsAnonInPath::No +/// fn f() { +/// _ = St { x: &0 }; // res=Infer, name='_, IsAnonInPath::Yes +/// _ = St::<'_> { x: &0 }; // res=Infer, name='_, IsAnonInPath::No +/// } +/// +/// struct Name<'a>(&'a str); // res=Param, name='a, IsAnonInPath::No +/// const A: Name = Name("a"); // res=Static, name='_, IsAnonInPath::Yes +/// const B: &str = ""; // res=Static, name='_, IsAnonInPath::No +/// static C: &'_ str = ""; // res=Static, name='_, IsAnonInPath::No +/// static D: &'static str = ""; // res=Static, name='static, IsAnonInPath::No +/// +/// trait Tr {} +/// fn tr(_: Box) {} // res=ImplicitObjectLifetimeDefault, name='_, IsAnonInPath::No +/// +/// // (commented out because these cases trigger errors) +/// // struct S1<'a>(&'a str); // res=Param, name='a, IsAnonInPath::No +/// // struct S2(S1); // res=Error, name='_, IsAnonInPath::Yes +/// // struct S3(S1<'_>); // res=Error, name='_, IsAnonInPath::No +/// // struct S4(S1<'a>); // res=Error, name='a, IsAnonInPath::No +/// ``` #[derive(Debug, Copy, Clone, HashStable_Generic)] pub struct Lifetime { #[stable_hasher(ignore)] pub hir_id: HirId, - /// Either "`'a`", referring to a named lifetime definition, - /// `'_` referring to an anonymous lifetime (either explicitly `'_` or `&type`), - /// or "``" (i.e., `kw::Empty`) when appearing in path. - /// - /// See `Lifetime::suggestion_position` for practical use. + /// Either a named lifetime definition (e.g. `'a`, `'static`) or an + /// anonymous lifetime (`'_`, either explicitly written, or inserted for + /// things like `&type`). pub ident: Ident, /// Semantics of this lifetime. pub res: LifetimeName, + + /// Is the lifetime anonymous and in a path? Used only for error + /// suggestions. See `Lifetime::suggestion` for example use. + pub is_anon_in_path: IsAnonInPath, } #[derive(Debug, Copy, Clone, HashStable_Generic)] @@ -111,11 +151,12 @@ pub enum LifetimeName { /// that was already reported. Error, - /// User wrote an anonymous lifetime, either `'_` or nothing. - /// The semantics of this lifetime should be inferred by typechecking code. + /// User wrote an anonymous lifetime, either `'_` or nothing (which gets + /// converted to `'_`). The semantics of this lifetime should be inferred + /// by typechecking code. Infer, - /// User wrote `'static`. + /// User wrote `'static` or nothing (which gets converted to `'_`). Static, } @@ -135,34 +176,56 @@ impl LifetimeName { impl fmt::Display for Lifetime { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.ident.name != kw::Empty { self.ident.name.fmt(f) } else { "'_".fmt(f) } + self.ident.name.fmt(f) } } impl Lifetime { + pub fn new( + hir_id: HirId, + ident: Ident, + res: LifetimeName, + is_anon_in_path: IsAnonInPath, + ) -> Lifetime { + let lifetime = Lifetime { hir_id, ident, res, is_anon_in_path }; + + // Sanity check: elided lifetimes form a strict subset of anonymous lifetimes. + #[cfg(debug_assertions)] + match (lifetime.is_elided(), lifetime.is_anonymous()) { + (false, false) => {} // e.g. `'a` + (false, true) => {} // e.g. explicit `'_` + (true, true) => {} // e.g. `&x` + (true, false) => panic!("bad Lifetime"), + } + + lifetime + } + pub fn is_elided(&self) -> bool { self.res.is_elided() } pub fn is_anonymous(&self) -> bool { - self.ident.name == kw::Empty || self.ident.name == kw::UnderscoreLifetime + self.ident.name == kw::UnderscoreLifetime } pub fn suggestion(&self, new_lifetime: &str) -> (Span, String) { debug_assert!(new_lifetime.starts_with('\'')); - match (self.ident.name.is_empty(), self.ident.span.is_empty()) { + match (self.is_anon_in_path, self.ident.span.is_empty()) { // The user wrote `Path`, and omitted the `'_,`. - (true, true) => (self.ident.span, format!("{new_lifetime}, ")), + (IsAnonInPath::Yes, true) => (self.ident.span, format!("{new_lifetime}, ")), // The user wrote `Path` and omitted the `<'_>`. - (true, false) => (self.ident.span.shrink_to_hi(), format!("<{new_lifetime}>")), + (IsAnonInPath::Yes, false) => { + (self.ident.span.shrink_to_hi(), format!("<{new_lifetime}>")) + } // The user wrote `&type` or `&mut type`. - (false, true) => (self.ident.span, format!("{new_lifetime} ")), + (IsAnonInPath::No, true) => (self.ident.span, format!("{new_lifetime} ")), // The user wrote `'a` or `'_`. - (false, false) => (self.ident.span, format!("{new_lifetime}")), + (IsAnonInPath::No, false) => (self.ident.span, format!("{new_lifetime}")), } } } diff --git a/compiler/rustc_hir/src/hir/tests.rs b/compiler/rustc_hir/src/hir/tests.rs index f75b9662132e..62ef02d2f500 100644 --- a/compiler/rustc_hir/src/hir/tests.rs +++ b/compiler/rustc_hir/src/hir/tests.rs @@ -58,6 +58,7 @@ fn trait_object_roundtrips_impl(syntax: TraitObjectSyntax) { hir_id: HirId::INVALID, ident: Ident::new(sym::name, DUMMY_SP), res: LifetimeName::Static, + is_anon_in_path: IsAnonInPath::No, } }, syntax, diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 7159397c4b1a..b30390a9330e 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -9,7 +9,7 @@ use rustc_errors::{ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{Visitor, VisitorExt, walk_ty}; -use rustc_hir::{self as hir, AmbigArg, FnRetTy, GenericParamKind, Node}; +use rustc_hir::{self as hir, AmbigArg, FnRetTy, GenericParamKind, IsAnonInPath, Node}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath}; use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, Region, Ty, TyCtxt}; @@ -567,10 +567,14 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { impl<'v> Visitor<'v> for ImplicitLifetimeFinder { fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) { - let make_suggestion = |ident: Ident| { - if ident.name == kw::Empty && ident.span.is_empty() { + let make_suggestion = |lifetime: &hir::Lifetime| { + if lifetime.is_anon_in_path == IsAnonInPath::Yes + && lifetime.ident.span.is_empty() + { format!("{}, ", self.suggestion_param_name) - } else if ident.name == kw::UnderscoreLifetime && ident.span.is_empty() { + } else if lifetime.ident.name == kw::UnderscoreLifetime + && lifetime.ident.span.is_empty() + { format!("{} ", self.suggestion_param_name) } else { self.suggestion_param_name.clone() @@ -584,7 +588,7 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { matches!( arg, hir::GenericArg::Lifetime(lifetime) - if lifetime.ident.name == kw::Empty + if lifetime.is_anon_in_path == IsAnonInPath::Yes ) }) { self.suggestions.push(( @@ -605,7 +609,7 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { { self.suggestions.push(( lifetime.ident.span, - make_suggestion(lifetime.ident), + make_suggestion(lifetime), )); } } @@ -614,8 +618,7 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { } } hir::TyKind::Ref(lifetime, ..) if lifetime.is_anonymous() => { - self.suggestions - .push((lifetime.ident.span, make_suggestion(lifetime.ident))); + self.suggestions.push((lifetime.ident.span, make_suggestion(lifetime))); } _ => {} } diff --git a/tests/pretty/hir-lifetimes.pp b/tests/pretty/hir-lifetimes.pp index df3aba516b9c..e545b0c8f576 100644 --- a/tests/pretty/hir-lifetimes.pp +++ b/tests/pretty/hir-lifetimes.pp @@ -73,7 +73,7 @@ fn h<'b, F>(f: F, y: Foo<'b>) where F: for<'d> MyTrait<'d, 'b> { } struct S<'a>(&'a u32); extern "C" { - unsafe fn g1(s: S<>); + unsafe fn g1(s: S<'_>); unsafe fn g2(s: S<'_>); unsafe fn g3<'a>(s: S<'a>); } @@ -86,7 +86,7 @@ fn f() { { let _ = St{ x: &0,}; }; { let _ = St{ x: &0,}; }; } struct Name<'a>(&'a str); -const A: Name<> = Name("a"); +const A: Name<'_> = Name("a"); const B: &'_ str = ""; static C: &'_ str = ""; static D: &'static str = ""; diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr index dbc9e7d254c8..191daff2137d 100644 --- a/tests/ui/stats/input-stats.stderr +++ b/tests/ui/stats/input-stats.stderr @@ -119,7 +119,7 @@ hir-stats HIR STATS hir-stats Name Accumulated Size Count Item Size hir-stats ---------------------------------------------------------------- hir-stats ForeignItemRef 24 ( 0.3%) 1 24 -hir-stats Lifetime 24 ( 0.3%) 1 24 +hir-stats Lifetime 28 ( 0.3%) 1 28 hir-stats Mod 32 ( 0.4%) 1 32 hir-stats ExprField 40 ( 0.4%) 1 40 hir-stats TraitItemRef 56 ( 0.6%) 2 28 @@ -155,7 +155,7 @@ hir-stats Generics 560 ( 6.2%) 10 56 hir-stats Ty 720 ( 8.0%) 15 48 hir-stats - Ptr 48 ( 0.5%) 1 hir-stats - Ref 48 ( 0.5%) 1 -hir-stats - Path 624 ( 7.0%) 13 +hir-stats - Path 624 ( 6.9%) 13 hir-stats Expr 768 ( 8.6%) 12 64 hir-stats - InlineAsm 64 ( 0.7%) 1 hir-stats - Match 64 ( 0.7%) 1 @@ -174,5 +174,5 @@ hir-stats - Use 352 ( 3.9%) 4 hir-stats Path 1_240 (13.8%) 31 40 hir-stats PathSegment 1_920 (21.4%) 40 48 hir-stats ---------------------------------------------------------------- -hir-stats Total 8_976 180 +hir-stats Total 8_980 180 hir-stats From 3b7d59ad1212a6e6556423b4c383aee99f7d20e0 Mon Sep 17 00:00:00 2001 From: Adam Greig Date: Fri, 28 Mar 2025 01:54:35 +0000 Subject: [PATCH 623/745] Update target maintainers for thumb targets to reflect new REWG Arm team name --- src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md | 3 +-- src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md | 3 +-- src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md | 3 +-- src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md | 3 +-- src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md | 3 +-- 5 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md index f4ed6201bbdc..746b84435479 100644 --- a/src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md +++ b/src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md @@ -26,8 +26,7 @@ only option because there is no FPU support in [Armv6-M]. ## Target maintainers -* [Rust Embedded Devices Working Group Cortex-M - Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org` +* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team) ## Target CPU and Target Feature options diff --git a/src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md index 11c9486cb76e..12e28265678c 100644 --- a/src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md +++ b/src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md @@ -21,8 +21,7 @@ See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all ## Target maintainers -* [Rust Embedded Devices Working Group Cortex-M - Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org` +* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team) ## Target CPU and Target Feature options diff --git a/src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md index b258033bb0fa..03324b341d07 100644 --- a/src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md +++ b/src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md @@ -22,8 +22,7 @@ only option because there is no FPU support in [Armv7-M]. ## Target maintainers -* [Rust Embedded Devices Working Group Cortex-M - Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org` +* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team) ## Target CPU and Target Feature options diff --git a/src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md index 0ae4e3e94bd8..4a92e856466c 100644 --- a/src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md +++ b/src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md @@ -22,8 +22,7 @@ only option because there is no FPU support in [Armv8-M] Baseline. ## Target maintainers -* [Rust Embedded Devices Working Group Cortex-M - Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org` +* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team) ## Target CPU and Target Feature options diff --git a/src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md index 82fdc5b21cf2..9f85d08fa0ac 100644 --- a/src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md +++ b/src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md @@ -25,8 +25,7 @@ See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all ## Target maintainers -* [Rust Embedded Devices Working Group Cortex-M - Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org` +* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team) ## Target CPU and Target Feature options From b24083bccc15a55d8488fee8ee629689c5039ded Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Thu, 27 Mar 2025 23:10:30 +0530 Subject: [PATCH 624/745] Add new change-id option in bootstrap.example.toml and update the change-id description references --- bootstrap.example.toml | 5 +++-- src/bootstrap/src/bin/main.rs | 4 ++-- src/bootstrap/src/core/config/config.rs | 6 +++++- src/bootstrap/src/utils/change_tracker.rs | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/bootstrap.example.toml b/bootstrap.example.toml index caffe1a93712..2a98821f2252 100644 --- a/bootstrap.example.toml +++ b/bootstrap.example.toml @@ -28,8 +28,9 @@ # - A new option # - A change in the default values # -# If `change-id` does not match the version that is currently running, -# `x.py` will inform you about the changes made on bootstrap. +# If the change-id does not match the version currently in use, x.py will +# display the changes made to the bootstrap. +# To suppress these warnings, you can set change-id = "ignore". #change-id = # ============================================================================= diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index 5df9902a9778..7ec3140c0386 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -163,7 +163,7 @@ fn check_version(config: &Config) -> Option { msg.push_str("WARNING: The `change-id` is missing in the `bootstrap.toml`. This means that you will not be able to track the major changes made to the bootstrap configurations.\n"); msg.push_str("NOTE: to silence this warning, "); msg.push_str(&format!( - "add `change-id = {latest_change_id}` at the top of `bootstrap.toml`" + "add `change-id = {latest_change_id}` or change-id = \"ignore\" at the top of `bootstrap.toml`" )); return Some(msg); } @@ -195,7 +195,7 @@ fn check_version(config: &Config) -> Option { msg.push_str("NOTE: to silence this warning, "); msg.push_str(&format!( - "update `bootstrap.toml` to use `change-id = {latest_change_id}` instead" + "update `bootstrap.toml` to use `change-id = {latest_change_id}` or change-id = \"ignore\" instead" )); if io::stdout().is_terminal() { diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 96316d4d0fdb..bbb0fbfbb935 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -724,7 +724,11 @@ fn deserialize_change_id<'de, D: Deserializer<'de>>( Ok(match value { toml::Value::String(s) if s == "ignore" => Some(ChangeId::Ignore), toml::Value::Integer(i) => Some(ChangeId::Id(i as usize)), - _ => return Err(serde::de::Error::custom("expected \"ignore\" or an integer")), + _ => { + return Err(serde::de::Error::custom( + "expected \"ignore\" or an integer for change-id", + )); + } }) } diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 78887a42a000..5314141dd1b0 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -393,6 +393,6 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ ChangeInfo { change_id: 138986, severity: ChangeSeverity::Info, - summary: "You can now use `change_id = \"ignore\"` to suppress `change_id` warnings in the console.", + summary: "You can now use `change-id = \"ignore\"` to suppress `change-id ` warnings in the console.", }, ]; From c83504faefcbb7c26426cbc20686b910bd58c8d2 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Fri, 21 Mar 2025 13:30:56 +0100 Subject: [PATCH 625/745] bootstrap: bump cc to 1.2.17 and cmake to 0.1.54 --- src/bootstrap/Cargo.lock | 8 ++++---- src/bootstrap/Cargo.toml | 6 ++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index 890e64e2babb..17ee4d610f95 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -88,9 +88,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.22" +version = "1.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0" +checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" dependencies = [ "shlex", ] @@ -150,9 +150,9 @@ checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "cmake" -version = "0.1.48" +version = "0.1.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8ad8cef104ac57b68b89df3208164d228503abbdce70f6880ffa3d970e7443a" +checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" dependencies = [ "cc", ] diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index d3e2b9e05e99..23aa87a74075 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -32,10 +32,8 @@ test = false # Most of the time updating these dependencies requires modifications to the # bootstrap codebase(e.g., https://github.com/rust-lang/rust/issues/124565); # otherwise, some targets will fail. That's why these dependencies are explicitly pinned. -# -# Do not upgrade this crate unless https://github.com/rust-lang/cc-rs/issues/1317 is fixed. -cc = "=1.1.22" -cmake = "=0.1.48" +cc = "=1.2.17" +cmake = "=0.1.54" build_helper = { path = "../build_helper" } clap = { version = "4.4", default-features = false, features = ["std", "usage", "help", "derive", "error-context"] } From 9cf05b893d33a4a83a145396ed76e41ea1da97f2 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 24 Mar 2025 13:08:25 +0100 Subject: [PATCH 626/745] bootstrap: Always set CMAKE_SYSTEM_NAME when cross-compiling To avoid a panic in cmake-rs that was introduced in: https://github.com/rust-lang/cmake-rs/pull/158 --- src/bootstrap/src/core/build_steps/llvm.rs | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 9ae1825fae89..0bc879c7d713 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -645,10 +645,17 @@ fn configure_cmake( if !builder.is_builder_target(target) { cfg.define("CMAKE_CROSSCOMPILING", "True"); + // NOTE: Ideally, we wouldn't have to do this, and `cmake-rs` would just handle it for us. + // But it currently determines this based on the `CARGO_CFG_TARGET_OS` environment variable, + // which isn't set when compiling outside `build.rs` (like bootstrap is). + // + // So for now, we define `CMAKE_SYSTEM_NAME` ourselves, to panicking in `cmake-rs`. if target.contains("netbsd") { cfg.define("CMAKE_SYSTEM_NAME", "NetBSD"); } else if target.contains("dragonfly") { cfg.define("CMAKE_SYSTEM_NAME", "DragonFly"); + } else if target.contains("openbsd") { + cfg.define("CMAKE_SYSTEM_NAME", "OpenBSD"); } else if target.contains("freebsd") { cfg.define("CMAKE_SYSTEM_NAME", "FreeBSD"); } else if target.is_windows() { @@ -659,10 +666,27 @@ fn configure_cmake( cfg.define("CMAKE_SYSTEM_NAME", "SunOS"); } else if target.contains("linux") { cfg.define("CMAKE_SYSTEM_NAME", "Linux"); + } else if target.contains("darwin") { + // macOS + cfg.define("CMAKE_SYSTEM_NAME", "Darwin"); + } else if target.contains("ios") { + cfg.define("CMAKE_SYSTEM_NAME", "iOS"); + } else if target.contains("tvos") { + cfg.define("CMAKE_SYSTEM_NAME", "tvOS"); + } else if target.contains("visionos") { + cfg.define("CMAKE_SYSTEM_NAME", "visionOS"); + } else if target.contains("watchos") { + cfg.define("CMAKE_SYSTEM_NAME", "watchOS"); + } else if target.contains("none") { + // "none" should be the last branch + cfg.define("CMAKE_SYSTEM_NAME", "Generic"); } else { builder.info(&format!( "could not determine CMAKE_SYSTEM_NAME from the target `{target}`, build may fail", )); + // Fallback, set `CMAKE_SYSTEM_NAME` anyhow to avoid the logic `cmake-rs` tries, and + // to avoid CMAKE_SYSTEM_NAME being inferred from the host. + cfg.define("CMAKE_SYSTEM_NAME", "Generic"); } // When cross-compiling we should also set CMAKE_SYSTEM_VERSION, but in From a9cb15d793495b6b6318c7a60c42d12ddcf1609a Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 24 Mar 2025 11:05:41 +0100 Subject: [PATCH 627/745] bootstrap: Fix CMAKE_OSX_ARCHITECTURES on all Apple platforms --- src/bootstrap/src/core/build_steps/llvm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 0bc879c7d713..41d3ca2c4cd4 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -696,7 +696,7 @@ fn configure_cmake( // CMakeFiles (and then only in tests), and so far no issues have been // reported, the system version is currently left unset. - if target.contains("darwin") { + if target.contains("apple") { // Make sure that CMake does not build universal binaries on macOS. // Explicitly specify the one single target architecture. if target.starts_with("aarch64") { From e8704e899cc72e8a04e0235e2ad7c7375d0c0633 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 24 Mar 2025 22:42:23 +0100 Subject: [PATCH 628/745] bootstrap: Set CMAKE_SYSTEM_NAME=Darwin on Apple platforms compiler-rt's CMake setup seems to have special logic for Apple platforms that works poorly when this is not set. --- src/bootstrap/src/core/build_steps/llvm.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 41d3ca2c4cd4..de91b5d1eb5b 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -697,6 +697,14 @@ fn configure_cmake( // reported, the system version is currently left unset. if target.contains("apple") { + if !target.contains("darwin") { + // FIXME(madsmtm): compiler-rt's CMake setup is kinda weird, it seems like they do + // version testing etc. for macOS (i.e. Darwin), even while building for iOS? + // + // So for now we set it to "Darwin" on all Apple platforms. + cfg.define("CMAKE_SYSTEM_NAME", "Darwin"); + } + // Make sure that CMake does not build universal binaries on macOS. // Explicitly specify the one single target architecture. if target.starts_with("aarch64") { From 011eabd6909e7ba2d6b0fd812658e16d17a38961 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 24 Mar 2025 22:58:39 +0100 Subject: [PATCH 629/745] bootstrap: Override CMAKE_OSX_SYSROOT when building compiler-rt Similarly to what was previously done for the `llvm` step. --- src/bootstrap/src/core/build_steps/llvm.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index de91b5d1eb5b..e21804fa3c07 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -385,9 +385,6 @@ impl Step for Llvm { || target.contains("apple-watchos") || target.contains("apple-visionos") { - // These two defines prevent CMake from automatically trying to add a MacOSX sysroot, which leads to a compiler error. - cfg.define("CMAKE_OSX_SYSROOT", "/"); - cfg.define("CMAKE_OSX_DEPLOYMENT_TARGET", ""); // Prevent cmake from adding -bundle to CFLAGS automatically, which leads to a compiler error because "-bitcode_bundle" also gets added. cfg.define("LLVM_ENABLE_PLUGINS", "OFF"); // Zlib fails to link properly, leading to a compiler error. @@ -703,6 +700,10 @@ fn configure_cmake( // // So for now we set it to "Darwin" on all Apple platforms. cfg.define("CMAKE_SYSTEM_NAME", "Darwin"); + + // These two defines prevent CMake from automatically trying to add a MacOSX sysroot, which leads to a compiler error. + cfg.define("CMAKE_OSX_SYSROOT", "/"); + cfg.define("CMAKE_OSX_DEPLOYMENT_TARGET", ""); } // Make sure that CMake does not build universal binaries on macOS. From 7a6a3241ca18147c86926bb388aad54c4e3eadc5 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Tue, 25 Mar 2025 11:03:06 +0100 Subject: [PATCH 630/745] bootstrap: Update download-ci-llvm-stamp This PR makes a fairly large version update to CMake and cc, so it is likely that LLVM is built differently. --- src/bootstrap/download-ci-llvm-stamp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp index d2c0d380fb40..e157ff233bbf 100644 --- a/src/bootstrap/download-ci-llvm-stamp +++ b/src/bootstrap/download-ci-llvm-stamp @@ -1,4 +1,4 @@ Change this file to make users of the `download-ci-llvm` configuration download a new version of LLVM from CI, even if the LLVM submodule hasn’t changed. -Last change is for: https://github.com/rust-lang/rust/pull/134740 +Last change is for: https://github.com/rust-lang/rust/pull/138784 From d5f7e71d5c861c513fda67bd35382ac03049e177 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 28 Mar 2025 10:11:45 +0300 Subject: [PATCH 631/745] bootstrap: update `test_find` test `cc::Build::get_archiver` is noisy on the `arm-linux-androideabi` target and constantly printing `llvm-ar --version` output during bootstrap tests on all platforms. Signed-off-by: onur-ozkan --- src/bootstrap/src/utils/cc_detect/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/utils/cc_detect/tests.rs b/src/bootstrap/src/utils/cc_detect/tests.rs index c97529cbe9eb..b4a1b52dd230 100644 --- a/src/bootstrap/src/utils/cc_detect/tests.rs +++ b/src/bootstrap/src/utils/cc_detect/tests.rs @@ -264,7 +264,7 @@ fn test_find_target_without_config() { fn test_find() { let mut build = Build::new(Config { ..Config::parse(Flags::parse(&["check".to_owned()])) }); let target1 = TargetSelection::from_user("x86_64-unknown-linux-gnu"); - let target2 = TargetSelection::from_user("arm-linux-androideabi"); + let target2 = TargetSelection::from_user("x86_64-unknown-openbsd"); build.targets.push(target1.clone()); build.hosts.push(target2.clone()); find(&build); From 3a9a5770ef44401315e8c99b13b81b4c595fc82e Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 28 Mar 2025 08:15:18 +0100 Subject: [PATCH 632/745] Remove ScopeDepth entirely. The scope depth was tracked, but never actually used for anything. --- .../rustc_hir_analysis/src/check/region.rs | 38 +++++++------------ compiler/rustc_middle/src/middle/region.rs | 8 ++-- compiler/rustc_middle/src/ty/rvalue_scopes.rs | 2 +- 3 files changed, 18 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index ba8124b11fc1..9d99a3ea6739 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -23,18 +23,11 @@ use tracing::debug; #[derive(Debug, Copy, Clone)] struct Context { - /// The scope that contains any new variables declared, plus its depth in - /// the scope tree. + /// The scope that contains any new variables declared. var_parent: Option, - /// Region parent of expressions, etc., plus its depth in the scope tree. - parent: Option<(Scope, ScopeDepth)>, -} - -impl Context { - fn set_var_parent(&mut self) { - self.var_parent = self.parent.map(|(p, _)| p); - } + /// Region parent of expressions, etc. + parent: Option, } struct ScopeResolutionVisitor<'tcx> { @@ -119,7 +112,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi // itself has returned. visitor.enter_node_scope_with_dtor(blk.hir_id.local_id); - visitor.cx.set_var_parent(); + visitor.cx.var_parent = visitor.cx.parent; { // This block should be kept approximately in sync with @@ -138,7 +131,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi local_id: blk.hir_id.local_id, data: ScopeData::Remainder(FirstStatementIndex::new(i)), }); - visitor.cx.set_var_parent(); + visitor.cx.var_parent = visitor.cx.parent; visitor.visit_stmt(statement); // We need to back out temporarily to the last enclosing scope // for the `else` block, so that even the temporaries receiving @@ -163,7 +156,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi local_id: blk.hir_id.local_id, data: ScopeData::Remainder(FirstStatementIndex::new(i)), }); - visitor.cx.set_var_parent(); + visitor.cx.var_parent = visitor.cx.parent; visitor.visit_stmt(statement) } hir::StmtKind::Item(..) => { @@ -213,7 +206,7 @@ fn resolve_arm<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, arm: &'tcx hir: visitor.terminating_scopes.insert(arm.hir_id.local_id); visitor.enter_node_scope_with_dtor(arm.hir_id.local_id); - visitor.cx.set_var_parent(); + visitor.cx.var_parent = visitor.cx.parent; if let Some(expr) = arm.guard && !has_let_expr(expr) @@ -490,7 +483,7 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi ScopeData::IfThen }; visitor.enter_scope(Scope { local_id: then.hir_id.local_id, data }); - visitor.cx.set_var_parent(); + visitor.cx.var_parent = visitor.cx.parent; visitor.visit_expr(cond); visitor.visit_expr(then); visitor.cx = expr_cx; @@ -505,7 +498,7 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi ScopeData::IfThen }; visitor.enter_scope(Scope { local_id: then.hir_id.local_id, data }); - visitor.cx.set_var_parent(); + visitor.cx.var_parent = visitor.cx.parent; visitor.visit_expr(cond); visitor.visit_expr(then); visitor.cx = expr_cx; @@ -545,7 +538,7 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi // Keep traversing up while we can. match visitor.scope_tree.parent_map.get(&scope) { // Don't cross from closure bodies to their parent. - Some(&(superscope, _)) => match superscope.data { + Some(&superscope) => match superscope.data { ScopeData::CallSite => break, _ => scope = superscope, }, @@ -782,19 +775,16 @@ fn resolve_local<'tcx>( impl<'tcx> ScopeResolutionVisitor<'tcx> { /// Records the current parent (if any) as the parent of `child_scope`. /// Returns the depth of `child_scope`. - fn record_child_scope(&mut self, child_scope: Scope) -> ScopeDepth { + fn record_child_scope(&mut self, child_scope: Scope) { let parent = self.cx.parent; self.scope_tree.record_scope_parent(child_scope, parent); - // If `child_scope` has no parent, it must be the root node, and so has - // a depth of 1. Otherwise, its depth is one more than its parent's. - parent.map_or(1, |(_p, d)| d + 1) } /// Records the current parent (if any) as the parent of `child_scope`, /// and sets `child_scope` as the new current parent. fn enter_scope(&mut self, child_scope: Scope) { - let child_depth = self.record_child_scope(child_scope); - self.cx.parent = Some((child_scope, child_depth)); + self.record_child_scope(child_scope); + self.cx.parent = Some(child_scope); } fn enter_node_scope_with_dtor(&mut self, id: hir::ItemLocalId) { @@ -855,7 +845,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { self.enter_body(body.value.hir_id, |this| { if this.tcx.hir_body_owner_kind(owner_id).is_fn_or_closure() { // The arguments and `self` are parented to the fn. - this.cx.set_var_parent(); + this.cx.var_parent = this.cx.parent; for param in body.params { this.visit_pat(param.pat); } diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index 66ece8f0e52f..ba31f775b651 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -199,8 +199,6 @@ impl Scope { } } -pub type ScopeDepth = u32; - /// The region scope tree encodes information about region relationships. #[derive(Default, Debug, HashStable)] pub struct ScopeTree { @@ -213,7 +211,7 @@ pub struct ScopeTree { /// conditional expression or repeating block. (Note that the /// enclosing scope ID for the block associated with a closure is /// the closure itself.) - pub parent_map: FxIndexMap, + pub parent_map: FxIndexMap, /// Maps from a variable or binding ID to the block in which that /// variable is declared. @@ -328,7 +326,7 @@ pub struct YieldData { } impl ScopeTree { - pub fn record_scope_parent(&mut self, child: Scope, parent: Option<(Scope, ScopeDepth)>) { + pub fn record_scope_parent(&mut self, child: Scope, parent: Option) { debug!("{:?}.parent = {:?}", child, parent); if let Some(p) = parent { @@ -353,7 +351,7 @@ impl ScopeTree { /// Returns the narrowest scope that encloses `id`, if any. pub fn opt_encl_scope(&self, id: Scope) -> Option { - self.parent_map.get(&id).cloned().map(|(p, _)| p) + self.parent_map.get(&id).cloned() } /// Returns the lifetime of the local variable `var_id`, if any. diff --git a/compiler/rustc_middle/src/ty/rvalue_scopes.rs b/compiler/rustc_middle/src/ty/rvalue_scopes.rs index b00c8169a36a..9bf6e3a75900 100644 --- a/compiler/rustc_middle/src/ty/rvalue_scopes.rs +++ b/compiler/rustc_middle/src/ty/rvalue_scopes.rs @@ -38,7 +38,7 @@ impl RvalueScopes { let mut id = Scope { local_id: expr_id, data: ScopeData::Node }; let mut backwards_incompatible = None; - while let Some(&(p, _)) = region_scope_tree.parent_map.get(&id) { + while let Some(&p) = region_scope_tree.parent_map.get(&id) { match p.data { ScopeData::Destruction => { debug!("temporary_scope({expr_id:?}) = {id:?} [enclosing]"); From deeac1c588d3487202490280ee64434ad3c45f0c Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 28 Mar 2025 08:36:16 +0100 Subject: [PATCH 633/745] Remove outdated comment. --- compiler/rustc_hir_analysis/src/check/region.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 9d99a3ea6739..2528adb937b3 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -774,7 +774,6 @@ fn resolve_local<'tcx>( impl<'tcx> ScopeResolutionVisitor<'tcx> { /// Records the current parent (if any) as the parent of `child_scope`. - /// Returns the depth of `child_scope`. fn record_child_scope(&mut self, child_scope: Scope) { let parent = self.cx.parent; self.scope_tree.record_scope_parent(child_scope, parent); From c41476034d49813d574af3877f6995e14b10729d Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 28 Mar 2025 10:16:03 +0100 Subject: [PATCH 634/745] Put pin!() tests in the right file. --- library/coretests/tests/pin.rs | 14 -------------- library/coretests/tests/pin_macro.rs | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/library/coretests/tests/pin.rs b/library/coretests/tests/pin.rs index a866cf12a3bb..b3fb06e710d4 100644 --- a/library/coretests/tests/pin.rs +++ b/library/coretests/tests/pin.rs @@ -34,9 +34,6 @@ fn pin_const() { } pin_mut_const(); - - // Check that we accept a Rust 2024 $expr. - std::pin::pin!(const { 1 }); } #[allow(unused)] @@ -84,14 +81,3 @@ mod pin_coerce_unsized { arg } } - -#[test] -#[cfg(not(bootstrap))] -fn temp_lifetime() { - // Check that temporary lifetimes work as in Rust 2021. - // Regression test for https://github.com/rust-lang/rust/issues/138596 - match std::pin::pin!(foo(&mut 0)) { - _ => {} - } - async fn foo(_: &mut usize) {} -} diff --git a/library/coretests/tests/pin_macro.rs b/library/coretests/tests/pin_macro.rs index 43542397a613..639eab740c0b 100644 --- a/library/coretests/tests/pin_macro.rs +++ b/library/coretests/tests/pin_macro.rs @@ -30,3 +30,20 @@ fn unsize_coercion() { let dyn_obj: Pin<&mut dyn Send> = pin!([PhantomPinned; 2]); stuff(dyn_obj); } + +#[test] +fn rust_2024_expr() { + // Check that we accept a Rust 2024 $expr. + std::pin::pin!(const { 1 }); +} + +#[test] +#[cfg(not(bootstrap))] +fn temp_lifetime() { + // Check that temporary lifetimes work as in Rust 2021. + // Regression test for https://github.com/rust-lang/rust/issues/138596 + match std::pin::pin!(foo(&mut 0)) { + _ => {} + } + async fn foo(_: &mut usize) {} +} From a5fa12b6b908894f59a788641c4b14839e556c5f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 14 Mar 2025 15:56:33 +0000 Subject: [PATCH 635/745] Avoid wrapping constant allocations in packed structs when not necessary This way LLVM will set the string merging flag if the alloc is a nul terminated string, reducing binary sizes. --- compiler/rustc_codegen_gcc/src/consts.rs | 1 + compiler/rustc_codegen_llvm/src/consts.rs | 2 +- tests/codegen/const-array.rs | 4 +-- tests/codegen/debug-vtable.rs | 2 +- tests/codegen/external-no-mangle-statics.rs | 32 ++++++++++----------- tests/codegen/link_section.rs | 2 +- tests/codegen/remap_path_prefix/main.rs | 2 +- tests/codegen/uninit-consts.rs | 6 ++-- 8 files changed, 26 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index c514b7a428bc..474475f311f7 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -364,6 +364,7 @@ pub fn const_alloc_to_gcc<'gcc>( llvals.push(cx.const_bytes(bytes)); } + // FIXME(bjorn3) avoid wrapping in a struct when there is only a single element. cx.const_struct(&llvals, true) } diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index a4e5749b3acb..a1ab6714d370 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -128,7 +128,7 @@ pub(crate) fn const_alloc_to_llvm<'ll>( append_chunks_of_init_and_uninit_bytes(&mut llvals, cx, alloc, range); } - cx.const_struct(&llvals, true) + if let &[data] = &*llvals { data } else { cx.const_struct(&llvals, true) } } fn codegen_static_initializer<'ll, 'tcx>( diff --git a/tests/codegen/const-array.rs b/tests/codegen/const-array.rs index e257d8acc088..b3df76c3d8e0 100644 --- a/tests/codegen/const-array.rs +++ b/tests/codegen/const-array.rs @@ -2,7 +2,7 @@ #![crate_type = "lib"] -const LUT: [u8; 2] = [1, 1]; +const LUT: [u8; 4] = [1, 1, 1, 1]; // CHECK-LABEL: @decode #[no_mangle] @@ -11,5 +11,5 @@ pub fn decode(i: u8) -> u8 { // CHECK-NEXT: icmp // CHECK-NEXT: select // CHECK-NEXT: ret - if i < 2 { LUT[i as usize] } else { 2 } + if i < 4 { LUT[i as usize] } else { 2 } } diff --git a/tests/codegen/debug-vtable.rs b/tests/codegen/debug-vtable.rs index b9808e4079bc..8a7b1cc3c4bc 100644 --- a/tests/codegen/debug-vtable.rs +++ b/tests/codegen/debug-vtable.rs @@ -15,7 +15,7 @@ // Make sure that vtables don't have the unnamed_addr attribute when debuginfo is enabled. // This helps debuggers more reliably map from dyn pointer to concrete type. -// CHECK: @vtable.2 = private constant <{ +// CHECK: @vtable.2 = private constant [ // CHECK: @vtable.3 = private constant <{ // CHECK: @vtable.4 = private constant <{ diff --git a/tests/codegen/external-no-mangle-statics.rs b/tests/codegen/external-no-mangle-statics.rs index dc4eca8c7b48..49f42ee977d5 100644 --- a/tests/codegen/external-no-mangle-statics.rs +++ b/tests/codegen/external-no-mangle-statics.rs @@ -6,72 +6,72 @@ // `#[no_mangle]`d static variables always have external linkage, i.e., no `internal` in their // definitions -// CHECK: @A = {{(dso_local )?}}local_unnamed_addr constant +// CHECK-DAG: @A = {{(dso_local )?}}local_unnamed_addr constant #[no_mangle] static A: u8 = 0; -// CHECK: @B = {{(dso_local )?}}local_unnamed_addr global +// CHECK-DAG: @B = {{(dso_local )?}}local_unnamed_addr global #[no_mangle] static mut B: u8 = 0; -// CHECK: @C = {{(dso_local )?}}local_unnamed_addr constant +// CHECK-DAG: @C = {{(dso_local )?}}local_unnamed_addr constant #[no_mangle] pub static C: u8 = 0; -// CHECK: @D = {{(dso_local )?}}local_unnamed_addr global +// CHECK-DAG: @D = {{(dso_local )?}}local_unnamed_addr global #[no_mangle] pub static mut D: u8 = 0; mod private { - // CHECK: @E = {{(dso_local )?}}local_unnamed_addr constant + // CHECK-DAG: @E = {{(dso_local )?}}local_unnamed_addr constant #[no_mangle] static E: u8 = 0; - // CHECK: @F = {{(dso_local )?}}local_unnamed_addr global + // CHECK-DAG: @F = {{(dso_local )?}}local_unnamed_addr global #[no_mangle] static mut F: u8 = 0; - // CHECK: @G = {{(dso_local )?}}local_unnamed_addr constant + // CHECK-DAG: @G = {{(dso_local )?}}local_unnamed_addr constant #[no_mangle] pub static G: u8 = 0; - // CHECK: @H = {{(dso_local )?}}local_unnamed_addr global + // CHECK-DAG: @H = {{(dso_local )?}}local_unnamed_addr global #[no_mangle] pub static mut H: u8 = 0; } const HIDDEN: () = { - // CHECK: @I = {{(dso_local )?}}local_unnamed_addr constant + // CHECK-DAG: @I = {{(dso_local )?}}local_unnamed_addr constant #[no_mangle] static I: u8 = 0; - // CHECK: @J = {{(dso_local )?}}local_unnamed_addr global + // CHECK-DAG: @J = {{(dso_local )?}}local_unnamed_addr global #[no_mangle] static mut J: u8 = 0; - // CHECK: @K = {{(dso_local )?}}local_unnamed_addr constant + // CHECK-DAG: @K = {{(dso_local )?}}local_unnamed_addr constant #[no_mangle] pub static K: u8 = 0; - // CHECK: @L = {{(dso_local )?}}local_unnamed_addr global + // CHECK-DAG: @L = {{(dso_local )?}}local_unnamed_addr global #[no_mangle] pub static mut L: u8 = 0; }; fn x() { - // CHECK: @M = {{(dso_local )?}}local_unnamed_addr constant + // CHECK-DAG: @M = {{(dso_local )?}}local_unnamed_addr constant #[no_mangle] static M: fn() = x; - // CHECK: @N = {{(dso_local )?}}local_unnamed_addr global + // CHECK-DAG: @N = {{(dso_local )?}}local_unnamed_addr global #[no_mangle] static mut N: u8 = 0; - // CHECK: @O = {{(dso_local )?}}local_unnamed_addr constant + // CHECK-DAG: @O = {{(dso_local )?}}local_unnamed_addr constant #[no_mangle] pub static O: u8 = 0; - // CHECK: @P = {{(dso_local )?}}local_unnamed_addr global + // CHECK-DAG: @P = {{(dso_local )?}}local_unnamed_addr global #[no_mangle] pub static mut P: u8 = 0; } diff --git a/tests/codegen/link_section.rs b/tests/codegen/link_section.rs index 196f5edb7d63..f62f69480793 100644 --- a/tests/codegen/link_section.rs +++ b/tests/codegen/link_section.rs @@ -3,7 +3,7 @@ #![crate_type = "lib"] -// CHECK: @VAR1 = {{(dso_local )?}}constant <{ [4 x i8] }> <{ [4 x i8] c"\01\00\00\00" }>, section ".test_one" +// CHECK: @VAR1 = {{(dso_local )?}}constant [4 x i8] c"\01\00\00\00", section ".test_one" #[no_mangle] #[link_section = ".test_one"] #[cfg(target_endian = "little")] diff --git a/tests/codegen/remap_path_prefix/main.rs b/tests/codegen/remap_path_prefix/main.rs index bfbccfe0df80..7d17b3b67cfa 100644 --- a/tests/codegen/remap_path_prefix/main.rs +++ b/tests/codegen/remap_path_prefix/main.rs @@ -12,7 +12,7 @@ mod aux_mod; include!("aux_mod.rs"); // Here we check that the expansion of the file!() macro is mapped. -// CHECK: @alloc_5761061597a97f66e13ef2ff92712c4b = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }> +// CHECK: @alloc_5761061597a97f66e13ef2ff92712c4b = private unnamed_addr constant [34 x i8] c"/the/src/remap_path_prefix/main.rs" pub static FILE_PATH: &'static str = file!(); fn main() { diff --git a/tests/codegen/uninit-consts.rs b/tests/codegen/uninit-consts.rs index a58008e171e2..bde71a35c47d 100644 --- a/tests/codegen/uninit-consts.rs +++ b/tests/codegen/uninit-consts.rs @@ -11,15 +11,15 @@ pub struct PartiallyUninit { y: MaybeUninit<[u8; 10]>, } -// CHECK: [[FULLY_UNINIT:@.*]] = private unnamed_addr constant <{ [10 x i8] }> undef +// CHECK: [[FULLY_UNINIT:@.*]] = private unnamed_addr constant [10 x i8] undef // CHECK: [[PARTIALLY_UNINIT:@.*]] = private unnamed_addr constant <{ [4 x i8], [12 x i8] }> <{ [4 x i8] c"{{\\EF\\BE\\AD\\DE|\\DE\\AD\\BE\\EF}}", [12 x i8] undef }>, align 4 // This shouldn't contain undef, since it contains more chunks // than the default value of uninit_const_chunk_threshold. -// CHECK: [[UNINIT_PADDING_HUGE:@.*]] = private unnamed_addr constant <{ [32768 x i8] }> <{ [32768 x i8] c"{{.+}}" }>, align 4 +// CHECK: [[UNINIT_PADDING_HUGE:@.*]] = private unnamed_addr constant [32768 x i8] c"{{.+}}", align 4 -// CHECK: [[FULLY_UNINIT_HUGE:@.*]] = private unnamed_addr constant <{ [16384 x i8] }> undef +// CHECK: [[FULLY_UNINIT_HUGE:@.*]] = private unnamed_addr constant [16384 x i8] undef // CHECK-LABEL: @fully_uninit #[no_mangle] From 5c82a59bd30815a942b64fa09e22dbe442edf56d Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 25 Mar 2025 12:57:42 +0000 Subject: [PATCH 636/745] Add test and comment --- compiler/rustc_codegen_llvm/src/consts.rs | 5 +++++ tests/assembly/cstring-merging.rs | 27 +++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 tests/assembly/cstring-merging.rs diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index a1ab6714d370..75b4ff1b6bbf 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -128,6 +128,11 @@ pub(crate) fn const_alloc_to_llvm<'ll>( append_chunks_of_init_and_uninit_bytes(&mut llvals, cx, alloc, range); } + // Avoid wrapping in a struct if there is only a single value. This ensures + // that LLVM is able to perform the string merging optimization if the constant + // is a valid C string. LLVM only considers bare arrays for this optimization, + // not arrays wrapped in a struct. LLVM handles this at: + // https://github.com/rust-lang/llvm-project/blob/acaea3d2bb8f351b740db7ebce7d7a40b9e21488/llvm/lib/Target/TargetLoweringObjectFile.cpp#L249-L280 if let &[data] = &*llvals { data } else { cx.const_struct(&llvals, true) } } diff --git a/tests/assembly/cstring-merging.rs b/tests/assembly/cstring-merging.rs new file mode 100644 index 000000000000..7436e2418230 --- /dev/null +++ b/tests/assembly/cstring-merging.rs @@ -0,0 +1,27 @@ +//@ only-linux +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type=lib -Copt-level=3 --edition 2024 + +use std::ffi::CStr; + +// CHECK: .section .rodata.str1.1,"aMS" +// CHECK: .Lanon.{{.+}}: +// CHECK-NEXT: .asciz "foo" +#[unsafe(no_mangle)] +static CSTR: &[u8; 4] = b"foo\0"; + +// CHECK-NOT: .section +// CHECK: .Lanon.{{.+}}: +// CHECK-NEXT: .asciz "bar" +#[unsafe(no_mangle)] +pub fn cstr() -> &'static CStr { + c"bar" +} + +// CHECK-NOT: .section +// CHECK: .Lanon.{{.+}}: +// CHECK-NEXT: .asciz "baz" +#[unsafe(no_mangle)] +pub fn manual_cstr() -> &'static str { + "baz\0" +} From 87d524bef68b6a63f965cec81e0ce28e00843907 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 28 Mar 2025 10:35:53 +0100 Subject: [PATCH 637/745] Update `coverage-run-rustdoc` output --- tests/coverage-run-rustdoc/doctest.coverage | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/coverage-run-rustdoc/doctest.coverage b/tests/coverage-run-rustdoc/doctest.coverage index f007eb0cadea..0fa94361c472 100644 --- a/tests/coverage-run-rustdoc/doctest.coverage +++ b/tests/coverage-run-rustdoc/doctest.coverage @@ -58,21 +58,21 @@ $DIR/doctest.rs: LL| |//! LL| |//! doctest with custom main: LL| |//! ``` - LL| 1|//! fn some_func() { - LL| 1|//! println!("called some_func()"); - LL| 1|//! } - LL| |//! - LL| |//! #[derive(Debug)] - LL| |//! struct SomeError; + LL| |//! fn some_func() { + LL| |//! println!("called some_func()"); + LL| |//! } + LL| 1|//! + LL| 1|//! #[derive(Debug)] + LL| 1|//! struct SomeError; LL| |//! LL| |//! extern crate doctest_crate; LL| |//! - LL| 1|//! fn doctest_main() -> Result<(), SomeError> { + LL| |//! fn doctest_main() -> Result<(), SomeError> { LL| 1|//! some_func(); LL| 1|//! doctest_crate::fn_run_in_doctests(2); LL| 1|//! Ok(()) LL| 1|//! } - LL| |//! + LL| 1|//! LL| |//! // this `main` is not shown as covered, as it clashes with all the other LL| |//! // `main` functions that were automatically generated for doctests LL| |//! fn main() -> Result<(), SomeError> { From 024c8c306318d8dfd6a8d63f7df1b22423fa1398 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 28 Mar 2025 12:07:33 +0100 Subject: [PATCH 638/745] cache mangle_internal_symbol results --- src/tools/miri/src/helpers.rs | 13 ++++++ src/tools/miri/src/machine.rs | 5 ++ src/tools/miri/src/shims/foreign_items.rs | 57 +++++++++-------------- 3 files changed, 41 insertions(+), 34 deletions(-) diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index d1429a0be1d0..29ed94a2e4a2 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -17,6 +17,7 @@ use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, MaybeResult, TyAndLayout}; use rustc_middle::ty::{self, Binder, FloatTy, FnSig, IntTy, Ty, TyCtxt, UintTy}; use rustc_session::config::CrateType; use rustc_span::{Span, Symbol}; +use rustc_symbol_mangling::mangle_internal_symbol; use rustc_target::callconv::{Conv, FnAbi}; use crate::*; @@ -1258,6 +1259,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { interp_ok(array) } + + fn mangle_internal_symbol<'a>(&'a mut self, name: &'static str) -> &'a str + where + 'tcx: 'a, + { + let this = self.eval_context_mut(); + let tcx = *this.tcx; + this.machine + .mangle_internal_symbol_cache + .entry(name) + .or_insert_with(|| mangle_internal_symbol(tcx, name)) + } } impl<'tcx> MiriMachine<'tcx> { diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index bd901a4ed19e..fb99bdc51764 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -611,6 +611,9 @@ pub struct MiriMachine<'tcx> { pub(crate) reject_in_isolation_warned: RefCell>, /// Remembers which int2ptr casts we have already warned about. pub(crate) int2ptr_warned: RefCell>, + + /// Cache for `mangle_internal_symbol`. + pub(crate) mangle_internal_symbol_cache: FxHashMap<&'static str, String>, } impl<'tcx> MiriMachine<'tcx> { @@ -757,6 +760,7 @@ impl<'tcx> MiriMachine<'tcx> { native_call_mem_warned: Cell::new(false), reject_in_isolation_warned: Default::default(), int2ptr_warned: Default::default(), + mangle_internal_symbol_cache: Default::default(), } } @@ -930,6 +934,7 @@ impl VisitProvenance for MiriMachine<'_> { native_call_mem_warned: _, reject_in_isolation_warned: _, int2ptr_warned: _, + mangle_internal_symbol_cache: _, } = self; threads.visit_provenance(visit); diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 03c6081e992c..52c16a0c2e2d 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -9,10 +9,9 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::CrateNum; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::interpret::AllocInit; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{Instance, Ty}; use rustc_middle::{mir, ty}; use rustc_span::Symbol; -use rustc_symbol_mangling::mangle_internal_symbol; use rustc_target::callconv::{Conv, FnAbi}; use self::helpers::{ToHost, ToSoft}; @@ -52,7 +51,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Some shims forward to other MIR bodies. match link_name.as_str() { - name if name == mangle_internal_symbol(*this.tcx, "__rust_alloc_error_handler") => { + name if name == this.mangle_internal_symbol("__rust_alloc_error_handler") => { // Forward to the right symbol that implements this function. let Some(handler_kind) = this.tcx.alloc_error_handler_kind(()) else { // in real code, this symbol does not exist without an allocator @@ -60,11 +59,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "`__rust_alloc_error_handler` cannot be called when no alloc error handler is set" ); }; - let name = - mangle_internal_symbol(*this.tcx, alloc_error_handler_name(handler_kind)); - let handler = this - .lookup_exported_symbol(Symbol::intern(&name))? - .expect("missing alloc error handler symbol"); + let name = Symbol::intern( + this.mangle_internal_symbol(alloc_error_handler_name(handler_kind)), + ); + let handler = + this.lookup_exported_symbol(name)?.expect("missing alloc error handler symbol"); return interp_ok(Some(handler)); } _ => {} @@ -138,30 +137,22 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Find it if it was not cached. let mut instance_and_crate: Option<(ty::Instance<'_>, CrateNum)> = None; helpers::iter_exported_symbols(tcx, |cnum, def_id| { + let attrs = tcx.codegen_fn_attrs(def_id); + // Skip over imports of items. if tcx.is_foreign_item(def_id) { - // Skip over imports of items + return interp_ok(()); + } + // Skip over items without an explicitly defined symbol name. + if !(attrs.export_name.is_some() + || attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) + || attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)) + { return interp_ok(()); } - let attrs = tcx.codegen_fn_attrs(def_id); - // FIXME use tcx.symbol_name(instance) instead - let symbol_name = if let Some(export_name) = attrs.export_name { - export_name - } else if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) - || attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) - { - tcx.item_name(def_id) - } else { - // Skip over items without an explicitly defined symbol name. - return interp_ok(()); - }; - let symbol_name = - if attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) { - Symbol::intern(&mangle_internal_symbol(tcx, symbol_name.as_str())) - } else { - symbol_name - }; - if symbol_name == link_name { + let instance = Instance::mono(tcx, def_id); + let symbol_name = tcx.symbol_name(instance).name; + if symbol_name == link_name.as_str() { if let Some((original_instance, original_cnum)) = instance_and_crate { // Make sure we are consistent wrt what is 'first' and 'second'. let original_span = tcx.def_span(original_instance.def_id()).data(); @@ -505,9 +496,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } // Rust allocation - name if name == mangle_internal_symbol(*this.tcx, "__rust_alloc") - || name == "miri_alloc" => - { + name if name == this.mangle_internal_symbol("__rust_alloc") || name == "miri_alloc" => { let default = |ecx: &mut MiriInterpCx<'tcx>| { // Only call `check_shim` when `#[global_allocator]` isn't used. When that // macro is used, we act like no shim exists, so that the exported function can run. @@ -540,7 +529,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { _ => return this.emulate_allocator(default), } } - name if name == mangle_internal_symbol(*this.tcx, "__rust_alloc_zeroed") => { + name if name == this.mangle_internal_symbol("__rust_alloc_zeroed") => { return this.emulate_allocator(|this| { // See the comment for `__rust_alloc` why `check_shim` is only called in the // default case. @@ -559,7 +548,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_pointer(ptr, dest) }); } - name if name == mangle_internal_symbol(*this.tcx, "__rust_dealloc") + name if name == this.mangle_internal_symbol("__rust_dealloc") || name == "miri_dealloc" => { let default = |ecx: &mut MiriInterpCx<'tcx>| { @@ -592,7 +581,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { _ => return this.emulate_allocator(default), } } - name if name == mangle_internal_symbol(*this.tcx, "__rust_realloc") => { + name if name == this.mangle_internal_symbol("__rust_realloc") => { return this.emulate_allocator(|this| { // See the comment for `__rust_alloc` why `check_shim` is only called in the // default case. From 827cb1b2a7b4334b38b20c291a95de62894c335c Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Fri, 28 Mar 2025 12:14:09 +0000 Subject: [PATCH 639/745] use `try_fold` instead of `fold` --- compiler/stable_mir/src/mir/body.rs | 3 +-- compiler/stable_mir/src/mir/visit.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index b1bf7bce828c..2a1c163de3c4 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -1057,8 +1057,7 @@ impl Place { /// In order to retrieve the correct type, the `locals` argument must match the list of all /// locals from the function body where this place originates from. pub fn ty(&self, locals: &[LocalDecl]) -> Result { - let start_ty = locals[self.local].ty; - self.projection.iter().fold(Ok(start_ty), |place_ty, elem| elem.ty(place_ty?)) + self.projection.iter().try_fold(locals[self.local].ty, |place_ty, elem| elem.ty(place_ty)) } } diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs index 09447e70dfb1..9d2368ba3320 100644 --- a/compiler/stable_mir/src/mir/visit.rs +++ b/compiler/stable_mir/src/mir/visit.rs @@ -563,7 +563,7 @@ pub struct PlaceRef<'a> { impl PlaceRef<'_> { /// Get the type of this place. pub fn ty(&self, locals: &[LocalDecl]) -> Result { - self.projection.iter().fold(Ok(locals[self.local].ty), |place_ty, elem| elem.ty(place_ty?)) + self.projection.iter().try_fold(locals[self.local].ty, |place_ty, elem| elem.ty(place_ty)) } } From 9ef35ddc0ca236db91d444a31de5fc8ac835ce9b Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Fri, 28 Mar 2025 12:21:21 +0000 Subject: [PATCH 640/745] use `slice::contains` where applicable --- compiler/rustc_builtin_macros/src/edition_panic.rs | 10 +++++----- compiler/rustc_codegen_ssa/src/back/write.rs | 2 +- compiler/rustc_codegen_ssa/src/codegen_attrs.rs | 2 +- compiler/rustc_mir_build/src/builder/scope.rs | 2 +- compiler/rustc_passes/src/entry.rs | 2 +- compiler/rustc_session/src/utils.rs | 11 ++++++----- compiler/rustc_span/src/lib.rs | 2 +- 7 files changed, 16 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/edition_panic.rs b/compiler/rustc_builtin_macros/src/edition_panic.rs index b39c9861fd64..ccfcc3079ebf 100644 --- a/compiler/rustc_builtin_macros/src/edition_panic.rs +++ b/compiler/rustc_builtin_macros/src/edition_panic.rs @@ -74,11 +74,11 @@ pub(crate) fn use_panic_2021(mut span: Span) -> bool { // (To avoid using the edition of e.g. the assert!() or debug_assert!() definition.) loop { let expn = span.ctxt().outer_expn_data(); - if let Some(features) = expn.allow_internal_unstable { - if features.iter().any(|&f| f == sym::edition_panic) { - span = expn.call_site; - continue; - } + if let Some(features) = expn.allow_internal_unstable + && features.contains(&sym::edition_panic) + { + span = expn.call_site; + continue; } break expn.edition >= Edition::Edition2021; } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 216a18e72edf..ccc0273280fe 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -2186,7 +2186,7 @@ fn msvc_imps_needed(tcx: TyCtxt<'_>) -> bool { // indirectly from ThinLTO. In theory these are not needed as ThinLTO could resolve // these, but it currently does not do so. let can_have_static_objects = - tcx.sess.lto() == Lto::Thin || tcx.crate_types().iter().any(|ct| *ct == CrateType::Rlib); + tcx.sess.lto() == Lto::Thin || tcx.crate_types().contains(&CrateType::Rlib); tcx.sess.target.is_like_windows && can_have_static_objects && diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index d16d4ed22838..a85d032f36ee 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -604,7 +604,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { if let Some((name, _)) = lang_items::extract(attrs) && let Some(lang_item) = LangItem::from_name(name) { - if WEAK_LANG_ITEMS.iter().any(|&l| l == lang_item) { + if WEAK_LANG_ITEMS.contains(&lang_item) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; } if let Some(link_name) = lang_item.link_name() { diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index e56c0ae92cac..e42336a1dbbc 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -1496,7 +1496,7 @@ fn build_scope_drops<'tcx>( // path, then don't generate the drop. (We only take this into // account for non-unwind paths so as not to disturb the // caching mechanism.) - if scope.moved_locals.iter().any(|&o| o == local) { + if scope.moved_locals.contains(&local) { continue; } diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index d2729876ebbb..2a435c4b2e05 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -24,7 +24,7 @@ struct EntryContext<'tcx> { } fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> { - let any_exe = tcx.crate_types().iter().any(|ty| *ty == CrateType::Executable); + let any_exe = tcx.crate_types().contains(&CrateType::Executable); if !any_exe { // No need to find a main function. return None; diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs index fcede379b893..2243e831b66e 100644 --- a/compiler/rustc_session/src/utils.rs +++ b/compiler/rustc_session/src/utils.rs @@ -149,14 +149,15 @@ pub fn extra_compiler_flags() -> Option<(Vec, bool)> { arg[a.len()..].to_string() }; let option = content.split_once('=').map(|s| s.0).unwrap_or(&content); - if ICE_REPORT_COMPILER_FLAGS_EXCLUDE.iter().any(|exc| option == *exc) { + if ICE_REPORT_COMPILER_FLAGS_EXCLUDE.contains(&option) { excluded_cargo_defaults = true; } else { result.push(a.to_string()); - match ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.iter().find(|s| option == **s) { - Some(s) => result.push(format!("{s}=[REDACTED]")), - None => result.push(content), - } + result.push(if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&option) { + format!("{option}=[REDACTED]") + } else { + content + }); } } } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index f19d4d9f3624..9e6ba2e1b9ce 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -876,7 +876,7 @@ impl Span { self.ctxt() .outer_expn_data() .allow_internal_unstable - .is_some_and(|features| features.iter().any(|&f| f == feature)) + .is_some_and(|features| features.contains(&feature)) } /// Checks if this span arises from a compiler desugaring of kind `kind`. From 0f418520c649f6bd0e731b4315a7c79b40df8e0e Mon Sep 17 00:00:00 2001 From: Rafael Bachmann Date: Fri, 28 Mar 2025 13:22:09 +0100 Subject: [PATCH 641/745] Fix formatting nit in process.rs --- library/std/src/process.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index f81ce8e1a1a1..3b765a9537bc 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1836,7 +1836,7 @@ impl crate::sealed::Sealed for ExitStatusError {} /// # if cfg!(unix) { /// use std::process::{Command, ExitStatusError}; /// -/// fn run(cmd: &str) -> Result<(),ExitStatusError> { +/// fn run(cmd: &str) -> Result<(), ExitStatusError> { /// Command::new(cmd).status().unwrap().exit_ok()?; /// Ok(()) /// } From 7310925076c797d67d3df026c6b22f9a73380661 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 28 Mar 2025 15:28:14 +0100 Subject: [PATCH 642/745] update lockfile --- Cargo.lock | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 856d293d610e..90e035e80106 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -547,7 +547,7 @@ dependencies = [ "termize", "tokio", "toml 0.7.8", - "ui_test 0.29.2", + "ui_test", "walkdir", ] @@ -2292,7 +2292,7 @@ dependencies = [ "smallvec", "tempfile", "tikv-jemalloc-sys", - "ui_test 0.28.0", + "ui_test", "windows-sys 0.52.0", ] @@ -5486,32 +5486,6 @@ dependencies = [ "regex-lite", ] -[[package]] -name = "ui_test" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7484683d60d50ca1d1b6433c3dbf6c5ad71d20387acdcfb16fe79573f3fba576" -dependencies = [ - "annotate-snippets 0.11.5", - "anyhow", - "bstr", - "cargo-platform", - "cargo_metadata 0.18.1", - "color-eyre", - "colored", - "comma", - "crossbeam-channel", - "indicatif", - "levenshtein", - "prettydiff", - "regex", - "rustc_version", - "rustfix", - "serde", - "serde_json", - "spanned", -] - [[package]] name = "ui_test" version = "0.29.2" From 074edbd89c0c116f10918e0bf07a5227b3922a33 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Fri, 28 Mar 2025 19:48:40 +0800 Subject: [PATCH 643/745] std: Explain range follows standard half-open range in `offset` Signed-off-by: xizheyin --- library/core/src/ptr/const_ptr.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 7d0839aff3f7..71a84aff2460 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -386,7 +386,8 @@ impl *const T { /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some /// [allocated object], and the entire memory range between `self` and the result must be in /// bounds of that allocated object. In particular, this range must not "wrap around" the edge - /// of the address space. + /// of the address space. Note that "range" here refers to a half-open range as usual in Rust, + /// i.e., `self..result` for non-negative offsets and `result..self` for negative offsets. /// /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. From 9055765ce1c89b0bc619df39aa8ba66ad641da9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Fri, 28 Mar 2025 15:58:41 +0100 Subject: [PATCH 644/745] `io::Take`: avoid new `BorrowedBuf` creation in some case --- library/std/src/io/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 6579b6887aaa..314cbb45d49e 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -2989,11 +2989,11 @@ impl Read for Take { return Ok(()); } - if self.limit <= buf.capacity() as u64 { - // if we just use an as cast to convert, limit may wrap around on a 32 bit target - let limit = cmp::min(self.limit, usize::MAX as u64) as usize; + if self.limit < buf.capacity() as u64 { + // The condition above guarantees that `self.limit` fits in `usize`. + let limit = self.limit as usize; - let extra_init = cmp::min(limit as usize, buf.init_ref().len()); + let extra_init = cmp::min(limit, buf.init_ref().len()); // SAFETY: no uninit data is written to ibuf let ibuf = unsafe { &mut buf.as_mut()[..limit] }; From 9300fa19b73e569d7c38f51149d9537a6ef0a232 Mon Sep 17 00:00:00 2001 From: Boxy Date: Fri, 28 Mar 2025 16:53:17 +0000 Subject: [PATCH 645/745] Bump to 1.88.0 --- src/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version b/src/version index f6342716723f..59be592144c2 100644 --- a/src/version +++ b/src/version @@ -1 +1 @@ -1.87.0 +1.88.0 From dabee5d5635fd9f5093031df19cacf805292528c Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 28 Mar 2025 17:01:23 +0000 Subject: [PATCH 646/745] Do not treat lifetimes from parent items as influencing child items --- compiler/rustc_resolve/src/late.rs | 5 ++++- .../static-default-lifetime/static-trait-impl.rs | 13 +++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 533e216ddb29..0d23ae501f04 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1833,7 +1833,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } LifetimeRibKind::StaticIfNoLifetimeInScope { lint_id: node_id, emit_lint } => { let mut lifetimes_in_scope = vec![]; - for rib in &self.lifetime_ribs[..i] { + for rib in self.lifetime_ribs[..i].iter().rev() { lifetimes_in_scope.extend(rib.bindings.iter().map(|(ident, _)| ident.span)); // Consider any anonymous lifetimes, too if let LifetimeRibKind::AnonymousCreateParameter { binder, .. } = rib.kind @@ -1841,6 +1841,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { { lifetimes_in_scope.extend(extra.iter().map(|(ident, _, _)| ident.span)); } + if let LifetimeRibKind::Item = rib.kind { + break; + } } if lifetimes_in_scope.is_empty() { self.record_lifetime_res( diff --git a/tests/ui/consts/static-default-lifetime/static-trait-impl.rs b/tests/ui/consts/static-default-lifetime/static-trait-impl.rs index b50bf01453dc..1e12259e4833 100644 --- a/tests/ui/consts/static-default-lifetime/static-trait-impl.rs +++ b/tests/ui/consts/static-default-lifetime/static-trait-impl.rs @@ -17,4 +17,17 @@ impl Bar<'static> for B { const STATIC: &str = ""; } +struct C; +impl Bar<'_> for C { + // make ^^ not cause + const STATIC: &'static str = { + struct B; + impl Bar<'static> for B { + const STATIC: &str = ""; + // ^ to emit a future incompat warning + } + "" + }; +} + fn main() {} From 7a295d1be07d191527dfcdf4613ced7ab6fa9676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Fri, 28 Mar 2025 15:14:35 +0100 Subject: [PATCH 647/745] Fix TAIT & ATPIT feature gating in the presence of anon consts --- compiler/rustc_ast_passes/src/feature_gate.rs | 7 ++ .../feature-gate-impl_trait_in_assoc_type.rs | 9 ++ ...ature-gate-impl_trait_in_assoc_type.stderr | 20 +++- .../feature-gate-type_alias_impl_trait.rs | 26 ++-- .../feature-gate-type_alias_impl_trait.stderr | 111 ++++++++++++++++++ tests/ui/impl-trait/impl_trait_projections.rs | 5 + .../impl-trait/impl_trait_projections.stderr | 10 +- .../inside-item-nested-in-anon-const.rs | 25 ++++ 8 files changed, 200 insertions(+), 13 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr create mode 100644 tests/ui/impl-trait/inside-item-nested-in-anon-const.rs diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 31ff102c127a..a3fcc110a166 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -99,6 +99,13 @@ impl<'a> PostExpansionVisitor<'a> { } visit::walk_ty(self, ty); } + + fn visit_anon_const(&mut self, _: &ast::AnonConst) -> Self::Result { + // We don't walk the anon const because it crosses a conceptual boundary: We're no + // longer "inside" the original type. + // Brittle: We assume that the callers of `check_impl_trait` will later recurse into + // the items found in the AnonConst to look for nested TyAliases. + } } ImplTraitVisitor { vis: self, in_associated_ty }.visit_ty(ty); } diff --git a/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.rs b/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.rs index 2c130664e9a1..f9b5176d78ac 100644 --- a/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.rs +++ b/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.rs @@ -17,4 +17,13 @@ impl Mop { //~| ERROR: unconstrained opaque type } +fn funky(_: [(); { + impl Foo for fn() { + type Bar = impl Sized; + //~^ ERROR: `impl Trait` in associated types is unstable + //~| ERROR: unconstrained opaque type + } + 0 +}]) {} + fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr b/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr index 7dfd79c72864..01d25c162281 100644 --- a/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr +++ b/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr @@ -18,6 +18,16 @@ LL | type Bop = impl std::fmt::Debug; = help: add `#![feature(impl_trait_in_assoc_type)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0658]: `impl Trait` in associated types is unstable + --> $DIR/feature-gate-impl_trait_in_assoc_type.rs:22:20 + | +LL | type Bar = impl Sized; + | ^^^^^^^^^^ + | + = note: see issue #63063 for more information + = help: add `#![feature(impl_trait_in_assoc_type)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error[E0658]: inherent associated types are unstable --> $DIR/feature-gate-impl_trait_in_assoc_type.rs:14:5 | @@ -44,6 +54,14 @@ LL | type Bop = impl std::fmt::Debug; | = note: `Bop` must be used in combination with a concrete type within the same impl -error: aborting due to 5 previous errors +error: unconstrained opaque type + --> $DIR/feature-gate-impl_trait_in_assoc_type.rs:22:20 + | +LL | type Bar = impl Sized; + | ^^^^^^^^^^ + | + = note: `Bar` must be used in combination with a concrete type within the same impl + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs index ec70a20844a5..d332fba0623c 100644 --- a/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs +++ b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs @@ -1,38 +1,42 @@ -//@ check-pass -#![feature(type_alias_impl_trait)] use std::fmt::Debug; -type Foo = impl Debug; +type Foo = impl Debug; //~ ERROR `impl Trait` in type aliases is unstable struct Bar(Foo); -#[define_opaque(Foo)] +#[define_opaque(Foo)] //~ ERROR use of unstable library feature `type_alias_impl_trait` fn define() -> Bar { Bar(42) } -type Foo2 = impl Debug; +type Foo2 = impl Debug; //~ ERROR `impl Trait` in type aliases is unstable -#[define_opaque(Foo2)] +#[define_opaque(Foo2)] //~ ERROR use of unstable library feature `type_alias_impl_trait` fn define2() { let x = || -> Foo2 { 42 }; } -type Foo3 = impl Debug; +type Foo3 = impl Debug; //~ ERROR `impl Trait` in type aliases is unstable -#[define_opaque(Foo3)] +#[define_opaque(Foo3)] //~ ERROR use of unstable library feature `type_alias_impl_trait` fn define3(x: Foo3) { let y: i32 = x; } -#[define_opaque(Foo3)] +#[define_opaque(Foo3)] //~ ERROR use of unstable library feature `type_alias_impl_trait` fn define3_1() { define3(42) } -type Foo4 = impl Debug; +type Foo4 = impl Debug; //~ ERROR `impl Trait` in type aliases is unstable -#[define_opaque(Foo4)] +#[define_opaque(Foo4)] //~ ERROR use of unstable library feature `type_alias_impl_trait` fn define4(_: Foo4) { let y: Foo4 = 42; } +type Foo5 = [(); { + type Foo = impl Debug; //~ ERROR `impl Trait` in type aliases is unstable + //~^ ERROR unconstrained opaque type + 0 +}]; + fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr new file mode 100644 index 000000000000..bab60eb42930 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr @@ -0,0 +1,111 @@ +error[E0658]: use of unstable library feature `type_alias_impl_trait`: `type_alias_impl_trait` has open design concerns + --> $DIR/feature-gate-type_alias_impl_trait.rs:6:3 + | +LL | #[define_opaque(Foo)] + | ^^^^^^^^^^^^^ + | + = note: see issue #63063 for more information + = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `type_alias_impl_trait`: `type_alias_impl_trait` has open design concerns + --> $DIR/feature-gate-type_alias_impl_trait.rs:13:3 + | +LL | #[define_opaque(Foo2)] + | ^^^^^^^^^^^^^ + | + = note: see issue #63063 for more information + = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `type_alias_impl_trait`: `type_alias_impl_trait` has open design concerns + --> $DIR/feature-gate-type_alias_impl_trait.rs:20:3 + | +LL | #[define_opaque(Foo3)] + | ^^^^^^^^^^^^^ + | + = note: see issue #63063 for more information + = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `type_alias_impl_trait`: `type_alias_impl_trait` has open design concerns + --> $DIR/feature-gate-type_alias_impl_trait.rs:24:3 + | +LL | #[define_opaque(Foo3)] + | ^^^^^^^^^^^^^ + | + = note: see issue #63063 for more information + = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `type_alias_impl_trait`: `type_alias_impl_trait` has open design concerns + --> $DIR/feature-gate-type_alias_impl_trait.rs:31:3 + | +LL | #[define_opaque(Foo4)] + | ^^^^^^^^^^^^^ + | + = note: see issue #63063 for more information + = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `impl Trait` in type aliases is unstable + --> $DIR/feature-gate-type_alias_impl_trait.rs:3:12 + | +LL | type Foo = impl Debug; + | ^^^^^^^^^^ + | + = note: see issue #63063 for more information + = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `impl Trait` in type aliases is unstable + --> $DIR/feature-gate-type_alias_impl_trait.rs:11:13 + | +LL | type Foo2 = impl Debug; + | ^^^^^^^^^^ + | + = note: see issue #63063 for more information + = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `impl Trait` in type aliases is unstable + --> $DIR/feature-gate-type_alias_impl_trait.rs:18:13 + | +LL | type Foo3 = impl Debug; + | ^^^^^^^^^^ + | + = note: see issue #63063 for more information + = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `impl Trait` in type aliases is unstable + --> $DIR/feature-gate-type_alias_impl_trait.rs:29:13 + | +LL | type Foo4 = impl Debug; + | ^^^^^^^^^^ + | + = note: see issue #63063 for more information + = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `impl Trait` in type aliases is unstable + --> $DIR/feature-gate-type_alias_impl_trait.rs:37:16 + | +LL | type Foo = impl Debug; + | ^^^^^^^^^^ + | + = note: see issue #63063 for more information + = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: unconstrained opaque type + --> $DIR/feature-gate-type_alias_impl_trait.rs:37:16 + | +LL | type Foo = impl Debug; + | ^^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same crate + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/impl-trait/impl_trait_projections.rs b/tests/ui/impl-trait/impl_trait_projections.rs index 2c277aee06da..89fe3c1509cc 100644 --- a/tests/ui/impl-trait/impl_trait_projections.rs +++ b/tests/ui/impl-trait/impl_trait_projections.rs @@ -35,4 +35,9 @@ fn projection_from_impl_trait_inside_dyn_trait_is_disallowed() panic!() } +fn parametrized_value_in_anon_const_is_disallowed() -> [(); None::] { + //~^ ERROR `impl Trait` is not allowed in paths + loop {} +} + fn main() {} diff --git a/tests/ui/impl-trait/impl_trait_projections.stderr b/tests/ui/impl-trait/impl_trait_projections.stderr index 5e0b80fcd592..21f45613938f 100644 --- a/tests/ui/impl-trait/impl_trait_projections.stderr +++ b/tests/ui/impl-trait/impl_trait_projections.stderr @@ -30,6 +30,14 @@ LL | -> as Iterator>::Item | = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error: aborting due to 4 previous errors +error[E0562]: `impl Trait` is not allowed in paths + --> $DIR/impl_trait_projections.rs:38:68 + | +LL | fn parametrized_value_in_anon_const_is_disallowed() -> [(); None::] { + | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/impl-trait/inside-item-nested-in-anon-const.rs b/tests/ui/impl-trait/inside-item-nested-in-anon-const.rs new file mode 100644 index 000000000000..ab54d5f87bae --- /dev/null +++ b/tests/ui/impl-trait/inside-item-nested-in-anon-const.rs @@ -0,0 +1,25 @@ +// Ensure we don't misclassify `impl Trait` as TAIT/ATPIT if located inside an anon const in a +// type alias/assoc type. +// issue: +//@ check-pass +#![forbid(unstable_features)] + +struct Girder; + +type Alias = Girder<{ + fn pass(input: impl Sized) -> impl Sized { input } + 0 +}>; + +trait Trait { + type Assoc; +} + +impl Trait for () { + type Assoc = [(); { + fn pass(input: impl Sized) -> impl Sized { input } + 0 + }]; +} + +fn main() {} From e6a2c29bc4e935e6abda1f5348cf726590d302aa Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Fri, 28 Mar 2025 14:15:08 -0400 Subject: [PATCH 648/745] tracking autodiff files via triagebot.toml --- triagebot.toml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index ebbcfa4516b9..d7ec803d1cf1 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -254,6 +254,16 @@ trigger_files = [ "compiler/rustc_attr_data_structures", ] +[autolabel."F-autodiff"] +trigger_files = [ + "src/tools/enzyme", + "src/doc/unstable-book/src/compiler-flags/autodiff.md", + "compiler/rustc_ast/src/expand/autodiff_attrs.rs", + "compiler/rustc_monomorphize/src/partitioning/autodiff.rs", + "compiler/rustc_codegen_llvm/src/builder/autodiff.rs", + "compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs", +] + [autolabel."T-rustdoc-frontend"] trigger_labels = [ "A-rustdoc-search", @@ -1092,6 +1102,23 @@ cc = ["@jdonszelmann"] [mentions."compiler/rustc_attr_data_structures"] cc = ["@jdonszelmann"] +[mentions."src/tools/enzyme"] +cc = ["@ZuseZ4"] +[mentions."src/doc/unstable-book/src/compiler-flags/autodiff.md"] +cc = ["@ZuseZ4"] +[mentions."compiler/rustc_ast/src/expand/autodiff_attrs.rs"] +cc = ["@ZuseZ4"] +[mentions."compiler/rustc_ast/src/expand/typetree.rs"] +cc = ["@ZuseZ4"] +[mentions."compiler/rustc_builtin_macros/src/autodiff.rs"] +cc = ["@ZuseZ4"] +[mentions."compiler/rustc_monomorphize/src/partitioning/autodiff.rs"] +cc = ["@ZuseZ4"] +[mentions."compiler/rustc_codegen_llvm/src/builder/autodiff.rs"] +cc = ["@ZuseZ4"] +[mentions."compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs"] +cc = ["@ZuseZ4"] + [assign] warn_non_default_branch.enable = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" From dd4f616423219d81ffd34786d6a589b3ad7ba803 Mon Sep 17 00:00:00 2001 From: joboet Date: Fri, 28 Mar 2025 19:32:36 +0100 Subject: [PATCH 649/745] std: deduplicate `errno` accesses By marking `__errno_location` as `#[ffi_const]` and `std::sys::os::errno` as `#[inline]`, this PR allows merging multiple calls to `io::Error::last_os_error()` into one. --- library/std/src/lib.rs | 1 + library/std/src/sys/pal/unix/os.rs | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index ad005833ad53..9dcedaa13f66 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -297,6 +297,7 @@ #![feature(extended_varargs_abi_support)] #![feature(f128)] #![feature(f16)] +#![feature(ffi_const)] #![feature(formatting_options)] #![feature(if_let_guard)] #![feature(intra_doc_pointers)] diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index 30282fbf6554..f47421c67051 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -59,11 +59,14 @@ unsafe extern "C" { #[cfg_attr(any(target_os = "freebsd", target_vendor = "apple"), link_name = "__error")] #[cfg_attr(target_os = "haiku", link_name = "_errnop")] #[cfg_attr(target_os = "aix", link_name = "_Errno")] + // SAFETY: this will always return the same pointer on a given thread. + #[unsafe(ffi_const)] fn errno_location() -> *mut c_int; } /// Returns the platform-specific value of errno #[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))] +#[inline] pub fn errno() -> i32 { unsafe { (*errno_location()) as i32 } } @@ -72,16 +75,19 @@ pub fn errno() -> i32 { // needed for readdir and syscall! #[cfg(all(not(target_os = "dragonfly"), not(target_os = "vxworks"), not(target_os = "rtems")))] #[allow(dead_code)] // but not all target cfgs actually end up using it +#[inline] pub fn set_errno(e: i32) { unsafe { *errno_location() = e as c_int } } #[cfg(target_os = "vxworks")] +#[inline] pub fn errno() -> i32 { unsafe { libc::errnoGet() } } #[cfg(target_os = "rtems")] +#[inline] pub fn errno() -> i32 { unsafe extern "C" { #[thread_local] @@ -92,6 +98,7 @@ pub fn errno() -> i32 { } #[cfg(target_os = "dragonfly")] +#[inline] pub fn errno() -> i32 { unsafe extern "C" { #[thread_local] @@ -103,6 +110,7 @@ pub fn errno() -> i32 { #[cfg(target_os = "dragonfly")] #[allow(dead_code)] +#[inline] pub fn set_errno(e: i32) { unsafe extern "C" { #[thread_local] From 7c74474d8d9fb2a714d86bae7a5099d27899e150 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 28 Mar 2025 16:32:28 +0300 Subject: [PATCH 650/745] hygiene: Rewrite `apply_mark_internal` to be more understandable --- compiler/rustc_span/src/hygiene.rs | 119 +++++++++--------- .../nonterminal-token-hygiene.stdout | 20 +-- 2 files changed, 70 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 4390085cd049..e7a8dee27f56 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -75,6 +75,21 @@ pub struct SyntaxContextData { } impl SyntaxContextData { + fn new( + (parent, outer_expn, outer_transparency): SyntaxContextKey, + opaque: SyntaxContext, + opaque_and_semitransparent: SyntaxContext, + ) -> SyntaxContextData { + SyntaxContextData { + outer_expn, + outer_transparency, + parent, + opaque, + opaque_and_semitransparent, + dollar_crate_name: kw::DollarCrate, + } + } + fn root() -> SyntaxContextData { SyntaxContextData { outer_expn: ExpnId::root(), @@ -543,7 +558,7 @@ impl HygieneData { ) -> SyntaxContext { assert_ne!(expn_id, ExpnId::root()); if transparency == Transparency::Opaque { - return self.apply_mark_internal(ctxt, expn_id, transparency); + return self.alloc_ctxt(ctxt, expn_id, transparency); } let call_site_ctxt = self.expn_data(expn_id).call_site.ctxt(); @@ -554,7 +569,7 @@ impl HygieneData { }; if call_site_ctxt.is_root() { - return self.apply_mark_internal(ctxt, expn_id, transparency); + return self.alloc_ctxt(ctxt, expn_id, transparency); } // Otherwise, `expn_id` is a macros 1.0 definition and the call site is in a @@ -567,74 +582,60 @@ impl HygieneData { // // See the example at `test/ui/hygiene/legacy_interaction.rs`. for (expn_id, transparency) in self.marks(ctxt) { - call_site_ctxt = self.apply_mark_internal(call_site_ctxt, expn_id, transparency); + call_site_ctxt = self.alloc_ctxt(call_site_ctxt, expn_id, transparency); } - self.apply_mark_internal(call_site_ctxt, expn_id, transparency) + self.alloc_ctxt(call_site_ctxt, expn_id, transparency) } - fn apply_mark_internal( + /// Allocate a new context with the given key, or retrieve it from cache if the given key + /// already exists. The auxiliary fields are calculated from the key. + fn alloc_ctxt( &mut self, - ctxt: SyntaxContext, + parent: SyntaxContext, expn_id: ExpnId, transparency: Transparency, ) -> SyntaxContext { - let syntax_context_data = &mut self.syntax_context_data; - debug_assert!(!syntax_context_data[ctxt.0 as usize].is_decode_placeholder()); - let mut opaque = syntax_context_data[ctxt.0 as usize].opaque; - let mut opaque_and_semitransparent = - syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent; + debug_assert!(!self.syntax_context_data[parent.0 as usize].is_decode_placeholder()); - if transparency >= Transparency::Opaque { - let parent = opaque; - opaque = *self - .syntax_context_map - .entry((parent, expn_id, transparency)) - .or_insert_with(|| { - let new_opaque = SyntaxContext::from_usize(syntax_context_data.len()); - syntax_context_data.push(SyntaxContextData { - outer_expn: expn_id, - outer_transparency: transparency, - parent, - opaque: new_opaque, - opaque_and_semitransparent: new_opaque, - dollar_crate_name: kw::DollarCrate, - }); - new_opaque - }); + // Look into the cache first. + let key = (parent, expn_id, transparency); + if let Some(ctxt) = self.syntax_context_map.get(&key) { + return *ctxt; } - if transparency >= Transparency::SemiTransparent { - let parent = opaque_and_semitransparent; - opaque_and_semitransparent = *self - .syntax_context_map - .entry((parent, expn_id, transparency)) - .or_insert_with(|| { - let new_opaque_and_semitransparent = - SyntaxContext::from_usize(syntax_context_data.len()); - syntax_context_data.push(SyntaxContextData { - outer_expn: expn_id, - outer_transparency: transparency, - parent, - opaque, - opaque_and_semitransparent: new_opaque_and_semitransparent, - dollar_crate_name: kw::DollarCrate, - }); - new_opaque_and_semitransparent - }); - } + // Reserve a new syntax context. + let ctxt = SyntaxContext::from_usize(self.syntax_context_data.len()); + self.syntax_context_data.push(SyntaxContextData::decode_placeholder()); + self.syntax_context_map.insert(key, ctxt); - let parent = ctxt; - *self.syntax_context_map.entry((parent, expn_id, transparency)).or_insert_with(|| { - syntax_context_data.push(SyntaxContextData { - outer_expn: expn_id, - outer_transparency: transparency, - parent, - opaque, - opaque_and_semitransparent, - dollar_crate_name: kw::DollarCrate, - }); - SyntaxContext::from_usize(syntax_context_data.len() - 1) - }) + // Opaque and semi-transparent versions of the parent. Note that they may be equal to the + // parent itself. E.g. `parent_opaque` == `parent` if the expn chain contains only opaques, + // and `parent_opaque_and_semitransparent` == `parent` if the expn contains only opaques + // and semi-transparents. + let parent_opaque = self.syntax_context_data[parent.0 as usize].opaque; + let parent_opaque_and_semitransparent = + self.syntax_context_data[parent.0 as usize].opaque_and_semitransparent; + + // Evaluate opaque and semi-transparent versions of the new syntax context. + let (opaque, opaque_and_semitransparent) = match transparency { + Transparency::Transparent => (parent_opaque, parent_opaque_and_semitransparent), + Transparency::SemiTransparent => ( + parent_opaque, + // Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents. + self.alloc_ctxt(parent_opaque_and_semitransparent, expn_id, transparency), + ), + Transparency::Opaque => ( + // Will be the same as `ctxt` if the expn chain contains only opaques. + self.alloc_ctxt(parent_opaque, expn_id, transparency), + // Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents. + self.alloc_ctxt(parent_opaque_and_semitransparent, expn_id, transparency), + ), + }; + + // Fill the full data, now that we have it. + self.syntax_context_data[ctxt.as_u32() as usize] = + SyntaxContextData::new(key, opaque, opaque_and_semitransparent); + ctxt } } diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout index c80a33206fb4..6fd6cb474693 100644 --- a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout +++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout @@ -5,19 +5,19 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ stream: TokenStream [ Ident { ident: "struct", - span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#4), + span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#5), }, Ident { ident: "S", - span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#4), + span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#5), }, Punct { ch: ';', spacing: Alone, - span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#4), + span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#5), }, ], - span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#5), + span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#4), }, ] #![feature /* 0#0 */(prelude_import)] @@ -59,7 +59,7 @@ macro_rules! outer struct S /* 0#0 */; macro inner /* 0#3 */ { () => { print_bang! { struct S; } } } -struct S /* 0#4 */; +struct S /* 0#5 */; // OK, not a duplicate definition of `S` fn main /* 0#0 */() {} @@ -70,7 +70,7 @@ crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer") crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #3, def_site_ctxt: #3, kind: Macro(Bang, "inner") -crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "print_bang") +crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "print_bang") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") @@ -83,9 +83,9 @@ SyntaxContexts: #1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque) #2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent) #3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent) -#4: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque) -#5: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque) +#4: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque) +#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque) #6: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque) -#7: parent: #5, outer_mark: (crate0::{{expn4}}, Transparent) -#8: parent: #4, outer_mark: (crate0::{{expn4}}, SemiTransparent) +#7: parent: #4, outer_mark: (crate0::{{expn4}}, Transparent) +#8: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent) */ From fbe5e555214c079d82985c40b44a3b992d695fab Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Thu, 27 Mar 2025 22:43:23 -0700 Subject: [PATCH 651/745] bootstrap: Avoid cloning change-id list --- src/bootstrap/src/bin/main.rs | 2 +- src/bootstrap/src/core/config/config.rs | 2 +- src/bootstrap/src/utils/change_tracker.rs | 22 +++++++++------------- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index 7ec3140c0386..cbfe00a757ce 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -191,7 +191,7 @@ fn check_version(config: &Config) -> Option { } msg.push_str("There have been changes to x.py since you last updated:\n"); - msg.push_str(&human_readable_changes(&changes)); + msg.push_str(&human_readable_changes(changes)); msg.push_str("NOTE: to silence this warning, "); msg.push_str(&format!( diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index bbb0fbfbb935..1712be7f947f 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1381,7 +1381,7 @@ impl Config { if !changes.is_empty() { println!( "WARNING: There have been changes to x.py since you last updated:\n{}", - crate::human_readable_changes(&changes) + crate::human_readable_changes(changes) ); } } diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 5314141dd1b0..244391739f38 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -35,29 +35,25 @@ impl Display for ChangeSeverity { } } -pub fn find_recent_config_change_ids(current_id: usize) -> Vec { - if !CONFIG_CHANGE_HISTORY.iter().any(|config| config.change_id == current_id) { +pub fn find_recent_config_change_ids(current_id: usize) -> &'static [ChangeInfo] { + if let Some(index) = + CONFIG_CHANGE_HISTORY.iter().position(|config| config.change_id == current_id) + { + // Skip the current_id and IDs before it + &CONFIG_CHANGE_HISTORY[index + 1..] + } else { // If the current change-id is greater than the most recent one, return // an empty list (it may be due to switching from a recent branch to an // older one); otherwise, return the full list (assuming the user provided // the incorrect change-id by accident). if let Some(config) = CONFIG_CHANGE_HISTORY.iter().max_by_key(|config| config.change_id) { if current_id > config.change_id { - return Vec::new(); + return &[]; } } - return CONFIG_CHANGE_HISTORY.to_vec(); + CONFIG_CHANGE_HISTORY } - - let index = - CONFIG_CHANGE_HISTORY.iter().position(|config| config.change_id == current_id).unwrap(); - - CONFIG_CHANGE_HISTORY - .iter() - .skip(index + 1) // Skip the current_id and IDs before it - .cloned() - .collect() } pub fn human_readable_changes(changes: &[ChangeInfo]) -> String { From 122d7e1dcd921eafabd5c76d050d997876110e08 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 28 Mar 2025 15:24:49 +0100 Subject: [PATCH 652/745] Remove `terminating_scopes` hash set. --- .../rustc_hir_analysis/src/check/region.rs | 259 +++++++----------- 1 file changed, 95 insertions(+), 164 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 2528adb937b3..cf66ab708bb9 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -8,7 +8,6 @@ use std::mem; -use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, Visitor}; @@ -45,28 +44,6 @@ struct ScopeResolutionVisitor<'tcx> { scope_tree: ScopeTree, cx: Context, - - /// `terminating_scopes` is a set containing the ids of each - /// statement, or conditional/repeating expression. These scopes - /// are calling "terminating scopes" because, when attempting to - /// find the scope of a temporary, by default we search up the - /// enclosing scopes until we encounter the terminating scope. A - /// conditional/repeating expression is one which is not - /// guaranteed to execute exactly once upon entering the parent - /// scope. This could be because the expression only executes - /// conditionally, such as the expression `b` in `a && b`, or - /// because the expression may execute many times, such as a loop - /// body. The reason that we distinguish such expressions is that, - /// upon exiting the parent scope, we cannot statically know how - /// many times the expression executed, and thus if the expression - /// creates temporaries we cannot know statically how many such - /// temporaries we would have to cleanup. Therefore, we ensure that - /// the temporaries never outlast the conditional/repeating - /// expression, preventing the need for dynamic checks and/or - /// arbitrary amounts of stack space. Terminating scopes end - /// up being contained in a DestructionScope that contains the - /// destructor's execution. - terminating_scopes: FxHashSet, } /// Records the lifetime of a local variable as `cx.var_parent` @@ -81,7 +58,11 @@ fn record_var_lifetime(visitor: &mut ScopeResolutionVisitor<'_>, var_id: hir::It } } -fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hir::Block<'tcx>) { +fn resolve_block<'tcx>( + visitor: &mut ScopeResolutionVisitor<'tcx>, + blk: &'tcx hir::Block<'tcx>, + terminating: bool, +) { debug!("resolve_block(blk.hir_id={:?})", blk.hir_id); let prev_cx = visitor.cx; @@ -111,7 +92,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi // `other_argument()` has run and also the call to `quux(..)` // itself has returned. - visitor.enter_node_scope_with_dtor(blk.hir_id.local_id); + visitor.enter_node_scope_with_dtor(blk.hir_id.local_id, terminating); visitor.cx.var_parent = visitor.cx.parent; { @@ -140,8 +121,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi // the sequence of visits agree with the order in the default // `hir::intravisit` visitor. mem::swap(&mut prev_cx, &mut visitor.cx); - visitor.terminating_scopes.insert(els.hir_id.local_id); - visitor.visit_block(els); + resolve_block(visitor, els, true); // From now on, we continue normally. visitor.cx = prev_cx; } @@ -169,12 +149,12 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi if let Some(tail_expr) = blk.expr { let local_id = tail_expr.hir_id.local_id; let edition = blk.span.edition(); - if edition.at_least_rust_2024() { - visitor.terminating_scopes.insert(local_id); - } else if !visitor - .tcx - .lints_that_dont_need_to_run(()) - .contains(&lint::LintId::of(lint::builtin::TAIL_EXPR_DROP_ORDER)) + let terminating = edition.at_least_rust_2024(); + if !terminating + && !visitor + .tcx + .lints_that_dont_need_to_run(()) + .contains(&lint::LintId::of(lint::builtin::TAIL_EXPR_DROP_ORDER)) { // If this temporary scope will be changing once the codebase adopts Rust 2024, // and we are linting about possible semantic changes that would result, @@ -185,7 +165,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi .backwards_incompatible_scope .insert(local_id, Scope { local_id, data: ScopeData::Node }); } - visitor.visit_expr(tail_expr); + resolve_expr(visitor, tail_expr, terminating); } } @@ -203,18 +183,14 @@ fn resolve_arm<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, arm: &'tcx hir: let prev_cx = visitor.cx; - visitor.terminating_scopes.insert(arm.hir_id.local_id); - - visitor.enter_node_scope_with_dtor(arm.hir_id.local_id); + visitor.enter_node_scope_with_dtor(arm.hir_id.local_id, true); visitor.cx.var_parent = visitor.cx.parent; - if let Some(expr) = arm.guard - && !has_let_expr(expr) - { - visitor.terminating_scopes.insert(expr.hir_id.local_id); + resolve_pat(visitor, arm.pat); + if let Some(guard) = arm.guard { + resolve_expr(visitor, guard, !has_let_expr(guard)); } - - intravisit::walk_arm(visitor, arm); + resolve_expr(visitor, arm.body, false); visitor.cx = prev_cx; } @@ -243,126 +219,24 @@ fn resolve_stmt<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, stmt: &'tcx hi // associated destruction scope that represents the scope of the // statement plus its destructors, and thus the scope for which // regions referenced by the destructors need to survive. - visitor.terminating_scopes.insert(stmt_id); let prev_parent = visitor.cx.parent; - visitor.enter_node_scope_with_dtor(stmt_id); + visitor.enter_node_scope_with_dtor(stmt_id, true); intravisit::walk_stmt(visitor, stmt); visitor.cx.parent = prev_parent; } -fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hir::Expr<'tcx>) { +fn resolve_expr<'tcx>( + visitor: &mut ScopeResolutionVisitor<'tcx>, + expr: &'tcx hir::Expr<'tcx>, + terminating: bool, +) { debug!("resolve_expr - pre-increment {} expr = {:?}", visitor.expr_and_pat_count, expr); let prev_cx = visitor.cx; - visitor.enter_node_scope_with_dtor(expr.hir_id.local_id); - - { - let terminating_scopes = &mut visitor.terminating_scopes; - let mut terminating = |id: hir::ItemLocalId| { - terminating_scopes.insert(id); - }; - match expr.kind { - // Conditional or repeating scopes are always terminating - // scopes, meaning that temporaries cannot outlive them. - // This ensures fixed size stacks. - hir::ExprKind::Binary( - source_map::Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. }, - l, - r, - ) => { - // expr is a short circuiting operator (|| or &&). As its - // functionality can't be overridden by traits, it always - // processes bool sub-expressions. bools are Copy and thus we - // can drop any temporaries in evaluation (read) order - // (with the exception of potentially failing let expressions). - // We achieve this by enclosing the operands in a terminating - // scope, both the LHS and the RHS. - - // We optimize this a little in the presence of chains. - // Chains like a && b && c get lowered to AND(AND(a, b), c). - // In here, b and c are RHS, while a is the only LHS operand in - // that chain. This holds true for longer chains as well: the - // leading operand is always the only LHS operand that is not a - // binop itself. Putting a binop like AND(a, b) into a - // terminating scope is not useful, thus we only put the LHS - // into a terminating scope if it is not a binop. - - let terminate_lhs = match l.kind { - // let expressions can create temporaries that live on - hir::ExprKind::Let(_) => false, - // binops already drop their temporaries, so there is no - // need to put them into a terminating scope. - // This is purely an optimization to reduce the number of - // terminating scopes. - hir::ExprKind::Binary( - source_map::Spanned { - node: hir::BinOpKind::And | hir::BinOpKind::Or, .. - }, - .., - ) => false, - // otherwise: mark it as terminating - _ => true, - }; - if terminate_lhs { - terminating(l.hir_id.local_id); - } - - // `Let` expressions (in a let-chain) shouldn't be terminating, as their temporaries - // should live beyond the immediate expression - if !matches!(r.kind, hir::ExprKind::Let(_)) { - terminating(r.hir_id.local_id); - } - } - hir::ExprKind::If(_, then, Some(otherwise)) => { - terminating(then.hir_id.local_id); - terminating(otherwise.hir_id.local_id); - } - - hir::ExprKind::If(_, then, None) => { - terminating(then.hir_id.local_id); - } - - hir::ExprKind::Loop(body, _, _, _) => { - terminating(body.hir_id.local_id); - } - - hir::ExprKind::DropTemps(expr) => { - // `DropTemps(expr)` does not denote a conditional scope. - // Rather, we want to achieve the same behavior as `{ let _t = expr; _t }`. - terminating(expr.hir_id.local_id); - } - - hir::ExprKind::AssignOp(..) - | hir::ExprKind::Index(..) - | hir::ExprKind::Unary(..) - | hir::ExprKind::Call(..) - | hir::ExprKind::MethodCall(..) => { - // FIXME(https://github.com/rust-lang/rfcs/issues/811) Nested method calls - // - // The lifetimes for a call or method call look as follows: - // - // call.id - // - arg0.id - // - ... - // - argN.id - // - call.callee_id - // - // The idea is that call.callee_id represents *the time when - // the invoked function is actually running* and call.id - // represents *the time to prepare the arguments and make the - // call*. See the section "Borrows in Calls" borrowck/README.md - // for an extended explanation of why this distinction is - // important. - // - // record_superlifetime(new_cx, expr.callee_id); - } - - _ => {} - } - } + visitor.enter_node_scope_with_dtor(expr.hir_id.local_id, terminating); let prev_pessimistic = visitor.pessimistic_yield; @@ -417,6 +291,53 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi // properly, we can't miss any types. match expr.kind { + // Conditional or repeating scopes are always terminating + // scopes, meaning that temporaries cannot outlive them. + // This ensures fixed size stacks. + hir::ExprKind::Binary( + source_map::Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. }, + left, + right, + ) => { + // expr is a short circuiting operator (|| or &&). As its + // functionality can't be overridden by traits, it always + // processes bool sub-expressions. bools are Copy and thus we + // can drop any temporaries in evaluation (read) order + // (with the exception of potentially failing let expressions). + // We achieve this by enclosing the operands in a terminating + // scope, both the LHS and the RHS. + + // We optimize this a little in the presence of chains. + // Chains like a && b && c get lowered to AND(AND(a, b), c). + // In here, b and c are RHS, while a is the only LHS operand in + // that chain. This holds true for longer chains as well: the + // leading operand is always the only LHS operand that is not a + // binop itself. Putting a binop like AND(a, b) into a + // terminating scope is not useful, thus we only put the LHS + // into a terminating scope if it is not a binop. + + let terminate_lhs = match left.kind { + // let expressions can create temporaries that live on + hir::ExprKind::Let(_) => false, + // binops already drop their temporaries, so there is no + // need to put them into a terminating scope. + // This is purely an optimization to reduce the number of + // terminating scopes. + hir::ExprKind::Binary( + source_map::Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. }, + .., + ) => false, + // otherwise: mark it as terminating + _ => true, + }; + + // `Let` expressions (in a let-chain) shouldn't be terminating, as their temporaries + // should live beyond the immediate expression + let terminate_rhs = !matches!(right.kind, hir::ExprKind::Let(_)); + + resolve_expr(visitor, left, terminate_lhs); + resolve_expr(visitor, right, terminate_rhs); + } // Manually recurse over closures, because they are nested bodies // that share the parent environment. We handle const blocks in // `visit_inline_const`. @@ -485,9 +406,9 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi visitor.enter_scope(Scope { local_id: then.hir_id.local_id, data }); visitor.cx.var_parent = visitor.cx.parent; visitor.visit_expr(cond); - visitor.visit_expr(then); + resolve_expr(visitor, then, true); visitor.cx = expr_cx; - visitor.visit_expr(otherwise); + resolve_expr(visitor, otherwise, true); } hir::ExprKind::If(cond, then, None) => { @@ -500,10 +421,20 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi visitor.enter_scope(Scope { local_id: then.hir_id.local_id, data }); visitor.cx.var_parent = visitor.cx.parent; visitor.visit_expr(cond); - visitor.visit_expr(then); + resolve_expr(visitor, then, true); visitor.cx = expr_cx; } + hir::ExprKind::Loop(body, _, _, _) => { + resolve_block(visitor, body, true); + } + + hir::ExprKind::DropTemps(expr) => { + // `DropTemps(expr)` does not denote a conditional scope. + // Rather, we want to achieve the same behavior as `{ let _t = expr; _t }`. + resolve_expr(visitor, expr, true); + } + _ => intravisit::walk_expr(visitor, expr), } @@ -786,12 +717,12 @@ impl<'tcx> ScopeResolutionVisitor<'tcx> { self.cx.parent = Some(child_scope); } - fn enter_node_scope_with_dtor(&mut self, id: hir::ItemLocalId) { + fn enter_node_scope_with_dtor(&mut self, id: hir::ItemLocalId, terminating: bool) { // If node was previously marked as a terminating scope during the // recursive visit of its parent node in the HIR, then we need to // account for the destruction scope representing the scope of // the destructors that run immediately after it completes. - if self.terminating_scopes.contains(&id) { + if terminating { self.enter_scope(Scope { local_id: id, data: ScopeData::Destruction }); } self.enter_scope(Scope { local_id: id, data: ScopeData::Node }); @@ -803,13 +734,11 @@ impl<'tcx> ScopeResolutionVisitor<'tcx> { // visited the body. let outer_ec = mem::replace(&mut self.expr_and_pat_count, 0); let outer_cx = self.cx; - let outer_ts = mem::take(&mut self.terminating_scopes); // The 'pessimistic yield' flag is set to true when we are // processing a `+=` statement and have to make pessimistic // control flow assumptions. This doesn't apply to nested // bodies within the `+=` statements. See #69307. let outer_pessimistic_yield = mem::replace(&mut self.pessimistic_yield, false); - self.terminating_scopes.insert(hir_id.local_id); self.enter_scope(Scope { local_id: hir_id.local_id, data: ScopeData::CallSite }); self.enter_scope(Scope { local_id: hir_id.local_id, data: ScopeData::Arguments }); @@ -819,14 +748,13 @@ impl<'tcx> ScopeResolutionVisitor<'tcx> { // Restore context we had at the start. self.expr_and_pat_count = outer_ec; self.cx = outer_cx; - self.terminating_scopes = outer_ts; self.pessimistic_yield = outer_pessimistic_yield; } } impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { fn visit_block(&mut self, b: &'tcx Block<'tcx>) { - resolve_block(self, b); + resolve_block(self, b, false); } fn visit_body(&mut self, body: &hir::Body<'tcx>) { @@ -850,7 +778,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { } // The body of the every fn is a root scope. - this.visit_expr(body.value) + resolve_expr(this, body.value, true); } else { // Only functions have an outer terminating (drop) scope, while // temporaries in constant initializers may be 'static, but only @@ -871,6 +799,10 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { // (i.e., `'static`), which means that after `g` returns, it drops, // and all the associated destruction scope rules apply. this.cx.var_parent = None; + this.enter_scope(Scope { + local_id: body.value.hir_id.local_id, + data: ScopeData::Destruction, + }); resolve_local(this, None, Some(body.value)); } }) @@ -886,7 +818,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { resolve_stmt(self, s); } fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { - resolve_expr(self, ex); + resolve_expr(self, ex, false); } fn visit_local(&mut self, l: &'tcx LetStmt<'tcx>) { resolve_local(self, Some(l.pat), l.init) @@ -916,7 +848,6 @@ pub(crate) fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree { scope_tree: ScopeTree::default(), expr_and_pat_count: 0, cx: Context { parent: None, var_parent: None }, - terminating_scopes: Default::default(), pessimistic_yield: false, fixup_scopes: vec![], }; From 5004e10ceb5c02a7170d81adb551a25f6f9e3565 Mon Sep 17 00:00:00 2001 From: Frank King Date: Sat, 29 Mar 2025 12:13:38 +0800 Subject: [PATCH 653/745] Add a test for `Weak` created from `UniqueArc::downgrade` --- library/alloctests/tests/arc.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/library/alloctests/tests/arc.rs b/library/alloctests/tests/arc.rs index 45a145c6271a..00bdf527133f 100644 --- a/library/alloctests/tests/arc.rs +++ b/library/alloctests/tests/arc.rs @@ -1,7 +1,7 @@ use std::any::Any; use std::cell::{Cell, RefCell}; use std::iter::TrustedLen; -use std::sync::{Arc, Weak}; +use std::sync::{Arc, UniqueArc, Weak}; #[test] fn uninhabited() { @@ -263,6 +263,27 @@ fn make_mut_unsized() { assert_eq!(*other_data, [110, 20, 30]); } +#[test] +fn test_unique_arc_weak() { + let data = UniqueArc::new(32); + + // Test that `Weak` downgraded from `UniqueArc` cannot be upgraded. + let weak = UniqueArc::downgrade(&data); + assert_eq!(weak.strong_count(), 0); + assert_eq!(weak.weak_count(), 0); + assert!(weak.upgrade().is_none()); + + // Test that `Weak` can now be upgraded after the `UniqueArc` being converted to `Arc`. + let strong = UniqueArc::into_arc(data); + assert_eq!(*strong, 32); + assert_eq!(weak.strong_count(), 1); + assert_eq!(weak.weak_count(), 1); + let upgraded = weak.upgrade().unwrap(); + assert_eq!(*upgraded, 32); + assert_eq!(weak.strong_count(), 2); + assert_eq!(weak.weak_count(), 1); +} + #[allow(unused)] mod pin_coerce_unsized { use alloc::sync::{Arc, UniqueArc}; From 163ea4acd0e93d5a45ea44b42a999abe39d0a93f Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 28 Mar 2025 10:38:44 +0100 Subject: [PATCH 654/745] Add more tests for pin!(). Co-authored-by: Daniel Henry-Mantilla --- library/coretests/tests/pin_macro.rs | 11 ++++++++ tests/ui/pin-macro/pin_move.rs | 26 +++++++++++++++++++ tests/ui/pin-macro/pin_move.stderr | 38 ++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 tests/ui/pin-macro/pin_move.rs create mode 100644 tests/ui/pin-macro/pin_move.stderr diff --git a/library/coretests/tests/pin_macro.rs b/library/coretests/tests/pin_macro.rs index 639eab740c0b..3174c91a6498 100644 --- a/library/coretests/tests/pin_macro.rs +++ b/library/coretests/tests/pin_macro.rs @@ -47,3 +47,14 @@ fn temp_lifetime() { } async fn foo(_: &mut usize) {} } + +#[test] +fn transitive_extension() { + async fn temporary() {} + + // `pin!` witnessed in the wild being used like this, even if it yields + // a `Pin<&mut &mut impl Unpin>`; it does work because `pin!` + // happens to transitively extend the lifespan of `temporary()`. + let p = pin!(&mut temporary()); + let _use = p; +} diff --git a/tests/ui/pin-macro/pin_move.rs b/tests/ui/pin-macro/pin_move.rs new file mode 100644 index 000000000000..0f6d34fad951 --- /dev/null +++ b/tests/ui/pin-macro/pin_move.rs @@ -0,0 +1,26 @@ +//@ edition:2024 + +use core::marker::PhantomPinned; +use core::pin::pin; + +fn a() { + struct NotCopy(T); + #[allow(unused_mut)] + let mut pointee = NotCopy(PhantomPinned); + pin!(pointee); + let _moved = pointee; + //~^ ERROR use of moved value +} + +fn b() { + struct NotCopy(T); + let mut pointee = NotCopy(PhantomPinned); + pin!(*&mut pointee); + //~^ ERROR cannot move + let _moved = pointee; +} + +fn main() { + a(); + b(); +} diff --git a/tests/ui/pin-macro/pin_move.stderr b/tests/ui/pin-macro/pin_move.stderr new file mode 100644 index 000000000000..c9b8ad9b2021 --- /dev/null +++ b/tests/ui/pin-macro/pin_move.stderr @@ -0,0 +1,38 @@ +error[E0382]: use of moved value: `pointee` + --> $DIR/pin_move.rs:11:18 + | +LL | let mut pointee = NotCopy(PhantomPinned); + | ----------- move occurs because `pointee` has type `a::NotCopy`, which does not implement the `Copy` trait +LL | pin!(pointee); + | ------- value moved here +LL | let _moved = pointee; + | ^^^^^^^ value used here after move + | +note: if `a::NotCopy` implemented `Clone`, you could clone the value + --> $DIR/pin_move.rs:7:5 + | +LL | struct NotCopy(T); + | ^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | pin!(pointee); + | ------- you could clone this value + +error[E0507]: cannot move out of a mutable reference + --> $DIR/pin_move.rs:18:10 + | +LL | pin!(*&mut pointee); + | ^^^^^^^^^^^^^ move occurs because value has type `b::NotCopy`, which does not implement the `Copy` trait + | +note: if `b::NotCopy` implemented `Clone`, you could clone the value + --> $DIR/pin_move.rs:16:5 + | +LL | struct NotCopy(T); + | ^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type +LL | let mut pointee = NotCopy(PhantomPinned); +LL | pin!(*&mut pointee); + | ------------- you could clone this value + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0382, E0507. +For more information about an error, try `rustc --explain E0382`. From 366095d6c738821ab6745bf3b224e8643e0eb464 Mon Sep 17 00:00:00 2001 From: bohan Date: Sat, 29 Mar 2025 17:37:01 +0800 Subject: [PATCH 655/745] less decoding if it has the same syntax context --- compiler/rustc_metadata/src/rmeta/mod.rs | 4 +- .../rustc_middle/src/query/on_disk_cache.rs | 10 +- compiler/rustc_middle/src/ty/parameterized.rs | 2 +- compiler/rustc_span/src/hygiene.rs | 201 ++++++------------ .../nonterminal-token-hygiene.stdout | 20 +- 5 files changed, 80 insertions(+), 157 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index dc453b1e747c..34e4f2f26022 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -36,7 +36,7 @@ use rustc_serialize::opaque::FileEncoder; use rustc_session::config::{SymbolManglingVersion, TargetModifier}; use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib}; use rustc_span::edition::Edition; -use rustc_span::hygiene::{ExpnIndex, MacroKind, SyntaxContextData}; +use rustc_span::hygiene::{ExpnIndex, MacroKind, SyntaxContextKey}; use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Ident, Span, Symbol}; use rustc_target::spec::{PanicStrategy, TargetTuple}; use table::TableBuilder; @@ -193,7 +193,7 @@ enum LazyState { Previous(NonZero), } -type SyntaxContextTable = LazyTable>>; +type SyntaxContextTable = LazyTable>>; type ExpnDataTable = LazyTable>>; type ExpnHashTable = LazyTable>>; diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 14e3ce8bef6b..ce6219c207fd 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -16,7 +16,7 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixed use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_session::Session; use rustc_span::hygiene::{ - ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextData, + ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextKey, }; use rustc_span::source_map::Spanned; use rustc_span::{ @@ -75,9 +75,9 @@ pub struct OnDiskCache { alloc_decoding_state: AllocDecodingState, // A map from syntax context ids to the position of their associated - // `SyntaxContextData`. We use a `u32` instead of a `SyntaxContext` + // `SyntaxContextKey`. We use a `u32` instead of a `SyntaxContext` // to represent the fact that we are storing *encoded* ids. When we decode - // a `SyntaxContext`, a new id will be allocated from the global `HygieneData`, + // a `SyntaxContextKey`, a new id will be allocated from the global `HygieneData`, // which will almost certainly be different than the serialized id. syntax_contexts: FxHashMap, // A map from the `DefPathHash` of an `ExpnId` to the position @@ -305,7 +305,7 @@ impl OnDiskCache { let mut expn_data = UnhashMap::default(); let mut foreign_expn_data = UnhashMap::default(); - // Encode all hygiene data (`SyntaxContextData` and `ExpnData`) from the current + // Encode all hygiene data (`SyntaxContextKey` and `ExpnData`) from the current // session. hygiene_encode_context.encode( @@ -566,7 +566,7 @@ impl<'a, 'tcx> SpanDecoder for CacheDecoder<'a, 'tcx> { // We look up the position of the associated `SyntaxData` and decode it. let pos = syntax_contexts.get(&id).unwrap(); this.with_position(pos.to_usize(), |decoder| { - let data: SyntaxContextData = decode_tagged(decoder, TAG_SYNTAX_CONTEXT); + let data: SyntaxContextKey = decode_tagged(decoder, TAG_SYNTAX_CONTEXT); data }) }) diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 19e2b5745632..134f76d7248d 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -111,7 +111,7 @@ trivially_parameterized_over_tcx! { rustc_span::Span, rustc_span::Symbol, rustc_span::def_id::DefPathHash, - rustc_span::hygiene::SyntaxContextData, + rustc_span::hygiene::SyntaxContextKey, rustc_span::Ident, rustc_type_ir::Variance, rustc_hir::Attribute, diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 4390085cd049..f94858856729 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -24,9 +24,6 @@ // because getting it wrong can lead to nested `HygieneData::with` calls that // trigger runtime aborts. (Fortunately these are obvious and easy to fix.) -use std::cell::RefCell; -use std::collections::hash_map::Entry; -use std::collections::hash_set::Entry as SetEntry; use std::hash::Hash; use std::sync::Arc; use std::{fmt, iter, mem}; @@ -34,7 +31,7 @@ use std::{fmt, iter, mem}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher}; -use rustc_data_structures::sync::{Lock, WorkerLocal}; +use rustc_data_structures::sync::Lock; use rustc_data_structures::unhash::UnhashMap; use rustc_hashes::Hash64; use rustc_index::IndexVec; @@ -59,10 +56,10 @@ impl !PartialOrd for SyntaxContext {} /// If this part of two syntax contexts is equal, then the whole syntax contexts should be equal. /// The other fields are only for caching. -type SyntaxContextKey = (SyntaxContext, ExpnId, Transparency); +pub type SyntaxContextKey = (SyntaxContext, ExpnId, Transparency); #[derive(Clone, Copy, PartialEq, Debug, Encodable, Decodable)] -pub struct SyntaxContextData { +struct SyntaxContextData { outer_expn: ExpnId, outer_transparency: Transparency, parent: SyntaxContext, @@ -94,6 +91,21 @@ impl SyntaxContextData { self.dollar_crate_name == kw::Empty } + fn new( + (parent, outer_expn, outer_transparency): SyntaxContextKey, + opaque: SyntaxContext, + opaque_and_semitransparent: SyntaxContext, + ) -> Self { + SyntaxContextData { + parent, + outer_expn, + outer_transparency, + opaque, + opaque_and_semitransparent, + dollar_crate_name: kw::DollarCrate, + } + } + fn key(&self) -> SyntaxContextKey { (self.parent, self.outer_expn, self.outer_transparency) } @@ -574,67 +586,49 @@ impl HygieneData { fn apply_mark_internal( &mut self, - ctxt: SyntaxContext, + parent: SyntaxContext, expn_id: ExpnId, transparency: Transparency, ) -> SyntaxContext { - let syntax_context_data = &mut self.syntax_context_data; - debug_assert!(!syntax_context_data[ctxt.0 as usize].is_decode_placeholder()); - let mut opaque = syntax_context_data[ctxt.0 as usize].opaque; - let mut opaque_and_semitransparent = - syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent; - - if transparency >= Transparency::Opaque { - let parent = opaque; - opaque = *self - .syntax_context_map - .entry((parent, expn_id, transparency)) - .or_insert_with(|| { - let new_opaque = SyntaxContext::from_usize(syntax_context_data.len()); - syntax_context_data.push(SyntaxContextData { - outer_expn: expn_id, - outer_transparency: transparency, - parent, - opaque: new_opaque, - opaque_and_semitransparent: new_opaque, - dollar_crate_name: kw::DollarCrate, - }); - new_opaque - }); + debug_assert!(!self.syntax_context_data[parent.0 as usize].is_decode_placeholder()); + // Look into the cache first. + let key = (parent, expn_id, transparency); + if let Some(ctxt) = self.syntax_context_map.get(&key) { + return *ctxt; } + // Reserve a new syntax context. + let ctxt = SyntaxContext::from_usize(self.syntax_context_data.len()); + self.syntax_context_data.push(SyntaxContextData::decode_placeholder()); + self.syntax_context_map.insert(key, ctxt); - if transparency >= Transparency::SemiTransparent { - let parent = opaque_and_semitransparent; - opaque_and_semitransparent = *self - .syntax_context_map - .entry((parent, expn_id, transparency)) - .or_insert_with(|| { - let new_opaque_and_semitransparent = - SyntaxContext::from_usize(syntax_context_data.len()); - syntax_context_data.push(SyntaxContextData { - outer_expn: expn_id, - outer_transparency: transparency, - parent, - opaque, - opaque_and_semitransparent: new_opaque_and_semitransparent, - dollar_crate_name: kw::DollarCrate, - }); - new_opaque_and_semitransparent - }); - } + // Opaque and semi-transparent versions of the parent. Note that they may be equal to the + // parent itself. E.g. `parent_opaque` == `parent` if the expn chain contains only opaques, + // and `parent_opaque_and_semitransparent` == `parent` if the expn contains only opaques + // and semi-transparents. + let parent_opaque = self.syntax_context_data[parent.0 as usize].opaque; + let parent_opaque_and_semitransparent = + self.syntax_context_data[parent.0 as usize].opaque_and_semitransparent; - let parent = ctxt; - *self.syntax_context_map.entry((parent, expn_id, transparency)).or_insert_with(|| { - syntax_context_data.push(SyntaxContextData { - outer_expn: expn_id, - outer_transparency: transparency, - parent, - opaque, - opaque_and_semitransparent, - dollar_crate_name: kw::DollarCrate, - }); - SyntaxContext::from_usize(syntax_context_data.len() - 1) - }) + // Evaluate opaque and semi-transparent versions of the new syntax context. + let (opaque, opaque_and_semitransparent) = match transparency { + Transparency::Transparent => (parent_opaque, parent_opaque_and_semitransparent), + Transparency::SemiTransparent => ( + parent_opaque, + // Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents. + self.apply_mark_internal(parent_opaque_and_semitransparent, expn_id, transparency), + ), + Transparency::Opaque => ( + // Will be the same as `ctxt` if the expn chain contains only opaques. + self.apply_mark_internal(parent_opaque, expn_id, transparency), + // Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents. + self.apply_mark_internal(parent_opaque_and_semitransparent, expn_id, transparency), + ), + }; + + // Fill the full data, now that we have it. + self.syntax_context_data[ctxt.as_u32() as usize] = + SyntaxContextData::new(key, opaque, opaque_and_semitransparent); + ctxt } } @@ -1265,7 +1259,7 @@ impl HygieneEncodeContext { pub fn encode( &self, encoder: &mut T, - mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextData), + mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextKey), mut encode_expn: impl FnMut(&mut T, ExpnId, &ExpnData, ExpnHash), ) { // When we serialize a `SyntaxContextData`, we may end up serializing @@ -1323,9 +1317,6 @@ struct HygieneDecodeContextInner { /// Additional information used to assist in decoding hygiene data pub struct HygieneDecodeContext { inner: Lock, - - /// A set of serialized `SyntaxContext` ids that are currently being decoded on each thread. - local_in_progress: WorkerLocal>>, } /// Register an expansion which has been decoded from the on-disk-cache for the local crate. @@ -1396,10 +1387,10 @@ pub fn decode_expn_id( // to track which `SyntaxContext`s we have already decoded. // The provided closure will be invoked to deserialize a `SyntaxContextData` // if we haven't already seen the id of the `SyntaxContext` we are deserializing. -pub fn decode_syntax_context SyntaxContextData>( +pub fn decode_syntax_context SyntaxContextKey>( d: &mut D, context: &HygieneDecodeContext, - decode_data: F, + decode_ctxt_key: F, ) -> SyntaxContext { let raw_id: u32 = Decodable::decode(d); if raw_id == 0 { @@ -1408,58 +1399,9 @@ pub fn decode_syntax_context SyntaxContext return SyntaxContext::root(); } - let pending_ctxt = { - let mut inner = context.inner.lock(); - - // Reminder: `HygieneDecodeContext` is per-crate, so there are no collisions between - // raw ids from different crate metadatas. - if let Some(ctxt) = inner.remapped_ctxts.get(raw_id as usize).copied().flatten() { - // This has already been decoded. - return ctxt; - } - - match inner.decoding.entry(raw_id) { - Entry::Occupied(ctxt_entry) => { - let pending_ctxt = *ctxt_entry.get(); - match context.local_in_progress.borrow_mut().entry(raw_id) { - // We're decoding this already on the current thread. Return here and let the - // function higher up the stack finish decoding to handle recursive cases. - // Hopefully having a `SyntaxContext` that refers to an incorrect data is ok - // during reminder of the decoding process, it's certainly not ok after the - // top level decoding function returns. - SetEntry::Occupied(..) => return pending_ctxt, - // Some other thread is currently decoding this. - // Race with it (alternatively we could wait here). - // We cannot return this value, unlike in the recursive case above, because it - // may expose a `SyntaxContext` pointing to incorrect data to arbitrary code. - SetEntry::Vacant(entry) => { - entry.insert(); - pending_ctxt - } - } - } - Entry::Vacant(entry) => { - // We are the first thread to start decoding. Mark the current thread as being progress. - context.local_in_progress.borrow_mut().insert(raw_id); - - // Allocate and store SyntaxContext id *before* calling the decoder function, - // as the SyntaxContextData may reference itself. - let new_ctxt = HygieneData::with(|hygiene_data| { - // Push a dummy SyntaxContextData to ensure that nobody else can get the - // same ID as us. This will be overwritten after call `decode_data`. - hygiene_data.syntax_context_data.push(SyntaxContextData::decode_placeholder()); - SyntaxContext::from_usize(hygiene_data.syntax_context_data.len() - 1) - }); - entry.insert(new_ctxt); - new_ctxt - } - } - }; - // Don't try to decode data while holding the lock, since we need to // be able to recursively decode a SyntaxContext - let ctxt_data = decode_data(d, raw_id); - let ctxt_key = ctxt_data.key(); + let ctxt_key = decode_ctxt_key(d, raw_id); let ctxt = HygieneData::with(|hygiene_data| { match hygiene_data.syntax_context_map.get(&ctxt_key) { @@ -1473,29 +1415,10 @@ pub fn decode_syntax_context SyntaxContext Some(&ctxt) => ctxt, // This is a completely new context. // Overwrite its placeholder data with our decoded data. - None => { - let ctxt_data_ref = - &mut hygiene_data.syntax_context_data[pending_ctxt.as_u32() as usize]; - let prev_ctxt_data = mem::replace(ctxt_data_ref, ctxt_data); - // Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names`. - // We don't care what the encoding crate set this to - we want to resolve it - // from the perspective of the current compilation session. - ctxt_data_ref.dollar_crate_name = kw::DollarCrate; - // Make sure nothing weird happened while `decode_data` was running. - if !prev_ctxt_data.is_decode_placeholder() { - // Another thread may have already inserted the decoded data, - // but the decoded data should match. - assert_eq!(prev_ctxt_data, *ctxt_data_ref); - } - hygiene_data.syntax_context_map.insert(ctxt_key, pending_ctxt); - pending_ctxt - } + None => hygiene_data.apply_mark_internal(ctxt_key.0, ctxt_key.1, ctxt_key.2), } }); - // Mark the context as completed - context.local_in_progress.borrow_mut().remove(&raw_id); - let mut inner = context.inner.lock(); let new_len = raw_id as usize + 1; if inner.remapped_ctxts.len() < new_len { @@ -1507,7 +1430,7 @@ pub fn decode_syntax_context SyntaxContext ctxt } -fn for_all_ctxts_in( +fn for_all_ctxts_in( ctxts: impl Iterator, mut f: F, ) { @@ -1515,7 +1438,7 @@ fn for_all_ctxts_in( ctxts.map(|ctxt| (ctxt, data.syntax_context_data[ctxt.0 as usize].clone())).collect() }); for (ctxt, data) in all_data.into_iter() { - f(ctxt.0, ctxt, &data); + f(ctxt.0, ctxt, &data.key()); } } diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout index c80a33206fb4..6fd6cb474693 100644 --- a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout +++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout @@ -5,19 +5,19 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ stream: TokenStream [ Ident { ident: "struct", - span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#4), + span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#5), }, Ident { ident: "S", - span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#4), + span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#5), }, Punct { ch: ';', spacing: Alone, - span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#4), + span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#5), }, ], - span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#5), + span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#4), }, ] #![feature /* 0#0 */(prelude_import)] @@ -59,7 +59,7 @@ macro_rules! outer struct S /* 0#0 */; macro inner /* 0#3 */ { () => { print_bang! { struct S; } } } -struct S /* 0#4 */; +struct S /* 0#5 */; // OK, not a duplicate definition of `S` fn main /* 0#0 */() {} @@ -70,7 +70,7 @@ crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer") crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #3, def_site_ctxt: #3, kind: Macro(Bang, "inner") -crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "print_bang") +crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "print_bang") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") @@ -83,9 +83,9 @@ SyntaxContexts: #1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque) #2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent) #3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent) -#4: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque) -#5: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque) +#4: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque) +#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque) #6: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque) -#7: parent: #5, outer_mark: (crate0::{{expn4}}, Transparent) -#8: parent: #4, outer_mark: (crate0::{{expn4}}, SemiTransparent) +#7: parent: #4, outer_mark: (crate0::{{expn4}}, Transparent) +#8: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent) */ From cf451f08307168f32ffc74b478026e5e3ebc5ca9 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 29 Mar 2025 12:52:10 +0300 Subject: [PATCH 656/745] compiletest: Support matching diagnostics on lines below --- src/doc/rustc-dev-guide/src/tests/ui.md | 15 +++++++++++++++ src/tools/compiletest/src/errors.rs | 8 +++++++- tests/ui/parser/issues/issue-103451.rs | 2 +- tests/ui/parser/issues/issue-10636-2.rs | 2 +- .../issue-58094-missing-right-square-bracket.rs | 3 +-- ...ssue-58094-missing-right-square-bracket.stderr | 2 +- tests/ui/parser/issues/issue-62524.rs | 3 ++- tests/ui/parser/issues/issue-62524.stderr | 2 +- tests/ui/parser/issues/issue-62554.rs | 3 +-- tests/ui/parser/issues/issue-62554.stderr | 2 +- tests/ui/parser/issues/issue-62894.rs | 2 +- tests/ui/parser/issues/issue-62973.rs | 4 +++- tests/ui/parser/issues/issue-62973.stderr | 6 +++--- tests/ui/parser/issues/issue-63116.rs | 3 ++- tests/ui/parser/issues/issue-63116.stderr | 4 ++-- tests/ui/parser/issues/issue-63135.rs | 3 +-- tests/ui/parser/issues/issue-63135.stderr | 2 +- tests/ui/parser/issues/issue-81804.rs | 5 ++--- tests/ui/parser/issues/issue-81804.stderr | 4 ++-- tests/ui/parser/issues/issue-81827.rs | 7 ++----- tests/ui/parser/issues/issue-81827.stderr | 4 ++-- tests/ui/parser/issues/issue-84104.rs | 2 +- tests/ui/parser/issues/issue-84148-2.rs | 2 +- tests/ui/parser/issues/issue-88770.rs | 3 +-- tests/ui/parser/issues/issue-88770.stderr | 2 +- tests/ui/parser/mbe_missing_right_paren.rs | 2 +- tests/ui/parser/missing_right_paren.rs | 3 +-- tests/ui/parser/missing_right_paren.stderr | 2 +- tests/ui/parser/unbalanced-doublequote.rs | 4 +--- tests/ui/parser/unbalanced-doublequote.stderr | 2 +- tests/ui/parser/use-unclosed-brace.rs | 2 +- 31 files changed, 62 insertions(+), 48 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index 98bb9dee76c5..1190c2646af1 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -202,6 +202,9 @@ several ways to match the message with the line (see the examples below): * `~|`: Associates the error level and message with the *same* line as the *previous comment*. This is more convenient than using multiple carets when there are multiple messages associated with the same line. +* `~v`: Associates the error level and message with the *next* error + annotation line. Each symbol (`v`) that you add adds a line to this, so `~vvv` + is three lines below the error annotation line. * `~?`: Used to match error levels and messages with errors not having line information. These can be placed on any line in the test file, but are conventionally placed at the end. @@ -273,6 +276,18 @@ fn main() { //~| ERROR this pattern has 1 field, but the corresponding tuple struct has 3 fields [E0023] ``` +#### Positioned above error line + +Use the `//~v` idiom with number of v's in the string to indicate the number +of lines below. This is typically used in lexer or parser tests matching on errors like unclosed +delimiter or unclosed literal happening at the end of file. + +```rust,ignore +// ignore-tidy-trailing-newlines +//~v ERROR this file contains an unclosed delimiter +fn main((ؼ +``` + #### Error without line information Use `//~?` to match an error without line information. diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index c0566ef93b92..b68f817146fd 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -122,13 +122,17 @@ fn parse_expected( // //~| // //~^ // //~^^^^^ + // //~v + // //~vvvvv // //~? // //[rev1]~ // //[rev1,rev2]~^^ static RE: OnceLock = OnceLock::new(); let captures = RE - .get_or_init(|| Regex::new(r"//(?:\[(?P[\w\-,]+)])?~(?P\?|\||\^*)").unwrap()) + .get_or_init(|| { + Regex::new(r"//(?:\[(?P[\w\-,]+)])?~(?P\?|\||[v\^]*)").unwrap() + }) .captures(line)?; match (test_revision, captures.name("revs")) { @@ -164,6 +168,8 @@ fn parse_expected( (true, Some(last_nonfollow_error.expect("encountered //~| without preceding //~^ line"))) } else if line_num_adjust == "?" { (false, None) + } else if line_num_adjust.starts_with('v') { + (false, Some(line_num + line_num_adjust.len())) } else { (false, Some(line_num - line_num_adjust.len())) }; diff --git a/tests/ui/parser/issues/issue-103451.rs b/tests/ui/parser/issues/issue-103451.rs index 6b0928229e91..687dbc632d67 100644 --- a/tests/ui/parser/issues/issue-103451.rs +++ b/tests/ui/parser/issues/issue-103451.rs @@ -1,4 +1,4 @@ -//@ error-pattern: this file contains an unclosed delimiter struct R { } +//~vv ERROR this file contains an unclosed delimiter struct S { x: [u8; R diff --git a/tests/ui/parser/issues/issue-10636-2.rs b/tests/ui/parser/issues/issue-10636-2.rs index 7200ea1f1dd1..dcc03fec545c 100644 --- a/tests/ui/parser/issues/issue-10636-2.rs +++ b/tests/ui/parser/issues/issue-10636-2.rs @@ -1,7 +1,7 @@ -//@ error-pattern: mismatched closing delimiter: `}` // FIXME(31528) we emit a bunch of silly errors here due to continuing past the // first one. This would be easy-ish to address by better recovery in tokenisation. +//~vvvvv ERROR mismatched closing delimiter: `}` pub fn trace_option(option: Option) { option.map(|some| 42; diff --git a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs index 7952d29c2602..0c0fbd7d5929 100644 --- a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs +++ b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs @@ -1,5 +1,4 @@ // Fixed in #66054. // ignore-tidy-trailing-newlines -//@ error-pattern: this file contains an unclosed delimiter -//@ error-pattern: aborting due to 1 previous error +//~v ERROR this file contains an unclosed delimiter #[Ѕ \ No newline at end of file diff --git a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr index 14f5469f6af9..28fd78d660dd 100644 --- a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr +++ b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/issue-58094-missing-right-square-bracket.rs:5:4 + --> $DIR/issue-58094-missing-right-square-bracket.rs:4:4 | LL | #[Ѕ | - ^ diff --git a/tests/ui/parser/issues/issue-62524.rs b/tests/ui/parser/issues/issue-62524.rs index a219f662cf78..a8c7d6eb9fdd 100644 --- a/tests/ui/parser/issues/issue-62524.rs +++ b/tests/ui/parser/issues/issue-62524.rs @@ -1,6 +1,7 @@ // ignore-tidy-trailing-newlines -//@ error-pattern: aborting due to 1 previous error + #![allow(uncommon_codepoints)] +//~vv ERROR this file contains an unclosed delimiter y![ Ϥ, \ No newline at end of file diff --git a/tests/ui/parser/issues/issue-62524.stderr b/tests/ui/parser/issues/issue-62524.stderr index d83a49aedd6e..c1ff6e7e7158 100644 --- a/tests/ui/parser/issues/issue-62524.stderr +++ b/tests/ui/parser/issues/issue-62524.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/issue-62524.rs:6:3 + --> $DIR/issue-62524.rs:7:3 | LL | y![ | - unclosed delimiter diff --git a/tests/ui/parser/issues/issue-62554.rs b/tests/ui/parser/issues/issue-62554.rs index 9f196e4b0d61..4a8a1684a412 100644 --- a/tests/ui/parser/issues/issue-62554.rs +++ b/tests/ui/parser/issues/issue-62554.rs @@ -1,5 +1,4 @@ -//@ error-pattern:this file contains an unclosed delimiter - fn main() {} +//~v ERROR this file contains an unclosed delimiter fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { diff --git a/tests/ui/parser/issues/issue-62554.stderr b/tests/ui/parser/issues/issue-62554.stderr index d4aaef161813..50515c4c574a 100644 --- a/tests/ui/parser/issues/issue-62554.stderr +++ b/tests/ui/parser/issues/issue-62554.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/issue-62554.rs:5:89 + --> $DIR/issue-62554.rs:4:89 | LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { | - - - - -^ diff --git a/tests/ui/parser/issues/issue-62894.rs b/tests/ui/parser/issues/issue-62894.rs index 5b1627a25537..c49cbe4b934d 100644 --- a/tests/ui/parser/issues/issue-62894.rs +++ b/tests/ui/parser/issues/issue-62894.rs @@ -1,6 +1,6 @@ // Regression test for #62894, shouldn't crash. -//@ error-pattern: this file contains an unclosed delimiter +//~vvv ERROR this file contains an unclosed delimiter fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! fn main() {} diff --git a/tests/ui/parser/issues/issue-62973.rs b/tests/ui/parser/issues/issue-62973.rs index 5c666d802fe4..a091e4eec1d9 100644 --- a/tests/ui/parser/issues/issue-62973.rs +++ b/tests/ui/parser/issues/issue-62973.rs @@ -1,8 +1,10 @@ // ignore-tidy-trailing-newlines -//@ error-pattern: aborting due to 3 previous errors fn main() {} +//~vvv ERROR mismatched closing delimiter: `)` +//~vv ERROR mismatched closing delimiter: `)` +//~vvv ERROR this file contains an unclosed delimiter fn p() { match s { v, E { [) {) } diff --git a/tests/ui/parser/issues/issue-62973.stderr b/tests/ui/parser/issues/issue-62973.stderr index 493183988e18..ea3e2bebee40 100644 --- a/tests/ui/parser/issues/issue-62973.stderr +++ b/tests/ui/parser/issues/issue-62973.stderr @@ -1,5 +1,5 @@ error: mismatched closing delimiter: `)` - --> $DIR/issue-62973.rs:6:27 + --> $DIR/issue-62973.rs:8:27 | LL | fn p() { match s { v, E { [) {) } | ^^ mismatched closing delimiter @@ -7,7 +7,7 @@ LL | fn p() { match s { v, E { [) {) } | unclosed delimiter error: mismatched closing delimiter: `)` - --> $DIR/issue-62973.rs:6:30 + --> $DIR/issue-62973.rs:8:30 | LL | fn p() { match s { v, E { [) {) } | ^^ mismatched closing delimiter @@ -15,7 +15,7 @@ LL | fn p() { match s { v, E { [) {) } | unclosed delimiter error: this file contains an unclosed delimiter - --> $DIR/issue-62973.rs:8:2 + --> $DIR/issue-62973.rs:10:2 | LL | fn p() { match s { v, E { [) {) } | - - - - missing open `(` for this delimiter diff --git a/tests/ui/parser/issues/issue-63116.rs b/tests/ui/parser/issues/issue-63116.rs index 3be9606b4edb..48abe639e8d9 100644 --- a/tests/ui/parser/issues/issue-63116.rs +++ b/tests/ui/parser/issues/issue-63116.rs @@ -1,3 +1,4 @@ // fixed by #66361 -//@ error-pattern: aborting due to 2 previous errors +//~vv ERROR mismatched closing delimiter: `]` +//~v ERROR this file contains an unclosed delimiter impl W $DIR/issue-63116.rs:3:14 + --> $DIR/issue-63116.rs:4:14 | LL | impl W $DIR/issue-63116.rs:3:18 + --> $DIR/issue-63116.rs:4:18 | LL | impl W $DIR/issue-63135.rs:3:16 + --> $DIR/issue-63135.rs:2:16 | LL | fn i(n{...,f # | - - ^ diff --git a/tests/ui/parser/issues/issue-81804.rs b/tests/ui/parser/issues/issue-81804.rs index 7c9e6e905825..57951ca5c4bc 100644 --- a/tests/ui/parser/issues/issue-81804.rs +++ b/tests/ui/parser/issues/issue-81804.rs @@ -1,6 +1,5 @@ -//@ error-pattern: this file contains an unclosed delimiter -//@ error-pattern: this file contains an unclosed delimiter - fn main() {} +//~vv ERROR mismatched closing delimiter: `}` +//~v ERROR this file contains an unclosed delimiter fn p([=(} diff --git a/tests/ui/parser/issues/issue-81804.stderr b/tests/ui/parser/issues/issue-81804.stderr index 6caaaa792b19..f12c6a61ce5e 100644 --- a/tests/ui/parser/issues/issue-81804.stderr +++ b/tests/ui/parser/issues/issue-81804.stderr @@ -1,5 +1,5 @@ error: mismatched closing delimiter: `}` - --> $DIR/issue-81804.rs:6:8 + --> $DIR/issue-81804.rs:5:8 | LL | fn p([=(} | ^^ mismatched closing delimiter @@ -7,7 +7,7 @@ LL | fn p([=(} | unclosed delimiter error: this file contains an unclosed delimiter - --> $DIR/issue-81804.rs:6:11 + --> $DIR/issue-81804.rs:5:11 | LL | fn p([=(} | -- ^ diff --git a/tests/ui/parser/issues/issue-81827.rs b/tests/ui/parser/issues/issue-81827.rs index a2bd345fc050..7dfeec13022a 100644 --- a/tests/ui/parser/issues/issue-81827.rs +++ b/tests/ui/parser/issues/issue-81827.rs @@ -1,10 +1,7 @@ -//@ error-pattern: this file contains an unclosed delimiter -//@ error-pattern: mismatched closing delimiter: `]` - #![crate_name="0"] - - fn main() {} +//~vv ERROR mismatched closing delimiter: `]` +//~v ERROR this file contains an unclosed delimiter fn r()->i{0|{#[cfg(r(0{]0 diff --git a/tests/ui/parser/issues/issue-81827.stderr b/tests/ui/parser/issues/issue-81827.stderr index d12c74b4a342..986ed6b7e70f 100644 --- a/tests/ui/parser/issues/issue-81827.stderr +++ b/tests/ui/parser/issues/issue-81827.stderr @@ -1,5 +1,5 @@ error: mismatched closing delimiter: `]` - --> $DIR/issue-81827.rs:10:23 + --> $DIR/issue-81827.rs:7:23 | LL | fn r()->i{0|{#[cfg(r(0{]0 | - ^^ mismatched closing delimiter @@ -8,7 +8,7 @@ LL | fn r()->i{0|{#[cfg(r(0{]0 | closing delimiter possibly meant for this error: this file contains an unclosed delimiter - --> $DIR/issue-81827.rs:10:27 + --> $DIR/issue-81827.rs:7:27 | LL | fn r()->i{0|{#[cfg(r(0{]0 | - - - ^ diff --git a/tests/ui/parser/issues/issue-84104.rs b/tests/ui/parser/issues/issue-84104.rs index bced05e684a7..6baf882701d3 100644 --- a/tests/ui/parser/issues/issue-84104.rs +++ b/tests/ui/parser/issues/issue-84104.rs @@ -1,2 +1,2 @@ -//@ error-pattern: this file contains an unclosed delimiter +//~v ERROR this file contains an unclosed delimiter #[i=i::<ښܖ< diff --git a/tests/ui/parser/issues/issue-84148-2.rs b/tests/ui/parser/issues/issue-84148-2.rs index 560475bd32c3..452279021ab9 100644 --- a/tests/ui/parser/issues/issue-84148-2.rs +++ b/tests/ui/parser/issues/issue-84148-2.rs @@ -1,2 +1,2 @@ -//@ error-pattern: this file contains an unclosed delimiter +//~v ERROR this file contains an unclosed delimiter fn f(t:for<>t? diff --git a/tests/ui/parser/issues/issue-88770.rs b/tests/ui/parser/issues/issue-88770.rs index ecc50481f65d..0dd18435ce3f 100644 --- a/tests/ui/parser/issues/issue-88770.rs +++ b/tests/ui/parser/issues/issue-88770.rs @@ -1,7 +1,6 @@ // Regression test for the ICE described in #88770. -//@ error-pattern:this file contains an unclosed delimiter - +//~vvvv ERROR this file contains an unclosed delimiter fn m(){print!("",(c for&g u e diff --git a/tests/ui/parser/issues/issue-88770.stderr b/tests/ui/parser/issues/issue-88770.stderr index 5b54072d009f..137cfea7e1d0 100644 --- a/tests/ui/parser/issues/issue-88770.stderr +++ b/tests/ui/parser/issues/issue-88770.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/issue-88770.rs:8:3 + --> $DIR/issue-88770.rs:7:3 | LL | fn m(){print!("",(c for&g | - - - unclosed delimiter diff --git a/tests/ui/parser/mbe_missing_right_paren.rs b/tests/ui/parser/mbe_missing_right_paren.rs index 9c57b0ebcfc3..851919316647 100644 --- a/tests/ui/parser/mbe_missing_right_paren.rs +++ b/tests/ui/parser/mbe_missing_right_paren.rs @@ -1,3 +1,3 @@ // ignore-tidy-trailing-newlines -//@ error-pattern: this file contains an unclosed delimiter +//~v ERROR this file contains an unclosed delimiter macro_rules! abc(ؼ \ No newline at end of file diff --git a/tests/ui/parser/missing_right_paren.rs b/tests/ui/parser/missing_right_paren.rs index bbf4519a713e..311a16c214c3 100644 --- a/tests/ui/parser/missing_right_paren.rs +++ b/tests/ui/parser/missing_right_paren.rs @@ -1,4 +1,3 @@ // ignore-tidy-trailing-newlines -//@ error-pattern: this file contains an unclosed delimiter -//@ error-pattern: aborting due to 1 previous error +//~v ERROR this file contains an unclosed delimiter fn main((ؼ \ No newline at end of file diff --git a/tests/ui/parser/missing_right_paren.stderr b/tests/ui/parser/missing_right_paren.stderr index 4815f04fbce0..97ccb40a5a2a 100644 --- a/tests/ui/parser/missing_right_paren.stderr +++ b/tests/ui/parser/missing_right_paren.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/missing_right_paren.rs:4:11 + --> $DIR/missing_right_paren.rs:3:11 | LL | fn main((ؼ | -- ^ diff --git a/tests/ui/parser/unbalanced-doublequote.rs b/tests/ui/parser/unbalanced-doublequote.rs index d9c936186ea0..43e23a70271b 100644 --- a/tests/ui/parser/unbalanced-doublequote.rs +++ b/tests/ui/parser/unbalanced-doublequote.rs @@ -1,6 +1,4 @@ -//@ error-pattern: unterminated double quote string - - +//~vv ERROR unterminated double quote string fn main() { " } diff --git a/tests/ui/parser/unbalanced-doublequote.stderr b/tests/ui/parser/unbalanced-doublequote.stderr index d40b982da7c3..60057eddbb42 100644 --- a/tests/ui/parser/unbalanced-doublequote.stderr +++ b/tests/ui/parser/unbalanced-doublequote.stderr @@ -1,5 +1,5 @@ error[E0765]: unterminated double quote string - --> $DIR/unbalanced-doublequote.rs:5:5 + --> $DIR/unbalanced-doublequote.rs:3:5 | LL | / " LL | | } diff --git a/tests/ui/parser/use-unclosed-brace.rs b/tests/ui/parser/use-unclosed-brace.rs index 6679651fe47e..aa52fe92ac1b 100644 --- a/tests/ui/parser/use-unclosed-brace.rs +++ b/tests/ui/parser/use-unclosed-brace.rs @@ -1,4 +1,3 @@ -//@ error-pattern: this file contains an unclosed delimiter use foo::{bar, baz; use std::fmt::Display; @@ -7,4 +6,5 @@ mod bar { } mod baz { } +//~v ERROR this file contains an unclosed delimiter fn main() {} From 439048e074e1a4293e1839875e799329d92e4f81 Mon Sep 17 00:00:00 2001 From: Lieselotte <52315535+she3py@users.noreply.github.com> Date: Sat, 29 Mar 2025 12:21:51 +0100 Subject: [PATCH 657/745] `BackendRepr::is_signed`: comment why this may panics --- compiler/rustc_abi/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 3f28dc7a1efa..843d5ca61ddd 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1462,7 +1462,8 @@ impl BackendRepr { !self.is_unsized() } - /// Returns `true` if this is a single signed integer scalar + /// Returns `true` if this is a single signed integer scalar. + /// Sanity check: panics if this is not a scalar type (see PR #70189). #[inline] pub fn is_signed(&self) -> bool { match self { From daeb449640b189069f76a13a4a208b1a6d6a32b6 Mon Sep 17 00:00:00 2001 From: Lieselotte <52315535+she3py@users.noreply.github.com> Date: Sat, 29 Mar 2025 12:39:06 +0100 Subject: [PATCH 658/745] Mark .pp files as Rust --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index d29c15fe712f..8700d5d6dcff 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,6 +5,7 @@ *.h rust *.rs rust diff=rust *.fixed linguist-language=Rust +*.pp linguist-language=Rust *.mir linguist-language=Rust src/etc/installer/gfx/* binary src/vendor/** -text From 89c9c21b06c8661242b0545f690ac3e716327ac6 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sat, 22 Mar 2025 11:24:33 +0000 Subject: [PATCH 659/745] Start using with_native_path in std::sys::fs --- library/std/src/fs.rs | 16 +-- library/std/src/sys/fs/mod.rs | 101 +++++++++++++++-- library/std/src/sys/fs/unix.rs | 199 +++++++++++++++------------------ 3 files changed, 191 insertions(+), 125 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index f9a360585e85..01fbd27e3991 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -2362,7 +2362,7 @@ impl AsInner for DirEntry { #[doc(alias = "rm", alias = "unlink", alias = "DeleteFile")] #[stable(feature = "rust1", since = "1.0.0")] pub fn remove_file>(path: P) -> io::Result<()> { - fs_imp::unlink(path.as_ref()) + fs_imp::remove_file(path.as_ref()) } /// Given a path, queries the file system to get information about a file, @@ -2401,7 +2401,7 @@ pub fn remove_file>(path: P) -> io::Result<()> { #[doc(alias = "stat")] #[stable(feature = "rust1", since = "1.0.0")] pub fn metadata>(path: P) -> io::Result { - fs_imp::stat(path.as_ref()).map(Metadata) + fs_imp::metadata(path.as_ref()).map(Metadata) } /// Queries the metadata about a file without following symlinks. @@ -2436,7 +2436,7 @@ pub fn metadata>(path: P) -> io::Result { #[doc(alias = "lstat")] #[stable(feature = "symlink_metadata", since = "1.1.0")] pub fn symlink_metadata>(path: P) -> io::Result { - fs_imp::lstat(path.as_ref()).map(Metadata) + fs_imp::symlink_metadata(path.as_ref()).map(Metadata) } /// Renames a file or directory to a new name, replacing the original file if @@ -2590,7 +2590,7 @@ pub fn copy, Q: AsRef>(from: P, to: Q) -> io::Result { #[doc(alias = "CreateHardLink", alias = "linkat")] #[stable(feature = "rust1", since = "1.0.0")] pub fn hard_link, Q: AsRef>(original: P, link: Q) -> io::Result<()> { - fs_imp::link(original.as_ref(), link.as_ref()) + fs_imp::hard_link(original.as_ref(), link.as_ref()) } /// Creates a new symbolic link on the filesystem. @@ -2656,7 +2656,7 @@ pub fn soft_link, Q: AsRef>(original: P, link: Q) -> io::Re /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn read_link>(path: P) -> io::Result { - fs_imp::readlink(path.as_ref()) + fs_imp::read_link(path.as_ref()) } /// Returns the canonical, absolute form of a path with all intermediate @@ -2832,7 +2832,7 @@ pub fn create_dir_all>(path: P) -> io::Result<()> { #[doc(alias = "rmdir", alias = "RemoveDirectory")] #[stable(feature = "rust1", since = "1.0.0")] pub fn remove_dir>(path: P) -> io::Result<()> { - fs_imp::rmdir(path.as_ref()) + fs_imp::remove_dir(path.as_ref()) } /// Removes a directory at this path, after removing all its contents. Use @@ -2959,7 +2959,7 @@ pub fn remove_dir_all>(path: P) -> io::Result<()> { #[doc(alias = "ls", alias = "opendir", alias = "FindFirstFile", alias = "FindNextFile")] #[stable(feature = "rust1", since = "1.0.0")] pub fn read_dir>(path: P) -> io::Result { - fs_imp::readdir(path.as_ref()).map(ReadDir) + fs_imp::read_dir(path.as_ref()).map(ReadDir) } /// Changes the permissions found on a file or a directory. @@ -2995,7 +2995,7 @@ pub fn read_dir>(path: P) -> io::Result { #[doc(alias = "chmod", alias = "SetFileAttributes")] #[stable(feature = "set_permissions", since = "1.1.0")] pub fn set_permissions>(path: P, perm: Permissions) -> io::Result<()> { - fs_imp::set_perm(path.as_ref(), perm.0) + fs_imp::set_permissions(path.as_ref(), perm.0) } impl DirBuilder { diff --git a/library/std/src/sys/fs/mod.rs b/library/std/src/sys/fs/mod.rs index c2e19eb393a1..3b176d0d16c4 100644 --- a/library/std/src/sys/fs/mod.rs +++ b/library/std/src/sys/fs/mod.rs @@ -1,28 +1,115 @@ #![deny(unsafe_op_in_unsafe_fn)] +use crate::io; +use crate::path::{Path, PathBuf}; + pub mod common; cfg_if::cfg_if! { if #[cfg(target_family = "unix")] { mod unix; - pub use unix::*; + use unix as imp; + pub use unix::{chown, fchown, lchown}; + #[cfg(not(target_os = "fuchsia"))] + pub use unix::chroot; + pub(crate) use unix::debug_assert_fd_is_open; + #[cfg(any(target_os = "linux", target_os = "android"))] + pub(crate) use unix::CachedFileMetadata; + use crate::sys::common::small_c_string::run_path_with_cstr as with_native_path; } else if #[cfg(target_os = "windows")] { mod windows; - pub use windows::*; + use windows as imp; + pub use windows::{symlink_inner, junction_point}; } else if #[cfg(target_os = "hermit")] { mod hermit; - pub use hermit::*; + use hermit as imp; } else if #[cfg(target_os = "solid_asp3")] { mod solid; - pub use solid::*; + use solid as imp; } else if #[cfg(target_os = "uefi")] { mod uefi; - pub use uefi::*; + use uefi as imp; } else if #[cfg(target_os = "wasi")] { mod wasi; - pub use wasi::*; + use wasi as imp; } else { mod unsupported; - pub use unsupported::*; + use unsupported as imp; } } + +// FIXME: Replace this with platform-specific path conversion functions. +#[cfg(not(target_family = "unix"))] +#[inline] +pub fn with_native_path(path: &Path, f: &dyn Fn(&Path) -> io::Result) -> io::Result { + f(path) +} + +pub use imp::{ + DirBuilder, DirEntry, File, FileAttr, FilePermissions, FileTimes, FileType, OpenOptions, + ReadDir, +}; + +pub fn read_dir(path: &Path) -> io::Result { + // FIXME: use with_native_path + imp::readdir(path) +} + +pub fn remove_file(path: &Path) -> io::Result<()> { + with_native_path(path, &imp::unlink) +} + +pub fn rename(old: &Path, new: &Path) -> io::Result<()> { + with_native_path(old, &|old| with_native_path(new, &|new| imp::rename(old, new))) +} + +pub fn remove_dir(path: &Path) -> io::Result<()> { + with_native_path(path, &imp::rmdir) +} + +pub fn remove_dir_all(path: &Path) -> io::Result<()> { + // FIXME: use with_native_path + imp::remove_dir_all(path) +} + +pub fn read_link(path: &Path) -> io::Result { + with_native_path(path, &imp::readlink) +} + +pub fn symlink(original: &Path, link: &Path) -> io::Result<()> { + with_native_path(original, &|original| { + with_native_path(link, &|link| imp::symlink(original, link)) + }) +} + +pub fn hard_link(original: &Path, link: &Path) -> io::Result<()> { + with_native_path(original, &|original| { + with_native_path(link, &|link| imp::link(original, link)) + }) +} + +pub fn metadata(path: &Path) -> io::Result { + with_native_path(path, &imp::stat) +} + +pub fn symlink_metadata(path: &Path) -> io::Result { + with_native_path(path, &imp::lstat) +} + +pub fn set_permissions(path: &Path, perm: FilePermissions) -> io::Result<()> { + with_native_path(path, &|path| imp::set_perm(path, perm.clone())) +} + +pub fn canonicalize(path: &Path) -> io::Result { + with_native_path(path, &imp::canonicalize) +} + +pub fn copy(from: &Path, to: &Path) -> io::Result { + // FIXME: use with_native_path + imp::copy(from, to) +} + +pub fn exists(path: &Path) -> io::Result { + // FIXME: use with_native_path + imp::exists(path) +} diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 7c3ed8029f7d..e32392ca94eb 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -926,7 +926,7 @@ impl DirEntry { miri ))] pub fn metadata(&self) -> io::Result { - lstat(&self.path()) + run_path_with_cstr(&self.path(), &lstat) } #[cfg(any( @@ -1653,7 +1653,7 @@ impl fmt::Debug for File { fn get_path(fd: c_int) -> Option { let mut p = PathBuf::from("/proc/self/fd"); p.push(&fd.to_string()); - readlink(&p).ok() + run_path_with_cstr(&p, &readlink).ok() } #[cfg(any(target_vendor = "apple", target_os = "netbsd"))] @@ -1671,7 +1671,7 @@ impl fmt::Debug for File { // fallback to procfs as last resort let mut p = PathBuf::from("/proc/self/fd"); p.push(&fd.to_string()); - return readlink(&p).ok(); + return run_path_with_cstr(&p, &readlink).ok() } else { return None; } @@ -1826,127 +1826,106 @@ pub fn readdir(path: &Path) -> io::Result { } } -pub fn unlink(p: &Path) -> io::Result<()> { - run_path_with_cstr(p, &|p| cvt(unsafe { libc::unlink(p.as_ptr()) }).map(|_| ())) +pub fn unlink(p: &CStr) -> io::Result<()> { + cvt(unsafe { libc::unlink(p.as_ptr()) }).map(|_| ()) } -pub fn rename(old: &Path, new: &Path) -> io::Result<()> { - run_path_with_cstr(old, &|old| { - run_path_with_cstr(new, &|new| { - cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) }).map(|_| ()) - }) - }) +pub fn rename(old: &CStr, new: &CStr) -> io::Result<()> { + cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) }).map(|_| ()) } -pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> { - run_path_with_cstr(p, &|p| cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) }).map(|_| ())) +pub fn set_perm(p: &CStr, perm: FilePermissions) -> io::Result<()> { + cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) }).map(|_| ()) } -pub fn rmdir(p: &Path) -> io::Result<()> { - run_path_with_cstr(p, &|p| cvt(unsafe { libc::rmdir(p.as_ptr()) }).map(|_| ())) +pub fn rmdir(p: &CStr) -> io::Result<()> { + cvt(unsafe { libc::rmdir(p.as_ptr()) }).map(|_| ()) } -pub fn readlink(p: &Path) -> io::Result { - run_path_with_cstr(p, &|c_path| { - let p = c_path.as_ptr(); +pub fn readlink(c_path: &CStr) -> io::Result { + let p = c_path.as_ptr(); - let mut buf = Vec::with_capacity(256); + let mut buf = Vec::with_capacity(256); - loop { - let buf_read = - cvt(unsafe { libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity()) })? - as usize; + loop { + let buf_read = + cvt(unsafe { libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity()) })? as usize; - unsafe { - buf.set_len(buf_read); - } - - if buf_read != buf.capacity() { - buf.shrink_to_fit(); - - return Ok(PathBuf::from(OsString::from_vec(buf))); - } - - // Trigger the internal buffer resizing logic of `Vec` by requiring - // more space than the current capacity. The length is guaranteed to be - // the same as the capacity due to the if statement above. - buf.reserve(1); - } - }) -} - -pub fn symlink(original: &Path, link: &Path) -> io::Result<()> { - run_path_with_cstr(original, &|original| { - run_path_with_cstr(link, &|link| { - cvt(unsafe { libc::symlink(original.as_ptr(), link.as_ptr()) }).map(|_| ()) - }) - }) -} - -pub fn link(original: &Path, link: &Path) -> io::Result<()> { - run_path_with_cstr(original, &|original| { - run_path_with_cstr(link, &|link| { - cfg_if::cfg_if! { - if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita", target_env = "nto70"))] { - // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves - // it implementation-defined whether `link` follows symlinks, so rely on the - // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior. - // Android has `linkat` on newer versions, but we happen to know `link` - // always has the correct behavior, so it's here as well. - cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?; - } else { - // Where we can, use `linkat` instead of `link`; see the comment above - // this one for details on why. - cvt(unsafe { libc::linkat(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?; - } - } - Ok(()) - }) - }) -} - -pub fn stat(p: &Path) -> io::Result { - run_path_with_cstr(p, &|p| { - cfg_has_statx! { - if let Some(ret) = unsafe { try_statx( - libc::AT_FDCWD, - p.as_ptr(), - libc::AT_STATX_SYNC_AS_STAT, - libc::STATX_BASIC_STATS | libc::STATX_BTIME, - ) } { - return ret; - } + unsafe { + buf.set_len(buf_read); } - let mut stat: stat64 = unsafe { mem::zeroed() }; - cvt(unsafe { stat64(p.as_ptr(), &mut stat) })?; - Ok(FileAttr::from_stat64(stat)) - }) -} + if buf_read != buf.capacity() { + buf.shrink_to_fit(); -pub fn lstat(p: &Path) -> io::Result { - run_path_with_cstr(p, &|p| { - cfg_has_statx! { - if let Some(ret) = unsafe { try_statx( - libc::AT_FDCWD, - p.as_ptr(), - libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT, - libc::STATX_BASIC_STATS | libc::STATX_BTIME, - ) } { - return ret; - } + return Ok(PathBuf::from(OsString::from_vec(buf))); } - let mut stat: stat64 = unsafe { mem::zeroed() }; - cvt(unsafe { lstat64(p.as_ptr(), &mut stat) })?; - Ok(FileAttr::from_stat64(stat)) - }) + // Trigger the internal buffer resizing logic of `Vec` by requiring + // more space than the current capacity. The length is guaranteed to be + // the same as the capacity due to the if statement above. + buf.reserve(1); + } } -pub fn canonicalize(p: &Path) -> io::Result { - let r = run_path_with_cstr(p, &|path| unsafe { - Ok(libc::realpath(path.as_ptr(), ptr::null_mut())) - })?; +pub fn symlink(original: &CStr, link: &CStr) -> io::Result<()> { + cvt(unsafe { libc::symlink(original.as_ptr(), link.as_ptr()) }).map(|_| ()) +} + +pub fn link(original: &CStr, link: &CStr) -> io::Result<()> { + cfg_if::cfg_if! { + if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita", target_env = "nto70"))] { + // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves + // it implementation-defined whether `link` follows symlinks, so rely on the + // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior. + // Android has `linkat` on newer versions, but we happen to know `link` + // always has the correct behavior, so it's here as well. + cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?; + } else { + // Where we can, use `linkat` instead of `link`; see the comment above + // this one for details on why. + cvt(unsafe { libc::linkat(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?; + } + } + Ok(()) +} + +pub fn stat(p: &CStr) -> io::Result { + cfg_has_statx! { + if let Some(ret) = unsafe { try_statx( + libc::AT_FDCWD, + p.as_ptr(), + libc::AT_STATX_SYNC_AS_STAT, + libc::STATX_BASIC_STATS | libc::STATX_BTIME, + ) } { + return ret; + } + } + + let mut stat: stat64 = unsafe { mem::zeroed() }; + cvt(unsafe { stat64(p.as_ptr(), &mut stat) })?; + Ok(FileAttr::from_stat64(stat)) +} + +pub fn lstat(p: &CStr) -> io::Result { + cfg_has_statx! { + if let Some(ret) = unsafe { try_statx( + libc::AT_FDCWD, + p.as_ptr(), + libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT, + libc::STATX_BASIC_STATS | libc::STATX_BTIME, + ) } { + return ret; + } + } + + let mut stat: stat64 = unsafe { mem::zeroed() }; + cvt(unsafe { lstat64(p.as_ptr(), &mut stat) })?; + Ok(FileAttr::from_stat64(stat)) +} + +pub fn canonicalize(path: &CStr) -> io::Result { + let r = unsafe { libc::realpath(path.as_ptr(), ptr::null_mut()) }; if r.is_null() { return Err(io::Error::last_os_error()); } @@ -2324,19 +2303,19 @@ mod remove_dir_impl { Ok(()) } - fn remove_dir_all_modern(p: &Path) -> io::Result<()> { + fn remove_dir_all_modern(p: &CStr) -> io::Result<()> { // We cannot just call remove_dir_all_recursive() here because that would not delete a passed // symlink. No need to worry about races, because remove_dir_all_recursive() does not recurse // into symlinks. let attr = lstat(p)?; if attr.file_type().is_symlink() { - crate::fs::remove_file(p) + super::unlink(p) } else { - run_path_with_cstr(p, &|p| remove_dir_all_recursive(None, &p)) + remove_dir_all_recursive(None, &p) } } pub fn remove_dir_all(p: &Path) -> io::Result<()> { - remove_dir_all_modern(p) + run_path_with_cstr(p, &remove_dir_all_modern) } } From 02899f86f5b6d3aa87e9809fa3ee0d91fa3df574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Sat, 29 Mar 2025 17:27:33 +0100 Subject: [PATCH 660/745] Properly document FakeReads --- compiler/rustc_middle/src/mir/syntax.rs | 112 ++++++++++++++++++------ 1 file changed, 84 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 4f86703e9537..6d6e6a1f185b 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -334,14 +334,19 @@ pub enum StatementKind<'tcx> { /// See [`Rvalue`] documentation for details on each of those. Assign(Box<(Place<'tcx>, Rvalue<'tcx>)>), - /// This represents all the reading that a pattern match may do (e.g., inspecting constants and - /// discriminant values), and the kind of pattern it comes from. This is in order to adapt - /// potential error messages to these specific patterns. + /// When executed at runtime, this is a nop. /// - /// Note that this also is emitted for regular `let` bindings to ensure that locals that are - /// never accessed still get some sanity checks for, e.g., `let x: ! = ..;` + /// During static analysis, a fake read: + /// - requires that the value being read is initialized (or, in the case + /// of closures, that it was fully initialized at some point in the past) + /// - constitutes a use of a value for the purposes of NLL (i.e. if the + /// value being fake-read is a reference, the lifetime of that reference + /// will be extended to cover the `FakeRead`) + /// - but, unlike an actual read, does *not* invalidate any exclusive + /// borrows. /// - /// When executed at runtime this is a nop. + /// See [`FakeReadCause`] for more details on the situations in which a + /// `FakeRead` is emitted. /// /// Disallowed after drop elaboration. FakeRead(Box<(FakeReadCause, Place<'tcx>)>), @@ -518,28 +523,59 @@ pub enum RetagKind { /// The `FakeReadCause` describes the type of pattern why a FakeRead statement exists. #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, Hash, HashStable, PartialEq)] pub enum FakeReadCause { - /// Inject a fake read of the borrowed input at the end of each guards - /// code. + /// A fake read injected into a match guard to ensure that the discriminants + /// that are being matched on aren't modified while the match guard is being + /// evaluated. + /// + /// At the beginning of each match guard, a [fake borrow][FakeBorrowKind] is + /// inserted for each discriminant accessed in the entire `match` statement. + /// + /// Then, at the end of the match guard, a `FakeRead(ForMatchGuard)` is + /// inserted to keep the fake borrows alive until that point. /// /// This should ensure that you cannot change the variant for an enum while /// you are in the midst of matching on it. ForMatchGuard, - /// `let x: !; match x {}` doesn't generate any read of x so we need to - /// generate a read of x to check that it is initialized and safe. + /// Fake read of the scrutinee of a `match` or destructuring `let` + /// (i.e. `let` with non-trivial pattern). /// - /// If a closure pattern matches a Place starting with an Upvar, then we introduce a - /// FakeRead for that Place outside the closure, in such a case this option would be - /// Some(closure_def_id). - /// Otherwise, the value of the optional LocalDefId will be None. + /// In `match x { ... }`, we generate a `FakeRead(ForMatchedPlace, x)` + /// and insert it into the `otherwise_block` (which is supposed to be + /// unreachable for irrefutable pattern-matches like `match` or `let`). + /// + /// This is necessary because `let x: !; match x {}` doesn't generate any + /// actual read of x, so we need to generate a `FakeRead` to check that it + /// is initialized. + /// + /// If the `FakeRead(ForMatchedPlace)` is being performed with a closure + /// that doesn't capture the required upvars, the `FakeRead` within the + /// closure is omitted entirely. + /// + /// To make sure that this is still sound, if a closure matches against + /// a Place starting with an Upvar, we hoist the `FakeRead` to the + /// definition point of the closure. + /// + /// If the `FakeRead` comes from being hoisted out of a closure like this, + /// we record the `LocalDefId` of the closure. Otherwise, the `Option` will be `None`. // // We can use LocalDefId here since fake read statements are removed // before codegen in the `CleanupNonCodegenStatements` pass. ForMatchedPlace(Option), - /// A fake read of the RefWithinGuard version of a bind-by-value variable - /// in a match guard to ensure that its value hasn't change by the time - /// we create the OutsideGuard version. + /// A fake read injected into a match guard to ensure that the places + /// bound by the pattern are immutable for the duration of the match guard. + /// + /// Within a match guard, references are created for each place that the + /// pattern creates a binding for — this is known as the `RefWithinGuard` + /// version of the variables. To make sure that the references stay + /// alive until the end of the match guard, and properly prevent the + /// places in question from being modified, a `FakeRead(ForGuardBinding)` + /// is inserted at the end of the match guard. + /// + /// For details on how these references are created, see the extensive + /// documentation on `bind_matched_candidate_for_guard` in + /// `rustc_mir_build`. ForGuardBinding, /// Officially, the semantics of @@ -552,22 +588,42 @@ pub enum FakeReadCause { /// However, if we see the simple pattern `let var = `, we optimize this to /// evaluate `` directly into the variable `var`. This is mostly unobservable, /// but in some cases it can affect the borrow checker, as in #53695. - /// Therefore, we insert a "fake read" here to ensure that we get - /// appropriate errors. /// - /// If a closure pattern matches a Place starting with an Upvar, then we introduce a - /// FakeRead for that Place outside the closure, in such a case this option would be - /// Some(closure_def_id). - /// Otherwise, the value of the optional DefId will be None. + /// Therefore, we insert a `FakeRead(ForLet)` immediately after each `let` + /// with a trivial pattern. + /// + /// FIXME: `ExprUseVisitor` has an entirely different opinion on what `FakeRead(ForLet)` + /// is supposed to mean. If it was accurate to what MIR lowering does, + /// would it even make sense to hoist these out of closures like + /// `ForMatchedPlace`? ForLet(Option), - /// If we have an index expression like + /// Currently, index expressions overloaded through the `Index` trait + /// get lowered differently than index expressions with builtin semantics + /// for arrays and slices — the latter will emit code to perform + /// bound checks, and then return a MIR place that will only perform the + /// indexing "for real" when it gets incorporated into an instruction. /// - /// (*x)[1][{ x = y; 4}] + /// This is observable in the fact that the following compiles: /// - /// then the first bounds check is invalidated when we evaluate the second - /// index expression. Thus we create a fake borrow of `x` across the second - /// indexer, which will cause a borrow check error. + /// ``` + /// fn f(x: &mut [&mut [u32]], i: usize) { + /// x[i][x[i].len() - 1] += 1; + /// } + /// ``` + /// + /// However, we need to be careful to not let the user invalidate the + /// bound check with an expression like + /// + /// `(*x)[1][{ x = y; 4}]` + /// + /// Here, the first bounds check would be invalidated when we evaluate the + /// second index expression. To make sure that this doesn't happen, we + /// create a fake borrow of `x` and hold it while we evaluate the second + /// index. + /// + /// This borrow is kept alive by a `FakeRead(ForIndex)` at the end of its + /// scope. ForIndex, } From 2dfd2a2a242e920b7378328b87f901652d9d81be Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 30 Mar 2025 00:39:55 +0300 Subject: [PATCH 661/745] Remove attribute `#[rustc_error]` --- compiler/rustc_feature/src/builtin_attrs.rs | 6 +-- compiler/rustc_interface/messages.ftl | 6 --- compiler/rustc_interface/src/errors.rs | 14 ------- compiler/rustc_interface/src/passes.rs | 42 +++---------------- compiler/rustc_middle/src/util/bug.rs | 2 +- compiler/rustc_span/src/symbol.rs | 2 +- .../crates/hir-expand/src/inert_attr_macro.rs | 4 -- tests/incremental/delayed_span_bug.rs | 4 +- .../bound-lifetime-constrained.ok.stderr | 8 ---- .../bound-lifetime-constrained.rs | 5 +-- .../bound-lifetime-in-binding-only.ok.stderr | 8 ---- .../bound-lifetime-in-binding-only.rs | 5 +-- .../bound-lifetime-in-return-only.ok.stderr | 8 ---- .../bound-lifetime-in-return-only.rs | 5 +-- .../borrowck-report-with-custom-diagnostic.rs | 3 +- ...rowck-report-with-custom-diagnostic.stderr | 6 +-- tests/ui/borrowck/mut-borrow-outside-loop.rs | 4 +- tests/ui/codemap_tests/issue-11715.rs | 3 +- tests/ui/codemap_tests/issue-11715.stderr | 2 +- tests/ui/consts/async-block.rs | 5 +-- .../ui/consts/async-block.with_feature.stderr | 8 ---- .../allow-non-lint-warnings.rs | 10 +++-- ...llow-non-lint-warnings.without_flag.stderr | 10 +++-- .../feature-gate-rustc-attrs-1.rs | 1 - .../feature-gate-rustc-attrs-1.stderr | 13 +----- tests/ui/mir/issue-75053.rs | 5 +-- tests/ui/mir/issue-75053.stderr | 8 ---- tests/ui/proc-macro/no-macro-use-attr.rs | 5 +-- tests/ui/proc-macro/no-macro-use-attr.stderr | 8 +--- .../feature-gate.no_gate.stderr | 2 +- .../feature-gate.rs | 6 +-- .../feature-gate.with_gate.stderr | 8 ---- tests/ui/rustc-error.rs | 6 --- tests/ui/rustc-error.stderr | 8 ---- tests/ui/span/range-2.rs | 4 +- .../regionck-unboxed-closure-lifetimes.rs | 3 +- .../regionck-unboxed-closure-lifetimes.stderr | 2 +- tests/ui/suggestions/attribute-typos.rs | 4 +- tests/ui/suggestions/attribute-typos.stderr | 10 ++--- .../const-traits/feature-gate.gated.stderr | 8 ---- tests/ui/traits/const-traits/feature-gate.rs | 5 +-- tests/ui/treat-err-as-bug/span_delayed_bug.rs | 2 +- .../treat-err-as-bug/span_delayed_bug.stderr | 2 +- tests/ui/type-alias-impl-trait/issue-53096.rs | 6 +-- .../type-alias-impl-trait/issue-53096.stderr | 8 ---- tests/ui/type-alias-impl-trait/issue-60407.rs | 6 +-- .../type-alias-impl-trait/issue-60407.stderr | 8 ---- 47 files changed, 72 insertions(+), 236 deletions(-) delete mode 100644 tests/ui/associated-types/bound-lifetime-constrained.ok.stderr delete mode 100644 tests/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr delete mode 100644 tests/ui/associated-types/bound-lifetime-in-return-only.ok.stderr delete mode 100644 tests/ui/consts/async-block.with_feature.stderr delete mode 100644 tests/ui/mir/issue-75053.stderr delete mode 100644 tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr delete mode 100644 tests/ui/rustc-error.rs delete mode 100644 tests/ui/rustc-error.stderr delete mode 100644 tests/ui/traits/const-traits/feature-gate.gated.stderr delete mode 100644 tests/ui/type-alias-impl-trait/issue-53096.stderr delete mode 100644 tests/ui/type-alias-impl-trait/issue-60407.stderr diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 6fe65c88f712..1e33e2e9393f 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -1087,9 +1087,9 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ WarnFollowing, EncodeCrossCrate::No ), rustc_attr!( - TEST, rustc_error, Normal, - template!(Word, List: "delayed_bug_from_inside_query"), - WarnFollowingWordOnly, EncodeCrossCrate::Yes + TEST, rustc_delayed_bug_from_inside_query, Normal, + template!(Word), + WarnFollowing, EncodeCrossCrate::No ), rustc_attr!( TEST, rustc_dump_user_args, Normal, template!(Word), diff --git a/compiler/rustc_interface/messages.ftl b/compiler/rustc_interface/messages.ftl index ffbe708ba8da..4b9c71d71725 100644 --- a/compiler/rustc_interface/messages.ftl +++ b/compiler/rustc_interface/messages.ftl @@ -50,11 +50,5 @@ interface_out_dir_error = interface_proc_macro_crate_panic_abort = building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic -interface_rustc_error_fatal = - fatal error triggered by #[rustc_error] - -interface_rustc_error_unexpected_annotation = - unexpected annotation used with `#[rustc_error(...)]`! - interface_temps_dir_error = failed to find or create the directory specified by `--temps-dir` diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs index ef0235b5577f..6b39b4f18911 100644 --- a/compiler/rustc_interface/src/errors.rs +++ b/compiler/rustc_interface/src/errors.rs @@ -73,20 +73,6 @@ pub struct TempsDirError; #[diag(interface_out_dir_error)] pub struct OutDirError; -#[derive(Diagnostic)] -#[diag(interface_rustc_error_fatal)] -pub struct RustcErrorFatal { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(interface_rustc_error_unexpected_annotation)] -pub struct RustcErrorUnexpectedAnnotation { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(interface_failed_writing_file)] pub struct FailedWritingFile<'a> { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 2440f0639c8a..93013c8b3f61 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1067,48 +1067,18 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) { }); } -/// Check for the `#[rustc_error]` annotation, which forces an error in codegen. This is used -/// to write UI tests that actually test that compilation succeeds without reporting -/// an error. -fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) { - let Some((def_id, _)) = tcx.entry_fn(()) else { return }; - for attr in tcx.get_attrs(def_id, sym::rustc_error) { - match attr.meta_item_list() { - // Check if there is a `#[rustc_error(delayed_bug_from_inside_query)]`. - Some(list) - if list.iter().any(|list_item| { - matches!( - list_item.ident().map(|i| i.name), - Some(sym::delayed_bug_from_inside_query) - ) - }) => - { - tcx.ensure_ok().trigger_delayed_bug(def_id); - } - - // Bare `#[rustc_error]`. - None => { - tcx.dcx().emit_fatal(errors::RustcErrorFatal { span: tcx.def_span(def_id) }); - } - - // Some other attribute. - Some(_) => { - tcx.dcx().emit_warn(errors::RustcErrorUnexpectedAnnotation { - span: tcx.def_span(def_id), - }); - } - } - } -} - /// Runs the codegen backend, after which the AST and analysis can /// be discarded. pub(crate) fn start_codegen<'tcx>( codegen_backend: &dyn CodegenBackend, tcx: TyCtxt<'tcx>, ) -> Box { - // Hook for UI tests. - check_for_rustc_errors_attr(tcx); + // Hook for tests. + if let Some((def_id, _)) = tcx.entry_fn(()) + && tcx.has_attr(def_id, sym::rustc_delayed_bug_from_inside_query) + { + tcx.ensure_ok().trigger_delayed_bug(def_id); + } // Don't run this test assertions when not doing codegen. Compiletest tries to build // build-fail tests in check mode first and expects it to not give an error in that case. diff --git a/compiler/rustc_middle/src/util/bug.rs b/compiler/rustc_middle/src/util/bug.rs index 7dda68b8393a..c4357fae1046 100644 --- a/compiler/rustc_middle/src/util/bug.rs +++ b/compiler/rustc_middle/src/util/bug.rs @@ -49,7 +49,7 @@ fn opt_span_bug_fmt>( pub fn trigger_delayed_bug(tcx: TyCtxt<'_>, key: rustc_hir::def_id::DefId) { tcx.dcx().span_delayed_bug( tcx.def_span(key), - "delayed bug triggered by #[rustc_error(delayed_bug_from_inside_query)]", + "delayed bug triggered by #[rustc_delayed_bug_from_inside_query]", ); } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6807f96e712c..409497c169e2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1771,6 +1771,7 @@ symbols! { rustc_deallocator, rustc_def_path, rustc_default_body_unstable, + rustc_delayed_bug_from_inside_query, rustc_deny_explicit_impl, rustc_deprecated_safe_2024, rustc_diagnostic_item, @@ -1787,7 +1788,6 @@ symbols! { rustc_dump_user_args, rustc_dump_vtable, rustc_effective_visibility, - rustc_error, rustc_evaluate_where_clauses, rustc_expected_cgu_reuse, rustc_force_inline, diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs index 9a7a1a01a09c..4c4174e2680f 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs @@ -665,10 +665,6 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ..."), WarnFollowing), rustc_attr!(TEST, rustc_abi, Normal, template!(List: "field1, field2, ..."), WarnFollowing), rustc_attr!(TEST, rustc_regions, Normal, template!(Word), WarnFollowing), - rustc_attr!( - TEST, rustc_error, Normal, - template!(Word, List: "delayed_bug_from_inside_query"), WarnFollowingWordOnly - ), rustc_attr!(TEST, rustc_dump_user_args, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_evaluate_where_clauses, Normal, template!(Word), WarnFollowing), rustc_attr!( diff --git a/tests/incremental/delayed_span_bug.rs b/tests/incremental/delayed_span_bug.rs index 958e9dd07e2d..1534aca5dddf 100644 --- a/tests/incremental/delayed_span_bug.rs +++ b/tests/incremental/delayed_span_bug.rs @@ -1,8 +1,8 @@ //@ revisions: cfail1 cfail2 //@ should-ice -//@ error-pattern: delayed bug triggered by #[rustc_error(delayed_bug_from_inside_query)] +//@ error-pattern: delayed bug triggered by #[rustc_delayed_bug_from_inside_query] #![feature(rustc_attrs)] -#[rustc_error(delayed_bug_from_inside_query)] +#[rustc_delayed_bug_from_inside_query] fn main() {} diff --git a/tests/ui/associated-types/bound-lifetime-constrained.ok.stderr b/tests/ui/associated-types/bound-lifetime-constrained.ok.stderr deleted file mode 100644 index 9082044fe068..000000000000 --- a/tests/ui/associated-types/bound-lifetime-constrained.ok.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/bound-lifetime-constrained.rs:48:1 - | -LL | fn main() { } - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/associated-types/bound-lifetime-constrained.rs b/tests/ui/associated-types/bound-lifetime-constrained.rs index 1dc3b2f5c2b7..3a5a77f57f23 100644 --- a/tests/ui/associated-types/bound-lifetime-constrained.rs +++ b/tests/ui/associated-types/bound-lifetime-constrained.rs @@ -1,7 +1,7 @@ //@ revisions: func object clause ok +//@[ok] check-pass #![allow(dead_code)] -#![feature(rustc_attrs)] trait Foo<'a> { type Item; @@ -44,5 +44,4 @@ fn clause2() where T: for<'a> Fn() -> <() as Foo<'a>>::Item { //[clause]~^ ERROR `Output` references lifetime `'a` } -#[rustc_error] -fn main() { } //[ok]~ ERROR fatal error triggered by #[rustc_error] +fn main() { } diff --git a/tests/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr b/tests/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr deleted file mode 100644 index 435e224bd892..000000000000 --- a/tests/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/bound-lifetime-in-binding-only.rs:71:1 - | -LL | fn main() { } - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/associated-types/bound-lifetime-in-binding-only.rs b/tests/ui/associated-types/bound-lifetime-in-binding-only.rs index e973e58b629f..2401fe0ef1f7 100644 --- a/tests/ui/associated-types/bound-lifetime-in-binding-only.rs +++ b/tests/ui/associated-types/bound-lifetime-in-binding-only.rs @@ -1,7 +1,7 @@ //@ revisions: angle paren ok elision +//@[ok] check-pass #![allow(dead_code)] -#![feature(rustc_attrs)] #![feature(unboxed_closures)] trait Foo { @@ -67,5 +67,4 @@ fn ok2 Fn<(&'b Parameterized<'a>,), Output=&'a i32>>() { fn ok3() where for<'a> Parameterized<'a>: Foo { } -#[rustc_error] -fn main() { } //[ok]~ ERROR fatal error triggered by #[rustc_error] +fn main() { } diff --git a/tests/ui/associated-types/bound-lifetime-in-return-only.ok.stderr b/tests/ui/associated-types/bound-lifetime-in-return-only.ok.stderr deleted file mode 100644 index 1815a7be7ee8..000000000000 --- a/tests/ui/associated-types/bound-lifetime-in-return-only.ok.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/bound-lifetime-in-return-only.rs:49:1 - | -LL | fn main() { } - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/associated-types/bound-lifetime-in-return-only.rs b/tests/ui/associated-types/bound-lifetime-in-return-only.rs index bf3aa6149cce..8a28f5b77861 100644 --- a/tests/ui/associated-types/bound-lifetime-in-return-only.rs +++ b/tests/ui/associated-types/bound-lifetime-in-return-only.rs @@ -1,7 +1,7 @@ //@ revisions: sig local structure ok elision +//@[ok] check-pass #![allow(dead_code)] -#![feature(rustc_attrs)] #![feature(unboxed_closures)] trait Foo { @@ -45,5 +45,4 @@ fn ok1(_: &dyn for<'a> Fn(&Parameterized<'a>) -> &'a i32) { fn ok2(_: &dyn for<'a,'b> Fn<(&'b Parameterized<'a>,), Output=&'a i32>) { } -#[rustc_error] -fn main() { } //[ok]~ ERROR fatal error triggered by #[rustc_error] +fn main() { } diff --git a/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.rs b/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.rs index 6f323d912275..9d323bf0324e 100644 --- a/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.rs +++ b/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.rs @@ -1,6 +1,5 @@ -#![feature(rustc_attrs)] #![allow(dead_code)] -fn main() { #![rustc_error] // rust-lang/rust#49855 +fn main() { // Original borrow ends at end of function let mut x = 1; let y = &mut x; diff --git a/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr b/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr index db73d4c04acc..444a74cbfcf5 100644 --- a/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr +++ b/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr @@ -1,5 +1,5 @@ error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-report-with-custom-diagnostic.rs:8:13 + --> $DIR/borrowck-report-with-custom-diagnostic.rs:7:13 | LL | let y = &mut x; | ------ mutable borrow occurs here @@ -11,7 +11,7 @@ LL | y.use_mut(); | - mutable borrow later used here error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-report-with-custom-diagnostic.rs:21:21 + --> $DIR/borrowck-report-with-custom-diagnostic.rs:20:21 | LL | let y = &x; | -- immutable borrow occurs here @@ -23,7 +23,7 @@ LL | y.use_ref(); | - immutable borrow later used here error[E0499]: cannot borrow `x` as mutable more than once at a time - --> $DIR/borrowck-report-with-custom-diagnostic.rs:36:17 + --> $DIR/borrowck-report-with-custom-diagnostic.rs:35:17 | LL | let y = &mut x; | ------ first mutable borrow occurs here diff --git a/tests/ui/borrowck/mut-borrow-outside-loop.rs b/tests/ui/borrowck/mut-borrow-outside-loop.rs index c02bfbf87390..3cc362def38f 100644 --- a/tests/ui/borrowck/mut-borrow-outside-loop.rs +++ b/tests/ui/borrowck/mut-borrow-outside-loop.rs @@ -1,6 +1,6 @@ // ensure borrowck messages are correct outside special case -#![feature(rustc_attrs)] -fn main() { #![rustc_error] // rust-lang/rust#49855 + +fn main() { let mut void = (); let first = &mut void; diff --git a/tests/ui/codemap_tests/issue-11715.rs b/tests/ui/codemap_tests/issue-11715.rs index 617d57ff75a4..d0daaf444b34 100644 --- a/tests/ui/codemap_tests/issue-11715.rs +++ b/tests/ui/codemap_tests/issue-11715.rs @@ -1,5 +1,4 @@ -#![feature(rustc_attrs)] -fn main() { #![rustc_error] // rust-lang/rust#49855 +fn main() { let mut x = "foo"; let y = &mut x; let z = &mut x; //~ ERROR cannot borrow diff --git a/tests/ui/codemap_tests/issue-11715.stderr b/tests/ui/codemap_tests/issue-11715.stderr index 5d0cf718761c..6b330560adb9 100644 --- a/tests/ui/codemap_tests/issue-11715.stderr +++ b/tests/ui/codemap_tests/issue-11715.stderr @@ -1,5 +1,5 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time - --> $DIR/issue-11715.rs:5:13 + --> $DIR/issue-11715.rs:4:13 | LL | let y = &mut x; | ------ first mutable borrow occurs here diff --git a/tests/ui/consts/async-block.rs b/tests/ui/consts/async-block.rs index 40be4d195d4b..1211a150f7d5 100644 --- a/tests/ui/consts/async-block.rs +++ b/tests/ui/consts/async-block.rs @@ -2,8 +2,8 @@ //@ edition:2018 //@ revisions: with_feature without_feature +//@[with_feature] check-pass -#![feature(rustc_attrs)] #![cfg_attr(with_feature, feature(const_async_blocks))] use std::future::Future; @@ -15,5 +15,4 @@ const _: i32 = { core::mem::ManuallyDrop::new(async { 0 }); 4 }; static _FUT: &(dyn Future + Sync) = &async {}; //[without_feature]~^ `async` block -#[rustc_error] -fn main() {} //[with_feature]~ fatal error triggered by #[rustc_error] +fn main() {} diff --git a/tests/ui/consts/async-block.with_feature.stderr b/tests/ui/consts/async-block.with_feature.stderr deleted file mode 100644 index 8228fa29edf1..000000000000 --- a/tests/ui/consts/async-block.with_feature.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/async-block.rs:19:1 - | -LL | fn main() {} - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs b/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs index 8980ef9c4220..f928e1122894 100644 --- a/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs +++ b/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs @@ -13,14 +13,16 @@ //! - Original impl PR: . //! - RFC 507 "Release channels": //! . -#![feature(rustc_attrs)] //@ revisions: without_flag with_flag +//@ check-pass +//@ compile-flags: -Zunleash-the-miri-inside-of-you //@[with_flag] compile-flags: -Awarnings -//@ check-pass +fn non_constant() {} +const fn constant() { non_constant() } -#[rustc_error(warn)] fn main() {} -//[without_flag]~^ WARN unexpected annotation used with `#[rustc_error(...)]`! + +//[without_flag]~? WARN skipping const checks diff --git a/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr b/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr index 3f33ccbd1c9f..08ae11fc18a9 100644 --- a/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr +++ b/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr @@ -1,8 +1,10 @@ -warning: unexpected annotation used with `#[rustc_error(...)]`! - --> $DIR/allow-non-lint-warnings.rs:25:1 +warning: skipping const checks | -LL | fn main() {} - | ^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/allow-non-lint-warnings.rs:24:23 + | +LL | const fn constant() { non_constant() } + | ^^^^^^^^^^^^^^ warning: 1 warning emitted diff --git a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs index 7ae4a8d911ba..025b4b52f12f 100644 --- a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs +++ b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs @@ -1,7 +1,6 @@ // Test that `#[rustc_*]` attributes are gated by `rustc_attrs` feature gate. #[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable -#[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable #[rustc_nonnull_optimization_guaranteed] //~ ERROR the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to document guaranteed niche optimizations in libcore and libstd and will never be stable fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr index 8c3a8eb2df87..0f760e0602d2 100644 --- a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr +++ b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr @@ -7,18 +7,9 @@ LL | #[rustc_variance] = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable - --> $DIR/feature-gate-rustc-attrs-1.rs:4:1 - | -LL | #[rustc_error] - | ^^^^^^^^^^^^^^ - | - = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0658]: the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to document guaranteed niche optimizations in libcore and libstd and will never be stable (note that the compiler does not even check whether the type indeed is being non-null-optimized; it is your responsibility to ensure that the attribute is only used on types that are optimized) - --> $DIR/feature-gate-rustc-attrs-1.rs:5:1 + --> $DIR/feature-gate-rustc-attrs-1.rs:4:1 | LL | #[rustc_nonnull_optimization_guaranteed] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -26,6 +17,6 @@ LL | #[rustc_nonnull_optimization_guaranteed] = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/mir/issue-75053.rs b/tests/ui/mir/issue-75053.rs index 9b247fa54349..4bc481b82e53 100644 --- a/tests/ui/mir/issue-75053.rs +++ b/tests/ui/mir/issue-75053.rs @@ -1,6 +1,7 @@ +//@ check-pass //@ compile-flags: -Z mir-opt-level=3 -#![feature(type_alias_impl_trait, rustc_attrs)] +#![feature(type_alias_impl_trait)] use std::marker::PhantomData; @@ -43,8 +44,6 @@ impl>>, U> MyIndex> for Scope { } } -#[rustc_error] fn main() { - //~^ ERROR let _pos: Phantom1> = Scope::new().my_index(); } diff --git a/tests/ui/mir/issue-75053.stderr b/tests/ui/mir/issue-75053.stderr deleted file mode 100644 index 91032bc3797e..000000000000 --- a/tests/ui/mir/issue-75053.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/issue-75053.rs:47:1 - | -LL | fn main() { - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/proc-macro/no-macro-use-attr.rs b/tests/ui/proc-macro/no-macro-use-attr.rs index d44f51bfd8d4..252003781311 100644 --- a/tests/ui/proc-macro/no-macro-use-attr.rs +++ b/tests/ui/proc-macro/no-macro-use-attr.rs @@ -1,10 +1,9 @@ +//@ check-pass //@ proc-macro: test-macros.rs -#![feature(rustc_attrs)] #![warn(unused_extern_crates)] extern crate test_macros; //~^ WARN unused extern crate -#[rustc_error] -fn main() {} //~ ERROR fatal error triggered by #[rustc_error] +fn main() {} diff --git a/tests/ui/proc-macro/no-macro-use-attr.stderr b/tests/ui/proc-macro/no-macro-use-attr.stderr index 3dda3cc7d5a5..4913672450ab 100644 --- a/tests/ui/proc-macro/no-macro-use-attr.stderr +++ b/tests/ui/proc-macro/no-macro-use-attr.stderr @@ -10,11 +10,5 @@ note: the lint level is defined here LL | #![warn(unused_extern_crates)] | ^^^^^^^^^^^^^^^^^^^^ -error: fatal error triggered by #[rustc_error] - --> $DIR/no-macro-use-attr.rs:10:1 - | -LL | fn main() {} - | ^^^^^^^^^ - -error: aborting due to 1 previous error; 1 warning emitted +warning: 1 warning emitted diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr index 085843496266..c5756269def6 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr @@ -1,5 +1,5 @@ error[E0658]: use of unstable library feature `structural_match` - --> $DIR/feature-gate.rs:29:6 + --> $DIR/feature-gate.rs:27:6 | LL | impl std::marker::StructuralPartialEq for Foo { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs index 711b07fee3b6..694081654d58 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs @@ -3,11 +3,10 @@ // used in a match. //@ revisions: with_gate no_gate - +//@[with_gate] check-pass // gate-test-structural_match #![allow(unused)] -#![feature(rustc_attrs)] #![cfg_attr(with_gate, feature(structural_match))] @@ -17,8 +16,7 @@ struct Foo { const FOO: Foo = Foo { x: 0 }; -#[rustc_error] -fn main() { //[with_gate]~ ERROR fatal error triggered by #[rustc_error] +fn main() { let y = Foo { x: 1 }; match y { FOO => { } diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr deleted file mode 100644 index 505b7d79cadb..000000000000 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/feature-gate.rs:21:1 - | -LL | fn main() { - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/rustc-error.rs b/tests/ui/rustc-error.rs deleted file mode 100644 index 69d57948fb5e..000000000000 --- a/tests/ui/rustc-error.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![feature(rustc_attrs)] - -#[rustc_error] -fn main() { - //~^ ERROR fatal error triggered by #[rustc_error] -} diff --git a/tests/ui/rustc-error.stderr b/tests/ui/rustc-error.stderr deleted file mode 100644 index 67451195b64f..000000000000 --- a/tests/ui/rustc-error.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/rustc-error.rs:4:1 - | -LL | fn main() { - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/span/range-2.rs b/tests/ui/span/range-2.rs index c4bb16f44bd1..2e8252169b7e 100644 --- a/tests/ui/span/range-2.rs +++ b/tests/ui/span/range-2.rs @@ -1,6 +1,6 @@ // Test range syntax - borrow errors. -#![feature(rustc_attrs)] -pub fn main() { #![rustc_error] // rust-lang/rust#49855 + +pub fn main() { let r = { let a = 42; let b = 42; diff --git a/tests/ui/span/regionck-unboxed-closure-lifetimes.rs b/tests/ui/span/regionck-unboxed-closure-lifetimes.rs index 60ccaa872e73..fe6c353e8f8e 100644 --- a/tests/ui/span/regionck-unboxed-closure-lifetimes.rs +++ b/tests/ui/span/regionck-unboxed-closure-lifetimes.rs @@ -1,7 +1,6 @@ -#![feature(rustc_attrs)] use std::ops::FnMut; -fn main() { #![rustc_error] // rust-lang/rust#49855 +fn main() { let mut f; { let c = 1; diff --git a/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr b/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr index 225f83b6e666..bb6298211bc1 100644 --- a/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr +++ b/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr @@ -1,5 +1,5 @@ error[E0597]: `c` does not live long enough - --> $DIR/regionck-unboxed-closure-lifetimes.rs:8:21 + --> $DIR/regionck-unboxed-closure-lifetimes.rs:7:21 | LL | let c = 1; | - binding `c` declared here diff --git a/tests/ui/suggestions/attribute-typos.rs b/tests/ui/suggestions/attribute-typos.rs index 7c8231bbb24f..4c2336e105e2 100644 --- a/tests/ui/suggestions/attribute-typos.rs +++ b/tests/ui/suggestions/attribute-typos.rs @@ -4,8 +4,8 @@ fn foo() {} #[tests] //~ ERROR cannot find attribute `tests` in this scope fn bar() {} -#[rustc_err] -//~^ ERROR cannot find attribute `rustc_err` in this scope +#[rustc_dumm] +//~^ ERROR cannot find attribute `rustc_dumm` in this scope //~| ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler fn main() {} diff --git a/tests/ui/suggestions/attribute-typos.stderr b/tests/ui/suggestions/attribute-typos.stderr index b871c9b45a56..a1a01c0abd63 100644 --- a/tests/ui/suggestions/attribute-typos.stderr +++ b/tests/ui/suggestions/attribute-typos.stderr @@ -1,14 +1,14 @@ error: attributes starting with `rustc` are reserved for use by the `rustc` compiler --> $DIR/attribute-typos.rs:7:3 | -LL | #[rustc_err] - | ^^^^^^^^^ +LL | #[rustc_dumm] + | ^^^^^^^^^^ -error: cannot find attribute `rustc_err` in this scope +error: cannot find attribute `rustc_dumm` in this scope --> $DIR/attribute-typos.rs:7:3 | -LL | #[rustc_err] - | ^^^^^^^^^ help: a built-in attribute with a similar name exists: `rustc_error` +LL | #[rustc_dumm] + | ^^^^^^^^^^ help: a built-in attribute with a similar name exists: `rustc_dummy` error: cannot find attribute `tests` in this scope --> $DIR/attribute-typos.rs:4:3 diff --git a/tests/ui/traits/const-traits/feature-gate.gated.stderr b/tests/ui/traits/const-traits/feature-gate.gated.stderr deleted file mode 100644 index 12f9355e41d4..000000000000 --- a/tests/ui/traits/const-traits/feature-gate.gated.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/feature-gate.rs:22:1 - | -LL | fn main() {} - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/traits/const-traits/feature-gate.rs b/tests/ui/traits/const-traits/feature-gate.rs index c36ec3538c36..921dfb054e30 100644 --- a/tests/ui/traits/const-traits/feature-gate.rs +++ b/tests/ui/traits/const-traits/feature-gate.rs @@ -1,8 +1,8 @@ //@ revisions: stock gated +//@[gated] check-pass // gate-test-const_trait_impl #![cfg_attr(gated, feature(const_trait_impl))] -#![feature(rustc_attrs)] struct S; #[const_trait] //[stock]~ ERROR `const_trait` is a temporary placeholder @@ -18,5 +18,4 @@ macro_rules! discard { ($ty:ty) => {} } discard! { impl ~const T } //[stock]~ ERROR const trait impls are experimental discard! { impl const T } //[stock]~ ERROR const trait impls are experimental -#[rustc_error] -fn main() {} //[gated]~ ERROR fatal error triggered by #[rustc_error] +fn main() {} diff --git a/tests/ui/treat-err-as-bug/span_delayed_bug.rs b/tests/ui/treat-err-as-bug/span_delayed_bug.rs index 296bdd7a12d9..88a9d07c94cf 100644 --- a/tests/ui/treat-err-as-bug/span_delayed_bug.rs +++ b/tests/ui/treat-err-as-bug/span_delayed_bug.rs @@ -8,5 +8,5 @@ #![feature(rustc_attrs)] -#[rustc_error(delayed_bug_from_inside_query)] +#[rustc_delayed_bug_from_inside_query] fn main() {} diff --git a/tests/ui/treat-err-as-bug/span_delayed_bug.stderr b/tests/ui/treat-err-as-bug/span_delayed_bug.stderr index aec1b89c7666..1c8d279c14c4 100644 --- a/tests/ui/treat-err-as-bug/span_delayed_bug.stderr +++ b/tests/ui/treat-err-as-bug/span_delayed_bug.stderr @@ -1,4 +1,4 @@ -error: internal compiler error: delayed bug triggered by #[rustc_error(delayed_bug_from_inside_query)] +error: internal compiler error: delayed bug triggered by #[rustc_delayed_bug_from_inside_query] --> $DIR/span_delayed_bug.rs:12:1 | LL | fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-53096.rs b/tests/ui/type-alias-impl-trait/issue-53096.rs index c24f1bf44fab..60e455a6a07d 100644 --- a/tests/ui/type-alias-impl-trait/issue-53096.rs +++ b/tests/ui/type-alias-impl-trait/issue-53096.rs @@ -1,4 +1,5 @@ -#![feature(rustc_attrs)] +//@ check-pass + #![feature(type_alias_impl_trait)] pub type Foo = impl Fn() -> usize; @@ -8,5 +9,4 @@ pub const fn bar() -> Foo { } const BAZR: Foo = bar(); -#[rustc_error] -fn main() {} //~ ERROR +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-53096.stderr b/tests/ui/type-alias-impl-trait/issue-53096.stderr deleted file mode 100644 index 53490896af79..000000000000 --- a/tests/ui/type-alias-impl-trait/issue-53096.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/issue-53096.rs:12:1 - | -LL | fn main() {} - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/type-alias-impl-trait/issue-60407.rs b/tests/ui/type-alias-impl-trait/issue-60407.rs index 5b8ff6b74de5..53280c28ecb1 100644 --- a/tests/ui/type-alias-impl-trait/issue-60407.rs +++ b/tests/ui/type-alias-impl-trait/issue-60407.rs @@ -1,4 +1,6 @@ -#![feature(type_alias_impl_trait, rustc_attrs)] +//@ check-pass + +#![feature(type_alias_impl_trait)] pub type Debuggable = impl core::fmt::Debug; @@ -9,8 +11,6 @@ pub fn foo() -> Debuggable { static mut TEST: Option = None; -#[rustc_error] fn main() { - //~^ ERROR unsafe { TEST = Some(foo()) } } diff --git a/tests/ui/type-alias-impl-trait/issue-60407.stderr b/tests/ui/type-alias-impl-trait/issue-60407.stderr deleted file mode 100644 index f517d5b65fa2..000000000000 --- a/tests/ui/type-alias-impl-trait/issue-60407.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/issue-60407.rs:13:1 - | -LL | fn main() { - | ^^^^^^^^^ - -error: aborting due to 1 previous error - From 41fdd280ff1089d1618487d59ed49f83160d2513 Mon Sep 17 00:00:00 2001 From: jyn Date: Sat, 22 Mar 2025 16:09:37 -0400 Subject: [PATCH 662/745] rustc_resolve: Test the order that preludes are resolved --- tests/ui/resolve/auxiliary/macro_helpers.rs | 16 ++++ tests/ui/resolve/prelude-order.rs | 89 +++++++++++++++++++++ tests/ui/resolve/prelude-order.stderr | 47 +++++++++++ 3 files changed, 152 insertions(+) create mode 100644 tests/ui/resolve/auxiliary/macro_helpers.rs create mode 100644 tests/ui/resolve/prelude-order.rs create mode 100644 tests/ui/resolve/prelude-order.stderr diff --git a/tests/ui/resolve/auxiliary/macro_helpers.rs b/tests/ui/resolve/auxiliary/macro_helpers.rs new file mode 100644 index 000000000000..43aa336457de --- /dev/null +++ b/tests/ui/resolve/auxiliary/macro_helpers.rs @@ -0,0 +1,16 @@ +/* macro namespace. */ + +extern crate proc_macro; +use proc_macro::*; +use std::str::FromStr; + +const ERROR: &str = "fn helper() { \"helper\" }"; +// https://doc.rust-lang.org/nightly/std/prelude/v1/index.html#attributes +// NOTE: all the bang macros in std are currently unstable. +#[proc_macro_attribute] pub fn test // lang. + (_: TokenStream, _: TokenStream) -> TokenStream { + TokenStream::from_str("fn test_macro() { \"\" }").unwrap() } +// https://doc.rust-lang.org/nightly/reference/attributes.html#built-in-attributes-index +#[proc_macro_attribute] pub fn global_allocator // lang. + (_: TokenStream, _: TokenStream) -> TokenStream { + TokenStream::from_str("fn global_allocator_macro() { \"\" }").unwrap() } diff --git a/tests/ui/resolve/prelude-order.rs b/tests/ui/resolve/prelude-order.rs new file mode 100644 index 000000000000..a3f194270d48 --- /dev/null +++ b/tests/ui/resolve/prelude-order.rs @@ -0,0 +1,89 @@ +//@ proc-macro:macro_helpers.rs +//@ compile-flags: --crate-type=lib + +/* There are 5 preludes and 3 namespaces. Test the order in which they are resolved. + * See https://doc.rust-lang.org/nightly/reference/names/preludes.html. + * + * Macros cannot be in the type or value namespace. + * Tools and extern crates cannot be in the macro or value namespace. + * + * Test the following truth tables: + +Type: +| ...... | tool | extern | macro | lang | libs | +| tool | N/A | mirror +| extern | extern | N/A | universe +| macro | N/A | N/A | N/A | +| lang | tool | extern | N/A | N/A | +| libs | tool | extern | N/A | X | N/A | + +Macro: +| ...... | tool | extern | macro | lang | libs | +| tool | N/A | mirror +| extern | N/A | N/A | universe +| macro | N/A | N/A | N/A | +| lang | N/A | N/A | macro | N/A | +| libs | N/A | N/A | macro | X | N/A | + +Value: N/A. Only libs has items in the value namespace. + +† ambiguous +X don't care (controlled namespace with no overlap) + +* Types are tested with `#[name::inner]`. Macros are tested with `#[name]`. +* WARNING: I have found in testing that attribute macros give ambiguity errors in some contexts +* instead of choosing a prelude. Have not been able to replicate. +* +* There should be 7 total tests. +* See `rustc_resolve::ident::visit_scopes` for more information, +* and for a definition of "controlled namespace". +*/ + +#![feature(register_tool)] + +/* tool prelude */ +#![register_tool(type_ns)] // extern prelude. type. +#![register_tool(i8)] // lang prelude. type. +#![register_tool(Sync)] // libs prelude. type. + +/* extern prelude */ +extern crate macro_helpers as type_ns; // tool prelude. type. +extern crate macro_helpers as usize; // lang prelude. type. +extern crate macro_helpers as Option; // libs prelude. type. + +/* macro_use prelude */ +#[macro_use] +extern crate macro_helpers as _; + +/* lang and libs implicitly in scope */ + +// tool/extern -> extern +#[type_ns::inner] //~ ERROR could not find `inner` in `type_ns` +fn t1() {} + +// tool/lang -> tool +#[i8::inner] // ok +fn t2() {} + +// tool/libs -> tool +#[Sync::not_real] // ok +fn t3() {} + +// extern/lang -> extern +#[usize::inner] //~ ERROR could not find `inner` in `usize` +fn e1() {} // NOTE: testing with `-> usize` isn't valid, crates aren't considered in that scope + // (unless they have generic arguments, for some reason.) + +// extern/libs -> extern +// https://github.com/rust-lang/rust/issues/139095 +fn e2() -> Option { None } //~ ERROR: expected type, found crate + +// macro/libs -> macro +#[test] //~ ERROR mismatched types +fn m1() {} + +// macro/lang -> macro +#[global_allocator] //~ ERROR mismatched types +fn m2() {} + +// lang/libs: no items that currently overlap, in either macro or type ns. diff --git a/tests/ui/resolve/prelude-order.stderr b/tests/ui/resolve/prelude-order.stderr new file mode 100644 index 000000000000..1b9cc94285aa --- /dev/null +++ b/tests/ui/resolve/prelude-order.stderr @@ -0,0 +1,47 @@ +error[E0433]: failed to resolve: could not find `inner` in `type_ns` + --> $DIR/prelude-order.rs:61:12 + | +LL | #[type_ns::inner] + | ^^^^^ could not find `inner` in `type_ns` + +error[E0433]: failed to resolve: could not find `inner` in `usize` + --> $DIR/prelude-order.rs:73:10 + | +LL | #[usize::inner] + | ^^^^^ could not find `inner` in `usize` + +error[E0573]: expected type, found crate `Option` + --> $DIR/prelude-order.rs:79:12 + | +LL | fn e2() -> Option { None } + | ^^^^^^^^^^^ not a type + | +help: consider importing this enum instead + | +LL + use std::option::Option; + | + +error[E0308]: mismatched types + --> $DIR/prelude-order.rs:82:1 + | +LL | #[test] + | ^^^^^^^- help: try adding a return type: `-> &'static str` + | | + | expected `()`, found `&str` + | + = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/prelude-order.rs:86:1 + | +LL | #[global_allocator] + | ^^^^^^^^^^^^^^^^^^^- help: try adding a return type: `-> &'static str` + | | + | expected `()`, found `&str` + | + = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0308, E0433, E0573. +For more information about an error, try `rustc --explain E0308`. From 4f2baaa9c6b75d4267eea9e1096339d56d380615 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 25 Mar 2025 18:57:04 +0000 Subject: [PATCH 663/745] Do not mix normalized and unnormalized caller bounds when constructing param-env for receiver_is_dispatchable --- .../src/traits/dyn_compatibility.rs | 35 ++++++++++++------- tests/ui/associated-types/issue-59324.stderr | 30 ++++++++-------- ...-do-not-mix-normalized-and-unnormalized.rs | 26 ++++++++++++++ 3 files changed, 63 insertions(+), 28 deletions(-) create mode 100644 tests/ui/self/dyn-dispatch-do-not-mix-normalized-and-unnormalized.rs diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 78a452439836..fa6bbf1d6e57 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -583,27 +583,36 @@ fn receiver_is_dispatchable<'tcx>( // create a modified param env, with `Self: Unsize` and `U: Trait` (and all of // its supertraits) added to caller bounds. `U: ?Sized` is already implied here. let param_env = { - let param_env = tcx.param_env(method.def_id); + // N.B. We generally want to emulate the construction of the `unnormalized_param_env` + // in the param-env query here. The fact that we don't just start with the clauses + // in the param-env of the method is because those are already normalized, and mixing + // normalized and unnormalized copies of predicates in `normalize_param_env_or_error` + // will cause ambiguity that the user can't really avoid. + // + // We leave out certain complexities of the param-env query here. Specifically, we: + // 1. Do not add `~const` bounds since there are no `dyn const Trait`s. + // 2. Do not add RPITIT self projection bounds for defaulted methods, since we + // are not constructing a param-env for "inside" of the body of the defaulted + // method, so we don't really care about projecting to a specific RPIT type, + // and because RPITITs are not dyn compatible (yet). + let mut predicates = tcx.predicates_of(method.def_id).instantiate_identity(tcx).predicates; // Self: Unsize let unsize_predicate = - ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]).upcast(tcx); + ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]); + predicates.push(unsize_predicate.upcast(tcx)); // U: Trait - let trait_predicate = { - let trait_def_id = method.trait_container(tcx).unwrap(); - let args = GenericArgs::for_item(tcx, trait_def_id, |param, _| { - if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) } - }); - - ty::TraitRef::new_from_args(tcx, trait_def_id, args).upcast(tcx) - }; + let trait_def_id = method.trait_container(tcx).unwrap(); + let args = GenericArgs::for_item(tcx, trait_def_id, |param, _| { + if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) } + }); + let trait_predicate = ty::TraitRef::new_from_args(tcx, trait_def_id, args); + predicates.push(trait_predicate.upcast(tcx)); normalize_param_env_or_error( tcx, - ty::ParamEnv::new(tcx.mk_clauses_from_iter( - param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]), - )), + ty::ParamEnv::new(tcx.mk_clauses(&predicates)), ObligationCause::dummy_with_span(tcx.def_span(method.def_id)), ) }; diff --git a/tests/ui/associated-types/issue-59324.stderr b/tests/ui/associated-types/issue-59324.stderr index f5e696b7ac1c..f79afc89d10f 100644 --- a/tests/ui/associated-types/issue-59324.stderr +++ b/tests/ui/associated-types/issue-59324.stderr @@ -27,21 +27,6 @@ help: consider further restricting type parameter `Bug` with trait `Foo` LL | pub trait ThriftService: | +++++ -error[E0277]: the trait bound `Bug: Foo` is not satisfied - --> $DIR/issue-59324.rs:16:5 - | -LL | / fn get_service( -LL | | -LL | | -LL | | &self, -LL | | ) -> Self::AssocType; - | |_________________________^ the trait `Foo` is not implemented for `Bug` - | -help: consider further restricting type parameter `Bug` with trait `Foo` - | -LL | pub trait ThriftService: - | +++++ - error[E0277]: the trait bound `Bug: Foo` is not satisfied --> $DIR/issue-59324.rs:16:5 | @@ -64,6 +49,21 @@ help: this trait has no implementations, consider adding one LL | pub trait Foo: NotFoo { | ^^^^^^^^^^^^^^^^^^^^^ +error[E0277]: the trait bound `Bug: Foo` is not satisfied + --> $DIR/issue-59324.rs:16:5 + | +LL | / fn get_service( +LL | | +LL | | +LL | | &self, +LL | | ) -> Self::AssocType; + | |_________________________^ the trait `Foo` is not implemented for `Bug` + | +help: consider further restricting type parameter `Bug` with trait `Foo` + | +LL | pub trait ThriftService: + | +++++ + error[E0277]: the trait bound `Bug: Foo` is not satisfied --> $DIR/issue-59324.rs:20:10 | diff --git a/tests/ui/self/dyn-dispatch-do-not-mix-normalized-and-unnormalized.rs b/tests/ui/self/dyn-dispatch-do-not-mix-normalized-and-unnormalized.rs new file mode 100644 index 000000000000..2bc70de2a340 --- /dev/null +++ b/tests/ui/self/dyn-dispatch-do-not-mix-normalized-and-unnormalized.rs @@ -0,0 +1,26 @@ +//@ check-pass + +// Regression test for . + +// Previously, we'd take the normalized param env's clauses which included +// `::Value = i32`, which comes from the supertraits of `TraitD` +// after normalizing `::Value = ::Scalar`. Since +// `normalize_param_env_or_error` ends up re-elaborating `PF: TraitD`, we'd +// end up with both versions of this predicate (normalized and unnormalized). +// Since these projections preds are not equal, we'd fail with ambiguity. + +trait TraitB {} + +trait TraitC: TraitB { + type Value; +} + +trait TraitD: TraitC { + type Scalar; +} + +trait TraitE { + fn apply>(&self); +} + +fn main() {} From cc5ee70b1a51bf30e85d261cc6e485eb3431bcac Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sun, 30 Mar 2025 10:35:59 +0200 Subject: [PATCH 664/745] Simplify expansion for format_args!(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of calling new(), we can just use a struct expression directly. Before: Placeholder::new(…, …, …, …) After: Placeholder { position: …, flags: …, width: …, precision: …, } --- compiler/rustc_ast_lowering/src/format.rs | 28 +++++++++++------------ compiler/rustc_span/src/symbol.rs | 4 ++++ library/core/src/fmt/rt.rs | 8 +------ 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index 343895984ca4..0de0319c6676 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -323,14 +323,12 @@ fn make_count<'hir>( /// Generates /// /// ```text -/// ::…, // alignment -/// …u32, // flags -/// , // width -/// , // precision -/// ) +/// , +/// width: , +/// } /// ``` fn make_format_spec<'hir>( ctx: &mut LoweringContext<'_, 'hir>, @@ -384,13 +382,13 @@ fn make_format_spec<'hir>( let flags = ctx.expr_u32(sp, flags); let precision = make_count(ctx, sp, precision, argmap); let width = make_count(ctx, sp, width, argmap); - let format_placeholder_new = ctx.arena.alloc(ctx.expr_lang_item_type_relative( - sp, - hir::LangItem::FormatPlaceholder, - sym::new, - )); - let args = ctx.arena.alloc_from_iter([position, flags, precision, width]); - ctx.expr_call_mut(sp, format_placeholder_new, args) + let position = ctx.expr_field(Ident::new(sym::position, sp), ctx.arena.alloc(position), sp); + let flags = ctx.expr_field(Ident::new(sym::flags, sp), ctx.arena.alloc(flags), sp); + let precision = ctx.expr_field(Ident::new(sym::precision, sp), ctx.arena.alloc(precision), sp); + let width = ctx.expr_field(Ident::new(sym::width, sp), ctx.arena.alloc(width), sp); + let placeholder = ctx.arena.alloc(hir::QPath::LangItem(hir::LangItem::FormatPlaceholder, sp)); + let fields = ctx.arena.alloc_from_iter([position, flags, precision, width]); + ctx.expr(sp, hir::ExprKind::Struct(placeholder, fields, hir::StructTailExpr::None)) } fn expand_format_args<'hir>( diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6807f96e712c..cc4c9860bc27 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -986,6 +986,7 @@ symbols! { field_init_shorthand, file, file_options, + flags, float, float_to_int_unchecked, floorf128, @@ -1570,6 +1571,7 @@ symbols! { pointer_like, poll, poll_next, + position, post_dash_lto: "post-lto", postfix_match, powerpc_target_feature, @@ -1585,6 +1587,7 @@ symbols! { precise_capturing, precise_capturing_in_traits, precise_pointer_size_matching, + precision, pref_align_of, prefetch_read_data, prefetch_read_instruction, @@ -2274,6 +2277,7 @@ symbols! { wasm_target_feature, where_clause_attrs, while_let, + width, windows, windows_subsystem, with_negative_coherence, diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs index d27f7e6e0d8e..0b04ebccae2b 100644 --- a/library/core/src/fmt/rt.rs +++ b/library/core/src/fmt/rt.rs @@ -20,8 +20,8 @@ pub struct Placeholder { pub width: Count, } +#[cfg(bootstrap)] impl Placeholder { - #[cfg(bootstrap)] #[inline] pub const fn new( position: usize, @@ -33,12 +33,6 @@ impl Placeholder { ) -> Self { Self { position, fill, align, flags, precision, width } } - - #[cfg(not(bootstrap))] - #[inline] - pub const fn new(position: usize, flags: u32, precision: Count, width: Count) -> Self { - Self { position, flags, precision, width } - } } #[cfg(bootstrap)] From 31face9f6087c2914ea995af969bb995629a5e78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sun, 30 Mar 2025 11:14:33 +0200 Subject: [PATCH 665/745] Revert "Auto merge of #129827 - bvanjoi:less-decoding, r=petrochenkov" Reverting because of a performance regression. This reverts commit d4812c8638173ec163825d56a72a33589483ec4c, reversing changes made to 5cc60728e7ee10eb2ae5f61f7d412d9805b22f0c. --- compiler/rustc_metadata/src/rmeta/mod.rs | 4 +- .../rustc_middle/src/query/on_disk_cache.rs | 10 +- compiler/rustc_middle/src/ty/parameterized.rs | 2 +- compiler/rustc_span/src/hygiene.rs | 201 ++++++++++++------ .../nonterminal-token-hygiene.stdout | 20 +- 5 files changed, 157 insertions(+), 80 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 34e4f2f26022..dc453b1e747c 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -36,7 +36,7 @@ use rustc_serialize::opaque::FileEncoder; use rustc_session::config::{SymbolManglingVersion, TargetModifier}; use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib}; use rustc_span::edition::Edition; -use rustc_span::hygiene::{ExpnIndex, MacroKind, SyntaxContextKey}; +use rustc_span::hygiene::{ExpnIndex, MacroKind, SyntaxContextData}; use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Ident, Span, Symbol}; use rustc_target::spec::{PanicStrategy, TargetTuple}; use table::TableBuilder; @@ -193,7 +193,7 @@ enum LazyState { Previous(NonZero), } -type SyntaxContextTable = LazyTable>>; +type SyntaxContextTable = LazyTable>>; type ExpnDataTable = LazyTable>>; type ExpnHashTable = LazyTable>>; diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index ce6219c207fd..14e3ce8bef6b 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -16,7 +16,7 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixed use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_session::Session; use rustc_span::hygiene::{ - ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextKey, + ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextData, }; use rustc_span::source_map::Spanned; use rustc_span::{ @@ -75,9 +75,9 @@ pub struct OnDiskCache { alloc_decoding_state: AllocDecodingState, // A map from syntax context ids to the position of their associated - // `SyntaxContextKey`. We use a `u32` instead of a `SyntaxContext` + // `SyntaxContextData`. We use a `u32` instead of a `SyntaxContext` // to represent the fact that we are storing *encoded* ids. When we decode - // a `SyntaxContextKey`, a new id will be allocated from the global `HygieneData`, + // a `SyntaxContext`, a new id will be allocated from the global `HygieneData`, // which will almost certainly be different than the serialized id. syntax_contexts: FxHashMap, // A map from the `DefPathHash` of an `ExpnId` to the position @@ -305,7 +305,7 @@ impl OnDiskCache { let mut expn_data = UnhashMap::default(); let mut foreign_expn_data = UnhashMap::default(); - // Encode all hygiene data (`SyntaxContextKey` and `ExpnData`) from the current + // Encode all hygiene data (`SyntaxContextData` and `ExpnData`) from the current // session. hygiene_encode_context.encode( @@ -566,7 +566,7 @@ impl<'a, 'tcx> SpanDecoder for CacheDecoder<'a, 'tcx> { // We look up the position of the associated `SyntaxData` and decode it. let pos = syntax_contexts.get(&id).unwrap(); this.with_position(pos.to_usize(), |decoder| { - let data: SyntaxContextKey = decode_tagged(decoder, TAG_SYNTAX_CONTEXT); + let data: SyntaxContextData = decode_tagged(decoder, TAG_SYNTAX_CONTEXT); data }) }) diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 134f76d7248d..19e2b5745632 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -111,7 +111,7 @@ trivially_parameterized_over_tcx! { rustc_span::Span, rustc_span::Symbol, rustc_span::def_id::DefPathHash, - rustc_span::hygiene::SyntaxContextKey, + rustc_span::hygiene::SyntaxContextData, rustc_span::Ident, rustc_type_ir::Variance, rustc_hir::Attribute, diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index f94858856729..4390085cd049 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -24,6 +24,9 @@ // because getting it wrong can lead to nested `HygieneData::with` calls that // trigger runtime aborts. (Fortunately these are obvious and easy to fix.) +use std::cell::RefCell; +use std::collections::hash_map::Entry; +use std::collections::hash_set::Entry as SetEntry; use std::hash::Hash; use std::sync::Arc; use std::{fmt, iter, mem}; @@ -31,7 +34,7 @@ use std::{fmt, iter, mem}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher}; -use rustc_data_structures::sync::Lock; +use rustc_data_structures::sync::{Lock, WorkerLocal}; use rustc_data_structures::unhash::UnhashMap; use rustc_hashes::Hash64; use rustc_index::IndexVec; @@ -56,10 +59,10 @@ impl !PartialOrd for SyntaxContext {} /// If this part of two syntax contexts is equal, then the whole syntax contexts should be equal. /// The other fields are only for caching. -pub type SyntaxContextKey = (SyntaxContext, ExpnId, Transparency); +type SyntaxContextKey = (SyntaxContext, ExpnId, Transparency); #[derive(Clone, Copy, PartialEq, Debug, Encodable, Decodable)] -struct SyntaxContextData { +pub struct SyntaxContextData { outer_expn: ExpnId, outer_transparency: Transparency, parent: SyntaxContext, @@ -91,21 +94,6 @@ impl SyntaxContextData { self.dollar_crate_name == kw::Empty } - fn new( - (parent, outer_expn, outer_transparency): SyntaxContextKey, - opaque: SyntaxContext, - opaque_and_semitransparent: SyntaxContext, - ) -> Self { - SyntaxContextData { - parent, - outer_expn, - outer_transparency, - opaque, - opaque_and_semitransparent, - dollar_crate_name: kw::DollarCrate, - } - } - fn key(&self) -> SyntaxContextKey { (self.parent, self.outer_expn, self.outer_transparency) } @@ -586,49 +574,67 @@ impl HygieneData { fn apply_mark_internal( &mut self, - parent: SyntaxContext, + ctxt: SyntaxContext, expn_id: ExpnId, transparency: Transparency, ) -> SyntaxContext { - debug_assert!(!self.syntax_context_data[parent.0 as usize].is_decode_placeholder()); - // Look into the cache first. - let key = (parent, expn_id, transparency); - if let Some(ctxt) = self.syntax_context_map.get(&key) { - return *ctxt; + let syntax_context_data = &mut self.syntax_context_data; + debug_assert!(!syntax_context_data[ctxt.0 as usize].is_decode_placeholder()); + let mut opaque = syntax_context_data[ctxt.0 as usize].opaque; + let mut opaque_and_semitransparent = + syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent; + + if transparency >= Transparency::Opaque { + let parent = opaque; + opaque = *self + .syntax_context_map + .entry((parent, expn_id, transparency)) + .or_insert_with(|| { + let new_opaque = SyntaxContext::from_usize(syntax_context_data.len()); + syntax_context_data.push(SyntaxContextData { + outer_expn: expn_id, + outer_transparency: transparency, + parent, + opaque: new_opaque, + opaque_and_semitransparent: new_opaque, + dollar_crate_name: kw::DollarCrate, + }); + new_opaque + }); } - // Reserve a new syntax context. - let ctxt = SyntaxContext::from_usize(self.syntax_context_data.len()); - self.syntax_context_data.push(SyntaxContextData::decode_placeholder()); - self.syntax_context_map.insert(key, ctxt); - // Opaque and semi-transparent versions of the parent. Note that they may be equal to the - // parent itself. E.g. `parent_opaque` == `parent` if the expn chain contains only opaques, - // and `parent_opaque_and_semitransparent` == `parent` if the expn contains only opaques - // and semi-transparents. - let parent_opaque = self.syntax_context_data[parent.0 as usize].opaque; - let parent_opaque_and_semitransparent = - self.syntax_context_data[parent.0 as usize].opaque_and_semitransparent; + if transparency >= Transparency::SemiTransparent { + let parent = opaque_and_semitransparent; + opaque_and_semitransparent = *self + .syntax_context_map + .entry((parent, expn_id, transparency)) + .or_insert_with(|| { + let new_opaque_and_semitransparent = + SyntaxContext::from_usize(syntax_context_data.len()); + syntax_context_data.push(SyntaxContextData { + outer_expn: expn_id, + outer_transparency: transparency, + parent, + opaque, + opaque_and_semitransparent: new_opaque_and_semitransparent, + dollar_crate_name: kw::DollarCrate, + }); + new_opaque_and_semitransparent + }); + } - // Evaluate opaque and semi-transparent versions of the new syntax context. - let (opaque, opaque_and_semitransparent) = match transparency { - Transparency::Transparent => (parent_opaque, parent_opaque_and_semitransparent), - Transparency::SemiTransparent => ( - parent_opaque, - // Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents. - self.apply_mark_internal(parent_opaque_and_semitransparent, expn_id, transparency), - ), - Transparency::Opaque => ( - // Will be the same as `ctxt` if the expn chain contains only opaques. - self.apply_mark_internal(parent_opaque, expn_id, transparency), - // Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents. - self.apply_mark_internal(parent_opaque_and_semitransparent, expn_id, transparency), - ), - }; - - // Fill the full data, now that we have it. - self.syntax_context_data[ctxt.as_u32() as usize] = - SyntaxContextData::new(key, opaque, opaque_and_semitransparent); - ctxt + let parent = ctxt; + *self.syntax_context_map.entry((parent, expn_id, transparency)).or_insert_with(|| { + syntax_context_data.push(SyntaxContextData { + outer_expn: expn_id, + outer_transparency: transparency, + parent, + opaque, + opaque_and_semitransparent, + dollar_crate_name: kw::DollarCrate, + }); + SyntaxContext::from_usize(syntax_context_data.len() - 1) + }) } } @@ -1259,7 +1265,7 @@ impl HygieneEncodeContext { pub fn encode( &self, encoder: &mut T, - mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextKey), + mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextData), mut encode_expn: impl FnMut(&mut T, ExpnId, &ExpnData, ExpnHash), ) { // When we serialize a `SyntaxContextData`, we may end up serializing @@ -1317,6 +1323,9 @@ struct HygieneDecodeContextInner { /// Additional information used to assist in decoding hygiene data pub struct HygieneDecodeContext { inner: Lock, + + /// A set of serialized `SyntaxContext` ids that are currently being decoded on each thread. + local_in_progress: WorkerLocal>>, } /// Register an expansion which has been decoded from the on-disk-cache for the local crate. @@ -1387,10 +1396,10 @@ pub fn decode_expn_id( // to track which `SyntaxContext`s we have already decoded. // The provided closure will be invoked to deserialize a `SyntaxContextData` // if we haven't already seen the id of the `SyntaxContext` we are deserializing. -pub fn decode_syntax_context SyntaxContextKey>( +pub fn decode_syntax_context SyntaxContextData>( d: &mut D, context: &HygieneDecodeContext, - decode_ctxt_key: F, + decode_data: F, ) -> SyntaxContext { let raw_id: u32 = Decodable::decode(d); if raw_id == 0 { @@ -1399,9 +1408,58 @@ pub fn decode_syntax_context SyntaxContext return SyntaxContext::root(); } + let pending_ctxt = { + let mut inner = context.inner.lock(); + + // Reminder: `HygieneDecodeContext` is per-crate, so there are no collisions between + // raw ids from different crate metadatas. + if let Some(ctxt) = inner.remapped_ctxts.get(raw_id as usize).copied().flatten() { + // This has already been decoded. + return ctxt; + } + + match inner.decoding.entry(raw_id) { + Entry::Occupied(ctxt_entry) => { + let pending_ctxt = *ctxt_entry.get(); + match context.local_in_progress.borrow_mut().entry(raw_id) { + // We're decoding this already on the current thread. Return here and let the + // function higher up the stack finish decoding to handle recursive cases. + // Hopefully having a `SyntaxContext` that refers to an incorrect data is ok + // during reminder of the decoding process, it's certainly not ok after the + // top level decoding function returns. + SetEntry::Occupied(..) => return pending_ctxt, + // Some other thread is currently decoding this. + // Race with it (alternatively we could wait here). + // We cannot return this value, unlike in the recursive case above, because it + // may expose a `SyntaxContext` pointing to incorrect data to arbitrary code. + SetEntry::Vacant(entry) => { + entry.insert(); + pending_ctxt + } + } + } + Entry::Vacant(entry) => { + // We are the first thread to start decoding. Mark the current thread as being progress. + context.local_in_progress.borrow_mut().insert(raw_id); + + // Allocate and store SyntaxContext id *before* calling the decoder function, + // as the SyntaxContextData may reference itself. + let new_ctxt = HygieneData::with(|hygiene_data| { + // Push a dummy SyntaxContextData to ensure that nobody else can get the + // same ID as us. This will be overwritten after call `decode_data`. + hygiene_data.syntax_context_data.push(SyntaxContextData::decode_placeholder()); + SyntaxContext::from_usize(hygiene_data.syntax_context_data.len() - 1) + }); + entry.insert(new_ctxt); + new_ctxt + } + } + }; + // Don't try to decode data while holding the lock, since we need to // be able to recursively decode a SyntaxContext - let ctxt_key = decode_ctxt_key(d, raw_id); + let ctxt_data = decode_data(d, raw_id); + let ctxt_key = ctxt_data.key(); let ctxt = HygieneData::with(|hygiene_data| { match hygiene_data.syntax_context_map.get(&ctxt_key) { @@ -1415,10 +1473,29 @@ pub fn decode_syntax_context SyntaxContext Some(&ctxt) => ctxt, // This is a completely new context. // Overwrite its placeholder data with our decoded data. - None => hygiene_data.apply_mark_internal(ctxt_key.0, ctxt_key.1, ctxt_key.2), + None => { + let ctxt_data_ref = + &mut hygiene_data.syntax_context_data[pending_ctxt.as_u32() as usize]; + let prev_ctxt_data = mem::replace(ctxt_data_ref, ctxt_data); + // Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names`. + // We don't care what the encoding crate set this to - we want to resolve it + // from the perspective of the current compilation session. + ctxt_data_ref.dollar_crate_name = kw::DollarCrate; + // Make sure nothing weird happened while `decode_data` was running. + if !prev_ctxt_data.is_decode_placeholder() { + // Another thread may have already inserted the decoded data, + // but the decoded data should match. + assert_eq!(prev_ctxt_data, *ctxt_data_ref); + } + hygiene_data.syntax_context_map.insert(ctxt_key, pending_ctxt); + pending_ctxt + } } }); + // Mark the context as completed + context.local_in_progress.borrow_mut().remove(&raw_id); + let mut inner = context.inner.lock(); let new_len = raw_id as usize + 1; if inner.remapped_ctxts.len() < new_len { @@ -1430,7 +1507,7 @@ pub fn decode_syntax_context SyntaxContext ctxt } -fn for_all_ctxts_in( +fn for_all_ctxts_in( ctxts: impl Iterator, mut f: F, ) { @@ -1438,7 +1515,7 @@ fn for_all_ctxts_in( ctxts.map(|ctxt| (ctxt, data.syntax_context_data[ctxt.0 as usize].clone())).collect() }); for (ctxt, data) in all_data.into_iter() { - f(ctxt.0, ctxt, &data.key()); + f(ctxt.0, ctxt, &data); } } diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout index 6fd6cb474693..c80a33206fb4 100644 --- a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout +++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout @@ -5,19 +5,19 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ stream: TokenStream [ Ident { ident: "struct", - span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#5), + span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#4), }, Ident { ident: "S", - span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#5), + span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#4), }, Punct { ch: ';', spacing: Alone, - span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#5), + span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#4), }, ], - span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#4), + span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#5), }, ] #![feature /* 0#0 */(prelude_import)] @@ -59,7 +59,7 @@ macro_rules! outer struct S /* 0#0 */; macro inner /* 0#3 */ { () => { print_bang! { struct S; } } } -struct S /* 0#5 */; +struct S /* 0#4 */; // OK, not a duplicate definition of `S` fn main /* 0#0 */() {} @@ -70,7 +70,7 @@ crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer") crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #3, def_site_ctxt: #3, kind: Macro(Bang, "inner") -crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "print_bang") +crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "print_bang") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") @@ -83,9 +83,9 @@ SyntaxContexts: #1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque) #2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent) #3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent) -#4: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque) -#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque) +#4: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque) +#5: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque) #6: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque) -#7: parent: #4, outer_mark: (crate0::{{expn4}}, Transparent) -#8: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent) +#7: parent: #5, outer_mark: (crate0::{{expn4}}, Transparent) +#8: parent: #4, outer_mark: (crate0::{{expn4}}, SemiTransparent) */ From d035ca7db384e125d1a5110cefb3872386fa692f Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sun, 30 Mar 2025 11:19:07 +0200 Subject: [PATCH 666/745] Improve hir_pretty for struct expressions. Before: let a = StructWithSomeFields{ field_1: 1, field_2: 2, field_3: 3, field_4: 4, field_5: 5, field_6: 6,}; let a = StructWithSomeFields{ field_1: 1, field_2: 2, ..a}; After: let a = StructWithSomeFields { field_1: 1, field_2: 2, field_3: 3, field_4: 4, field_5: 5, field_6: 6 }; let a = StructWithSomeFields { field_1: 1, field_2: 2, ..a }; --- compiler/rustc_hir_pretty/src/lib.rs | 14 ++++---------- tests/pretty/hir-lifetimes.pp | 6 +++--- tests/pretty/hir-struct-expr.pp | 28 ++++++++++++++++++++++++++++ tests/pretty/hir-struct-expr.rs | 24 ++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 13 deletions(-) create mode 100644 tests/pretty/hir-struct-expr.pp create mode 100644 tests/pretty/hir-struct-expr.rs diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index ddaca89ccf82..1c23761b2e5b 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1193,7 +1193,8 @@ impl<'a> State<'a> { wth: hir::StructTailExpr<'_>, ) { self.print_qpath(qpath, true); - self.word("{"); + self.nbsp(); + self.word_space("{"); self.commasep_cmnt(Consistent, fields, |s, field| s.print_expr_field(field), |f| f.span); match wth { hir::StructTailExpr::Base(expr) => { @@ -1215,20 +1216,13 @@ impl<'a> State<'a> { self.word(".."); self.end(); } - hir::StructTailExpr::None => { - if !fields.is_empty() { - self.word(","); - } - } + hir::StructTailExpr::None => {} } - + self.space(); self.word("}"); } fn print_expr_field(&mut self, field: &hir::ExprField<'_>) { - if self.attrs(field.hir_id).is_empty() { - self.space(); - } self.cbox(INDENT_UNIT); self.print_attrs_as_outer(self.attrs(field.hir_id)); if !field.is_shorthand { diff --git a/tests/pretty/hir-lifetimes.pp b/tests/pretty/hir-lifetimes.pp index e545b0c8f576..4d1ab9d383bf 100644 --- a/tests/pretty/hir-lifetimes.pp +++ b/tests/pretty/hir-lifetimes.pp @@ -30,10 +30,10 @@ impl Foo<'_> { // FIXME: impl Traits printed as just `/*impl Trait*/`, ugh fn iter1<'a>(&self) - -> /*impl Trait*/ { #[lang = "Range"]{ start: 0, end: 1,} } + -> /*impl Trait*/ { #[lang = "Range"] { start: 0, end: 1 } } fn iter2(&self) - -> /*impl Trait*/ { #[lang = "Range"]{ start: 0, end: 1,} } + -> /*impl Trait*/ { #[lang = "Range"] { start: 0, end: 1 } } } fn a(x: Foo<'_>) { } @@ -82,7 +82,7 @@ struct St<'a> { x: &'a u32, } -fn f() { { let _ = St{ x: &0,}; }; { let _ = St{ x: &0,}; }; } +fn f() { { let _ = St { x: &0 }; }; { let _ = St { x: &0 }; }; } struct Name<'a>(&'a str); diff --git a/tests/pretty/hir-struct-expr.pp b/tests/pretty/hir-struct-expr.pp new file mode 100644 index 000000000000..f85d17542dff --- /dev/null +++ b/tests/pretty/hir-struct-expr.pp @@ -0,0 +1,28 @@ +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; +//@ pretty-compare-only +//@ pretty-mode:hir +//@ pp-exact:hir-struct-expr.pp + +struct StructWithSomeFields { + field_1: i32, + field_2: i32, + field_3: i32, + field_4: i32, + field_5: i32, + field_6: i32, +} + +fn main() { + let a = + StructWithSomeFields { + field_1: 1, + field_2: 2, + field_3: 3, + field_4: 4, + field_5: 5, + field_6: 6 }; + let a = StructWithSomeFields { field_1: 1, field_2: 2, ..a }; +} diff --git a/tests/pretty/hir-struct-expr.rs b/tests/pretty/hir-struct-expr.rs new file mode 100644 index 000000000000..9580f5d557d3 --- /dev/null +++ b/tests/pretty/hir-struct-expr.rs @@ -0,0 +1,24 @@ +//@ pretty-compare-only +//@ pretty-mode:hir +//@ pp-exact:hir-struct-expr.pp + +struct StructWithSomeFields { + field_1: i32, + field_2: i32, + field_3: i32, + field_4: i32, + field_5: i32, + field_6: i32, +} + +fn main() { + let a = StructWithSomeFields { + field_1: 1, + field_2: 2, + field_3: 3, + field_4: 4, + field_5: 5, + field_6: 6, + }; + let a = StructWithSomeFields { field_1: 1, field_2: 2, ..a }; +} From db576c13607401e686181d428de61136011f4551 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 9 Mar 2025 13:52:03 +0100 Subject: [PATCH 667/745] Expose `peel_casts` method as an util method inside `rustc_lint` --- compiler/rustc_lint/src/lib.rs | 1 + compiler/rustc_lint/src/reference_casting.rs | 44 +--------------- compiler/rustc_lint/src/utils.rs | 55 ++++++++++++++++++++ 3 files changed, 57 insertions(+), 43 deletions(-) create mode 100644 compiler/rustc_lint/src/utils.rs diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index c38a75400181..f6e624554567 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -80,6 +80,7 @@ mod types; mod unit_bindings; mod unqualified_local_imports; mod unused; +mod utils; use async_closures::AsyncClosureUsage; use async_fn_in_trait::AsyncFnInTrait; diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs index 7c6656f91c99..1d4d380cb685 100644 --- a/compiler/rustc_lint/src/reference_casting.rs +++ b/compiler/rustc_lint/src/reference_casting.rs @@ -6,6 +6,7 @@ use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::sym; use crate::lints::InvalidReferenceCastingDiag; +use crate::utils::peel_casts; use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { @@ -235,46 +236,3 @@ fn is_cast_to_bigger_memory_layout<'tcx>( None } } - -fn peel_casts<'tcx>(cx: &LateContext<'tcx>, mut e: &'tcx Expr<'tcx>) -> (&'tcx Expr<'tcx>, bool) { - let mut gone_trough_unsafe_cell_raw_get = false; - - loop { - e = e.peel_blocks(); - // as ... - e = if let ExprKind::Cast(expr, _) = e.kind { - expr - // .cast(), .cast_mut() or .cast_const() - } else if let ExprKind::MethodCall(_, expr, [], _) = e.kind - && let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) - && matches!( - cx.tcx.get_diagnostic_name(def_id), - Some(sym::ptr_cast | sym::const_ptr_cast | sym::ptr_cast_mut | sym::ptr_cast_const) - ) - { - expr - // ptr::from_ref(), UnsafeCell::raw_get() or mem::transmute<_, _>() - } else if let ExprKind::Call(path, [arg]) = e.kind - && let ExprKind::Path(ref qpath) = path.kind - && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() - && matches!( - cx.tcx.get_diagnostic_name(def_id), - Some(sym::ptr_from_ref | sym::unsafe_cell_raw_get | sym::transmute) - ) - { - if cx.tcx.is_diagnostic_item(sym::unsafe_cell_raw_get, def_id) { - gone_trough_unsafe_cell_raw_get = true; - } - arg - } else { - let init = cx.expr_or_init(e); - if init.hir_id != e.hir_id { - init - } else { - break; - } - }; - } - - (e, gone_trough_unsafe_cell_raw_get) -} diff --git a/compiler/rustc_lint/src/utils.rs b/compiler/rustc_lint/src/utils.rs new file mode 100644 index 000000000000..64bfa428ae43 --- /dev/null +++ b/compiler/rustc_lint/src/utils.rs @@ -0,0 +1,55 @@ +use rustc_hir::{Expr, ExprKind}; +use rustc_span::sym; + +use crate::LateContext; + +/// Given an expression, peel all of casts (` as ...`, `.cast{,_mut,_const}()`, +/// `ptr::from_ref()`, ...) and init expressions. +/// +/// Returns the outermost expression and a boolean representing if one of the casts was +/// `UnsafeCell::raw_get()` +pub(crate) fn peel_casts<'tcx>( + cx: &LateContext<'tcx>, + mut e: &'tcx Expr<'tcx>, +) -> (&'tcx Expr<'tcx>, bool) { + let mut gone_trough_unsafe_cell_raw_get = false; + + loop { + e = e.peel_blocks(); + // as ... + e = if let ExprKind::Cast(expr, _) = e.kind { + expr + // .cast(), .cast_mut() or .cast_const() + } else if let ExprKind::MethodCall(_, expr, [], _) = e.kind + && let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) + && matches!( + cx.tcx.get_diagnostic_name(def_id), + Some(sym::ptr_cast | sym::const_ptr_cast | sym::ptr_cast_mut | sym::ptr_cast_const) + ) + { + expr + // ptr::from_ref(), UnsafeCell::raw_get() or mem::transmute<_, _>() + } else if let ExprKind::Call(path, [arg]) = e.kind + && let ExprKind::Path(ref qpath) = path.kind + && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() + && matches!( + cx.tcx.get_diagnostic_name(def_id), + Some(sym::ptr_from_ref | sym::unsafe_cell_raw_get | sym::transmute) + ) + { + if cx.tcx.is_diagnostic_item(sym::unsafe_cell_raw_get, def_id) { + gone_trough_unsafe_cell_raw_get = true; + } + arg + } else { + let init = cx.expr_or_init(e); + if init.hir_id != e.hir_id { + init + } else { + break; + } + }; + } + + (e, gone_trough_unsafe_cell_raw_get) +} From a20d2ef0d9f10d65080216e7e7a1ace57ee210e8 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 9 Mar 2025 13:40:03 +0100 Subject: [PATCH 668/745] Improve explicitness of the impl of the `useless_ptr_null_checks` lint --- compiler/rustc_lint/messages.ftl | 18 +++++++++--------- compiler/rustc_lint/src/lints.rs | 10 +++++----- compiler/rustc_lint/src/ptr_nulls.rs | 24 ++++++++++++------------ 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index d51865810b9a..01e6a819cf38 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -680,15 +680,6 @@ lint_private_extern_crate_reexport = extern crate `{$ident}` is private and cann lint_proc_macro_derive_resolution_fallback = cannot find {$ns} `{$ident}` in this scope .label = names from parent modules are not accessible without an explicit import -lint_ptr_null_checks_fn_ptr = function pointers are not nullable, so checking them for null will always return false - .help = wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value - .label = expression has type `{$orig_ty}` - -lint_ptr_null_checks_fn_ret = returned pointer of `{$fn_name}` call is never null, so checking it for null will always return false - -lint_ptr_null_checks_ref = references are not nullable, so checking them for null will always return false - .label = expression has type `{$orig_ty}` - lint_query_instability = using `{$query}` can result in unstable query results .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale @@ -978,6 +969,15 @@ lint_unused_result = unused result of type `{$ty}` lint_use_let_underscore_ignore_suggestion = use `let _ = ...` to ignore the expression or result +lint_useless_ptr_null_checks_fn_ptr = function pointers are not nullable, so checking them for null will always return false + .help = wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + .label = expression has type `{$orig_ty}` + +lint_useless_ptr_null_checks_fn_ret = returned pointer of `{$fn_name}` call is never null, so checking it for null will always return false + +lint_useless_ptr_null_checks_ref = references are not nullable, so checking them for null will always return false + .label = expression has type `{$orig_ty}` + lint_uses_power_alignment = repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type lint_variant_size_differences = diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 005863095729..774665e93c42 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -591,21 +591,21 @@ pub(crate) struct ExpectationNote { // ptr_nulls.rs #[derive(LintDiagnostic)] -pub(crate) enum PtrNullChecksDiag<'a> { - #[diag(lint_ptr_null_checks_fn_ptr)] - #[help(lint_help)] +pub(crate) enum UselessPtrNullChecksDiag<'a> { + #[diag(lint_useless_ptr_null_checks_fn_ptr)] + #[help] FnPtr { orig_ty: Ty<'a>, #[label] label: Span, }, - #[diag(lint_ptr_null_checks_ref)] + #[diag(lint_useless_ptr_null_checks_ref)] Ref { orig_ty: Ty<'a>, #[label] label: Span, }, - #[diag(lint_ptr_null_checks_fn_ret)] + #[diag(lint_useless_ptr_null_checks_fn_ret)] FnRet { fn_name: Ident }, } diff --git a/compiler/rustc_lint/src/ptr_nulls.rs b/compiler/rustc_lint/src/ptr_nulls.rs index 1489f9de8199..9ace3a689ad9 100644 --- a/compiler/rustc_lint/src/ptr_nulls.rs +++ b/compiler/rustc_lint/src/ptr_nulls.rs @@ -3,7 +3,7 @@ use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind}; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::sym; -use crate::lints::PtrNullChecksDiag; +use crate::lints::UselessPtrNullChecksDiag; use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { @@ -38,10 +38,10 @@ declare_lint_pass!(PtrNullChecks => [USELESS_PTR_NULL_CHECKS]); /// a fn ptr, a reference, or a function call whose definition is /// annotated with `#![rustc_never_returns_null_ptr]`. /// If this situation is present, the function returns the appropriate diagnostic. -fn incorrect_check<'a, 'tcx: 'a>( +fn useless_check<'a, 'tcx: 'a>( cx: &'a LateContext<'tcx>, mut e: &'a Expr<'a>, -) -> Option> { +) -> Option> { let mut had_at_least_one_cast = false; loop { e = e.peel_blocks(); @@ -50,14 +50,14 @@ fn incorrect_check<'a, 'tcx: 'a>( && cx.tcx.has_attr(def_id, sym::rustc_never_returns_null_ptr) && let Some(fn_name) = cx.tcx.opt_item_ident(def_id) { - return Some(PtrNullChecksDiag::FnRet { fn_name }); + return Some(UselessPtrNullChecksDiag::FnRet { fn_name }); } else if let ExprKind::Call(path, _args) = e.kind && let ExprKind::Path(ref qpath) = path.kind && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() && cx.tcx.has_attr(def_id, sym::rustc_never_returns_null_ptr) && let Some(fn_name) = cx.tcx.opt_item_ident(def_id) { - return Some(PtrNullChecksDiag::FnRet { fn_name }); + return Some(UselessPtrNullChecksDiag::FnRet { fn_name }); } e = if let ExprKind::Cast(expr, t) = e.kind && let TyKind::Ptr(_) = t.kind @@ -73,9 +73,9 @@ fn incorrect_check<'a, 'tcx: 'a>( } else if had_at_least_one_cast { let orig_ty = cx.typeck_results().expr_ty(e); return if orig_ty.is_fn() { - Some(PtrNullChecksDiag::FnPtr { orig_ty, label: e.span }) + Some(UselessPtrNullChecksDiag::FnPtr { orig_ty, label: e.span }) } else if orig_ty.is_ref() { - Some(PtrNullChecksDiag::Ref { orig_ty, label: e.span }) + Some(UselessPtrNullChecksDiag::Ref { orig_ty, label: e.span }) } else { None }; @@ -97,7 +97,7 @@ impl<'tcx> LateLintPass<'tcx> for PtrNullChecks { cx.tcx.get_diagnostic_name(def_id), Some(sym::ptr_const_is_null | sym::ptr_is_null) ) - && let Some(diag) = incorrect_check(cx, arg) => + && let Some(diag) = useless_check(cx, arg) => { cx.emit_span_lint(USELESS_PTR_NULL_CHECKS, expr.span, diag) } @@ -110,18 +110,18 @@ impl<'tcx> LateLintPass<'tcx> for PtrNullChecks { cx.tcx.get_diagnostic_name(def_id), Some(sym::ptr_const_is_null | sym::ptr_is_null) ) - && let Some(diag) = incorrect_check(cx, receiver) => + && let Some(diag) = useless_check(cx, receiver) => { cx.emit_span_lint(USELESS_PTR_NULL_CHECKS, expr.span, diag) } ExprKind::Binary(op, left, right) if matches!(op.node, BinOpKind::Eq) => { let to_check: &Expr<'_>; - let diag: PtrNullChecksDiag<'_>; - if let Some(ddiag) = incorrect_check(cx, left) { + let diag: UselessPtrNullChecksDiag<'_>; + if let Some(ddiag) = useless_check(cx, left) { to_check = right; diag = ddiag; - } else if let Some(ddiag) = incorrect_check(cx, right) { + } else if let Some(ddiag) = useless_check(cx, right) { to_check = left; diag = ddiag; } else { From b1bc7255bb16f2500d5bdcbc17c06c2acd91c7f0 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Sun, 30 Mar 2025 15:25:27 +0200 Subject: [PATCH 669/745] Delete unreacheable `#[rustc_on_unimplemented]` --- library/alloc/src/vec/mod.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 3782f9e95194..633ef717e04d 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -3360,10 +3360,6 @@ impl Hash for Vec { } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented( - message = "vector indices are of type `usize` or ranges of `usize`", - label = "vector indices are of type `usize` or ranges of `usize`" -)] impl, A: Allocator> Index for Vec { type Output = I::Output; @@ -3374,10 +3370,6 @@ impl, A: Allocator> Index for Vec { } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented( - message = "vector indices are of type `usize` or ranges of `usize`", - label = "vector indices are of type `usize` or ranges of `usize`" -)] impl, A: Allocator> IndexMut for Vec { #[inline] fn index_mut(&mut self, index: I) -> &mut Self::Output { From 41bee761bb81888c09c0567377abdcacf564f6b9 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Sun, 30 Mar 2025 15:25:47 +0200 Subject: [PATCH 670/745] use `diagnostic::on_unimplemented` instead --- library/core/src/iter/traits/accum.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/iter/traits/accum.rs b/library/core/src/iter/traits/accum.rs index 5b7d95c2f65e..12e2b8b393a8 100644 --- a/library/core/src/iter/traits/accum.rs +++ b/library/core/src/iter/traits/accum.rs @@ -10,7 +10,7 @@ use crate::num::Wrapping; /// [`sum()`]: Iterator::sum /// [`FromIterator`]: iter::FromIterator #[stable(feature = "iter_arith_traits", since = "1.12.0")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "a value of type `{Self}` cannot be made by summing an iterator over elements of type `{A}`", label = "value of type `{Self}` cannot be made by summing a `std::iter::Iterator`" )] @@ -31,7 +31,7 @@ pub trait Sum: Sized { /// [`product()`]: Iterator::product /// [`FromIterator`]: iter::FromIterator #[stable(feature = "iter_arith_traits", since = "1.12.0")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "a value of type `{Self}` cannot be made by multiplying all elements of type `{A}` from an iterator", label = "value of type `{Self}` cannot be made by multiplying all elements from a `std::iter::Iterator`" )] From 66b1f3ba0c9bbd40e671078a320c6d99f415a055 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 30 Mar 2025 14:42:17 +0000 Subject: [PATCH 671/745] Rustup to rustc 1.88.0-nightly (1799887bb 2025-03-29) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index ab650c05d357..ceff15b1180a 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-03-25" +channel = "nightly-2025-03-30" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From ba315abda789c9f59f2100102232bddb30b0d3d3 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 30 Mar 2025 15:01:39 +0000 Subject: [PATCH 672/745] Fix rustc test suite --- scripts/test_rustc_tests.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index 5e96210d8589..95a4302b5e47 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -27,7 +27,6 @@ done git checkout -- tests/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed git checkout -- tests/ui/proc-macro/pretty-print-hack/ git checkout -- tests/ui/entry-point/auxiliary/bad_main_functions.rs -rm tests/ui/parser/unclosed-delimiter-in-dep.rs # submodule contains //~ERROR # missing features # ================ @@ -136,7 +135,6 @@ rm -r tests/run-make/incr-add-rust-src-component # ============ rm -r tests/run-make/extern-fn-explicit-align # argument alignment not yet supported rm -r tests/run-make/panic-abort-eh_frame # .eh_frame emitted with panic=abort -rm tests/ui/deprecation/deprecated_inline_threshold.rs # missing deprecation warning for -Cinline-threshold # bugs in the test suite # ====================== From 08f6747ac7428dcbc1e35732eac120d2659669b0 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 30 Mar 2025 15:48:52 +0000 Subject: [PATCH 673/745] Update tidy exceptions --- src/tools/tidy/src/deps.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 1a6550691ee3..603653847e31 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -181,6 +181,8 @@ const EXCEPTIONS_RUSTBOOK: ExceptionList = &[ const EXCEPTIONS_CRANELIFT: ExceptionList = &[ // tidy-alphabetical-start + ("cranelift-assembler-x64", "Apache-2.0 WITH LLVM-exception"), + ("cranelift-assembler-x64-meta", "Apache-2.0 WITH LLVM-exception"), ("cranelift-bforest", "Apache-2.0 WITH LLVM-exception"), ("cranelift-bitset", "Apache-2.0 WITH LLVM-exception"), ("cranelift-codegen", "Apache-2.0 WITH LLVM-exception"), @@ -512,6 +514,8 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ "bitflags", "bumpalo", "cfg-if", + "cranelift-assembler-x64", + "cranelift-assembler-x64-meta", "cranelift-bforest", "cranelift-bitset", "cranelift-codegen", From 96a2f698444144efe2cb359102ca15a48d66ad6b Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 9 Mar 2025 14:38:16 +0100 Subject: [PATCH 674/745] Uplift `clippy::invalid_null_ptr_usage` as `invalid_null_arguments` --- compiler/rustc_lint/messages.ftl | 4 + compiler/rustc_lint/src/lints.rs | 16 ++ compiler/rustc_lint/src/ptr_nulls.rs | 106 +++++++- compiler/rustc_lint/src/utils.rs | 2 +- tests/ui/lint/invalid_null_args.rs | 136 ++++++++++ tests/ui/lint/invalid_null_args.stderr | 330 +++++++++++++++++++++++++ 6 files changed, 590 insertions(+), 4 deletions(-) create mode 100644 tests/ui/lint/invalid_null_args.rs create mode 100644 tests/ui/lint/invalid_null_args.stderr diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 01e6a819cf38..f45caf96f9b6 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -456,6 +456,10 @@ lint_invalid_nan_comparisons_eq_ne = incorrect NaN comparison, NaN cannot be dir lint_invalid_nan_comparisons_lt_le_gt_ge = incorrect NaN comparison, NaN is not orderable +lint_invalid_null_arguments = calling this function with a null pointer is undefined behavior, even if the result of the function is unused + .origin = null pointer originates from here + .doc = for more information, visit and + lint_invalid_reference_casting_assign_to_ref = assigning to `&T` is undefined behavior, consider using an `UnsafeCell` .label = casting happened here diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 774665e93c42..4de998c08747 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -609,6 +609,22 @@ pub(crate) enum UselessPtrNullChecksDiag<'a> { FnRet { fn_name: Ident }, } +#[derive(LintDiagnostic)] +pub(crate) enum InvalidNullArgumentsDiag { + #[diag(lint_invalid_null_arguments)] + #[help(lint_doc)] + NullPtrInline { + #[label(lint_origin)] + null_span: Span, + }, + #[diag(lint_invalid_null_arguments)] + #[help(lint_doc)] + NullPtrThroughBinding { + #[note(lint_origin)] + null_span: Span, + }, +} + // for_loops_over_fallibles.rs #[derive(LintDiagnostic)] #[diag(lint_for_loops_over_fallibles)] diff --git a/compiler/rustc_lint/src/ptr_nulls.rs b/compiler/rustc_lint/src/ptr_nulls.rs index 9ace3a689ad9..826bce2c3150 100644 --- a/compiler/rustc_lint/src/ptr_nulls.rs +++ b/compiler/rustc_lint/src/ptr_nulls.rs @@ -1,9 +1,11 @@ use rustc_ast::LitKind; use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind}; +use rustc_middle::ty::RawPtr; use rustc_session::{declare_lint, declare_lint_pass}; -use rustc_span::sym; +use rustc_span::{Span, sym}; -use crate::lints::UselessPtrNullChecksDiag; +use crate::lints::{InvalidNullArgumentsDiag, UselessPtrNullChecksDiag}; +use crate::utils::peel_casts; use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { @@ -31,7 +33,30 @@ declare_lint! { "useless checking of non-null-typed pointer" } -declare_lint_pass!(PtrNullChecks => [USELESS_PTR_NULL_CHECKS]); +declare_lint! { + /// The `invalid_null_arguments` lint checks for invalid usage of null pointers in arguments. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// # use std::{slice, ptr}; + /// // Undefined behavior + /// # let _slice: &[u8] = + /// unsafe { slice::from_raw_parts(ptr::null(), 0) }; + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Calling methods whos safety invariants requires non-null ptr with a null pointer + /// is [Undefined Behavior](https://doc.rust-lang.org/reference/behavior-considered-undefined.html)! + INVALID_NULL_ARGUMENTS, + Deny, + "invalid null pointer in arguments" +} + +declare_lint_pass!(PtrNullChecks => [USELESS_PTR_NULL_CHECKS, INVALID_NULL_ARGUMENTS]); /// This function checks if the expression is from a series of consecutive casts, /// ie. `(my_fn as *const _ as *mut _).cast_mut()` and whether the original expression is either @@ -85,6 +110,25 @@ fn useless_check<'a, 'tcx: 'a>( } } +/// Checks if the given expression is a null pointer (modulo casting) +fn is_null_ptr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option { + let (expr, _) = peel_casts(cx, expr); + + if let ExprKind::Call(path, []) = expr.kind + && let ExprKind::Path(ref qpath) = path.kind + && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() + && let Some(diag_item) = cx.tcx.get_diagnostic_name(def_id) + { + (diag_item == sym::ptr_null || diag_item == sym::ptr_null_mut).then_some(expr.span) + } else if let ExprKind::Lit(spanned) = expr.kind + && let LitKind::Int(v, _) = spanned.node + { + (v == 0).then_some(expr.span) + } else { + None + } +} + impl<'tcx> LateLintPass<'tcx> for PtrNullChecks { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { match expr.kind { @@ -102,6 +146,62 @@ impl<'tcx> LateLintPass<'tcx> for PtrNullChecks { cx.emit_span_lint(USELESS_PTR_NULL_CHECKS, expr.span, diag) } + // Catching: + // (arg...) where `arg` is null-ptr and `path` is a fn that expect non-null-ptr + ExprKind::Call(path, args) + if let ExprKind::Path(ref qpath) = path.kind + && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() + && let Some(diag_name) = cx.tcx.get_diagnostic_name(def_id) => + { + // `arg` positions where null would cause U.B and whenever ZST are allowed. + // + // We should probably have a `rustc` attribute, but checking them is costly, + // maybe if we checked for null ptr first, it would be acceptable? + let (arg_indices, are_zsts_allowed): (&[_], _) = match diag_name { + sym::ptr_read + | sym::ptr_read_unaligned + | sym::ptr_read_volatile + | sym::ptr_replace + | sym::ptr_write + | sym::ptr_write_bytes + | sym::ptr_write_unaligned + | sym::ptr_write_volatile => (&[0], true), + sym::slice_from_raw_parts | sym::slice_from_raw_parts_mut => (&[0], false), + sym::ptr_copy + | sym::ptr_copy_nonoverlapping + | sym::ptr_swap + | sym::ptr_swap_nonoverlapping => (&[0, 1], true), + _ => return, + }; + + for &arg_idx in arg_indices { + if let Some(arg) = args.get(arg_idx) + && let Some(null_span) = is_null_ptr(cx, arg) + && let Some(ty) = cx.typeck_results().expr_ty_opt(arg) + && let RawPtr(ty, _mutbl) = ty.kind() + { + // If ZST are fine, don't lint on them + let typing_env = cx.typing_env(); + if are_zsts_allowed + && cx + .tcx + .layout_of(typing_env.as_query_input(*ty)) + .is_ok_and(|layout| layout.is_1zst()) + { + break; + } + + let diag = if arg.span.contains(null_span) { + InvalidNullArgumentsDiag::NullPtrInline { null_span } + } else { + InvalidNullArgumentsDiag::NullPtrThroughBinding { null_span } + }; + + cx.emit_span_lint(INVALID_NULL_ARGUMENTS, expr.span, diag) + } + } + } + // Catching: // (fn_ptr as * ).is_null() ExprKind::MethodCall(_, receiver, _, _) diff --git a/compiler/rustc_lint/src/utils.rs b/compiler/rustc_lint/src/utils.rs index 64bfa428ae43..a7295d9c5326 100644 --- a/compiler/rustc_lint/src/utils.rs +++ b/compiler/rustc_lint/src/utils.rs @@ -6,7 +6,7 @@ use crate::LateContext; /// Given an expression, peel all of casts (` as ...`, `.cast{,_mut,_const}()`, /// `ptr::from_ref()`, ...) and init expressions. /// -/// Returns the outermost expression and a boolean representing if one of the casts was +/// Returns the innermost expression and a boolean representing if one of the casts was /// `UnsafeCell::raw_get()` pub(crate) fn peel_casts<'tcx>( cx: &LateContext<'tcx>, diff --git a/tests/ui/lint/invalid_null_args.rs b/tests/ui/lint/invalid_null_args.rs new file mode 100644 index 000000000000..7948f0d86d09 --- /dev/null +++ b/tests/ui/lint/invalid_null_args.rs @@ -0,0 +1,136 @@ +// check-fail +// run-rustfix + +use std::ptr; +use std::mem; + +unsafe fn null_ptr() { + ptr::write( + //~^ ERROR calling this function with a null pointer is undefined behavior + ptr::null_mut() as *mut u32, + mem::transmute::<[u8; 4], _>([0, 0, 0, 255]), + ); + + let null_ptr = ptr::null_mut(); + ptr::write( + //~^ ERROR calling this function with a null pointer is undefined behavior + null_ptr as *mut u32, + mem::transmute::<[u8; 4], _>([0, 0, 0, 255]), + ); + + let _: &[usize] = std::slice::from_raw_parts(ptr::null(), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + let _: &[usize] = std::slice::from_raw_parts(ptr::null_mut(), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + let _: &[usize] = std::slice::from_raw_parts(0 as *mut _, 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + let _: &[usize] = std::slice::from_raw_parts(mem::transmute(0usize), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + + let _: &[usize] = std::slice::from_raw_parts_mut(ptr::null_mut(), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + + ptr::copy::(ptr::null(), ptr::NonNull::dangling().as_ptr(), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + ptr::copy::(ptr::NonNull::dangling().as_ptr(), ptr::null_mut(), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + + ptr::copy_nonoverlapping::(ptr::null(), ptr::NonNull::dangling().as_ptr(), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + ptr::copy_nonoverlapping::( + //~^ ERROR calling this function with a null pointer is undefined behavior + ptr::NonNull::dangling().as_ptr(), + ptr::null_mut(), + 0 + ); + + #[derive(Copy, Clone)] + struct A(usize); + let mut v = A(200); + + let _a: A = ptr::read(ptr::null()); + //~^ ERROR calling this function with a null pointer is undefined behavior + let _a: A = ptr::read(ptr::null_mut()); + //~^ ERROR calling this function with a null pointer is undefined behavior + + let _a: A = ptr::read_unaligned(ptr::null()); + //~^ ERROR calling this function with a null pointer is undefined behavior + let _a: A = ptr::read_unaligned(ptr::null_mut()); + //~^ ERROR calling this function with a null pointer is undefined behavior + + let _a: A = ptr::read_volatile(ptr::null()); + //~^ ERROR calling this function with a null pointer is undefined behavior + let _a: A = ptr::read_volatile(ptr::null_mut()); + //~^ ERROR calling this function with a null pointer is undefined behavior + + let _a: A = ptr::replace(ptr::null_mut(), v); + //~^ ERROR calling this function with a null pointer is undefined behavior + + ptr::swap::(ptr::null_mut(), &mut v); + //~^ ERROR calling this function with a null pointer is undefined behavior + ptr::swap::(&mut v, ptr::null_mut()); + //~^ ERROR calling this function with a null pointer is undefined behavior + + ptr::swap_nonoverlapping::(ptr::null_mut(), &mut v, 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + ptr::swap_nonoverlapping::(&mut v, ptr::null_mut(), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + + ptr::write(ptr::null_mut(), v); + //~^ ERROR calling this function with a null pointer is undefined behavior + + ptr::write_unaligned(ptr::null_mut(), v); + //~^ ERROR calling this function with a null pointer is undefined behavior + + ptr::write_volatile(ptr::null_mut(), v); + //~^ ERROR calling this function with a null pointer is undefined behavior + + ptr::write_bytes::(ptr::null_mut(), 42, 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + + // with indirections + let const_ptr = null_ptr as *const u8; + let _a: u8 = ptr::read(const_ptr); + //~^ ERROR calling this function with a null pointer is undefined behavior +} + +unsafe fn zst() { + struct Zst; // zero-sized type + + std::slice::from_raw_parts::<()>(ptr::null(), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + std::slice::from_raw_parts::(ptr::null(), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + std::slice::from_raw_parts_mut::<()>(ptr::null_mut(), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + std::slice::from_raw_parts_mut::(ptr::null_mut(), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + + ptr::read::<()>(ptr::null()); + ptr::read::(ptr::null()); + + ptr::write(ptr::null_mut(), ()); + ptr::write(ptr::null_mut(), Zst); + + ptr::copy(ptr::null::<()>(), ptr::null_mut::<()>(), 1); + ptr::copy(ptr::null::(), ptr::null_mut::(), 1); +} + +unsafe fn not_invalid() { + // Simplified false-positive from std quicksort implementation + + let mut a = ptr::null_mut(); + let mut b = (); + + loop { + if false { + break; + } + + a = &raw mut b; + } + + ptr::write(a, ()); +} + +fn main() {} diff --git a/tests/ui/lint/invalid_null_args.stderr b/tests/ui/lint/invalid_null_args.stderr new file mode 100644 index 000000000000..f95bc2afa829 --- /dev/null +++ b/tests/ui/lint/invalid_null_args.stderr @@ -0,0 +1,330 @@ +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:8:5 + | +LL | / ptr::write( +LL | | +LL | | ptr::null_mut() as *mut u32, + | | --------------- null pointer originates from here +LL | | mem::transmute::<[u8; 4], _>([0, 0, 0, 255]), +LL | | ); + | |_____^ + | + = help: for more information, visit and + = note: `#[deny(invalid_null_arguments)]` on by default + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:15:5 + | +LL | / ptr::write( +LL | | +LL | | null_ptr as *mut u32, +LL | | mem::transmute::<[u8; 4], _>([0, 0, 0, 255]), +LL | | ); + | |_____^ + | + = help: for more information, visit and +note: null pointer originates from here + --> $DIR/invalid_null_args.rs:14:20 + | +LL | let null_ptr = ptr::null_mut(); + | ^^^^^^^^^^^^^^^ + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:21:23 + | +LL | let _: &[usize] = std::slice::from_raw_parts(ptr::null(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:23:23 + | +LL | let _: &[usize] = std::slice::from_raw_parts(ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:25:23 + | +LL | let _: &[usize] = std::slice::from_raw_parts(0 as *mut _, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^^^^^^^^^^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:27:23 + | +LL | let _: &[usize] = std::slice::from_raw_parts(mem::transmute(0usize), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------^^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:30:23 + | +LL | let _: &[usize] = std::slice::from_raw_parts_mut(ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:33:5 + | +LL | ptr::copy::(ptr::null(), ptr::NonNull::dangling().as_ptr(), 0); + | ^^^^^^^^^^^^^^^^^^^-----------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:35:5 + | +LL | ptr::copy::(ptr::NonNull::dangling().as_ptr(), ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:38:5 + | +LL | ptr::copy_nonoverlapping::(ptr::null(), ptr::NonNull::dangling().as_ptr(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:40:5 + | +LL | / ptr::copy_nonoverlapping::( +LL | | +LL | | ptr::NonNull::dangling().as_ptr(), +LL | | ptr::null_mut(), + | | --------------- null pointer originates from here +LL | | 0 +LL | | ); + | |_____^ + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:51:17 + | +LL | let _a: A = ptr::read(ptr::null()); + | ^^^^^^^^^^-----------^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:53:17 + | +LL | let _a: A = ptr::read(ptr::null_mut()); + | ^^^^^^^^^^---------------^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:56:17 + | +LL | let _a: A = ptr::read_unaligned(ptr::null()); + | ^^^^^^^^^^^^^^^^^^^^-----------^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:58:17 + | +LL | let _a: A = ptr::read_unaligned(ptr::null_mut()); + | ^^^^^^^^^^^^^^^^^^^^---------------^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:61:17 + | +LL | let _a: A = ptr::read_volatile(ptr::null()); + | ^^^^^^^^^^^^^^^^^^^-----------^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:63:17 + | +LL | let _a: A = ptr::read_volatile(ptr::null_mut()); + | ^^^^^^^^^^^^^^^^^^^---------------^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:66:17 + | +LL | let _a: A = ptr::replace(ptr::null_mut(), v); + | ^^^^^^^^^^^^^---------------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:69:5 + | +LL | ptr::swap::(ptr::null_mut(), &mut v); + | ^^^^^^^^^^^^^^^---------------^^^^^^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:71:5 + | +LL | ptr::swap::(&mut v, ptr::null_mut()); + | ^^^^^^^^^^^^^^^^^^^^^^^---------------^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:74:5 + | +LL | ptr::swap_nonoverlapping::(ptr::null_mut(), &mut v, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^^^^^^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:76:5 + | +LL | ptr::swap_nonoverlapping::(&mut v, ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:79:5 + | +LL | ptr::write(ptr::null_mut(), v); + | ^^^^^^^^^^^---------------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:82:5 + | +LL | ptr::write_unaligned(ptr::null_mut(), v); + | ^^^^^^^^^^^^^^^^^^^^^---------------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:85:5 + | +LL | ptr::write_volatile(ptr::null_mut(), v); + | ^^^^^^^^^^^^^^^^^^^^---------------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:88:5 + | +LL | ptr::write_bytes::(ptr::null_mut(), 42, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:93:18 + | +LL | let _a: u8 = ptr::read(const_ptr); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: for more information, visit and +note: null pointer originates from here + --> $DIR/invalid_null_args.rs:14:20 + | +LL | let null_ptr = ptr::null_mut(); + | ^^^^^^^^^^^^^^^ + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:100:5 + | +LL | std::slice::from_raw_parts::<()>(ptr::null(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:102:5 + | +LL | std::slice::from_raw_parts::(ptr::null(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:104:5 + | +LL | std::slice::from_raw_parts_mut::<()>(ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:106:5 + | +LL | std::slice::from_raw_parts_mut::(ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: aborting due to 31 previous errors + From b738343a54bdaf009d928737e7c682c72aec475c Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 9 Mar 2025 14:55:46 +0100 Subject: [PATCH 675/745] Drop `clippy::invalid_null_ptr_usage` --- .../clippy/clippy_lints/src/declared_lints.rs | 1 - .../clippy_lints/src/deprecated_lints.rs | 2 + src/tools/clippy/clippy_lints/src/ptr.rs | 73 +--------- src/tools/clippy/tests/ui/crashes/ice-1782.rs | 2 +- .../tests/ui/invalid_null_ptr_usage.fixed | 66 --------- .../clippy/tests/ui/invalid_null_ptr_usage.rs | 66 --------- .../tests/ui/invalid_null_ptr_usage.stderr | 136 ------------------ .../ui/invalid_null_ptr_usage_no_std.fixed | 79 ---------- .../tests/ui/invalid_null_ptr_usage_no_std.rs | 79 ---------- .../ui/invalid_null_ptr_usage_no_std.stderr | 136 ------------------ src/tools/clippy/tests/ui/rename.fixed | 1 + src/tools/clippy/tests/ui/rename.rs | 1 + src/tools/clippy/tests/ui/rename.stderr | 30 ++-- 13 files changed, 24 insertions(+), 648 deletions(-) delete mode 100644 src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed delete mode 100644 src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs delete mode 100644 src/tools/clippy/tests/ui/invalid_null_ptr_usage.stderr delete mode 100644 src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.fixed delete mode 100644 src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.rs delete mode 100644 src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.stderr diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs index 7fa23dad6981..39e451637070 100644 --- a/src/tools/clippy/clippy_lints/src/declared_lints.rs +++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs @@ -638,7 +638,6 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::precedence::PRECEDENCE_INFO, crate::precedence::PRECEDENCE_BITS_INFO, crate::ptr::CMP_NULL_INFO, - crate::ptr::INVALID_NULL_PTR_USAGE_INFO, crate::ptr::MUT_FROM_REF_INFO, crate::ptr::PTR_ARG_INFO, crate::ptr::PTR_EQ_INFO, diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs index 0031da406f17..de66ead4f420 100644 --- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs +++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs @@ -131,6 +131,8 @@ declare_with_version! { RENAMED(RENAMED_VERSION): &[(&str, &str)] = &[ ("clippy::clone_double_ref", "suspicious_double_ref_op"), #[clippy::version = ""] ("clippy::cmp_nan", "invalid_nan_comparisons"), + #[clippy::version = "CURRENT_RUSTC_VERSION"] + ("clippy::invalid_null_ptr_usage", "invalid_null_arguments"), #[clippy::version = "1.86.0"] ("clippy::double_neg", "double_negations"), #[clippy::version = ""] diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index 55f1ece05593..50ef56db167c 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -125,29 +125,6 @@ declare_clippy_lint! { "fns that create mutable refs from immutable ref args" } -declare_clippy_lint! { - /// ### What it does - /// This lint checks for invalid usages of `ptr::null`. - /// - /// ### Why is this bad? - /// This causes undefined behavior. - /// - /// ### Example - /// ```ignore - /// // Undefined behavior - /// unsafe { std::slice::from_raw_parts(ptr::null(), 0); } - /// ``` - /// - /// Use instead: - /// ```ignore - /// unsafe { std::slice::from_raw_parts(NonNull::dangling().as_ptr(), 0); } - /// ``` - #[clippy::version = "1.53.0"] - pub INVALID_NULL_PTR_USAGE, - correctness, - "invalid usage of a null pointer, suggesting `NonNull::dangling()` instead" -} - declare_clippy_lint! { /// ### What it does /// Use `std::ptr::eq` when applicable @@ -177,7 +154,7 @@ declare_clippy_lint! { "use `std::ptr::eq` when comparing raw pointers" } -declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF, INVALID_NULL_PTR_USAGE, PTR_EQ]); +declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF, PTR_EQ]); impl<'tcx> LateLintPass<'tcx> for Ptr { fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { @@ -301,54 +278,6 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { format!("{non_null_path_snippet}.is_null()"), Applicability::MachineApplicable, ); - } else { - check_invalid_ptr_usage(cx, expr); - } - } -} - -fn check_invalid_ptr_usage<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let ExprKind::Call(fun, args) = expr.kind - && let ExprKind::Path(ref qpath) = fun.kind - && let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id() - && let Some(name) = cx.tcx.get_diagnostic_name(fun_def_id) - { - // TODO: `ptr_slice_from_raw_parts` and its mutable variant should probably still be linted - // conditionally based on how the return value is used, but not universally like the other - // functions since there are valid uses for null slice pointers. - // - // See: https://github.com/rust-lang/rust-clippy/pull/13452/files#r1773772034 - - // `arg` positions where null would cause U.B. - let arg_indices: &[_] = match name { - sym::ptr_read - | sym::ptr_read_unaligned - | sym::ptr_read_volatile - | sym::ptr_replace - | sym::ptr_write - | sym::ptr_write_bytes - | sym::ptr_write_unaligned - | sym::ptr_write_volatile - | sym::slice_from_raw_parts - | sym::slice_from_raw_parts_mut => &[0], - sym::ptr_copy | sym::ptr_copy_nonoverlapping | sym::ptr_swap | sym::ptr_swap_nonoverlapping => &[0, 1], - _ => return, - }; - - for &arg_idx in arg_indices { - if let Some(arg) = args.get(arg_idx).filter(|arg| is_null_path(cx, arg)) - && let Some(std_or_core) = std_or_core(cx) - { - span_lint_and_sugg( - cx, - INVALID_NULL_PTR_USAGE, - arg.span, - "pointer must be non-null", - "change this to", - format!("{std_or_core}::ptr::NonNull::dangling().as_ptr()"), - Applicability::MachineApplicable, - ); - } } } } diff --git a/src/tools/clippy/tests/ui/crashes/ice-1782.rs b/src/tools/clippy/tests/ui/crashes/ice-1782.rs index fefdc405cce2..4a1886c08af6 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-1782.rs +++ b/src/tools/clippy/tests/ui/crashes/ice-1782.rs @@ -1,6 +1,6 @@ //@ check-pass -#![allow(dead_code, unused_variables)] +#![allow(dead_code, unused_variables, invalid_null_arguments)] #![allow(clippy::unnecessary_cast, clippy::missing_transmute_annotations)] /// Should not trigger an ICE in `SpanlessEq` / `consts::constant` diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed b/src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed deleted file mode 100644 index ce78e89ee829..000000000000 --- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed +++ /dev/null @@ -1,66 +0,0 @@ -fn main() { - unsafe { - let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - - let _slice: &[usize] = std::slice::from_raw_parts_mut(std::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - - std::ptr::copy::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - std::ptr::copy::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - - std::ptr::copy_nonoverlapping::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - std::ptr::copy_nonoverlapping::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - - struct A; // zero sized struct - assert_eq!(std::mem::size_of::(), 0); - - let _a: A = std::ptr::read(std::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - let _a: A = std::ptr::read(std::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - - let _a: A = std::ptr::read_unaligned(std::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - let _a: A = std::ptr::read_unaligned(std::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - - let _a: A = std::ptr::read_volatile(std::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - let _a: A = std::ptr::read_volatile(std::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - - let _a: A = std::ptr::replace(std::ptr::NonNull::dangling().as_ptr(), A); - //~^ invalid_null_ptr_usage - let _slice: *const [usize] = std::ptr::slice_from_raw_parts(std::ptr::null_mut(), 0); // shouldn't lint - let _slice: *const [usize] = std::ptr::slice_from_raw_parts_mut(std::ptr::null_mut(), 0); - - std::ptr::swap::(std::ptr::NonNull::dangling().as_ptr(), &mut A); - //~^ invalid_null_ptr_usage - std::ptr::swap::(&mut A, std::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - - std::ptr::swap_nonoverlapping::(std::ptr::NonNull::dangling().as_ptr(), &mut A, 0); - //~^ invalid_null_ptr_usage - std::ptr::swap_nonoverlapping::(&mut A, std::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - - std::ptr::write(std::ptr::NonNull::dangling().as_ptr(), A); - //~^ invalid_null_ptr_usage - - std::ptr::write_unaligned(std::ptr::NonNull::dangling().as_ptr(), A); - //~^ invalid_null_ptr_usage - - std::ptr::write_volatile(std::ptr::NonNull::dangling().as_ptr(), A); - //~^ invalid_null_ptr_usage - - std::ptr::write_bytes::(std::ptr::NonNull::dangling().as_ptr(), 42, 0); - //~^ invalid_null_ptr_usage - } -} diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs b/src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs deleted file mode 100644 index 361865fbd960..000000000000 --- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs +++ /dev/null @@ -1,66 +0,0 @@ -fn main() { - unsafe { - let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null(), 0); - //~^ invalid_null_ptr_usage - let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null_mut(), 0); - //~^ invalid_null_ptr_usage - - let _slice: &[usize] = std::slice::from_raw_parts_mut(std::ptr::null_mut(), 0); - //~^ invalid_null_ptr_usage - - std::ptr::copy::(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - std::ptr::copy::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0); - //~^ invalid_null_ptr_usage - - std::ptr::copy_nonoverlapping::(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - std::ptr::copy_nonoverlapping::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0); - //~^ invalid_null_ptr_usage - - struct A; // zero sized struct - assert_eq!(std::mem::size_of::(), 0); - - let _a: A = std::ptr::read(std::ptr::null()); - //~^ invalid_null_ptr_usage - let _a: A = std::ptr::read(std::ptr::null_mut()); - //~^ invalid_null_ptr_usage - - let _a: A = std::ptr::read_unaligned(std::ptr::null()); - //~^ invalid_null_ptr_usage - let _a: A = std::ptr::read_unaligned(std::ptr::null_mut()); - //~^ invalid_null_ptr_usage - - let _a: A = std::ptr::read_volatile(std::ptr::null()); - //~^ invalid_null_ptr_usage - let _a: A = std::ptr::read_volatile(std::ptr::null_mut()); - //~^ invalid_null_ptr_usage - - let _a: A = std::ptr::replace(std::ptr::null_mut(), A); - //~^ invalid_null_ptr_usage - let _slice: *const [usize] = std::ptr::slice_from_raw_parts(std::ptr::null_mut(), 0); // shouldn't lint - let _slice: *const [usize] = std::ptr::slice_from_raw_parts_mut(std::ptr::null_mut(), 0); - - std::ptr::swap::(std::ptr::null_mut(), &mut A); - //~^ invalid_null_ptr_usage - std::ptr::swap::(&mut A, std::ptr::null_mut()); - //~^ invalid_null_ptr_usage - - std::ptr::swap_nonoverlapping::(std::ptr::null_mut(), &mut A, 0); - //~^ invalid_null_ptr_usage - std::ptr::swap_nonoverlapping::(&mut A, std::ptr::null_mut(), 0); - //~^ invalid_null_ptr_usage - - std::ptr::write(std::ptr::null_mut(), A); - //~^ invalid_null_ptr_usage - - std::ptr::write_unaligned(std::ptr::null_mut(), A); - //~^ invalid_null_ptr_usage - - std::ptr::write_volatile(std::ptr::null_mut(), A); - //~^ invalid_null_ptr_usage - - std::ptr::write_bytes::(std::ptr::null_mut(), 42, 0); - //~^ invalid_null_ptr_usage - } -} diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.stderr b/src/tools/clippy/tests/ui/invalid_null_ptr_usage.stderr deleted file mode 100644 index 3f9d15b90401..000000000000 --- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.stderr +++ /dev/null @@ -1,136 +0,0 @@ -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:3:59 - | -LL | let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null(), 0); - | ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - | - = note: `#[deny(clippy::invalid_null_ptr_usage)]` on by default - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:5:59 - | -LL | let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null_mut(), 0); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:8:63 - | -LL | let _slice: &[usize] = std::slice::from_raw_parts_mut(std::ptr::null_mut(), 0); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:11:33 - | -LL | std::ptr::copy::(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0); - | ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:13:73 - | -LL | std::ptr::copy::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:16:48 - | -LL | std::ptr::copy_nonoverlapping::(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0); - | ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:18:88 - | -LL | std::ptr::copy_nonoverlapping::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:24:36 - | -LL | let _a: A = std::ptr::read(std::ptr::null()); - | ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:26:36 - | -LL | let _a: A = std::ptr::read(std::ptr::null_mut()); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:29:46 - | -LL | let _a: A = std::ptr::read_unaligned(std::ptr::null()); - | ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:31:46 - | -LL | let _a: A = std::ptr::read_unaligned(std::ptr::null_mut()); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:34:45 - | -LL | let _a: A = std::ptr::read_volatile(std::ptr::null()); - | ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:36:45 - | -LL | let _a: A = std::ptr::read_volatile(std::ptr::null_mut()); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:39:39 - | -LL | let _a: A = std::ptr::replace(std::ptr::null_mut(), A); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:44:29 - | -LL | std::ptr::swap::(std::ptr::null_mut(), &mut A); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:46:37 - | -LL | std::ptr::swap::(&mut A, std::ptr::null_mut()); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:49:44 - | -LL | std::ptr::swap_nonoverlapping::(std::ptr::null_mut(), &mut A, 0); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:51:52 - | -LL | std::ptr::swap_nonoverlapping::(&mut A, std::ptr::null_mut(), 0); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:54:25 - | -LL | std::ptr::write(std::ptr::null_mut(), A); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:57:35 - | -LL | std::ptr::write_unaligned(std::ptr::null_mut(), A); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:60:34 - | -LL | std::ptr::write_volatile(std::ptr::null_mut(), A); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:63:40 - | -LL | std::ptr::write_bytes::(std::ptr::null_mut(), 42, 0); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: aborting due to 22 previous errors - diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.fixed b/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.fixed deleted file mode 100644 index df7ab166187d..000000000000 --- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.fixed +++ /dev/null @@ -1,79 +0,0 @@ -#![no_std] -#![feature(lang_items)] - -use core::panic::PanicInfo; - -#[lang = "eh_personality"] -extern "C" fn eh_personality() {} - -#[panic_handler] -fn panic(info: &PanicInfo) -> ! { - loop {} -} - -fn main() { - unsafe { - let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - - let _slice: &[usize] = core::slice::from_raw_parts_mut(core::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - - core::ptr::copy::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - core::ptr::copy::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - - core::ptr::copy_nonoverlapping::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - core::ptr::copy_nonoverlapping::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - - struct A; // zero sized struct - assert_eq!(core::mem::size_of::(), 0); - - let _a: A = core::ptr::read(core::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - let _a: A = core::ptr::read(core::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - - let _a: A = core::ptr::read_unaligned(core::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - let _a: A = core::ptr::read_unaligned(core::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - - let _a: A = core::ptr::read_volatile(core::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - let _a: A = core::ptr::read_volatile(core::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - - let _a: A = core::ptr::replace(core::ptr::NonNull::dangling().as_ptr(), A); - //~^ invalid_null_ptr_usage - let _slice: *const [usize] = core::ptr::slice_from_raw_parts(core::ptr::null_mut(), 0); // shouldn't lint - let _slice: *const [usize] = core::ptr::slice_from_raw_parts_mut(core::ptr::null_mut(), 0); - - core::ptr::swap::(core::ptr::NonNull::dangling().as_ptr(), &mut A); - //~^ invalid_null_ptr_usage - core::ptr::swap::(&mut A, core::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - - core::ptr::swap_nonoverlapping::(core::ptr::NonNull::dangling().as_ptr(), &mut A, 0); - //~^ invalid_null_ptr_usage - core::ptr::swap_nonoverlapping::(&mut A, core::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - - core::ptr::write(core::ptr::NonNull::dangling().as_ptr(), A); - //~^ invalid_null_ptr_usage - - core::ptr::write_unaligned(core::ptr::NonNull::dangling().as_ptr(), A); - //~^ invalid_null_ptr_usage - - core::ptr::write_volatile(core::ptr::NonNull::dangling().as_ptr(), A); - //~^ invalid_null_ptr_usage - - core::ptr::write_bytes::(core::ptr::NonNull::dangling().as_ptr(), 42, 0); - //~^ invalid_null_ptr_usage - } -} diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.rs b/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.rs deleted file mode 100644 index 38ddfff05535..000000000000 --- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.rs +++ /dev/null @@ -1,79 +0,0 @@ -#![no_std] -#![feature(lang_items)] - -use core::panic::PanicInfo; - -#[lang = "eh_personality"] -extern "C" fn eh_personality() {} - -#[panic_handler] -fn panic(info: &PanicInfo) -> ! { - loop {} -} - -fn main() { - unsafe { - let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::null(), 0); - //~^ invalid_null_ptr_usage - let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::null_mut(), 0); - //~^ invalid_null_ptr_usage - - let _slice: &[usize] = core::slice::from_raw_parts_mut(core::ptr::null_mut(), 0); - //~^ invalid_null_ptr_usage - - core::ptr::copy::(core::ptr::null(), core::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - core::ptr::copy::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::null_mut(), 0); - //~^ invalid_null_ptr_usage - - core::ptr::copy_nonoverlapping::(core::ptr::null(), core::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - core::ptr::copy_nonoverlapping::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::null_mut(), 0); - //~^ invalid_null_ptr_usage - - struct A; // zero sized struct - assert_eq!(core::mem::size_of::(), 0); - - let _a: A = core::ptr::read(core::ptr::null()); - //~^ invalid_null_ptr_usage - let _a: A = core::ptr::read(core::ptr::null_mut()); - //~^ invalid_null_ptr_usage - - let _a: A = core::ptr::read_unaligned(core::ptr::null()); - //~^ invalid_null_ptr_usage - let _a: A = core::ptr::read_unaligned(core::ptr::null_mut()); - //~^ invalid_null_ptr_usage - - let _a: A = core::ptr::read_volatile(core::ptr::null()); - //~^ invalid_null_ptr_usage - let _a: A = core::ptr::read_volatile(core::ptr::null_mut()); - //~^ invalid_null_ptr_usage - - let _a: A = core::ptr::replace(core::ptr::null_mut(), A); - //~^ invalid_null_ptr_usage - let _slice: *const [usize] = core::ptr::slice_from_raw_parts(core::ptr::null_mut(), 0); // shouldn't lint - let _slice: *const [usize] = core::ptr::slice_from_raw_parts_mut(core::ptr::null_mut(), 0); - - core::ptr::swap::(core::ptr::null_mut(), &mut A); - //~^ invalid_null_ptr_usage - core::ptr::swap::(&mut A, core::ptr::null_mut()); - //~^ invalid_null_ptr_usage - - core::ptr::swap_nonoverlapping::(core::ptr::null_mut(), &mut A, 0); - //~^ invalid_null_ptr_usage - core::ptr::swap_nonoverlapping::(&mut A, core::ptr::null_mut(), 0); - //~^ invalid_null_ptr_usage - - core::ptr::write(core::ptr::null_mut(), A); - //~^ invalid_null_ptr_usage - - core::ptr::write_unaligned(core::ptr::null_mut(), A); - //~^ invalid_null_ptr_usage - - core::ptr::write_volatile(core::ptr::null_mut(), A); - //~^ invalid_null_ptr_usage - - core::ptr::write_bytes::(core::ptr::null_mut(), 42, 0); - //~^ invalid_null_ptr_usage - } -} diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.stderr b/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.stderr deleted file mode 100644 index b5dd21ce6248..000000000000 --- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.stderr +++ /dev/null @@ -1,136 +0,0 @@ -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:16:60 - | -LL | let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::null(), 0); - | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - | - = note: `#[deny(clippy::invalid_null_ptr_usage)]` on by default - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:18:60 - | -LL | let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::null_mut(), 0); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:21:64 - | -LL | let _slice: &[usize] = core::slice::from_raw_parts_mut(core::ptr::null_mut(), 0); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:24:34 - | -LL | core::ptr::copy::(core::ptr::null(), core::ptr::NonNull::dangling().as_ptr(), 0); - | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:26:75 - | -LL | core::ptr::copy::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::null_mut(), 0); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:29:49 - | -LL | core::ptr::copy_nonoverlapping::(core::ptr::null(), core::ptr::NonNull::dangling().as_ptr(), 0); - | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:31:90 - | -LL | core::ptr::copy_nonoverlapping::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::null_mut(), 0); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:37:37 - | -LL | let _a: A = core::ptr::read(core::ptr::null()); - | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:39:37 - | -LL | let _a: A = core::ptr::read(core::ptr::null_mut()); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:42:47 - | -LL | let _a: A = core::ptr::read_unaligned(core::ptr::null()); - | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:44:47 - | -LL | let _a: A = core::ptr::read_unaligned(core::ptr::null_mut()); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:47:46 - | -LL | let _a: A = core::ptr::read_volatile(core::ptr::null()); - | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:49:46 - | -LL | let _a: A = core::ptr::read_volatile(core::ptr::null_mut()); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:52:40 - | -LL | let _a: A = core::ptr::replace(core::ptr::null_mut(), A); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:57:30 - | -LL | core::ptr::swap::(core::ptr::null_mut(), &mut A); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:59:38 - | -LL | core::ptr::swap::(&mut A, core::ptr::null_mut()); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:62:45 - | -LL | core::ptr::swap_nonoverlapping::(core::ptr::null_mut(), &mut A, 0); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:64:53 - | -LL | core::ptr::swap_nonoverlapping::(&mut A, core::ptr::null_mut(), 0); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:67:26 - | -LL | core::ptr::write(core::ptr::null_mut(), A); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:70:36 - | -LL | core::ptr::write_unaligned(core::ptr::null_mut(), A); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:73:35 - | -LL | core::ptr::write_volatile(core::ptr::null_mut(), A); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:76:41 - | -LL | core::ptr::write_bytes::(core::ptr::null_mut(), 42, 0); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: aborting due to 22 previous errors - diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed index 501811fa491b..796404706968 100644 --- a/src/tools/clippy/tests/ui/rename.fixed +++ b/src/tools/clippy/tests/ui/rename.fixed @@ -119,6 +119,7 @@ #![warn(invalid_atomic_ordering)] //~ ERROR: lint `clippy::invalid_atomic_ordering` #![warn(invalid_value)] //~ ERROR: lint `clippy::invalid_ref` #![warn(invalid_from_utf8_unchecked)] //~ ERROR: lint `clippy::invalid_utf8_in_unchecked` +#![warn(invalid_null_arguments)] //~ ERROR: lint `clippy::invalid_null_ptr_usage` #![warn(let_underscore_drop)] //~ ERROR: lint `clippy::let_underscore_drop` #![warn(unexpected_cfgs)] //~ ERROR: lint `clippy::maybe_misused_cfg` #![warn(enum_intrinsics_non_enums)] //~ ERROR: lint `clippy::mem_discriminant_non_enum` diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs index 7f4b8062e1b4..aa7b905b4b81 100644 --- a/src/tools/clippy/tests/ui/rename.rs +++ b/src/tools/clippy/tests/ui/rename.rs @@ -119,6 +119,7 @@ #![warn(clippy::invalid_atomic_ordering)] //~ ERROR: lint `clippy::invalid_atomic_ordering` #![warn(clippy::invalid_ref)] //~ ERROR: lint `clippy::invalid_ref` #![warn(clippy::invalid_utf8_in_unchecked)] //~ ERROR: lint `clippy::invalid_utf8_in_unchecked` +#![warn(clippy::invalid_null_ptr_usage)] //~ ERROR: lint `clippy::invalid_null_ptr_usage` #![warn(clippy::let_underscore_drop)] //~ ERROR: lint `clippy::let_underscore_drop` #![warn(clippy::maybe_misused_cfg)] //~ ERROR: lint `clippy::maybe_misused_cfg` #![warn(clippy::mem_discriminant_non_enum)] //~ ERROR: lint `clippy::mem_discriminant_non_enum` diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr index f24eaec3917a..b3c88167c111 100644 --- a/src/tools/clippy/tests/ui/rename.stderr +++ b/src/tools/clippy/tests/ui/rename.stderr @@ -343,71 +343,77 @@ error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_fro LL | #![warn(clippy::invalid_utf8_in_unchecked)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked` -error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop` +error: lint `clippy::invalid_null_ptr_usage` has been renamed to `invalid_null_arguments` --> tests/ui/rename.rs:122:9 | +LL | #![warn(clippy::invalid_null_ptr_usage)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_null_arguments` + +error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop` + --> tests/ui/rename.rs:123:9 + | LL | #![warn(clippy::let_underscore_drop)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop` error: lint `clippy::maybe_misused_cfg` has been renamed to `unexpected_cfgs` - --> tests/ui/rename.rs:123:9 + --> tests/ui/rename.rs:124:9 | LL | #![warn(clippy::maybe_misused_cfg)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs` error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums` - --> tests/ui/rename.rs:124:9 + --> tests/ui/rename.rs:125:9 | LL | #![warn(clippy::mem_discriminant_non_enum)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums` error: lint `clippy::mismatched_target_os` has been renamed to `unexpected_cfgs` - --> tests/ui/rename.rs:125:9 + --> tests/ui/rename.rs:126:9 | LL | #![warn(clippy::mismatched_target_os)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs` error: lint `clippy::panic_params` has been renamed to `non_fmt_panics` - --> tests/ui/rename.rs:126:9 + --> tests/ui/rename.rs:127:9 | LL | #![warn(clippy::panic_params)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics` error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally` - --> tests/ui/rename.rs:127:9 + --> tests/ui/rename.rs:128:9 | LL | #![warn(clippy::positional_named_format_parameters)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally` error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `dangling_pointers_from_temporaries` - --> tests/ui/rename.rs:128:9 + --> tests/ui/rename.rs:129:9 | LL | #![warn(clippy::temporary_cstring_as_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `dangling_pointers_from_temporaries` error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops` - --> tests/ui/rename.rs:129:9 + --> tests/ui/rename.rs:130:9 | LL | #![warn(clippy::undropped_manually_drops)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops` error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints` - --> tests/ui/rename.rs:130:9 + --> tests/ui/rename.rs:131:9 | LL | #![warn(clippy::unknown_clippy_lints)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints` error: lint `clippy::unused_label` has been renamed to `unused_labels` - --> tests/ui/rename.rs:131:9 + --> tests/ui/rename.rs:132:9 | LL | #![warn(clippy::unused_label)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels` error: lint `clippy::vtable_address_comparisons` has been renamed to `ambiguous_wide_pointer_comparisons` - --> tests/ui/rename.rs:132:9 + --> tests/ui/rename.rs:133:9 | LL | #![warn(clippy::vtable_address_comparisons)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `ambiguous_wide_pointer_comparisons` -error: aborting due to 68 previous errors +error: aborting due to 69 previous errors From aa8848040a160842d47a5a143e04da8ad9f27613 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 9 Mar 2025 22:23:31 +0100 Subject: [PATCH 676/745] Allow `invalid_null_arguments` in some tests --- tests/ui/precondition-checks/copy-nonoverlapping.rs | 2 ++ tests/ui/precondition-checks/copy.rs | 2 ++ tests/ui/precondition-checks/read_volatile.rs | 2 ++ tests/ui/precondition-checks/replace.rs | 2 ++ tests/ui/precondition-checks/slice-from-raw-parts-mut.rs | 2 ++ tests/ui/precondition-checks/slice-from-raw-parts.rs | 2 ++ tests/ui/precondition-checks/swap-nonoverlapping.rs | 2 ++ tests/ui/precondition-checks/write_volatile.rs | 2 ++ tests/ui/precondition-checks/zero-size-null.rs | 2 ++ 9 files changed, 18 insertions(+) diff --git a/tests/ui/precondition-checks/copy-nonoverlapping.rs b/tests/ui/precondition-checks/copy-nonoverlapping.rs index 81018e4bff3e..eacaa63e543a 100644 --- a/tests/ui/precondition-checks/copy-nonoverlapping.rs +++ b/tests/ui/precondition-checks/copy-nonoverlapping.rs @@ -3,6 +3,8 @@ //@ error-pattern: unsafe precondition(s) violated: ptr::copy_nonoverlapping requires //@ revisions: null_src null_dst misaligned_src misaligned_dst overlapping +#![allow(invalid_null_arguments)] + use std::ptr; fn main() { diff --git a/tests/ui/precondition-checks/copy.rs b/tests/ui/precondition-checks/copy.rs index 694853f950ab..1fadd90bf70b 100644 --- a/tests/ui/precondition-checks/copy.rs +++ b/tests/ui/precondition-checks/copy.rs @@ -3,6 +3,8 @@ //@ error-pattern: unsafe precondition(s) violated: ptr::copy requires //@ revisions: null_src null_dst misaligned_src misaligned_dst +#![allow(invalid_null_arguments)] + use std::ptr; fn main() { diff --git a/tests/ui/precondition-checks/read_volatile.rs b/tests/ui/precondition-checks/read_volatile.rs index e14881d02903..ada8932c398c 100644 --- a/tests/ui/precondition-checks/read_volatile.rs +++ b/tests/ui/precondition-checks/read_volatile.rs @@ -3,6 +3,8 @@ //@ error-pattern: unsafe precondition(s) violated: ptr::read_volatile requires //@ revisions: null misaligned +#![allow(invalid_null_arguments)] + use std::ptr; fn main() { diff --git a/tests/ui/precondition-checks/replace.rs b/tests/ui/precondition-checks/replace.rs index 2808cee7b64b..44afbd8174c0 100644 --- a/tests/ui/precondition-checks/replace.rs +++ b/tests/ui/precondition-checks/replace.rs @@ -3,6 +3,8 @@ //@ error-pattern: unsafe precondition(s) violated: ptr::replace requires //@ revisions: null misaligned +#![allow(invalid_null_arguments)] + use std::ptr; fn main() { diff --git a/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs b/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs index 3801639e2551..9b9ded69a83b 100644 --- a/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs +++ b/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs @@ -3,6 +3,8 @@ //@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts_mut requires //@ revisions: null misaligned toolarge +#![allow(invalid_null_arguments)] + fn main() { unsafe { #[cfg(null)] diff --git a/tests/ui/precondition-checks/slice-from-raw-parts.rs b/tests/ui/precondition-checks/slice-from-raw-parts.rs index a3690fa045eb..96578c1eae58 100644 --- a/tests/ui/precondition-checks/slice-from-raw-parts.rs +++ b/tests/ui/precondition-checks/slice-from-raw-parts.rs @@ -3,6 +3,8 @@ //@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts requires //@ revisions: null misaligned toolarge +#![allow(invalid_null_arguments)] + fn main() { unsafe { #[cfg(null)] diff --git a/tests/ui/precondition-checks/swap-nonoverlapping.rs b/tests/ui/precondition-checks/swap-nonoverlapping.rs index 52e4a3c870be..ea1f6f36ad78 100644 --- a/tests/ui/precondition-checks/swap-nonoverlapping.rs +++ b/tests/ui/precondition-checks/swap-nonoverlapping.rs @@ -3,6 +3,8 @@ //@ error-pattern: unsafe precondition(s) violated: ptr::swap_nonoverlapping requires //@ revisions: null_src null_dst misaligned_src misaligned_dst overlapping +#![allow(invalid_null_arguments)] + use std::ptr; fn main() { diff --git a/tests/ui/precondition-checks/write_volatile.rs b/tests/ui/precondition-checks/write_volatile.rs index ac0b89b5ecf2..0d5ecb014b3d 100644 --- a/tests/ui/precondition-checks/write_volatile.rs +++ b/tests/ui/precondition-checks/write_volatile.rs @@ -3,6 +3,8 @@ //@ error-pattern: unsafe precondition(s) violated: ptr::write_volatile requires //@ revisions: null misaligned +#![allow(invalid_null_arguments)] + use std::ptr; fn main() { diff --git a/tests/ui/precondition-checks/zero-size-null.rs b/tests/ui/precondition-checks/zero-size-null.rs index 43a81175f944..55d768fc9e58 100644 --- a/tests/ui/precondition-checks/zero-size-null.rs +++ b/tests/ui/precondition-checks/zero-size-null.rs @@ -7,8 +7,10 @@ use std::ptr; fn main() { unsafe { + #[expect(invalid_null_arguments)] // false-positive, copy of 0 ptr::copy_nonoverlapping::(ptr::null(), ptr::null_mut(), 0); ptr::copy_nonoverlapping::<()>(ptr::null(), ptr::null_mut(), 123); + #[expect(invalid_null_arguments)] // false-positive, copy of 0 ptr::copy::(ptr::null(), ptr::null_mut(), 0); ptr::copy::<()>(ptr::null(), ptr::null_mut(), 123); ptr::swap::<()>(ptr::null_mut(), ptr::null_mut()); From f3cbc3992e1428e92c608410614c3e7b7a64b815 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Sun, 30 Mar 2025 22:13:47 +0200 Subject: [PATCH 677/745] Remove duplicate c-variadic.md --- .../src/library-features/c-variadic.md | 26 ------------------- src/tools/tidy/src/unstable_book.rs | 12 ++++----- 2 files changed, 5 insertions(+), 33 deletions(-) delete mode 100644 src/doc/unstable-book/src/library-features/c-variadic.md diff --git a/src/doc/unstable-book/src/library-features/c-variadic.md b/src/doc/unstable-book/src/library-features/c-variadic.md deleted file mode 100644 index 77762116e6b1..000000000000 --- a/src/doc/unstable-book/src/library-features/c-variadic.md +++ /dev/null @@ -1,26 +0,0 @@ -# `c_variadic` - -The tracking issue for this feature is: [#44930] - -[#44930]: https://github.com/rust-lang/rust/issues/44930 - ------------------------- - -The `c_variadic` library feature exposes the `VaList` structure, -Rust's analogue of C's `va_list` type. - -## Examples - -```rust -#![feature(c_variadic)] - -use std::ffi::VaList; - -pub unsafe extern "C" fn vadd(n: usize, mut args: VaList) -> usize { - let mut sum = 0; - for _ in 0..n { - sum += args.arg::(); - } - sum -} -``` diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs index 8be25b98df0d..d19de081807d 100644 --- a/src/tools/tidy/src/unstable_book.rs +++ b/src/tools/tidy/src/unstable_book.rs @@ -93,14 +93,12 @@ pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) { // Check for Unstable Book sections that don't have a corresponding unstable feature for feature_name in &unstable_book_lib_features_section_file_names - &unstable_lib_feature_names { - if !unstable_lang_feature_names.contains(&feature_name) { - tidy_error!( - bad, - "The Unstable Book has a 'library feature' section '{}' which doesn't \ + tidy_error!( + bad, + "The Unstable Book has a 'library feature' section '{}' which doesn't \ correspond to an unstable library feature", - feature_name - ); - } + feature_name + ); } // Check for Unstable Book sections that don't have a corresponding unstable feature. From 14e4f9f245c615cd379397908abc52c795b65d04 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Sun, 30 Mar 2025 22:19:18 +0200 Subject: [PATCH 678/745] Suggest switching underscores for dashes --- src/tools/tidy/src/unstable_book.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs index d19de081807d..a2453a6c9605 100644 --- a/src/tools/tidy/src/unstable_book.rs +++ b/src/tools/tidy/src/unstable_book.rs @@ -72,6 +72,19 @@ fn collect_unstable_book_lib_features_section_file_names(base_src_path: &Path) - collect_unstable_book_section_file_names(&unstable_book_lib_features_path(base_src_path)) } +/// Would switching underscores for dashes work? +fn maybe_suggest_dashes(names: &BTreeSet, feature_name: &str, bad: &mut bool) { + let with_dashes = feature_name.replace('_', "-"); + if names.contains(&with_dashes) { + tidy_error!( + bad, + "the file `{}.md` contains underscores; use dashes instead: `{}.md`", + feature_name, + with_dashes, + ); + } +} + pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) { let lang_features = features.lang; let lib_features = features @@ -99,6 +112,7 @@ pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) { correspond to an unstable library feature", feature_name ); + maybe_suggest_dashes(&unstable_lib_feature_names, &feature_name, bad); } // Check for Unstable Book sections that don't have a corresponding unstable feature. @@ -110,7 +124,8 @@ pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) { "The Unstable Book has a 'language feature' section '{}' which doesn't \ correspond to an unstable language feature", feature_name - ) + ); + maybe_suggest_dashes(&unstable_lang_feature_names, &feature_name, bad); } // List unstable features that don't have Unstable Book sections. From 8a3ee9755245eccae6327c3f4cc658fe12615b18 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Sun, 30 Mar 2025 15:45:44 -0700 Subject: [PATCH 679/745] Apply suggestions from code review Co-authored-by: Mark Rousskov Co-authored-by: alexey semenyuk --- RELEASES.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 3047a0c366a4..0948eb85192e 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -5,7 +5,7 @@ Version 1.86.0 (2025-04-03) Language -------- -- [Stabilize the ability to upcast a trait object to one of its supertraits.](https://github.com/rust-lang/rust/pull/134367) +- [Stabilize upcasting trait objects to supertraits.](https://github.com/rust-lang/rust/pull/134367) - [Allow safe functions to be marked with the `#[target_feature]` attribute.](https://github.com/rust-lang/rust/pull/134090) - [The `missing_abi` lint now warns-by-default.](https://github.com/rust-lang/rust/pull/132397) - Rust now lints about double negations, to catch cases that might have intended to be a prefix decrement operator (`--x`) as written in other languages. This was previously a clippy lint, `clippy::double_neg`, and is [now available directly in Rust as `double_negations`.](https://github.com/rust-lang/rust/pull/126604) @@ -104,8 +104,9 @@ Compatibility Notes - [The `wasm_c_abi` future compatibility warning is now a hard error.](https://github.com/rust-lang/rust/pull/133951) Users of `wasm-bindgen` should upgrade to at least version 0.2.89, otherwise compilation will fail. - [Remove long-deprecated no-op attributes `#![no_start]` and `#![crate_id]`.](https://github.com/rust-lang/rust/pull/134300) -- The future incompatibility lint `cenum_impl_drop_cast` [has been made into a hard error.](https://github.com/rust-lang/rust/pull/135964) This means it is now an error to cast a field-less enum to an integer if the enum implements `Drop`. +- [The future incompatibility lint `cenum_impl_drop_cast` has been made into a hard error.](https://github.com/rust-lang/rust/pull/135964) This means it is now an error to cast a field-less enum to an integer if the enum implements `Drop`. - [SSE2 is now required for "i686" 32-bit x86 hard-float targets; disabling it causes a warning that will become a hard error eventually.](https://github.com/rust-lang/rust/pull/137037) + To compile for pre-SSE2 32-bit x86, use a "i586" target instead. @@ -117,7 +118,7 @@ significant improvements to the performance or internals of rustc and related tools. - [Build the rustc on AArch64 Linux with ThinLTO + PGO.](https://github.com/rust-lang/rust/pull/133807) -The ARM 64-bit compiler (AArch64) on Linux is now optimized with ThinLTO and PGO, similar to the optimizations we have already performed for the x86-64 compiler on Linux. This should make it up to 30% faster. + The ARM 64-bit compiler (AArch64) on Linux is now optimized with ThinLTO and PGO, similar to the optimizations we have already performed for the x86-64 compiler on Linux. This should make it up to 30% faster. Version 1.85.1 (2025-03-18) From 897acc3e5d3622927118924fa920c8be0ef6f154 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 30 Mar 2025 21:39:12 +0000 Subject: [PATCH 680/745] Encode synthetic by-move coroutine body with a different DefPathData --- compiler/rustc_hir/src/def.rs | 2 +- compiler/rustc_hir/src/definitions.rs | 15 +++++++++++++-- compiler/rustc_middle/src/ty/context.rs | 6 +++--- compiler/rustc_middle/src/ty/print/mod.rs | 7 +++++-- .../rustc_query_system/src/dep_graph/graph.rs | 7 ++++--- .../src/cfi/typeid/itanium_cxx_abi/encode.rs | 1 + compiler/rustc_symbol_mangling/src/legacy.rs | 5 ++++- compiler/rustc_symbol_mangling/src/v0.rs | 1 + tests/coverage/async_closure.cov-map | 18 +++++++++--------- tests/coverage/async_closure.coverage | 2 +- ...itten-closure-synthetic-closure-conflict.rs | 15 +++++++++++++++ ...-{closure#0}-{synthetic#0}.built.after.mir} | 4 ++-- .../async_closure_fake_read_for_by_move.rs | 2 +- ...-{closure#0}-{synthetic#0}.built.after.mir} | 4 ++-- ...-{closure#1}-{synthetic#0}.built.after.mir} | 4 ++-- tests/mir-opt/async_closure_shims.rs | 4 ++-- tests/ui/stable-mir-print/async-closure.stdout | 2 +- 17 files changed, 67 insertions(+), 32 deletions(-) create mode 100644 tests/incremental/user-written-closure-synthetic-closure-conflict.rs rename tests/mir-opt/{async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir => async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir} (85%) rename tests/mir-opt/{async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir => async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir} (80%) rename tests/mir-opt/{async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir => async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir} (80%) diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 5f8941d4754e..dc00b52a5936 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -294,7 +294,7 @@ impl DefKind { DefKind::GlobalAsm => DefPathData::GlobalAsm, DefKind::Impl { .. } => DefPathData::Impl, DefKind::Closure => DefPathData::Closure, - DefKind::SyntheticCoroutineBody => DefPathData::Closure, + DefKind::SyntheticCoroutineBody => DefPathData::SyntheticCoroutineBody, } } diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 61f5efd9978c..c52954aa96fc 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -291,6 +291,8 @@ pub enum DefPathData { /// An existential `impl Trait` type node. /// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name. OpaqueTy, + /// A synthetic body for a coroutine's by-move body. + SyntheticCoroutineBody, } impl Definitions { @@ -415,8 +417,16 @@ impl DefPathData { ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name), - Impl | ForeignMod | CrateRoot | Use | GlobalAsm | Closure | Ctor | AnonConst - | OpaqueTy => None, + Impl + | ForeignMod + | CrateRoot + | Use + | GlobalAsm + | Closure + | Ctor + | AnonConst + | OpaqueTy + | SyntheticCoroutineBody => None, } } @@ -441,6 +451,7 @@ impl DefPathData { Ctor => DefPathDataName::Anon { namespace: sym::constructor }, AnonConst => DefPathDataName::Anon { namespace: sym::constant }, OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque }, + SyntheticCoroutineBody => DefPathDataName::Anon { namespace: sym::synthetic }, } } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 08d4c1f9cf2f..618a65a01864 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1930,10 +1930,10 @@ impl<'tcx> TyCtxt<'tcx> { // As a consequence, this LocalDefId is always re-created before it is needed by the incr. // comp. engine itself. // - // This call also writes to the value of `source_span` and `expn_that_defined` queries. + // This call also writes to the value of the `source_span` query. // This is fine because: - // - those queries are `eval_always` so we won't miss their result changing; - // - this write will have happened before these queries are called. + // - that query is `eval_always` so we won't miss its result changing; + // - this write will have happened before that query is called. let def_id = self.untracked.definitions.write().create_def(parent, data); // This function modifies `self.definitions` using a side-effect. diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index dc2040aa5cf8..5904deaaaad8 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -139,8 +139,7 @@ pub trait Printer<'tcx>: Sized { match key.disambiguated_data.data { DefPathData::Closure => { - // FIXME(async_closures): This is somewhat ugly. - // We need to additionally print the `kind` field of a closure if + // We need to additionally print the `kind` field of a coroutine if // it is desugared from a coroutine-closure. if let Some(hir::CoroutineKind::Desugared( _, @@ -156,6 +155,10 @@ pub trait Printer<'tcx>: Sized { // Closures' own generics are only captures, don't print them. } } + DefPathData::SyntheticCoroutineBody => { + // Synthetic coroutine bodies have no distinct generics, since like + // closures they're all just internal state of the coroutine. + } // This covers both `DefKind::AnonConst` and `DefKind::InlineConst`. // Anon consts doesn't have their own generics, and inline consts' own // generics are their inferred types, so don't print them. diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 495f34733f70..127dcd825da5 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -66,6 +66,7 @@ pub struct MarkFrame<'a> { parent: Option<&'a MarkFrame<'a>>, } +#[derive(Debug)] pub(super) enum DepNodeColor { Red, Green(DepNodeIndex), @@ -909,7 +910,7 @@ impl DepGraphData { self.try_mark_previous_green(qcx, parent_dep_node_index, dep_dep_node, frame); if node_index.is_some() { - debug!("managed to MARK dependency {dep_dep_node:?} as green",); + debug!("managed to MARK dependency {dep_dep_node:?} as green"); return Some(()); } } @@ -930,7 +931,7 @@ impl DepGraphData { return Some(()); } Some(DepNodeColor::Red) => { - debug!("dependency {dep_dep_node:?} was red after forcing",); + debug!("dependency {dep_dep_node:?} was red after forcing"); return None; } None => {} @@ -950,7 +951,7 @@ impl DepGraphData { // invalid state will not be persisted to the // incremental compilation cache because of // compilation errors being present. - debug!("dependency {dep_dep_node:?} resulted in compilation error",); + debug!("dependency {dep_dep_node:?} resulted in compilation error"); return None; } diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index e088417d72e3..d56ca9c24538 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -716,6 +716,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String { hir::definitions::DefPathData::Ctor => "c", hir::definitions::DefPathData::AnonConst => "k", hir::definitions::DefPathData::OpaqueTy => "i", + hir::definitions::DefPathData::SyntheticCoroutineBody => "s", hir::definitions::DefPathData::CrateRoot | hir::definitions::DefPathData::Use | hir::definitions::DefPathData::GlobalAsm diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 88754f1f15b4..2802e8918073 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -28,7 +28,10 @@ pub(super) fn mangle<'tcx>( loop { let key = tcx.def_key(ty_def_id); match key.disambiguated_data.data { - DefPathData::TypeNs(_) | DefPathData::ValueNs(_) | DefPathData::Closure => { + DefPathData::TypeNs(_) + | DefPathData::ValueNs(_) + | DefPathData::Closure + | DefPathData::SyntheticCoroutineBody => { instance_ty = tcx.type_of(ty_def_id).instantiate_identity(); debug!(?instance_ty); break; diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index d824a23279b1..99d44bcd7eb8 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -850,6 +850,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { DefPathData::Ctor => 'c', DefPathData::AnonConst => 'k', DefPathData::OpaqueTy => 'i', + DefPathData::SyntheticCoroutineBody => 's', // These should never show up as `path_append` arguments. DefPathData::CrateRoot diff --git a/tests/coverage/async_closure.cov-map b/tests/coverage/async_closure.cov-map index 9144a938a9e2..0e1d98778307 100644 --- a/tests/coverage/async_closure.cov-map +++ b/tests/coverage/async_closure.cov-map @@ -38,6 +38,15 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36) Highest counter ID seen: c0 +Function name: async_closure::main::{closure#0} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 23, 00, 24] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36) +Highest counter ID seen: c0 + Function name: async_closure::main::{closure#0}::{closure#0}:: Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24] Number of files: 1 @@ -47,12 +56,3 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36) Highest counter ID seen: c0 -Function name: async_closure::main::{closure#0}::{closure#1}:: -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 23, 00, 24] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36) -Highest counter ID seen: c0 - diff --git a/tests/coverage/async_closure.coverage b/tests/coverage/async_closure.coverage index 7fbea2658125..10a8ea14504b 100644 --- a/tests/coverage/async_closure.coverage +++ b/tests/coverage/async_closure.coverage @@ -14,7 +14,7 @@ | async_closure::main::{closure#0}: | LL| 1| let async_closure = async || {}; ------------------ - | async_closure::main::{closure#0}::{closure#1}::: + | async_closure::main::{closure#0}: | LL| 1| let async_closure = async || {}; ------------------ LL| 1| executor::block_on(async_closure()); diff --git a/tests/incremental/user-written-closure-synthetic-closure-conflict.rs b/tests/incremental/user-written-closure-synthetic-closure-conflict.rs new file mode 100644 index 000000000000..618604d06b17 --- /dev/null +++ b/tests/incremental/user-written-closure-synthetic-closure-conflict.rs @@ -0,0 +1,15 @@ +//@ revisions: rpass1 rpass2 +//@ edition: 2024 + +#![allow(unused)] + +fn main() { + #[cfg(rpass1)] + async || {}; + + #[cfg(rpass2)] + || { + || (); + || (); + }; +} diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir similarity index 85% rename from tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir rename to tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir index bd0baddb1f89..9070c95bca4d 100644 --- a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir +++ b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir @@ -1,6 +1,6 @@ -// MIR for `foo::{closure#0}::{closure#1}` after built +// MIR for `foo::{closure#0}::{synthetic#0}` after built -fn foo::{closure#0}::{closure#1}(_1: {async closure body@$DIR/async_closure_fake_read_for_by_move.rs:12:27: 15:6}, _2: ResumeTy) -> () +fn foo::{closure#0}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_fake_read_for_by_move.rs:12:27: 15:6}, _2: ResumeTy) -> () yields () { debug _task_context => _2; diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.rs b/tests/mir-opt/async_closure_fake_read_for_by_move.rs index 3c5aec94bbfe..e78671f5e9d5 100644 --- a/tests/mir-opt/async_closure_fake_read_for_by_move.rs +++ b/tests/mir-opt/async_closure_fake_read_for_by_move.rs @@ -7,7 +7,7 @@ enum Foo { } // EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir -// EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir +// EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir fn foo(f: &Foo) { let x = async move || match f { Foo::Bar if true => {} diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir similarity index 80% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir rename to tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir index a9e08d2e8f60..c5f538e5ecd8 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir @@ -1,6 +1,6 @@ -// MIR for `main::{closure#0}::{closure#0}::{closure#1}` after built +// MIR for `main::{closure#0}::{closure#0}::{synthetic#0}` after built -fn main::{closure#0}::{closure#0}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> () +fn main::{closure#0}::{closure#0}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> () yields () { debug _task_context => _2; diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir similarity index 80% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir rename to tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir index 4452ae7812e3..e295f9b3cf12 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir @@ -1,6 +1,6 @@ -// MIR for `main::{closure#0}::{closure#1}::{closure#1}` after built +// MIR for `main::{closure#0}::{closure#1}::{synthetic#0}` after built -fn main::{closure#0}::{closure#1}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> () +fn main::{closure#0}::{closure#1}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> () yields () { debug _task_context => _2; diff --git a/tests/mir-opt/async_closure_shims.rs b/tests/mir-opt/async_closure_shims.rs index cd2e83e939ab..93cc7834a643 100644 --- a/tests/mir-opt/async_closure_shims.rs +++ b/tests/mir-opt/async_closure_shims.rs @@ -42,11 +42,11 @@ async fn call_normal_mut>(f: &mut impl FnMut(i32) -> F) { // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir -// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir +// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir -// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir +// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir pub fn main() { block_on(async { let b = 2i32; diff --git a/tests/ui/stable-mir-print/async-closure.stdout b/tests/ui/stable-mir-print/async-closure.stdout index 21df1fd39540..12e7a5530ace 100644 --- a/tests/ui/stable-mir-print/async-closure.stdout +++ b/tests/ui/stable-mir-print/async-closure.stdout @@ -56,7 +56,7 @@ fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async closure body@$DIR/async-clo unreachable; } } -fn foo::{closure#0}::{closure#1}(_1: Pin<&mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}>, _2: &mut Context<'_>) -> Poll<()> { +fn foo::{closure#0}::{synthetic#0}(_1: Pin<&mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}>, _2: &mut Context<'_>) -> Poll<()> { let mut _0: Poll<()>; let _3: i32; let mut _4: &i32; From 73d33ed1bafdf3c0b32e936492eb6a9cdd9b080c Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Mon, 31 Mar 2025 01:26:55 +0200 Subject: [PATCH 681/745] Remove mention of `exhaustive_patterns` from `never` docs --- library/core/src/primitive_docs.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 89c856fe1074..ba4c849837e7 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -127,15 +127,13 @@ mod prim_bool {} /// [`Result`] which we can unpack like this: /// /// ``` -/// #![feature(exhaustive_patterns)] /// use std::str::FromStr; /// let Ok(s) = String::from_str("hello"); /// ``` /// -/// Since the [`Err`] variant contains a `!`, it can never occur. If the `exhaustive_patterns` -/// feature is present this means we can exhaustively match on [`Result`] by just taking the -/// [`Ok`] variant. This illustrates another behavior of `!` - it can be used to "delete" certain -/// enum variants from generic types like `Result`. +/// Since the [`Err`] variant contains a `!`, it can never occur. This means we can exhaustively +/// match on [`Result`] by just taking the [`Ok`] variant. This illustrates another behavior +/// of `!` - it can be used to "delete" certain enum variants from generic types like `Result`. /// /// ## Infinite loops /// From 0666b740e5fd06f682a9a8d539b6ea3bb1d56538 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 14 Jan 2025 14:49:58 +0000 Subject: [PATCH 682/745] Simplify find_commandline_library --- compiler/rustc_metadata/src/locator.rs | 44 ++++++++++---------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index d5dd5059aacc..038236827489 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -728,37 +728,25 @@ impl<'a> CrateLocator<'a> { let Some(file) = loc_orig.file_name().and_then(|s| s.to_str()) else { return Err(CrateError::ExternLocationNotFile(self.crate_name, loc_orig.clone())); }; - // FnMut cannot return reference to captured value, so references - // must be taken outside the closure. - let rlibs = &mut rlibs; - let rmetas = &mut rmetas; - let dylibs = &mut dylibs; - let type_via_filename = (|| { - if file.starts_with("lib") { - if file.ends_with(".rlib") { - return Some(rlibs); - } - if file.ends_with(".rmeta") { - return Some(rmetas); - } + if file.starts_with("lib") { + if file.ends_with(".rlib") { + rlibs.insert(loc_canon.clone(), PathKind::ExternFlag); + continue; } - let dll_prefix = self.target.dll_prefix.as_ref(); - let dll_suffix = self.target.dll_suffix.as_ref(); - if file.starts_with(dll_prefix) && file.ends_with(dll_suffix) { - return Some(dylibs); - } - None - })(); - match type_via_filename { - Some(type_via_filename) => { - type_via_filename.insert(loc_canon.clone(), PathKind::ExternFlag); - } - None => { - self.crate_rejections - .via_filename - .push(CrateMismatch { path: loc_orig.clone(), got: String::new() }); + if file.ends_with(".rmeta") { + rmetas.insert(loc_canon.clone(), PathKind::ExternFlag); + continue; } } + let dll_prefix = self.target.dll_prefix.as_ref(); + let dll_suffix = self.target.dll_suffix.as_ref(); + if file.starts_with(dll_prefix) && file.ends_with(dll_suffix) { + dylibs.insert(loc_canon.clone(), PathKind::ExternFlag); + continue; + } + self.crate_rejections + .via_filename + .push(CrateMismatch { path: loc_orig.clone(), got: String::new() }); } // Extract the dylib/rlib/rmeta triple. From 9800eb2cabd962ff1899e94841b15ca9dc874528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 20 Feb 2025 21:23:10 +0100 Subject: [PATCH 683/745] Add `-Zembed-metadata` CLI option --- compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_session/src/options.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index b44be1710edf..4592e0144388 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -787,6 +787,7 @@ fn test_unstable_options_tracking_hash() { tracked!(direct_access_external_data, Some(true)); tracked!(dual_proc_macros, true); tracked!(dwarf_version, Some(5)); + tracked!(embed_metadata, false); tracked!(embed_source, true); tracked!(emit_thin_lto, false); tracked!(emscripten_wasm_eh, true); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 4cc666b3e37d..cd5e2c4173e7 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2175,6 +2175,8 @@ options! { them only if an error has not been emitted"), ehcont_guard: bool = (false, parse_bool, [TRACKED], "generate Windows EHCont Guard tables"), + embed_metadata: bool = (true, parse_bool, [TRACKED], + "embed metadata in rlibs and dylibs (default: yes)"), embed_source: bool = (false, parse_bool, [TRACKED], "embed source text in DWARF debug sections (default: no)"), emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED], From a5057b786b1f6fd04c4b590ea7eb160e36c281db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 20 Feb 2025 21:34:11 +0100 Subject: [PATCH 684/745] Add documentation of the option into the unstable book --- src/doc/unstable-book/src/compiler-flags/embed-metadata.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/doc/unstable-book/src/compiler-flags/embed-metadata.md diff --git a/src/doc/unstable-book/src/compiler-flags/embed-metadata.md b/src/doc/unstable-book/src/compiler-flags/embed-metadata.md new file mode 100644 index 000000000000..a2a790ee76af --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/embed-metadata.md @@ -0,0 +1,3 @@ +## `embed-metadata` + +This option instructs `rustc` to include the full metadata in `rlib` and `dylib` crate types. The default value is `yes` (enabled). If disabled (`no`), only stub metadata will be stored in these files, to reduce their size on disk. When using `-Zembed-metadata=no`, you will probably want to use `--emit=metadata` to produce the full metadata into a separate `.rmeta` file. From 4dca28cfa27661e0d87f9de23761445cac62d2d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 28 Mar 2025 17:58:23 +0100 Subject: [PATCH 685/745] Store only a metadata stub into `rlibs` and `dylibs` with `-Zembed-metadata=no` --- compiler/rustc_codegen_ssa/src/back/link.rs | 2 +- .../rustc_codegen_ssa/src/back/metadata.rs | 4 +- compiler/rustc_metadata/src/fs.rs | 26 ++++-- compiler/rustc_metadata/src/rmeta/encoder.rs | 91 +++++++++++++++---- compiler/rustc_metadata/src/rmeta/mod.rs | 6 ++ 5 files changed, 101 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index b59d73a9aae0..7d4110872417 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -294,7 +294,7 @@ fn link_rlib<'a>( let (metadata, metadata_position) = create_wrapper_file( sess, ".rmeta".to_string(), - codegen_results.metadata.raw_data(), + codegen_results.metadata.stub_or_full(), ); let metadata = emit_wrapper_file(sess, &metadata, tmpdir, METADATA_FILENAME); match metadata_position { diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 68b453ff4242..ac9ac9bbb31f 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -540,8 +540,8 @@ pub fn create_compressed_metadata_file( symbol_name: &str, ) -> Vec { let mut packed_metadata = rustc_metadata::METADATA_HEADER.to_vec(); - packed_metadata.write_all(&(metadata.raw_data().len() as u64).to_le_bytes()).unwrap(); - packed_metadata.extend(metadata.raw_data()); + packed_metadata.write_all(&(metadata.stub_or_full().len() as u64).to_le_bytes()).unwrap(); + packed_metadata.extend(metadata.stub_or_full()); let Some(mut file) = create_object_file(sess) else { if sess.target.is_like_wasm { diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index 4450d050c8e1..c4e1e0f1d1a9 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -3,7 +3,7 @@ use std::{fs, io}; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_middle::ty::TyCtxt; -use rustc_session::config::{OutFileName, OutputType}; +use rustc_session::config::{CrateType, OutFileName, OutputType}; use rustc_session::output::filename_for_metadata; use rustc_session::{MetadataKind, Session}; use tempfile::Builder as TempFileBuilder; @@ -50,7 +50,14 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) { .tempdir_in(out_filename.parent().unwrap_or_else(|| Path::new(""))) .unwrap_or_else(|err| tcx.dcx().emit_fatal(FailedCreateTempdir { err })); let metadata_tmpdir = MaybeTempDir::new(metadata_tmpdir, tcx.sess.opts.cg.save_temps); - let metadata_filename = metadata_tmpdir.as_ref().join(METADATA_FILENAME); + let metadata_filename = metadata_tmpdir.as_ref().join("full.rmeta"); + let metadata_stub_filename = if !tcx.sess.opts.unstable_opts.embed_metadata + && !tcx.crate_types().contains(&CrateType::ProcMacro) + { + Some(metadata_tmpdir.as_ref().join("stub.rmeta")) + } else { + None + }; // Always create a file at `metadata_filename`, even if we have nothing to write to it. // This simplifies the creation of the output `out_filename` when requested. @@ -60,9 +67,15 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) { std::fs::File::create(&metadata_filename).unwrap_or_else(|err| { tcx.dcx().emit_fatal(FailedCreateFile { filename: &metadata_filename, err }); }); + if let Some(metadata_stub_filename) = &metadata_stub_filename { + std::fs::File::create(metadata_stub_filename).unwrap_or_else(|err| { + tcx.dcx() + .emit_fatal(FailedCreateFile { filename: &metadata_stub_filename, err }); + }); + } } MetadataKind::Uncompressed | MetadataKind::Compressed => { - encode_metadata(tcx, &metadata_filename); + encode_metadata(tcx, &metadata_filename, metadata_stub_filename.as_deref()) } }; @@ -100,9 +113,10 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) { // Load metadata back to memory: codegen may need to include it in object files. let metadata = - EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|err| { - tcx.dcx().emit_fatal(FailedCreateEncodedMetadata { err }); - }); + EncodedMetadata::from_path(metadata_filename, metadata_stub_filename, metadata_tmpdir) + .unwrap_or_else(|err| { + tcx.dcx().emit_fatal(FailedCreateEncodedMetadata { err }); + }); let need_metadata_module = metadata_kind == MetadataKind::Compressed; diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 7ab3d432bdf8..386d3d3156a1 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -701,6 +701,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { triple: tcx.sess.opts.target_triple.clone(), hash: tcx.crate_hash(LOCAL_CRATE), is_proc_macro_crate: proc_macro_data.is_some(), + is_stub: false, }, extra_filename: tcx.sess.opts.cg.extra_filename.clone(), stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(), @@ -2231,8 +2232,12 @@ fn prefetch_mir(tcx: TyCtxt<'_>) { // generated regardless of trailing bytes that end up in it. pub struct EncodedMetadata { - // The declaration order matters because `mmap` should be dropped before `_temp_dir`. - mmap: Option, + // The declaration order matters because `full_metadata` should be dropped + // before `_temp_dir`. + full_metadata: Option, + // This is an optional stub metadata containing only the crate header. + // The header should be very small, so we load it directly into memory. + stub_metadata: Option>, // We need to carry MaybeTempDir to avoid deleting the temporary // directory while accessing the Mmap. _temp_dir: Option, @@ -2240,33 +2245,50 @@ pub struct EncodedMetadata { impl EncodedMetadata { #[inline] - pub fn from_path(path: PathBuf, temp_dir: Option) -> std::io::Result { + pub fn from_path( + path: PathBuf, + stub_path: Option, + temp_dir: Option, + ) -> std::io::Result { let file = std::fs::File::open(&path)?; let file_metadata = file.metadata()?; if file_metadata.len() == 0 { - return Ok(Self { mmap: None, _temp_dir: None }); + return Ok(Self { full_metadata: None, stub_metadata: None, _temp_dir: None }); } - let mmap = unsafe { Some(Mmap::map(file)?) }; - Ok(Self { mmap, _temp_dir: temp_dir }) + let full_mmap = unsafe { Some(Mmap::map(file)?) }; + + let stub = + if let Some(stub_path) = stub_path { Some(std::fs::read(stub_path)?) } else { None }; + + Ok(Self { full_metadata: full_mmap, stub_metadata: stub, _temp_dir: temp_dir }) } #[inline] - pub fn raw_data(&self) -> &[u8] { - self.mmap.as_deref().unwrap_or_default() + pub fn full(&self) -> &[u8] { + &self.full_metadata.as_deref().unwrap_or_default() + } + + #[inline] + pub fn stub_or_full(&self) -> &[u8] { + self.stub_metadata.as_deref().unwrap_or(self.full()) } } impl Encodable for EncodedMetadata { fn encode(&self, s: &mut S) { - let slice = self.raw_data(); + self.stub_metadata.encode(s); + + let slice = self.full(); slice.encode(s) } } impl Decodable for EncodedMetadata { fn decode(d: &mut D) -> Self { + let stub = >>::decode(d); + let len = d.read_usize(); - let mmap = if len > 0 { + let full_metadata = if len > 0 { let mut mmap = MmapMut::map_anon(len).unwrap(); mmap.copy_from_slice(d.read_raw_bytes(len)); Some(mmap.make_read_only().unwrap()) @@ -2274,11 +2296,11 @@ impl Decodable for EncodedMetadata { None }; - Self { mmap, _temp_dir: None } + Self { full_metadata, stub_metadata: stub, _temp_dir: None } } } -pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) { +pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) { let _prof_timer = tcx.prof.verbose_generic_activity("generate_crate_metadata"); // Since encoding metadata is not in a query, and nothing is cached, @@ -2292,6 +2314,42 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) { join(|| prefetch_mir(tcx), || tcx.exported_symbols(LOCAL_CRATE)); } + with_encode_metadata_header(tcx, path, |ecx| { + // Encode all the entries and extra information in the crate, + // culminating in the `CrateRoot` which points to all of it. + let root = ecx.encode_crate_root(); + + // Flush buffer to ensure backing file has the correct size. + ecx.opaque.flush(); + // Record metadata size for self-profiling + tcx.prof.artifact_size( + "crate_metadata", + "crate_metadata", + ecx.opaque.file().metadata().unwrap().len(), + ); + + root.position.get() + }); + + if let Some(ref_path) = ref_path { + with_encode_metadata_header(tcx, ref_path, |ecx| { + let header: LazyValue = ecx.lazy(CrateHeader { + name: tcx.crate_name(LOCAL_CRATE), + triple: tcx.sess.opts.target_triple.clone(), + hash: tcx.crate_hash(LOCAL_CRATE), + is_proc_macro_crate: false, + is_stub: true, + }); + header.position.get() + }); + } +} + +fn with_encode_metadata_header( + tcx: TyCtxt<'_>, + path: &Path, + f: impl FnOnce(&mut EncodeContext<'_, '_>) -> usize, +) { let mut encoder = opaque::FileEncoder::new(path) .unwrap_or_else(|err| tcx.dcx().emit_fatal(FailCreateFileEncoder { err })); encoder.emit_raw_bytes(METADATA_HEADER); @@ -2326,9 +2384,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) { // Encode the rustc version string in a predictable location. rustc_version(tcx.sess.cfg_version).encode(&mut ecx); - // Encode all the entries and extra information in the crate, - // culminating in the `CrateRoot` which points to all of it. - let root = ecx.encode_crate_root(); + let root_position = f(&mut ecx); // Make sure we report any errors from writing to the file. // If we forget this, compilation can succeed with an incomplete rmeta file, @@ -2338,12 +2394,9 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) { } let file = ecx.opaque.file(); - if let Err(err) = encode_root_position(file, root.position.get()) { + if let Err(err) = encode_root_position(file, root_position) { tcx.dcx().emit_fatal(FailWriteFile { path: ecx.opaque.path(), err }); } - - // Record metadata size for self-profiling - tcx.prof.artifact_size("crate_metadata", "crate_metadata", file.metadata().unwrap().len()); } fn encode_root_position(mut file: &File, pos: usize) -> Result<(), std::io::Error> { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index dc453b1e747c..bbdc986ef7a2 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -221,6 +221,12 @@ pub(crate) struct CrateHeader { /// This is separate from [`ProcMacroData`] to avoid having to update [`METADATA_VERSION`] every /// time ProcMacroData changes. pub(crate) is_proc_macro_crate: bool, + /// Whether this crate metadata section is just a stub. + /// Stubs do not contain the full metadata (it will be typically stored + /// in a separate rmeta file). + /// + /// This is used inside rlibs and dylibs when using `-Zembed-metadata=no`. + pub(crate) is_stub: bool, } /// Serialized `.rmeta` data for a crate. From 674a7adf9bd765354f58c50f3632f3410a6ac9f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 14 Mar 2025 11:45:22 +0100 Subject: [PATCH 686/745] Add an error when full metadata was not found --- compiler/rustc_metadata/messages.ftl | 4 ++++ compiler/rustc_metadata/src/errors.rs | 9 +++++++++ compiler/rustc_metadata/src/locator.rs | 23 ++++++++++++++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index 9adbcabcf450..d997ba198aca 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -97,6 +97,10 @@ metadata_found_staticlib = found staticlib `{$crate_name}` instead of rlib or dylib{$add_info} .help = please recompile that crate using --crate-type lib +metadata_full_metadata_not_found = + only metadata stub found for `{$flavor}` dependency `{$crate_name}` + please provide path to the corresponding .rmeta file with full metadata + metadata_global_alloc_required = no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 0c54628598c4..c45daeda85db 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -525,6 +525,15 @@ impl Diagnostic<'_, G> for MultipleCandidates { } } +#[derive(Diagnostic)] +#[diag(metadata_full_metadata_not_found)] +pub(crate) struct FullMetadataNotFound { + #[primary_span] + pub span: Span, + pub flavor: CrateFlavor, + pub crate_name: Symbol, +} + #[derive(Diagnostic)] #[diag(metadata_symbol_conflicts_current, code = E0519)] pub struct SymbolConflictsCurrent { diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 038236827489..112954eca0df 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -654,7 +654,24 @@ impl<'a> CrateLocator<'a> { continue; } } - *slot = Some((hash, metadata, lib.clone())); + + // We error eagerly here. If we're locating a rlib, then in theory the full metadata + // could still be in a (later resolved) dylib. In practice, if the rlib and dylib + // were produced in a way where one has full metadata and the other hasn't, it would + // mean that they were compiled using different compiler flags and probably also have + // a different SVH value. + if metadata.get_header().is_stub { + // `is_stub` should never be true for .rmeta files. + assert_ne!(flavor, CrateFlavor::Rmeta); + + // Because rmeta files are resolved before rlib/dylib files, if this is a stub and + // we haven't found a slot already, it means that the full metadata is missing. + if slot.is_none() { + return Err(CrateError::FullMetadataNotFound(self.crate_name, flavor)); + } + } else { + *slot = Some((hash, metadata, lib.clone())); + } ret = Some((lib, kind)); } @@ -916,6 +933,7 @@ pub(crate) enum CrateError { ExternLocationNotExist(Symbol, PathBuf), ExternLocationNotFile(Symbol, PathBuf), MultipleCandidates(Symbol, CrateFlavor, Vec), + FullMetadataNotFound(Symbol, CrateFlavor), SymbolConflictsCurrent(Symbol), StableCrateIdCollision(Symbol, Symbol), DlOpen(String, String), @@ -966,6 +984,9 @@ impl CrateError { CrateError::MultipleCandidates(crate_name, flavor, candidates) => { dcx.emit_err(errors::MultipleCandidates { span, crate_name, flavor, candidates }); } + CrateError::FullMetadataNotFound(crate_name, flavor) => { + dcx.emit_err(errors::FullMetadataNotFound { span, crate_name, flavor }); + } CrateError::SymbolConflictsCurrent(root_name) => { dcx.emit_err(errors::SymbolConflictsCurrent { span, crate_name: root_name }); } From 5a71da56d88b52a89b24dd64dad4421994a7a39b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 14 Mar 2025 11:45:25 +0100 Subject: [PATCH 687/745] Add tests --- tests/run-make/embed-metadata/dep1.rs | 1 + tests/run-make/embed-metadata/foo.rs | 5 ++ tests/run-make/embed-metadata/rmake.rs | 86 ++++++++++++++++++++++++++ 3 files changed, 92 insertions(+) create mode 100644 tests/run-make/embed-metadata/dep1.rs create mode 100644 tests/run-make/embed-metadata/foo.rs create mode 100644 tests/run-make/embed-metadata/rmake.rs diff --git a/tests/run-make/embed-metadata/dep1.rs b/tests/run-make/embed-metadata/dep1.rs new file mode 100644 index 000000000000..be70c3933e09 --- /dev/null +++ b/tests/run-make/embed-metadata/dep1.rs @@ -0,0 +1 @@ +pub fn func_dep1() {} diff --git a/tests/run-make/embed-metadata/foo.rs b/tests/run-make/embed-metadata/foo.rs new file mode 100644 index 000000000000..0cc9cede8608 --- /dev/null +++ b/tests/run-make/embed-metadata/foo.rs @@ -0,0 +1,5 @@ +extern crate dep1; + +fn main() { + dep1::func_dep1(); +} diff --git a/tests/run-make/embed-metadata/rmake.rs b/tests/run-make/embed-metadata/rmake.rs new file mode 100644 index 000000000000..acefb1864844 --- /dev/null +++ b/tests/run-make/embed-metadata/rmake.rs @@ -0,0 +1,86 @@ +// Tests the -Zembed-metadata compiler flag. +// Tracking issue: https://github.com/rust-lang/rust/issues/139165 + +use run_make_support::rfs::{create_dir, remove_file, rename}; +use run_make_support::{Rustc, dynamic_lib_name, path, run_in_tmpdir, rust_lib_name, rustc}; + +#[derive(Debug, Copy, Clone)] +enum LibraryKind { + Rlib, + Dylib, +} + +impl LibraryKind { + fn crate_type(&self) -> &str { + match self { + LibraryKind::Rlib => "rlib", + LibraryKind::Dylib => "dylib", + } + } + + fn add_extern(&self, rustc: &mut Rustc, dep_name: &str, dep_path: &str) { + let dep_path = match self { + LibraryKind::Dylib => format!("{dep_path}/{}", dynamic_lib_name(dep_name)), + LibraryKind::Rlib => format!("{dep_path}/{}", rust_lib_name(dep_name)), + }; + rustc.extern_(dep_name, dep_path); + } +} + +fn main() { + // The compiler takes different paths based on if --extern is passed or not, so we test all + // combinations (`rlib`/`dylib` x `--extern`/`no --extern`). + for kind in [LibraryKind::Rlib, LibraryKind::Dylib] { + eprintln!("Testing library kind {kind:?}"); + lookup_rmeta_in_lib_dir(kind); + lookup_rmeta_through_extern(kind); + lookup_rmeta_missing(kind); + } +} + +// Lookup .rmeta file in the same directory as a rlib/dylib with stub metadata. +fn lookup_rmeta_in_lib_dir(kind: LibraryKind) { + run_in_tmpdir(|| { + build_dep_rustc(kind).run(); + rustc().input("foo.rs").run(); + }); +} + +// Lookup .rmeta file when specifying the dependency using --extern. +fn lookup_rmeta_through_extern(kind: LibraryKind) { + run_in_tmpdir(|| { + // Generate libdep1.rlib and libdep1.rmeta in deps + create_dir("deps"); + build_dep_rustc(kind).out_dir("deps").run(); + + let mut rustc = rustc(); + kind.add_extern(&mut rustc, "dep1", "deps"); + rustc.extern_("dep1", path("deps").join("libdep1.rmeta")); + rustc.input("foo.rs").run(); + }); +} + +// Check the error message when the .rmeta file is missing. +fn lookup_rmeta_missing(kind: LibraryKind) { + run_in_tmpdir(|| { + create_dir("deps"); + build_dep_rustc(kind).out_dir("deps").run(); + + let mut rustc = rustc(); + kind.add_extern(&mut rustc, "dep1", "deps"); + rustc.input("foo.rs").run_fail().assert_stderr_contains("only metadata stub found"); + }); +} + +fn build_dep_rustc(kind: LibraryKind) -> Rustc { + let mut dep_rustc = rustc(); + dep_rustc + .arg("-Zembed-metadata=no") + .crate_type(kind.crate_type()) + .input("dep1.rs") + .emit("metadata,link"); + if matches!(kind, LibraryKind::Dylib) { + dep_rustc.arg("-Cprefer-dynamic"); + } + dep_rustc +} From 53f4397bd9c6b83936725fcf8d640be231c6facd Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Mon, 31 Mar 2025 11:01:46 +0100 Subject: [PATCH 688/745] Remove Amanieu from the libs review rotation --- triagebot.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 217da9935383..3e7a441c4532 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1161,7 +1161,6 @@ compiler = [ ] libs = [ "@Mark-Simulacrum", - "@Amanieu", "@Noratrieb", "@workingjubilee", "@joboet", From 4e99dca8c35b37fcf097e7bd3c2b00abb7a64dfb Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 31 Mar 2025 15:37:16 +0200 Subject: [PATCH 689/745] Remove fragile equal-pointers-unequal/*/print3.rs tests. --- .../equal-pointers-unequal/as-cast/print3.rs | 23 ----------------- .../exposed-provenance/print3.rs | 25 ------------------- .../strict-provenance/print3.rs | 25 ------------------- 3 files changed, 73 deletions(-) delete mode 100644 tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs delete mode 100644 tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs delete mode 100644 tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs deleted file mode 100644 index eda83e999a52..000000000000 --- a/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs +++ /dev/null @@ -1,23 +0,0 @@ -//@ known-bug: #107975 -//@ compile-flags: -Copt-level=2 -//@ run-pass - -// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499 - -fn main() { - let a = { - let v = 0; - &v as *const _ as usize - }; - let b = { - let v = 0; - &v as *const _ as usize - }; - - assert_ne!(a, b); - assert_ne!(a, b); - let c = a; - assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "false true false"); - println!("{a} {b}"); - assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "true true true"); -} diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs deleted file mode 100644 index c7f46318aaef..000000000000 --- a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs +++ /dev/null @@ -1,25 +0,0 @@ -//@ known-bug: #107975 -//@ compile-flags: -Copt-level=2 -//@ run-pass - -// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499 - -use std::ptr; - -fn main() { - let a: usize = { - let v = 0; - ptr::from_ref(&v).expose_provenance() - }; - let b: usize = { - let v = 0; - ptr::from_ref(&v).expose_provenance() - }; - - assert_ne!(a, b); - assert_ne!(a, b); - let c = a; - assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "false true false"); - println!("{a} {b}"); - assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "true true true"); -} diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs deleted file mode 100644 index a02ff30918da..000000000000 --- a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs +++ /dev/null @@ -1,25 +0,0 @@ -//@ known-bug: #107975 -//@ compile-flags: -Copt-level=2 -//@ run-pass - -// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499 - -use std::ptr; - -fn main() { - let a: usize = { - let v = 0; - ptr::from_ref(&v).addr() - }; - let b: usize = { - let v = 0; - ptr::from_ref(&v).addr() - }; - - assert_ne!(a, b); - assert_ne!(a, b); - let c = a; - assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "false true false"); - println!("{a} {b}"); - assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "true true true"); -} From dea947212795fb4fcdef2b2351008d08be3fb854 Mon Sep 17 00:00:00 2001 From: reez12g Date: Sun, 30 Mar 2025 17:53:19 +0900 Subject: [PATCH 690/745] Add tests for LLVM 20 slice bounds check optimization --- .../slice-last-elements-optimization.rs | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 tests/codegen/slice-last-elements-optimization.rs diff --git a/tests/codegen/slice-last-elements-optimization.rs b/tests/codegen/slice-last-elements-optimization.rs new file mode 100644 index 000000000000..b90f91d7b17b --- /dev/null +++ b/tests/codegen/slice-last-elements-optimization.rs @@ -0,0 +1,37 @@ +//@ compile-flags: -Copt-level=3 +//@ only-x86_64 +//@ min-llvm-version: 20 +#![crate_type = "lib"] + +// This test verifies that LLVM 20 properly optimizes the bounds check +// when accessing the last few elements of a slice with proper conditions. +// Previously, this would generate an unreachable branch to +// slice_start_index_len_fail even when the bounds check was provably safe. + +// CHECK-LABEL: @last_four_initial( +#[no_mangle] +pub fn last_four_initial(s: &[u8]) -> &[u8] { + // Previously this would generate a branch to slice_start_index_len_fail + // that is unreachable. The LLVM 20 fix should eliminate this branch. + // CHECK-NOT: slice_start_index_len_fail + // CHECK-NOT: unreachable + let start = if s.len() <= 4 { 0 } else { s.len() - 4 }; + &s[start..] +} + +// CHECK-LABEL: @last_four_optimized( +#[no_mangle] +pub fn last_four_optimized(s: &[u8]) -> &[u8] { + // This version was already correctly optimized before the fix in LLVM 20. + // CHECK-NOT: slice_start_index_len_fail + // CHECK-NOT: unreachable + if s.len() <= 4 { &s[0..] } else { &s[s.len() - 4..] } +} + +// Just to verify we're correctly checking for the right thing +// CHECK-LABEL: @test_bounds_check_happens( +#[no_mangle] +pub fn test_bounds_check_happens(s: &[u8], i: usize) -> &[u8] { + // CHECK: slice_start_index_len_fail + &s[i..] +} From 3ef1a3f1c5775357c6192584a42bb6469c1f51b8 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Mon, 31 Mar 2025 16:10:02 +0000 Subject: [PATCH 691/745] Remove ChrisDenton from on vacation --- triagebot.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 217da9935383..47a8c588ad9e 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1124,7 +1124,6 @@ warn_non_default_branch.enable = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" users_on_vacation = [ "jyn514", - "ChrisDenton", "saethlin", ] From 753968162a423d5a63ca86ef509d4aaf18ac1f9a Mon Sep 17 00:00:00 2001 From: tiif Date: Mon, 31 Mar 2025 16:42:01 +0000 Subject: [PATCH 692/745] Fix invalid link --- compiler/rustc_middle/src/ty/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ac98cbc8d6cb..0ffaef82f1c8 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -953,7 +953,7 @@ impl<'tcx> rustc_type_ir::Flags for Clauses<'tcx> { /// environment. `ParamEnv` is the type that represents this information. See the /// [dev guide chapter][param_env_guide] for more information. /// -/// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/param_env/param_env_summary.html +/// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/typing_parameter_envs.html #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] #[derive(HashStable, TypeVisitable, TypeFoldable)] pub struct ParamEnv<'tcx> { @@ -977,7 +977,7 @@ impl<'tcx> ParamEnv<'tcx> { /// to use an empty environment. See the [dev guide section][param_env_guide] /// for information on what a `ParamEnv` is and how to acquire one. /// - /// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/param_env/param_env_summary.html + /// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/typing_parameter_envs.html #[inline] pub fn empty() -> Self { Self::new(ListWithCachedTypeInfo::empty()) From b14a0ce7f6b9b72d3495fc9b0d632fd14400dcec Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Mon, 31 Mar 2025 14:34:14 -0400 Subject: [PATCH 693/745] PassWrapper: adapt for llvm/llvm-project@94122d58fc77079a291a3d008914006cb509d9db We also have to remove the LLVM argument in cast-target-abi.rs for LLVM 21. I'm not really sure what the best approach here is since that test already uses revisions. We could also fork the test into a copy for LLVM 19-20 and another for LLVM 21, but what I did for now was drop the lint-abort-on-error flag to LLVM figuring that some coverage was better than none, but I'm happy to change this if that was a bad direction. The above also applies for ffi-out-of-bounds-loads.rs. r? dianqk @rustbot label llvm-main --- compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 13 +++++++++---- tests/codegen/cast-target-abi.rs | 2 +- tests/codegen/cffi/ffi-out-of-bounds-loads.rs | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 86f1bcc46eea..257bdc01993f 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -855,10 +855,15 @@ extern "C" LLVMRustResult LLVMRustOptimize( } if (LintIR) { - PipelineStartEPCallbacks.push_back( - [](ModulePassManager &MPM, OptimizationLevel Level) { - MPM.addPass(createModuleToFunctionPassAdaptor(LintPass())); - }); + PipelineStartEPCallbacks.push_back([](ModulePassManager &MPM, + OptimizationLevel Level) { +#if LLVM_VERSION_GE(21, 0) + MPM.addPass( + createModuleToFunctionPassAdaptor(LintPass(/*AbortOnError=*/true))); +#else + MPM.addPass(createModuleToFunctionPassAdaptor(LintPass())); +#endif + }); } if (InstrumentCoverage) { diff --git a/tests/codegen/cast-target-abi.rs b/tests/codegen/cast-target-abi.rs index 186198bc631e..e1a7ad718a06 100644 --- a/tests/codegen/cast-target-abi.rs +++ b/tests/codegen/cast-target-abi.rs @@ -2,7 +2,7 @@ //@ add-core-stubs //@ revisions:aarch64 loongarch64 powerpc64 sparc64 x86_64 //@ min-llvm-version: 19 -//@ compile-flags: -Copt-level=3 -Cno-prepopulate-passes -Zlint-llvm-ir -Cllvm-args=-lint-abort-on-error +//@ compile-flags: -Copt-level=3 -Cno-prepopulate-passes -Zlint-llvm-ir //@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu //@[aarch64] needs-llvm-components: arm diff --git a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs index 404f6237849e..73bc7ef6b77d 100644 --- a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs +++ b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs @@ -1,7 +1,7 @@ //@ add-core-stubs //@ revisions: linux apple //@ min-llvm-version: 19 -//@ compile-flags: -Copt-level=0 -Cno-prepopulate-passes -Zlint-llvm-ir -Cllvm-args=-lint-abort-on-error +//@ compile-flags: -Copt-level=0 -Cno-prepopulate-passes -Zlint-llvm-ir //@[linux] compile-flags: --target x86_64-unknown-linux-gnu //@[linux] needs-llvm-components: x86 From a6a6d01bbc93da72474983d355e7442abbd162e8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 26 Mar 2025 09:47:46 +1100 Subject: [PATCH 694/745] Use `sym::dummy` in one more place. It makes it clearer that the symbol is unused and doesn't matter. --- compiler/rustc_resolve/src/diagnostics.rs | 2 +- compiler/rustc_span/src/hygiene.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 63ea8c4ced13..f7343b93281f 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1091,7 +1091,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { )); } Scope::BuiltinAttrs => { - let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(kw::Empty)); + let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(sym::dummy)); if filter_fn(res) { suggestions.extend( BUILTIN_ATTRIBUTES diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index e7a8dee27f56..9959e98e3dd7 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -1440,7 +1440,8 @@ pub fn decode_syntax_context SyntaxContext } } Entry::Vacant(entry) => { - // We are the first thread to start decoding. Mark the current thread as being progress. + // We are the first thread to start decoding. Mark the current thread as being + // progress. context.local_in_progress.borrow_mut().insert(raw_id); // Allocate and store SyntaxContext id *before* calling the decoder function, From 9fb0defa520c82ccf79af7961ee926dba77b4e96 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 26 Mar 2025 13:23:13 +1100 Subject: [PATCH 695/745] Tweak `check_doc_keyword`. To use one `kw::Empty` instead of two. It's a little more direct this way, and avoids `kw::Empty` being used for both "no string" and "empty string". --- compiler/rustc_passes/src/check_attr.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index ada3151c3b8c..3019c5c0dae8 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1041,11 +1041,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { s <= kw::Union || s == sym::SelfTy } - let doc_keyword = meta.value_str().unwrap_or(kw::Empty); - if doc_keyword == kw::Empty { - self.doc_attr_str_error(meta, "keyword"); - return; - } + let doc_keyword = match meta.value_str() { + Some(value) if value != kw::Empty => value, + _ => return self.doc_attr_str_error(meta, "keyword"), + }; + let item_kind = match self.tcx.hir_node(hir_id) { hir::Node::Item(item) => Some(&item.kind), _ => None, From 929749d8018b3a5afde968cff6da11b8460dd52d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 26 Mar 2025 13:33:38 +1100 Subject: [PATCH 696/745] Improve `is_doc_keyword`. This is part of the implementation of `#[doc(keyword = "match")]` attributes used by `std` to provide documentation for keywords. `is_doc_keyword` currently does a crude keyword range test that's intended to catch all keywords but misses `kw::Yeet`. This commit changes it to use `Symbol` methods, including the new `is_weak` method (required for `union`). `Symbol` methods are much less prone to falling out of date if new keywords are added. --- compiler/rustc_passes/src/check_attr.rs | 4 ++-- compiler/rustc_span/src/symbol.rs | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 3019c5c0dae8..cfc0369c5989 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -35,7 +35,7 @@ use rustc_session::lint::builtin::{ UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES, }; use rustc_session::parse::feature_err; -use rustc_span::{BytePos, DUMMY_SP, Span, Symbol, kw, sym}; +use rustc_span::{BytePos, DUMMY_SP, Span, Symbol, edition, kw, sym}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs}; use rustc_trait_selection::traits::ObligationCtxt; @@ -1038,7 +1038,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // FIXME: Once rustdoc can handle URL conflicts on case insensitive file systems, we // can remove the `SelfTy` case here, remove `sym::SelfTy`, and update the // `#[doc(keyword = "SelfTy")` attribute in `library/std/src/keyword_docs.rs`. - s <= kw::Union || s == sym::SelfTy + s.is_reserved(|| edition::LATEST_STABLE_EDITION) || s.is_weak() || s == sym::SelfTy } let doc_keyword = match meta.value_str() { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 47dd80c432ea..c6e570e524f5 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -131,7 +131,7 @@ symbols! { // tidy-alphabetical-end // Weak keywords, have special meaning only in specific contexts. - // Matching predicates: none + // Matching predicates: `is_weak` // tidy-alphabetical-start Auto: "auto", Builtin: "builtin", @@ -2725,6 +2725,10 @@ impl Symbol { || self.is_unused_keyword_conditional(edition) } + pub fn is_weak(self) -> bool { + self >= kw::Auto && self <= kw::Yeet + } + /// A keyword or reserved identifier that can be used as a path segment. pub fn is_path_segment_keyword(self) -> bool { self == kw::Super From 27850631638e74bd017d963a35c53e7f81f42e4d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 27 Mar 2025 22:56:13 +1100 Subject: [PATCH 697/745] Avoid `kw::Empty` use for `AuxParamsAttr`. By changing two of the fields to use `Option` instead of `Ident`. As a result, `None` now means "no identifier", which is much clearer than using an empty identifier. --- .../src/significant_drop_tightening.rs | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs index e9db7c9d031a..76874cc34206 100644 --- a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs +++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs @@ -79,10 +79,11 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> { if apa.counter <= 1 || !apa.has_expensive_expr_after_last_attr { continue; } + let first_bind_ident = apa.first_bind_ident.unwrap(); span_lint_and_then( cx, SIGNIFICANT_DROP_TIGHTENING, - apa.first_bind_ident.span, + first_bind_ident.span, "temporary with significant `Drop` can be early dropped", |diag| { match apa.counter { @@ -91,13 +92,13 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> { let indent = " ".repeat(indent_of(cx, apa.last_stmt_span).unwrap_or(0)); let init_method = snippet(cx, apa.first_method_span, ".."); let usage_method = snippet(cx, apa.last_method_span, ".."); - let stmt = if apa.last_bind_ident == Ident::empty() { - format!("\n{indent}{init_method}.{usage_method};") - } else { + let stmt = if let Some(last_bind_ident) = apa.last_bind_ident { format!( "\n{indent}let {} = {init_method}.{usage_method};", - snippet(cx, apa.last_bind_ident.span, ".."), + snippet(cx, last_bind_ident.span, ".."), ) + } else { + format!("\n{indent}{init_method}.{usage_method};") }; diag.multipart_suggestion_verbose( @@ -113,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> { format!( "\n{}drop({});", " ".repeat(indent_of(cx, apa.last_stmt_span).unwrap_or(0)), - apa.first_bind_ident + first_bind_ident ), Applicability::MaybeIncorrect, ); @@ -124,7 +125,7 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> { apa.first_block_span, format!( "temporary `{}` is currently being dropped at the end of its contained scope", - apa.first_bind_ident + first_bind_ident ), ); }, @@ -283,7 +284,7 @@ impl<'tcx> Visitor<'tcx> for StmtsChecker<'_, '_, '_, '_, 'tcx> { let mut apa = AuxParamsAttr { first_block_hir_id: self.ap.curr_block_hir_id, first_block_span: self.ap.curr_block_span, - first_bind_ident: ident, + first_bind_ident: Some(ident), first_method_span: { let expr_or_init = expr_or_init(self.cx, expr); if let hir::ExprKind::MethodCall(_, local_expr, _, span) = expr_or_init.kind { @@ -307,7 +308,7 @@ impl<'tcx> Visitor<'tcx> for StmtsChecker<'_, '_, '_, '_, 'tcx> { match self.ap.curr_stmt.kind { hir::StmtKind::Let(local) => { if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind { - apa.last_bind_ident = ident; + apa.last_bind_ident = Some(ident); } if let Some(local_init) = local.init && let hir::ExprKind::MethodCall(_, _, _, span) = local_init.kind @@ -373,7 +374,7 @@ struct AuxParamsAttr { first_block_span: Span, /// The binding or variable that references the initial construction of the type marked with /// `#[has_significant_drop]`. - first_bind_ident: Ident, + first_bind_ident: Option, /// Similar to `init_bind_ident` but encompasses the right-hand method call. first_method_span: Span, /// Similar to `init_bind_ident` but encompasses the whole contained statement. @@ -381,7 +382,7 @@ struct AuxParamsAttr { /// The last visited binding or variable span within a block that had any referenced inner type /// marked with `#[has_significant_drop]`. - last_bind_ident: Ident, + last_bind_ident: Option, /// Similar to `last_bind_span` but encompasses the right-hand method call. last_method_span: Span, /// Similar to `last_bind_span` but encompasses the whole contained statement. @@ -395,10 +396,10 @@ impl Default for AuxParamsAttr { has_expensive_expr_after_last_attr: false, first_block_hir_id: HirId::INVALID, first_block_span: DUMMY_SP, - first_bind_ident: Ident::empty(), + first_bind_ident: None, first_method_span: DUMMY_SP, first_stmt_span: DUMMY_SP, - last_bind_ident: Ident::empty(), + last_bind_ident: None, last_method_span: DUMMY_SP, last_stmt_span: DUMMY_SP, } @@ -413,7 +414,7 @@ fn dummy_stmt_expr<'any>(expr: &'any hir::Expr<'any>) -> hir::Stmt<'any> { } } -fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Ident, lcx: &LateContext<'_>) -> bool { +fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Option, lcx: &LateContext<'_>) -> bool { if let hir::ExprKind::Call(fun, [first_arg]) = expr.kind && let hir::ExprKind::Path(hir::QPath::Resolved(_, fun_path)) = &fun.kind && let Res::Def(DefKind::Fn, did) = fun_path.res @@ -422,6 +423,7 @@ fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Ident, lcx: &LateContext<'_ let has_ident = |local_expr: &hir::Expr<'_>| { if let hir::ExprKind::Path(hir::QPath::Resolved(_, arg_path)) = &local_expr.kind && let [first_arg_ps, ..] = arg_path.segments + && let Some(first_bind_ident) = first_bind_ident && &first_arg_ps.ident == first_bind_ident { true From 7feac15ca7f601b7ef0dd63e9113103f720f5405 Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Sun, 16 Apr 2023 11:50:15 +0000 Subject: [PATCH 698/745] rustdoc-json: Add test for #[automatically_derived] attribute --- tests/rustdoc-json/attrs/automatically_derived.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 tests/rustdoc-json/attrs/automatically_derived.rs diff --git a/tests/rustdoc-json/attrs/automatically_derived.rs b/tests/rustdoc-json/attrs/automatically_derived.rs new file mode 100644 index 000000000000..4e1ab3d145e5 --- /dev/null +++ b/tests/rustdoc-json/attrs/automatically_derived.rs @@ -0,0 +1,13 @@ +#[derive(Default)] +pub struct Derive; + +pub struct Manual; + +impl Default for Manual { + fn default() -> Self { + Self + } +} + +//@ is '$.index[?(@.inner.impl.for.resolved_path.path == "Derive" && @.inner.impl.trait.path == "Default")].attrs' '["#[automatically_derived]"]' +//@ is '$.index[?(@.inner.impl.for.resolved_path.path == "Manual" && @.inner.impl.trait.path == "Default")].attrs' '[]' From e2d5033bce2085fb2baaf5e887d11959928def74 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 31 Mar 2025 20:46:48 +0000 Subject: [PATCH 699/745] Feed HIR for by-move coroutine body def, since the inliner tries to read its attrs --- .../src/coroutine/by_move_body.rs | 2 ++ tests/crashes/134335.rs | 12 -------- .../by-move-body-inlined-attrs.rs | 28 +++++++++++++++++++ 3 files changed, 30 insertions(+), 12 deletions(-) delete mode 100644 tests/crashes/134335.rs create mode 100644 tests/ui/async-await/async-closures/by-move-body-inlined-attrs.rs diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index 89a306c61047..dd0e07f2218e 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -219,6 +219,8 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>( mir::MirSource::from_instance(InstanceKind::Item(body_def.def_id().to_def_id())); dump_mir(tcx, false, "built", &"after", &by_move_body, |_, _| Ok(())); + // Feed HIR because we try to access this body's attrs in the inliner. + body_def.feed_hir(); // Inherited from the by-ref coroutine. body_def.codegen_fn_attrs(tcx.codegen_fn_attrs(coroutine_def_id).clone()); body_def.coverage_attr_on(tcx.coverage_attr_on(coroutine_def_id)); diff --git a/tests/crashes/134335.rs b/tests/crashes/134335.rs deleted file mode 100644 index bee6686ff3fa..000000000000 --- a/tests/crashes/134335.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ known-bug: #134335 -//@compile-flags: -Zunstable-options --edition=2024 --crate-type=lib -pub async fn async_closure(x: &mut i32) { - let c = async move || { - *x += 1; - }; - call_once(c).await; -} - -fn call_once(f: impl FnOnce() -> T) -> T { - f() -} diff --git a/tests/ui/async-await/async-closures/by-move-body-inlined-attrs.rs b/tests/ui/async-await/async-closures/by-move-body-inlined-attrs.rs new file mode 100644 index 000000000000..ecfc06d2bad0 --- /dev/null +++ b/tests/ui/async-await/async-closures/by-move-body-inlined-attrs.rs @@ -0,0 +1,28 @@ +//@ check-pass +//@ compile-flags: -Zinline-mir -Zvalidate-mir +//@ edition: 2024 + +// See comment below. + +use std::future::Future; +use std::pin::pin; +use std::task::{Context, Waker}; + +fn call_once(f: impl FnOnce() -> T) -> T { f() } + +fn main() { + let x = async || {}; + // We first inline `call_once<{async closure}>`. + // + // This gives us a future whose type is the "FnOnce" flavor of the async closure's + // child coroutine. The body of this coroutine is synthetic, which we synthesize in + // the by-move body query. + let fut = pin!(call_once(x)); + // We then try to inline that body in this poll call. + // + // The inliner does some inlinability checks; one of these checks involves checking + // the body for the `#[rustc_no_mir_inline]` attribute. Since the synthetic body had + // no HIR synthesized, but it's still a local def id, we end up ICEing in the + // `local_def_id_to_hir_id` call when trying to read its attrs. + fut.poll(&mut Context::from_waker(Waker::noop())); +} From 654b7b541300c2d3d497031728b637ab4e457916 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 27 Mar 2025 16:12:00 +0100 Subject: [PATCH 700/745] increment depth of nested obligations --- .../src/traits/effects.rs | 8 --- .../src/traits/fulfill.rs | 56 ++++++++++++------- .../src/traits/select/confirmation.rs | 12 +--- tests/ui/infinite/infinite-autoderef.stderr | 4 +- tests/ui/occurs-check-2.rs | 2 +- tests/ui/occurs-check-2.stderr | 6 +- tests/ui/occurs-check-3.stderr | 4 +- tests/ui/occurs-check.stderr | 4 +- .../mutual-recursion-issue-75860.stderr | 2 +- ...ype-alias-impl-trait-with-cycle-error-1.rs | 3 +- ...alias-impl-trait-with-cycle-error-1.stderr | 11 ++-- ...ype-alias-impl-trait-with-cycle-error-2.rs | 4 +- ...alias-impl-trait-with-cycle-error-2.stderr | 11 ++-- ...ype-alias-impl-trait-with-cycle-error-3.rs | 4 +- ...alias-impl-trait-with-cycle-error-3.stderr | 11 ++-- 15 files changed, 70 insertions(+), 72 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index 3c127416cbf7..b8e15088853c 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -106,10 +106,6 @@ fn match_candidate<'tcx>( more_nested(selcx, &mut nested); - for nested in &mut nested { - nested.set_depth_from_parent(obligation.recursion_depth); - } - Ok(nested) } @@ -378,10 +374,6 @@ fn evaluate_host_effect_from_selection_candiate<'tcx>( }), ); - for nested in &mut nested { - nested.set_depth_from_parent(obligation.recursion_depth); - } - Ok(nested) } _ => Err(EvaluationFailure::NoSolution), diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index e39f8e673dba..e98a240a53f5 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -225,9 +225,15 @@ struct FulfillProcessor<'a, 'tcx> { selcx: SelectionContext<'a, 'tcx>, } -fn mk_pending<'tcx>(os: PredicateObligations<'tcx>) -> PendingPredicateObligations<'tcx> { +fn mk_pending<'tcx>( + parent: &PredicateObligation<'tcx>, + os: PredicateObligations<'tcx>, +) -> PendingPredicateObligations<'tcx> { os.into_iter() - .map(|o| PendingPredicateObligation { obligation: o, stalled_on: vec![] }) + .map(|mut o| { + o.set_depth_from_parent(parent.recursion_depth); + PendingPredicateObligation { obligation: o, stalled_on: vec![] } + }) .collect() } @@ -341,7 +347,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ); if predicate != obligation.predicate { obligations.push(obligation.with(infcx.tcx, predicate)); - return ProcessResult::Changed(mk_pending(obligations)); + return ProcessResult::Changed(mk_pending(obligation, obligations)); } } let binder = obligation.predicate.kind(); @@ -385,7 +391,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { let mut obligations = PredicateObligations::with_capacity(1); obligations.push(obligation.with(infcx.tcx, pred)); - ProcessResult::Changed(mk_pending(obligations)) + ProcessResult::Changed(mk_pending(obligation, obligations)) } ty::PredicateKind::Ambiguous => ProcessResult::Unchanged, ty::PredicateKind::NormalizesTo(..) => { @@ -410,6 +416,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { let host_obligation = obligation.with(infcx.tcx, data); self.process_host_obligation( + obligation, host_obligation, &mut pending_obligation.stalled_on, ) @@ -486,7 +493,10 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { // `>::Output` when this is an `Expr` representing // `lhs + rhs`. ty::ConstKind::Expr(_) => { - return ProcessResult::Changed(mk_pending(PredicateObligations::new())); + return ProcessResult::Changed(mk_pending( + obligation, + PredicateObligations::new(), + )); } ty::ConstKind::Placeholder(_) => { bug!("placeholder const {:?} in old solver", ct) @@ -503,7 +513,10 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ct_ty, ty, ) { - Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())), + Ok(inf_ok) => ProcessResult::Changed(mk_pending( + obligation, + inf_ok.into_obligations(), + )), Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select( SelectionError::ConstArgHasWrongType { ct, ct_ty, expected_ty: ty }, )), @@ -537,7 +550,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { vec![TyOrConstInferVar::maybe_from_generic_arg(arg).unwrap()]; ProcessResult::Unchanged } - Some(os) => ProcessResult::Changed(mk_pending(os)), + Some(os) => ProcessResult::Changed(mk_pending(obligation, os)), } } @@ -553,11 +566,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { vec![TyOrConstInferVar::Ty(a), TyOrConstInferVar::Ty(b)]; ProcessResult::Unchanged } - Ok(Ok(mut ok)) => { - for subobligation in &mut ok.obligations { - subobligation.set_depth_from_parent(obligation.recursion_depth); - } - ProcessResult::Changed(mk_pending(ok.obligations)) + Ok(Ok(ok)) => { + ProcessResult::Changed(mk_pending(obligation, ok.obligations)) } Ok(Err(err)) => { let expected_found = if subtype.a_is_expected { @@ -582,7 +592,9 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { vec![TyOrConstInferVar::Ty(a), TyOrConstInferVar::Ty(b)]; ProcessResult::Unchanged } - Ok(Ok(ok)) => ProcessResult::Changed(mk_pending(ok.obligations)), + Ok(Ok(ok)) => { + ProcessResult::Changed(mk_pending(obligation, ok.obligations)) + } Ok(Err(err)) => { let expected_found = ExpectedFound::new(coerce.b, coerce.a); ProcessResult::Error(FulfillmentErrorCode::Subtype(expected_found, err)) @@ -645,6 +657,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ) { return ProcessResult::Changed(mk_pending( + obligation, new_obligations.into_obligations(), )); } @@ -659,6 +672,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { .eq(DefineOpaqueTypes::Yes, c1, c2) { return ProcessResult::Changed(mk_pending( + obligation, new_obligations.into_obligations(), )); } @@ -704,9 +718,10 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { c1, c2, ) { - Ok(inf_ok) => { - ProcessResult::Changed(mk_pending(inf_ok.into_obligations())) - } + Ok(inf_ok) => ProcessResult::Changed(mk_pending( + obligation, + inf_ok.into_obligations(), + )), Err(err) => { ProcessResult::Error(FulfillmentErrorCode::ConstEquate( ExpectedFound::new(c1, c2), @@ -790,7 +805,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { match self.selcx.poly_select(&trait_obligation) { Ok(Some(impl_source)) => { debug!("selecting trait at depth {} yielded Ok(Some)", obligation.recursion_depth); - ProcessResult::Changed(mk_pending(impl_source.nested_obligations())) + ProcessResult::Changed(mk_pending(obligation, impl_source.nested_obligations())) } Ok(None) => { debug!("selecting trait at depth {} yielded Ok(None)", obligation.recursion_depth); @@ -854,7 +869,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { } match project::poly_project_and_unify_term(&mut self.selcx, &project_obligation) { - ProjectAndUnifyResult::Holds(os) => ProcessResult::Changed(mk_pending(os)), + ProjectAndUnifyResult::Holds(os) => ProcessResult::Changed(mk_pending(obligation, os)), ProjectAndUnifyResult::FailedNormalization => { stalled_on.clear(); stalled_on.extend(args_infer_vars( @@ -868,7 +883,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { let mut obligations = PredicateObligations::with_capacity(1); obligations.push(project_obligation.with(tcx, project_obligation.predicate)); - ProcessResult::Changed(mk_pending(obligations)) + ProcessResult::Changed(mk_pending(obligation, obligations)) } ProjectAndUnifyResult::MismatchedProjectionTypes(e) => { ProcessResult::Error(FulfillmentErrorCode::Project(e)) @@ -878,11 +893,12 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { fn process_host_obligation( &mut self, + obligation: &PredicateObligation<'tcx>, host_obligation: HostEffectObligation<'tcx>, stalled_on: &mut Vec, ) -> ProcessResult, FulfillmentErrorCode<'tcx>> { match effects::evaluate_host_effect_obligation(&mut self.selcx, &host_obligation) { - Ok(nested) => ProcessResult::Changed(mk_pending(nested)), + Ok(nested) => ProcessResult::Changed(mk_pending(obligation, nested)), Err(effects::EvaluationFailure::Ambiguous) => { stalled_on.clear(); stalled_on.extend(args_infer_vars( diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 630241725fdb..2cb7d2d89313 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -39,7 +39,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &PolyTraitObligation<'tcx>, candidate: SelectionCandidate<'tcx>, ) -> Result, SelectionError<'tcx>> { - let mut impl_src = match candidate { + Ok(match candidate { SizedCandidate { has_nested } => { let data = self.confirm_builtin_candidate(obligation, has_nested); ImplSource::Builtin(BuiltinImplSource::Misc, data) @@ -139,15 +139,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { BikeshedGuaranteedNoDropCandidate => { self.confirm_bikeshed_guaranteed_no_drop_candidate(obligation) } - }; - - // The obligations returned by confirmation are recursively evaluated - // so we need to make sure they have the correct depth. - for subobligation in impl_src.borrow_nested_obligations_mut() { - subobligation.set_depth_from_parent(obligation.recursion_depth); - } - - Ok(impl_src) + }) } fn confirm_projection_candidate( diff --git a/tests/ui/infinite/infinite-autoderef.stderr b/tests/ui/infinite/infinite-autoderef.stderr index 7d09af9a7d4a..7770cc8a7204 100644 --- a/tests/ui/infinite/infinite-autoderef.stderr +++ b/tests/ui/infinite/infinite-autoderef.stderr @@ -1,8 +1,8 @@ error[E0275]: overflow assigning `Box<_>` to `_` - --> $DIR/infinite-autoderef.rs:16:13 + --> $DIR/infinite-autoderef.rs:16:22 | LL | x = Box::new(x); - | ^^^^^^^^^^^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/occurs-check-2.rs b/tests/ui/occurs-check-2.rs index 1ec460a87352..9289a8e870a1 100644 --- a/tests/ui/occurs-check-2.rs +++ b/tests/ui/occurs-check-2.rs @@ -4,6 +4,6 @@ fn main() { let g; g = f; - f = Box::new(g); //~^ ERROR overflow assigning `Box<_>` to `_` + f = Box::new(g); } diff --git a/tests/ui/occurs-check-2.stderr b/tests/ui/occurs-check-2.stderr index 54307a6c5474..5f296967f30d 100644 --- a/tests/ui/occurs-check-2.stderr +++ b/tests/ui/occurs-check-2.stderr @@ -1,8 +1,8 @@ error[E0275]: overflow assigning `Box<_>` to `_` - --> $DIR/occurs-check-2.rs:7:9 + --> $DIR/occurs-check-2.rs:6:9 | -LL | f = Box::new(g); - | ^^^^^^^^^^^ +LL | g = f; + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/occurs-check-3.stderr b/tests/ui/occurs-check-3.stderr index 77b67ec1a62c..eb05c94957c9 100644 --- a/tests/ui/occurs-check-3.stderr +++ b/tests/ui/occurs-check-3.stderr @@ -1,8 +1,8 @@ error[E0275]: overflow assigning `Clam<_>` to `_` - --> $DIR/occurs-check-3.rs:6:9 + --> $DIR/occurs-check-3.rs:6:17 | LL | c = Clam::A(c); - | ^^^^^^^^^^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/occurs-check.stderr b/tests/ui/occurs-check.stderr index 30468d68cbd0..ea7c541abc13 100644 --- a/tests/ui/occurs-check.stderr +++ b/tests/ui/occurs-check.stderr @@ -1,8 +1,8 @@ error[E0275]: overflow assigning `Box<_>` to `_` - --> $DIR/occurs-check.rs:3:9 + --> $DIR/occurs-check.rs:3:18 | LL | f = Box::new(f); - | ^^^^^^^^^^^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/traits/mutual-recursion-issue-75860.stderr b/tests/ui/traits/mutual-recursion-issue-75860.stderr index 272c56301bc8..9e8eb1adb111 100644 --- a/tests/ui/traits/mutual-recursion-issue-75860.stderr +++ b/tests/ui/traits/mutual-recursion-issue-75860.stderr @@ -2,7 +2,7 @@ error[E0275]: overflow assigning `_` to `Option<_>` --> $DIR/mutual-recursion-issue-75860.rs:9:33 | LL | let left = |o_a: Option<_>| o_a.unwrap(); - | ^^^ + | ^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs index 19986247d40d..53b7667aa9f1 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs @@ -1,9 +1,10 @@ #![feature(type_alias_impl_trait)] -//@ known-bug: #109268 type Foo = impl Fn() -> Foo; +#[define_opaque(Foo)] fn crash(x: Foo) -> Foo { + //~^ ERROR overflow evaluating the requirement `>::Output == Foo` x } diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr index ad96a0eeb87d..ee8922b673e2 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr @@ -1,10 +1,9 @@ -error: unconstrained opaque type - --> $DIR/type-alias-impl-trait-with-cycle-error-1.rs:4:12 +error[E0275]: overflow evaluating the requirement `>::Output == Foo` + --> $DIR/type-alias-impl-trait-with-cycle-error-1.rs:6:21 | -LL | type Foo = impl Fn() -> Foo; - | ^^^^^^^^^^^^^^^^ - | - = note: `Foo` must be used in combination with a concrete type within the same crate +LL | fn crash(x: Foo) -> Foo { + | ^^^ error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs index 761cc83af510..d0c62d290698 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs @@ -1,13 +1,13 @@ #![feature(type_alias_impl_trait)] -//@ known-bug: #109268 pub trait Bar { type Item; } type Foo = impl Bar; - +#[define_opaque(Foo)] fn crash(x: Foo) -> Foo { + //~^ ERROR overflow evaluating the requirement `>::Item == Foo` x } diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr index e5bb8163a811..40bd6517c06d 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr @@ -1,10 +1,9 @@ -error: unconstrained opaque type - --> $DIR/type-alias-impl-trait-with-cycle-error-2.rs:8:12 +error[E0275]: overflow evaluating the requirement `>::Item == Foo` + --> $DIR/type-alias-impl-trait-with-cycle-error-2.rs:9:21 | -LL | type Foo = impl Bar; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `Foo` must be used in combination with a concrete type within the same crate +LL | fn crash(x: Foo) -> Foo { + | ^^^ error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs index 52942afd6392..de3d23b83a29 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs @@ -1,9 +1,9 @@ #![feature(type_alias_impl_trait)] -//@ known-bug: #109268 type Foo<'a> = impl Fn() -> Foo<'a>; - +#[define_opaque(Foo)] fn crash<'a>(_: &'a (), x: Foo<'a>) -> Foo<'a> { + //~^ ERROR overflow evaluating the requirement ` as FnOnce<()>>::Output == Foo<'a>` x } diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr index 157310bf6236..f9e26fde1bda 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr @@ -1,10 +1,9 @@ -error: unconstrained opaque type - --> $DIR/type-alias-impl-trait-with-cycle-error-3.rs:4:16 +error[E0275]: overflow evaluating the requirement ` as FnOnce<()>>::Output == Foo<'a>` + --> $DIR/type-alias-impl-trait-with-cycle-error-3.rs:5:40 | -LL | type Foo<'a> = impl Fn() -> Foo<'a>; - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: `Foo` must be used in combination with a concrete type within the same crate +LL | fn crash<'a>(_: &'a (), x: Foo<'a>) -> Foo<'a> { + | ^^^^^^^ error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0275`. From e80a3e22328641b43a5ea66bfafdfe5950686779 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 29 Mar 2025 18:34:44 +1100 Subject: [PATCH 701/745] coverage: Tweak tests/coverage/assert-ne.rs This test is intended to demonstrate that a particular macro-argument span doesn't get lost during span-refinement, but it turns out that span-extraction currently doesn't yield any MIR spans for this position. This patch therefore tweaks the test to add a function call in that position, so that it still remains relevant to span refinement. --- tests/coverage/assert-ne.coverage | 2 +- tests/coverage/assert-ne.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/coverage/assert-ne.coverage b/tests/coverage/assert-ne.coverage index 236a8fd13858..fc43d4a8e06a 100644 --- a/tests/coverage/assert-ne.coverage +++ b/tests/coverage/assert-ne.coverage @@ -7,7 +7,7 @@ LL| | LL| 1|fn main() { LL| 1| assert_ne!( - LL| 1| Foo(5), // Make sure this expression's span isn't lost. + LL| 1| black_box(Foo(5)), // Make sure this expression's span isn't lost. LL| 1| if black_box(false) { LL| 0| Foo(0) // LL| | } else { diff --git a/tests/coverage/assert-ne.rs b/tests/coverage/assert-ne.rs index 8a8fe0898048..9d9fcb71ba7f 100644 --- a/tests/coverage/assert-ne.rs +++ b/tests/coverage/assert-ne.rs @@ -7,7 +7,7 @@ struct Foo(u32); fn main() { assert_ne!( - Foo(5), // Make sure this expression's span isn't lost. + black_box(Foo(5)), // Make sure this expression's span isn't lost. if black_box(false) { Foo(0) // } else { From 577272eedeaace00aa695135b3b8fee3768536a5 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 29 Mar 2025 21:33:01 +1100 Subject: [PATCH 702/745] coverage: Shrink call spans to just the function name This is a way to shrink call spans that doesn't involve mixing different spans, and avoids overlap with argument spans. This patch also removes some low-value comments that were causing rustfmt to ignore the match arms. --- .../src/coverage/spans/from_mir.rs | 18 ++++----- tests/coverage/assert-ne.cov-map | 4 +- tests/coverage/attr/off-on-sandwich.cov-map | 12 +++--- tests/coverage/branch/if.cov-map | 4 +- tests/coverage/branch/lazy-boolean.cov-map | 8 ++-- tests/coverage/branch/let-else.cov-map | 4 +- tests/coverage/branch/match-arms.cov-map | 28 ++++++------- tests/coverage/condition/conditions.cov-map | 10 +++-- tests/coverage/coroutine.cov-map | 4 +- tests/coverage/holes.cov-map | 18 ++++----- tests/coverage/inline-dead.cov-map | 4 +- tests/coverage/loop-break.cov-map | 4 +- tests/coverage/mcdc/non_control_flow.cov-map | 10 +++-- tests/coverage/no_cov_crate.cov-map | 8 ++-- tests/coverage/sort_groups.cov-map | 4 +- tests/coverage/try_error_result.cov-map | 40 +++++++++---------- tests/coverage/try_error_result.coverage | 2 +- tests/coverage/unicode.cov-map | 6 +-- tests/coverage/unicode.coverage | 2 +- tests/coverage/unreachable.cov-map | 12 +++--- ...ch_match_arms.main.InstrumentCoverage.diff | 8 ++-- ...ment_coverage.main.InstrumentCoverage.diff | 2 +- 22 files changed, 106 insertions(+), 106 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index 1faa2171c0b0..804cd8ab3f7d 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -120,22 +120,20 @@ fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option { // an `if condition { block }` has a span that includes the executed block, if true, // but for coverage, the code region executed, up to *and* through the SwitchInt, // actually stops before the if's block.) - TerminatorKind::Unreachable // Unreachable blocks are not connected to the MIR CFG + TerminatorKind::Unreachable | TerminatorKind::Assert { .. } | TerminatorKind::Drop { .. } | TerminatorKind::SwitchInt { .. } - // For `FalseEdge`, only the `real` branch is taken, so it is similar to a `Goto`. | TerminatorKind::FalseEdge { .. } | TerminatorKind::Goto { .. } => None, // Call `func` operand can have a more specific span when part of a chain of calls - TerminatorKind::Call { ref func, .. } - | TerminatorKind::TailCall { ref func, .. } => { + TerminatorKind::Call { ref func, .. } | TerminatorKind::TailCall { ref func, .. } => { let mut span = terminator.source_info.span; - if let mir::Operand::Constant(box constant) = func { - if constant.span.lo() > span.lo() { - span = span.with_lo(constant.span.lo()); - } + if let mir::Operand::Constant(constant) = func + && span.contains(constant.span) + { + span = constant.span; } Some(span) } @@ -147,9 +145,7 @@ fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option { | TerminatorKind::Yield { .. } | TerminatorKind::CoroutineDrop | TerminatorKind::FalseUnwind { .. } - | TerminatorKind::InlineAsm { .. } => { - Some(terminator.source_info.span) - } + | TerminatorKind::InlineAsm { .. } => Some(terminator.source_info.span), } } diff --git a/tests/coverage/assert-ne.cov-map b/tests/coverage/assert-ne.cov-map index b432e63c168c..27d4b0382dec 100644 --- a/tests/coverage/assert-ne.cov-map +++ b/tests/coverage/assert-ne.cov-map @@ -1,12 +1,12 @@ Function name: assert_ne::main -Raw bytes (28): 0x[01, 01, 02, 01, 05, 01, 09, 04, 01, 08, 01, 03, 1c, 05, 04, 0d, 00, 13, 02, 02, 0d, 00, 13, 06, 03, 05, 01, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 01, 09, 04, 01, 08, 01, 03, 15, 05, 04, 0d, 00, 13, 02, 02, 0d, 00, 13, 06, 03, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Counter(2) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 28) +- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 21) - Code(Counter(1)) at (prev + 4, 13) to (start + 0, 19) - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 19) = (c0 - c1) diff --git a/tests/coverage/attr/off-on-sandwich.cov-map b/tests/coverage/attr/off-on-sandwich.cov-map index ef6f5a9dc428..c55c5897d8ba 100644 --- a/tests/coverage/attr/off-on-sandwich.cov-map +++ b/tests/coverage/attr/off-on-sandwich.cov-map @@ -1,30 +1,30 @@ Function name: off_on_sandwich::dense_a::dense_b -Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 05, 02, 12, 01, 07, 05, 00, 06] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 05, 02, 10, 01, 07, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 16, 5) to (start + 2, 18) +- Code(Counter(0)) at (prev + 16, 5) to (start + 2, 16) - Code(Counter(0)) at (prev + 7, 5) to (start + 0, 6) Highest counter ID seen: c0 Function name: off_on_sandwich::sparse_a::sparse_b::sparse_c -Raw bytes (14): 0x[01, 01, 00, 02, 01, 22, 09, 02, 17, 01, 0b, 09, 00, 0a] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 22, 09, 02, 15, 01, 0b, 09, 00, 0a] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 34, 9) to (start + 2, 23) +- Code(Counter(0)) at (prev + 34, 9) to (start + 2, 21) - Code(Counter(0)) at (prev + 11, 9) to (start + 0, 10) Highest counter ID seen: c0 Function name: off_on_sandwich::sparse_a::sparse_b::sparse_c::sparse_d -Raw bytes (14): 0x[01, 01, 00, 02, 01, 25, 0d, 02, 1b, 01, 07, 0d, 00, 0e] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 25, 0d, 02, 19, 01, 07, 0d, 00, 0e] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 37, 13) to (start + 2, 27) +- Code(Counter(0)) at (prev + 37, 13) to (start + 2, 25) - Code(Counter(0)) at (prev + 7, 13) to (start + 0, 14) Highest counter ID seen: c0 diff --git a/tests/coverage/branch/if.cov-map b/tests/coverage/branch/if.cov-map index a6b865318c66..392ace1683a7 100644 --- a/tests/coverage/branch/if.cov-map +++ b/tests/coverage/branch/if.cov-map @@ -23,7 +23,7 @@ Number of file 0 mappings: 8 Highest counter ID seen: c2 Function name: if::branch_not -Raw bytes (116): 0x[01, 01, 07, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 01, 11, 01, 11, 12, 01, 0c, 01, 01, 10, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 01, 09, 00, 11, 02, 01, 05, 00, 06, 01, 01, 08, 00, 0a, 20, 0a, 09, 00, 08, 00, 0a, 0a, 00, 0b, 02, 06, 09, 02, 05, 00, 06, 01, 01, 08, 00, 0b, 20, 0d, 12, 00, 08, 00, 0b, 0d, 00, 0c, 02, 06, 12, 02, 05, 00, 06, 01, 01, 08, 00, 0c, 20, 1a, 11, 00, 08, 00, 0c, 1a, 00, 0d, 02, 06, 11, 02, 05, 00, 06, 01, 01, 01, 00, 02] +Raw bytes (116): 0x[01, 01, 07, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 01, 11, 01, 11, 12, 01, 0c, 01, 01, 10, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 01, 09, 00, 10, 02, 01, 05, 00, 06, 01, 01, 08, 00, 0a, 20, 0a, 09, 00, 08, 00, 0a, 0a, 00, 0b, 02, 06, 09, 02, 05, 00, 06, 01, 01, 08, 00, 0b, 20, 0d, 12, 00, 08, 00, 0b, 0d, 00, 0c, 02, 06, 12, 02, 05, 00, 06, 01, 01, 08, 00, 0c, 20, 1a, 11, 00, 08, 00, 0c, 1a, 00, 0d, 02, 06, 11, 02, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 7 @@ -40,7 +40,7 @@ Number of file 0 mappings: 18 - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) -- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 17) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 16) - Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 8) to (start + 0, 10) diff --git a/tests/coverage/branch/lazy-boolean.cov-map b/tests/coverage/branch/lazy-boolean.cov-map index 622f30e2b56f..ff285a038fb8 100644 --- a/tests/coverage/branch/lazy-boolean.cov-map +++ b/tests/coverage/branch/lazy-boolean.cov-map @@ -34,7 +34,7 @@ Number of file 0 mappings: 6 Highest counter ID seen: c1 Function name: lazy_boolean::chain -Raw bytes (141): 0x[01, 01, 0f, 01, 05, 05, 09, 09, 0d, 01, 11, 01, 11, 01, 3b, 11, 15, 01, 3b, 11, 15, 01, 37, 3b, 19, 11, 15, 01, 37, 3b, 19, 11, 15, 13, 01, 24, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 05, 02, 00, 0d, 00, 12, 05, 00, 16, 00, 1b, 20, 09, 06, 00, 16, 00, 1b, 09, 00, 1f, 00, 24, 20, 0d, 0a, 00, 1f, 00, 24, 0d, 00, 28, 00, 2d, 01, 01, 05, 00, 11, 01, 03, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 11, 12, 00, 0d, 00, 12, 12, 00, 16, 00, 1b, 20, 15, 1e, 00, 16, 00, 1b, 1e, 00, 1f, 00, 24, 20, 19, 32, 00, 1f, 00, 24, 32, 00, 28, 00, 2d, 01, 01, 05, 01, 02] +Raw bytes (141): 0x[01, 01, 0f, 01, 05, 05, 09, 09, 0d, 01, 11, 01, 11, 01, 3b, 11, 15, 01, 3b, 11, 15, 01, 37, 3b, 19, 11, 15, 01, 37, 3b, 19, 11, 15, 13, 01, 24, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 05, 02, 00, 0d, 00, 12, 05, 00, 16, 00, 1b, 20, 09, 06, 00, 16, 00, 1b, 09, 00, 1f, 00, 24, 20, 0d, 0a, 00, 1f, 00, 24, 0d, 00, 28, 00, 2d, 01, 01, 05, 00, 10, 01, 03, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 11, 12, 00, 0d, 00, 12, 12, 00, 16, 00, 1b, 20, 15, 1e, 00, 16, 00, 1b, 1e, 00, 1f, 00, 24, 20, 19, 32, 00, 1f, 00, 24, 32, 00, 28, 00, 2d, 01, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 15 @@ -69,7 +69,7 @@ Number of file 0 mappings: 19 true = c3 false = (c2 - c3) - Code(Counter(3)) at (prev + 0, 40) to (start + 0, 45) -- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 16) - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 18) - Branch { true: Counter(4), false: Expression(4, Sub) } at (prev + 0, 13) to (start + 0, 18) @@ -91,7 +91,7 @@ Number of file 0 mappings: 19 Highest counter ID seen: c6 Function name: lazy_boolean::nested_mixed -Raw bytes (137): 0x[01, 01, 0d, 01, 05, 01, 1f, 05, 09, 05, 09, 1f, 0d, 05, 09, 1f, 0d, 05, 09, 01, 11, 11, 15, 01, 15, 01, 33, 15, 19, 13, 01, 31, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 05, 02, 00, 0e, 00, 13, 02, 00, 17, 00, 1d, 20, 09, 06, 00, 17, 00, 1d, 1f, 00, 23, 00, 28, 20, 0d, 1a, 00, 23, 00, 28, 1a, 00, 2c, 00, 33, 01, 01, 05, 00, 11, 01, 03, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 11, 22, 00, 0e, 00, 13, 11, 00, 17, 00, 1c, 20, 15, 26, 00, 17, 00, 1c, 2a, 00, 22, 00, 28, 20, 19, 2e, 00, 22, 00, 28, 19, 00, 2c, 00, 33, 01, 01, 05, 01, 02] +Raw bytes (137): 0x[01, 01, 0d, 01, 05, 01, 1f, 05, 09, 05, 09, 1f, 0d, 05, 09, 1f, 0d, 05, 09, 01, 11, 11, 15, 01, 15, 01, 33, 15, 19, 13, 01, 31, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 05, 02, 00, 0e, 00, 13, 02, 00, 17, 00, 1d, 20, 09, 06, 00, 17, 00, 1d, 1f, 00, 23, 00, 28, 20, 0d, 1a, 00, 23, 00, 28, 1a, 00, 2c, 00, 33, 01, 01, 05, 00, 10, 01, 03, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 11, 22, 00, 0e, 00, 13, 11, 00, 17, 00, 1c, 20, 15, 26, 00, 17, 00, 1c, 2a, 00, 22, 00, 28, 20, 19, 2e, 00, 22, 00, 28, 19, 00, 2c, 00, 33, 01, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 13 @@ -127,7 +127,7 @@ Number of file 0 mappings: 19 false = ((c1 + c2) - c3) - Code(Expression(6, Sub)) at (prev + 0, 44) to (start + 0, 51) = ((c1 + c2) - c3) -- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 16) - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 14) to (start + 0, 19) - Branch { true: Counter(4), false: Expression(8, Sub) } at (prev + 0, 14) to (start + 0, 19) diff --git a/tests/coverage/branch/let-else.cov-map b/tests/coverage/branch/let-else.cov-map index 215d71599e4c..811b9838e3f5 100644 --- a/tests/coverage/branch/let-else.cov-map +++ b/tests/coverage/branch/let-else.cov-map @@ -1,5 +1,5 @@ Function name: let_else::let_else -Raw bytes (43): 0x[01, 01, 01, 01, 05, 07, 01, 0c, 01, 01, 10, 20, 02, 05, 03, 09, 00, 10, 02, 00, 0e, 00, 0f, 01, 00, 13, 00, 18, 05, 01, 09, 01, 0f, 02, 04, 05, 00, 0b, 01, 01, 01, 00, 02] +Raw bytes (43): 0x[01, 01, 01, 01, 05, 07, 01, 0c, 01, 01, 10, 20, 02, 05, 03, 09, 00, 10, 02, 00, 0e, 00, 0f, 01, 00, 13, 00, 18, 05, 01, 09, 01, 0f, 02, 04, 05, 00, 0a, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 @@ -13,7 +13,7 @@ Number of file 0 mappings: 7 = (c0 - c1) - Code(Counter(0)) at (prev + 0, 19) to (start + 0, 24) - Code(Counter(1)) at (prev + 1, 9) to (start + 1, 15) -- Code(Expression(0, Sub)) at (prev + 4, 5) to (start + 0, 11) +- Code(Expression(0, Sub)) at (prev + 4, 5) to (start + 0, 10) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 diff --git a/tests/coverage/branch/match-arms.cov-map b/tests/coverage/branch/match-arms.cov-map index d5b4d04d4019..caa18820cf8e 100644 --- a/tests/coverage/branch/match-arms.cov-map +++ b/tests/coverage/branch/match-arms.cov-map @@ -1,5 +1,5 @@ Function name: match_arms::guards -Raw bytes (88): 0x[01, 01, 08, 15, 05, 19, 09, 1d, 0d, 21, 11, 01, 17, 1b, 11, 1f, 0d, 05, 09, 0c, 01, 30, 01, 01, 10, 21, 03, 0b, 00, 10, 05, 01, 11, 00, 29, 20, 05, 02, 00, 17, 00, 1b, 09, 01, 11, 00, 29, 20, 09, 06, 00, 17, 00, 1b, 0d, 01, 11, 00, 29, 20, 0d, 0a, 00, 17, 00, 1b, 11, 01, 11, 00, 29, 20, 11, 0e, 00, 17, 00, 1b, 12, 01, 0e, 00, 18, 01, 03, 05, 01, 02] +Raw bytes (88): 0x[01, 01, 08, 15, 05, 19, 09, 1d, 0d, 21, 11, 01, 17, 1b, 11, 1f, 0d, 05, 09, 0c, 01, 30, 01, 01, 10, 21, 03, 0b, 00, 10, 05, 01, 11, 00, 28, 20, 05, 02, 00, 17, 00, 1b, 09, 01, 11, 00, 28, 20, 09, 06, 00, 17, 00, 1b, 0d, 01, 11, 00, 28, 20, 0d, 0a, 00, 17, 00, 1b, 11, 01, 11, 00, 28, 20, 11, 0e, 00, 17, 00, 1b, 12, 01, 0e, 00, 15, 01, 03, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 8 @@ -14,29 +14,29 @@ Number of expressions: 8 Number of file 0 mappings: 12 - Code(Counter(0)) at (prev + 48, 1) to (start + 1, 16) - Code(Counter(8)) at (prev + 3, 11) to (start + 0, 16) -- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 41) +- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 40) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 23) to (start + 0, 27) true = c1 false = (c5 - c1) -- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 41) +- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 40) - Branch { true: Counter(2), false: Expression(1, Sub) } at (prev + 0, 23) to (start + 0, 27) true = c2 false = (c6 - c2) -- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 41) +- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 40) - Branch { true: Counter(3), false: Expression(2, Sub) } at (prev + 0, 23) to (start + 0, 27) true = c3 false = (c7 - c3) -- Code(Counter(4)) at (prev + 1, 17) to (start + 0, 41) +- Code(Counter(4)) at (prev + 1, 17) to (start + 0, 40) - Branch { true: Counter(4), false: Expression(3, Sub) } at (prev + 0, 23) to (start + 0, 27) true = c4 false = (c8 - c4) -- Code(Expression(4, Sub)) at (prev + 1, 14) to (start + 0, 24) +- Code(Expression(4, Sub)) at (prev + 1, 14) to (start + 0, 21) = (c0 - (((c1 + c2) + c3) + c4)) - Code(Counter(0)) at (prev + 3, 5) to (start + 1, 2) Highest counter ID seen: c8 Function name: match_arms::match_arms -Raw bytes (45): 0x[01, 01, 03, 01, 07, 0b, 0d, 05, 09, 07, 01, 18, 01, 01, 10, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 21, 09, 01, 11, 00, 21, 0d, 01, 11, 00, 21, 02, 01, 11, 00, 21, 01, 03, 05, 01, 02] +Raw bytes (45): 0x[01, 01, 03, 01, 07, 0b, 0d, 05, 09, 07, 01, 18, 01, 01, 10, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 20, 09, 01, 11, 00, 20, 0d, 01, 11, 00, 20, 02, 01, 11, 00, 20, 01, 03, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 @@ -46,16 +46,16 @@ Number of expressions: 3 Number of file 0 mappings: 7 - Code(Counter(0)) at (prev + 24, 1) to (start + 1, 16) - Code(Counter(0)) at (prev + 3, 11) to (start + 0, 16) -- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 33) -- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 33) -- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 33) -- Code(Expression(0, Sub)) at (prev + 1, 17) to (start + 0, 33) +- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 32) +- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 32) +- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 32) +- Code(Expression(0, Sub)) at (prev + 1, 17) to (start + 0, 32) = (c0 - ((c1 + c2) + c3)) - Code(Counter(0)) at (prev + 3, 5) to (start + 1, 2) Highest counter ID seen: c3 Function name: match_arms::or_patterns -Raw bytes (57): 0x[01, 01, 04, 05, 09, 01, 0b, 03, 0d, 01, 03, 09, 01, 25, 01, 01, 10, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 12, 09, 00, 1e, 00, 1f, 03, 00, 24, 00, 2e, 0d, 01, 11, 00, 12, 06, 00, 1e, 00, 1f, 0e, 00, 24, 00, 2e, 01, 03, 05, 01, 02] +Raw bytes (57): 0x[01, 01, 04, 05, 09, 01, 0b, 03, 0d, 01, 03, 09, 01, 25, 01, 01, 10, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 12, 09, 00, 1e, 00, 1f, 03, 00, 24, 00, 2d, 0d, 01, 11, 00, 12, 06, 00, 1e, 00, 1f, 0e, 00, 24, 00, 2d, 01, 03, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -68,12 +68,12 @@ Number of file 0 mappings: 9 - Code(Counter(0)) at (prev + 3, 11) to (start + 0, 16) - Code(Counter(1)) at (prev + 1, 17) to (start + 0, 18) - Code(Counter(2)) at (prev + 0, 30) to (start + 0, 31) -- Code(Expression(0, Add)) at (prev + 0, 36) to (start + 0, 46) +- Code(Expression(0, Add)) at (prev + 0, 36) to (start + 0, 45) = (c1 + c2) - Code(Counter(3)) at (prev + 1, 17) to (start + 0, 18) - Code(Expression(1, Sub)) at (prev + 0, 30) to (start + 0, 31) = (c0 - ((c1 + c2) + c3)) -- Code(Expression(3, Sub)) at (prev + 0, 36) to (start + 0, 46) +- Code(Expression(3, Sub)) at (prev + 0, 36) to (start + 0, 45) = (c0 - (c1 + c2)) - Code(Counter(0)) at (prev + 3, 5) to (start + 1, 2) Highest counter ID seen: c3 diff --git a/tests/coverage/condition/conditions.cov-map b/tests/coverage/condition/conditions.cov-map index 417637f2d2e3..c34075a0bcfc 100644 --- a/tests/coverage/condition/conditions.cov-map +++ b/tests/coverage/condition/conditions.cov-map @@ -109,15 +109,17 @@ Number of file 0 mappings: 1 Highest counter ID seen: c0 Function name: conditions::func_call -Raw bytes (37): 0x[01, 01, 02, 01, 05, 05, 09, 05, 01, 25, 01, 01, 0a, 20, 05, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 0f, 20, 09, 06, 00, 0e, 00, 0f, 01, 01, 01, 00, 02] +Raw bytes (47): 0x[01, 01, 02, 01, 05, 05, 09, 07, 01, 25, 01, 00, 20, 01, 01, 05, 00, 08, 01, 00, 09, 00, 0a, 20, 05, 02, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 20, 09, 06, 00, 0e, 00, 0f, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 5 -- Code(Counter(0)) at (prev + 37, 1) to (start + 1, 10) -- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 1, 9) to (start + 0, 10) +Number of file 0 mappings: 7 +- Code(Counter(0)) at (prev + 37, 1) to (start + 0, 32) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 8) +- Code(Counter(0)) at (prev + 0, 9) to (start + 0, 10) +- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 9) to (start + 0, 10) true = c1 false = (c0 - c1) - Code(Counter(1)) at (prev + 0, 14) to (start + 0, 15) diff --git a/tests/coverage/coroutine.cov-map b/tests/coverage/coroutine.cov-map index c6f2d415056d..297dde3b2b0f 100644 --- a/tests/coverage/coroutine.cov-map +++ b/tests/coverage/coroutine.cov-map @@ -13,7 +13,7 @@ Number of file 0 mappings: 4 Highest counter ID seen: c1 Function name: coroutine::main -Raw bytes (53): 0x[01, 01, 02, 01, 05, 05, 09, 09, 01, 13, 01, 02, 16, 01, 08, 0b, 00, 2e, 05, 01, 2b, 00, 2d, 02, 01, 0e, 00, 35, 05, 02, 0b, 00, 2e, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 35, 09, 02, 01, 00, 02] +Raw bytes (53): 0x[01, 01, 02, 01, 05, 05, 09, 09, 01, 13, 01, 02, 16, 01, 08, 0b, 00, 2d, 05, 01, 2b, 00, 2d, 02, 01, 0e, 00, 35, 05, 02, 0b, 00, 2e, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 35, 09, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 @@ -21,7 +21,7 @@ Number of expressions: 2 - expression 1 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 9 - Code(Counter(0)) at (prev + 19, 1) to (start + 2, 22) -- Code(Counter(0)) at (prev + 8, 11) to (start + 0, 46) +- Code(Counter(0)) at (prev + 8, 11) to (start + 0, 45) - Code(Counter(1)) at (prev + 1, 43) to (start + 0, 45) - Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 53) = (c0 - c1) diff --git a/tests/coverage/holes.cov-map b/tests/coverage/holes.cov-map index 3deacbc8e128..8ff291d2d7d3 100644 --- a/tests/coverage/holes.cov-map +++ b/tests/coverage/holes.cov-map @@ -8,20 +8,20 @@ Number of file 0 mappings: 1 Highest counter ID seen: (none) Function name: holes::main -Raw bytes (69): 0x[01, 01, 00, 0d, 01, 08, 01, 01, 12, 01, 05, 05, 00, 12, 01, 07, 09, 00, 11, 01, 09, 05, 00, 12, 01, 04, 05, 00, 12, 01, 07, 05, 00, 12, 01, 06, 05, 00, 12, 01, 04, 05, 00, 12, 01, 04, 05, 00, 12, 01, 06, 05, 03, 0f, 01, 0a, 05, 03, 0f, 01, 0a, 05, 0c, 0d, 01, 0f, 0e, 05, 02] +Raw bytes (69): 0x[01, 01, 00, 0d, 01, 08, 01, 01, 11, 01, 05, 05, 00, 11, 01, 07, 09, 00, 11, 01, 09, 05, 00, 11, 01, 04, 05, 00, 11, 01, 07, 05, 00, 11, 01, 06, 05, 00, 11, 01, 04, 05, 00, 11, 01, 04, 05, 00, 11, 01, 06, 05, 03, 0f, 01, 0a, 05, 03, 0f, 01, 0a, 05, 0c, 0d, 01, 0f, 0e, 05, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 13 -- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 18) -- Code(Counter(0)) at (prev + 5, 5) to (start + 0, 18) +- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 17) +- Code(Counter(0)) at (prev + 5, 5) to (start + 0, 17) - Code(Counter(0)) at (prev + 7, 9) to (start + 0, 17) -- Code(Counter(0)) at (prev + 9, 5) to (start + 0, 18) -- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 18) -- Code(Counter(0)) at (prev + 7, 5) to (start + 0, 18) -- Code(Counter(0)) at (prev + 6, 5) to (start + 0, 18) -- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 18) -- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 18) +- Code(Counter(0)) at (prev + 9, 5) to (start + 0, 17) +- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 17) +- Code(Counter(0)) at (prev + 7, 5) to (start + 0, 17) +- Code(Counter(0)) at (prev + 6, 5) to (start + 0, 17) +- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 17) +- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 17) - Code(Counter(0)) at (prev + 6, 5) to (start + 3, 15) - Code(Counter(0)) at (prev + 10, 5) to (start + 3, 15) - Code(Counter(0)) at (prev + 10, 5) to (start + 12, 13) diff --git a/tests/coverage/inline-dead.cov-map b/tests/coverage/inline-dead.cov-map index 49cdc514fedb..65cefe76c29a 100644 --- a/tests/coverage/inline-dead.cov-map +++ b/tests/coverage/inline-dead.cov-map @@ -8,14 +8,14 @@ Number of file 0 mappings: 1 Highest counter ID seen: (none) Function name: inline_dead::live:: -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0e, 01, 01, 09, 05, 02, 09, 00, 0f, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0e, 01, 01, 09, 05, 02, 09, 00, 0d, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 14, 1) to (start + 1, 9) -- Code(Counter(1)) at (prev + 2, 9) to (start + 0, 15) +- Code(Counter(1)) at (prev + 2, 9) to (start + 0, 13) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) diff --git a/tests/coverage/loop-break.cov-map b/tests/coverage/loop-break.cov-map index f13e82da1514..fccc4d64395b 100644 --- a/tests/coverage/loop-break.cov-map +++ b/tests/coverage/loop-break.cov-map @@ -1,12 +1,12 @@ Function name: loop_break::main -Raw bytes (31): 0x[01, 01, 01, 05, 01, 05, 01, 03, 01, 00, 0b, 05, 02, 0c, 00, 27, 01, 01, 0d, 00, 12, 02, 01, 09, 00, 0a, 01, 02, 01, 00, 02] +Raw bytes (31): 0x[01, 01, 01, 05, 01, 05, 01, 03, 01, 00, 0b, 05, 02, 0c, 00, 21, 01, 01, 0d, 00, 12, 02, 01, 09, 00, 0a, 01, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(1), rhs = Counter(0) Number of file 0 mappings: 5 - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 11) -- Code(Counter(1)) at (prev + 2, 12) to (start + 0, 39) +- Code(Counter(1)) at (prev + 2, 12) to (start + 0, 33) - Code(Counter(0)) at (prev + 1, 13) to (start + 0, 18) - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 10) = (c1 - c0) diff --git a/tests/coverage/mcdc/non_control_flow.cov-map b/tests/coverage/mcdc/non_control_flow.cov-map index c282d53c5ac2..959d21901de8 100644 --- a/tests/coverage/mcdc/non_control_flow.cov-map +++ b/tests/coverage/mcdc/non_control_flow.cov-map @@ -113,15 +113,17 @@ Number of file 0 mappings: 1 Highest counter ID seen: c0 Function name: non_control_flow::func_call -Raw bytes (50): 0x[01, 01, 02, 01, 05, 05, 09, 06, 01, 29, 01, 01, 0a, 28, 03, 02, 01, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 06, 02, 00, 00, 00, 0e, 00, 0f, 01, 01, 01, 00, 02] +Raw bytes (60): 0x[01, 01, 02, 01, 05, 05, 09, 08, 01, 29, 01, 00, 20, 01, 01, 05, 00, 08, 01, 00, 09, 00, 0a, 28, 03, 02, 00, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 06, 02, 00, 00, 00, 0e, 00, 0f, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 41, 1) to (start + 1, 10) -- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 9) to (start + 0, 15) +Number of file 0 mappings: 8 +- Code(Counter(0)) at (prev + 41, 1) to (start + 0, 32) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 8) +- Code(Counter(0)) at (prev + 0, 9) to (start + 0, 10) +- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 9) to (start + 0, 15) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 9) to (start + 0, 10) true = c1 false = (c0 - c1) diff --git a/tests/coverage/no_cov_crate.cov-map b/tests/coverage/no_cov_crate.cov-map index 04171fdb79b6..244b0099544b 100644 --- a/tests/coverage/no_cov_crate.cov-map +++ b/tests/coverage/no_cov_crate.cov-map @@ -35,22 +35,22 @@ Number of file 0 mappings: 1 Highest counter ID seen: c0 Function name: no_cov_crate::nested_fns::outer -Raw bytes (14): 0x[01, 01, 00, 02, 01, 33, 05, 02, 23, 01, 0c, 05, 00, 06] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 33, 05, 02, 22, 01, 0c, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 51, 5) to (start + 2, 35) +- Code(Counter(0)) at (prev + 51, 5) to (start + 2, 34) - Code(Counter(0)) at (prev + 12, 5) to (start + 0, 6) Highest counter ID seen: c0 Function name: no_cov_crate::nested_fns::outer_both_covered -Raw bytes (14): 0x[01, 01, 00, 02, 01, 41, 05, 02, 17, 01, 0b, 05, 00, 06] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 41, 05, 02, 16, 01, 0b, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 65, 5) to (start + 2, 23) +- Code(Counter(0)) at (prev + 65, 5) to (start + 2, 22) - Code(Counter(0)) at (prev + 11, 5) to (start + 0, 6) Highest counter ID seen: c0 diff --git a/tests/coverage/sort_groups.cov-map b/tests/coverage/sort_groups.cov-map index 69e134222960..898d68171c50 100644 --- a/tests/coverage/sort_groups.cov-map +++ b/tests/coverage/sort_groups.cov-map @@ -55,13 +55,13 @@ Number of file 0 mappings: 4 Highest counter ID seen: c1 Function name: sort_groups::main -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 06, 01, 04, 23, 05, 04, 24, 02, 06, 02, 02, 05, 00, 06, 01, 01, 05, 02, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 06, 01, 04, 1c, 05, 04, 24, 02, 06, 02, 02, 05, 00, 06, 01, 01, 05, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 6, 1) to (start + 4, 35) +- Code(Counter(0)) at (prev + 6, 1) to (start + 4, 28) - Code(Counter(1)) at (prev + 4, 36) to (start + 2, 6) - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c0 - c1) diff --git a/tests/coverage/try_error_result.cov-map b/tests/coverage/try_error_result.cov-map index 35b2c36a5751..a4a8e21d8c31 100644 --- a/tests/coverage/try_error_result.cov-map +++ b/tests/coverage/try_error_result.cov-map @@ -41,13 +41,13 @@ Number of file 0 mappings: 4 Highest counter ID seen: c1 Function name: try_error_result::main -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 71, 01, 02, 0c, 05, 03, 05, 00, 06, 02, 02, 05, 00, 0b, 01, 01, 01, 00, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 71, 01, 02, 0a, 05, 03, 05, 00, 06, 02, 02, 05, 00, 0b, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 113, 1) to (start + 2, 12) +- Code(Counter(0)) at (prev + 113, 1) to (start + 2, 10) - Code(Counter(1)) at (prev + 3, 5) to (start + 0, 6) - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 11) = (c0 - c1) @@ -55,7 +55,7 @@ Number of file 0 mappings: 4 Highest counter ID seen: c1 Function name: try_error_result::test1 -Raw bytes (67): 0x[01, 01, 04, 07, 05, 01, 09, 05, 01, 05, 09, 0b, 01, 0d, 01, 02, 17, 05, 07, 09, 00, 0e, 09, 02, 09, 04, 1a, 02, 06, 0d, 00, 29, 02, 00, 29, 00, 2a, 00, 01, 0d, 00, 2a, 00, 00, 2a, 00, 2b, 0a, 04, 0d, 00, 2a, 00, 00, 2a, 00, 2b, 0e, 03, 05, 00, 0b, 01, 01, 01, 00, 02] +Raw bytes (67): 0x[01, 01, 04, 07, 05, 01, 09, 05, 01, 05, 09, 0b, 01, 0d, 01, 02, 17, 05, 07, 09, 00, 0e, 09, 02, 09, 04, 1a, 02, 06, 0d, 00, 11, 02, 00, 29, 00, 2a, 00, 01, 0d, 00, 11, 00, 00, 2a, 00, 2b, 0a, 04, 0d, 00, 11, 00, 00, 2a, 00, 2b, 0e, 03, 05, 00, 0b, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -67,13 +67,13 @@ Number of file 0 mappings: 11 - Code(Counter(0)) at (prev + 13, 1) to (start + 2, 23) - Code(Counter(1)) at (prev + 7, 9) to (start + 0, 14) - Code(Counter(2)) at (prev + 2, 9) to (start + 4, 26) -- Code(Expression(0, Sub)) at (prev + 6, 13) to (start + 0, 41) +- Code(Expression(0, Sub)) at (prev + 6, 13) to (start + 0, 17) = ((c0 + c2) - c1) - Code(Expression(0, Sub)) at (prev + 0, 41) to (start + 0, 42) = ((c0 + c2) - c1) -- Code(Zero) at (prev + 1, 13) to (start + 0, 42) +- Code(Zero) at (prev + 1, 13) to (start + 0, 17) - Code(Zero) at (prev + 0, 42) to (start + 0, 43) -- Code(Expression(2, Sub)) at (prev + 4, 13) to (start + 0, 42) +- Code(Expression(2, Sub)) at (prev + 4, 13) to (start + 0, 17) = (c1 - c0) - Code(Zero) at (prev + 0, 42) to (start + 0, 43) - Code(Expression(3, Sub)) at (prev + 3, 5) to (start + 0, 11) @@ -82,7 +82,7 @@ Number of file 0 mappings: 11 Highest counter ID seen: c2 Function name: try_error_result::test2 -Raw bytes (336): 0x[01, 01, 36, 0d, 11, 0d, 3f, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 0d, 3f, 11, 15, 0d, 3b, 3f, 19, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 41, 53, 21, 25, 41, 21, 41, 53, 21, 25, 09, 73, 77, 2d, 0d, 29, 09, 0d, 09, 77, 0d, 29, 09, 73, 77, 2d, 0d, 29, 45, 8b, 01, 31, 35, 45, 31, 45, 8b, 01, 31, 35, 49, 9f, 01, 39, 3d, 49, 39, 49, 9f, 01, 39, 3d, 05, 09, ab, 01, 09, af, 01, 3d, b3, 01, 39, b7, 01, 35, bb, 01, 31, bf, 01, 2d, c3, 01, 29, c7, 01, 25, cb, 01, 21, cf, 01, 1d, d3, 01, 19, d7, 01, 15, 05, 11, 28, 01, 3d, 01, 03, 17, 05, 08, 09, 00, 0e, 09, 02, 09, 04, 1a, 0d, 06, 0d, 00, 2f, 11, 00, 2f, 00, 30, 02, 00, 31, 03, 35, 15, 04, 11, 00, 12, 1e, 02, 11, 04, 12, 32, 05, 11, 00, 14, 1e, 00, 17, 00, 41, 19, 00, 41, 00, 42, 26, 00, 43, 00, 5f, 1d, 00, 5f, 00, 60, 32, 01, 0d, 00, 20, 4e, 01, 11, 00, 14, 41, 00, 17, 00, 41, 21, 00, 41, 00, 42, 4a, 00, 43, 00, 60, 25, 00, 60, 00, 61, 4e, 01, 0d, 00, 20, 6e, 04, 11, 00, 14, 62, 00, 17, 00, 42, 29, 00, 42, 00, 43, 66, 00, 44, 00, 61, 2d, 00, 61, 00, 62, 6e, 01, 0d, 00, 20, 86, 01, 01, 11, 00, 14, 45, 00, 17, 01, 36, 31, 01, 36, 00, 37, 82, 01, 01, 12, 00, 2f, 35, 00, 2f, 00, 30, 86, 01, 01, 0d, 00, 20, 9a, 01, 01, 11, 00, 14, 49, 00, 17, 01, 36, 39, 02, 11, 00, 12, 96, 01, 01, 12, 00, 2f, 3d, 01, 11, 00, 12, 9a, 01, 02, 0d, 00, 20, a2, 01, 03, 05, 00, 0b, a6, 01, 01, 01, 00, 02] +Raw bytes (336): 0x[01, 01, 36, 0d, 11, 0d, 3f, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 0d, 3f, 11, 15, 0d, 3b, 3f, 19, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 41, 53, 21, 25, 41, 21, 41, 53, 21, 25, 09, 73, 77, 2d, 0d, 29, 09, 0d, 09, 77, 0d, 29, 09, 73, 77, 2d, 0d, 29, 45, 8b, 01, 31, 35, 45, 31, 45, 8b, 01, 31, 35, 49, 9f, 01, 39, 3d, 49, 39, 49, 9f, 01, 39, 3d, 05, 09, ab, 01, 09, af, 01, 3d, b3, 01, 39, b7, 01, 35, bb, 01, 31, bf, 01, 2d, c3, 01, 29, c7, 01, 25, cb, 01, 21, cf, 01, 1d, d3, 01, 19, d7, 01, 15, 05, 11, 28, 01, 3d, 01, 03, 17, 05, 08, 09, 00, 0e, 09, 02, 09, 04, 1a, 0d, 06, 0d, 00, 1f, 11, 00, 2f, 00, 30, 02, 00, 31, 03, 1c, 15, 04, 11, 00, 12, 1e, 02, 11, 03, 27, 32, 05, 11, 00, 14, 1e, 00, 17, 00, 29, 19, 00, 41, 00, 42, 26, 00, 43, 00, 47, 1d, 00, 5f, 00, 60, 32, 01, 0d, 00, 20, 4e, 01, 11, 00, 14, 41, 00, 17, 00, 29, 21, 00, 41, 00, 42, 4a, 00, 43, 00, 47, 25, 00, 60, 00, 61, 4e, 01, 0d, 00, 20, 6e, 04, 11, 00, 14, 62, 00, 17, 00, 29, 29, 00, 42, 00, 43, 66, 00, 44, 00, 48, 2d, 00, 61, 00, 62, 6e, 01, 0d, 00, 20, 86, 01, 01, 11, 00, 14, 45, 00, 17, 01, 1d, 31, 01, 36, 00, 37, 82, 01, 01, 12, 00, 16, 35, 00, 2f, 00, 30, 86, 01, 01, 0d, 00, 20, 9a, 01, 01, 11, 00, 14, 49, 00, 17, 01, 1d, 39, 02, 11, 00, 12, 96, 01, 01, 12, 00, 16, 3d, 01, 11, 00, 12, 9a, 01, 02, 0d, 00, 20, a2, 01, 03, 05, 00, 0b, a6, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 54 @@ -144,56 +144,56 @@ Number of file 0 mappings: 40 - Code(Counter(0)) at (prev + 61, 1) to (start + 3, 23) - Code(Counter(1)) at (prev + 8, 9) to (start + 0, 14) - Code(Counter(2)) at (prev + 2, 9) to (start + 4, 26) -- Code(Counter(3)) at (prev + 6, 13) to (start + 0, 47) +- Code(Counter(3)) at (prev + 6, 13) to (start + 0, 31) - Code(Counter(4)) at (prev + 0, 47) to (start + 0, 48) -- Code(Expression(0, Sub)) at (prev + 0, 49) to (start + 3, 53) +- Code(Expression(0, Sub)) at (prev + 0, 49) to (start + 3, 28) = (c3 - c4) - Code(Counter(5)) at (prev + 4, 17) to (start + 0, 18) -- Code(Expression(7, Sub)) at (prev + 2, 17) to (start + 4, 18) +- Code(Expression(7, Sub)) at (prev + 2, 17) to (start + 3, 39) = (c3 - (c4 + c5)) - Code(Expression(12, Sub)) at (prev + 5, 17) to (start + 0, 20) = (c3 - (((c4 + c5) + c6) + c7)) -- Code(Expression(7, Sub)) at (prev + 0, 23) to (start + 0, 65) +- Code(Expression(7, Sub)) at (prev + 0, 23) to (start + 0, 41) = (c3 - (c4 + c5)) - Code(Counter(6)) at (prev + 0, 65) to (start + 0, 66) -- Code(Expression(9, Sub)) at (prev + 0, 67) to (start + 0, 95) +- Code(Expression(9, Sub)) at (prev + 0, 67) to (start + 0, 71) = (c3 - ((c4 + c5) + c6)) - Code(Counter(7)) at (prev + 0, 95) to (start + 0, 96) - Code(Expression(12, Sub)) at (prev + 1, 13) to (start + 0, 32) = (c3 - (((c4 + c5) + c6) + c7)) - Code(Expression(19, Sub)) at (prev + 1, 17) to (start + 0, 20) = (c16 - (c8 + c9)) -- Code(Counter(16)) at (prev + 0, 23) to (start + 0, 65) +- Code(Counter(16)) at (prev + 0, 23) to (start + 0, 41) - Code(Counter(8)) at (prev + 0, 65) to (start + 0, 66) -- Code(Expression(18, Sub)) at (prev + 0, 67) to (start + 0, 96) +- Code(Expression(18, Sub)) at (prev + 0, 67) to (start + 0, 71) = (c16 - c8) - Code(Counter(9)) at (prev + 0, 96) to (start + 0, 97) - Code(Expression(19, Sub)) at (prev + 1, 13) to (start + 0, 32) = (c16 - (c8 + c9)) - Code(Expression(27, Sub)) at (prev + 4, 17) to (start + 0, 20) = (c2 - ((c3 + c10) + c11)) -- Code(Expression(24, Sub)) at (prev + 0, 23) to (start + 0, 66) +- Code(Expression(24, Sub)) at (prev + 0, 23) to (start + 0, 41) = (c2 - c3) - Code(Counter(10)) at (prev + 0, 66) to (start + 0, 67) -- Code(Expression(25, Sub)) at (prev + 0, 68) to (start + 0, 97) +- Code(Expression(25, Sub)) at (prev + 0, 68) to (start + 0, 72) = (c2 - (c3 + c10)) - Code(Counter(11)) at (prev + 0, 97) to (start + 0, 98) - Code(Expression(27, Sub)) at (prev + 1, 13) to (start + 0, 32) = (c2 - ((c3 + c10) + c11)) - Code(Expression(33, Sub)) at (prev + 1, 17) to (start + 0, 20) = (c17 - (c12 + c13)) -- Code(Counter(17)) at (prev + 0, 23) to (start + 1, 54) +- Code(Counter(17)) at (prev + 0, 23) to (start + 1, 29) - Code(Counter(12)) at (prev + 1, 54) to (start + 0, 55) -- Code(Expression(32, Sub)) at (prev + 1, 18) to (start + 0, 47) +- Code(Expression(32, Sub)) at (prev + 1, 18) to (start + 0, 22) = (c17 - c12) - Code(Counter(13)) at (prev + 0, 47) to (start + 0, 48) - Code(Expression(33, Sub)) at (prev + 1, 13) to (start + 0, 32) = (c17 - (c12 + c13)) - Code(Expression(38, Sub)) at (prev + 1, 17) to (start + 0, 20) = (c18 - (c14 + c15)) -- Code(Counter(18)) at (prev + 0, 23) to (start + 1, 54) +- Code(Counter(18)) at (prev + 0, 23) to (start + 1, 29) - Code(Counter(14)) at (prev + 2, 17) to (start + 0, 18) -- Code(Expression(37, Sub)) at (prev + 1, 18) to (start + 0, 47) +- Code(Expression(37, Sub)) at (prev + 1, 18) to (start + 0, 22) = (c18 - c14) - Code(Counter(15)) at (prev + 1, 17) to (start + 0, 18) - Code(Expression(38, Sub)) at (prev + 2, 13) to (start + 0, 32) diff --git a/tests/coverage/try_error_result.coverage b/tests/coverage/try_error_result.coverage index 7100248f7df8..7a89c0452ac4 100644 --- a/tests/coverage/try_error_result.coverage +++ b/tests/coverage/try_error_result.coverage @@ -86,7 +86,7 @@ LL| 1| . LL| 1| expect_err( LL| 1| "call should fail" - LL| 1| ); + LL| | ); LL| 1| let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?; ^0 ^0 ^0 LL| 0| assert_eq!(val, 57); diff --git a/tests/coverage/unicode.cov-map b/tests/coverage/unicode.cov-map index 7b9dc0b9bc88..29d40a055130 100644 --- a/tests/coverage/unicode.cov-map +++ b/tests/coverage/unicode.cov-map @@ -1,5 +1,5 @@ Function name: unicode::main -Raw bytes (53): 0x[01, 01, 02, 05, 01, 01, 0d, 09, 01, 0e, 01, 00, 0b, 02, 01, 09, 00, 0c, 05, 00, 10, 00, 1b, 02, 00, 1c, 00, 28, 01, 02, 08, 00, 25, 09, 00, 29, 00, 46, 0d, 00, 47, 02, 06, 06, 02, 05, 00, 06, 01, 02, 05, 01, 02] +Raw bytes (53): 0x[01, 01, 02, 05, 01, 01, 0d, 09, 01, 0e, 01, 00, 0b, 02, 01, 09, 00, 0c, 05, 00, 10, 00, 1b, 02, 00, 1c, 00, 28, 01, 02, 08, 00, 23, 09, 00, 29, 00, 44, 0d, 00, 47, 02, 06, 06, 02, 05, 00, 06, 01, 02, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 @@ -12,8 +12,8 @@ Number of file 0 mappings: 9 - Code(Counter(1)) at (prev + 0, 16) to (start + 0, 27) - Code(Expression(0, Sub)) at (prev + 0, 28) to (start + 0, 40) = (c1 - c0) -- Code(Counter(0)) at (prev + 2, 8) to (start + 0, 37) -- Code(Counter(2)) at (prev + 0, 41) to (start + 0, 70) +- Code(Counter(0)) at (prev + 2, 8) to (start + 0, 35) +- Code(Counter(2)) at (prev + 0, 41) to (start + 0, 68) - Code(Counter(3)) at (prev + 0, 71) to (start + 2, 6) - Code(Expression(1, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c0 - c3) diff --git a/tests/coverage/unicode.coverage b/tests/coverage/unicode.coverage index 84c5f05a8c4e..443499545500 100644 --- a/tests/coverage/unicode.coverage +++ b/tests/coverage/unicode.coverage @@ -15,7 +15,7 @@ LL| 33| for _İ in 'А'..='Я' { /* Я */ } ^32 ^32 LL| | - LL| 1| if 申し訳ございません() && 申し訳ございません() { + LL| 1| if 申し訳ございません() && 申し訳ございません() { ^0 LL| 0| println!("true"); LL| 1| } diff --git a/tests/coverage/unreachable.cov-map b/tests/coverage/unreachable.cov-map index 97961bc74145..0bc18bfcbd31 100644 --- a/tests/coverage/unreachable.cov-map +++ b/tests/coverage/unreachable.cov-map @@ -1,27 +1,27 @@ Function name: unreachable::UNREACHABLE_CLOSURE::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 0e, 27, 00, 47] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 0e, 27, 00, 45] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 14, 39) to (start + 0, 71) +- Code(Zero) at (prev + 14, 39) to (start + 0, 69) Highest counter ID seen: (none) Function name: unreachable::unreachable_function (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 10, 01, 01, 25] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 10, 01, 01, 23] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 16, 1) to (start + 1, 37) +- Code(Zero) at (prev + 16, 1) to (start + 1, 35) Highest counter ID seen: (none) Function name: unreachable::unreachable_intrinsic (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 01, 01, 2c] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 01, 01, 2a] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 21, 1) to (start + 1, 44) +- Code(Zero) at (prev + 21, 1) to (start + 1, 42) Highest counter ID seen: (none) diff --git a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff index 8e1cdb7182b1..542b70bcee96 100644 --- a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff @@ -27,10 +27,10 @@ } + coverage Code { bcb: bcb0 } => $DIR/branch_match_arms.rs:14:1: 15:21 (#0); -+ coverage Code { bcb: bcb1 } => $DIR/branch_match_arms.rs:16:17: 16:33 (#0); -+ coverage Code { bcb: bcb3 } => $DIR/branch_match_arms.rs:17:17: 17:33 (#0); -+ coverage Code { bcb: bcb4 } => $DIR/branch_match_arms.rs:18:17: 18:33 (#0); -+ coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:17: 19:33 (#0); ++ coverage Code { bcb: bcb1 } => $DIR/branch_match_arms.rs:16:17: 16:32 (#0); ++ coverage Code { bcb: bcb3 } => $DIR/branch_match_arms.rs:17:17: 17:32 (#0); ++ coverage Code { bcb: bcb4 } => $DIR/branch_match_arms.rs:18:17: 18:32 (#0); ++ coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:17: 19:32 (#0); + coverage Code { bcb: bcb2 } => $DIR/branch_match_arms.rs:21:2: 21:2 (#0); + bb0: { diff --git a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff index 1a71cb8dea7f..30de92f3b868 100644 --- a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff @@ -8,7 +8,7 @@ let mut _3: !; + coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:13:1: 13:11 (#0); -+ coverage Code { bcb: bcb1 } => $DIR/instrument_coverage.rs:15:12: 15:17 (#0); ++ coverage Code { bcb: bcb1 } => $DIR/instrument_coverage.rs:15:12: 15:15 (#0); + coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:16:13: 16:18 (#0); + coverage Code { bcb: bcb3 } => $DIR/instrument_coverage.rs:17:10: 17:10 (#0); + coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:19:2: 19:2 (#0); From 62a533ce7801ac35344f3ebaa983e90dbeba447a Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 25 Mar 2025 20:34:32 +1100 Subject: [PATCH 703/745] coverage: Instead of splitting, just discard any span that overlaps a hole --- .../rustc_mir_transform/src/coverage/spans.rs | 62 +++++-------------- compiler/rustc_mir_transform/src/lib.rs | 1 + tests/coverage/async_block.cov-map | 8 +-- tests/coverage/async_block.coverage | 2 +- tests/coverage/async_closure.cov-map | 14 +++-- tests/coverage/async_closure.coverage | 4 +- tests/coverage/closure.cov-map | 12 ++-- tests/coverage/closure.coverage | 22 +++---- tests/coverage/holes.cov-map | 6 +- tests/coverage/holes.coverage | 20 +++--- 10 files changed, 63 insertions(+), 88 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 8befe9c5d8dd..b1f613432a8b 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -1,4 +1,5 @@ use std::collections::VecDeque; +use std::iter; use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir; @@ -83,9 +84,7 @@ pub(super) fn extract_refined_covspans( // Split the covspans into separate buckets that don't overlap any holes. let buckets = divide_spans_into_buckets(covspans, &holes); - for mut covspans in buckets { - // Make sure each individual bucket is internally sorted. - covspans.sort_by(compare_covspans); + for covspans in buckets { let _span = debug_span!("processing bucket", ?covspans).entered(); let mut covspans = remove_unwanted_overlapping_spans(covspans); @@ -161,50 +160,37 @@ fn split_visible_macro_spans(covspans: &mut Vec) { } /// Uses the holes to divide the given covspans into buckets, such that: -/// - No span in any hole overlaps a bucket (truncating the spans if necessary). +/// - No span in any hole overlaps a bucket (discarding spans if necessary). /// - The spans in each bucket are strictly after all spans in previous buckets, /// and strictly before all spans in subsequent buckets. /// -/// The resulting buckets are sorted relative to each other, but might not be -/// internally sorted. +/// The lists of covspans and holes must be sorted. +/// The resulting buckets are sorted relative to each other, and each bucket's +/// contents are sorted. #[instrument(level = "debug")] fn divide_spans_into_buckets(input_covspans: Vec, holes: &[Hole]) -> Vec> { debug_assert!(input_covspans.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le())); debug_assert!(holes.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le())); - // Now we're ready to start carving holes out of the initial coverage spans, - // and grouping them in buckets separated by the holes. + // Now we're ready to start grouping spans into buckets separated by holes. let mut input_covspans = VecDeque::from(input_covspans); - let mut fragments = vec![]; // For each hole: // - Identify the spans that are entirely or partly before the hole. - // - Put those spans in a corresponding bucket, truncated to the start of the hole. - // - If one of those spans also extends after the hole, put the rest of it - // in a "fragments" vector that is processed by the next hole. + // - Discard any that overlap with the hole. + // - Add the remaining identified spans to the corresponding bucket. let mut buckets = (0..holes.len()).map(|_| vec![]).collect::>(); for (hole, bucket) in holes.iter().zip(&mut buckets) { - let fragments_from_prev = std::mem::take(&mut fragments); - - // Only inspect spans that precede or overlap this hole, - // leaving the rest to be inspected by later holes. - // (This relies on the spans and holes both being sorted.) - let relevant_input_covspans = - drain_front_while(&mut input_covspans, |c| c.span.lo() < hole.span.hi()); - - for covspan in fragments_from_prev.into_iter().chain(relevant_input_covspans) { - let (before, after) = covspan.split_around_hole_span(hole.span); - bucket.extend(before); - fragments.extend(after); - } + bucket.extend( + drain_front_while(&mut input_covspans, |c| c.span.lo() < hole.span.hi()) + .filter(|c| !c.span.overlaps(hole.span)), + ); } - // After finding the spans before each hole, any remaining fragments/spans - // form their own final bucket, after the final hole. + // Any remaining spans form their own final bucket, after the final hole. // (If there were no holes, this will just be all of the initial spans.) - fragments.extend(input_covspans); - buckets.push(fragments); + buckets.push(Vec::from(input_covspans)); buckets } @@ -215,7 +201,7 @@ fn drain_front_while<'a, T>( queue: &'a mut VecDeque, mut pred_fn: impl FnMut(&T) -> bool, ) -> impl Iterator { - std::iter::from_fn(move || if pred_fn(queue.front()?) { queue.pop_front() } else { None }) + iter::from_fn(move || queue.pop_front_if(|x| pred_fn(x))) } /// Takes one of the buckets of (sorted) spans extracted from MIR, and "refines" @@ -258,22 +244,6 @@ struct Covspan { } impl Covspan { - /// Splits this covspan into 0-2 parts: - /// - The part that is strictly before the hole span, if any. - /// - The part that is strictly after the hole span, if any. - fn split_around_hole_span(&self, hole_span: Span) -> (Option, Option) { - let before = try { - let span = self.span.trim_end(hole_span)?; - Self { span, ..*self } - }; - let after = try { - let span = self.span.trim_start(hole_span)?; - Self { span, ..*self } - }; - - (before, after) - } - /// If `self` and `other` can be merged (i.e. they have the same BCB), /// mutates `self.span` to also include `other.span` and returns true. /// diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 205d388f4fb5..c372b77ad257 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -12,6 +12,7 @@ #![feature(map_try_insert)] #![feature(never_type)] #![feature(try_blocks)] +#![feature(vec_deque_pop_if)] #![feature(yeet_expr)] // tidy-alphabetical-end diff --git a/tests/coverage/async_block.cov-map b/tests/coverage/async_block.cov-map index 5eb69e668ca5..d9196f446f13 100644 --- a/tests/coverage/async_block.cov-map +++ b/tests/coverage/async_block.cov-map @@ -1,5 +1,5 @@ Function name: async_block::main -Raw bytes (36): 0x[01, 01, 01, 05, 01, 06, 01, 07, 01, 00, 0b, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 13, 02, 00, 14, 01, 16, 02, 07, 0a, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (36): 0x[01, 01, 01, 05, 01, 06, 01, 07, 01, 00, 0b, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 13, 02, 01, 0d, 00, 13, 02, 07, 09, 00, 22, 01, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 @@ -9,11 +9,11 @@ Number of file 0 mappings: 6 - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 10) = (c1 - c0) - Code(Counter(1)) at (prev + 0, 14) to (start + 0, 19) -- Code(Expression(0, Sub)) at (prev + 0, 20) to (start + 1, 22) +- Code(Expression(0, Sub)) at (prev + 1, 13) to (start + 0, 19) = (c1 - c0) -- Code(Expression(0, Sub)) at (prev + 7, 10) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 7, 9) to (start + 0, 34) = (c1 - c0) -- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +- Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: async_block::main::{closure#0} diff --git a/tests/coverage/async_block.coverage b/tests/coverage/async_block.coverage index 9e3294492cd0..4e00024aebd2 100644 --- a/tests/coverage/async_block.coverage +++ b/tests/coverage/async_block.coverage @@ -15,6 +15,6 @@ LL| 12| } LL| 16| }; LL| 16| executor::block_on(future); - LL| 16| } + LL| | } LL| 1|} diff --git a/tests/coverage/async_closure.cov-map b/tests/coverage/async_closure.cov-map index 0e1d98778307..a4ef0ceeb6df 100644 --- a/tests/coverage/async_closure.cov-map +++ b/tests/coverage/async_closure.cov-map @@ -30,21 +30,23 @@ Number of file 0 mappings: 2 Highest counter ID seen: c0 Function name: async_closure::main::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 23, 00, 24] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35) +- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36) Highest counter ID seen: c0 Function name: async_closure::main::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 23, 00, 24] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35) +- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36) Highest counter ID seen: c0 Function name: async_closure::main::{closure#0}::{closure#0}:: diff --git a/tests/coverage/async_closure.coverage b/tests/coverage/async_closure.coverage index 10a8ea14504b..5aed131de2e5 100644 --- a/tests/coverage/async_closure.coverage +++ b/tests/coverage/async_closure.coverage @@ -9,13 +9,15 @@ LL| | LL| 1|pub fn main() { LL| 2| let async_closure = async || {}; - ^1 ------------------ | async_closure::main::{closure#0}: | LL| 1| let async_closure = async || {}; ------------------ | async_closure::main::{closure#0}: | LL| 1| let async_closure = async || {}; + ------------------ + | async_closure::main::{closure#0}::{closure#0}::: + | LL| 1| let async_closure = async || {}; ------------------ LL| 1| executor::block_on(async_closure()); LL| 1| executor::block_on(call_once(async_closure)); diff --git a/tests/coverage/closure.cov-map b/tests/coverage/closure.cov-map index fa20c8cf6d78..2d784ba09b60 100644 --- a/tests/coverage/closure.cov-map +++ b/tests/coverage/closure.cov-map @@ -1,15 +1,15 @@ Function name: closure::main -Raw bytes (126): 0x[01, 01, 01, 01, 05, 18, 01, 09, 01, 0f, 0d, 01, 16, 0e, 06, 0a, 01, 10, 05, 13, 0d, 01, 1a, 0e, 06, 0a, 01, 10, 05, 0c, 16, 01, 16, 05, 0d, 18, 01, 19, 09, 01, 1e, 01, 04, 09, 00, 29, 01, 01, 09, 00, 2d, 01, 01, 09, 00, 24, 01, 05, 09, 00, 24, 01, 02, 09, 00, 21, 01, 04, 09, 00, 21, 01, 04, 09, 00, 28, 01, 09, 09, 00, 32, 01, 04, 09, 00, 33, 01, 07, 09, 00, 4b, 01, 08, 09, 00, 48, 01, 0a, 09, 00, 47, 01, 08, 09, 00, 44, 01, 0a, 08, 00, 10, 05, 00, 11, 04, 06, 02, 04, 05, 00, 06, 01, 01, 05, 03, 02] +Raw bytes (126): 0x[01, 01, 01, 01, 05, 18, 01, 09, 01, 0d, 1b, 01, 1a, 05, 02, 0a, 01, 0c, 05, 11, 1b, 01, 1e, 05, 02, 0a, 01, 0c, 05, 0c, 16, 01, 16, 05, 0d, 18, 01, 19, 09, 01, 1e, 01, 04, 09, 00, 29, 01, 01, 09, 00, 2d, 01, 01, 09, 00, 24, 01, 05, 09, 00, 24, 01, 02, 09, 00, 21, 01, 04, 09, 00, 21, 01, 04, 09, 00, 28, 01, 09, 09, 00, 32, 01, 04, 09, 00, 33, 01, 07, 09, 00, 4b, 01, 08, 09, 00, 48, 01, 0a, 09, 00, 47, 01, 08, 09, 00, 44, 01, 0a, 08, 00, 10, 05, 00, 11, 04, 06, 02, 04, 05, 00, 06, 01, 01, 05, 03, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 24 -- Code(Counter(0)) at (prev + 9, 1) to (start + 15, 13) -- Code(Counter(0)) at (prev + 22, 14) to (start + 6, 10) -- Code(Counter(0)) at (prev + 16, 5) to (start + 19, 13) -- Code(Counter(0)) at (prev + 26, 14) to (start + 6, 10) -- Code(Counter(0)) at (prev + 16, 5) to (start + 12, 22) +- Code(Counter(0)) at (prev + 9, 1) to (start + 13, 27) +- Code(Counter(0)) at (prev + 26, 5) to (start + 2, 10) +- Code(Counter(0)) at (prev + 12, 5) to (start + 17, 27) +- Code(Counter(0)) at (prev + 30, 5) to (start + 2, 10) +- Code(Counter(0)) at (prev + 12, 5) to (start + 12, 22) - Code(Counter(0)) at (prev + 22, 5) to (start + 13, 24) - Code(Counter(0)) at (prev + 25, 9) to (start + 1, 30) - Code(Counter(0)) at (prev + 4, 9) to (start + 0, 41) diff --git a/tests/coverage/closure.coverage b/tests/coverage/closure.coverage index 3eac52eb7236..2deeb9806c4d 100644 --- a/tests/coverage/closure.coverage +++ b/tests/coverage/closure.coverage @@ -20,18 +20,18 @@ LL| 1| some_string LL| 1| . LL| 1| unwrap_or_else - LL| 1| ( - LL| 1| || + LL| | ( + LL| | || LL| 0| { LL| 0| let mut countdown = 0; LL| 0| if is_false { LL| 0| countdown = 10; LL| 0| } LL| 0| "alt string 1".to_owned() - LL| 1| } - LL| 1| ) - LL| 1| ); - LL| 1| + LL| 0| } + LL| | ) + LL| | ); + LL| | LL| 1| some_string = Some(String::from("the string content")); LL| 1| let LL| 1| a @@ -62,8 +62,8 @@ LL| 1| some_string LL| 1| . LL| 1| unwrap_or_else - LL| 1| ( - LL| 1| || + LL| | ( + LL| | || LL| 1| { LL| 1| let mut countdown = 0; LL| 1| if is_false { @@ -71,9 +71,9 @@ LL| 1| } LL| 1| "alt string 3".to_owned() LL| 1| } - LL| 1| ) - LL| 1| ); - LL| 1| + LL| | ) + LL| | ); + LL| | LL| 1| some_string = None; LL| 1| let LL| 1| a diff --git a/tests/coverage/holes.cov-map b/tests/coverage/holes.cov-map index 8ff291d2d7d3..6e2d243e8dd2 100644 --- a/tests/coverage/holes.cov-map +++ b/tests/coverage/holes.cov-map @@ -8,7 +8,7 @@ Number of file 0 mappings: 1 Highest counter ID seen: (none) Function name: holes::main -Raw bytes (69): 0x[01, 01, 00, 0d, 01, 08, 01, 01, 11, 01, 05, 05, 00, 11, 01, 07, 09, 00, 11, 01, 09, 05, 00, 11, 01, 04, 05, 00, 11, 01, 07, 05, 00, 11, 01, 06, 05, 00, 11, 01, 04, 05, 00, 11, 01, 04, 05, 00, 11, 01, 06, 05, 03, 0f, 01, 0a, 05, 03, 0f, 01, 0a, 05, 0c, 0d, 01, 0f, 0e, 05, 02] +Raw bytes (69): 0x[01, 01, 00, 0d, 01, 08, 01, 01, 11, 01, 05, 05, 00, 11, 01, 07, 09, 00, 11, 01, 09, 05, 00, 11, 01, 04, 05, 00, 11, 01, 07, 05, 00, 11, 01, 06, 05, 00, 11, 01, 04, 05, 00, 11, 01, 04, 05, 00, 11, 01, 06, 05, 03, 0f, 01, 0a, 05, 03, 0f, 01, 0a, 05, 06, 27, 01, 13, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 @@ -24,8 +24,8 @@ Number of file 0 mappings: 13 - Code(Counter(0)) at (prev + 4, 5) to (start + 0, 17) - Code(Counter(0)) at (prev + 6, 5) to (start + 3, 15) - Code(Counter(0)) at (prev + 10, 5) to (start + 3, 15) -- Code(Counter(0)) at (prev + 10, 5) to (start + 12, 13) -- Code(Counter(0)) at (prev + 15, 14) to (start + 5, 2) +- Code(Counter(0)) at (prev + 10, 5) to (start + 6, 39) +- Code(Counter(0)) at (prev + 19, 5) to (start + 1, 2) Highest counter ID seen: c0 Function name: holes::main::_unused_fn (unused) diff --git a/tests/coverage/holes.coverage b/tests/coverage/holes.coverage index 1b45c12156ae..a6a02f1b9d08 100644 --- a/tests/coverage/holes.coverage +++ b/tests/coverage/holes.coverage @@ -84,18 +84,18 @@ LL| 1| // `nested_filter::OnlyBodies` or equivalent. LL| 1| #[rustfmt::skip] LL| 1| let _const_block_inside_anon_const = - LL| 1| [ - LL| 1| 0 - LL| 1| ; - LL| 1| 7 - LL| 1| + - LL| 1| const + LL| | [ + LL| | 0 + LL| | ; + LL| | 7 + LL| | + + LL| | const LL| | { LL| | 3 - LL| 1| } - LL| 1| ] - LL| 1| ; - LL| 1| + LL| | } + LL| | ] + LL| | ; + LL| | LL| 1| black_box(()); LL| 1|} From 26cea8a2863a3aa0fd169d8561ce77036ef6983e Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 25 Mar 2025 22:02:22 +1100 Subject: [PATCH 704/745] coverage: Don't split bang-macro spans, just truncate them --- .../src/coverage/mappings.rs | 2 +- .../rustc_mir_transform/src/coverage/spans.rs | 43 ++++++------------- tests/coverage/abort.cov-map | 4 +- tests/coverage/assert_not.cov-map | 10 ++--- tests/coverage/bad_counter_ids.cov-map | 16 +++---- tests/coverage/branch/guard.cov-map | 4 +- tests/coverage/branch/if-let.cov-map | 4 +- tests/coverage/branch/if.cov-map | 16 +++---- tests/coverage/branch/lazy-boolean.cov-map | 16 +++---- tests/coverage/branch/let-else.cov-map | 4 +- tests/coverage/branch/match-arms.cov-map | 12 +++--- tests/coverage/branch/match-trivial.cov-map | 8 ++-- tests/coverage/branch/while.cov-map | 16 +++---- tests/coverage/closure_macro.cov-map | 6 +-- tests/coverage/closure_macro_async.cov-map | 6 +-- tests/coverage/coroutine.cov-map | 6 +-- tests/coverage/inline.cov-map | 4 +- tests/coverage/issue-83601.cov-map | 6 +-- tests/coverage/issue-84561.cov-map | 34 +++++++-------- tests/coverage/issue-84561.coverage | 42 +++++++++--------- tests/coverage/loops_branches.cov-map | 12 +++--- tests/coverage/macro_name_span.cov-map | 4 +- tests/coverage/panic_unwind.cov-map | 4 +- tests/coverage/try_error_result.cov-map | 12 +++--- tests/coverage/yield.cov-map | 10 ++--- 25 files changed, 142 insertions(+), 159 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/mappings.rs b/compiler/rustc_mir_transform/src/coverage/mappings.rs index d83c0d40a7e5..73bd2d0705e1 100644 --- a/compiler/rustc_mir_transform/src/coverage/mappings.rs +++ b/compiler/rustc_mir_transform/src/coverage/mappings.rs @@ -96,7 +96,7 @@ pub(super) fn extract_all_mapping_info_from_mir<'tcx>( } } else { // Extract coverage spans from MIR statements/terminators as normal. - extract_refined_covspans(mir_body, hir_info, graph, &mut code_mappings); + extract_refined_covspans(tcx, mir_body, hir_info, graph, &mut code_mappings); } branch_pairs.extend(extract_branch_pairs(mir_body, hir_info, graph)); diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index b1f613432a8b..f57a158e3e4a 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -3,6 +3,7 @@ use std::iter; use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir; +use rustc_middle::ty::TyCtxt; use rustc_span::{DesugaringKind, ExpnKind, MacroKind, Span}; use tracing::{debug, debug_span, instrument}; @@ -12,8 +13,9 @@ use crate::coverage::{ExtractedHirInfo, mappings, unexpand}; mod from_mir; -pub(super) fn extract_refined_covspans( - mir_body: &mir::Body<'_>, +pub(super) fn extract_refined_covspans<'tcx>( + tcx: TyCtxt<'tcx>, + mir_body: &mir::Body<'tcx>, hir_info: &ExtractedHirInfo, graph: &CoverageGraph, code_mappings: &mut impl Extend, @@ -51,7 +53,7 @@ pub(super) fn extract_refined_covspans( // First, perform the passes that need macro information. covspans.sort_by(|a, b| graph.cmp_in_dominator_order(a.bcb, b.bcb)); remove_unwanted_expansion_spans(&mut covspans); - split_visible_macro_spans(&mut covspans); + shrink_visible_macro_spans(tcx, &mut covspans); // We no longer need the extra information in `SpanFromMir`, so convert to `Covspan`. let mut covspans = covspans.into_iter().map(SpanFromMir::into_covspan).collect::>(); @@ -128,35 +130,16 @@ fn remove_unwanted_expansion_spans(covspans: &mut Vec) { } /// When a span corresponds to a macro invocation that is visible from the -/// function body, split it into two parts. The first part covers just the -/// macro name plus `!`, and the second part covers the rest of the macro -/// invocation. This seems to give better results for code that uses macros. -fn split_visible_macro_spans(covspans: &mut Vec) { - let mut extra_spans = vec![]; +/// function body, truncate it to just the macro name plus `!`. +/// This seems to give better results for code that uses macros. +fn shrink_visible_macro_spans(tcx: TyCtxt<'_>, covspans: &mut Vec) { + let source_map = tcx.sess.source_map(); - covspans.retain(|covspan| { - let Some(ExpnKind::Macro(MacroKind::Bang, visible_macro)) = covspan.expn_kind else { - return true; - }; - - let split_len = visible_macro.as_str().len() as u32 + 1; - let (before, after) = covspan.span.split_at(split_len); - if !covspan.span.contains(before) || !covspan.span.contains(after) { - // Something is unexpectedly wrong with the split point. - // The debug assertion in `split_at` will have already caught this, - // but in release builds it's safer to do nothing and maybe get a - // bug report for unexpected coverage, rather than risk an ICE. - return true; + for covspan in covspans { + if matches!(covspan.expn_kind, Some(ExpnKind::Macro(MacroKind::Bang, _))) { + covspan.span = source_map.span_through_char(covspan.span, '!'); } - - extra_spans.push(SpanFromMir::new(before, covspan.expn_kind.clone(), covspan.bcb)); - extra_spans.push(SpanFromMir::new(after, covspan.expn_kind.clone(), covspan.bcb)); - false // Discard the original covspan that we just split. - }); - - // The newly-split spans are added at the end, so any previous sorting - // is not preserved. - covspans.extend(extra_spans); + } } /// Uses the holes to divide the given covspans into buckets, such that: diff --git a/tests/coverage/abort.cov-map b/tests/coverage/abort.cov-map index 84fae4a595a7..26536caeba52 100644 --- a/tests/coverage/abort.cov-map +++ b/tests/coverage/abort.cov-map @@ -34,14 +34,14 @@ Number of file 0 mappings: 13 Highest counter ID seen: c4 Function name: abort::might_abort -Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 03, 01, 01, 14, 05, 02, 09, 01, 24, 02, 02, 0c, 03, 02] +Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 03, 01, 01, 14, 05, 02, 09, 01, 0f, 02, 02, 0c, 03, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 3, 1) to (start + 1, 20) -- Code(Counter(1)) at (prev + 2, 9) to (start + 1, 36) +- Code(Counter(1)) at (prev + 2, 9) to (start + 1, 15) - Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 3, 2) = (c0 - c1) Highest counter ID seen: c1 diff --git a/tests/coverage/assert_not.cov-map b/tests/coverage/assert_not.cov-map index 526110ebbb76..3aef4274edc3 100644 --- a/tests/coverage/assert_not.cov-map +++ b/tests/coverage/assert_not.cov-map @@ -1,13 +1,13 @@ Function name: assert_not::main -Raw bytes (29): 0x[01, 01, 00, 05, 01, 06, 01, 01, 12, 01, 02, 05, 00, 14, 01, 01, 05, 00, 14, 01, 01, 05, 00, 16, 01, 01, 01, 00, 02] +Raw bytes (29): 0x[01, 01, 00, 05, 01, 06, 01, 01, 11, 01, 02, 05, 00, 13, 01, 01, 05, 00, 13, 01, 01, 05, 00, 15, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 5 -- Code(Counter(0)) at (prev + 6, 1) to (start + 1, 18) -- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 20) -- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 20) -- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 22) +- Code(Counter(0)) at (prev + 6, 1) to (start + 1, 17) +- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 19) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 19) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 21) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/bad_counter_ids.cov-map b/tests/coverage/bad_counter_ids.cov-map index baac0073fcbe..f08a70a899d0 100644 --- a/tests/coverage/bad_counter_ids.cov-map +++ b/tests/coverage/bad_counter_ids.cov-map @@ -1,10 +1,10 @@ Function name: bad_counter_ids::eq_bad -Raw bytes (14): 0x[01, 01, 00, 02, 01, 24, 01, 02, 1f, 00, 03, 01, 00, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 24, 01, 02, 0f, 00, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 36, 1) to (start + 2, 31) +- Code(Counter(0)) at (prev + 36, 1) to (start + 2, 15) - Code(Zero) at (prev + 3, 1) to (start + 0, 2) Highest counter ID seen: c0 @@ -20,12 +20,12 @@ Number of file 0 mappings: 3 Highest counter ID seen: c0 Function name: bad_counter_ids::eq_good -Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 01, 02, 1f, 01, 03, 01, 00, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 01, 02, 0f, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 16, 1) to (start + 2, 31) +- Code(Counter(0)) at (prev + 16, 1) to (start + 2, 15) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) Highest counter ID seen: c0 @@ -41,12 +41,12 @@ Number of file 0 mappings: 3 Highest counter ID seen: c0 Function name: bad_counter_ids::ne_bad -Raw bytes (14): 0x[01, 01, 00, 02, 01, 2e, 01, 02, 1f, 00, 03, 01, 00, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 2e, 01, 02, 0f, 00, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 46, 1) to (start + 2, 31) +- Code(Counter(0)) at (prev + 46, 1) to (start + 2, 15) - Code(Zero) at (prev + 3, 1) to (start + 0, 2) Highest counter ID seen: c0 @@ -62,12 +62,12 @@ Number of file 0 mappings: 3 Highest counter ID seen: c0 Function name: bad_counter_ids::ne_good -Raw bytes (14): 0x[01, 01, 00, 02, 01, 1a, 01, 02, 1f, 01, 03, 01, 00, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 1a, 01, 02, 0f, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 26, 1) to (start + 2, 31) +- Code(Counter(0)) at (prev + 26, 1) to (start + 2, 15) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/branch/guard.cov-map b/tests/coverage/branch/guard.cov-map index 55f45daa9c93..46533df00f71 100644 --- a/tests/coverage/branch/guard.cov-map +++ b/tests/coverage/branch/guard.cov-map @@ -1,5 +1,5 @@ Function name: guard::branch_match_guard -Raw bytes (89): 0x[01, 01, 08, 05, 0d, 09, 05, 05, 0f, 0d, 11, 17, 1b, 01, 05, 1f, 11, 09, 0d, 0d, 01, 0c, 01, 01, 10, 02, 03, 0b, 00, 0c, 06, 01, 14, 02, 0a, 0d, 03, 0e, 00, 0f, 05, 00, 14, 00, 19, 20, 0d, 02, 00, 14, 00, 1e, 0d, 00, 1d, 02, 0a, 11, 03, 0e, 00, 0f, 02, 00, 14, 00, 19, 20, 11, 0a, 00, 14, 00, 1e, 11, 00, 1d, 02, 0a, 12, 03, 0e, 02, 0a, 01, 04, 01, 00, 02] +Raw bytes (89): 0x[01, 01, 08, 05, 0d, 09, 05, 05, 0f, 0d, 11, 17, 1b, 01, 05, 1f, 11, 09, 0d, 0d, 01, 0c, 01, 01, 0e, 02, 03, 0b, 00, 0c, 06, 01, 14, 02, 0a, 0d, 03, 0e, 00, 0f, 05, 00, 14, 00, 19, 20, 0d, 02, 00, 14, 00, 1e, 0d, 00, 1d, 02, 0a, 11, 03, 0e, 00, 0f, 02, 00, 14, 00, 19, 20, 11, 0a, 00, 14, 00, 1e, 11, 00, 1d, 02, 0a, 12, 03, 0e, 02, 0a, 01, 04, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 8 @@ -12,7 +12,7 @@ Number of expressions: 8 - expression 6 operands: lhs = Expression(7, Add), rhs = Counter(4) - expression 7 operands: lhs = Counter(2), rhs = Counter(3) Number of file 0 mappings: 13 -- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14) - Code(Expression(0, Sub)) at (prev + 3, 11) to (start + 0, 12) = (c1 - c3) - Code(Expression(1, Sub)) at (prev + 1, 20) to (start + 2, 10) diff --git a/tests/coverage/branch/if-let.cov-map b/tests/coverage/branch/if-let.cov-map index db45df2a5cd0..7f6b174615a9 100644 --- a/tests/coverage/branch/if-let.cov-map +++ b/tests/coverage/branch/if-let.cov-map @@ -1,11 +1,11 @@ Function name: if_let::if_let -Raw bytes (43): 0x[01, 01, 01, 01, 05, 07, 01, 0c, 01, 01, 10, 20, 02, 05, 03, 0c, 00, 13, 02, 00, 11, 00, 12, 01, 00, 16, 00, 1b, 02, 00, 1c, 02, 06, 05, 02, 0c, 02, 06, 01, 03, 05, 01, 02] +Raw bytes (43): 0x[01, 01, 01, 01, 05, 07, 01, 0c, 01, 01, 0e, 20, 02, 05, 03, 0c, 00, 13, 02, 00, 11, 00, 12, 01, 00, 16, 00, 1b, 02, 00, 1c, 02, 06, 05, 02, 0c, 02, 06, 01, 03, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14) - Branch { true: Expression(0, Sub), false: Counter(1) } at (prev + 3, 12) to (start + 0, 19) true = (c0 - c1) false = c1 diff --git a/tests/coverage/branch/if.cov-map b/tests/coverage/branch/if.cov-map index 392ace1683a7..1d40f032aa87 100644 --- a/tests/coverage/branch/if.cov-map +++ b/tests/coverage/branch/if.cov-map @@ -1,5 +1,5 @@ Function name: if::branch_and -Raw bytes (54): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 08, 01, 2b, 01, 01, 10, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 20, 09, 06, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (54): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 08, 01, 2b, 01, 01, 0e, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 20, 09, 06, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 @@ -7,7 +7,7 @@ Number of expressions: 3 - expression 1 operands: lhs = Counter(1), rhs = Counter(2) - expression 2 operands: lhs = Counter(0), rhs = Counter(2) Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 43, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 43, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 3, 8) to (start + 0, 9) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 8) to (start + 0, 9) true = c1 @@ -23,7 +23,7 @@ Number of file 0 mappings: 8 Highest counter ID seen: c2 Function name: if::branch_not -Raw bytes (116): 0x[01, 01, 07, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 01, 11, 01, 11, 12, 01, 0c, 01, 01, 10, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 01, 09, 00, 10, 02, 01, 05, 00, 06, 01, 01, 08, 00, 0a, 20, 0a, 09, 00, 08, 00, 0a, 0a, 00, 0b, 02, 06, 09, 02, 05, 00, 06, 01, 01, 08, 00, 0b, 20, 0d, 12, 00, 08, 00, 0b, 0d, 00, 0c, 02, 06, 12, 02, 05, 00, 06, 01, 01, 08, 00, 0c, 20, 1a, 11, 00, 08, 00, 0c, 1a, 00, 0d, 02, 06, 11, 02, 05, 00, 06, 01, 01, 01, 00, 02] +Raw bytes (116): 0x[01, 01, 07, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 01, 11, 01, 11, 12, 01, 0c, 01, 01, 0e, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 01, 09, 00, 10, 02, 01, 05, 00, 06, 01, 01, 08, 00, 0a, 20, 0a, 09, 00, 08, 00, 0a, 0a, 00, 0b, 02, 06, 09, 02, 05, 00, 06, 01, 01, 08, 00, 0b, 20, 0d, 12, 00, 08, 00, 0b, 0d, 00, 0c, 02, 06, 12, 02, 05, 00, 06, 01, 01, 08, 00, 0c, 20, 1a, 11, 00, 08, 00, 0c, 1a, 00, 0d, 02, 06, 11, 02, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 7 @@ -35,7 +35,7 @@ Number of expressions: 7 - expression 5 operands: lhs = Counter(0), rhs = Counter(4) - expression 6 operands: lhs = Counter(0), rhs = Counter(4) Number of file 0 mappings: 18 -- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 3, 8) to (start + 0, 9) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 8) to (start + 0, 9) true = c1 @@ -68,7 +68,7 @@ Number of file 0 mappings: 18 Highest counter ID seen: c4 Function name: if::branch_not_as -Raw bytes (90): 0x[01, 01, 05, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 0e, 01, 1d, 01, 01, 10, 01, 03, 08, 00, 14, 20, 02, 05, 00, 08, 00, 14, 02, 00, 15, 02, 06, 05, 02, 05, 00, 06, 01, 01, 08, 00, 15, 20, 09, 0a, 00, 08, 00, 15, 09, 00, 16, 02, 06, 0a, 02, 05, 00, 06, 01, 01, 08, 00, 16, 20, 12, 0d, 00, 08, 00, 16, 12, 00, 17, 02, 06, 0d, 02, 05, 00, 06, 01, 01, 01, 00, 02] +Raw bytes (90): 0x[01, 01, 05, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 0e, 01, 1d, 01, 01, 0e, 01, 03, 08, 00, 14, 20, 02, 05, 00, 08, 00, 14, 02, 00, 15, 02, 06, 05, 02, 05, 00, 06, 01, 01, 08, 00, 15, 20, 09, 0a, 00, 08, 00, 15, 09, 00, 16, 02, 06, 0a, 02, 05, 00, 06, 01, 01, 08, 00, 16, 20, 12, 0d, 00, 08, 00, 16, 12, 00, 17, 02, 06, 0d, 02, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 5 @@ -78,7 +78,7 @@ Number of expressions: 5 - expression 3 operands: lhs = Counter(0), rhs = Counter(3) - expression 4 operands: lhs = Counter(0), rhs = Counter(3) Number of file 0 mappings: 14 -- Code(Counter(0)) at (prev + 29, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 29, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 3, 8) to (start + 0, 20) - Branch { true: Expression(0, Sub), false: Counter(1) } at (prev + 0, 8) to (start + 0, 20) true = (c0 - c1) @@ -104,7 +104,7 @@ Number of file 0 mappings: 14 Highest counter ID seen: c3 Function name: if::branch_or -Raw bytes (60): 0x[01, 01, 06, 01, 05, 01, 17, 05, 09, 05, 09, 01, 17, 05, 09, 08, 01, 35, 01, 01, 10, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 20, 09, 12, 00, 0d, 00, 0e, 17, 00, 0f, 02, 06, 12, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (60): 0x[01, 01, 06, 01, 05, 01, 17, 05, 09, 05, 09, 01, 17, 05, 09, 08, 01, 35, 01, 01, 0e, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 20, 09, 12, 00, 0d, 00, 0e, 17, 00, 0f, 02, 06, 12, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 6 @@ -115,7 +115,7 @@ Number of expressions: 6 - expression 4 operands: lhs = Counter(0), rhs = Expression(5, Add) - expression 5 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 53, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 53, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 3, 8) to (start + 0, 9) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 8) to (start + 0, 9) true = c1 diff --git a/tests/coverage/branch/lazy-boolean.cov-map b/tests/coverage/branch/lazy-boolean.cov-map index ff285a038fb8..5d4fc57eb8f7 100644 --- a/tests/coverage/branch/lazy-boolean.cov-map +++ b/tests/coverage/branch/lazy-boolean.cov-map @@ -1,11 +1,11 @@ Function name: lazy_boolean::branch_and -Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 13, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 01, 01, 05, 01, 02] +Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 13, 01, 01, 0e, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 01, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 19, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 19, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 4, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 13) to (start + 0, 14) @@ -16,13 +16,13 @@ Number of file 0 mappings: 6 Highest counter ID seen: c1 Function name: lazy_boolean::branch_or -Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 1b, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 01, 01, 05, 01, 02] +Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 1b, 01, 01, 0e, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 01, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 27, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 27, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 4, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 13) to (start + 0, 14) @@ -34,7 +34,7 @@ Number of file 0 mappings: 6 Highest counter ID seen: c1 Function name: lazy_boolean::chain -Raw bytes (141): 0x[01, 01, 0f, 01, 05, 05, 09, 09, 0d, 01, 11, 01, 11, 01, 3b, 11, 15, 01, 3b, 11, 15, 01, 37, 3b, 19, 11, 15, 01, 37, 3b, 19, 11, 15, 13, 01, 24, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 05, 02, 00, 0d, 00, 12, 05, 00, 16, 00, 1b, 20, 09, 06, 00, 16, 00, 1b, 09, 00, 1f, 00, 24, 20, 0d, 0a, 00, 1f, 00, 24, 0d, 00, 28, 00, 2d, 01, 01, 05, 00, 10, 01, 03, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 11, 12, 00, 0d, 00, 12, 12, 00, 16, 00, 1b, 20, 15, 1e, 00, 16, 00, 1b, 1e, 00, 1f, 00, 24, 20, 19, 32, 00, 1f, 00, 24, 32, 00, 28, 00, 2d, 01, 01, 05, 01, 02] +Raw bytes (141): 0x[01, 01, 0f, 01, 05, 05, 09, 09, 0d, 01, 11, 01, 11, 01, 3b, 11, 15, 01, 3b, 11, 15, 01, 37, 3b, 19, 11, 15, 01, 37, 3b, 19, 11, 15, 13, 01, 24, 01, 01, 0e, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 05, 02, 00, 0d, 00, 12, 05, 00, 16, 00, 1b, 20, 09, 06, 00, 16, 00, 1b, 09, 00, 1f, 00, 24, 20, 0d, 0a, 00, 1f, 00, 24, 0d, 00, 28, 00, 2d, 01, 01, 05, 00, 10, 01, 03, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 11, 12, 00, 0d, 00, 12, 12, 00, 16, 00, 1b, 20, 15, 1e, 00, 16, 00, 1b, 1e, 00, 1f, 00, 24, 20, 19, 32, 00, 1f, 00, 24, 32, 00, 28, 00, 2d, 01, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 15 @@ -54,7 +54,7 @@ Number of expressions: 15 - expression 13 operands: lhs = Expression(14, Add), rhs = Counter(6) - expression 14 operands: lhs = Counter(4), rhs = Counter(5) Number of file 0 mappings: 19 -- Code(Counter(0)) at (prev + 36, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 36, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 4, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 18) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 13) to (start + 0, 18) @@ -91,7 +91,7 @@ Number of file 0 mappings: 19 Highest counter ID seen: c6 Function name: lazy_boolean::nested_mixed -Raw bytes (137): 0x[01, 01, 0d, 01, 05, 01, 1f, 05, 09, 05, 09, 1f, 0d, 05, 09, 1f, 0d, 05, 09, 01, 11, 11, 15, 01, 15, 01, 33, 15, 19, 13, 01, 31, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 05, 02, 00, 0e, 00, 13, 02, 00, 17, 00, 1d, 20, 09, 06, 00, 17, 00, 1d, 1f, 00, 23, 00, 28, 20, 0d, 1a, 00, 23, 00, 28, 1a, 00, 2c, 00, 33, 01, 01, 05, 00, 10, 01, 03, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 11, 22, 00, 0e, 00, 13, 11, 00, 17, 00, 1c, 20, 15, 26, 00, 17, 00, 1c, 2a, 00, 22, 00, 28, 20, 19, 2e, 00, 22, 00, 28, 19, 00, 2c, 00, 33, 01, 01, 05, 01, 02] +Raw bytes (137): 0x[01, 01, 0d, 01, 05, 01, 1f, 05, 09, 05, 09, 1f, 0d, 05, 09, 1f, 0d, 05, 09, 01, 11, 11, 15, 01, 15, 01, 33, 15, 19, 13, 01, 31, 01, 01, 0e, 01, 04, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 05, 02, 00, 0e, 00, 13, 02, 00, 17, 00, 1d, 20, 09, 06, 00, 17, 00, 1d, 1f, 00, 23, 00, 28, 20, 0d, 1a, 00, 23, 00, 28, 1a, 00, 2c, 00, 33, 01, 01, 05, 00, 10, 01, 03, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 11, 22, 00, 0e, 00, 13, 11, 00, 17, 00, 1c, 20, 15, 26, 00, 17, 00, 1c, 2a, 00, 22, 00, 28, 20, 19, 2e, 00, 22, 00, 28, 19, 00, 2c, 00, 33, 01, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 13 @@ -109,7 +109,7 @@ Number of expressions: 13 - expression 11 operands: lhs = Counter(0), rhs = Expression(12, Add) - expression 12 operands: lhs = Counter(5), rhs = Counter(6) Number of file 0 mappings: 19 -- Code(Counter(0)) at (prev + 49, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 49, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 4, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 14) to (start + 0, 19) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 14) to (start + 0, 19) diff --git a/tests/coverage/branch/let-else.cov-map b/tests/coverage/branch/let-else.cov-map index 811b9838e3f5..78507a326388 100644 --- a/tests/coverage/branch/let-else.cov-map +++ b/tests/coverage/branch/let-else.cov-map @@ -1,11 +1,11 @@ Function name: let_else::let_else -Raw bytes (43): 0x[01, 01, 01, 01, 05, 07, 01, 0c, 01, 01, 10, 20, 02, 05, 03, 09, 00, 10, 02, 00, 0e, 00, 0f, 01, 00, 13, 00, 18, 05, 01, 09, 01, 0f, 02, 04, 05, 00, 0a, 01, 01, 01, 00, 02] +Raw bytes (43): 0x[01, 01, 01, 01, 05, 07, 01, 0c, 01, 01, 0e, 20, 02, 05, 03, 09, 00, 10, 02, 00, 0e, 00, 0f, 01, 00, 13, 00, 18, 05, 01, 09, 01, 0f, 02, 04, 05, 00, 0a, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14) - Branch { true: Expression(0, Sub), false: Counter(1) } at (prev + 3, 9) to (start + 0, 16) true = (c0 - c1) false = c1 diff --git a/tests/coverage/branch/match-arms.cov-map b/tests/coverage/branch/match-arms.cov-map index caa18820cf8e..ef71d12c8af1 100644 --- a/tests/coverage/branch/match-arms.cov-map +++ b/tests/coverage/branch/match-arms.cov-map @@ -1,5 +1,5 @@ Function name: match_arms::guards -Raw bytes (88): 0x[01, 01, 08, 15, 05, 19, 09, 1d, 0d, 21, 11, 01, 17, 1b, 11, 1f, 0d, 05, 09, 0c, 01, 30, 01, 01, 10, 21, 03, 0b, 00, 10, 05, 01, 11, 00, 28, 20, 05, 02, 00, 17, 00, 1b, 09, 01, 11, 00, 28, 20, 09, 06, 00, 17, 00, 1b, 0d, 01, 11, 00, 28, 20, 0d, 0a, 00, 17, 00, 1b, 11, 01, 11, 00, 28, 20, 11, 0e, 00, 17, 00, 1b, 12, 01, 0e, 00, 15, 01, 03, 05, 01, 02] +Raw bytes (88): 0x[01, 01, 08, 15, 05, 19, 09, 1d, 0d, 21, 11, 01, 17, 1b, 11, 1f, 0d, 05, 09, 0c, 01, 30, 01, 01, 0e, 21, 03, 0b, 00, 10, 05, 01, 11, 00, 28, 20, 05, 02, 00, 17, 00, 1b, 09, 01, 11, 00, 28, 20, 09, 06, 00, 17, 00, 1b, 0d, 01, 11, 00, 28, 20, 0d, 0a, 00, 17, 00, 1b, 11, 01, 11, 00, 28, 20, 11, 0e, 00, 17, 00, 1b, 12, 01, 0e, 00, 15, 01, 03, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 8 @@ -12,7 +12,7 @@ Number of expressions: 8 - expression 6 operands: lhs = Expression(7, Add), rhs = Counter(3) - expression 7 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 12 -- Code(Counter(0)) at (prev + 48, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 48, 1) to (start + 1, 14) - Code(Counter(8)) at (prev + 3, 11) to (start + 0, 16) - Code(Counter(1)) at (prev + 1, 17) to (start + 0, 40) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 23) to (start + 0, 27) @@ -36,7 +36,7 @@ Number of file 0 mappings: 12 Highest counter ID seen: c8 Function name: match_arms::match_arms -Raw bytes (45): 0x[01, 01, 03, 01, 07, 0b, 0d, 05, 09, 07, 01, 18, 01, 01, 10, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 20, 09, 01, 11, 00, 20, 0d, 01, 11, 00, 20, 02, 01, 11, 00, 20, 01, 03, 05, 01, 02] +Raw bytes (45): 0x[01, 01, 03, 01, 07, 0b, 0d, 05, 09, 07, 01, 18, 01, 01, 0e, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 20, 09, 01, 11, 00, 20, 0d, 01, 11, 00, 20, 02, 01, 11, 00, 20, 01, 03, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 @@ -44,7 +44,7 @@ Number of expressions: 3 - expression 1 operands: lhs = Expression(2, Add), rhs = Counter(3) - expression 2 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 24, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 24, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 3, 11) to (start + 0, 16) - Code(Counter(1)) at (prev + 1, 17) to (start + 0, 32) - Code(Counter(2)) at (prev + 1, 17) to (start + 0, 32) @@ -55,7 +55,7 @@ Number of file 0 mappings: 7 Highest counter ID seen: c3 Function name: match_arms::or_patterns -Raw bytes (57): 0x[01, 01, 04, 05, 09, 01, 0b, 03, 0d, 01, 03, 09, 01, 25, 01, 01, 10, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 12, 09, 00, 1e, 00, 1f, 03, 00, 24, 00, 2d, 0d, 01, 11, 00, 12, 06, 00, 1e, 00, 1f, 0e, 00, 24, 00, 2d, 01, 03, 05, 01, 02] +Raw bytes (57): 0x[01, 01, 04, 05, 09, 01, 0b, 03, 0d, 01, 03, 09, 01, 25, 01, 01, 0e, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 12, 09, 00, 1e, 00, 1f, 03, 00, 24, 00, 2d, 0d, 01, 11, 00, 12, 06, 00, 1e, 00, 1f, 0e, 00, 24, 00, 2d, 01, 03, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -64,7 +64,7 @@ Number of expressions: 4 - expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3) - expression 3 operands: lhs = Counter(0), rhs = Expression(0, Add) Number of file 0 mappings: 9 -- Code(Counter(0)) at (prev + 37, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 37, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 3, 11) to (start + 0, 16) - Code(Counter(1)) at (prev + 1, 17) to (start + 0, 18) - Code(Counter(2)) at (prev + 0, 30) to (start + 0, 31) diff --git a/tests/coverage/branch/match-trivial.cov-map b/tests/coverage/branch/match-trivial.cov-map index 31322f127af7..1b0c6d12e3dc 100644 --- a/tests/coverage/branch/match-trivial.cov-map +++ b/tests/coverage/branch/match-trivial.cov-map @@ -1,19 +1,19 @@ Function name: match_trivial::_uninhabited (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 01, 10] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 01, 0e] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 22, 1) to (start + 1, 16) +- Code(Zero) at (prev + 22, 1) to (start + 1, 14) Highest counter ID seen: (none) Function name: match_trivial::trivial -Raw bytes (14): 0x[01, 01, 00, 02, 01, 1e, 01, 01, 10, 01, 03, 0b, 05, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 1e, 01, 01, 0e, 01, 03, 0b, 05, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 30, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 30, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 3, 11) to (start + 5, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/branch/while.cov-map b/tests/coverage/branch/while.cov-map index 5ce92c72b512..67746af051b6 100644 --- a/tests/coverage/branch/while.cov-map +++ b/tests/coverage/branch/while.cov-map @@ -1,11 +1,11 @@ Function name: while::while_cond -Raw bytes (38): 0x[01, 01, 01, 05, 01, 06, 01, 0c, 01, 01, 10, 01, 03, 09, 00, 12, 05, 01, 0b, 00, 10, 20, 02, 01, 00, 0b, 00, 10, 02, 00, 11, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (38): 0x[01, 01, 01, 05, 01, 06, 01, 0c, 01, 01, 0e, 01, 03, 09, 00, 12, 05, 01, 0b, 00, 10, 20, 02, 01, 00, 0b, 00, 10, 02, 00, 11, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(1), rhs = Counter(0) Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 18) - Code(Counter(1)) at (prev + 1, 11) to (start + 0, 16) - Branch { true: Expression(0, Sub), false: Counter(0) } at (prev + 0, 11) to (start + 0, 16) @@ -17,13 +17,13 @@ Number of file 0 mappings: 6 Highest counter ID seen: c1 Function name: while::while_cond_not -Raw bytes (38): 0x[01, 01, 01, 05, 01, 06, 01, 15, 01, 01, 10, 01, 03, 09, 00, 12, 05, 01, 0b, 00, 14, 20, 02, 01, 00, 0b, 00, 14, 02, 00, 15, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (38): 0x[01, 01, 01, 05, 01, 06, 01, 15, 01, 01, 0e, 01, 03, 09, 00, 12, 05, 01, 0b, 00, 14, 20, 02, 01, 00, 0b, 00, 14, 02, 00, 15, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(1), rhs = Counter(0) Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 21, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 21, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 18) - Code(Counter(1)) at (prev + 1, 11) to (start + 0, 20) - Branch { true: Expression(0, Sub), false: Counter(0) } at (prev + 0, 11) to (start + 0, 20) @@ -35,7 +35,7 @@ Number of file 0 mappings: 6 Highest counter ID seen: c1 Function name: while::while_op_and -Raw bytes (58): 0x[01, 01, 05, 05, 09, 05, 01, 0f, 05, 01, 09, 05, 01, 08, 01, 1e, 01, 01, 10, 01, 03, 09, 01, 12, 05, 02, 0b, 00, 10, 20, 09, 02, 00, 0b, 00, 10, 09, 00, 14, 00, 19, 20, 12, 0a, 00, 14, 00, 19, 12, 00, 1a, 03, 06, 01, 04, 01, 00, 02] +Raw bytes (58): 0x[01, 01, 05, 05, 09, 05, 01, 0f, 05, 01, 09, 05, 01, 08, 01, 1e, 01, 01, 0e, 01, 03, 09, 01, 12, 05, 02, 0b, 00, 10, 20, 09, 02, 00, 0b, 00, 10, 09, 00, 14, 00, 19, 20, 12, 0a, 00, 14, 00, 19, 12, 00, 1a, 03, 06, 01, 04, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 5 @@ -45,7 +45,7 @@ Number of expressions: 5 - expression 3 operands: lhs = Counter(0), rhs = Counter(2) - expression 4 operands: lhs = Counter(1), rhs = Counter(0) Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 30, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 30, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 3, 9) to (start + 1, 18) - Code(Counter(1)) at (prev + 2, 11) to (start + 0, 16) - Branch { true: Counter(2), false: Expression(0, Sub) } at (prev + 0, 11) to (start + 0, 16) @@ -61,7 +61,7 @@ Number of file 0 mappings: 8 Highest counter ID seen: c2 Function name: while::while_op_or -Raw bytes (56): 0x[01, 01, 04, 05, 09, 05, 0b, 01, 09, 05, 01, 08, 01, 29, 01, 01, 10, 01, 03, 09, 01, 12, 05, 02, 0b, 00, 10, 20, 09, 02, 00, 0b, 00, 10, 02, 00, 14, 00, 19, 20, 06, 01, 00, 14, 00, 19, 0e, 00, 1a, 03, 06, 01, 04, 01, 00, 02] +Raw bytes (56): 0x[01, 01, 04, 05, 09, 05, 0b, 01, 09, 05, 01, 08, 01, 29, 01, 01, 0e, 01, 03, 09, 01, 12, 05, 02, 0b, 00, 10, 20, 09, 02, 00, 0b, 00, 10, 02, 00, 14, 00, 19, 20, 06, 01, 00, 14, 00, 19, 0e, 00, 1a, 03, 06, 01, 04, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -70,7 +70,7 @@ Number of expressions: 4 - expression 2 operands: lhs = Counter(0), rhs = Counter(2) - expression 3 operands: lhs = Counter(1), rhs = Counter(0) Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 41, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 41, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 3, 9) to (start + 1, 18) - Code(Counter(1)) at (prev + 2, 11) to (start + 0, 16) - Branch { true: Counter(2), false: Expression(0, Sub) } at (prev + 0, 11) to (start + 0, 16) diff --git a/tests/coverage/closure_macro.cov-map b/tests/coverage/closure_macro.cov-map index 653848dd6ffc..9dd99c8fab3f 100644 --- a/tests/coverage/closure_macro.cov-map +++ b/tests/coverage/closure_macro.cov-map @@ -8,16 +8,16 @@ Number of file 0 mappings: 1 Highest counter ID seen: c0 Function name: closure_macro::main -Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 21, 01, 01, 21, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] +Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 21, 01, 01, 20, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 34, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 33, 1) to (start + 1, 33) +- Code(Counter(0)) at (prev + 33, 1) to (start + 1, 32) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) -- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 84) +- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 52) - Code(Counter(1)) at (prev + 0, 84) to (start + 0, 85) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 2, 11) = (c0 - c1) diff --git a/tests/coverage/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map index 1bd1460a147a..2548754d754c 100644 --- a/tests/coverage/closure_macro_async.cov-map +++ b/tests/coverage/closure_macro_async.cov-map @@ -17,16 +17,16 @@ Number of file 0 mappings: 1 Highest counter ID seen: c0 Function name: closure_macro_async::test::{closure#0} -Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 25, 2b, 01, 21, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] +Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 25, 2b, 01, 20, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 34, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 37, 43) to (start + 1, 33) +- Code(Counter(0)) at (prev + 37, 43) to (start + 1, 32) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) -- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 84) +- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 52) - Code(Counter(1)) at (prev + 0, 84) to (start + 0, 85) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 2, 11) = (c0 - c1) diff --git a/tests/coverage/coroutine.cov-map b/tests/coverage/coroutine.cov-map index 297dde3b2b0f..fee32376d831 100644 --- a/tests/coverage/coroutine.cov-map +++ b/tests/coverage/coroutine.cov-map @@ -13,7 +13,7 @@ Number of file 0 mappings: 4 Highest counter ID seen: c1 Function name: coroutine::main -Raw bytes (53): 0x[01, 01, 02, 01, 05, 05, 09, 09, 01, 13, 01, 02, 16, 01, 08, 0b, 00, 2d, 05, 01, 2b, 00, 2d, 02, 01, 0e, 00, 35, 05, 02, 0b, 00, 2e, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 35, 09, 02, 01, 00, 02] +Raw bytes (53): 0x[01, 01, 02, 01, 05, 05, 09, 09, 01, 13, 01, 02, 16, 01, 08, 0b, 00, 2d, 05, 01, 2b, 00, 2d, 02, 01, 0e, 00, 14, 05, 02, 0b, 00, 2e, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 14, 09, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 @@ -23,12 +23,12 @@ Number of file 0 mappings: 9 - Code(Counter(0)) at (prev + 19, 1) to (start + 2, 22) - Code(Counter(0)) at (prev + 8, 11) to (start + 0, 45) - Code(Counter(1)) at (prev + 1, 43) to (start + 0, 45) -- Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 53) +- Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 20) = (c0 - c1) - Code(Counter(1)) at (prev + 2, 11) to (start + 0, 46) - Code(Counter(3)) at (prev + 1, 34) to (start + 0, 39) - Code(Counter(2)) at (prev + 0, 44) to (start + 0, 46) -- Code(Expression(1, Sub)) at (prev + 1, 14) to (start + 0, 53) +- Code(Expression(1, Sub)) at (prev + 1, 14) to (start + 0, 20) = (c1 - c2) - Code(Counter(2)) at (prev + 2, 1) to (start + 0, 2) Highest counter ID seen: c3 diff --git a/tests/coverage/inline.cov-map b/tests/coverage/inline.cov-map index a569ad53cbc2..7264391baaf7 100644 --- a/tests/coverage/inline.cov-map +++ b/tests/coverage/inline.cov-map @@ -15,12 +15,12 @@ Number of file 0 mappings: 5 Highest counter ID seen: c1 Function name: inline::error -Raw bytes (9): 0x[01, 01, 00, 01, 01, 31, 01, 01, 14] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 31, 01, 01, 0b] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 49, 1) to (start + 1, 20) +- Code(Counter(0)) at (prev + 49, 1) to (start + 1, 11) Highest counter ID seen: c0 Function name: inline::length:: diff --git a/tests/coverage/issue-83601.cov-map b/tests/coverage/issue-83601.cov-map index c188cca1b517..f10231090089 100644 --- a/tests/coverage/issue-83601.cov-map +++ b/tests/coverage/issue-83601.cov-map @@ -1,12 +1,12 @@ Function name: issue_83601::main -Raw bytes (21): 0x[01, 01, 01, 05, 09, 03, 01, 06, 01, 02, 1c, 05, 03, 09, 01, 1c, 02, 02, 05, 03, 02] +Raw bytes (21): 0x[01, 01, 01, 05, 09, 03, 01, 06, 01, 02, 0f, 05, 03, 09, 01, 0f, 02, 02, 05, 03, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 6, 1) to (start + 2, 28) -- Code(Counter(1)) at (prev + 3, 9) to (start + 1, 28) +- Code(Counter(0)) at (prev + 6, 1) to (start + 2, 15) +- Code(Counter(1)) at (prev + 3, 9) to (start + 1, 15) - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 3, 2) = (c1 - c2) Highest counter ID seen: c1 diff --git a/tests/coverage/issue-84561.cov-map b/tests/coverage/issue-84561.cov-map index c8f75cddcb5b..3bd4e7d2a366 100644 --- a/tests/coverage/issue-84561.cov-map +++ b/tests/coverage/issue-84561.cov-map @@ -1,11 +1,11 @@ Function name: ::fmt -Raw bytes (27): 0x[01, 01, 01, 01, 05, 04, 01, 8a, 01, 05, 01, 25, 05, 01, 25, 00, 26, 02, 01, 09, 00, 0f, 01, 01, 05, 00, 06] +Raw bytes (27): 0x[01, 01, 01, 01, 05, 04, 01, 8a, 01, 05, 01, 24, 05, 01, 25, 00, 26, 02, 01, 09, 00, 0f, 01, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 138, 5) to (start + 1, 37) +- Code(Counter(0)) at (prev + 138, 5) to (start + 1, 36) - Code(Counter(1)) at (prev + 1, 37) to (start + 0, 38) - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 15) = (c0 - c1) @@ -59,7 +59,7 @@ Number of file 0 mappings: 1 Highest counter ID seen: c0 Function name: issue_84561::test3 -Raw bytes (315): 0x[01, 01, 1b, 1d, 21, 25, 29, 21, 25, 2d, 31, 21, 17, 25, 2d, 41, 45, 49, 4d, 51, 55, 33, 51, 49, 4d, 33, 37, 49, 4d, 51, 59, 55, 59, 55, 59, 47, 5d, 55, 59, 61, 65, 71, 75, 69, 6d, 69, 6d, 69, 6d, 63, 79, 71, 75, 79, 7d, 7d, 81, 01, 33, 01, 08, 01, 03, 1c, 05, 04, 09, 01, 1c, 09, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 11, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 19, 02, 05, 00, 1f, 1d, 01, 05, 00, 0f, 02, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 25, 03, 20, 00, 30, 29, 00, 33, 00, 41, 06, 00, 4b, 00, 5a, 0a, 01, 05, 00, 0f, 2d, 05, 09, 03, 10, 31, 05, 0d, 00, 1b, 0e, 02, 0d, 00, 1c, 12, 04, 09, 05, 06, 35, 06, 05, 03, 06, 39, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 41, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 1a, 05, 09, 03, 0a, 33, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 22, 03, 0d, 00, 1d, 26, 03, 09, 00, 13, 2e, 03, 0d, 00, 1d, 47, 03, 05, 00, 0f, 47, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 42, 02, 0d, 00, 13, 61, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 4a, 02, 0d, 00, 13, 63, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 71, 04, 0d, 00, 13, 5a, 02, 0d, 00, 17, 5a, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, 5a, 02, 15, 00, 1b, 75, 04, 0d, 00, 13, 5e, 03, 09, 00, 19, 79, 02, 05, 00, 0f, 66, 03, 09, 00, 22, 7d, 02, 05, 00, 0f, 6a, 03, 09, 00, 2c, 81, 01, 02, 01, 00, 02] +Raw bytes (315): 0x[01, 01, 1b, 1d, 21, 25, 29, 21, 25, 2d, 31, 21, 17, 25, 2d, 41, 45, 49, 4d, 51, 55, 33, 51, 49, 4d, 33, 37, 49, 4d, 51, 59, 55, 59, 55, 59, 47, 5d, 55, 59, 61, 65, 71, 75, 69, 6d, 69, 6d, 69, 6d, 63, 79, 71, 75, 79, 7d, 7d, 81, 01, 33, 01, 08, 01, 03, 0f, 05, 04, 09, 01, 0f, 09, 02, 05, 04, 0f, 0d, 05, 05, 00, 0f, 11, 01, 05, 00, 0f, 15, 01, 09, 01, 0f, 19, 02, 05, 00, 0f, 1d, 01, 05, 00, 0f, 02, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 25, 03, 20, 00, 30, 29, 00, 33, 00, 41, 06, 00, 4b, 00, 5a, 0a, 01, 05, 00, 0f, 2d, 05, 09, 03, 10, 31, 05, 0d, 00, 1b, 0e, 02, 0d, 00, 1c, 12, 04, 09, 02, 0f, 35, 06, 05, 00, 0f, 39, 04, 05, 00, 0f, 3d, 04, 09, 01, 0f, 41, 05, 08, 00, 0f, 45, 01, 09, 00, 13, 1a, 05, 09, 00, 13, 33, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 22, 03, 0d, 00, 1d, 26, 03, 09, 00, 13, 2e, 03, 0d, 00, 1d, 47, 03, 05, 00, 0f, 47, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 42, 02, 0d, 00, 13, 61, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 4a, 02, 0d, 00, 13, 63, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 00, 17, 71, 04, 0d, 00, 13, 5a, 02, 0d, 00, 17, 5a, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, 5a, 02, 15, 00, 1b, 75, 04, 0d, 00, 13, 5e, 03, 09, 00, 19, 79, 02, 05, 00, 0f, 66, 03, 09, 00, 22, 7d, 02, 05, 00, 0f, 6a, 03, 09, 00, 2c, 81, 01, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 27 @@ -91,13 +91,13 @@ Number of expressions: 27 - expression 25 operands: lhs = Counter(30), rhs = Counter(31) - expression 26 operands: lhs = Counter(31), rhs = Counter(32) Number of file 0 mappings: 51 -- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 28) -- Code(Counter(1)) at (prev + 4, 9) to (start + 1, 28) -- Code(Counter(2)) at (prev + 2, 5) to (start + 4, 31) -- Code(Counter(3)) at (prev + 5, 5) to (start + 0, 31) -- Code(Counter(4)) at (prev + 1, 5) to (start + 0, 31) -- Code(Counter(5)) at (prev + 1, 9) to (start + 1, 28) -- Code(Counter(6)) at (prev + 2, 5) to (start + 0, 31) +- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 15) +- Code(Counter(1)) at (prev + 4, 9) to (start + 1, 15) +- Code(Counter(2)) at (prev + 2, 5) to (start + 4, 15) +- Code(Counter(3)) at (prev + 5, 5) to (start + 0, 15) +- Code(Counter(4)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(5)) at (prev + 1, 9) to (start + 1, 15) +- Code(Counter(6)) at (prev + 2, 5) to (start + 0, 15) - Code(Counter(7)) at (prev + 1, 5) to (start + 0, 15) - Code(Expression(0, Sub)) at (prev + 0, 32) to (start + 0, 48) = (c7 - c8) @@ -112,14 +112,14 @@ Number of file 0 mappings: 51 - Code(Counter(12)) at (prev + 5, 13) to (start + 0, 27) - Code(Expression(3, Sub)) at (prev + 2, 13) to (start + 0, 28) = (c11 - c12) -- Code(Expression(4, Sub)) at (prev + 4, 9) to (start + 5, 6) +- Code(Expression(4, Sub)) at (prev + 4, 9) to (start + 2, 15) = (c8 - (c9 + c11)) -- Code(Counter(13)) at (prev + 6, 5) to (start + 3, 6) -- Code(Counter(14)) at (prev + 4, 5) to (start + 3, 6) -- Code(Counter(15)) at (prev + 4, 9) to (start + 4, 6) +- Code(Counter(13)) at (prev + 6, 5) to (start + 0, 15) +- Code(Counter(14)) at (prev + 4, 5) to (start + 0, 15) +- Code(Counter(15)) at (prev + 4, 9) to (start + 1, 15) - Code(Counter(16)) at (prev + 5, 8) to (start + 0, 15) -- Code(Counter(17)) at (prev + 1, 9) to (start + 3, 10) -- Code(Expression(6, Sub)) at (prev + 5, 9) to (start + 3, 10) +- Code(Counter(17)) at (prev + 1, 9) to (start + 0, 19) +- Code(Expression(6, Sub)) at (prev + 5, 9) to (start + 0, 19) = (c16 - c17) - Code(Expression(12, Add)) at (prev + 5, 8) to (start + 0, 15) = (c18 + c19) @@ -144,7 +144,7 @@ Number of file 0 mappings: 51 - Code(Expression(24, Add)) at (prev + 3, 5) to (start + 0, 15) = (c28 + c29) - Code(Counter(26)) at (prev + 1, 12) to (start + 0, 19) -- Code(Counter(27)) at (prev + 1, 13) to (start + 3, 14) +- Code(Counter(27)) at (prev + 1, 13) to (start + 0, 23) - Code(Counter(28)) at (prev + 4, 13) to (start + 0, 19) - Code(Expression(22, Sub)) at (prev + 2, 13) to (start + 0, 23) = (c26 - c27) diff --git a/tests/coverage/issue-84561.coverage b/tests/coverage/issue-84561.coverage index 2a642e2427b9..a55f42a696e6 100644 --- a/tests/coverage/issue-84561.coverage +++ b/tests/coverage/issue-84561.coverage @@ -47,32 +47,32 @@ LL| 1| let is_true = std::env::args().len() == 1; LL| 1| LL| 1| assert_eq!( - LL| 1| Foo(1), - LL| 1| Foo(1) - LL| 1| ); + LL| | Foo(1), + LL| | Foo(1) + LL| | ); LL| 1| assert_ne!( - LL| 1| Foo(0), - LL| 1| Foo(1) - LL| 1| ); + LL| | Foo(0), + LL| | Foo(1) + LL| | ); LL| 1| assert_eq!( - LL| 1| Foo(2), - LL| 1| Foo(2) - LL| 1| ); + LL| | Foo(2), + LL| | Foo(2) + LL| | ); LL| 1| let bar = Foo(1); LL| 1| assert_ne!( - LL| 1| bar, - LL| 1| Foo(3) - LL| 1| ); + LL| | bar, + LL| | Foo(3) + LL| | ); LL| 1| if is_true { LL| 1| assert_ne!( - LL| 1| Foo(0), - LL| 1| Foo(4) - LL| 1| ); + LL| | Foo(0), + LL| | Foo(4) + LL| | ); LL| | } else { LL| 0| assert_eq!( - LL| 0| Foo(3), - LL| 0| Foo(3) - LL| 0| ); + LL| | Foo(3), + LL| | Foo(3) + LL| | ); LL| | } LL| 1| if is_true { LL| 1| assert_ne!( @@ -106,9 +106,9 @@ LL| 1| assert_ne!( LL| 1| if is_true { LL| 1| assert_eq!( - LL| 1| Foo(3), - LL| 1| Foo(3) - LL| 1| ); + LL| | Foo(3), + LL| | Foo(3) + LL| | ); LL| 1| Foo(0) LL| | } else { LL| 0| assert_ne!( diff --git a/tests/coverage/loops_branches.cov-map b/tests/coverage/loops_branches.cov-map index 2cb0f948b3e1..2157cd6ee3f8 100644 --- a/tests/coverage/loops_branches.cov-map +++ b/tests/coverage/loops_branches.cov-map @@ -1,5 +1,5 @@ Function name: ::fmt -Raw bytes (112): 0x[01, 01, 04, 07, 0b, 01, 0d, 05, 09, 09, 0d, 14, 01, 09, 05, 01, 10, 01, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 01, 01, 0d, 00, 0e, 01, 01, 0d, 00, 1e, 05, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, 0d, 03, 0d, 00, 0e, 09, 00, 12, 00, 17, 0d, 01, 10, 00, 14, 0d, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 0d, 01, 11, 00, 12, 0d, 01, 11, 00, 22, 02, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 0e, 03, 09, 00, 0f, 01, 01, 05, 00, 06] +Raw bytes (112): 0x[01, 01, 04, 07, 0b, 01, 0d, 05, 09, 09, 0d, 14, 01, 09, 05, 01, 10, 01, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 01, 01, 0d, 00, 0e, 01, 01, 0d, 00, 1d, 05, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, 0d, 03, 0d, 00, 0e, 09, 00, 12, 00, 17, 0d, 01, 10, 00, 14, 0d, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 0d, 01, 11, 00, 12, 0d, 01, 11, 00, 21, 02, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 0e, 03, 09, 00, 0f, 01, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -13,7 +13,7 @@ Number of file 0 mappings: 20 - Code(Zero) at (prev + 1, 23) to (start + 0, 27) - Code(Zero) at (prev + 0, 28) to (start + 0, 30) - Code(Counter(0)) at (prev + 1, 13) to (start + 0, 14) -- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 30) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 29) - Code(Counter(1)) at (prev + 0, 30) to (start + 0, 31) - Code(Zero) at (prev + 1, 16) to (start + 1, 10) - Code(Counter(3)) at (prev + 3, 13) to (start + 0, 14) @@ -23,7 +23,7 @@ Number of file 0 mappings: 20 - Code(Zero) at (prev + 1, 27) to (start + 0, 31) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) - Code(Counter(3)) at (prev + 1, 17) to (start + 0, 18) -- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 34) +- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 33) - Code(Expression(0, Sub)) at (prev + 0, 34) to (start + 0, 35) = ((c0 + c3) - (c1 + c2)) - Code(Zero) at (prev + 1, 20) to (start + 1, 14) @@ -33,7 +33,7 @@ Number of file 0 mappings: 20 Highest counter ID seen: c3 Function name: ::fmt -Raw bytes (112): 0x[01, 01, 04, 07, 0b, 01, 09, 05, 0d, 05, 09, 14, 01, 22, 05, 01, 11, 00, 01, 12, 01, 0a, 01, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 01, 01, 0d, 00, 0e, 01, 01, 0d, 00, 1e, 0d, 00, 1e, 00, 1f, 09, 02, 0d, 00, 0e, 05, 00, 12, 00, 17, 09, 01, 10, 00, 15, 00, 00, 16, 01, 0e, 09, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 09, 01, 11, 00, 12, 09, 01, 11, 00, 22, 02, 00, 22, 00, 23, 0e, 03, 09, 00, 0f, 01, 01, 05, 00, 06] +Raw bytes (112): 0x[01, 01, 04, 07, 0b, 01, 09, 05, 0d, 05, 09, 14, 01, 22, 05, 01, 11, 00, 01, 12, 01, 0a, 01, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 01, 01, 0d, 00, 0e, 01, 01, 0d, 00, 1d, 0d, 00, 1e, 00, 1f, 09, 02, 0d, 00, 0e, 05, 00, 12, 00, 17, 09, 01, 10, 00, 15, 00, 00, 16, 01, 0e, 09, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 09, 01, 11, 00, 12, 09, 01, 11, 00, 21, 02, 00, 22, 00, 23, 0e, 03, 09, 00, 0f, 01, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -48,7 +48,7 @@ Number of file 0 mappings: 20 - Code(Zero) at (prev + 1, 23) to (start + 0, 27) - Code(Zero) at (prev + 0, 28) to (start + 0, 30) - Code(Counter(0)) at (prev + 1, 13) to (start + 0, 14) -- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 30) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 29) - Code(Counter(3)) at (prev + 0, 30) to (start + 0, 31) - Code(Counter(2)) at (prev + 2, 13) to (start + 0, 14) - Code(Counter(1)) at (prev + 0, 18) to (start + 0, 23) @@ -58,7 +58,7 @@ Number of file 0 mappings: 20 - Code(Zero) at (prev + 1, 27) to (start + 0, 31) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) - Code(Counter(2)) at (prev + 1, 17) to (start + 0, 18) -- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 34) +- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 33) - Code(Expression(0, Sub)) at (prev + 0, 34) to (start + 0, 35) = ((c0 + c2) - (c1 + c3)) - Code(Expression(3, Sub)) at (prev + 3, 9) to (start + 0, 15) diff --git a/tests/coverage/macro_name_span.cov-map b/tests/coverage/macro_name_span.cov-map index 58620452b2ba..bd033faa5510 100644 --- a/tests/coverage/macro_name_span.cov-map +++ b/tests/coverage/macro_name_span.cov-map @@ -1,10 +1,10 @@ Function name: macro_name_span::affected_function -Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 1c, 01, 40] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 1c, 01, 3e] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 22, 28) to (start + 1, 64) +- Code(Counter(0)) at (prev + 22, 28) to (start + 1, 62) Highest counter ID seen: c0 Function name: macro_name_span::main diff --git a/tests/coverage/panic_unwind.cov-map b/tests/coverage/panic_unwind.cov-map index 4628a24689e7..18b13919fe5e 100644 --- a/tests/coverage/panic_unwind.cov-map +++ b/tests/coverage/panic_unwind.cov-map @@ -26,14 +26,14 @@ Number of file 0 mappings: 9 Highest counter ID seen: c3 Function name: panic_unwind::might_panic -Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 04, 01, 01, 14, 05, 02, 09, 01, 19, 02, 02, 0c, 03, 02] +Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 04, 01, 01, 14, 05, 02, 09, 01, 0f, 02, 02, 0c, 03, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 4, 1) to (start + 1, 20) -- Code(Counter(1)) at (prev + 2, 9) to (start + 1, 25) +- Code(Counter(1)) at (prev + 2, 9) to (start + 1, 15) - Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 3, 2) = (c0 - c1) Highest counter ID seen: c1 diff --git a/tests/coverage/try_error_result.cov-map b/tests/coverage/try_error_result.cov-map index a4a8e21d8c31..e45f3de10815 100644 --- a/tests/coverage/try_error_result.cov-map +++ b/tests/coverage/try_error_result.cov-map @@ -82,7 +82,7 @@ Number of file 0 mappings: 11 Highest counter ID seen: c2 Function name: try_error_result::test2 -Raw bytes (336): 0x[01, 01, 36, 0d, 11, 0d, 3f, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 0d, 3f, 11, 15, 0d, 3b, 3f, 19, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 41, 53, 21, 25, 41, 21, 41, 53, 21, 25, 09, 73, 77, 2d, 0d, 29, 09, 0d, 09, 77, 0d, 29, 09, 73, 77, 2d, 0d, 29, 45, 8b, 01, 31, 35, 45, 31, 45, 8b, 01, 31, 35, 49, 9f, 01, 39, 3d, 49, 39, 49, 9f, 01, 39, 3d, 05, 09, ab, 01, 09, af, 01, 3d, b3, 01, 39, b7, 01, 35, bb, 01, 31, bf, 01, 2d, c3, 01, 29, c7, 01, 25, cb, 01, 21, cf, 01, 1d, d3, 01, 19, d7, 01, 15, 05, 11, 28, 01, 3d, 01, 03, 17, 05, 08, 09, 00, 0e, 09, 02, 09, 04, 1a, 0d, 06, 0d, 00, 1f, 11, 00, 2f, 00, 30, 02, 00, 31, 03, 1c, 15, 04, 11, 00, 12, 1e, 02, 11, 03, 27, 32, 05, 11, 00, 14, 1e, 00, 17, 00, 29, 19, 00, 41, 00, 42, 26, 00, 43, 00, 47, 1d, 00, 5f, 00, 60, 32, 01, 0d, 00, 20, 4e, 01, 11, 00, 14, 41, 00, 17, 00, 29, 21, 00, 41, 00, 42, 4a, 00, 43, 00, 47, 25, 00, 60, 00, 61, 4e, 01, 0d, 00, 20, 6e, 04, 11, 00, 14, 62, 00, 17, 00, 29, 29, 00, 42, 00, 43, 66, 00, 44, 00, 48, 2d, 00, 61, 00, 62, 6e, 01, 0d, 00, 20, 86, 01, 01, 11, 00, 14, 45, 00, 17, 01, 1d, 31, 01, 36, 00, 37, 82, 01, 01, 12, 00, 16, 35, 00, 2f, 00, 30, 86, 01, 01, 0d, 00, 20, 9a, 01, 01, 11, 00, 14, 49, 00, 17, 01, 1d, 39, 02, 11, 00, 12, 96, 01, 01, 12, 00, 16, 3d, 01, 11, 00, 12, 9a, 01, 02, 0d, 00, 20, a2, 01, 03, 05, 00, 0b, a6, 01, 01, 01, 00, 02] +Raw bytes (336): 0x[01, 01, 36, 0d, 11, 0d, 3f, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 0d, 3f, 11, 15, 0d, 3b, 3f, 19, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 41, 53, 21, 25, 41, 21, 41, 53, 21, 25, 09, 73, 77, 2d, 0d, 29, 09, 0d, 09, 77, 0d, 29, 09, 73, 77, 2d, 0d, 29, 45, 8b, 01, 31, 35, 45, 31, 45, 8b, 01, 31, 35, 49, 9f, 01, 39, 3d, 49, 39, 49, 9f, 01, 39, 3d, 05, 09, ab, 01, 09, af, 01, 3d, b3, 01, 39, b7, 01, 35, bb, 01, 31, bf, 01, 2d, c3, 01, 29, c7, 01, 25, cb, 01, 21, cf, 01, 1d, d3, 01, 19, d7, 01, 15, 05, 11, 28, 01, 3d, 01, 03, 17, 05, 08, 09, 00, 0e, 09, 02, 09, 04, 1a, 0d, 06, 0d, 00, 1f, 11, 00, 2f, 00, 30, 02, 00, 31, 03, 1c, 15, 04, 11, 00, 12, 1e, 02, 11, 03, 27, 32, 05, 11, 00, 14, 1e, 00, 17, 00, 29, 19, 00, 41, 00, 42, 26, 00, 43, 00, 47, 1d, 00, 5f, 00, 60, 32, 01, 0d, 00, 17, 4e, 01, 11, 00, 14, 41, 00, 17, 00, 29, 21, 00, 41, 00, 42, 4a, 00, 43, 00, 47, 25, 00, 60, 00, 61, 4e, 01, 0d, 00, 17, 6e, 04, 11, 00, 14, 62, 00, 17, 00, 29, 29, 00, 42, 00, 43, 66, 00, 44, 00, 48, 2d, 00, 61, 00, 62, 6e, 01, 0d, 00, 17, 86, 01, 01, 11, 00, 14, 45, 00, 17, 01, 1d, 31, 01, 36, 00, 37, 82, 01, 01, 12, 00, 16, 35, 00, 2f, 00, 30, 86, 01, 01, 0d, 00, 17, 9a, 01, 01, 11, 00, 14, 49, 00, 17, 01, 1d, 39, 02, 11, 00, 12, 96, 01, 01, 12, 00, 16, 3d, 01, 11, 00, 12, 9a, 01, 02, 0d, 00, 17, a2, 01, 03, 05, 00, 0b, a6, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 54 @@ -159,7 +159,7 @@ Number of file 0 mappings: 40 - Code(Expression(9, Sub)) at (prev + 0, 67) to (start + 0, 71) = (c3 - ((c4 + c5) + c6)) - Code(Counter(7)) at (prev + 0, 95) to (start + 0, 96) -- Code(Expression(12, Sub)) at (prev + 1, 13) to (start + 0, 32) +- Code(Expression(12, Sub)) at (prev + 1, 13) to (start + 0, 23) = (c3 - (((c4 + c5) + c6) + c7)) - Code(Expression(19, Sub)) at (prev + 1, 17) to (start + 0, 20) = (c16 - (c8 + c9)) @@ -168,7 +168,7 @@ Number of file 0 mappings: 40 - Code(Expression(18, Sub)) at (prev + 0, 67) to (start + 0, 71) = (c16 - c8) - Code(Counter(9)) at (prev + 0, 96) to (start + 0, 97) -- Code(Expression(19, Sub)) at (prev + 1, 13) to (start + 0, 32) +- Code(Expression(19, Sub)) at (prev + 1, 13) to (start + 0, 23) = (c16 - (c8 + c9)) - Code(Expression(27, Sub)) at (prev + 4, 17) to (start + 0, 20) = (c2 - ((c3 + c10) + c11)) @@ -178,7 +178,7 @@ Number of file 0 mappings: 40 - Code(Expression(25, Sub)) at (prev + 0, 68) to (start + 0, 72) = (c2 - (c3 + c10)) - Code(Counter(11)) at (prev + 0, 97) to (start + 0, 98) -- Code(Expression(27, Sub)) at (prev + 1, 13) to (start + 0, 32) +- Code(Expression(27, Sub)) at (prev + 1, 13) to (start + 0, 23) = (c2 - ((c3 + c10) + c11)) - Code(Expression(33, Sub)) at (prev + 1, 17) to (start + 0, 20) = (c17 - (c12 + c13)) @@ -187,7 +187,7 @@ Number of file 0 mappings: 40 - Code(Expression(32, Sub)) at (prev + 1, 18) to (start + 0, 22) = (c17 - c12) - Code(Counter(13)) at (prev + 0, 47) to (start + 0, 48) -- Code(Expression(33, Sub)) at (prev + 1, 13) to (start + 0, 32) +- Code(Expression(33, Sub)) at (prev + 1, 13) to (start + 0, 23) = (c17 - (c12 + c13)) - Code(Expression(38, Sub)) at (prev + 1, 17) to (start + 0, 20) = (c18 - (c14 + c15)) @@ -196,7 +196,7 @@ Number of file 0 mappings: 40 - Code(Expression(37, Sub)) at (prev + 1, 18) to (start + 0, 22) = (c18 - c14) - Code(Counter(15)) at (prev + 1, 17) to (start + 0, 18) -- Code(Expression(38, Sub)) at (prev + 2, 13) to (start + 0, 32) +- Code(Expression(38, Sub)) at (prev + 2, 13) to (start + 0, 23) = (c18 - (c14 + c15)) - Code(Expression(40, Sub)) at (prev + 3, 5) to (start + 0, 11) = (c1 - c2) diff --git a/tests/coverage/yield.cov-map b/tests/coverage/yield.cov-map index d296f9bd778a..bf0916e5503a 100644 --- a/tests/coverage/yield.cov-map +++ b/tests/coverage/yield.cov-map @@ -1,5 +1,5 @@ Function name: yield::main -Raw bytes (94): 0x[01, 01, 05, 01, 05, 05, 09, 09, 11, 11, 15, 11, 15, 10, 01, 07, 01, 01, 16, 01, 07, 0b, 00, 2e, 05, 01, 27, 00, 29, 02, 01, 0e, 00, 34, 05, 02, 0b, 00, 2e, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 34, 09, 03, 09, 00, 16, 09, 08, 0b, 00, 2e, 11, 01, 27, 00, 29, 0a, 01, 0e, 00, 34, 11, 02, 0b, 00, 2e, 12, 01, 27, 00, 29, 15, 01, 0e, 00, 34, 12, 02, 01, 00, 02] +Raw bytes (94): 0x[01, 01, 05, 01, 05, 05, 09, 09, 11, 11, 15, 11, 15, 10, 01, 07, 01, 01, 16, 01, 07, 0b, 00, 2e, 05, 01, 27, 00, 29, 02, 01, 0e, 00, 14, 05, 02, 0b, 00, 2e, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 14, 09, 03, 09, 00, 16, 09, 08, 0b, 00, 2e, 11, 01, 27, 00, 29, 0a, 01, 0e, 00, 14, 11, 02, 0b, 00, 2e, 12, 01, 27, 00, 29, 15, 01, 0e, 00, 14, 12, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 5 @@ -12,22 +12,22 @@ Number of file 0 mappings: 16 - Code(Counter(0)) at (prev + 7, 1) to (start + 1, 22) - Code(Counter(0)) at (prev + 7, 11) to (start + 0, 46) - Code(Counter(1)) at (prev + 1, 39) to (start + 0, 41) -- Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 52) +- Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 20) = (c0 - c1) - Code(Counter(1)) at (prev + 2, 11) to (start + 0, 46) - Code(Counter(3)) at (prev + 1, 34) to (start + 0, 39) - Code(Counter(2)) at (prev + 0, 44) to (start + 0, 46) -- Code(Expression(1, Sub)) at (prev + 1, 14) to (start + 0, 52) +- Code(Expression(1, Sub)) at (prev + 1, 14) to (start + 0, 20) = (c1 - c2) - Code(Counter(2)) at (prev + 3, 9) to (start + 0, 22) - Code(Counter(2)) at (prev + 8, 11) to (start + 0, 46) - Code(Counter(4)) at (prev + 1, 39) to (start + 0, 41) -- Code(Expression(2, Sub)) at (prev + 1, 14) to (start + 0, 52) +- Code(Expression(2, Sub)) at (prev + 1, 14) to (start + 0, 20) = (c2 - c4) - Code(Counter(4)) at (prev + 2, 11) to (start + 0, 46) - Code(Expression(4, Sub)) at (prev + 1, 39) to (start + 0, 41) = (c4 - c5) -- Code(Counter(5)) at (prev + 1, 14) to (start + 0, 52) +- Code(Counter(5)) at (prev + 1, 14) to (start + 0, 20) - Code(Expression(4, Sub)) at (prev + 2, 1) to (start + 0, 2) = (c4 - c5) Highest counter ID seen: c5 From 59307fd9fd17b46d0fa65c7e542d39dedd2dec66 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 20 Mar 2025 15:53:22 +1100 Subject: [PATCH 705/745] Factor out some shared code. `global_allocator_spans` and `alloc_error_handler_span` are identical except for `name`. --- compiler/rustc_metadata/src/creader.rs | 46 ++++++++------------------ 1 file changed, 14 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index b7f13e0afdcd..e1ee562dafeb 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -1032,14 +1032,19 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } fn inject_allocator_crate(&mut self, krate: &ast::Crate) { - self.cstore.has_global_allocator = match &*global_allocator_spans(krate) { - [span1, span2, ..] => { - self.dcx().emit_err(errors::NoMultipleGlobalAlloc { span2: *span2, span1: *span1 }); - true - } - spans => !spans.is_empty(), - }; - self.cstore.has_alloc_error_handler = match &*alloc_error_handler_spans(krate) { + self.cstore.has_global_allocator = + match &*fn_spans(krate, Symbol::intern(&global_fn_name(sym::alloc))) { + [span1, span2, ..] => { + self.dcx() + .emit_err(errors::NoMultipleGlobalAlloc { span2: *span2, span1: *span1 }); + true + } + spans => !spans.is_empty(), + }; + self.cstore.has_alloc_error_handler = match &*fn_spans( + krate, + Symbol::intern(alloc_error_handler_name(AllocatorKind::Global)), + ) { [span1, span2, ..] => { self.dcx() .emit_err(errors::NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 }); @@ -1368,7 +1373,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } } -fn global_allocator_spans(krate: &ast::Crate) -> Vec { +fn fn_spans(krate: &ast::Crate, name: Symbol) -> Vec { struct Finder { name: Symbol, spans: Vec, @@ -1384,29 +1389,6 @@ fn global_allocator_spans(krate: &ast::Crate) -> Vec { } } - let name = Symbol::intern(&global_fn_name(sym::alloc)); - let mut f = Finder { name, spans: Vec::new() }; - visit::walk_crate(&mut f, krate); - f.spans -} - -fn alloc_error_handler_spans(krate: &ast::Crate) -> Vec { - struct Finder { - name: Symbol, - spans: Vec, - } - impl<'ast> visit::Visitor<'ast> for Finder { - fn visit_item(&mut self, item: &'ast ast::Item) { - if item.ident.name == self.name - && attr::contains_name(&item.attrs, sym::rustc_std_internal_symbol) - { - self.spans.push(item.span); - } - visit::walk_item(self, item) - } - } - - let name = Symbol::intern(alloc_error_handler_name(AllocatorKind::Global)); let mut f = Finder { name, spans: Vec::new() }; visit::walk_crate(&mut f, krate); f.spans From 4c551bcacd4b6d5652a6e9bc6fd5b7afbac435ae Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 21 Mar 2025 09:47:32 +1100 Subject: [PATCH 706/745] Simplify `ItemVisitorKind`. Instead of putting the item inside it, just pass the ident and visibility (the only things needed) alongside it where necessary. This helps with the next commit, which will move the ident's location. Specifically, it gets rid of the `match visitor_kind` in `rewrite_type_alias`. --- src/tools/rustfmt/src/items.rs | 42 ++++++++++++++++++-------------- src/tools/rustfmt/src/visitor.rs | 29 +++++++++++++--------- 2 files changed, 41 insertions(+), 30 deletions(-) diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 3fb3284e3d7f..415b83060b85 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -6,7 +6,7 @@ use std::cmp::{Ordering, max, min}; use regex::Regex; use rustc_ast::visit; use rustc_ast::{ast, ptr}; -use rustc_span::{BytePos, DUMMY_SP, Span, symbol}; +use rustc_span::{BytePos, DUMMY_SP, Ident, Span, symbol}; use tracing::debug; use crate::attr::filter_inline_attrs; @@ -1679,11 +1679,12 @@ fn format_tuple_struct( Some(result) } -pub(crate) enum ItemVisitorKind<'a> { - Item(&'a ast::Item), - AssocTraitItem(&'a ast::AssocItem), - AssocImplItem(&'a ast::AssocItem), - ForeignItem(&'a ast::ForeignItem), +#[derive(Clone, Copy)] +pub(crate) enum ItemVisitorKind { + Item, + AssocTraitItem, + AssocImplItem, + ForeignItem, } struct TyAliasRewriteInfo<'c, 'g>( @@ -1695,11 +1696,13 @@ struct TyAliasRewriteInfo<'c, 'g>( Span, ); -pub(crate) fn rewrite_type_alias<'a, 'b>( +pub(crate) fn rewrite_type_alias<'a>( ty_alias_kind: &ast::TyAlias, + vis: &ast::Visibility, + ident: Ident, context: &RewriteContext<'a>, indent: Indent, - visitor_kind: &ItemVisitorKind<'b>, + visitor_kind: ItemVisitorKind, span: Span, ) -> RewriteResult { use ItemVisitorKind::*; @@ -1715,11 +1718,6 @@ pub(crate) fn rewrite_type_alias<'a, 'b>( let rhs_hi = ty .as_ref() .map_or(where_clauses.before.span.hi(), |ty| ty.span.hi()); - let (ident, vis) = match visitor_kind { - Item(i) => (i.ident, &i.vis), - AssocTraitItem(i) | AssocImplItem(i) => (i.ident, &i.vis), - ForeignItem(i) => (i.ident, &i.vis), - }; let rw_info = &TyAliasRewriteInfo(context, indent, generics, where_clauses, ident, span); let op_ty = opaque_ty(ty); // Type Aliases are formatted slightly differently depending on the context @@ -1727,14 +1725,14 @@ pub(crate) fn rewrite_type_alias<'a, 'b>( // https://rustc-dev-guide.rust-lang.org/opaque-types-type-alias-impl-trait.html // https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/items.md#type-aliases match (visitor_kind, &op_ty) { - (Item(_) | AssocTraitItem(_) | ForeignItem(_), Some(op_bounds)) => { + (Item | AssocTraitItem | ForeignItem, Some(op_bounds)) => { let op = OpaqueType { bounds: op_bounds }; rewrite_ty(rw_info, Some(bounds), Some(&op), rhs_hi, vis) } - (Item(_) | AssocTraitItem(_) | ForeignItem(_), None) => { + (Item | AssocTraitItem | ForeignItem, None) => { rewrite_ty(rw_info, Some(bounds), ty_opt, rhs_hi, vis) } - (AssocImplItem(_), _) => { + (AssocImplItem, _) => { let result = if let Some(op_bounds) = op_ty { let op = OpaqueType { bounds: op_bounds }; rewrite_ty( @@ -3498,8 +3496,16 @@ impl Rewrite for ast::ForeignItem { .map(|s| s + ";") } ast::ForeignItemKind::TyAlias(ref ty_alias) => { - let (kind, span) = (&ItemVisitorKind::ForeignItem(self), self.span); - rewrite_type_alias(ty_alias, context, shape.indent, kind, span) + let kind = ItemVisitorKind::ForeignItem; + rewrite_type_alias( + ty_alias, + &self.vis, + self.ident, + context, + shape.indent, + kind, + self.span, + ) } ast::ForeignItemKind::MacCall(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Item) diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index 5749d8c63faf..c70649cc8125 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -3,7 +3,7 @@ use std::rc::Rc; use std::sync::Arc; use rustc_ast::{ast, token::Delimiter, visit}; -use rustc_span::{BytePos, Pos, Span, symbol}; +use rustc_span::{BytePos, Ident, Pos, Span, symbol}; use tracing::debug; use crate::attr::*; @@ -573,7 +573,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } ast::ItemKind::TyAlias(ref ty_alias) => { use ItemVisitorKind::Item; - self.visit_ty_alias_kind(ty_alias, &Item(item), item.span); + self.visit_ty_alias_kind(ty_alias, &item.vis, item.ident, Item, item.span); } ast::ItemKind::GlobalAsm(..) => { let snippet = Some(self.snippet(item.span).to_owned()); @@ -605,11 +605,15 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { fn visit_ty_alias_kind( &mut self, ty_kind: &ast::TyAlias, - visitor_kind: &ItemVisitorKind<'_>, + vis: &ast::Visibility, + ident: Ident, + visitor_kind: ItemVisitorKind, span: Span, ) { let rewrite = rewrite_type_alias( ty_kind, + vis, + ident, &self.get_context(), self.block_indent, visitor_kind, @@ -619,15 +623,16 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.push_rewrite(span, rewrite); } - fn visit_assoc_item(&mut self, visitor_kind: &ItemVisitorKind<'_>) { + fn visit_assoc_item(&mut self, ai: &ast::AssocItem, visitor_kind: ItemVisitorKind) { use ItemVisitorKind::*; // TODO(calebcartwright): Not sure the skip spans are correct - let (ai, skip_span, assoc_ctxt) = match visitor_kind { - AssocTraitItem(ai) => (*ai, ai.span(), visit::AssocCtxt::Trait), + let assoc_ctxt = match visitor_kind { + AssocTraitItem => visit::AssocCtxt::Trait, // There is no difference between trait and inherent assoc item formatting - AssocImplItem(ai) => (*ai, ai.span, visit::AssocCtxt::Impl { of_trait: false }), + AssocImplItem => visit::AssocCtxt::Impl { of_trait: false }, _ => unreachable!(), }; + let skip_span = ai.span; skip_out_of_file_lines_range_visitor!(self, ai.span); if self.visit_attrs(&ai.attrs, ast::AttrStyle::Outer) { @@ -637,10 +642,10 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // TODO(calebcartwright): consider enabling box_patterns feature gate match (&ai.kind, visitor_kind) { - (ast::AssocItemKind::Const(..), AssocTraitItem(_)) => { + (ast::AssocItemKind::Const(..), AssocTraitItem) => { self.visit_static(&StaticParts::from_trait_item(ai)) } - (ast::AssocItemKind::Const(..), AssocImplItem(_)) => { + (ast::AssocItemKind::Const(..), AssocImplItem) => { self.visit_static(&StaticParts::from_impl_item(ai)) } (ast::AssocItemKind::Fn(ref fn_kind), _) => { @@ -670,7 +675,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } } (ast::AssocItemKind::Type(ref ty_alias), _) => { - self.visit_ty_alias_kind(ty_alias, visitor_kind, ai.span); + self.visit_ty_alias_kind(ty_alias, &ai.vis, ai.ident, visitor_kind, ai.span); } (ast::AssocItemKind::MacCall(ref mac), _) => { self.visit_mac(mac, Some(ai.ident), MacroPosition::Item); @@ -680,11 +685,11 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } pub(crate) fn visit_trait_item(&mut self, ti: &ast::AssocItem) { - self.visit_assoc_item(&ItemVisitorKind::AssocTraitItem(ti)); + self.visit_assoc_item(ti, ItemVisitorKind::AssocTraitItem); } pub(crate) fn visit_impl_item(&mut self, ii: &ast::AssocItem) { - self.visit_assoc_item(&ItemVisitorKind::AssocImplItem(ii)); + self.visit_assoc_item(ii, ItemVisitorKind::AssocImplItem); } fn visit_mac(&mut self, mac: &ast::MacCall, ident: Option, pos: MacroPosition) { From deed0f2480c507f7a3979ea814ade54685c5c45a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 20 Mar 2025 17:28:45 +1100 Subject: [PATCH 707/745] Remove useless `Option` arg. `FmtVisitor::visit_mac` has an `Option` arg which is always either `None` or `Some(kw::Empty)`, because `ItemKind::MacCall` always has an empty ident. This value is passed through various functions until it reaches `rewrite_macro_name`, which treats `None` and `Some(kw::Empty)` the same. In other words, the argument is useless. This commit removes it. There is no change in behaviour. The commit also changes a few `symbol::Ident` occurrences to `Ident` in `macros.rs`; `Symbol` is imported in that file so `Ident` might as well be, too. (This is a good example of why it's a bad idea for `Itemt` to have an `ident` field when various item kinds don't have an identifier. It's easy to get confused when "empty identifier" is used to mean "no identifier". This will be fixed in a subsequent commit.) --- src/tools/rustfmt/src/expr.rs | 2 +- src/tools/rustfmt/src/items.rs | 2 +- src/tools/rustfmt/src/macros.rs | 34 +++++++------------------------ src/tools/rustfmt/src/patterns.rs | 4 +--- src/tools/rustfmt/src/types.rs | 2 +- src/tools/rustfmt/src/visitor.rs | 10 ++++----- 6 files changed, 16 insertions(+), 38 deletions(-) diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index e866f13efc73..65120770edd6 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -246,7 +246,7 @@ pub(crate) fn format_expr( | ast::ExprKind::Await(_, _) | ast::ExprKind::Yield(ast::YieldKind::Postfix(_)) => rewrite_chain(expr, context, shape), ast::ExprKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|_| { + rewrite_macro(mac, context, shape, MacroPosition::Expression).or_else(|_| { wrap_str( context.snippet(expr.span).to_owned(), context.config.max_width(), diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 415b83060b85..fdda885b7298 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -3508,7 +3508,7 @@ impl Rewrite for ast::ForeignItem { ) } ast::ForeignItemKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Item) + rewrite_macro(mac, context, shape, MacroPosition::Item) } }?; diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs index e239ff47c043..ddf3d2ce96af 100644 --- a/src/tools/rustfmt/src/macros.rs +++ b/src/tools/rustfmt/src/macros.rs @@ -16,10 +16,7 @@ use rustc_ast::token::{Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::{TokenStream, TokenStreamIter, TokenTree}; use rustc_ast::{ast, ptr}; use rustc_ast_pretty::pprust; -use rustc_span::{ - BytePos, DUMMY_SP, Span, Symbol, - symbol::{self, kw}, -}; +use rustc_span::{BytePos, DUMMY_SP, Ident, Span, Symbol}; use tracing::debug; use crate::comment::{ @@ -60,7 +57,7 @@ pub(crate) enum MacroArg { Ty(ptr::P), Pat(ptr::P), Item(ptr::P), - Keyword(symbol::Ident, Span), + Keyword(Ident, Span), } impl MacroArg { @@ -103,20 +100,12 @@ impl Rewrite for MacroArg { } /// Rewrite macro name without using pretty-printer if possible. -fn rewrite_macro_name( - context: &RewriteContext<'_>, - path: &ast::Path, - extra_ident: Option, -) -> String { - let name = if path.segments.len() == 1 { +fn rewrite_macro_name(context: &RewriteContext<'_>, path: &ast::Path) -> String { + if path.segments.len() == 1 { // Avoid using pretty-printer in the common case. format!("{}!", rewrite_ident(context, path.segments[0].ident)) } else { format!("{}!", pprust::path_to_string(path)) - }; - match extra_ident { - Some(ident) if ident.name != kw::Empty => format!("{name} {ident}"), - _ => name, } } @@ -165,7 +154,6 @@ fn return_macro_parse_failure_fallback( pub(crate) fn rewrite_macro( mac: &ast::MacCall, - extra_ident: Option, context: &RewriteContext<'_>, shape: Shape, position: MacroPosition, @@ -179,14 +167,7 @@ pub(crate) fn rewrite_macro( } else { let guard = context.enter_macro(); let result = catch_unwind(AssertUnwindSafe(|| { - rewrite_macro_inner( - mac, - extra_ident, - context, - shape, - position, - guard.is_nested(), - ) + rewrite_macro_inner(mac, context, shape, position, guard.is_nested()) })); match result { Err(..) => { @@ -207,7 +188,6 @@ pub(crate) fn rewrite_macro( fn rewrite_macro_inner( mac: &ast::MacCall, - extra_ident: Option, context: &RewriteContext<'_>, shape: Shape, position: MacroPosition, @@ -222,7 +202,7 @@ fn rewrite_macro_inner( let original_style = macro_style(mac, context); - let macro_name = rewrite_macro_name(context, &mac.path, extra_ident); + let macro_name = rewrite_macro_name(context, &mac.path); let is_forced_bracket = FORCED_BRACKET_MACROS.contains(&¯o_name[..]); let style = if is_forced_bracket && !is_nested_macro { @@ -432,7 +412,7 @@ pub(crate) fn rewrite_macro_def( shape: Shape, indent: Indent, def: &ast::MacroDef, - ident: symbol::Ident, + ident: Ident, vis: &ast::Visibility, span: Span, ) -> RewriteResult { diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs index bafed41e39f4..8dc945745032 100644 --- a/src/tools/rustfmt/src/patterns.rs +++ b/src/tools/rustfmt/src/patterns.rs @@ -307,9 +307,7 @@ impl Rewrite for Pat { context, shape, ), - PatKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Pat) - } + PatKind::MacCall(ref mac) => rewrite_macro(mac, context, shape, MacroPosition::Pat), PatKind::Paren(ref pat) => pat .rewrite_result( context, diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 06a67334086c..75a5a8532b84 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -1018,7 +1018,7 @@ impl Rewrite for ast::Ty { ast::TyKind::BareFn(ref bare_fn) => rewrite_bare_fn(bare_fn, self.span, context, shape), ast::TyKind::Never => Ok(String::from("!")), ast::TyKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Expression) + rewrite_macro(mac, context, shape, MacroPosition::Expression) } ast::TyKind::ImplicitSelf => Ok(String::from("")), ast::TyKind::ImplTrait(_, ref it) => { diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index c70649cc8125..c73976d90b1e 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -172,7 +172,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { get_span_without_attrs(stmt.as_ast_node()), ); } else { - self.visit_mac(&mac_stmt.mac, None, MacroPosition::Statement); + self.visit_mac(&mac_stmt.mac, MacroPosition::Statement); } self.format_missing(stmt.span().hi()); } @@ -531,7 +531,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.format_mod(mod_kind, safety, &item.vis, item.span, item.ident, attrs); } ast::ItemKind::MacCall(ref mac) => { - self.visit_mac(mac, Some(item.ident), MacroPosition::Item); + self.visit_mac(mac, MacroPosition::Item); } ast::ItemKind::ForeignMod(ref foreign_mod) => { self.format_missing_with_indent(source!(self, item.span).lo()); @@ -678,7 +678,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.visit_ty_alias_kind(ty_alias, &ai.vis, ai.ident, visitor_kind, ai.span); } (ast::AssocItemKind::MacCall(ref mac), _) => { - self.visit_mac(mac, Some(ai.ident), MacroPosition::Item); + self.visit_mac(mac, MacroPosition::Item); } _ => unreachable!(), } @@ -692,12 +692,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.visit_assoc_item(ii, ItemVisitorKind::AssocImplItem); } - fn visit_mac(&mut self, mac: &ast::MacCall, ident: Option, pos: MacroPosition) { + fn visit_mac(&mut self, mac: &ast::MacCall, pos: MacroPosition) { skip_out_of_file_lines_range_visitor!(self, mac.span()); // 1 = ; let shape = self.shape().saturating_sub_width(1); - let rewrite = self.with_context(|ctx| rewrite_macro(mac, ident, ctx, shape, pos).ok()); + let rewrite = self.with_context(|ctx| rewrite_macro(mac, ctx, shape, pos).ok()); // As of v638 of the rustc-ap-* crates, the associated span no longer includes // the trailing semicolon. This determines the correct span to ensure scenarios // with whitespace between the delimiters and trailing semi (i.e. `foo!(abc) ;`) From 43018eacb61da96b718f70b7719bf5e51207df61 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 21 Mar 2025 15:25:30 +1100 Subject: [PATCH 708/745] Ignore `#[test_case]` on anything other than `fn`/`const`/`static`. `expand_test_case` looks for any item with a `#[test_case]` attribute and adds a `test_path_symbol` attribute to it while also fiddling with the item's ident's span. This is pretty weird, because `#[test_case]` is only valid on `fn`/`const`/`static` items, as far as I can tell. But you don't currently get an error or warning if you use it on other kinds of items. This commit changes things so that a `#[test_case]` item is modified only if it is `fn`/`const`/`static`. This is relevant for moving idents from `Item` to `ItemKind`, because some item kinds don't have an ident, e.g. `impl` blocks. The commit also does the following. - Renames a local variable `test_id` as `test_ident`. - Changes a `const` to `static` in `tests/ui/custom_test_frameworks/full.rs` to give the `static` case some test coverage. - Adds a `struct` and `impl` to the same test to give some test coverage to the non-affected item kinds. These have a `FIXME` comment identifying the weirdness here. Hopefully this will be useful breadcrumbs for somebody else in the future. --- compiler/rustc_builtin_macros/src/test.rs | 46 +++++++++++++---------- tests/ui/custom_test_frameworks/full.rs | 14 ++++++- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 239f8657284d..db3e431495bf 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -51,21 +51,26 @@ pub(crate) fn expand_test_case( return vec![]; } }; - item = item.map(|mut item| { - let test_path_symbol = Symbol::intern(&item_path( - // skip the name of the root module - &ecx.current_expansion.module.mod_path[1..], - &item.ident, - )); - item.vis = ast::Visibility { - span: item.vis.span, - kind: ast::VisibilityKind::Public, - tokens: None, - }; - item.ident.span = item.ident.span.with_ctxt(sp.ctxt()); - item.attrs.push(ecx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, sp)); - item - }); + + // `#[test_case]` is valid on functions, consts, and statics. Only modify + // the item in those cases. + match &mut item.kind { + ast::ItemKind::Fn(_) | ast::ItemKind::Const(_) | ast::ItemKind::Static(_) => { + item.ident.span = item.ident.span.with_ctxt(sp.ctxt()); + let test_path_symbol = Symbol::intern(&item_path( + // skip the name of the root module + &ecx.current_expansion.module.mod_path[1..], + &item.ident, + )); + item.vis = ast::Visibility { + span: item.vis.span, + kind: ast::VisibilityKind::Public, + tokens: None, + }; + item.attrs.push(ecx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, sp)); + } + _ => {} + } let ret = if is_stmt { Annotatable::Stmt(P(ecx.stmt_item(item.span, item))) @@ -162,17 +167,17 @@ pub(crate) fn expand_test_or_bench( let ret_ty_sp = cx.with_def_site_ctxt(fn_.sig.decl.output.span()); let attr_sp = cx.with_def_site_ctxt(attr_sp); - let test_id = Ident::new(sym::test, attr_sp); + let test_ident = Ident::new(sym::test, attr_sp); // creates test::$name - let test_path = |name| cx.path(ret_ty_sp, vec![test_id, Ident::from_str_and_span(name, sp)]); + let test_path = |name| cx.path(ret_ty_sp, vec![test_ident, Ident::from_str_and_span(name, sp)]); // creates test::ShouldPanic::$name let should_panic_path = |name| { cx.path( sp, vec![ - test_id, + test_ident, Ident::from_str_and_span("ShouldPanic", sp), Ident::from_str_and_span(name, sp), ], @@ -184,7 +189,7 @@ pub(crate) fn expand_test_or_bench( cx.path( sp, vec![ - test_id, + test_ident, Ident::from_str_and_span("TestType", sp), Ident::from_str_and_span(name, sp), ], @@ -380,7 +385,8 @@ pub(crate) fn expand_test_or_bench( }); // extern crate test - let test_extern = cx.item(sp, test_id, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None)); + let test_extern = + cx.item(sp, test_ident, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None)); debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const)); diff --git a/tests/ui/custom_test_frameworks/full.rs b/tests/ui/custom_test_frameworks/full.rs index 289767b1f698..6be29f0418d6 100644 --- a/tests/ui/custom_test_frameworks/full.rs +++ b/tests/ui/custom_test_frameworks/full.rs @@ -25,4 +25,16 @@ impl example_runner::Testable for IsFoo { const TEST_1: IsFoo = IsFoo("hello"); #[test_case] -const TEST_2: IsFoo = IsFoo("foo"); +static TEST_2: IsFoo = IsFoo("foo"); + +// FIXME: `test_case` is currently ignored on anything other than +// fn/const/static. Should this be a warning/error? +#[test_case] +struct _S; + +// FIXME: `test_case` is currently ignored on anything other than +// fn/const/static. Should this be a warning/error? +#[test_case] +impl _S { + fn _f() {} +} From df247968f267d30fb8b048c21f595f2293d8ff62 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 21 Mar 2025 09:47:43 +1100 Subject: [PATCH 709/745] Move `ast::Item::ident` into `ast::ItemKind`. `ast::Item` has an `ident` field. - It's always non-empty for these item kinds: `ExternCrate`, `Static`, `Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`, `Trait`, `TraitAlias`, `MacroDef`, `Delegation`. - It's always empty for these item kinds: `Use`, `ForeignMod`, `GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`. There is a similar story for `AssocItemKind` and `ForeignItemKind`. Some sites that handle items check for an empty ident, some don't. This is a very C-like way of doing things, but this is Rust, we have sum types, we can do this properly and never forget to check for the exceptional case and never YOLO possibly empty identifiers (or possibly dummy spans) around and hope that things will work out. The commit is large but it's mostly obvious plumbing work. Some notable things. - `ast::Item` got 8 bytes bigger. This could be avoided by boxing the fields within some of the `ast::ItemKind` variants (specifically: `Struct`, `Union`, `Enum`). I might do that in a follow-up; this commit is big enough already. - For the visitors: `FnKind` no longer needs an `ident` field because the `Fn` within how has one. - In the parser, the `ItemInfo` typedef is no longer needed. It was used in various places to return an `Ident` alongside an `ItemKind`, but now the `Ident` (if present) is within the `ItemKind`. - In a few places I renamed identifier variables called `name` (or `foo_name`) as `ident` (or `foo_ident`), to better match the type, and because `name` is normally used for `Symbol`s. It's confusing to see something like `foo_name.name`. --- compiler/rustc_ast/src/ast.rs | 107 ++++-- compiler/rustc_ast/src/mut_visit.rs | 84 +++-- compiler/rustc_ast/src/visit.rs | 87 +++-- compiler/rustc_ast_lowering/src/delegation.rs | 8 +- compiler/rustc_ast_lowering/src/item.rs | 353 ++++++++++-------- .../rustc_ast_passes/src/ast_validation.rs | 83 ++-- compiler/rustc_ast_passes/src/feature_gate.rs | 2 +- .../rustc_ast_pretty/src/pprust/state/item.rs | 83 ++-- .../src/alloc_error_handler.rs | 11 +- compiler/rustc_builtin_macros/src/asm.rs | 3 +- .../src/assert/context.rs | 1 - compiler/rustc_builtin_macros/src/autodiff.rs | 28 +- .../src/deriving/clone.rs | 4 +- .../src/deriving/cmp/partial_ord.rs | 2 +- .../src/deriving/coerce_pointee.rs | 6 +- .../src/deriving/generic/mod.rs | 17 +- .../src/global_allocator.rs | 20 +- .../src/proc_macro_harness.rs | 41 +- .../src/standard_library_imports.rs | 4 +- compiler/rustc_builtin_macros/src/test.rs | 24 +- .../rustc_builtin_macros/src/test_harness.rs | 46 +-- compiler/rustc_expand/src/base.rs | 7 +- compiler/rustc_expand/src/build.rs | 17 +- compiler/rustc_expand/src/expand.rs | 13 +- compiler/rustc_expand/src/placeholders.rs | 7 +- compiler/rustc_lint/src/builtin.rs | 4 +- compiler/rustc_lint/src/nonstandard_style.rs | 22 +- compiler/rustc_metadata/src/creader.rs | 12 +- compiler/rustc_parse/src/parser/item.rs | 201 +++++----- compiler/rustc_parse/src/parser/tests.rs | 2 +- compiler/rustc_passes/src/lang_items.rs | 14 +- .../rustc_resolve/src/build_reduced_graph.rs | 81 ++-- compiler/rustc_resolve/src/check_unused.rs | 4 +- compiler/rustc_resolve/src/def_collector.rs | 33 +- compiler/rustc_resolve/src/diagnostics.rs | 2 +- .../src/effective_visibilities.rs | 4 +- compiler/rustc_resolve/src/late.rs | 68 ++-- .../rustc_resolve/src/late/diagnostics.rs | 56 +-- src/librustdoc/doctest/make.rs | 8 +- .../clippy_lints/src/crate_in_macro_def.rs | 2 +- .../src/doc/needless_doctest_main.rs | 16 +- .../clippy/clippy_lints/src/duplicate_mod.rs | 2 +- .../clippy_lints/src/empty_line_after.rs | 16 +- .../clippy_lints/src/empty_with_brackets.rs | 5 +- .../src/field_scoped_visibility_modifiers.rs | 2 +- .../src/multiple_bound_locations.rs | 2 +- .../clippy_lints/src/partial_pub_fields.rs | 2 +- .../src/single_component_path_imports.rs | 6 +- .../clippy/clippy_utils/src/ast_utils/mod.rs | 79 +++- src/tools/rustfmt/src/items.rs | 78 ++-- src/tools/rustfmt/src/modules.rs | 10 +- src/tools/rustfmt/src/reorder.rs | 17 +- src/tools/rustfmt/src/visitor.rs | 52 +-- tests/ui/stats/input-stats.stderr | 78 ++-- 54 files changed, 1072 insertions(+), 864 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 064f05ef1f3e..33c20602dfd2 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3303,9 +3303,6 @@ pub struct Item { pub id: NodeId, pub span: Span, pub vis: Visibility, - /// The name of the item. - /// It might be a dummy name in case of anonymous items. - pub ident: Ident, pub kind: K, @@ -3327,23 +3324,23 @@ impl Item { pub fn opt_generics(&self) -> Option<&Generics> { match &self.kind { - ItemKind::ExternCrate(_) + ItemKind::ExternCrate(..) | ItemKind::Use(_) - | ItemKind::Mod(_, _) + | ItemKind::Mod(..) | ItemKind::ForeignMod(_) | ItemKind::GlobalAsm(_) | ItemKind::MacCall(_) | ItemKind::Delegation(_) | ItemKind::DelegationMac(_) - | ItemKind::MacroDef(_) => None, + | ItemKind::MacroDef(..) => None, ItemKind::Static(_) => None, ItemKind::Const(i) => Some(&i.generics), ItemKind::Fn(i) => Some(&i.generics), ItemKind::TyAlias(i) => Some(&i.generics), - ItemKind::TraitAlias(generics, _) - | ItemKind::Enum(_, generics) - | ItemKind::Struct(_, generics) - | ItemKind::Union(_, generics) => Some(&generics), + ItemKind::TraitAlias(_, generics, _) + | ItemKind::Enum(_, _, generics) + | ItemKind::Struct(_, _, generics) + | ItemKind::Union(_, _, generics) => Some(&generics), ItemKind::Trait(i) => Some(&i.generics), ItemKind::Impl(i) => Some(&i.generics), } @@ -3420,6 +3417,7 @@ impl Default for FnHeader { pub struct Trait { pub safety: Safety, pub is_auto: IsAuto, + pub ident: Ident, pub generics: Generics, pub bounds: GenericBounds, pub items: ThinVec>, @@ -3465,6 +3463,7 @@ pub struct TyAliasWhereClauses { #[derive(Clone, Encodable, Decodable, Debug)] pub struct TyAlias { pub defaultness: Defaultness, + pub ident: Ident, pub generics: Generics, pub where_clauses: TyAliasWhereClauses, pub bounds: GenericBounds, @@ -3493,6 +3492,7 @@ pub struct FnContract { #[derive(Clone, Encodable, Decodable, Debug)] pub struct Fn { pub defaultness: Defaultness, + pub ident: Ident, pub generics: Generics, pub sig: FnSig, pub contract: Option>, @@ -3506,6 +3506,7 @@ pub struct Delegation { pub id: NodeId, pub qself: Option>, pub path: Path, + pub ident: Ident, pub rename: Option, pub body: Option>, /// The item was expanded from a glob delegation item. @@ -3523,6 +3524,7 @@ pub struct DelegationMac { #[derive(Clone, Encodable, Decodable, Debug)] pub struct StaticItem { + pub ident: Ident, pub ty: P, pub safety: Safety, pub mutability: Mutability, @@ -3533,6 +3535,7 @@ pub struct StaticItem { #[derive(Clone, Encodable, Decodable, Debug)] pub struct ConstItem { pub defaultness: Defaultness, + pub ident: Ident, pub generics: Generics, pub ty: P, pub expr: Option>, @@ -3545,7 +3548,7 @@ pub enum ItemKind { /// An `extern crate` item, with the optional *original* crate name if the crate was renamed. /// /// E.g., `extern crate foo` or `extern crate foo_bar as foo`. - ExternCrate(Option), + ExternCrate(Option, Ident), /// A use declaration item (`use`). /// /// E.g., `use foo;`, `use foo::bar;` or `use foo::bar as FooBar;`. @@ -3567,7 +3570,7 @@ pub enum ItemKind { /// E.g., `mod foo;` or `mod foo { .. }`. /// `unsafe` keyword on modules is accepted syntactically for macro DSLs, but not /// semantically by Rust. - Mod(Safety, ModKind), + Mod(Safety, Ident, ModKind), /// An external module (`extern`). /// /// E.g., `extern {}` or `extern "C" {}`. @@ -3581,15 +3584,15 @@ pub enum ItemKind { /// An enum definition (`enum`). /// /// E.g., `enum Foo { C, D }`. - Enum(EnumDef, Generics), + Enum(Ident, EnumDef, Generics), /// A struct definition (`struct`). /// /// E.g., `struct Foo { x: A }`. - Struct(VariantData, Generics), + Struct(Ident, VariantData, Generics), /// A union definition (`union`). /// /// E.g., `union Foo { x: A, y: B }`. - Union(VariantData, Generics), + Union(Ident, VariantData, Generics), /// A trait declaration (`trait`). /// /// E.g., `trait Foo { .. }`, `trait Foo { .. }` or `auto trait Foo {}`. @@ -3597,7 +3600,7 @@ pub enum ItemKind { /// Trait alias. /// /// E.g., `trait Foo = Bar + Quux;`. - TraitAlias(Generics, GenericBounds), + TraitAlias(Ident, Generics, GenericBounds), /// An implementation. /// /// E.g., `impl Foo { .. }` or `impl Trait for Foo { .. }`. @@ -3608,7 +3611,7 @@ pub enum ItemKind { MacCall(P), /// A macro definition. - MacroDef(MacroDef), + MacroDef(Ident, MacroDef), /// A single delegation item (`reuse`). /// @@ -3620,6 +3623,31 @@ pub enum ItemKind { } impl ItemKind { + pub fn ident(&self) -> Option { + match *self { + ItemKind::ExternCrate(_, ident) + | ItemKind::Static(box StaticItem { ident, .. }) + | ItemKind::Const(box ConstItem { ident, .. }) + | ItemKind::Fn(box Fn { ident, .. }) + | ItemKind::Mod(_, ident, _) + | ItemKind::TyAlias(box TyAlias { ident, .. }) + | ItemKind::Enum(ident, ..) + | ItemKind::Struct(ident, ..) + | ItemKind::Union(ident, ..) + | ItemKind::Trait(box Trait { ident, .. }) + | ItemKind::TraitAlias(ident, ..) + | ItemKind::MacroDef(ident, _) + | ItemKind::Delegation(box Delegation { ident, .. }) => Some(ident), + + ItemKind::Use(_) + | ItemKind::ForeignMod(_) + | ItemKind::GlobalAsm(_) + | ItemKind::Impl(_) + | ItemKind::MacCall(_) + | ItemKind::DelegationMac(_) => None, + } + } + /// "a" or "an" pub fn article(&self) -> &'static str { use ItemKind::*; @@ -3660,11 +3688,11 @@ impl ItemKind { Self::Fn(box Fn { generics, .. }) | Self::TyAlias(box TyAlias { generics, .. }) | Self::Const(box ConstItem { generics, .. }) - | Self::Enum(_, generics) - | Self::Struct(_, generics) - | Self::Union(_, generics) + | Self::Enum(_, _, generics) + | Self::Struct(_, _, generics) + | Self::Union(_, _, generics) | Self::Trait(box Trait { generics, .. }) - | Self::TraitAlias(generics, _) + | Self::TraitAlias(_, generics, _) | Self::Impl(box Impl { generics, .. }) => Some(generics), _ => None, } @@ -3700,6 +3728,17 @@ pub enum AssocItemKind { } impl AssocItemKind { + pub fn ident(&self) -> Option { + match *self { + AssocItemKind::Const(box ConstItem { ident, .. }) + | AssocItemKind::Fn(box Fn { ident, .. }) + | AssocItemKind::Type(box TyAlias { ident, .. }) + | AssocItemKind::Delegation(box Delegation { ident, .. }) => Some(ident), + + AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(_) => None, + } + } + pub fn defaultness(&self) -> Defaultness { match *self { Self::Const(box ConstItem { defaultness, .. }) @@ -3746,14 +3785,26 @@ impl TryFrom for AssocItemKind { pub enum ForeignItemKind { /// A foreign static item (`static FOO: u8`). Static(Box), - /// An foreign function. + /// A foreign function. Fn(Box), - /// An foreign type. + /// A foreign type. TyAlias(Box), /// A macro expanding to foreign items. MacCall(P), } +impl ForeignItemKind { + pub fn ident(&self) -> Option { + match *self { + ForeignItemKind::Static(box StaticItem { ident, .. }) + | ForeignItemKind::Fn(box Fn { ident, .. }) + | ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => Some(ident), + + ForeignItemKind::MacCall(_) => None, + } + } +} + impl From for ItemKind { fn from(foreign_item_kind: ForeignItemKind) -> ItemKind { match foreign_item_kind { @@ -3790,21 +3841,21 @@ mod size_asserts { use super::*; // tidy-alphabetical-start - static_assert_size!(AssocItem, 88); + static_assert_size!(AssocItem, 80); static_assert_size!(AssocItemKind, 16); static_assert_size!(Attribute, 32); static_assert_size!(Block, 32); static_assert_size!(Expr, 72); static_assert_size!(ExprKind, 40); - static_assert_size!(Fn, 176); - static_assert_size!(ForeignItem, 88); + static_assert_size!(Fn, 184); + static_assert_size!(ForeignItem, 80); static_assert_size!(ForeignItemKind, 16); static_assert_size!(GenericArg, 24); static_assert_size!(GenericBound, 88); static_assert_size!(Generics, 40); static_assert_size!(Impl, 136); - static_assert_size!(Item, 136); - static_assert_size!(ItemKind, 64); + static_assert_size!(Item, 144); + static_assert_size!(ItemKind, 80); static_assert_size!(LitKind, 24); static_assert_size!(Local, 80); static_assert_size!(MetaItemLit, 40); diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 274fe312f7fa..30af6d910bfa 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -41,7 +41,6 @@ pub trait WalkItemKind { &mut self, span: Span, id: NodeId, - ident: &mut Ident, visibility: &mut Visibility, ctxt: Self::Ctxt, visitor: &mut impl MutVisitor, @@ -963,10 +962,10 @@ fn walk_fn(vis: &mut T, kind: FnKind<'_>) { match kind { FnKind::Fn( _ctxt, - _ident, _vis, Fn { defaultness, + ident, generics, contract, body, @@ -974,8 +973,9 @@ fn walk_fn(vis: &mut T, kind: FnKind<'_>) { define_opaque, }, ) => { - // Identifier and visibility are visited as a part of the item. + // Visibility is visited as a part of the item. visit_defaultness(vis, defaultness); + vis.visit_ident(ident); vis.visit_fn_header(header); vis.visit_generics(generics); vis.visit_fn_decl(decl); @@ -1233,12 +1233,11 @@ pub fn walk_item_kind( kind: &mut K, span: Span, id: NodeId, - ident: &mut Ident, visibility: &mut Visibility, ctxt: K::Ctxt, vis: &mut impl MutVisitor, ) { - kind.walk(span, id, ident, visibility, ctxt, vis) + kind.walk(span, id, visibility, ctxt, vis) } impl WalkItemKind for ItemKind { @@ -1247,21 +1246,22 @@ impl WalkItemKind for ItemKind { &mut self, span: Span, id: NodeId, - ident: &mut Ident, visibility: &mut Visibility, _ctxt: Self::Ctxt, vis: &mut impl MutVisitor, ) { match self { - ItemKind::ExternCrate(_orig_name) => {} + ItemKind::ExternCrate(_orig_name, ident) => vis.visit_ident(ident), ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree), ItemKind::Static(box StaticItem { + ident, ty, safety: _, mutability: _, expr, define_opaque, }) => { + vis.visit_ident(ident); vis.visit_ty(ty); visit_opt(expr, |expr| vis.visit_expr(expr)); walk_define_opaques(vis, define_opaque); @@ -1270,10 +1270,11 @@ impl WalkItemKind for ItemKind { walk_const_item(vis, item); } ItemKind::Fn(func) => { - vis.visit_fn(FnKind::Fn(FnCtxt::Free, ident, visibility, &mut *func), span, id); + vis.visit_fn(FnKind::Fn(FnCtxt::Free, visibility, &mut *func), span, id); } - ItemKind::Mod(safety, mod_kind) => { + ItemKind::Mod(safety, ident, mod_kind) => { visit_safety(vis, safety); + vis.visit_ident(ident); match mod_kind { ModKind::Loaded( items, @@ -1290,18 +1291,29 @@ impl WalkItemKind for ItemKind { } ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm), ItemKind::GlobalAsm(asm) => vis.visit_inline_asm(asm), - ItemKind::TyAlias(box TyAlias { defaultness, generics, where_clauses, bounds, ty }) => { + ItemKind::TyAlias(box TyAlias { + defaultness, + ident, + generics, + where_clauses, + bounds, + ty, + }) => { visit_defaultness(vis, defaultness); + vis.visit_ident(ident); vis.visit_generics(generics); visit_bounds(vis, bounds, BoundKind::Bound); visit_opt(ty, |ty| vis.visit_ty(ty)); walk_ty_alias_where_clauses(vis, where_clauses); } - ItemKind::Enum(EnumDef { variants }, generics) => { + ItemKind::Enum(ident, EnumDef { variants }, generics) => { + vis.visit_ident(ident); vis.visit_generics(generics); variants.flat_map_in_place(|variant| vis.flat_map_variant(variant)); } - ItemKind::Struct(variant_data, generics) | ItemKind::Union(variant_data, generics) => { + ItemKind::Struct(ident, variant_data, generics) + | ItemKind::Union(ident, variant_data, generics) => { + vis.visit_ident(ident); vis.visit_generics(generics); vis.visit_variant_data(variant_data); } @@ -1326,22 +1338,28 @@ impl WalkItemKind for ItemKind { vis.flat_map_assoc_item(item, AssocCtxt::Impl { of_trait: of_trait.is_some() }) }); } - ItemKind::Trait(box Trait { safety, is_auto: _, generics, bounds, items }) => { + ItemKind::Trait(box Trait { safety, is_auto: _, ident, generics, bounds, items }) => { visit_safety(vis, safety); + vis.visit_ident(ident); vis.visit_generics(generics); visit_bounds(vis, bounds, BoundKind::Bound); items.flat_map_in_place(|item| vis.flat_map_assoc_item(item, AssocCtxt::Trait)); } - ItemKind::TraitAlias(generics, bounds) => { + ItemKind::TraitAlias(ident, generics, bounds) => { + vis.visit_ident(ident); vis.visit_generics(generics); visit_bounds(vis, bounds, BoundKind::Bound); } ItemKind::MacCall(m) => vis.visit_mac_call(m), - ItemKind::MacroDef(def) => vis.visit_macro_def(def), + ItemKind::MacroDef(ident, def) => { + vis.visit_ident(ident); + vis.visit_macro_def(def) + } ItemKind::Delegation(box Delegation { id, qself, path, + ident, rename, body, from_glob: _, @@ -1349,6 +1367,7 @@ impl WalkItemKind for ItemKind { vis.visit_id(id); vis.visit_qself(qself); vis.visit_path(path); + vis.visit_ident(ident); if let Some(rename) = rename { vis.visit_ident(rename); } @@ -1381,7 +1400,6 @@ impl WalkItemKind for AssocItemKind { &mut self, span: Span, id: NodeId, - ident: &mut Ident, visibility: &mut Visibility, ctxt: Self::Ctxt, visitor: &mut impl MutVisitor, @@ -1391,20 +1409,18 @@ impl WalkItemKind for AssocItemKind { walk_const_item(visitor, item); } AssocItemKind::Fn(func) => { - visitor.visit_fn( - FnKind::Fn(FnCtxt::Assoc(ctxt), ident, visibility, &mut *func), - span, - id, - ); + visitor.visit_fn(FnKind::Fn(FnCtxt::Assoc(ctxt), visibility, &mut *func), span, id); } AssocItemKind::Type(box TyAlias { defaultness, + ident, generics, where_clauses, bounds, ty, }) => { visit_defaultness(visitor, defaultness); + visitor.visit_ident(ident); visitor.visit_generics(generics); visit_bounds(visitor, bounds, BoundKind::Bound); visit_opt(ty, |ty| visitor.visit_ty(ty)); @@ -1415,6 +1431,7 @@ impl WalkItemKind for AssocItemKind { id, qself, path, + ident, rename, body, from_glob: _, @@ -1422,6 +1439,7 @@ impl WalkItemKind for AssocItemKind { visitor.visit_id(id); visitor.visit_qself(qself); visitor.visit_path(path); + visitor.visit_ident(ident); if let Some(rename) = rename { visitor.visit_ident(rename); } @@ -1449,8 +1467,9 @@ impl WalkItemKind for AssocItemKind { } fn walk_const_item(vis: &mut T, item: &mut ConstItem) { - let ConstItem { defaultness, generics, ty, expr, define_opaque } = item; + let ConstItem { defaultness, ident, generics, ty, expr, define_opaque } = item; visit_defaultness(vis, defaultness); + vis.visit_ident(ident); vis.visit_generics(generics); vis.visit_ty(ty); visit_opt(expr, |expr| vis.visit_expr(expr)); @@ -1487,12 +1506,11 @@ fn walk_item_ctxt( item: &mut P>, ctxt: K::Ctxt, ) { - let Item { ident, attrs, id, kind, vis, span, tokens } = item.deref_mut(); + let Item { attrs, id, kind, vis, span, tokens } = item.deref_mut(); visitor.visit_id(id); visit_attrs(visitor, attrs); visitor.visit_vis(vis); - visitor.visit_ident(ident); - kind.walk(*span, *id, ident, vis, ctxt, visitor); + kind.walk(*span, *id, vis, ctxt, visitor); visit_lazy_tts(visitor, tokens); visitor.visit_span(span); } @@ -1525,38 +1543,37 @@ impl WalkItemKind for ForeignItemKind { &mut self, span: Span, id: NodeId, - ident: &mut Ident, visibility: &mut Visibility, _ctxt: Self::Ctxt, visitor: &mut impl MutVisitor, ) { match self { ForeignItemKind::Static(box StaticItem { + ident, ty, mutability: _, expr, safety: _, define_opaque, }) => { + visitor.visit_ident(ident); visitor.visit_ty(ty); visit_opt(expr, |expr| visitor.visit_expr(expr)); walk_define_opaques(visitor, define_opaque); } ForeignItemKind::Fn(func) => { - visitor.visit_fn( - FnKind::Fn(FnCtxt::Foreign, ident, visibility, &mut *func), - span, - id, - ); + visitor.visit_fn(FnKind::Fn(FnCtxt::Foreign, visibility, &mut *func), span, id); } ForeignItemKind::TyAlias(box TyAlias { defaultness, + ident, generics, where_clauses, bounds, ty, }) => { visit_defaultness(visitor, defaultness); + visitor.visit_ident(ident); visitor.visit_generics(generics); visit_bounds(visitor, bounds, BoundKind::Bound); visit_opt(ty, |ty| visitor.visit_ty(ty)); @@ -1984,8 +2001,7 @@ impl DummyAstNode for Item { span: Default::default(), tokens: Default::default(), }, - ident: Ident::dummy(), - kind: ItemKind::ExternCrate(None), + kind: ItemKind::ExternCrate(None, Ident::dummy()), tokens: Default::default(), } } @@ -2052,7 +2068,7 @@ impl DummyAstNode for crate::ast_traits::AstNo #[derive(Debug)] pub enum FnKind<'a> { /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`. - Fn(FnCtxt, &'a mut Ident, &'a mut Visibility, &'a mut Fn), + Fn(FnCtxt, &'a mut Visibility, &'a mut Fn), /// E.g., `|x, y| body`. Closure( diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 2716601ca4f9..1ef92ff8898e 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -66,7 +66,7 @@ impl BoundKind { #[derive(Copy, Clone, Debug)] pub enum FnKind<'a> { /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`. - Fn(FnCtxt, &'a Ident, &'a Visibility, &'a Fn), + Fn(FnCtxt, &'a Visibility, &'a Fn), /// E.g., `|x, y| body`. Closure(&'a ClosureBinder, &'a Option, &'a FnDecl, &'a Expr), @@ -75,21 +75,21 @@ pub enum FnKind<'a> { impl<'a> FnKind<'a> { pub fn header(&self) -> Option<&'a FnHeader> { match *self { - FnKind::Fn(_, _, _, Fn { sig, .. }) => Some(&sig.header), + FnKind::Fn(_, _, Fn { sig, .. }) => Some(&sig.header), FnKind::Closure(..) => None, } } pub fn ident(&self) -> Option<&Ident> { match self { - FnKind::Fn(_, ident, ..) => Some(ident), + FnKind::Fn(_, _, Fn { ident, .. }) => Some(ident), _ => None, } } pub fn decl(&self) -> &'a FnDecl { match self { - FnKind::Fn(_, _, _, Fn { sig, .. }) => &sig.decl, + FnKind::Fn(_, _, Fn { sig, .. }) => &sig.decl, FnKind::Closure(_, _, decl, _) => decl, } } @@ -118,7 +118,6 @@ pub trait WalkItemKind { &'a self, span: Span, id: NodeId, - ident: &'a Ident, visibility: &'a Visibility, ctxt: Self::Ctxt, visitor: &mut V, @@ -364,63 +363,72 @@ impl WalkItemKind for ItemKind { &'a self, span: Span, id: NodeId, - ident: &'a Ident, vis: &'a Visibility, _ctxt: Self::Ctxt, visitor: &mut V, ) -> V::Result { match self { - ItemKind::ExternCrate(_rename) => {} + ItemKind::ExternCrate(_rename, ident) => try_visit!(visitor.visit_ident(ident)), ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, id, false)), ItemKind::Static(box StaticItem { + ident, ty, safety: _, mutability: _, expr, define_opaque, }) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); try_visit!(walk_define_opaques(visitor, define_opaque)); } ItemKind::Const(box ConstItem { defaultness: _, + ident, generics, ty, expr, define_opaque, }) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); try_visit!(walk_define_opaques(visitor, define_opaque)); } ItemKind::Fn(func) => { - let kind = FnKind::Fn(FnCtxt::Free, ident, vis, &*func); + let kind = FnKind::Fn(FnCtxt::Free, vis, &*func); try_visit!(visitor.visit_fn(kind, span, id)); } - ItemKind::Mod(_unsafety, mod_kind) => match mod_kind { - ModKind::Loaded(items, _inline, _inner_span, _) => { - walk_list!(visitor, visit_item, items); + ItemKind::Mod(_unsafety, ident, mod_kind) => { + try_visit!(visitor.visit_ident(ident)); + match mod_kind { + ModKind::Loaded(items, _inline, _inner_span, _) => { + walk_list!(visitor, visit_item, items); + } + ModKind::Unloaded => {} } - ModKind::Unloaded => {} - }, + } ItemKind::ForeignMod(ForeignMod { extern_span: _, safety: _, abi: _, items }) => { walk_list!(visitor, visit_foreign_item, items); } ItemKind::GlobalAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)), ItemKind::TyAlias(box TyAlias { generics, + ident, bounds, ty, defaultness: _, where_clauses: _, }) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); visit_opt!(visitor, visit_ty, ty); } - ItemKind::Enum(enum_definition, generics) => { + ItemKind::Enum(ident, enum_definition, generics) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_enum_def(enum_definition)); } @@ -444,32 +452,47 @@ impl WalkItemKind for ItemKind { AssocCtxt::Impl { of_trait: of_trait.is_some() } ); } - ItemKind::Struct(struct_definition, generics) - | ItemKind::Union(struct_definition, generics) => { + ItemKind::Struct(ident, struct_definition, generics) + | ItemKind::Union(ident, struct_definition, generics) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_variant_data(struct_definition)); } - ItemKind::Trait(box Trait { safety: _, is_auto: _, generics, bounds, items }) => { + ItemKind::Trait(box Trait { + safety: _, + is_auto: _, + ident, + generics, + bounds, + items, + }) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::SuperTraits); walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait); } - ItemKind::TraitAlias(generics, bounds) => { + ItemKind::TraitAlias(ident, generics, bounds) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); } ItemKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)), - ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, id)), + ItemKind::MacroDef(ident, ts) => { + try_visit!(visitor.visit_ident(ident)); + try_visit!(visitor.visit_mac_def(ts, id)) + } ItemKind::Delegation(box Delegation { id, qself, path, + ident, rename, body, from_glob: _, }) => { try_visit!(visitor.visit_qself(qself)); try_visit!(visitor.visit_path(path, *id)); + try_visit!(visitor.visit_ident(ident)); visit_opt!(visitor, visit_ident, rename); visit_opt!(visitor, visit_block, body); } @@ -743,34 +766,37 @@ impl WalkItemKind for ForeignItemKind { &'a self, span: Span, id: NodeId, - ident: &'a Ident, vis: &'a Visibility, _ctxt: Self::Ctxt, visitor: &mut V, ) -> V::Result { match self { ForeignItemKind::Static(box StaticItem { + ident, ty, mutability: _, expr, safety: _, define_opaque, }) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); try_visit!(walk_define_opaques(visitor, define_opaque)); } ForeignItemKind::Fn(func) => { - let kind = FnKind::Fn(FnCtxt::Foreign, ident, vis, &*func); + let kind = FnKind::Fn(FnCtxt::Foreign, vis, &*func); try_visit!(visitor.visit_fn(kind, span, id)); } ForeignItemKind::TyAlias(box TyAlias { generics, + ident, bounds, ty, defaultness: _, where_clauses: _, }) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); visit_opt!(visitor, visit_ty, ty); @@ -917,10 +943,10 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu match kind { FnKind::Fn( _ctxt, - _ident, _vis, Fn { defaultness: _, + ident, sig: FnSig { header, decl, span: _ }, generics, contract, @@ -928,7 +954,8 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu define_opaque, }, ) => { - // Identifier and visibility are visited as a part of the item. + // Visibility is visited as a part of the item. + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_fn_header(header)); try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_fn_decl(decl)); @@ -952,7 +979,6 @@ impl WalkItemKind for AssocItemKind { &'a self, span: Span, id: NodeId, - ident: &'a Ident, vis: &'a Visibility, ctxt: Self::Ctxt, visitor: &mut V, @@ -960,28 +986,32 @@ impl WalkItemKind for AssocItemKind { match self { AssocItemKind::Const(box ConstItem { defaultness: _, + ident, generics, ty, expr, define_opaque, }) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); try_visit!(walk_define_opaques(visitor, define_opaque)); } AssocItemKind::Fn(func) => { - let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, vis, &*func); + let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), vis, &*func); try_visit!(visitor.visit_fn(kind, span, id)); } AssocItemKind::Type(box TyAlias { generics, + ident, bounds, ty, defaultness: _, where_clauses: _, }) => { try_visit!(visitor.visit_generics(generics)); + try_visit!(visitor.visit_ident(ident)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); visit_opt!(visitor, visit_ty, ty); } @@ -992,12 +1022,14 @@ impl WalkItemKind for AssocItemKind { id, qself, path, + ident, rename, body, from_glob: _, }) => { try_visit!(visitor.visit_qself(qself)); try_visit!(visitor.visit_path(path, *id)); + try_visit!(visitor.visit_ident(ident)); visit_opt!(visitor, visit_ident, rename); visit_opt!(visitor, visit_block, body); } @@ -1039,11 +1071,10 @@ fn walk_item_ctxt<'a, V: Visitor<'a>, K: WalkItemKind>( item: &'a Item, ctxt: K::Ctxt, ) -> V::Result { - let Item { id, span, ident, vis, attrs, kind, tokens: _ } = item; + let Item { id, span, vis, attrs, kind, tokens: _ } = item; walk_list!(visitor, visit_attribute, attrs); try_visit!(visitor.visit_vis(vis)); - try_visit!(visitor.visit_ident(ident)); - try_visit!(kind.walk(*span, *id, ident, vis, ctxt, visitor)); + try_visit!(kind.walk(*span, *id, vis, ctxt, visitor)); V::Result::output() } diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index f7640c602d6f..9899ee03a513 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -56,6 +56,7 @@ use crate::{AllowReturnTypeNotation, ImplTraitPosition, ResolverAstLoweringExt}; pub(crate) struct DelegationResults<'hir> { pub body_id: hir::BodyId, pub sig: hir::FnSig<'hir>, + pub ident: Ident, pub generics: &'hir hir::Generics<'hir>, } @@ -104,9 +105,9 @@ impl<'hir> LoweringContext<'_, 'hir> { let decl = self.lower_delegation_decl(sig_id, param_count, c_variadic, span); let sig = self.lower_delegation_sig(sig_id, decl, span); let body_id = self.lower_delegation_body(delegation, param_count, span); - + let ident = self.lower_ident(delegation.ident); let generics = self.lower_delegation_generics(span); - DelegationResults { body_id, sig, generics } + DelegationResults { body_id, sig, ident, generics } } Err(err) => self.generate_delegation_error(err, span), } @@ -405,8 +406,9 @@ impl<'hir> LoweringContext<'_, 'hir> { let header = self.generate_header_error(); let sig = hir::FnSig { decl, header, span }; + let ident = Ident::dummy(); let body_id = self.lower_body(|this| (&[], this.mk_expr(hir::ExprKind::Err(err), span))); - DelegationResults { generics, body_id, sig } + DelegationResults { ident, generics, body_id, sig } } fn generate_header_error(&self) -> hir::FnHeader { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 43bf951eddc6..28f596ac0926 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -107,7 +107,6 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { } fn lower_foreign_item(&mut self, item: &ForeignItem) { - debug_assert_ne!(item.ident.name, kw::Empty); self.with_lctx(item.id, |lctx| hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item))) } } @@ -151,7 +150,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let vis_span = self.lower_span(i.vis.span); let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); - let kind = self.lower_item_kind(i.span, i.id, hir_id, i.ident, attrs, vis_span, &i.kind); + let kind = self.lower_item_kind(i.span, i.id, hir_id, attrs, vis_span, &i.kind); let item = hir::Item { owner_id: hir_id.expect_owner(), kind, @@ -166,41 +165,44 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, id: NodeId, hir_id: hir::HirId, - ident: Ident, attrs: &'hir [hir::Attribute], vis_span: Span, i: &ItemKind, ) -> hir::ItemKind<'hir> { match i { - ItemKind::ExternCrate(orig_name) => { - debug_assert_ne!(ident.name, kw::Empty); - let ident = self.lower_ident(ident); + ItemKind::ExternCrate(orig_name, ident) => { + let ident = self.lower_ident(*ident); hir::ItemKind::ExternCrate(*orig_name, ident) } ItemKind::Use(use_tree) => { - debug_assert_eq!(ident.name, kw::Empty); // Start with an empty prefix. let prefix = Path { segments: ThinVec::new(), span: use_tree.span, tokens: None }; self.lower_use_tree(use_tree, &prefix, id, vis_span, attrs) } ItemKind::Static(box ast::StaticItem { + ident, ty: t, safety: _, mutability: m, expr: e, define_opaque, }) => { - debug_assert_ne!(ident.name, kw::Empty); - let ident = self.lower_ident(ident); + let ident = self.lower_ident(*ident); let (ty, body_id) = self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy); self.lower_define_opaque(hir_id, define_opaque); hir::ItemKind::Static(ident, ty, *m, body_id) } - ItemKind::Const(box ast::ConstItem { generics, ty, expr, define_opaque, .. }) => { - debug_assert_ne!(ident.name, kw::Empty); - let ident = self.lower_ident(ident); + ItemKind::Const(box ast::ConstItem { + ident, + generics, + ty, + expr, + define_opaque, + .. + }) => { + let ident = self.lower_ident(*ident); let (generics, (ty, body_id)) = self.lower_generics( generics, id, @@ -214,13 +216,13 @@ impl<'hir> LoweringContext<'_, 'hir> { } ItemKind::Fn(box Fn { sig: FnSig { decl, header, span: fn_sig_span }, + ident, generics, body, contract, define_opaque, .. }) => { - debug_assert_ne!(ident.name, kw::Empty); self.with_new_scopes(*fn_sig_span, |this| { // Note: we don't need to change the return type from `T` to // `impl Future` here because lower_body @@ -248,7 +250,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span: this.lower_span(*fn_sig_span), }; this.lower_define_opaque(hir_id, define_opaque); - let ident = this.lower_ident(ident); + let ident = this.lower_ident(*ident); hir::ItemKind::Fn { ident, sig, @@ -258,9 +260,8 @@ impl<'hir> LoweringContext<'_, 'hir> { } }) } - ItemKind::Mod(_, mod_kind) => { - debug_assert_ne!(ident.name, kw::Empty); - let ident = self.lower_ident(ident); + ItemKind::Mod(_, ident, mod_kind) => { + let ident = self.lower_ident(*ident); match mod_kind { ModKind::Loaded(items, _, spans, _) => { hir::ItemKind::Mod(ident, self.lower_mod(items, spans)) @@ -268,24 +269,19 @@ impl<'hir> LoweringContext<'_, 'hir> { ModKind::Unloaded => panic!("`mod` items should have been loaded by now"), } } - ItemKind::ForeignMod(fm) => { - debug_assert_eq!(ident.name, kw::Empty); - hir::ItemKind::ForeignMod { - abi: fm.abi.map_or(ExternAbi::FALLBACK, |abi| self.lower_abi(abi)), - items: self - .arena - .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))), - } - } + ItemKind::ForeignMod(fm) => hir::ItemKind::ForeignMod { + abi: fm.abi.map_or(ExternAbi::FALLBACK, |abi| self.lower_abi(abi)), + items: self + .arena + .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))), + }, ItemKind::GlobalAsm(asm) => { - debug_assert_eq!(ident.name, kw::Empty); let asm = self.lower_inline_asm(span, asm); let fake_body = self.lower_body(|this| (&[], this.expr(span, hir::ExprKind::InlineAsm(asm)))); hir::ItemKind::GlobalAsm { asm, fake_body } } - ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => { - debug_assert_ne!(ident.name, kw::Empty); + ItemKind::TyAlias(box TyAlias { ident, generics, where_clauses, ty, .. }) => { // We lower // // type Foo = impl Trait @@ -294,7 +290,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // // type Foo = Foo1 // opaque type Foo1: Trait - let ident = self.lower_ident(ident); + let ident = self.lower_ident(*ident); let mut generics = generics.clone(); add_ty_alias_where_clause(&mut generics, *where_clauses, true); let (generics, ty) = self.lower_generics( @@ -322,9 +318,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ItemKind::TyAlias(ident, ty, generics) } - ItemKind::Enum(enum_definition, generics) => { - debug_assert_ne!(ident.name, kw::Empty); - let ident = self.lower_ident(ident); + ItemKind::Enum(ident, enum_definition, generics) => { + let ident = self.lower_ident(*ident); let (generics, variants) = self.lower_generics( generics, id, @@ -337,9 +332,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ItemKind::Enum(ident, hir::EnumDef { variants }, generics) } - ItemKind::Struct(struct_def, generics) => { - debug_assert_ne!(ident.name, kw::Empty); - let ident = self.lower_ident(ident); + ItemKind::Struct(ident, struct_def, generics) => { + let ident = self.lower_ident(*ident); let (generics, struct_def) = self.lower_generics( generics, id, @@ -348,9 +342,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ItemKind::Struct(ident, struct_def, generics) } - ItemKind::Union(vdata, generics) => { - debug_assert_ne!(ident.name, kw::Empty); - let ident = self.lower_ident(ident); + ItemKind::Union(ident, vdata, generics) => { + let ident = self.lower_ident(*ident); let (generics, vdata) = self.lower_generics( generics, id, @@ -369,7 +362,6 @@ impl<'hir> LoweringContext<'_, 'hir> { self_ty: ty, items: impl_items, }) => { - debug_assert_eq!(ident.name, kw::Empty); // Lower the "impl header" first. This ordering is important // for in-band lifetimes! Consider `'a` here: // @@ -435,9 +427,8 @@ impl<'hir> LoweringContext<'_, 'hir> { items: new_impl_items, })) } - ItemKind::Trait(box Trait { is_auto, safety, generics, bounds, items }) => { - debug_assert_ne!(ident.name, kw::Empty); - let ident = self.lower_ident(ident); + ItemKind::Trait(box Trait { is_auto, safety, ident, generics, bounds, items }) => { + let ident = self.lower_ident(*ident); let (generics, (safety, items, bounds)) = self.lower_generics( generics, id, @@ -456,9 +447,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ItemKind::Trait(*is_auto, safety, ident, generics, bounds, items) } - ItemKind::TraitAlias(generics, bounds) => { - debug_assert_ne!(ident.name, kw::Empty); - let ident = self.lower_ident(ident); + ItemKind::TraitAlias(ident, generics, bounds) => { + let ident = self.lower_ident(*ident); let (generics, bounds) = self.lower_generics( generics, id, @@ -472,9 +462,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ItemKind::TraitAlias(ident, generics, bounds) } - ItemKind::MacroDef(MacroDef { body, macro_rules }) => { - debug_assert_ne!(ident.name, kw::Empty); - let ident = self.lower_ident(ident); + ItemKind::MacroDef(ident, MacroDef { body, macro_rules }) => { + let ident = self.lower_ident(*ident); let body = P(self.lower_delim_args(body)); let def_id = self.local_def_id(id); let def_kind = self.tcx.def_kind(def_id); @@ -488,11 +477,9 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ItemKind::Macro(ident, macro_def, macro_kind) } ItemKind::Delegation(box delegation) => { - debug_assert_ne!(ident.name, kw::Empty); - let ident = self.lower_ident(ident); let delegation_results = self.lower_delegation(delegation, id, false); hir::ItemKind::Fn { - ident, + ident: delegation_results.ident, sig: delegation_results.sig, generics: delegation_results.generics, body: delegation_results.body_id, @@ -649,61 +636,64 @@ impl<'hir> LoweringContext<'_, 'hir> { let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); let owner_id = hir_id.expect_owner(); let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); - let item = hir::ForeignItem { - owner_id, - ident: self.lower_ident(i.ident), - kind: match &i.kind { - ForeignItemKind::Fn(box Fn { sig, generics, define_opaque, .. }) => { - let fdec = &sig.decl; - let itctx = ImplTraitContext::Universal; - let (generics, (decl, fn_args)) = - self.lower_generics(generics, i.id, itctx, |this| { - ( - // Disallow `impl Trait` in foreign items. - this.lower_fn_decl( - fdec, - i.id, - sig.span, - FnDeclKind::ExternFn, - None, - ), - this.lower_fn_params_to_names(fdec), - ) - }); + let (ident, kind) = match &i.kind { + ForeignItemKind::Fn(box Fn { sig, ident, generics, define_opaque, .. }) => { + let fdec = &sig.decl; + let itctx = ImplTraitContext::Universal; + let (generics, (decl, fn_args)) = + self.lower_generics(generics, i.id, itctx, |this| { + ( + // Disallow `impl Trait` in foreign items. + this.lower_fn_decl(fdec, i.id, sig.span, FnDeclKind::ExternFn, None), + this.lower_fn_params_to_names(fdec), + ) + }); - // Unmarked safety in unsafe block defaults to unsafe. - let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe, attrs); + // Unmarked safety in unsafe block defaults to unsafe. + let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe, attrs); - if define_opaque.is_some() { - self.dcx().span_err(i.span, "foreign functions cannot define opaque types"); - } + if define_opaque.is_some() { + self.dcx().span_err(i.span, "foreign functions cannot define opaque types"); + } + ( + ident, hir::ForeignItemKind::Fn( hir::FnSig { header, decl, span: self.lower_span(sig.span) }, fn_args, generics, - ) - } - ForeignItemKind::Static(box StaticItem { - ty, - mutability, - expr: _, - safety, - define_opaque, - }) => { - let ty = self - .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy)); - let safety = self.lower_safety(*safety, hir::Safety::Unsafe); + ), + ) + } + ForeignItemKind::Static(box StaticItem { + ident, + ty, + mutability, + expr: _, + safety, + define_opaque, + }) => { + let ty = + self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy)); + let safety = self.lower_safety(*safety, hir::Safety::Unsafe); - if define_opaque.is_some() { - self.dcx().span_err(i.span, "foreign statics cannot define opaque types"); - } - - hir::ForeignItemKind::Static(ty, *mutability, safety) + // njn: where for this? + if define_opaque.is_some() { + self.dcx().span_err(i.span, "foreign statics cannot define opaque types"); } - ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, - ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"), - }, + + (ident, hir::ForeignItemKind::Static(ty, *mutability, safety)) + } + ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => { + (ident, hir::ForeignItemKind::Type) + } + ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"), + }; + + let item = hir::ForeignItem { + owner_id, + ident: self.lower_ident(*ident), + kind, vis_span: self.lower_span(i.vis.span), span: self.lower_span(i.span), }; @@ -713,7 +703,9 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef { hir::ForeignItemRef { id: hir::ForeignItemId { owner_id: self.owner_id(i.id) }, - ident: self.lower_ident(i.ident), + // `unwrap` is safe because `ForeignItemKind::MacCall` is the only foreign item kind + // without an identifier and it cannot reach here. + ident: self.lower_ident(i.kind.ident().unwrap()), span: self.lower_span(i.span), } } @@ -800,13 +792,19 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> { - debug_assert_ne!(i.ident.name, kw::Empty); let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); let trait_item_def_id = hir_id.expect_owner(); - let (generics, kind, has_default) = match &i.kind { - AssocItemKind::Const(box ConstItem { generics, ty, expr, define_opaque, .. }) => { + let (ident, generics, kind, has_default) = match &i.kind { + AssocItemKind::Const(box ConstItem { + ident, + generics, + ty, + expr, + define_opaque, + .. + }) => { let (generics, kind) = self.lower_generics( generics, i.id, @@ -831,9 +829,11 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - (generics, kind, expr.is_some()) + (*ident, generics, kind, expr.is_some()) } - AssocItemKind::Fn(box Fn { sig, generics, body: None, define_opaque, .. }) => { + AssocItemKind::Fn(box Fn { + sig, ident, generics, body: None, define_opaque, .. + }) => { // FIXME(contracts): Deny contract here since it won't apply to // any impl method or callees. let names = self.lower_fn_params_to_names(&sig.decl); @@ -851,10 +851,16 @@ impl<'hir> LoweringContext<'_, 'hir> { "only trait methods with default bodies can define opaque types", ); } - (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false) + ( + *ident, + generics, + hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), + false, + ) } AssocItemKind::Fn(box Fn { sig, + ident, generics, body: Some(body), contract, @@ -880,9 +886,16 @@ impl<'hir> LoweringContext<'_, 'hir> { attrs, ); self.lower_define_opaque(hir_id, &define_opaque); - (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true) + ( + *ident, + generics, + hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), + true, + ) } - AssocItemKind::Type(box TyAlias { generics, where_clauses, bounds, ty, .. }) => { + AssocItemKind::Type(box TyAlias { + ident, generics, where_clauses, bounds, ty, .. + }) => { let mut generics = generics.clone(); add_ty_alias_where_clause(&mut generics, *where_clauses, false); let (generics, kind) = self.lower_generics( @@ -905,7 +918,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) }, ); - (generics, kind, ty.is_some()) + (*ident, generics, kind, ty.is_some()) } AssocItemKind::Delegation(box delegation) => { let delegation_results = self.lower_delegation(delegation, i.id, false); @@ -913,7 +926,7 @@ impl<'hir> LoweringContext<'_, 'hir> { delegation_results.sig, hir::TraitFn::Provided(delegation_results.body_id), ); - (delegation_results.generics, item_kind, true) + (delegation.ident, delegation_results.generics, item_kind, true) } AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => { panic!("macros should have been expanded by now") @@ -922,7 +935,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let item = hir::TraitItem { owner_id: trait_item_def_id, - ident: self.lower_ident(i.ident), + ident: self.lower_ident(ident), generics, kind, span: self.lower_span(i.span), @@ -932,15 +945,20 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef { - let kind = match &i.kind { - AssocItemKind::Const(..) => hir::AssocItemKind::Const, - AssocItemKind::Type(..) => hir::AssocItemKind::Type, - AssocItemKind::Fn(box Fn { sig, .. }) => { - hir::AssocItemKind::Fn { has_self: sig.decl.has_self() } + let (ident, kind) = match &i.kind { + AssocItemKind::Const(box ConstItem { ident, .. }) => { + (*ident, hir::AssocItemKind::Const) } - AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn { - has_self: self.delegatee_is_method(i.id, delegation.id, i.span, false), - }, + AssocItemKind::Type(box TyAlias { ident, .. }) => (*ident, hir::AssocItemKind::Type), + AssocItemKind::Fn(box Fn { ident, sig, .. }) => { + (*ident, hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }) + } + AssocItemKind::Delegation(box delegation) => ( + delegation.ident, + hir::AssocItemKind::Fn { + has_self: self.delegatee_is_method(i.id, delegation.id, i.span, false), + }, + ), AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => { panic!("macros should have been expanded by now") } @@ -948,7 +966,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let id = hir::TraitItemId { owner_id: self.owner_id(i.id) }; hir::TraitItemRef { id, - ident: self.lower_ident(i.ident), + ident: self.lower_ident(ident), span: self.lower_span(i.span), kind, } @@ -964,16 +982,23 @@ impl<'hir> LoweringContext<'_, 'hir> { i: &AssocItem, is_in_trait_impl: bool, ) -> &'hir hir::ImplItem<'hir> { - debug_assert_ne!(i.ident.name, kw::Empty); // Since `default impl` is not yet implemented, this is always true in impls. let has_value = true; let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); - let (generics, kind) = match &i.kind { - AssocItemKind::Const(box ConstItem { generics, ty, expr, define_opaque, .. }) => self - .lower_generics( + let (ident, (generics, kind)) = match &i.kind { + AssocItemKind::Const(box ConstItem { + ident, + generics, + ty, + expr, + define_opaque, + .. + }) => ( + *ident, + self.lower_generics( generics, i.id, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), @@ -982,11 +1007,19 @@ impl<'hir> LoweringContext<'_, 'hir> { .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); let body = this.lower_const_body(i.span, expr.as_deref()); this.lower_define_opaque(hir_id, &define_opaque); - hir::ImplItemKind::Const(ty, body) }, ), - AssocItemKind::Fn(box Fn { sig, generics, body, contract, define_opaque, .. }) => { + ), + AssocItemKind::Fn(box Fn { + sig, + ident, + generics, + body, + contract, + define_opaque, + .. + }) => { let body_id = self.lower_maybe_coroutine_body( sig.span, i.span, @@ -1007,44 +1040,50 @@ impl<'hir> LoweringContext<'_, 'hir> { ); self.lower_define_opaque(hir_id, &define_opaque); - (generics, hir::ImplItemKind::Fn(sig, body_id)) + (*ident, (generics, hir::ImplItemKind::Fn(sig, body_id))) } - AssocItemKind::Type(box TyAlias { generics, where_clauses, ty, .. }) => { + AssocItemKind::Type(box TyAlias { ident, generics, where_clauses, ty, .. }) => { let mut generics = generics.clone(); add_ty_alias_where_clause(&mut generics, *where_clauses, false); - self.lower_generics( - &generics, - i.id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), - |this| match ty { - None => { - let guar = this.dcx().span_delayed_bug( - i.span, - "expected to lower associated type, but it was missing", - ); - let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err(guar))); - hir::ImplItemKind::Type(ty) - } - Some(ty) => { - let ty = this.lower_ty( - ty, - ImplTraitContext::OpaqueTy { - origin: hir::OpaqueTyOrigin::TyAlias { - parent: this.local_def_id(i.id), - in_assoc_ty: true, + ( + *ident, + self.lower_generics( + &generics, + i.id, + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + |this| match ty { + None => { + let guar = this.dcx().span_delayed_bug( + i.span, + "expected to lower associated type, but it was missing", + ); + let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err(guar))); + hir::ImplItemKind::Type(ty) + } + Some(ty) => { + let ty = this.lower_ty( + ty, + ImplTraitContext::OpaqueTy { + origin: hir::OpaqueTyOrigin::TyAlias { + parent: this.local_def_id(i.id), + in_assoc_ty: true, + }, }, - }, - ); - hir::ImplItemKind::Type(ty) - } - }, + ); + hir::ImplItemKind::Type(ty) + } + }, + ), ) } AssocItemKind::Delegation(box delegation) => { let delegation_results = self.lower_delegation(delegation, i.id, is_in_trait_impl); ( - delegation_results.generics, - hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id), + delegation.ident, + ( + delegation_results.generics, + hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id), + ), ) } AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => { @@ -1054,7 +1093,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let item = hir::ImplItem { owner_id: hir_id.expect_owner(), - ident: self.lower_ident(i.ident), + ident: self.lower_ident(ident), generics, kind, vis_span: self.lower_span(i.vis.span), @@ -1067,7 +1106,9 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_impl_item_ref(&mut self, i: &AssocItem, is_in_trait_impl: bool) -> hir::ImplItemRef { hir::ImplItemRef { id: hir::ImplItemId { owner_id: self.owner_id(i.id) }, - ident: self.lower_ident(i.ident), + // `unwrap` is safe because `AssocItemKind::{MacCall,DelegationMac}` are the only + // assoc item kinds without an identifier and they cannot reach here. + ident: self.lower_ident(i.kind.ident().unwrap()), span: self.lower_span(i.span), kind: match &i.kind { AssocItemKind::Const(..) => hir::AssocItemKind::Const, diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index da739b0e4532..86661f3f3590 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -607,7 +607,7 @@ impl<'a> AstValidator<'a> { fn deny_items(&self, trait_items: &[P], ident: Span) { if !trait_items.is_empty() { - let spans: Vec<_> = trait_items.iter().map(|i| i.ident.span).collect(); + let spans: Vec<_> = trait_items.iter().map(|i| i.kind.ident().unwrap().span).collect(); let total = trait_items.first().unwrap().span.to(trait_items.last().unwrap().span); self.dcx().emit_err(errors::AutoTraitItems { spans, total, ident }); } @@ -818,7 +818,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } if attr::contains_name(&item.attrs, sym::no_mangle) { - self.check_nomangle_item_asciionly(item.ident, item.span); + if let Some(ident) = item.kind.ident() { + self.check_nomangle_item_asciionly(ident, item.span); + } } match &item.kind { @@ -852,7 +854,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } this.visit_vis(&item.vis); - this.visit_ident(&item.ident); let disallowed = matches!(constness, Const::No) .then(|| TildeConstReason::TraitImpl { span: item.span }); this.with_tilde_const(disallowed, |this| this.visit_generics(generics)); @@ -906,7 +907,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } this.visit_vis(&item.vis); - this.visit_ident(&item.ident); this.with_tilde_const( Some(TildeConstReason::Impl { span: item.span }), |this| this.visit_generics(generics), @@ -918,8 +918,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> { return; // Avoid visiting again. } ItemKind::Fn( - func - @ box Fn { defaultness, generics: _, sig, contract: _, body, define_opaque: _ }, + func @ box Fn { + defaultness, + ident, + generics: _, + sig, + contract: _, + body, + define_opaque: _, + }, ) => { self.check_defaultness(item.span, *defaultness); @@ -949,8 +956,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } self.visit_vis(&item.vis); - self.visit_ident(&item.ident); - let kind = FnKind::Fn(FnCtxt::Free, &item.ident, &item.vis, &*func); + self.visit_ident(ident); + let kind = FnKind::Fn(FnCtxt::Free, &item.vis, &*func); self.visit_fn(kind, item.span, item.id); walk_list!(self, visit_attribute, &item.attrs); return; // Avoid visiting again. @@ -986,7 +993,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { }); return; // Avoid visiting again. } - ItemKind::Enum(def, _) => { + ItemKind::Enum(_, def, _) => { for variant in &def.variants { self.visibility_not_permitted( &variant.vis, @@ -1000,22 +1007,22 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } } - ItemKind::Trait(box Trait { is_auto, generics, bounds, items, .. }) => { + ItemKind::Trait(box Trait { is_auto, generics, ident, bounds, items, .. }) => { let is_const_trait = attr::find_by_name(&item.attrs, sym::const_trait).map(|attr| attr.span); self.with_in_trait(item.span, is_const_trait, |this| { if *is_auto == IsAuto::Yes { // Auto traits cannot have generics, super traits nor contain items. - this.deny_generic_params(generics, item.ident.span); - this.deny_super_traits(bounds, item.ident.span); - this.deny_where_clause(&generics.where_clause, item.ident.span); - this.deny_items(items, item.ident.span); + this.deny_generic_params(generics, ident.span); + this.deny_super_traits(bounds, ident.span); + this.deny_where_clause(&generics.where_clause, ident.span); + this.deny_items(items, ident.span); } // Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound // context for the supertraits. this.visit_vis(&item.vis); - this.visit_ident(&item.ident); + this.visit_ident(ident); let disallowed = is_const_trait .is_none() .then(|| TildeConstReason::Trait { span: item.span }); @@ -1028,7 +1035,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { walk_list!(self, visit_attribute, &item.attrs); return; // Avoid visiting again } - ItemKind::Mod(safety, mod_kind) => { + ItemKind::Mod(safety, ident, mod_kind) => { if let &Safety::Unsafe(span) = safety { self.dcx().emit_err(errors::UnsafeItem { span, kind: "module" }); } @@ -1036,13 +1043,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _, _)) && !attr::contains_name(&item.attrs, sym::path) { - self.check_mod_file_item_asciionly(item.ident); + self.check_mod_file_item_asciionly(*ident); } } - ItemKind::Struct(vdata, generics) => match vdata { + ItemKind::Struct(ident, vdata, generics) => match vdata { VariantData::Struct { fields, .. } => { self.visit_vis(&item.vis); - self.visit_ident(&item.ident); + self.visit_ident(ident); self.visit_generics(generics); // Permit `Anon{Struct,Union}` as field type. walk_list!(self, visit_struct_field_def, fields); @@ -1051,14 +1058,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } _ => {} }, - ItemKind::Union(vdata, generics) => { + ItemKind::Union(ident, vdata, generics) => { if vdata.fields().is_empty() { self.dcx().emit_err(errors::FieldlessUnion { span: item.span }); } match vdata { VariantData::Struct { fields, .. } => { self.visit_vis(&item.vis); - self.visit_ident(&item.ident); + self.visit_ident(ident); self.visit_generics(generics); // Permit `Anon{Struct,Union}` as field type. walk_list!(self, visit_struct_field_def, fields); @@ -1121,14 +1128,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { match &fi.kind { - ForeignItemKind::Fn(box Fn { defaultness, sig, body, .. }) => { + ForeignItemKind::Fn(box Fn { defaultness, ident, sig, body, .. }) => { self.check_defaultness(fi.span, *defaultness); - self.check_foreign_fn_bodyless(fi.ident, body.as_deref()); + self.check_foreign_fn_bodyless(*ident, body.as_deref()); self.check_foreign_fn_headerless(sig.header); - self.check_foreign_item_ascii_only(fi.ident); + self.check_foreign_item_ascii_only(*ident); } ForeignItemKind::TyAlias(box TyAlias { defaultness, + ident, generics, where_clauses, bounds, @@ -1136,15 +1144,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> { .. }) => { self.check_defaultness(fi.span, *defaultness); - self.check_foreign_kind_bodyless(fi.ident, "type", ty.as_ref().map(|b| b.span)); + self.check_foreign_kind_bodyless(*ident, "type", ty.as_ref().map(|b| b.span)); self.check_type_no_bounds(bounds, "`extern` blocks"); self.check_foreign_ty_genericless(generics, where_clauses); - self.check_foreign_item_ascii_only(fi.ident); + self.check_foreign_item_ascii_only(*ident); } - ForeignItemKind::Static(box StaticItem { expr, safety, .. }) => { + ForeignItemKind::Static(box StaticItem { ident, safety, expr, .. }) => { self.check_item_safety(fi.span, *safety); - self.check_foreign_kind_bodyless(fi.ident, "static", expr.as_ref().map(|b| b.span)); - self.check_foreign_item_ascii_only(fi.ident); + self.check_foreign_kind_bodyless(*ident, "static", expr.as_ref().map(|b| b.span)); + self.check_foreign_item_ascii_only(*ident); } ForeignItemKind::MacCall(..) => {} } @@ -1351,7 +1359,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } if let FnKind::Fn( - _, _, _, Fn { @@ -1364,7 +1371,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } // Functions without bodies cannot have patterns. - if let FnKind::Fn(ctxt, _, _, Fn { body: None, sig, .. }) = fk { + if let FnKind::Fn(ctxt, _, Fn { body: None, sig, .. }) = fk { Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| { if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) { if let Some(ident) = ident { @@ -1398,7 +1405,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { .is_some(); let disallowed = (!tilde_const_allowed).then(|| match fk { - FnKind::Fn(_, ident, _, _) => TildeConstReason::Function { ident: ident.span }, + FnKind::Fn(_, _, f) => TildeConstReason::Function { ident: f.ident.span }, FnKind::Closure(..) => TildeConstReason::Closure, }); self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk)); @@ -1406,7 +1413,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) { if attr::contains_name(&item.attrs, sym::no_mangle) { - self.check_nomangle_item_asciionly(item.ident, item.span); + if let Some(ident) = item.kind.ident() { + self.check_nomangle_item_asciionly(ident, item.span); + } } if ctxt == AssocCtxt::Trait || self.outer_trait_or_trait_impl.is_none() { @@ -1466,8 +1475,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } - if let AssocItemKind::Const(..) = item.kind { - self.check_item_named(item.ident, "const"); + if let AssocItemKind::Const(ci) = &item.kind { + self.check_item_named(ci.ident, "const"); } let parent_is_const = @@ -1480,8 +1489,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { || matches!(func.sig.header.constness, Const::Yes(_)) => { self.visit_vis(&item.vis); - self.visit_ident(&item.ident); - let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), &item.ident, &item.vis, &*func); + self.visit_ident(&func.ident); + let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), &item.vis, &*func); walk_list!(self, visit_attribute, &item.attrs); self.visit_fn(kind, item.span, item.id); } diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index a3fcc110a166..2fac881f4c42 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -236,7 +236,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate!(&self, trait_alias, i.span, "trait aliases are experimental"); } - ast::ItemKind::MacroDef(ast::MacroDef { macro_rules: false, .. }) => { + ast::ItemKind::MacroDef(_, ast::MacroDef { macro_rules: false, .. }) => { let msg = "`macro` is experimental"; gate!(&self, decl_macro, i.span, msg); } diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index d406a56c05da..653bd77cc4dd 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -28,23 +28,24 @@ impl<'a> State<'a> { } fn print_foreign_item(&mut self, item: &ast::ForeignItem) { - let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item; + let ast::Item { id, span, ref attrs, ref kind, ref vis, tokens: _ } = *item; self.ann.pre(self, AnnNode::SubItem(id)); self.hardbreak_if_not_bol(); self.maybe_print_comment(span.lo()); self.print_outer_attributes(attrs); match kind { ast::ForeignItemKind::Fn(func) => { - self.print_fn_full(ident, vis, attrs, &*func); + self.print_fn_full(vis, attrs, &*func); } ast::ForeignItemKind::Static(box ast::StaticItem { + ident, ty, mutability, expr, safety, define_opaque, }) => self.print_item_const( - ident, + *ident, Some(*mutability), &ast::Generics::default(), ty, @@ -56,13 +57,14 @@ impl<'a> State<'a> { ), ast::ForeignItemKind::TyAlias(box ast::TyAlias { defaultness, + ident, generics, where_clauses, bounds, ty, }) => { self.print_associated_type( - ident, + *ident, generics, *where_clauses, bounds, @@ -162,7 +164,7 @@ impl<'a> State<'a> { self.print_outer_attributes(&item.attrs); self.ann.pre(self, AnnNode::Item(item)); match &item.kind { - ast::ItemKind::ExternCrate(orig_name) => { + ast::ItemKind::ExternCrate(orig_name, ident) => { self.head(visibility_qualified(&item.vis, "extern crate")); if let &Some(orig_name) = orig_name { self.print_name(orig_name); @@ -170,7 +172,7 @@ impl<'a> State<'a> { self.word("as"); self.space(); } - self.print_ident(item.ident); + self.print_ident(*ident); self.word(";"); self.end(); // end inner head-block self.end(); // end outer head-block @@ -182,6 +184,7 @@ impl<'a> State<'a> { self.word(";"); } ast::ItemKind::Static(box StaticItem { + ident, ty, safety, mutability: mutbl, @@ -190,7 +193,7 @@ impl<'a> State<'a> { }) => { self.print_safety(*safety); self.print_item_const( - item.ident, + *ident, Some(*mutbl), &ast::Generics::default(), ty, @@ -203,13 +206,14 @@ impl<'a> State<'a> { } ast::ItemKind::Const(box ast::ConstItem { defaultness, + ident, generics, ty, expr, define_opaque, }) => { self.print_item_const( - item.ident, + *ident, None, generics, ty, @@ -221,15 +225,15 @@ impl<'a> State<'a> { ); } ast::ItemKind::Fn(func) => { - self.print_fn_full(item.ident, &item.vis, &item.attrs, &*func); + self.print_fn_full(&item.vis, &item.attrs, &*func); } - ast::ItemKind::Mod(safety, mod_kind) => { + ast::ItemKind::Mod(safety, ident, mod_kind) => { self.head(Self::to_string(|s| { s.print_visibility(&item.vis); s.print_safety(*safety); s.word("mod"); })); - self.print_ident(item.ident); + self.print_ident(*ident); match mod_kind { ModKind::Loaded(items, ..) => { @@ -273,13 +277,14 @@ impl<'a> State<'a> { } ast::ItemKind::TyAlias(box ast::TyAlias { defaultness, + ident, generics, where_clauses, bounds, ty, }) => { self.print_associated_type( - item.ident, + *ident, generics, *where_clauses, bounds, @@ -288,16 +293,16 @@ impl<'a> State<'a> { *defaultness, ); } - ast::ItemKind::Enum(enum_definition, params) => { - self.print_enum_def(enum_definition, params, item.ident, item.span, &item.vis); + ast::ItemKind::Enum(ident, enum_definition, params) => { + self.print_enum_def(enum_definition, params, *ident, item.span, &item.vis); } - ast::ItemKind::Struct(struct_def, generics) => { + ast::ItemKind::Struct(ident, struct_def, generics) => { self.head(visibility_qualified(&item.vis, "struct")); - self.print_struct(struct_def, generics, item.ident, item.span, true); + self.print_struct(struct_def, generics, *ident, item.span, true); } - ast::ItemKind::Union(struct_def, generics) => { + ast::ItemKind::Union(ident, struct_def, generics) => { self.head(visibility_qualified(&item.vis, "union")); - self.print_struct(struct_def, generics, item.ident, item.span, true); + self.print_struct(struct_def, generics, *ident, item.span, true); } ast::ItemKind::Impl(box ast::Impl { safety, @@ -347,19 +352,19 @@ impl<'a> State<'a> { self.bclose(item.span, empty); } ast::ItemKind::Trait(box ast::Trait { - is_auto, safety, + is_auto, + ident, generics, bounds, items, - .. }) => { self.head(""); self.print_visibility(&item.vis); self.print_safety(*safety); self.print_is_auto(*is_auto); self.word_nbsp("trait"); - self.print_ident(item.ident); + self.print_ident(*ident); self.print_generic_params(&generics.params); if !bounds.is_empty() { self.word_nbsp(":"); @@ -375,9 +380,9 @@ impl<'a> State<'a> { let empty = item.attrs.is_empty() && items.is_empty(); self.bclose(item.span, empty); } - ast::ItemKind::TraitAlias(generics, bounds) => { + ast::ItemKind::TraitAlias(ident, generics, bounds) => { self.head(visibility_qualified(&item.vis, "trait")); - self.print_ident(item.ident); + self.print_ident(*ident); self.print_generic_params(&generics.params); self.nbsp(); if !bounds.is_empty() { @@ -395,8 +400,8 @@ impl<'a> State<'a> { self.word(";"); } } - ast::ItemKind::MacroDef(macro_def) => { - self.print_mac_def(macro_def, &item.ident, item.span, |state| { + ast::ItemKind::MacroDef(ident, macro_def) => { + self.print_mac_def(macro_def, &ident, item.span, |state| { state.print_visibility(&item.vis) }); } @@ -549,24 +554,25 @@ impl<'a> State<'a> { } fn print_assoc_item(&mut self, item: &ast::AssocItem) { - let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item; + let ast::Item { id, span, ref attrs, ref kind, ref vis, tokens: _ } = *item; self.ann.pre(self, AnnNode::SubItem(id)); self.hardbreak_if_not_bol(); self.maybe_print_comment(span.lo()); self.print_outer_attributes(attrs); match kind { ast::AssocItemKind::Fn(func) => { - self.print_fn_full(ident, vis, attrs, &*func); + self.print_fn_full(vis, attrs, &*func); } ast::AssocItemKind::Const(box ast::ConstItem { defaultness, + ident, generics, ty, expr, define_opaque, }) => { self.print_item_const( - ident, + *ident, None, generics, ty, @@ -579,13 +585,14 @@ impl<'a> State<'a> { } ast::AssocItemKind::Type(box ast::TyAlias { defaultness, + ident, generics, where_clauses, bounds, ty, }) => { self.print_associated_type( - ident, + *ident, generics, *where_clauses, bounds, @@ -671,14 +678,8 @@ impl<'a> State<'a> { } } - fn print_fn_full( - &mut self, - name: Ident, - vis: &ast::Visibility, - attrs: &[ast::Attribute], - func: &ast::Fn, - ) { - let ast::Fn { defaultness, generics, sig, contract, body, define_opaque } = func; + fn print_fn_full(&mut self, vis: &ast::Visibility, attrs: &[ast::Attribute], func: &ast::Fn) { + let ast::Fn { defaultness, ident, generics, sig, contract, body, define_opaque } = func; self.print_define_opaques(define_opaque.as_deref()); @@ -687,7 +688,7 @@ impl<'a> State<'a> { } self.print_visibility(vis); self.print_defaultness(*defaultness); - self.print_fn(&sig.decl, sig.header, Some(name), generics); + self.print_fn(&sig.decl, sig.header, Some(*ident), generics); if let Some(contract) = &contract { self.nbsp(); self.print_contract(contract); @@ -734,13 +735,13 @@ impl<'a> State<'a> { &mut self, decl: &ast::FnDecl, header: ast::FnHeader, - name: Option, + ident: Option, generics: &ast::Generics, ) { self.print_fn_header_info(header); - if let Some(name) = name { + if let Some(ident) = ident { self.nbsp(); - self.print_ident(name); + self.print_ident(ident); } self.print_generic_params(&generics.params); self.print_fn_params_and_ret(decl, false); diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs index 1c1b2c88f76e..ea406e706660 100644 --- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs +++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs @@ -21,15 +21,15 @@ pub(crate) fn expand( // Allow using `#[alloc_error_handler]` on an item statement // FIXME - if we get deref patterns, use them to reduce duplication here - let (item, is_stmt, sig_span) = if let Annotatable::Item(item) = &item + let (item, ident, is_stmt, sig_span) = if let Annotatable::Item(item) = &item && let ItemKind::Fn(fn_kind) = &item.kind { - (item, false, ecx.with_def_site_ctxt(fn_kind.sig.span)) + (item, fn_kind.ident, false, ecx.with_def_site_ctxt(fn_kind.sig.span)) } else if let Annotatable::Stmt(stmt) = &item && let StmtKind::Item(item) = &stmt.kind && let ItemKind::Fn(fn_kind) = &item.kind { - (item, true, ecx.with_def_site_ctxt(fn_kind.sig.span)) + (item, fn_kind.ident, true, ecx.with_def_site_ctxt(fn_kind.sig.span)) } else { ecx.dcx().emit_err(errors::AllocErrorMustBeFn { span: item.span() }); return vec![orig_item]; @@ -39,7 +39,7 @@ pub(crate) fn expand( let span = ecx.with_def_site_ctxt(item.span); // Generate item statements for the allocator methods. - let stmts = thin_vec![generate_handler(ecx, item.ident, span, sig_span)]; + let stmts = thin_vec![generate_handler(ecx, ident, span, sig_span)]; // Generate anonymous constant serving as container for the allocator methods. let const_ty = ecx.ty(sig_span, TyKind::Tup(ThinVec::new())); @@ -85,6 +85,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span let kind = ItemKind::Fn(Box::new(Fn { defaultness: ast::Defaultness::Final, sig, + ident: Ident::from_str_and_span("__rg_oom", span), generics: Generics::default(), contract: None, body, @@ -93,6 +94,6 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span let attrs = thin_vec![cx.attr_word(sym::rustc_std_internal_symbol, span)]; - let item = cx.item(span, Ident::from_str_and_span("__rg_oom", span), attrs, kind); + let item = cx.item(span, attrs, kind); cx.stmt_item(sig_span, item) } diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index eb5b345e49ec..3e8ddb8abd43 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -10,7 +10,7 @@ use rustc_index::bit_set::GrowableBitSet; use rustc_parse::exp; use rustc_parse::parser::{ExpKeywordPair, Parser}; use rustc_session::lint; -use rustc_span::{ErrorGuaranteed, Ident, InnerSpan, Span, Symbol, kw}; +use rustc_span::{ErrorGuaranteed, InnerSpan, Span, Symbol, kw}; use rustc_target::asm::InlineAsmArch; use smallvec::smallvec; use {rustc_ast as ast, rustc_parse_format as parse}; @@ -888,7 +888,6 @@ pub(super) fn expand_global_asm<'cx>( }; match mac { Ok(inline_asm) => MacEager::items(smallvec![P(ast::Item { - ident: Ident::empty(), attrs: ast::AttrVec::new(), id: ast::DUMMY_NODE_ID, kind: ast::ItemKind::GlobalAsm(Box::new(inline_asm)), diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index a949ab94f3ad..ea7248ca5393 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -112,7 +112,6 @@ impl<'cx, 'a> Context<'cx, 'a> { self.span, self.cx.item( self.span, - Ident::empty(), thin_vec![self.cx.attr_nested_word(sym::allow, sym::unused_imports, self.span)], ItemKind::Use(UseTree { prefix: self.cx.path(self.span, self.cx.std_path(&[sym::asserting])), diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index be11711757e4..8937d35d53ae 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -146,26 +146,26 @@ mod llvm_enzyme { } let dcx = ecx.sess.dcx(); // first get the annotable item: - let (sig, is_impl): (FnSig, bool) = match &item { + let (primal, sig, is_impl): (Ident, FnSig, bool) = match &item { Annotatable::Item(iitem) => { - let sig = match &iitem.kind { - ItemKind::Fn(box ast::Fn { sig, .. }) => sig, + let (ident, sig) = match &iitem.kind { + ItemKind::Fn(box ast::Fn { ident, sig, .. }) => (ident, sig), _ => { dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); return vec![item]; } }; - (sig.clone(), false) + (*ident, sig.clone(), false) } Annotatable::AssocItem(assoc_item, Impl { of_trait: false }) => { - let sig = match &assoc_item.kind { - ast::AssocItemKind::Fn(box ast::Fn { sig, .. }) => sig, + let (ident, sig) = match &assoc_item.kind { + ast::AssocItemKind::Fn(box ast::Fn { ident, sig, .. }) => (ident, sig), _ => { dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); return vec![item]; } }; - (sig.clone(), true) + (*ident, sig.clone(), true) } _ => { dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); @@ -184,11 +184,9 @@ mod llvm_enzyme { let has_ret = has_ret(&sig.decl.output); let sig_span = ecx.with_call_site_ctxt(sig.span); - let (vis, primal) = match &item { - Annotatable::Item(iitem) => (iitem.vis.clone(), iitem.ident.clone()), - Annotatable::AssocItem(assoc_item, _) => { - (assoc_item.vis.clone(), assoc_item.ident.clone()) - } + let vis = match &item { + Annotatable::Item(iitem) => iitem.vis.clone(), + Annotatable::AssocItem(assoc_item, _) => assoc_item.vis.clone(), _ => { dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); return vec![item]; @@ -237,12 +235,12 @@ mod llvm_enzyme { let d_body = gen_enzyme_body( ecx, &x, n_active, &sig, &d_sig, primal, &new_args, span, sig_span, idents, errored, ); - let d_ident = first_ident(&meta_item_vec[0]); // The first element of it is the name of the function to be generated let asdf = Box::new(ast::Fn { defaultness: ast::Defaultness::Final, sig: d_sig, + ident: first_ident(&meta_item_vec[0]), generics: Generics::default(), contract: None, body: Some(d_body), @@ -323,14 +321,12 @@ mod llvm_enzyme { id: ast::DUMMY_NODE_ID, span, vis, - ident: d_ident, kind: assoc_item, tokens: None, }); Annotatable::AssocItem(d_fn, Impl { of_trait: false }) } else { - let mut d_fn = - ecx.item(span, d_ident, thin_vec![d_attr, inline_never], ItemKind::Fn(asdf)); + let mut d_fn = ecx.item(span, thin_vec![d_attr, inline_never], ItemKind::Fn(asdf)); d_fn.vis = vis; Annotatable::Item(d_fn) }; diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index c3656e8244fe..44cf215c6622 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -34,8 +34,8 @@ pub(crate) fn expand_deriving_clone( let is_simple; match item { Annotatable::Item(annitem) => match &annitem.kind { - ItemKind::Struct(_, Generics { params, .. }) - | ItemKind::Enum(_, Generics { params, .. }) => { + ItemKind::Struct(_, _, Generics { params, .. }) + | ItemKind::Enum(_, _, Generics { params, .. }) => { let container_id = cx.current_expansion.id.expn_data().parent.expect_local(); let has_derive_copy = cx.resolver.has_derive_copy(container_id); if has_derive_copy diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs index 7958e037555d..aa01da3151eb 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -21,7 +21,7 @@ pub(crate) fn expand_deriving_partial_ord( // Order in which to perform matching let discr_then_data = if let Annotatable::Item(item) = item - && let ItemKind::Enum(def, _) = &item.kind + && let ItemKind::Enum(_, def, _) = &item.kind { let dataful: Vec = def.variants.iter().map(|v| !v.data.fields().is_empty()).collect(); match dataful.iter().filter(|&&b| b).count() { diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs index 46b79e097808..446d8afeedd7 100644 --- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs +++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs @@ -30,7 +30,7 @@ pub(crate) fn expand_deriving_coerce_pointee( item.visit_with(&mut DetectNonGenericPointeeAttr { cx }); let (name_ident, generics) = if let Annotatable::Item(aitem) = item - && let ItemKind::Struct(struct_data, g) = &aitem.kind + && let ItemKind::Struct(ident, struct_data, g) = &aitem.kind { if !matches!( struct_data, @@ -40,7 +40,7 @@ pub(crate) fn expand_deriving_coerce_pointee( cx.dcx().emit_err(RequireOneField { span }); return; } - (aitem.ident, g) + (*ident, g) } else { cx.dcx().emit_err(RequireTransparent { span }); return; @@ -108,7 +108,6 @@ pub(crate) fn expand_deriving_coerce_pointee( push(Annotatable::Item( cx.item( span, - Ident::empty(), attrs.clone(), ast::ItemKind::Impl(Box::new(ast::Impl { safety: ast::Safety::Default, @@ -153,7 +152,6 @@ pub(crate) fn expand_deriving_coerce_pointee( let trait_ref = cx.trait_ref(trait_path); let item = cx.item( span, - Ident::empty(), attrs.clone(), ast::ItemKind::Impl(Box::new(ast::Impl { safety: ast::Safety::Default, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 03ee59de70e1..b9197be44426 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -487,28 +487,28 @@ impl<'a> TraitDef<'a> { ); let newitem = match &item.kind { - ast::ItemKind::Struct(struct_def, generics) => self.expand_struct_def( + ast::ItemKind::Struct(ident, struct_def, generics) => self.expand_struct_def( cx, struct_def, - item.ident, + *ident, generics, from_scratch, is_packed, ), - ast::ItemKind::Enum(enum_def, generics) => { + ast::ItemKind::Enum(ident, enum_def, generics) => { // We ignore `is_packed` here, because `repr(packed)` // enums cause an error later on. // // This can only cause further compilation errors // downstream in blatantly illegal code, so it is fine. - self.expand_enum_def(cx, enum_def, item.ident, generics, from_scratch) + self.expand_enum_def(cx, enum_def, *ident, generics, from_scratch) } - ast::ItemKind::Union(struct_def, generics) => { + ast::ItemKind::Union(ident, struct_def, generics) => { if self.supports_unions { self.expand_struct_def( cx, struct_def, - item.ident, + *ident, generics, from_scratch, is_packed, @@ -596,7 +596,6 @@ impl<'a> TraitDef<'a> { P(ast::AssocItem { id: ast::DUMMY_NODE_ID, span: self.span, - ident, vis: ast::Visibility { span: self.span.shrink_to_lo(), kind: ast::VisibilityKind::Inherited, @@ -605,6 +604,7 @@ impl<'a> TraitDef<'a> { attrs: ast::AttrVec::new(), kind: ast::AssocItemKind::Type(Box::new(ast::TyAlias { defaultness: ast::Defaultness::Final, + ident, generics: Generics::default(), where_clauses: ast::TyAliasWhereClauses::default(), bounds: Vec::new(), @@ -789,7 +789,6 @@ impl<'a> TraitDef<'a> { cx.item( self.span, - Ident::empty(), attrs, ast::ItemKind::Impl(Box::new(ast::Impl { safety: ast::Safety::Default, @@ -1033,10 +1032,10 @@ impl<'a> MethodDef<'a> { kind: ast::VisibilityKind::Inherited, tokens: None, }, - ident: method_ident, kind: ast::AssocItemKind::Fn(Box::new(ast::Fn { defaultness, sig, + ident: method_ident, generics: fn_generics, contract: None, body: Some(body_block), diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index 90d79235820f..4b1958bce322 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -25,15 +25,15 @@ pub(crate) fn expand( // Allow using `#[global_allocator]` on an item statement // FIXME - if we get deref patterns, use them to reduce duplication here - let (item, is_stmt, ty_span) = if let Annotatable::Item(item) = &item - && let ItemKind::Static(box ast::StaticItem { ty, .. }) = &item.kind + let (item, ident, is_stmt, ty_span) = if let Annotatable::Item(item) = &item + && let ItemKind::Static(box ast::StaticItem { ident, ty, .. }) = &item.kind { - (item, false, ecx.with_def_site_ctxt(ty.span)) + (item, *ident, false, ecx.with_def_site_ctxt(ty.span)) } else if let Annotatable::Stmt(stmt) = &item && let StmtKind::Item(item) = &stmt.kind - && let ItemKind::Static(box ast::StaticItem { ty, .. }) = &item.kind + && let ItemKind::Static(box ast::StaticItem { ident, ty, .. }) = &item.kind { - (item, true, ecx.with_def_site_ctxt(ty.span)) + (item, *ident, true, ecx.with_def_site_ctxt(ty.span)) } else { ecx.dcx().emit_err(errors::AllocMustStatics { span: item.span() }); return vec![orig_item]; @@ -41,7 +41,7 @@ pub(crate) fn expand( // Generate a bunch of new items using the AllocFnFactory let span = ecx.with_def_site_ctxt(item.span); - let f = AllocFnFactory { span, ty_span, global: item.ident, cx: ecx }; + let f = AllocFnFactory { span, ty_span, global: ident, cx: ecx }; // Generate item statements for the allocator methods. let stmts = ALLOCATOR_METHODS.iter().map(|method| f.allocator_fn(method)).collect(); @@ -80,17 +80,13 @@ impl AllocFnFactory<'_, '_> { let kind = ItemKind::Fn(Box::new(Fn { defaultness: ast::Defaultness::Final, sig, + ident: Ident::from_str_and_span(&global_fn_name(method.name), self.span), generics: Generics::default(), contract: None, body, define_opaque: None, })); - let item = self.cx.item( - self.span, - Ident::from_str_and_span(&global_fn_name(method.name), self.span), - self.attrs(), - kind, - ); + let item = self.cx.item(self.span, self.attrs(), kind); self.cx.stmt_item(self.ty_span, item) } diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index ee6475c8b8e9..7c25f26895ca 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -92,7 +92,12 @@ impl<'a> CollectProcMacros<'a> { } } - fn collect_custom_derive(&mut self, item: &'a ast::Item, attr: &'a ast::Attribute) { + fn collect_custom_derive( + &mut self, + item: &'a ast::Item, + function_name: Ident, + attr: &'a ast::Attribute, + ) { let Some((trait_name, proc_attrs)) = parse_macro_name_and_helper_attrs(self.dcx, attr, "derive") else { @@ -104,7 +109,7 @@ impl<'a> CollectProcMacros<'a> { id: item.id, span: item.span, trait_name, - function_name: item.ident, + function_name, attrs: proc_attrs, })); } else { @@ -118,12 +123,12 @@ impl<'a> CollectProcMacros<'a> { } } - fn collect_attr_proc_macro(&mut self, item: &'a ast::Item) { + fn collect_attr_proc_macro(&mut self, item: &'a ast::Item, function_name: Ident) { if self.in_root && item.vis.kind.is_pub() { self.macros.push(ProcMacro::Attr(ProcMacroDef { id: item.id, span: item.span, - function_name: item.ident, + function_name, })); } else { let msg = if !self.in_root { @@ -136,12 +141,12 @@ impl<'a> CollectProcMacros<'a> { } } - fn collect_bang_proc_macro(&mut self, item: &'a ast::Item) { + fn collect_bang_proc_macro(&mut self, item: &'a ast::Item, function_name: Ident) { if self.in_root && item.vis.kind.is_pub() { self.macros.push(ProcMacro::Bang(ProcMacroDef { id: item.id, span: item.span, - function_name: item.ident, + function_name, })); } else { let msg = if !self.in_root { @@ -165,12 +170,6 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { } } - // First up, make sure we're checking a bare function. If we're not then - // we're just not interested in this item. - // - // If we find one, try to locate a `#[proc_macro_derive]` attribute on it. - let is_fn = matches!(item.kind, ast::ItemKind::Fn(..)); - let mut found_attr: Option<&'a ast::Attribute> = None; for attr in &item.attrs { @@ -214,7 +213,13 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { return; }; - if !is_fn { + // First up, make sure we're checking a bare function. If we're not then + // we're just not interested in this item. + // + // If we find one, try to locate a `#[proc_macro_derive]` attribute on it. + let fn_ident = if let ast::ItemKind::Fn(fn_) = &item.kind { + fn_.ident + } else { self.dcx .create_err(errors::AttributeOnlyBeUsedOnBareFunctions { span: attr.span, @@ -222,7 +227,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { }) .emit(); return; - } + }; if self.is_test_crate { return; @@ -239,11 +244,11 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { } if attr.has_name(sym::proc_macro_derive) { - self.collect_custom_derive(item, attr); + self.collect_custom_derive(item, fn_ident, attr); } else if attr.has_name(sym::proc_macro_attribute) { - self.collect_attr_proc_macro(item); + self.collect_attr_proc_macro(item, fn_ident); } else if attr.has_name(sym::proc_macro) { - self.collect_bang_proc_macro(item); + self.collect_bang_proc_macro(item, fn_ident); }; let prev_in_root = mem::replace(&mut self.in_root, false); @@ -278,7 +283,7 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P { let span = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id()); let proc_macro = Ident::new(sym::proc_macro, span); - let krate = cx.item(span, proc_macro, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None)); + let krate = cx.item(span, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None, proc_macro)); let bridge = Ident::new(sym::bridge, span); let client = Ident::new(sym::client, span); diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs index ba63b185e096..a1ee53b7ca21 100644 --- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs +++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs @@ -43,9 +43,8 @@ pub fn inject( let item = cx.item( span, - Ident::new(name, ident_span), thin_vec![cx.attr_word(sym::macro_use, span)], - ast::ItemKind::ExternCrate(None), + ast::ItemKind::ExternCrate(None, Ident::new(name, ident_span)), ); krate.items.insert(0, item); @@ -68,7 +67,6 @@ pub fn inject( // Inject the relevant crate's prelude. let use_item = cx.item( span, - Ident::empty(), thin_vec![cx.attr_word(sym::prelude_import, span)], ast::ItemKind::Use(ast::UseTree { prefix: cx.path(span, import_path), diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index db3e431495bf..1cef4f9514cd 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -55,12 +55,14 @@ pub(crate) fn expand_test_case( // `#[test_case]` is valid on functions, consts, and statics. Only modify // the item in those cases. match &mut item.kind { - ast::ItemKind::Fn(_) | ast::ItemKind::Const(_) | ast::ItemKind::Static(_) => { - item.ident.span = item.ident.span.with_ctxt(sp.ctxt()); + ast::ItemKind::Fn(box ast::Fn { ident, .. }) + | ast::ItemKind::Const(box ast::ConstItem { ident, .. }) + | ast::ItemKind::Static(box ast::StaticItem { ident, .. }) => { + ident.span = ident.span.with_ctxt(sp.ctxt()); let test_path_symbol = Symbol::intern(&item_path( // skip the name of the root module &ecx.current_expansion.module.mod_path[1..], - &item.ident, + ident, )); item.vis = ast::Visibility { span: item.vis.span, @@ -228,7 +230,7 @@ pub(crate) fn expand_test_or_bench( // super::$test_fn(b) cx.expr_call( ret_ty_sp, - cx.expr_path(cx.path(sp, vec![item.ident])), + cx.expr_path(cx.path(sp, vec![fn_.ident])), thin_vec![cx.expr_ident(sp, b)], ), ], @@ -254,7 +256,7 @@ pub(crate) fn expand_test_or_bench( // $test_fn() cx.expr_call( ret_ty_sp, - cx.expr_path(cx.path(sp, vec![item.ident])), + cx.expr_path(cx.path(sp, vec![fn_.ident])), ThinVec::new(), ), // ) ], @@ -267,15 +269,14 @@ pub(crate) fn expand_test_or_bench( let test_path_symbol = Symbol::intern(&item_path( // skip the name of the root module &cx.current_expansion.module.mod_path[1..], - &item.ident, + &fn_.ident, )); - let location_info = get_location_info(cx, &item); + let location_info = get_location_info(cx, &fn_); let mut test_const = cx.item( sp, - Ident::new(item.ident.name, sp), thin_vec![ // #[cfg(test)] cx.attr_nested_word(sym::cfg, sym::test, attr_sp), @@ -288,6 +289,7 @@ pub(crate) fn expand_test_or_bench( ast::ItemKind::Const( ast::ConstItem { defaultness: ast::Defaultness::Final, + ident: Ident::new(fn_.ident.name, sp), generics: ast::Generics::default(), ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))), define_opaque: None, @@ -386,7 +388,7 @@ pub(crate) fn expand_test_or_bench( // extern crate test let test_extern = - cx.item(sp, test_ident, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None)); + cx.item(sp, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None, test_ident)); debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const)); @@ -440,8 +442,8 @@ fn not_testable_error(cx: &ExtCtxt<'_>, attr_sp: Span, item: Option<&ast::Item>) .emit(); } -fn get_location_info(cx: &ExtCtxt<'_>, item: &ast::Item) -> (Symbol, usize, usize, usize, usize) { - let span = item.ident.span; +fn get_location_info(cx: &ExtCtxt<'_>, fn_: &ast::Fn) -> (Symbol, usize, usize, usize, usize) { + let span = fn_.ident.span; let (source_file, lo_line, lo_col, hi_line, hi_col) = cx.sess.source_map().span_to_location_info(span); diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 768b459ec5e3..56a67b0534d9 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -134,27 +134,21 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { if let Some(name) = get_test_name(&item) { debug!("this is a test item"); - let test = Test { span: item.span, ident: item.ident, name }; + // `unwrap` is ok because only functions, consts, and static should reach here. + let test = Test { span: item.span, ident: item.kind.ident().unwrap(), name }; self.tests.push(test); } // We don't want to recurse into anything other than mods, since // mods or tests inside of functions will break things if let ast::ItemKind::Mod( + _, _, ModKind::Loaded(.., ast::ModSpans { inner_span: span, .. }, _), ) = item.kind { let prev_tests = mem::take(&mut self.tests); - walk_item_kind( - &mut item.kind, - item.span, - item.id, - &mut item.ident, - &mut item.vis, - (), - self, - ); + walk_item_kind(&mut item.kind, item.span, item.id, &mut item.vis, (), self); self.add_test_cases(item.id, span, prev_tests); } else { // But in those cases, we emit a lint to warn the user of these missing tests. @@ -181,9 +175,9 @@ impl<'a> Visitor<'a> for InnerItemLinter<'_> { } fn entry_point_type(item: &ast::Item, at_root: bool) -> EntryPointType { - match item.kind { - ast::ItemKind::Fn(..) => { - rustc_ast::entry::entry_point_type(&item.attrs, at_root, Some(item.ident.name)) + match &item.kind { + ast::ItemKind::Fn(fn_) => { + rustc_ast::entry::entry_point_type(&item.attrs, at_root, Some(fn_.ident.name)) } _ => EntryPointType::None, } @@ -295,7 +289,7 @@ fn generate_test_harness( fn mk_main(cx: &mut TestCtxt<'_>) -> P { let sp = cx.def_site; let ecx = &cx.ext_cx; - let test_id = Ident::new(sym::test, sp); + let test_ident = Ident::new(sym::test, sp); let runner_name = match cx.panic_strategy { PanicStrategy::Unwind => "test_main_static", @@ -303,10 +297,9 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { }; // test::test_main_static(...) - let mut test_runner = cx - .test_runner - .clone() - .unwrap_or_else(|| ecx.path(sp, vec![test_id, Ident::from_str_and_span(runner_name, sp)])); + let mut test_runner = cx.test_runner.clone().unwrap_or_else(|| { + ecx.path(sp, vec![test_ident, Ident::from_str_and_span(runner_name, sp)]) + }); test_runner.span = sp; @@ -317,7 +310,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { // extern crate test let test_extern_stmt = ecx.stmt_item( sp, - ecx.item(sp, test_id, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None)), + ecx.item(sp, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None, test_ident)), ); // #[rustc_main] @@ -340,23 +333,24 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { let decl = ecx.fn_decl(ThinVec::new(), ast::FnRetTy::Ty(main_ret_ty)); let sig = ast::FnSig { decl, header: ast::FnHeader::default(), span: sp }; let defaultness = ast::Defaultness::Final; + + // Honor the reexport_test_harness_main attribute + let main_ident = match cx.reexport_test_harness_main { + Some(sym) => Ident::new(sym, sp.with_ctxt(SyntaxContext::root())), + None => Ident::new(sym::main, sp), + }; + let main = ast::ItemKind::Fn(Box::new(ast::Fn { defaultness, sig, + ident: main_ident, generics: ast::Generics::default(), contract: None, body: Some(main_body), define_opaque: None, })); - // Honor the reexport_test_harness_main attribute - let main_id = match cx.reexport_test_harness_main { - Some(sym) => Ident::new(sym, sp.with_ctxt(SyntaxContext::root())), - None => Ident::new(sym::main, sp), - }; - let main = P(ast::Item { - ident: main_id, attrs: thin_vec![main_attr, coverage_attr, doc_hidden_attr], id: ast::DUMMY_NODE_ID, kind: main, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 990d0f2e028a..d14e476ba322 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1424,12 +1424,11 @@ pub fn parse_macro_name_and_helper_attrs( /// See #73345 and #83125 for more details. /// FIXME(#73933): Remove this eventually. fn pretty_printing_compatibility_hack(item: &Item, psess: &ParseSess) { - let name = item.ident.name; - if name == sym::ProceduralMasqueradeDummyType - && let ast::ItemKind::Enum(enum_def, _) = &item.kind + if let ast::ItemKind::Enum(ident, enum_def, _) = &item.kind + && ident.name == sym::ProceduralMasqueradeDummyType && let [variant] = &*enum_def.variants && variant.ident.name == sym::Input - && let FileName::Real(real) = psess.source_map().span_to_filename(item.ident.span) + && let FileName::Real(real) = psess.source_map().span_to_filename(ident.span) && let Some(c) = real .local_path() .unwrap_or(Path::new("")) diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 89a750bb39f0..f68172c1f67c 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -662,15 +662,8 @@ impl<'a> ExtCtxt<'a> { P(ast::FnDecl { inputs, output }) } - pub fn item( - &self, - span: Span, - name: Ident, - attrs: ast::AttrVec, - kind: ast::ItemKind, - ) -> P { + pub fn item(&self, span: Span, attrs: ast::AttrVec, kind: ast::ItemKind) -> P { P(ast::Item { - ident: name, attrs, id: ast::DUMMY_NODE_ID, kind, @@ -687,17 +680,17 @@ impl<'a> ExtCtxt<'a> { pub fn item_static( &self, span: Span, - name: Ident, + ident: Ident, ty: P, mutability: ast::Mutability, expr: P, ) -> P { self.item( span, - name, AttrVec::new(), ast::ItemKind::Static( ast::StaticItem { + ident, ty, safety: ast::Safety::Default, mutability, @@ -712,18 +705,18 @@ impl<'a> ExtCtxt<'a> { pub fn item_const( &self, span: Span, - name: Ident, + ident: Ident, ty: P, expr: P, ) -> P { let defaultness = ast::Defaultness::Final; self.item( span, - name, AttrVec::new(), ast::ItemKind::Const( ast::ConstItem { defaultness, + ident, // FIXME(generic_const_items): Pass the generics as a parameter. generics: ast::Generics::default(), ty, diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 22da1179feb9..d1dd454fa73d 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -743,6 +743,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { && matches!( item_inner.kind, ItemKind::Mod( + _, _, ModKind::Unloaded | ModKind::Loaded(_, Inline::No, _, _), ) @@ -911,7 +912,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> { fn visit_item(&mut self, item: &'ast ast::Item) { match &item.kind { - ItemKind::Mod(_, mod_kind) + ItemKind::Mod(_, _, mod_kind) if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _, _)) => { feature_err( @@ -1221,8 +1222,9 @@ impl InvocationCollectorNode for P { } // Work around borrow checker not seeing through `P`'s deref. - let (ident, span, mut attrs) = (node.ident, node.span, mem::take(&mut node.attrs)); - let ItemKind::Mod(_, mod_kind) = &mut node.kind else { unreachable!() }; + let (span, mut attrs) = (node.span, mem::take(&mut node.attrs)); + let ItemKind::Mod(_, ident, mod_kind) = &mut node.kind else { unreachable!() }; + let ident = *ident; let ecx = &mut collector.cx; let (file_path, dir_path, dir_ownership) = match mod_kind { @@ -1305,6 +1307,7 @@ impl InvocationCollectorNode for P { collector.cx.current_expansion.module = orig_module; res } + fn declared_names(&self) -> Vec { if let ItemKind::Use(ut) = &self.kind { fn collect_use_tree_leaves(ut: &ast::UseTree, idents: &mut Vec) { @@ -1324,7 +1327,7 @@ impl InvocationCollectorNode for P { return idents; } - vec![self.ident] + if let Some(ident) = self.kind.ident() { vec![ident] } else { vec![] } } } @@ -1844,11 +1847,11 @@ fn build_single_delegations<'a, Node: InvocationCollectorNode>( id: ast::DUMMY_NODE_ID, span: if from_glob { item_span } else { ident.span }, vis: item.vis.clone(), - ident: rename.unwrap_or(ident), kind: Node::delegation_item_kind(Box::new(ast::Delegation { id: ast::DUMMY_NODE_ID, qself: deleg.qself.clone(), path, + ident: rename.unwrap_or(ident), rename, body: deleg.body.clone(), from_glob, diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index a60a87244cc6..0136292decbc 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -26,7 +26,7 @@ pub(crate) fn placeholder( }) } - let ident = Ident::empty(); + let ident = Ident::dummy(); let attrs = ast::AttrVec::new(); let vis = vis.unwrap_or(ast::Visibility { span: DUMMY_SP, @@ -62,7 +62,6 @@ pub(crate) fn placeholder( AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item { id, span, - ident, vis, attrs, kind: ast::ItemKind::MacCall(mac_placeholder()), @@ -71,7 +70,6 @@ pub(crate) fn placeholder( AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![P(ast::AssocItem { id, span, - ident, vis, attrs, kind: ast::AssocItemKind::MacCall(mac_placeholder()), @@ -80,7 +78,6 @@ pub(crate) fn placeholder( AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![P(ast::AssocItem { id, span, - ident, vis, attrs, kind: ast::AssocItemKind::MacCall(mac_placeholder()), @@ -90,7 +87,6 @@ pub(crate) fn placeholder( AstFragment::TraitImplItems(smallvec![P(ast::AssocItem { id, span, - ident, vis, attrs, kind: ast::AssocItemKind::MacCall(mac_placeholder()), @@ -101,7 +97,6 @@ pub(crate) fn placeholder( AstFragment::ForeignItems(smallvec![P(ast::ForeignItem { id, span, - ident, vis, attrs, kind: ast::ForeignItemKind::MacCall(mac_placeholder()), diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 9dccd4a0552c..c56dbc2e1c40 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -330,7 +330,6 @@ impl EarlyLintPass for UnsafeCode { if let FnKind::Fn( ctxt, _, - _, ast::Fn { sig: ast::FnSig { header: ast::FnHeader { safety: ast::Safety::Unsafe(_), .. }, .. }, body, @@ -3116,6 +3115,7 @@ impl EarlyLintPass for SpecialModuleName { for item in &krate.items { if let ast::ItemKind::Mod( _, + ident, ast::ModKind::Unloaded | ast::ModKind::Loaded(_, ast::Inline::No, _, _), ) = item.kind { @@ -3123,7 +3123,7 @@ impl EarlyLintPass for SpecialModuleName { continue; } - match item.ident.name.as_str() { + match ident.name.as_str() { "lib" => cx.emit_span_lint( SPECIAL_MODULE_NAME, item.span, diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 752636ccaf06..df567e80e556 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -172,20 +172,22 @@ impl EarlyLintPass for NonCamelCaseTypes { } match &it.kind { - ast::ItemKind::TyAlias(..) - | ast::ItemKind::Enum(..) - | ast::ItemKind::Struct(..) - | ast::ItemKind::Union(..) => self.check_case(cx, "type", &it.ident), - ast::ItemKind::Trait(..) => self.check_case(cx, "trait", &it.ident), - ast::ItemKind::TraitAlias(..) => self.check_case(cx, "trait alias", &it.ident), + ast::ItemKind::TyAlias(box ast::TyAlias { ident, .. }) + | ast::ItemKind::Enum(ident, ..) + | ast::ItemKind::Struct(ident, ..) + | ast::ItemKind::Union(ident, ..) => self.check_case(cx, "type", ident), + ast::ItemKind::Trait(box ast::Trait { ident, .. }) => { + self.check_case(cx, "trait", ident) + } + ast::ItemKind::TraitAlias(ident, _, _) => self.check_case(cx, "trait alias", ident), // N.B. This check is only for inherent associated types, so that we don't lint against // trait impls where we should have warned for the trait definition already. ast::ItemKind::Impl(box ast::Impl { of_trait: None, items, .. }) => { for it in items { // FIXME: this doesn't respect `#[allow(..)]` on the item itself. - if let ast::AssocItemKind::Type(..) = it.kind { - self.check_case(cx, "associated type", &it.ident); + if let ast::AssocItemKind::Type(alias) = &it.kind { + self.check_case(cx, "associated type", &alias.ident); } } } @@ -194,8 +196,8 @@ impl EarlyLintPass for NonCamelCaseTypes { } fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) { - if let ast::AssocItemKind::Type(..) = it.kind { - self.check_case(cx, "associated type", &it.ident); + if let ast::AssocItemKind::Type(alias) = &it.kind { + self.check_case(cx, "associated type", &alias.ident); } } diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index e1ee562dafeb..16f87ab79bee 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -1315,17 +1315,14 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { definitions: &Definitions, ) -> Option { match item.kind { - ast::ItemKind::ExternCrate(orig_name) => { - debug!( - "resolving extern crate stmt. ident: {} orig_name: {:?}", - item.ident, orig_name - ); + ast::ItemKind::ExternCrate(orig_name, ident) => { + debug!("resolving extern crate stmt. ident: {} orig_name: {:?}", ident, orig_name); let name = match orig_name { Some(orig_name) => { validate_crate_name(self.sess, orig_name, Some(item.span)); orig_name } - None => item.ident.name, + None => ident.name, }; let dep_kind = if attr::contains_name(&item.attrs, sym::no_link) { CrateDepKind::MacrosOnly @@ -1380,7 +1377,8 @@ fn fn_spans(krate: &ast::Crate, name: Symbol) -> Vec { } impl<'ast> visit::Visitor<'ast> for Finder { fn visit_item(&mut self, item: &'ast ast::Item) { - if item.ident.name == self.name + if let Some(ident) = item.kind.ident() + && ident.name == self.name && attr::contains_name(&item.attrs, sym::rustc_std_internal_symbol) { self.spans.push(item.span); diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index aad185783755..ed6522850960 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -34,10 +34,10 @@ impl<'a> Parser<'a> { } /// Parses a `mod { ... }` or `mod ;` item. - fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemInfo> { + fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemKind> { let safety = self.parse_safety(Case::Sensitive); self.expect_keyword(exp!(Mod))?; - let id = self.parse_ident()?; + let ident = self.parse_ident()?; let mod_kind = if self.eat(exp!(Semi)) { ModKind::Unloaded } else { @@ -46,7 +46,7 @@ impl<'a> Parser<'a> { attrs.extend(inner_attrs); ModKind::Loaded(items, Inline::Yes, inner_span, Ok(())) }; - Ok((id, ItemKind::Mod(safety, mod_kind))) + Ok(ItemKind::Mod(safety, ident, mod_kind)) } /// Parses the contents of a module (inner attributes followed by module items). @@ -115,8 +115,6 @@ impl<'a> Parser<'a> { } } -pub(super) type ItemInfo = (Ident, ItemKind); - impl<'a> Parser<'a> { pub fn parse_item(&mut self, force_collect: ForceCollect) -> PResult<'a, Option>> { let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true }; @@ -163,11 +161,11 @@ impl<'a> Parser<'a> { fn_parse_mode, Case::Sensitive, )?; - if let Some((ident, kind)) = kind { + if let Some(kind) = kind { this.error_on_unconsumed_default(def, &kind); let span = lo.to(this.prev_token.span); let id = DUMMY_NODE_ID; - let item = Item { ident, attrs, id, kind, vis, span, tokens: None }; + let item = Item { attrs, id, kind, vis, span, tokens: None }; return Ok((Some(item), Trailing::No, UsePreAttrPos::No)); } @@ -208,7 +206,7 @@ impl<'a> Parser<'a> { def: &mut Defaultness, fn_parse_mode: FnParseMode, case: Case, - ) -> PResult<'a, Option> { + ) -> PResult<'a, Option> { let check_pub = def == &Defaultness::Final; let mut def_ = || mem::replace(def, Defaultness::Final); @@ -218,17 +216,15 @@ impl<'a> Parser<'a> { // FUNCTION ITEM let (ident, sig, generics, contract, body) = self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?; - ( + ItemKind::Fn(Box::new(Fn { + defaultness: def_(), ident, - ItemKind::Fn(Box::new(Fn { - defaultness: def_(), - sig, - generics, - contract, - body, - define_opaque: None, - })), - ) + sig, + generics, + contract, + body, + define_opaque: None, + })) } else if self.eat_keyword(exp!(Extern)) { if self.eat_keyword(exp!(Crate)) { // EXTERN CRATE @@ -247,8 +243,8 @@ impl<'a> Parser<'a> { // STATIC ITEM self.bump(); // `static` let mutability = self.parse_mutability(); - let (ident, item) = self.parse_static_item(safety, mutability)?; - (ident, ItemKind::Static(Box::new(item))) + let item = self.parse_static_item(safety, mutability)?; + ItemKind::Static(Box::new(item)) } else if let Const::Yes(const_span) = self.parse_constness(Case::Sensitive) { // CONST ITEM if self.token.is_keyword(kw::Impl) { @@ -258,16 +254,14 @@ impl<'a> Parser<'a> { self.recover_const_mut(const_span); self.recover_missing_kw_before_item()?; let (ident, generics, ty, expr) = self.parse_const_item()?; - ( + ItemKind::Const(Box::new(ConstItem { + defaultness: def_(), ident, - ItemKind::Const(Box::new(ConstItem { - defaultness: def_(), - generics, - ty, - expr, - define_opaque: None, - })), - ) + generics, + ty, + expr, + define_opaque: None, + })) } } else if self.check_keyword(exp!(Trait)) || self.check_auto_or_unsafe_trait_item() { // TRAIT ITEM @@ -334,14 +328,14 @@ impl<'a> Parser<'a> { self.recover_missing_kw_before_item()?; } // MACRO INVOCATION ITEM - (Ident::empty(), ItemKind::MacCall(P(self.parse_item_macro(vis)?))) + ItemKind::MacCall(P(self.parse_item_macro(vis)?)) } else { return Ok(None); }; Ok(Some(info)) } - fn recover_import_as_use(&mut self) -> PResult<'a, Option> { + fn recover_import_as_use(&mut self) -> PResult<'a, Option> { let span = self.token.span; let token_name = super::token_descr(&self.token); let snapshot = self.create_snapshot_for_diagnostic(); @@ -359,7 +353,7 @@ impl<'a> Parser<'a> { } } - fn parse_use_item(&mut self) -> PResult<'a, ItemInfo> { + fn parse_use_item(&mut self) -> PResult<'a, ItemKind> { let tree = self.parse_use_tree()?; if let Err(mut e) = self.expect_semi() { match tree.kind { @@ -373,7 +367,7 @@ impl<'a> Parser<'a> { } return Err(e); } - Ok((Ident::empty(), ItemKind::Use(tree))) + Ok(ItemKind::Use(tree)) } /// When parsing a statement, would the start of a path be an item? @@ -483,7 +477,7 @@ impl<'a> Parser<'a> { if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) } } - fn parse_item_builtin(&mut self) -> PResult<'a, Option> { + fn parse_item_builtin(&mut self) -> PResult<'a, Option> { // To be expanded Ok(None) } @@ -577,7 +571,7 @@ impl<'a> Parser<'a> { &mut self, attrs: &mut AttrVec, defaultness: Defaultness, - ) -> PResult<'a, ItemInfo> { + ) -> PResult<'a, ItemKind> { let safety = self.parse_safety(Case::Sensitive); self.expect_keyword(exp!(Impl))?; @@ -698,10 +692,10 @@ impl<'a> Parser<'a> { items: impl_items, })); - Ok((Ident::empty(), item_kind)) + Ok(item_kind) } - fn parse_item_delegation(&mut self) -> PResult<'a, ItemInfo> { + fn parse_item_delegation(&mut self) -> PResult<'a, ItemKind> { let span = self.token.span; self.expect_keyword(exp!(Reuse))?; @@ -724,7 +718,7 @@ impl<'a> Parser<'a> { }) }; - let (ident, item_kind) = if self.eat_path_sep() { + let item_kind = if self.eat_path_sep() { let suffixes = if self.eat(exp!(Star)) { None } else { @@ -732,7 +726,7 @@ impl<'a> Parser<'a> { Some(self.parse_delim_comma_seq(exp!(OpenBrace), exp!(CloseBrace), parse_suffix)?.0) }; let deleg = DelegationMac { qself, prefix: path, suffixes, body: body(self)? }; - (Ident::empty(), ItemKind::DelegationMac(Box::new(deleg))) + ItemKind::DelegationMac(Box::new(deleg)) } else { let rename = rename(self)?; let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident); @@ -740,17 +734,18 @@ impl<'a> Parser<'a> { id: DUMMY_NODE_ID, qself, path, + ident, rename, body: body(self)?, from_glob: false, }; - (ident, ItemKind::Delegation(Box::new(deleg))) + ItemKind::Delegation(Box::new(deleg)) }; let span = span.to(self.prev_token.span); self.psess.gated_spans.gate(sym::fn_delegation, span); - Ok((ident, item_kind)) + Ok(item_kind) } fn parse_item_list( @@ -900,7 +895,7 @@ impl<'a> Parser<'a> { } /// Parses `unsafe? auto? trait Foo { ... }` or `trait Foo = Bar;`. - fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemInfo> { + fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemKind> { let safety = self.parse_safety(Case::Sensitive); // Parse optional `auto` prefix. let is_auto = if self.eat_keyword(exp!(Auto)) { @@ -941,15 +936,12 @@ impl<'a> Parser<'a> { self.psess.gated_spans.gate(sym::trait_alias, whole_span); - Ok((ident, ItemKind::TraitAlias(generics, bounds))) + Ok(ItemKind::TraitAlias(ident, generics, bounds)) } else { // It's a normal trait. generics.where_clause = self.parse_where_clause()?; let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?; - Ok(( - ident, - ItemKind::Trait(Box::new(Trait { is_auto, safety, generics, bounds, items })), - )) + Ok(ItemKind::Trait(Box::new(Trait { is_auto, safety, ident, generics, bounds, items }))) } } @@ -977,11 +969,12 @@ impl<'a> Parser<'a> { force_collect: ForceCollect, ) -> PResult<'a, Option>>> { Ok(self.parse_item_(fn_parse_mode, force_collect)?.map( - |Item { attrs, id, span, vis, ident, kind, tokens }| { + |Item { attrs, id, span, vis, kind, tokens }| { let kind = match AssocItemKind::try_from(kind) { Ok(kind) => kind, Err(kind) => match kind { ItemKind::Static(box StaticItem { + ident, ty, safety: _, mutability: _, @@ -991,6 +984,7 @@ impl<'a> Parser<'a> { self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span }); AssocItemKind::Const(Box::new(ConstItem { defaultness: Defaultness::Final, + ident, generics: Generics::default(), ty, expr, @@ -1000,7 +994,7 @@ impl<'a> Parser<'a> { _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"), }, }; - Some(P(Item { attrs, id, span, vis, ident, kind, tokens })) + Some(P(Item { attrs, id, span, vis, kind, tokens })) }, )) } @@ -1010,7 +1004,7 @@ impl<'a> Parser<'a> { /// TypeAlias = "type" Ident Generics (":" GenericBounds)? WhereClause ("=" Ty)? WhereClause ";" ; /// ``` /// The `"type"` has already been eaten. - fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemInfo> { + fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemKind> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; @@ -1045,16 +1039,14 @@ impl<'a> Parser<'a> { self.expect_semi()?; - Ok(( + Ok(ItemKind::TyAlias(Box::new(TyAlias { + defaultness, ident, - ItemKind::TyAlias(Box::new(TyAlias { - defaultness, - generics, - where_clauses, - bounds, - ty, - })), - )) + generics, + where_clauses, + bounds, + ty, + }))) } /// Parses a `UseTree`. @@ -1158,16 +1150,16 @@ impl<'a> Parser<'a> { /// extern crate foo; /// extern crate bar as foo; /// ``` - fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemInfo> { + fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemKind> { // Accept `extern crate name-like-this` for better diagnostics - let orig_name = self.parse_crate_name_with_dashes()?; - let (item_name, orig_name) = if let Some(rename) = self.parse_rename()? { - (rename, Some(orig_name.name)) + let orig_ident = self.parse_crate_name_with_dashes()?; + let (orig_name, item_ident) = if let Some(rename) = self.parse_rename()? { + (Some(orig_ident.name), rename) } else { - (orig_name, None) + (None, orig_ident) }; self.expect_semi()?; - Ok((item_name, ItemKind::ExternCrate(orig_name))) + Ok(ItemKind::ExternCrate(orig_name, item_ident)) } fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, Ident> { @@ -1218,7 +1210,7 @@ impl<'a> Parser<'a> { &mut self, attrs: &mut AttrVec, mut safety: Safety, - ) -> PResult<'a, ItemInfo> { + ) -> PResult<'a, ItemKind> { let extern_span = self.prev_token.uninterpolated_span(); let abi = self.parse_abi(); // ABI? // FIXME: This recovery should be tested better. @@ -1236,7 +1228,7 @@ impl<'a> Parser<'a> { abi, items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?, }; - Ok((Ident::empty(), ItemKind::ForeignMod(module))) + Ok(ItemKind::ForeignMod(module)) } /// Parses a foreign item (one in an `extern { ... }` block). @@ -1246,11 +1238,11 @@ impl<'a> Parser<'a> { ) -> PResult<'a, Option>>> { let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: false }; Ok(self.parse_item_(fn_parse_mode, force_collect)?.map( - |Item { attrs, id, span, vis, ident, kind, tokens }| { + |Item { attrs, id, span, vis, kind, tokens }| { let kind = match ForeignItemKind::try_from(kind) { Ok(kind) => kind, Err(kind) => match kind { - ItemKind::Const(box ConstItem { ty, expr, .. }) => { + ItemKind::Const(box ConstItem { ident, ty, expr, .. }) => { let const_span = Some(span.with_hi(ident.span.lo())) .filter(|span| span.can_be_used_for_suggestions()); self.dcx().emit_err(errors::ExternItemCannotBeConst { @@ -1258,6 +1250,7 @@ impl<'a> Parser<'a> { const_span, }); ForeignItemKind::Static(Box::new(StaticItem { + ident, ty, mutability: Mutability::Not, expr, @@ -1268,7 +1261,7 @@ impl<'a> Parser<'a> { _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"), }, }; - Some(P(Item { attrs, id, span, vis, ident, kind, tokens })) + Some(P(Item { attrs, id, span, vis, kind, tokens })) }, )) } @@ -1343,13 +1336,13 @@ impl<'a> Parser<'a> { const_span: Span, attrs: &mut AttrVec, defaultness: Defaultness, - ) -> PResult<'a, ItemInfo> { + ) -> PResult<'a, ItemKind> { let impl_span = self.token.span; let err = self.expected_ident_found_err(); // Only try to recover if this is implementing a trait for a type - let mut impl_info = match self.parse_item_impl(attrs, defaultness) { - Ok(impl_info) => impl_info, + let mut item_kind = match self.parse_item_impl(attrs, defaultness) { + Ok(item_kind) => item_kind, Err(recovery_error) => { // Recovery failed, raise the "expected identifier" error recovery_error.cancel(); @@ -1357,7 +1350,7 @@ impl<'a> Parser<'a> { } }; - match &mut impl_info.1 { + match &mut item_kind { ItemKind::Impl(box Impl { of_trait: Some(trai), constness, .. }) => { *constness = Const::Yes(const_span); @@ -1374,7 +1367,7 @@ impl<'a> Parser<'a> { _ => unreachable!(), } - Ok(impl_info) + Ok(item_kind) } /// Parse a static item with the prefix `"static" "mut"?` already parsed and stored in `mutability`. @@ -1386,7 +1379,7 @@ impl<'a> Parser<'a> { &mut self, safety: Safety, mutability: Mutability, - ) -> PResult<'a, (Ident, StaticItem)> { + ) -> PResult<'a, StaticItem> { let ident = self.parse_ident()?; if self.token == TokenKind::Lt && self.may_recover() { @@ -1406,7 +1399,7 @@ impl<'a> Parser<'a> { self.expect_semi()?; - Ok((ident, StaticItem { ty, safety, mutability, expr, define_opaque: None })) + Ok(StaticItem { ident, ty, safety, mutability, expr, define_opaque: None }) } /// Parse a constant item with the prefix `"const"` already parsed. @@ -1531,7 +1524,7 @@ impl<'a> Parser<'a> { } /// Parses an enum declaration. - fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> { + fn parse_item_enum(&mut self) -> PResult<'a, ItemKind> { if self.token.is_keyword(kw::Struct) { let span = self.prev_token.span.to(self.token.span); let err = errors::EnumStructMutuallyExclusive { span }; @@ -1584,7 +1577,7 @@ impl<'a> Parser<'a> { }; let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() }; - Ok((id, ItemKind::Enum(enum_definition, generics))) + Ok(ItemKind::Enum(id, enum_definition, generics)) } fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option> { @@ -1676,8 +1669,8 @@ impl<'a> Parser<'a> { } /// Parses `struct Foo { ... }`. - fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> { - let class_name = self.parse_ident()?; + fn parse_item_struct(&mut self) -> PResult<'a, ItemKind> { + let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; @@ -1698,7 +1691,7 @@ impl<'a> Parser<'a> { let vdata = if self.token.is_keyword(kw::Where) { let tuple_struct_body; (generics.where_clause, tuple_struct_body) = - self.parse_struct_where_clause(class_name, generics.span)?; + self.parse_struct_where_clause(ident, generics.span)?; if let Some(body) = tuple_struct_body { // If we see a misplaced tuple struct body: `struct Foo where T: Copy, (T);` @@ -1712,7 +1705,7 @@ impl<'a> Parser<'a> { // If we see: `struct Foo where T: Copy { ... }` let (fields, recovered) = self.parse_record_struct_body( "struct", - class_name.span, + ident.span, generics.where_clause.has_where_token, )?; VariantData::Struct { fields, recovered } @@ -1724,7 +1717,7 @@ impl<'a> Parser<'a> { } else if self.token == token::OpenDelim(Delimiter::Brace) { let (fields, recovered) = self.parse_record_struct_body( "struct", - class_name.span, + ident.span, generics.where_clause.has_where_token, )?; VariantData::Struct { fields, recovered } @@ -1740,12 +1733,12 @@ impl<'a> Parser<'a> { return Err(self.dcx().create_err(err)); }; - Ok((class_name, ItemKind::Struct(vdata, generics))) + Ok(ItemKind::Struct(ident, vdata, generics)) } /// Parses `union Foo { ... }`. - fn parse_item_union(&mut self) -> PResult<'a, ItemInfo> { - let class_name = self.parse_ident()?; + fn parse_item_union(&mut self) -> PResult<'a, ItemKind> { + let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; @@ -1753,14 +1746,14 @@ impl<'a> Parser<'a> { generics.where_clause = self.parse_where_clause()?; let (fields, recovered) = self.parse_record_struct_body( "union", - class_name.span, + ident.span, generics.where_clause.has_where_token, )?; VariantData::Struct { fields, recovered } } else if self.token == token::OpenDelim(Delimiter::Brace) { let (fields, recovered) = self.parse_record_struct_body( "union", - class_name.span, + ident.span, generics.where_clause.has_where_token, )?; VariantData::Struct { fields, recovered } @@ -1772,7 +1765,7 @@ impl<'a> Parser<'a> { return Err(err); }; - Ok((class_name, ItemKind::Union(vdata, generics))) + Ok(ItemKind::Union(ident, vdata, generics)) } /// This function parses the fields of record structs: @@ -2124,15 +2117,17 @@ impl<'a> Parser<'a> { } } else if self.eat_keyword(exp!(Struct)) { match self.parse_item_struct() { - Ok((ident, _)) => self - .dcx() - .struct_span_err( - lo.with_hi(ident.span.hi()), - format!("structs are not allowed in {adt_ty} definitions"), - ) - .with_help( - "consider creating a new `struct` definition instead of nesting", - ), + Ok(item) => { + let ItemKind::Struct(ident, ..) = item else { unreachable!() }; + self.dcx() + .struct_span_err( + lo.with_hi(ident.span.hi()), + format!("structs are not allowed in {adt_ty} definitions"), + ) + .with_help( + "consider creating a new `struct` definition instead of nesting", + ) + } Err(err) => { err.cancel(); self.restore_snapshot(snapshot); @@ -2177,7 +2172,7 @@ impl<'a> Parser<'a> { /// MacParams = "(" TOKEN_STREAM ")" ; /// DeclMac = "macro" Ident MacParams? MacBody ; /// ``` - fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemInfo> { + fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemKind> { let ident = self.parse_ident()?; let body = if self.check(exp!(OpenBrace)) { self.parse_delim_args()? // `MacBody` @@ -2199,7 +2194,7 @@ impl<'a> Parser<'a> { }; self.psess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span)); - Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, macro_rules: false }))) + Ok(ItemKind::MacroDef(ident, ast::MacroDef { body, macro_rules: false })) } /// Is this a possibly malformed start of a `macro_rules! foo` item definition? @@ -2228,7 +2223,7 @@ impl<'a> Parser<'a> { &mut self, vis: &Visibility, has_bang: bool, - ) -> PResult<'a, ItemInfo> { + ) -> PResult<'a, ItemKind> { self.expect_keyword(exp!(MacroRules))?; // `macro_rules` if has_bang { @@ -2246,7 +2241,7 @@ impl<'a> Parser<'a> { self.eat_semi_for_macro_if_needed(&body); self.complain_if_pub_macro(vis, true); - Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, macro_rules: true }))) + Ok(ItemKind::MacroDef(ident, ast::MacroDef { body, macro_rules: true })) } /// Item macro invocations or `macro_rules!` definitions need inherited visibility. diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs index 471966d086d5..49ae6cb9b726 100644 --- a/compiler/rustc_parse/src/parser/tests.rs +++ b/compiler/rustc_parse/src/parser/tests.rs @@ -2922,7 +2922,7 @@ fn out_of_line_mod() { .unwrap() .unwrap(); - let ast::ItemKind::Mod(_, mod_kind) = &item.kind else { panic!() }; + let ast::ItemKind::Mod(_, _, mod_kind) = &item.kind else { panic!() }; assert_matches!(mod_kind, ast::ModKind::Loaded(items, ..) if items.len() == 2); }); } diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 9d4b46cd3066..664bd4ad0a25 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -268,22 +268,22 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems { impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> { fn visit_item(&mut self, i: &'ast ast::Item) { let target = match &i.kind { - ast::ItemKind::ExternCrate(_) => Target::ExternCrate, + ast::ItemKind::ExternCrate(..) => Target::ExternCrate, ast::ItemKind::Use(_) => Target::Use, ast::ItemKind::Static(_) => Target::Static, ast::ItemKind::Const(_) => Target::Const, ast::ItemKind::Fn(_) | ast::ItemKind::Delegation(..) => Target::Fn, - ast::ItemKind::Mod(_, _) => Target::Mod, + ast::ItemKind::Mod(..) => Target::Mod, ast::ItemKind::ForeignMod(_) => Target::ForeignFn, ast::ItemKind::GlobalAsm(_) => Target::GlobalAsm, ast::ItemKind::TyAlias(_) => Target::TyAlias, - ast::ItemKind::Enum(_, _) => Target::Enum, - ast::ItemKind::Struct(_, _) => Target::Struct, - ast::ItemKind::Union(_, _) => Target::Union, + ast::ItemKind::Enum(..) => Target::Enum, + ast::ItemKind::Struct(..) => Target::Struct, + ast::ItemKind::Union(..) => Target::Union, ast::ItemKind::Trait(_) => Target::Trait, - ast::ItemKind::TraitAlias(_, _) => Target::TraitAlias, + ast::ItemKind::TraitAlias(..) => Target::TraitAlias, ast::ItemKind::Impl(_) => Target::Impl, - ast::ItemKind::MacroDef(_) => Target::MacroDef, + ast::ItemKind::MacroDef(..) => Target::MacroDef, ast::ItemKind::MacCall(_) | ast::ItemKind::DelegationMac(_) => { unreachable!("macros should have been expanded") } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 97fbf7e378ac..7f29f1a084e6 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -10,8 +10,8 @@ use std::sync::Arc; use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind}; use rustc_ast::{ - self as ast, AssocItem, AssocItemKind, Block, ForeignItem, ForeignItemKind, Impl, Item, - ItemKind, MetaItemKind, NodeId, StmtKind, + self as ast, AssocItem, AssocItemKind, Block, ConstItem, Delegation, ForeignItem, + ForeignItemKind, Impl, Item, ItemKind, MetaItemKind, NodeId, StaticItem, StmtKind, }; use rustc_attr_parsing as attr; use rustc_expand::base::ResolverExpand; @@ -735,7 +735,6 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { let parent_scope = &self.parent_scope; let parent = parent_scope.module; let expansion = parent_scope.expansion; - let ident = item.ident; let sp = item.span; let vis = self.resolve_visibility(&item.vis); let feed = self.r.feed(item.id); @@ -762,9 +761,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { ); } - ItemKind::ExternCrate(orig_name) => { + ItemKind::ExternCrate(orig_name, ident) => { self.build_reduced_graph_for_extern_crate( orig_name, + ident, item, local_def_id, vis, @@ -772,7 +772,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { ); } - ItemKind::Mod(.., ref mod_kind) => { + ItemKind::Mod(_, ident, ref mod_kind) => { let module = self.r.new_module( Some(parent), ModuleKind::Def(def_kind, def_id, Some(ident.name)), @@ -792,10 +792,12 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } // These items live in the value namespace. - ItemKind::Const(..) | ItemKind::Delegation(..) | ItemKind::Static(..) => { + ItemKind::Const(box ConstItem { ident, .. }) + | ItemKind::Delegation(box Delegation { ident, .. }) + | ItemKind::Static(box StaticItem { ident, .. }) => { self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion)); } - ItemKind::Fn(..) => { + ItemKind::Fn(box ast::Fn { ident, .. }) => { self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion)); // Functions introducing procedural macros reserve a slot @@ -804,11 +806,11 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } // These items live in the type namespace. - ItemKind::TyAlias(..) | ItemKind::TraitAlias(..) => { + ItemKind::TyAlias(box ast::TyAlias { ident, .. }) | ItemKind::TraitAlias(ident, ..) => { self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); } - ItemKind::Enum(_, _) | ItemKind::Trait(..) => { + ItemKind::Enum(ident, _, _) | ItemKind::Trait(box ast::Trait { ident, .. }) => { let module = self.r.new_module( Some(parent), ModuleKind::Def(def_kind, def_id, Some(ident.name)), @@ -821,7 +823,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } // These items live in both the type and value namespaces. - ItemKind::Struct(ref vdata, _) => { + ItemKind::Struct(ident, ref vdata, _) => { self.build_reduced_graph_for_struct_variant( vdata.fields(), ident, @@ -872,7 +874,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } } - ItemKind::Union(ref vdata, _) => { + ItemKind::Union(ident, ref vdata, _) => { self.build_reduced_graph_for_struct_variant( vdata.fields(), ident, @@ -898,12 +900,12 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { fn build_reduced_graph_for_extern_crate( &mut self, orig_name: Option, + ident: Ident, item: &Item, local_def_id: LocalDefId, vis: ty::Visibility, parent: Module<'ra>, ) { - let ident = item.ident; let sp = item.span; let parent_scope = self.parent_scope; let expansion = parent_scope.expansion; @@ -987,7 +989,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } /// Constructs the reduced graph for one foreign item. - fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem) { + fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem, ident: Ident) { let feed = self.r.feed(item.id); let local_def_id = feed.key(); let def_id = local_def_id.to_def_id(); @@ -1000,7 +1002,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { let parent = self.parent_scope.module; let expansion = self.parent_scope.expansion; let vis = self.resolve_visibility(&item.vis); - self.r.define(parent, item.ident, ns, (self.res(def_id), vis, item.span, expansion)); + self.r.define(parent, ident, ns, (self.res(def_id), vis, item.span, expansion)); self.r.feed_visibility(feed, vis); } @@ -1043,7 +1045,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { span: item.span, }); } - if let ItemKind::ExternCrate(Some(orig_name)) = item.kind + if let ItemKind::ExternCrate(Some(orig_name), _) = item.kind && orig_name == kw::SelfLower { self.r.dcx().emit_err(errors::MacroUseExternCrateSelf { span: attr.span }); @@ -1177,11 +1179,15 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Invocation(invoc_id)) } - fn proc_macro_stub(&self, item: &ast::Item) -> Option<(MacroKind, Ident, Span)> { + fn proc_macro_stub( + &self, + item: &ast::Item, + fn_ident: Ident, + ) -> Option<(MacroKind, Ident, Span)> { if ast::attr::contains_name(&item.attrs, sym::proc_macro) { - return Some((MacroKind::Bang, item.ident, item.span)); + return Some((MacroKind::Bang, fn_ident, item.span)); } else if ast::attr::contains_name(&item.attrs, sym::proc_macro_attribute) { - return Some((MacroKind::Attr, item.ident, item.span)); + return Some((MacroKind::Attr, fn_ident, item.span)); } else if let Some(attr) = ast::attr::find_by_name(&item.attrs, sym::proc_macro_derive) && let Some(meta_item_inner) = attr.meta_item_list().and_then(|list| list.get(0).cloned()) @@ -1214,17 +1220,21 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { let feed = self.r.feed(item.id); let def_id = feed.key(); let (res, ident, span, macro_rules) = match &item.kind { - ItemKind::MacroDef(def) => (self.res(def_id), item.ident, item.span, def.macro_rules), - ItemKind::Fn(..) => match self.proc_macro_stub(item) { - Some((macro_kind, ident, span)) => { - let res = Res::Def(DefKind::Macro(macro_kind), def_id.to_def_id()); - let macro_data = MacroData::new(self.r.dummy_ext(macro_kind)); - self.r.macro_map.insert(def_id.to_def_id(), macro_data); - self.r.proc_macro_stubs.insert(def_id); - (res, ident, span, false) + ItemKind::MacroDef(ident, def) => { + (self.res(def_id), *ident, item.span, def.macro_rules) + } + ItemKind::Fn(box ast::Fn { ident: fn_ident, .. }) => { + match self.proc_macro_stub(item, *fn_ident) { + Some((macro_kind, ident, span)) => { + let res = Res::Def(DefKind::Macro(macro_kind), def_id.to_def_id()); + let macro_data = MacroData::new(self.r.dummy_ext(macro_kind)); + self.r.macro_map.insert(def_id.to_def_id(), macro_data); + self.r.proc_macro_stubs.insert(def_id); + (res, ident, span, false) + } + None => return parent_scope.macro_rules, } - None => return parent_scope.macro_rules, - }, + } _ => unreachable!(), }; @@ -1327,8 +1337,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { // Visit attributes after items for backward compatibility. // This way they can use `macro_rules` defined later. self.visit_vis(&item.vis); - self.visit_ident(&item.ident); - item.kind.walk(item.span, item.id, &item.ident, &item.vis, (), self); + item.kind.walk(item.span, item.id, &item.vis, (), self); visit::walk_list!(self, visit_attribute, &item.attrs); } _ => visit::walk_item(self, item), @@ -1358,7 +1367,10 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { return; } - self.build_reduced_graph_for_foreign_item(foreign_item); + // `unwrap` is safe because `MacCall` has been excluded, and other foreign item kinds have + // an ident. + let ident = foreign_item.kind.ident().unwrap(); + self.build_reduced_graph_for_foreign_item(foreign_item, ident); visit::walk_item(self, foreign_item); } @@ -1413,13 +1425,16 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { AssocItemKind::Type(..) => TypeNS, AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => bug!(), // handled above }; + // `unwrap` is safe because `MacCall`/`DelegationMac` have been excluded, and other foreign + // item kinds have an ident. + let ident = item.kind.ident().unwrap(); if ctxt == AssocCtxt::Trait { let parent = self.parent_scope.module; let expansion = self.parent_scope.expansion; - self.r.define(parent, item.ident, ns, (self.res(def_id), vis, item.span, expansion)); + self.r.define(parent, ident, ns, (self.res(def_id), vis, item.span, expansion)); } else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob) { let impl_def_id = self.r.tcx.local_parent(local_def_id); - let key = BindingKey::new(item.ident.normalize_to_macros_2_0(), ns); + let key = BindingKey::new(ident.normalize_to_macros_2_0(), ns); self.r.impl_binding_keys.entry(impl_def_id).or_default().insert(key); } diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 51ff4aa834ba..e97233e97ce5 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -219,14 +219,14 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'ra, 'tcx> { // because this means that they were generated in some fashion by the // compiler and we don't need to consider them. ast::ItemKind::Use(..) if item.span.is_dummy() => return, - ast::ItemKind::ExternCrate(orig_name) => { + ast::ItemKind::ExternCrate(orig_name, ident) => { self.extern_crate_items.push(ExternCrateToLint { id: item.id, span: item.span, vis_span: item.vis.span, span_with_attributes: item.span_with_attributes(), has_attrs: !item.attrs.is_empty(), - ident: item.ident, + ident, renames: orig_name.is_some(), }); } diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 6f48a75d6174..6ad056edbaf8 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -122,7 +122,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { }, ItemKind::Const(..) => DefKind::Const, ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn, - ItemKind::MacroDef(def) => { + ItemKind::MacroDef(ident, def) => { let edition = i.span.edition(); // FIXME(jdonszelmann) make one of these in the resolver? @@ -141,7 +141,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { ); let macro_data = - self.resolver.compile_macro(def, i.ident, &attrs, i.span, i.id, edition); + self.resolver.compile_macro(def, *ident, &attrs, i.span, i.id, edition); let macro_kind = macro_data.ext.macro_kind(); opt_macro_data = Some(macro_data); DefKind::Macro(macro_kind) @@ -152,7 +152,8 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { return self.visit_macro_invoc(i.id); } }; - let def_id = self.create_def(i.id, Some(i.ident.name), def_kind, i.span); + let def_id = + self.create_def(i.id, i.kind.ident().map(|ident| ident.name), def_kind, i.span); if let Some(macro_data) = opt_macro_data { self.resolver.macro_map.insert(def_id.to_def_id(), macro_data); @@ -161,7 +162,8 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { self.with_parent(def_id, |this| { this.with_impl_trait(ImplTraitContext::Existential, |this| { match i.kind { - ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => { + ItemKind::Struct(_, ref struct_def, _) + | ItemKind::Union(_, ref struct_def, _) => { // If this is a unit or tuple-like struct, register the constructor. if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(struct_def) { this.create_def( @@ -183,7 +185,6 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { match fn_kind { FnKind::Fn( _ctxt, - _ident, _vis, Fn { sig: FnSig { header, decl, span: _ }, generics, contract, body, .. }, ) if let Some(coroutine_kind) = header.coroutine_kind => { @@ -234,8 +235,9 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { } fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { - let def_kind = match fi.kind { + let (ident, def_kind) = match fi.kind { ForeignItemKind::Static(box StaticItem { + ident, ty: _, mutability, expr: _, @@ -247,14 +249,14 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { ast::Safety::Safe(_) => hir::Safety::Safe, }; - DefKind::Static { safety, mutability, nested: false } + (ident, DefKind::Static { safety, mutability, nested: false }) } - ForeignItemKind::Fn(_) => DefKind::Fn, - ForeignItemKind::TyAlias(_) => DefKind::ForeignTy, + ForeignItemKind::Fn(box Fn { ident, .. }) => (ident, DefKind::Fn), + ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => (ident, DefKind::ForeignTy), ForeignItemKind::MacCall(_) => return self.visit_macro_invoc(fi.id), }; - let def = self.create_def(fi.id, Some(fi.ident.name), def_kind, fi.span); + let def = self.create_def(fi.id, Some(ident.name), def_kind, fi.span); self.with_parent(def, |this| visit::walk_item(this, fi)); } @@ -318,16 +320,17 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { } fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) { - let def_kind = match &i.kind { - AssocItemKind::Fn(..) | AssocItemKind::Delegation(..) => DefKind::AssocFn, - AssocItemKind::Const(..) => DefKind::AssocConst, - AssocItemKind::Type(..) => DefKind::AssocTy, + let (ident, def_kind) = match &i.kind { + AssocItemKind::Fn(box Fn { ident, .. }) + | AssocItemKind::Delegation(box Delegation { ident, .. }) => (*ident, DefKind::AssocFn), + AssocItemKind::Const(box ConstItem { ident, .. }) => (*ident, DefKind::AssocConst), + AssocItemKind::Type(box TyAlias { ident, .. }) => (*ident, DefKind::AssocTy), AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => { return self.visit_macro_invoc(i.id); } }; - let def = self.create_def(i.id, Some(i.ident.name), def_kind, i.span); + let def = self.create_def(i.id, Some(ident.name), def_kind, i.span); self.with_parent(def, |this| visit::walk_assoc_item(this, i, ctxt)); } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 63ea8c4ced13..7d6af12909c7 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -3063,7 +3063,7 @@ impl<'tcx> visit::Visitor<'tcx> for UsePlacementFinder { fn visit_item(&mut self, item: &'tcx ast::Item) { if self.target_module == item.id { - if let ItemKind::Mod(_, ModKind::Loaded(items, _inline, mod_spans, _)) = &item.kind { + if let ItemKind::Mod(_, _, ModKind::Loaded(items, _inline, mod_spans, _)) = &item.kind { let inject = mod_spans.inject_use_span; if is_span_suitable_for_use_injection(inject) { self.first_legal_span = Some(inject); diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 6ef4aa407253..a5ca4565d7b4 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -252,7 +252,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> self.current_private_vis = prev_private_vis; } - ast::ItemKind::Enum(EnumDef { ref variants }, _) => { + ast::ItemKind::Enum(_, EnumDef { ref variants }, _) => { self.set_bindings_effective_visibilities(def_id); for variant in variants { let variant_def_id = self.r.local_def_id(variant.id); @@ -262,7 +262,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> } } - ast::ItemKind::Struct(ref def, _) | ast::ItemKind::Union(ref def, _) => { + ast::ItemKind::Struct(_, ref def, _) | ast::ItemKind::Union(_, ref def, _) => { for field in def.fields() { self.update_field(self.r.local_def_id(field.id), def_id); } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 0d23ae501f04..d4dd0800452a 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1025,8 +1025,8 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r match fn_kind { // Bail if the function is foreign, and thus cannot validly have // a body, or if there's no body for some other reason. - FnKind::Fn(FnCtxt::Foreign, _, _, Fn { sig, generics, .. }) - | FnKind::Fn(_, _, _, Fn { sig, generics, body: None, .. }) => { + FnKind::Fn(FnCtxt::Foreign, _, Fn { sig, generics, .. }) + | FnKind::Fn(_, _, Fn { sig, generics, body: None, .. }) => { self.visit_fn_header(&sig.header); self.visit_generics(generics); self.with_lifetime_rib( @@ -1058,7 +1058,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r // Create a label rib for the function. this.with_label_rib(RibKind::FnOrCoroutine, |this| { match fn_kind { - FnKind::Fn(_, _, _, Fn { sig, generics, contract, body, .. }) => { + FnKind::Fn(_, _, Fn { sig, generics, contract, body, .. }) => { this.visit_generics(generics); let declaration = &sig.decl; @@ -2632,8 +2632,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id)); } - let name = item.ident.name; - debug!("(resolving item) resolving {} ({:?})", name, item.kind); + debug!("(resolving item) resolving {:?} ({:?})", item.kind.ident(), item.kind); let def_kind = self.r.local_def_kind(item.id); match item.kind { @@ -2664,9 +2663,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.resolve_define_opaques(define_opaque); } - ItemKind::Enum(_, ref generics) - | ItemKind::Struct(_, ref generics) - | ItemKind::Union(_, ref generics) => { + ItemKind::Enum(_, _, ref generics) + | ItemKind::Struct(_, _, ref generics) + | ItemKind::Union(_, _, ref generics) => { self.resolve_adt(item, generics); } @@ -2710,7 +2709,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); } - ItemKind::TraitAlias(ref generics, ref bounds) => { + ItemKind::TraitAlias(_, ref generics, ref bounds) => { // Create a new rib for the trait-wide type parameters. self.with_generic_param_rib( &generics.params, @@ -2748,7 +2747,11 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } ItemKind::Static(box ast::StaticItem { - ref ty, ref expr, ref define_opaque, .. + ident, + ref ty, + ref expr, + ref define_opaque, + .. }) => { self.with_static_rib(def_kind, |this| { this.with_lifetime_rib( @@ -2762,13 +2765,14 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { if let Some(expr) = expr { // We already forbid generic params because of the above item rib, // so it doesn't matter whether this is a trivial constant. - this.resolve_const_body(expr, Some((item.ident, ConstantItemKind::Static))); + this.resolve_const_body(expr, Some((ident, ConstantItemKind::Static))); } }); self.resolve_define_opaques(define_opaque); } ItemKind::Const(box ast::ConstItem { + ident, ref generics, ref ty, ref expr, @@ -2801,10 +2805,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); if let Some(expr) = expr { - this.resolve_const_body( - expr, - Some((item.ident, ConstantItemKind::Const)), - ); + this.resolve_const_body(expr, Some((ident, ConstantItemKind::Const))); } }, ); @@ -2821,7 +2822,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.future_proof_import(use_tree); } - ItemKind::MacroDef(ref macro_def) => { + ItemKind::MacroDef(_, ref macro_def) => { // Maintain macro_rules scopes in the same way as during early resolution // for diagnostics and doc links. if macro_def.macro_rules { @@ -3319,7 +3320,12 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.resolve_doc_links(&item.attrs, MaybeExported::ImplItem(trait_id.ok_or(&item.vis))); match &item.kind { AssocItemKind::Const(box ast::ConstItem { - generics, ty, expr, define_opaque, .. + ident, + generics, + ty, + expr, + define_opaque, + .. }) => { debug!("resolve_implementation AssocItemKind::Const"); self.with_generic_param_rib( @@ -3350,7 +3356,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // exists in trait this.check_trait_item( item.id, - item.ident, + *ident, &item.kind, ValueNS, item.span, @@ -3376,7 +3382,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); self.resolve_define_opaques(define_opaque); } - AssocItemKind::Fn(box Fn { generics, define_opaque, .. }) => { + AssocItemKind::Fn(box Fn { ident, generics, define_opaque, .. }) => { debug!("resolve_implementation AssocItemKind::Fn"); // We also need a new scope for the impl item type parameters. self.with_generic_param_rib( @@ -3392,7 +3398,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // exists in trait this.check_trait_item( item.id, - item.ident, + *ident, &item.kind, ValueNS, item.span, @@ -3406,7 +3412,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.resolve_define_opaques(define_opaque); } - AssocItemKind::Type(box TyAlias { generics, .. }) => { + AssocItemKind::Type(box TyAlias { ident, generics, .. }) => { self.diag_metadata.in_non_gat_assoc_type = Some(generics.params.is_empty()); debug!("resolve_implementation AssocItemKind::Type"); // We also need a new scope for the impl item type parameters. @@ -3424,7 +3430,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // exists in trait this.check_trait_item( item.id, - item.ident, + *ident, &item.kind, TypeNS, item.span, @@ -3451,7 +3457,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { |this| { this.check_trait_item( item.id, - item.ident, + delegation.ident, &item.kind, ValueNS, item.span, @@ -4337,7 +4343,13 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { if let Some(items) = self.diag_metadata.current_trait_assoc_items && let [Segment { ident, .. }] = path && items.iter().any(|item| { - item.ident == *ident && matches!(item.kind, AssocItemKind::Type(_)) + if let AssocItemKind::Type(alias) = &item.kind + && alias.ident == *ident + { + true + } else { + false + } }) { let mut diag = self.r.tcx.dcx().struct_allow(""); @@ -5159,12 +5171,12 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { ItemKind::TyAlias(box TyAlias { generics, .. }) | ItemKind::Const(box ConstItem { generics, .. }) | ItemKind::Fn(box Fn { generics, .. }) - | ItemKind::Enum(_, generics) - | ItemKind::Struct(_, generics) - | ItemKind::Union(_, generics) + | ItemKind::Enum(_, _, generics) + | ItemKind::Struct(_, _, generics) + | ItemKind::Union(_, _, generics) | ItemKind::Impl(box Impl { generics, .. }) | ItemKind::Trait(box Trait { generics, .. }) - | ItemKind::TraitAlias(generics, _) => { + | ItemKind::TraitAlias(_, generics, _) => { if let ItemKind::Fn(box Fn { sig, .. }) = &item.kind { self.collect_fn_info(sig.header, &sig.decl, item.id, &item.attrs); } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index e40f84e7e598..2a2b1ecef161 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -224,12 +224,17 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let suggestion = if self.current_trait_ref.is_none() && let Some((fn_kind, _)) = self.diag_metadata.current_function && let Some(FnCtxt::Assoc(_)) = fn_kind.ctxt() - && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = fn_kind + && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = fn_kind && let Some(items) = self.diag_metadata.current_impl_items && let Some(item) = items.iter().find(|i| { - i.ident.name == item_str.name + if let Some(ident) = i.kind.ident() + && ident.name == item_str.name + { // Don't suggest if the item is in Fn signature arguments (#112590). - && !sig.span.contains(item_span) + !sig.span.contains(item_span) + } else { + false + } }) { let sp = item_span.shrink_to_lo(); @@ -268,14 +273,14 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // you can't call `fn foo(&self)` from `fn bar()` (#115992). // We also want to mention that the method exists. span_label = Some(( - item.ident.span, + fn_.ident.span, "a method by that name is available on `Self` here", )); None } AssocItemKind::Fn(fn_) if !fn_.sig.decl.has_self() && !is_call => { span_label = Some(( - item.ident.span, + fn_.ident.span, "an associated function by that name is available on `Self` here", )); None @@ -604,7 +609,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { Applicability::MaybeIncorrect, ); if !self.self_value_is_available(path[0].ident.span) { - if let Some((FnKind::Fn(_, _, _, ast::Fn { sig, .. }), fn_span)) = + if let Some((FnKind::Fn(_, _, ast::Fn { sig, .. }), fn_span)) = &self.diag_metadata.current_function { let (span, sugg) = if let Some(param) = sig.decl.inputs.get(0) { @@ -1064,15 +1069,11 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } err.code(E0411); err.span_label(span, "`Self` is only available in impls, traits, and type definitions"); - if let Some(item_kind) = self.diag_metadata.current_item { - if !item_kind.ident.span.is_dummy() { + if let Some(item) = self.diag_metadata.current_item { + if let Some(ident) = item.kind.ident() { err.span_label( - item_kind.ident.span, - format!( - "`Self` not allowed in {} {}", - item_kind.kind.article(), - item_kind.kind.descr() - ), + ident.span, + format!("`Self` not allowed in {} {}", item.kind.article(), item.kind.descr()), ); } } @@ -1150,17 +1151,14 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { ); } } - } else if let Some(item_kind) = self.diag_metadata.current_item { - if matches!(item_kind.kind, ItemKind::Delegation(..)) { - err.span_label(item_kind.span, format!("delegation supports {self_from_macro}")); + } else if let Some(item) = self.diag_metadata.current_item { + if matches!(item.kind, ItemKind::Delegation(..)) { + err.span_label(item.span, format!("delegation supports {self_from_macro}")); } else { + let span = if let Some(ident) = item.kind.ident() { ident.span } else { item.span }; err.span_label( - item_kind.ident.span, - format!( - "`self` not allowed in {} {}", - item_kind.kind.article(), - item_kind.kind.descr() - ), + span, + format!("`self` not allowed in {} {}", item.kind.article(), item.kind.descr()), ); } } @@ -2196,7 +2194,9 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { if let Some(items) = self.diag_metadata.current_trait_assoc_items { for assoc_item in items { - if assoc_item.ident == ident { + if let Some(assoc_ident) = assoc_item.kind.ident() + && assoc_ident == ident + { return Some(match &assoc_item.kind { ast::AssocItemKind::Const(..) => AssocSuggestion::AssocConst, ast::AssocItemKind::Fn(box ast::Fn { sig, .. }) if sig.decl.has_self() => { @@ -2735,7 +2735,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { return None; } match (self.diag_metadata.current_item, single_uppercase_char, self.diag_metadata.currently_processing_generic_args) { - (Some(Item { kind: ItemKind::Fn(..), ident, .. }), _, _) if ident.name == sym::main => { + (Some(Item { kind: ItemKind::Fn(fn_), .. }), _, _) if fn_.ident.name == sym::main => { // Ignore `fn main()` as we don't want to suggest `fn main()` } ( @@ -3400,7 +3400,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { { let pre = if lt.kind == MissingLifetimeKind::Ampersand && let Some((kind, _span)) = self.diag_metadata.current_function - && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = kind + && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = kind && !sig.decl.inputs.is_empty() && let sugg = sig .decl @@ -3441,7 +3441,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } else if (lt.kind == MissingLifetimeKind::Ampersand || lt.kind == MissingLifetimeKind::Underscore) && let Some((kind, _span)) = self.diag_metadata.current_function - && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = kind + && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = kind && let ast::FnRetTy::Ty(ret_ty) = &sig.decl.output && !sig.decl.inputs.is_empty() && let arg_refs = sig @@ -3501,7 +3501,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let mut owned_sugg = lt.kind == MissingLifetimeKind::Ampersand; let mut sugg = vec![(lt.span, String::new())]; if let Some((kind, _span)) = self.diag_metadata.current_function - && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = kind + && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = kind && let ast::FnRetTy::Ty(ty) = &sig.decl.output { let mut lt_finder = diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index 56b1e76ae8cf..4edd5433de6c 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -350,21 +350,21 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result { + ast::ItemKind::Fn(ref fn_item) if !info.has_main_fn => { // We only push if it's the top item because otherwise, we would duplicate // its content since the top-level item was already added. - if item.ident.name == sym::main { + if fn_item.ident.name == sym::main { info.has_main_fn = true; } } - ast::ItemKind::ExternCrate(original) => { + ast::ItemKind::ExternCrate(original, ident) => { is_extern_crate = true; if !info.already_has_extern_crate && let Some(crate_name) = crate_name { info.already_has_extern_crate = match original { Some(name) => name.as_str() == *crate_name, - None => item.ident.as_str() == *crate_name, + None => ident.as_str() == *crate_name, }; } } diff --git a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs index 7d86bd3e540a..c2aac7ca090b 100644 --- a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs +++ b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs @@ -53,7 +53,7 @@ declare_lint_pass!(CrateInMacroDef => [CRATE_IN_MACRO_DEF]); impl EarlyLintPass for CrateInMacroDef { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - if let ItemKind::MacroDef(macro_def) = &item.kind + if let ItemKind::MacroDef(_, macro_def) = &item.kind && item.attrs.iter().any(is_macro_export) && let Some(span) = contains_unhygienic_crate_reference(¯o_def.body.tokens) { diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs index 3008082c2329..f6c10da1596b 100644 --- a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs +++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs @@ -13,16 +13,16 @@ use rustc_parse::parser::ForceCollect; use rustc_session::parse::ParseSess; use rustc_span::edition::Edition; use rustc_span::source_map::{FilePathMapping, SourceMap}; -use rustc_span::{FileName, Pos, sym}; +use rustc_span::{FileName, Ident, Pos, sym}; use super::Fragments; -fn get_test_spans(item: &Item, test_attr_spans: &mut Vec>) { +fn get_test_spans(item: &Item, ident: Ident, test_attr_spans: &mut Vec>) { test_attr_spans.extend( item.attrs .iter() .find(|attr| attr.has_name(sym::test)) - .map(|attr| attr.span.lo().to_usize()..item.ident.span.hi().to_usize()), + .map(|attr| attr.span.lo().to_usize()..ident.span.hi().to_usize()), ); } @@ -64,10 +64,10 @@ pub fn check( match parser.parse_item(ForceCollect::No) { Ok(Some(item)) => match &item.kind { ItemKind::Fn(box Fn { - sig, body: Some(block), .. - }) if item.ident.name == sym::main => { + ident, sig, body: Some(block), .. + }) if ident.name == sym::main => { if !ignore { - get_test_spans(&item, &mut test_attr_spans); + get_test_spans(&item, *ident, &mut test_attr_spans); } let is_async = matches!(sig.header.coroutine_kind, Some(CoroutineKind::Async { .. })); let returns_nothing = match &sig.decl.output { @@ -85,10 +85,10 @@ pub fn check( } }, // Another function was found; this case is ignored for needless_doctest_main - ItemKind::Fn(box Fn { .. }) => { + ItemKind::Fn(fn_) => { eligible = false; if !ignore { - get_test_spans(&item, &mut test_attr_spans); + get_test_spans(&item, fn_.ident, &mut test_attr_spans); } }, // Tests with one of these items are ignored diff --git a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs index 1dac7b971f95..243c99a19ce1 100644 --- a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs +++ b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs @@ -63,7 +63,7 @@ impl_lint_pass!(DuplicateMod => [DUPLICATE_MOD]); impl EarlyLintPass for DuplicateMod { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, mod_spans, _)) = &item.kind + if let ItemKind::Mod(_, _, ModKind::Loaded(_, Inline::No, mod_spans, _)) = &item.kind && let FileName::Real(real) = cx.sess().source_map().span_to_filename(mod_spans.inner_span) && let Some(local_path) = real.into_local_path() && let Ok(absolute_path) = local_path.canonicalize() diff --git a/src/tools/clippy/clippy_lints/src/empty_line_after.rs b/src/tools/clippy/clippy_lints/src/empty_line_after.rs index 80c2b03c41cf..899b5c595261 100644 --- a/src/tools/clippy/clippy_lints/src/empty_line_after.rs +++ b/src/tools/clippy/clippy_lints/src/empty_line_after.rs @@ -9,7 +9,7 @@ use rustc_lexer::TokenKind; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::impl_lint_pass; use rustc_span::symbol::kw; -use rustc_span::{BytePos, ExpnKind, Ident, InnerSpan, Span, SpanData, Symbol}; +use rustc_span::{BytePos, ExpnKind, Ident, InnerSpan, Span, SpanData, Symbol, sym}; declare_clippy_lint! { /// ### What it does @@ -375,21 +375,21 @@ impl EmptyLineAfter { &mut self, cx: &EarlyContext<'_>, kind: &ItemKind, - ident: &Ident, + ident: &Option, span: Span, attrs: &[Attribute], id: NodeId, ) { self.items.push(ItemInfo { kind: kind.descr(), - name: ident.name, - span: if span.contains(ident.span) { + name: if let Some(ident) = ident { ident.name } else { sym::dummy }, + span: if let Some(ident) = ident { span.with_hi(ident.span.hi()) } else { span.with_hi(span.lo()) }, mod_items: match kind { - ItemKind::Mod(_, ModKind::Loaded(items, _, _, _)) => items + ItemKind::Mod(_, _, ModKind::Loaded(items, _, _, _)) => items .iter() .filter(|i| !matches!(i.span.ctxt().outer_expn_data().kind, ExpnKind::AstPass(_))) .map(|i| i.id) @@ -471,7 +471,7 @@ impl EarlyLintPass for EmptyLineAfter { self.check_item_kind( cx, &item.kind.clone().into(), - &item.ident, + &item.kind.ident(), item.span, &item.attrs, item.id, @@ -482,7 +482,7 @@ impl EarlyLintPass for EmptyLineAfter { self.check_item_kind( cx, &item.kind.clone().into(), - &item.ident, + &item.kind.ident(), item.span, &item.attrs, item.id, @@ -490,6 +490,6 @@ impl EarlyLintPass for EmptyLineAfter { } fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - self.check_item_kind(cx, &item.kind, &item.ident, item.span, &item.attrs, item.id); + self.check_item_kind(cx, &item.kind, &item.kind.ident(), item.span, &item.attrs, item.id); } } diff --git a/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs b/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs index 743ec5b9ea7f..7d87f04fef9d 100644 --- a/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs +++ b/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs @@ -74,10 +74,9 @@ declare_lint_pass!(EmptyWithBrackets => [EMPTY_STRUCTS_WITH_BRACKETS, EMPTY_ENUM impl EarlyLintPass for EmptyWithBrackets { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - let span_after_ident = item.span.with_lo(item.ident.span.hi()); - - if let ItemKind::Struct(var_data, _) = &item.kind + if let ItemKind::Struct(ident, var_data, _) = &item.kind && has_brackets(var_data) + && let span_after_ident = item.span.with_lo(ident.span.hi()) && has_no_fields(cx, var_data, span_after_ident) { span_lint_and_then( diff --git a/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs b/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs index ba2b37fbf11a..aae8291905d3 100644 --- a/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs +++ b/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs @@ -51,7 +51,7 @@ declare_lint_pass!(FieldScopedVisibilityModifiers => [FIELD_SCOPED_VISIBILITY_MO impl EarlyLintPass for FieldScopedVisibilityModifiers { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - let ItemKind::Struct(ref st, _) = item.kind else { + let ItemKind::Struct(_, ref st, _) = item.kind else { return; }; for field in st.fields() { diff --git a/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs b/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs index 0e1980a6acb6..4b32ba83b325 100644 --- a/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs +++ b/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs @@ -39,7 +39,7 @@ declare_lint_pass!(MultipleBoundLocations => [MULTIPLE_BOUND_LOCATIONS]); impl EarlyLintPass for MultipleBoundLocations { fn check_fn(&mut self, cx: &EarlyContext<'_>, kind: FnKind<'_>, _: Span, _: NodeId) { - if let FnKind::Fn(_, _, _, Fn { generics, .. }) = kind + if let FnKind::Fn(_, _, Fn { generics, .. }) = kind && !generics.params.is_empty() && !generics.where_clause.predicates.is_empty() { diff --git a/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs b/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs index 267e2067e101..cda752d003fa 100644 --- a/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs +++ b/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs @@ -41,7 +41,7 @@ declare_lint_pass!(PartialPubFields => [PARTIAL_PUB_FIELDS]); impl EarlyLintPass for PartialPubFields { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - let ItemKind::Struct(ref st, _) = item.kind else { + let ItemKind::Struct(_, ref st, _) = item.kind else { return; }; diff --git a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs index fa0824535042..35f80b2acda6 100644 --- a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs +++ b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs @@ -174,11 +174,11 @@ impl SingleComponentPathImports { } match &item.kind { - ItemKind::Mod(_, ModKind::Loaded(items, ..)) => { + ItemKind::Mod(_, _, ModKind::Loaded(items, ..)) => { self.check_mod(items); }, - ItemKind::MacroDef(MacroDef { macro_rules: true, .. }) => { - macros.push(item.ident.name); + ItemKind::MacroDef(ident, MacroDef { macro_rules: true, .. }) => { + macros.push(ident.name); }, ItemKind::Use(use_tree) => { let segments = &use_tree.prefix.segments; diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs index 6023ae9cc7b1..ff63eb505a5c 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs @@ -321,17 +321,18 @@ pub fn eq_local_kind(l: &LocalKind, r: &LocalKind) -> bool { } pub fn eq_item(l: &Item, r: &Item, mut eq_kind: impl FnMut(&K, &K) -> bool) -> bool { - eq_id(l.ident, r.ident) && over(&l.attrs, &r.attrs, eq_attr) && eq_vis(&l.vis, &r.vis) && eq_kind(&l.kind, &r.kind) + over(&l.attrs, &r.attrs, eq_attr) && eq_vis(&l.vis, &r.vis) && eq_kind(&l.kind, &r.kind) } #[expect(clippy::similar_names, clippy::too_many_lines)] // Just a big match statement pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { use ItemKind::*; match (l, r) { - (ExternCrate(l), ExternCrate(r)) => l == r, + (ExternCrate(ls, li), ExternCrate(rs, ri)) => ls == rs && eq_id(*li, *ri), (Use(l), Use(r)) => eq_use_tree(l, r), ( Static(box StaticItem { + ident: li, ty: lt, mutability: lm, expr: le, @@ -339,16 +340,22 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { define_opaque: _, }), Static(box StaticItem { + ident: ri, ty: rt, mutability: rm, expr: re, safety: rs, define_opaque: _, }), - ) => lm == rm && ls == rs && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()), + ) => eq_id(*li, *ri) + && lm == rm + && ls == rs + && eq_ty(lt, rt) + && eq_expr_opt(le.as_ref(), re.as_ref()), ( Const(box ConstItem { defaultness: ld, + ident: li, generics: lg, ty: lt, expr: le, @@ -356,16 +363,22 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { }), Const(box ConstItem { defaultness: rd, + ident: ri, generics: rg, ty: rt, expr: re, define_opaque: _, }), - ) => eq_defaultness(*ld, *rd) && eq_generics(lg, rg) && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()), + ) => eq_defaultness(*ld, *rd) + && eq_id(*li, *ri) + && eq_generics(lg, rg) + && eq_ty(lt, rt) + && eq_expr_opt(le.as_ref(), re.as_ref()), ( Fn(box ast::Fn { defaultness: ld, sig: lf, + ident: li, generics: lg, contract: lc, body: lb, @@ -374,6 +387,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { Fn(box ast::Fn { defaultness: rd, sig: rf, + ident: ri, generics: rg, contract: rc, body: rb, @@ -382,12 +396,14 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { ) => { eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) + && eq_id(*li, *ri) && eq_generics(lg, rg) && eq_opt_fn_contract(lc, rc) && both(lb.as_ref(), rb.as_ref(), |l, r| eq_block(l, r)) }, - (Mod(lu, lmk), Mod(ru, rmk)) => { - lu == ru + (Mod(ls, li, lmk), Mod(rs, ri, rmk)) => { + ls == rs + && eq_id(*li, *ri) && match (lmk, rmk) { (ModKind::Loaded(litems, linline, _, _), ModKind::Loaded(ritems, rinline, _, _)) => { linline == rinline && over(litems, ritems, |l, r| eq_item(l, r, eq_item_kind)) @@ -421,33 +437,40 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { && over(lb, rb, eq_generic_bound) && both(lt.as_ref(), rt.as_ref(), |l, r| eq_ty(l, r)) }, - (Enum(le, lg), Enum(re, rg)) => over(&le.variants, &re.variants, eq_variant) && eq_generics(lg, rg), - (Struct(lv, lg), Struct(rv, rg)) | (Union(lv, lg), Union(rv, rg)) => { - eq_variant_data(lv, rv) && eq_generics(lg, rg) + (Enum(li, le, lg), Enum(ri, re, rg)) => { + eq_id(*li, *ri) && over(&le.variants, &re.variants, eq_variant) && eq_generics(lg, rg) + } + (Struct(li, lv, lg), Struct(ri, rv, rg)) | (Union(li, lv, lg), Union(ri, rv, rg)) => { + eq_id(*li, *ri) && eq_variant_data(lv, rv) && eq_generics(lg, rg) }, ( Trait(box ast::Trait { is_auto: la, safety: lu, + ident: li, generics: lg, bounds: lb, - items: li, + items: lis, }), Trait(box ast::Trait { is_auto: ra, safety: ru, + ident: ri, generics: rg, bounds: rb, - items: ri, + items: ris, }), ) => { la == ra && matches!(lu, Safety::Default) == matches!(ru, Safety::Default) + && eq_id(*li, *ri) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound) - && over(li, ri, |l, r| eq_item(l, r, eq_assoc_item_kind)) + && over(lis, ris, |l, r| eq_item(l, r, eq_assoc_item_kind)) }, - (TraitAlias(lg, lb), TraitAlias(rg, rb)) => eq_generics(lg, rg) && over(lb, rb, eq_generic_bound), + (TraitAlias(li, lg, lb), TraitAlias(ri, rg, rb)) => { + eq_id(*li, *ri) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound) + } ( Impl(box ast::Impl { safety: lu, @@ -480,7 +503,9 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { && over(li, ri, |l, r| eq_item(l, r, eq_assoc_item_kind)) }, (MacCall(l), MacCall(r)) => eq_mac_call(l, r), - (MacroDef(l), MacroDef(r)) => l.macro_rules == r.macro_rules && eq_delim_args(&l.body, &r.body), + (MacroDef(li, ld), MacroDef(ri, rd)) => { + eq_id(*li, *ri) && ld.macro_rules == rd.macro_rules && eq_delim_args(&ld.body, &rd.body) + } _ => false, } } @@ -490,6 +515,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { match (l, r) { ( Static(box StaticItem { + ident: li, ty: lt, mutability: lm, expr: le, @@ -497,17 +523,25 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { define_opaque: _, }), Static(box StaticItem { + ident: ri, ty: rt, mutability: rm, expr: re, safety: rs, define_opaque: _, }), - ) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()) && ls == rs, + ) => { + eq_id(*li, *ri) + && eq_ty(lt, rt) + && lm == rm + && eq_expr_opt(le.as_ref(), re.as_ref()) + && ls == rs + } ( Fn(box ast::Fn { defaultness: ld, sig: lf, + ident: li, generics: lg, contract: lc, body: lb, @@ -516,6 +550,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { Fn(box ast::Fn { defaultness: rd, sig: rf, + ident: ri, generics: rg, contract: rc, body: rb, @@ -524,6 +559,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { ) => { eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) + && eq_id(*li, *ri) && eq_generics(lg, rg) && eq_opt_fn_contract(lc, rc) && both(lb.as_ref(), rb.as_ref(), |l, r| eq_block(l, r)) @@ -560,6 +596,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { ( Const(box ConstItem { defaultness: ld, + ident: li, generics: lg, ty: lt, expr: le, @@ -567,16 +604,24 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { }), Const(box ConstItem { defaultness: rd, + ident: ri, generics: rg, ty: rt, expr: re, define_opaque: _, }), - ) => eq_defaultness(*ld, *rd) && eq_generics(lg, rg) && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()), + ) => { + eq_defaultness(*ld, *rd) + && eq_id(*li, *ri) + && eq_generics(lg, rg) + && eq_ty(lt, rt) + && eq_expr_opt(le.as_ref(), re.as_ref()) + } ( Fn(box ast::Fn { defaultness: ld, sig: lf, + ident: li, generics: lg, contract: lc, body: lb, @@ -585,6 +630,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { Fn(box ast::Fn { defaultness: rd, sig: rf, + ident: ri, generics: rg, contract: rc, body: rb, @@ -593,6 +639,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { ) => { eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) + && eq_id(*li, *ri) && eq_generics(lg, rg) && eq_opt_fn_contract(lc, rc) && both(lb.as_ref(), rb.as_ref(), |l, r| eq_block(l, r)) diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index fdda885b7298..322af97d9dc4 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -333,12 +333,12 @@ impl<'a> FnSig<'a> { defaultness: ast::Defaultness, ) -> FnSig<'a> { match *fn_kind { - visit::FnKind::Fn(visit::FnCtxt::Assoc(..), _, vis, ast::Fn { sig, generics, .. }) => { + visit::FnKind::Fn(visit::FnCtxt::Assoc(..), vis, ast::Fn { sig, generics, .. }) => { let mut fn_sig = FnSig::from_method_sig(sig, generics, vis); fn_sig.defaultness = defaultness; fn_sig } - visit::FnKind::Fn(_, _, vis, ast::Fn { sig, generics, .. }) => FnSig { + visit::FnKind::Fn(_, vis, ast::Fn { sig, generics, .. }) => FnSig { decl, generics, ext: sig.header.ext, @@ -750,11 +750,10 @@ impl<'a> FmtVisitor<'a> { (Type(lty), Type(rty)) if both_type(<y.ty, &rty.ty) || both_opaque(<y.ty, &rty.ty) => { - a.ident.as_str().cmp(b.ident.as_str()) - } - (Const(..), Const(..)) | (MacCall(..), MacCall(..)) => { - a.ident.as_str().cmp(b.ident.as_str()) + lty.ident.as_str().cmp(rty.ident.as_str()) } + (Const(ca), Const(cb)) => ca.ident.as_str().cmp(cb.ident.as_str()), + (MacCall(..), MacCall(..)) => Ordering::Equal, (Fn(..), Fn(..)) | (Delegation(..), Delegation(..)) => { a.span.lo().cmp(&b.span.lo()) } @@ -1105,14 +1104,16 @@ impl<'a> StructParts<'a> { } pub(crate) fn from_item(item: &'a ast::Item) -> Self { - let (prefix, def, generics) = match item.kind { - ast::ItemKind::Struct(ref def, ref generics) => ("struct ", def, generics), - ast::ItemKind::Union(ref def, ref generics) => ("union ", def, generics), + let (prefix, def, ident, generics) = match item.kind { + ast::ItemKind::Struct(ident, ref def, ref generics) => { + ("struct ", def, ident, generics) + } + ast::ItemKind::Union(ident, ref def, ref generics) => ("union ", def, ident, generics), _ => unreachable!(), }; StructParts { prefix, - ident: item.ident, + ident, vis: &item.vis, def, generics: Some(generics), @@ -1168,6 +1169,7 @@ pub(crate) fn format_trait( let ast::Trait { is_auto, safety, + ident, ref generics, ref bounds, ref items, @@ -1186,13 +1188,13 @@ pub(crate) fn format_trait( let shape = Shape::indented(offset, context.config).offset_left(result.len())?; let generics_str = - rewrite_generics(context, rewrite_ident(context, item.ident), generics, shape).ok()?; + rewrite_generics(context, rewrite_ident(context, ident), generics, shape).ok()?; result.push_str(&generics_str); // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds. if !bounds.is_empty() { // Retrieve *unnormalized* ident (See #6069) - let source_ident = context.snippet(item.ident.span); + let source_ident = context.snippet(ident.span); let ident_hi = context.snippet_provider.span_after(item.span, source_ident); let bound_hi = bounds.last().unwrap().span().hi(); let snippet = context.snippet(mk_sp(ident_hi, bound_hi)); @@ -1699,7 +1701,6 @@ struct TyAliasRewriteInfo<'c, 'g>( pub(crate) fn rewrite_type_alias<'a>( ty_alias_kind: &ast::TyAlias, vis: &ast::Visibility, - ident: Ident, context: &RewriteContext<'a>, indent: Indent, visitor_kind: ItemVisitorKind, @@ -1709,6 +1710,7 @@ pub(crate) fn rewrite_type_alias<'a>( let ast::TyAlias { defaultness, + ident, ref generics, ref bounds, ref ty, @@ -2022,14 +2024,23 @@ pub(crate) struct StaticParts<'a> { impl<'a> StaticParts<'a> { pub(crate) fn from_item(item: &'a ast::Item) -> Self { - let (defaultness, prefix, safety, ty, mutability, expr, generics) = match &item.kind { - ast::ItemKind::Static(s) => { - (None, "static", s.safety, &s.ty, s.mutability, &s.expr, None) - } + let (defaultness, prefix, safety, ident, ty, mutability, expr, generics) = match &item.kind + { + ast::ItemKind::Static(s) => ( + None, + "static", + s.safety, + s.ident, + &s.ty, + s.mutability, + &s.expr, + None, + ), ast::ItemKind::Const(c) => ( Some(c.defaultness), "const", ast::Safety::Default, + c.ident, &c.ty, ast::Mutability::Not, &c.expr, @@ -2041,7 +2052,7 @@ impl<'a> StaticParts<'a> { prefix, safety, vis: &item.vis, - ident: item.ident, + ident, generics, ty, mutability, @@ -2051,7 +2062,7 @@ impl<'a> StaticParts<'a> { } } - pub(crate) fn from_trait_item(ti: &'a ast::AssocItem) -> Self { + pub(crate) fn from_trait_item(ti: &'a ast::AssocItem, ident: Ident) -> Self { let (defaultness, ty, expr_opt, generics) = match &ti.kind { ast::AssocItemKind::Const(c) => (c.defaultness, &c.ty, &c.expr, Some(&c.generics)), _ => unreachable!(), @@ -2060,7 +2071,7 @@ impl<'a> StaticParts<'a> { prefix: "const", safety: ast::Safety::Default, vis: &ti.vis, - ident: ti.ident, + ident, generics, ty, mutability: ast::Mutability::Not, @@ -2070,7 +2081,7 @@ impl<'a> StaticParts<'a> { } } - pub(crate) fn from_impl_item(ii: &'a ast::AssocItem) -> Self { + pub(crate) fn from_impl_item(ii: &'a ast::AssocItem, ident: Ident) -> Self { let (defaultness, ty, expr, generics) = match &ii.kind { ast::AssocItemKind::Const(c) => (c.defaultness, &c.ty, &c.expr, Some(&c.generics)), _ => unreachable!(), @@ -2079,7 +2090,7 @@ impl<'a> StaticParts<'a> { prefix: "const", safety: ast::Safety::Default, vis: &ii.vis, - ident: ii.ident, + ident, generics, ty, mutability: ast::Mutability::Not, @@ -3440,6 +3451,7 @@ impl Rewrite for ast::ForeignItem { let ast::Fn { defaultness, ref sig, + ident, ref generics, ref body, .. @@ -3451,7 +3463,8 @@ impl Rewrite for ast::ForeignItem { let inner_attrs = inner_attributes(&self.attrs); let fn_ctxt = visit::FnCtxt::Foreign; visitor.visit_fn( - visit::FnKind::Fn(fn_ctxt, &self.ident, &self.vis, fn_kind), + ident, + visit::FnKind::Fn(fn_ctxt, &self.vis, fn_kind), &sig.decl, self.span, defaultness, @@ -3462,7 +3475,7 @@ impl Rewrite for ast::ForeignItem { rewrite_fn_base( context, shape.indent, - self.ident, + ident, &FnSig::from_method_sig(sig, generics, &self.vis), span, FnBraceStyle::None, @@ -3481,7 +3494,7 @@ impl Rewrite for ast::ForeignItem { vis, safety, mut_str, - rewrite_ident(context, self.ident) + rewrite_ident(context, static_foreign_item.ident) ); // 1 = ; rewrite_assign_rhs( @@ -3497,15 +3510,7 @@ impl Rewrite for ast::ForeignItem { } ast::ForeignItemKind::TyAlias(ref ty_alias) => { let kind = ItemVisitorKind::ForeignItem; - rewrite_type_alias( - ty_alias, - &self.vis, - self.ident, - context, - shape.indent, - kind, - self.span, - ) + rewrite_type_alias(ty_alias, &self.vis, context, shape.indent, kind, self.span) } ast::ForeignItemKind::MacCall(ref mac) => { rewrite_macro(mac, context, shape, MacroPosition::Item) @@ -3568,12 +3573,13 @@ fn rewrite_attrs( pub(crate) fn rewrite_mod( context: &RewriteContext<'_>, item: &ast::Item, + ident: Ident, attrs_shape: Shape, ) -> Option { let mut result = String::with_capacity(32); result.push_str(&*format_visibility(context, &item.vis)); result.push_str("mod "); - result.push_str(rewrite_ident(context, item.ident)); + result.push_str(rewrite_ident(context, ident)); result.push(';'); rewrite_attrs(context, item, &result, attrs_shape) } @@ -3600,7 +3606,7 @@ pub(crate) fn rewrite_extern_crate( pub(crate) fn is_mod_decl(item: &ast::Item) -> bool { !matches!( item.kind, - ast::ItemKind::Mod(_, ast::ModKind::Loaded(_, ast::Inline::Yes, _, _)) + ast::ItemKind::Mod(_, _, ast::ModKind::Loaded(_, ast::Inline::Yes, _, _)) ) } diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs index a40ee7f66a97..bc5a6d3e7040 100644 --- a/src/tools/rustfmt/src/modules.rs +++ b/src/tools/rustfmt/src/modules.rs @@ -152,7 +152,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> { let mut visitor = visitor::CfgIfVisitor::new(self.psess); visitor.visit_item(&item); for module_item in visitor.mods() { - if let ast::ItemKind::Mod(_, ref sub_mod_kind) = module_item.item.kind { + if let ast::ItemKind::Mod(_, _, ref sub_mod_kind) = module_item.item.kind { self.visit_sub_mod( &module_item.item, Module::new( @@ -178,7 +178,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> { continue; } - if let ast::ItemKind::Mod(_, ref sub_mod_kind) = item.kind { + if let ast::ItemKind::Mod(_, _, ref sub_mod_kind) = item.kind { let span = item.span; self.visit_sub_mod( &item, @@ -204,7 +204,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> { self.visit_cfg_if(Cow::Borrowed(item))?; } - if let ast::ItemKind::Mod(_, ref sub_mod_kind) = item.kind { + if let ast::ItemKind::Mod(_, _, ref sub_mod_kind) = item.kind { let span = item.span; self.visit_sub_mod( item, @@ -248,7 +248,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> { if is_mod_decl(item) { // mod foo; // Look for an extern file. - self.find_external_module(item.ident, &item.attrs, sub_mod) + self.find_external_module(item.kind.ident().unwrap(), &item.attrs, sub_mod) } else { // An internal module (`mod foo { /* ... */ }`); Ok(Some(SubModKind::Internal(item))) @@ -291,7 +291,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> { self.visit_sub_mod_after_directory_update(sub_mod, Some(directory)) } SubModKind::Internal(item) => { - self.push_inline_mod_directory(item.ident, &item.attrs); + self.push_inline_mod_directory(item.kind.ident().unwrap(), &item.attrs); self.visit_sub_mod_after_directory_update(sub_mod, None) } SubModKind::MultiExternal(mods) => { diff --git a/src/tools/rustfmt/src/reorder.rs b/src/tools/rustfmt/src/reorder.rs index 8a31e0ac816e..2460b61698cc 100644 --- a/src/tools/rustfmt/src/reorder.rs +++ b/src/tools/rustfmt/src/reorder.rs @@ -25,14 +25,17 @@ use crate::visitor::FmtVisitor; /// Choose the ordering between the given two items. fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering { match (&a.kind, &b.kind) { - (&ast::ItemKind::Mod(..), &ast::ItemKind::Mod(..)) => { - a.ident.as_str().cmp(b.ident.as_str()) + (&ast::ItemKind::Mod(_, a_ident, _), &ast::ItemKind::Mod(_, b_ident, _)) => { + a_ident.as_str().cmp(b_ident.as_str()) } - (&ast::ItemKind::ExternCrate(ref a_name), &ast::ItemKind::ExternCrate(ref b_name)) => { + ( + &ast::ItemKind::ExternCrate(ref a_name, a_ident), + &ast::ItemKind::ExternCrate(ref b_name, b_ident), + ) => { // `extern crate foo as bar;` // ^^^ Comparing this. - let a_orig_name = a_name.unwrap_or(a.ident.name); - let b_orig_name = b_name.unwrap_or(b.ident.name); + let a_orig_name = a_name.unwrap_or(a_ident.name); + let b_orig_name = b_name.unwrap_or(b_ident.name); let result = a_orig_name.as_str().cmp(b_orig_name.as_str()); if result != Ordering::Equal { return result; @@ -44,7 +47,7 @@ fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering { (Some(..), None) => Ordering::Greater, (None, Some(..)) => Ordering::Less, (None, None) => Ordering::Equal, - (Some(..), Some(..)) => a.ident.as_str().cmp(b.ident.as_str()), + (Some(..), Some(..)) => a_ident.as_str().cmp(b_ident.as_str()), } } _ => unreachable!(), @@ -69,7 +72,7 @@ fn rewrite_reorderable_item( ) -> Option { match item.kind { ast::ItemKind::ExternCrate(..) => rewrite_extern_crate(context, item, shape), - ast::ItemKind::Mod(..) => rewrite_mod(context, item, shape), + ast::ItemKind::Mod(_, ident, _) => rewrite_mod(context, item, ident, shape), _ => None, } } diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index c73976d90b1e..1dc0a9069231 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -377,6 +377,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // on traits do not get handled here. pub(crate) fn visit_fn( &mut self, + ident: Ident, fk: visit::FnKind<'_>, fd: &ast::FnDecl, s: Span, @@ -388,7 +389,6 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let rewrite = match fk { visit::FnKind::Fn( _, - ident, _, ast::Fn { body: Some(ref b), .. @@ -397,7 +397,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { block = b; self.rewrite_fn_before_block( indent, - *ident, + ident, &FnSig::from_fn_kind(&fk, fd, defaultness), mk_sp(s.lo(), b.span.lo()), ) @@ -444,7 +444,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let should_visit_node_again = match item.kind { // For use/extern crate items, skip rewriting attributes but check for a skip attribute. - ast::ItemKind::Use(..) | ast::ItemKind::ExternCrate(_) => { + ast::ItemKind::Use(..) | ast::ItemKind::ExternCrate(..) => { if contains_skip(attrs) { self.push_skipped_with_span(attrs.as_slice(), item.span(), item.span()); false @@ -497,11 +497,11 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let rw = self.with_context(|ctx| format_trait(ctx, item, block_indent)); self.push_rewrite(item.span, rw); } - ast::ItemKind::TraitAlias(ref generics, ref generic_bounds) => { + ast::ItemKind::TraitAlias(ident, ref generics, ref generic_bounds) => { let shape = Shape::indented(self.block_indent, self.config); let rw = format_trait_alias( &self.get_context(), - item.ident, + ident, &item.vis, generics, generic_bounds, @@ -509,7 +509,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ); self.push_rewrite(item.span, rw); } - ast::ItemKind::ExternCrate(_) => { + ast::ItemKind::ExternCrate(..) => { let rw = rewrite_extern_crate(&self.get_context(), item, self.shape()); let span = if attrs.is_empty() { item.span @@ -521,14 +521,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ast::ItemKind::Struct(..) | ast::ItemKind::Union(..) => { self.visit_struct(&StructParts::from_item(item)); } - ast::ItemKind::Enum(ref def, ref generics) => { + ast::ItemKind::Enum(ident, ref def, ref generics) => { self.format_missing_with_indent(source!(self, item.span).lo()); - self.visit_enum(item.ident, &item.vis, def, generics, item.span); + self.visit_enum(ident, &item.vis, def, generics, item.span); self.last_pos = source!(self, item.span).hi(); } - ast::ItemKind::Mod(safety, ref mod_kind) => { + ast::ItemKind::Mod(safety, ident, ref mod_kind) => { self.format_missing_with_indent(source!(self, item.span).lo()); - self.format_mod(mod_kind, safety, &item.vis, item.span, item.ident, attrs); + self.format_mod(mod_kind, safety, &item.vis, item.span, ident, attrs); } ast::ItemKind::MacCall(ref mac) => { self.visit_mac(mac, MacroPosition::Item); @@ -544,6 +544,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let ast::Fn { defaultness, ref sig, + ident, ref generics, ref body, .. @@ -555,7 +556,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { _ => visit::FnCtxt::Foreign, }; self.visit_fn( - visit::FnKind::Fn(fn_ctxt, &item.ident, &item.vis, fn_kind), + ident, + visit::FnKind::Fn(fn_ctxt, &item.vis, fn_kind), &sig.decl, item.span, defaultness, @@ -564,28 +566,26 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } else { let indent = self.block_indent; let rewrite = self - .rewrite_required_fn( - indent, item.ident, sig, &item.vis, generics, item.span, - ) + .rewrite_required_fn(indent, ident, sig, &item.vis, generics, item.span) .ok(); self.push_rewrite(item.span, rewrite); } } ast::ItemKind::TyAlias(ref ty_alias) => { use ItemVisitorKind::Item; - self.visit_ty_alias_kind(ty_alias, &item.vis, item.ident, Item, item.span); + self.visit_ty_alias_kind(ty_alias, &item.vis, Item, item.span); } ast::ItemKind::GlobalAsm(..) => { let snippet = Some(self.snippet(item.span).to_owned()); self.push_rewrite(item.span, snippet); } - ast::ItemKind::MacroDef(ref def) => { + ast::ItemKind::MacroDef(ident, ref def) => { let rewrite = rewrite_macro_def( &self.get_context(), self.shape(), self.block_indent, def, - item.ident, + ident, &item.vis, item.span, ) @@ -606,14 +606,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { &mut self, ty_kind: &ast::TyAlias, vis: &ast::Visibility, - ident: Ident, visitor_kind: ItemVisitorKind, span: Span, ) { let rewrite = rewrite_type_alias( ty_kind, vis, - ident, &self.get_context(), self.block_indent, visitor_kind, @@ -642,16 +640,17 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // TODO(calebcartwright): consider enabling box_patterns feature gate match (&ai.kind, visitor_kind) { - (ast::AssocItemKind::Const(..), AssocTraitItem) => { - self.visit_static(&StaticParts::from_trait_item(ai)) + (ast::AssocItemKind::Const(c), AssocTraitItem) => { + self.visit_static(&StaticParts::from_trait_item(ai, c.ident)) } - (ast::AssocItemKind::Const(..), AssocImplItem) => { - self.visit_static(&StaticParts::from_impl_item(ai)) + (ast::AssocItemKind::Const(c), AssocImplItem) => { + self.visit_static(&StaticParts::from_impl_item(ai, c.ident)) } (ast::AssocItemKind::Fn(ref fn_kind), _) => { let ast::Fn { defaultness, ref sig, + ident, ref generics, ref body, .. @@ -660,7 +659,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let inner_attrs = inner_attributes(&ai.attrs); let fn_ctxt = visit::FnCtxt::Assoc(assoc_ctxt); self.visit_fn( - visit::FnKind::Fn(fn_ctxt, &ai.ident, &ai.vis, fn_kind), + ident, + visit::FnKind::Fn(fn_ctxt, &ai.vis, fn_kind), &sig.decl, ai.span, defaultness, @@ -669,13 +669,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } else { let indent = self.block_indent; let rewrite = self - .rewrite_required_fn(indent, ai.ident, sig, &ai.vis, generics, ai.span) + .rewrite_required_fn(indent, fn_kind.ident, sig, &ai.vis, generics, ai.span) .ok(); self.push_rewrite(ai.span, rewrite); } } (ast::AssocItemKind::Type(ref ty_alias), _) => { - self.visit_ty_alias_kind(ty_alias, &ai.vis, ai.ident, visitor_kind, ai.span); + self.visit_ty_alias_kind(ty_alias, &ai.vis, visitor_kind, ai.span); } (ast::AssocItemKind::MacCall(ref mac), _) => { self.visit_mac(mac, MacroPosition::Item); diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr index 191daff2137d..24e389486478 100644 --- a/tests/ui/stats/input-stats.stderr +++ b/tests/ui/stats/input-stats.stderr @@ -10,9 +10,9 @@ ast-stats-1 - DocComment 32 ( 0.5%) 1 ast-stats-1 - Normal 32 ( 0.5%) 1 ast-stats-1 WherePredicate 72 ( 1.1%) 1 72 ast-stats-1 - BoundPredicate 72 ( 1.1%) 1 +ast-stats-1 ForeignItem 80 ( 1.2%) 1 80 +ast-stats-1 - Fn 80 ( 1.2%) 1 ast-stats-1 Local 80 ( 1.2%) 1 80 -ast-stats-1 ForeignItem 88 ( 1.3%) 1 88 -ast-stats-1 - Fn 88 ( 1.3%) 1 ast-stats-1 Arm 96 ( 1.4%) 2 48 ast-stats-1 FnDecl 120 ( 1.8%) 5 24 ast-stats-1 Param 160 ( 2.4%) 4 40 @@ -23,37 +23,37 @@ ast-stats-1 - Expr 96 ( 1.4%) 3 ast-stats-1 Block 192 ( 2.9%) 6 32 ast-stats-1 FieldDef 208 ( 3.1%) 2 104 ast-stats-1 Variant 208 ( 3.1%) 2 104 -ast-stats-1 AssocItem 352 ( 5.3%) 4 88 -ast-stats-1 - Fn 176 ( 2.6%) 2 -ast-stats-1 - Type 176 ( 2.6%) 2 -ast-stats-1 GenericBound 352 ( 5.3%) 4 88 -ast-stats-1 - Trait 352 ( 5.3%) 4 -ast-stats-1 GenericParam 480 ( 7.2%) 5 96 +ast-stats-1 AssocItem 320 ( 4.8%) 4 80 +ast-stats-1 - Fn 160 ( 2.4%) 2 +ast-stats-1 - Type 160 ( 2.4%) 2 +ast-stats-1 GenericBound 352 ( 5.2%) 4 88 +ast-stats-1 - Trait 352 ( 5.2%) 4 +ast-stats-1 GenericParam 480 ( 7.1%) 5 96 ast-stats-1 Pat 504 ( 7.5%) 7 72 ast-stats-1 - Struct 72 ( 1.1%) 1 ast-stats-1 - Wild 72 ( 1.1%) 1 -ast-stats-1 - Ident 360 ( 5.4%) 5 +ast-stats-1 - Ident 360 ( 5.3%) 5 ast-stats-1 Expr 576 ( 8.6%) 8 72 ast-stats-1 - Match 72 ( 1.1%) 1 ast-stats-1 - Path 72 ( 1.1%) 1 ast-stats-1 - Struct 72 ( 1.1%) 1 ast-stats-1 - Lit 144 ( 2.1%) 2 ast-stats-1 - Block 216 ( 3.2%) 3 -ast-stats-1 PathSegment 744 (11.1%) 31 24 -ast-stats-1 Ty 896 (13.4%) 14 64 +ast-stats-1 PathSegment 744 (11.0%) 31 24 +ast-stats-1 Ty 896 (13.3%) 14 64 ast-stats-1 - Ptr 64 ( 1.0%) 1 ast-stats-1 - Ref 64 ( 1.0%) 1 ast-stats-1 - ImplicitSelf 128 ( 1.9%) 2 ast-stats-1 - Path 640 ( 9.5%) 10 -ast-stats-1 Item 1_224 (18.3%) 9 136 -ast-stats-1 - Enum 136 ( 2.0%) 1 -ast-stats-1 - ForeignMod 136 ( 2.0%) 1 -ast-stats-1 - Impl 136 ( 2.0%) 1 -ast-stats-1 - Trait 136 ( 2.0%) 1 -ast-stats-1 - Fn 272 ( 4.1%) 2 -ast-stats-1 - Use 408 ( 6.1%) 3 +ast-stats-1 Item 1_296 (19.2%) 9 144 +ast-stats-1 - Enum 144 ( 2.1%) 1 +ast-stats-1 - ForeignMod 144 ( 2.1%) 1 +ast-stats-1 - Impl 144 ( 2.1%) 1 +ast-stats-1 - Trait 144 ( 2.1%) 1 +ast-stats-1 - Fn 288 ( 4.3%) 2 +ast-stats-1 - Use 432 ( 6.4%) 3 ast-stats-1 ---------------------------------------------------------------- -ast-stats-1 Total 6_704 116 +ast-stats-1 Total 6_736 116 ast-stats-1 ast-stats-2 POST EXPANSION AST STATS ast-stats-2 Name Accumulated Size Count Item Size @@ -61,12 +61,12 @@ ast-stats-2 ---------------------------------------------------------------- ast-stats-2 Crate 40 ( 0.5%) 1 40 ast-stats-2 GenericArgs 40 ( 0.5%) 1 40 ast-stats-2 - AngleBracketed 40 ( 0.5%) 1 -ast-stats-2 ExprField 48 ( 0.7%) 1 48 +ast-stats-2 ExprField 48 ( 0.6%) 1 48 ast-stats-2 WherePredicate 72 ( 1.0%) 1 72 ast-stats-2 - BoundPredicate 72 ( 1.0%) 1 +ast-stats-2 ForeignItem 80 ( 1.1%) 1 80 +ast-stats-2 - Fn 80 ( 1.1%) 1 ast-stats-2 Local 80 ( 1.1%) 1 80 -ast-stats-2 ForeignItem 88 ( 1.2%) 1 88 -ast-stats-2 - Fn 88 ( 1.2%) 1 ast-stats-2 Arm 96 ( 1.3%) 2 48 ast-stats-2 FnDecl 120 ( 1.6%) 5 24 ast-stats-2 InlineAsm 120 ( 1.6%) 1 120 @@ -81,13 +81,13 @@ ast-stats-2 - Expr 96 ( 1.3%) 3 ast-stats-2 Block 192 ( 2.6%) 6 32 ast-stats-2 FieldDef 208 ( 2.8%) 2 104 ast-stats-2 Variant 208 ( 2.8%) 2 104 -ast-stats-2 AssocItem 352 ( 4.8%) 4 88 -ast-stats-2 - Fn 176 ( 2.4%) 2 -ast-stats-2 - Type 176 ( 2.4%) 2 +ast-stats-2 AssocItem 320 ( 4.3%) 4 80 +ast-stats-2 - Fn 160 ( 2.2%) 2 +ast-stats-2 - Type 160 ( 2.2%) 2 ast-stats-2 GenericBound 352 ( 4.8%) 4 88 ast-stats-2 - Trait 352 ( 4.8%) 4 ast-stats-2 GenericParam 480 ( 6.5%) 5 96 -ast-stats-2 Pat 504 ( 6.9%) 7 72 +ast-stats-2 Pat 504 ( 6.8%) 7 72 ast-stats-2 - Struct 72 ( 1.0%) 1 ast-stats-2 - Wild 72 ( 1.0%) 1 ast-stats-2 - Ident 360 ( 4.9%) 5 @@ -96,24 +96,24 @@ ast-stats-2 - InlineAsm 72 ( 1.0%) 1 ast-stats-2 - Match 72 ( 1.0%) 1 ast-stats-2 - Path 72 ( 1.0%) 1 ast-stats-2 - Struct 72 ( 1.0%) 1 -ast-stats-2 - Lit 144 ( 2.0%) 2 +ast-stats-2 - Lit 144 ( 1.9%) 2 ast-stats-2 - Block 216 ( 2.9%) 3 -ast-stats-2 PathSegment 864 (11.8%) 36 24 -ast-stats-2 Ty 896 (12.2%) 14 64 +ast-stats-2 PathSegment 864 (11.7%) 36 24 +ast-stats-2 Ty 896 (12.1%) 14 64 ast-stats-2 - Ptr 64 ( 0.9%) 1 ast-stats-2 - Ref 64 ( 0.9%) 1 ast-stats-2 - ImplicitSelf 128 ( 1.7%) 2 -ast-stats-2 - Path 640 ( 8.7%) 10 -ast-stats-2 Item 1_496 (20.3%) 11 136 -ast-stats-2 - Enum 136 ( 1.8%) 1 -ast-stats-2 - ExternCrate 136 ( 1.8%) 1 -ast-stats-2 - ForeignMod 136 ( 1.8%) 1 -ast-stats-2 - Impl 136 ( 1.8%) 1 -ast-stats-2 - Trait 136 ( 1.8%) 1 -ast-stats-2 - Fn 272 ( 3.7%) 2 -ast-stats-2 - Use 544 ( 7.4%) 4 +ast-stats-2 - Path 640 ( 8.6%) 10 +ast-stats-2 Item 1_584 (21.4%) 11 144 +ast-stats-2 - Enum 144 ( 1.9%) 1 +ast-stats-2 - ExternCrate 144 ( 1.9%) 1 +ast-stats-2 - ForeignMod 144 ( 1.9%) 1 +ast-stats-2 - Impl 144 ( 1.9%) 1 +ast-stats-2 - Trait 144 ( 1.9%) 1 +ast-stats-2 - Fn 288 ( 3.9%) 2 +ast-stats-2 - Use 576 ( 7.8%) 4 ast-stats-2 ---------------------------------------------------------------- -ast-stats-2 Total 7_352 127 +ast-stats-2 Total 7_400 127 ast-stats-2 hir-stats HIR STATS hir-stats Name Accumulated Size Count Item Size From ec10833609aa63327437aabfaedfbe8a0edcc4d9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 1 Apr 2025 14:49:58 +1100 Subject: [PATCH 710/745] Address review comments. --- .../rustc_ast_passes/src/ast_validation.rs | 16 ++-- .../src/proc_macro_harness.rs | 7 +- compiler/rustc_expand/src/expand.rs | 4 +- compiler/rustc_parse/src/parser/item.rs | 33 ++++--- .../rustc_resolve/src/build_reduced_graph.rs | 85 ++++++++++--------- compiler/rustc_resolve/src/def_collector.rs | 5 +- compiler/rustc_resolve/src/late.rs | 5 +- .../rustc_resolve/src/late/diagnostics.rs | 10 +-- .../clippy_lints/src/empty_line_after.rs | 15 ++-- .../clippy/clippy_utils/src/ast_utils/mod.rs | 14 ++- src/tools/rustfmt/src/visitor.rs | 2 +- tests/ui/custom_test_frameworks/full.rs | 7 +- 12 files changed, 104 insertions(+), 99 deletions(-) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 86661f3f3590..839d5d3bb954 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -817,10 +817,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.has_proc_macro_decls = true; } - if attr::contains_name(&item.attrs, sym::no_mangle) { - if let Some(ident) = item.kind.ident() { - self.check_nomangle_item_asciionly(ident, item.span); - } + if let Some(ident) = item.kind.ident() + && attr::contains_name(&item.attrs, sym::no_mangle) + { + self.check_nomangle_item_asciionly(ident, item.span); } match &item.kind { @@ -1412,10 +1412,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) { - if attr::contains_name(&item.attrs, sym::no_mangle) { - if let Some(ident) = item.kind.ident() { - self.check_nomangle_item_asciionly(ident, item.span); - } + if let Some(ident) = item.kind.ident() + && attr::contains_name(&item.attrs, sym::no_mangle) + { + self.check_nomangle_item_asciionly(ident, item.span); } if ctxt == AssocCtxt::Trait || self.outer_trait_or_trait_impl.is_none() { diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index 7c25f26895ca..8862965c0532 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -213,10 +213,8 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { return; }; - // First up, make sure we're checking a bare function. If we're not then - // we're just not interested in this item. - // - // If we find one, try to locate a `#[proc_macro_derive]` attribute on it. + // Make sure we're checking a bare function. If we're not then we're + // just not interested any further in this item. let fn_ident = if let ast::ItemKind::Fn(fn_) = &item.kind { fn_.ident } else { @@ -243,6 +241,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { return; } + // Try to locate a `#[proc_macro_derive]` attribute. if attr.has_name(sym::proc_macro_derive) { self.collect_custom_derive(item, fn_ident, attr); } else if attr.has_name(sym::proc_macro_attribute) { diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index d1dd454fa73d..bca846d2ec42 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1223,9 +1223,7 @@ impl InvocationCollectorNode for P { // Work around borrow checker not seeing through `P`'s deref. let (span, mut attrs) = (node.span, mem::take(&mut node.attrs)); - let ItemKind::Mod(_, ident, mod_kind) = &mut node.kind else { unreachable!() }; - let ident = *ident; - + let ItemKind::Mod(_, ident, ref mut mod_kind) = node.kind else { unreachable!() }; let ecx = &mut collector.cx; let (file_path, dir_path, dir_ownership) = match mod_kind { ModKind::Loaded(_, inline, _, _) => { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index ed6522850960..e93fb2473fbf 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -243,8 +243,7 @@ impl<'a> Parser<'a> { // STATIC ITEM self.bump(); // `static` let mutability = self.parse_mutability(); - let item = self.parse_static_item(safety, mutability)?; - ItemKind::Static(Box::new(item)) + self.parse_static_item(safety, mutability)? } else if let Const::Yes(const_span) = self.parse_constness(Case::Sensitive) { // CONST ITEM if self.token.is_keyword(kw::Impl) { @@ -681,7 +680,7 @@ impl<'a> Parser<'a> { } None => (None, ty_first), // impl Type }; - let item_kind = ItemKind::Impl(Box::new(Impl { + Ok(ItemKind::Impl(Box::new(Impl { safety, polarity, defaultness, @@ -690,9 +689,7 @@ impl<'a> Parser<'a> { of_trait, self_ty, items: impl_items, - })); - - Ok(item_kind) + }))) } fn parse_item_delegation(&mut self) -> PResult<'a, ItemKind> { @@ -1222,13 +1219,12 @@ impl<'a> Parser<'a> { safety = Safety::Unsafe(self.token.span); let _ = self.eat_keyword(exp!(Unsafe)); } - let module = ast::ForeignMod { + Ok(ItemKind::ForeignMod(ast::ForeignMod { extern_span, safety, abi, items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?, - }; - Ok(ItemKind::ForeignMod(module)) + })) } /// Parses a foreign item (one in an `extern { ... }` block). @@ -1370,7 +1366,8 @@ impl<'a> Parser<'a> { Ok(item_kind) } - /// Parse a static item with the prefix `"static" "mut"?` already parsed and stored in `mutability`. + /// Parse a static item with the prefix `"static" "mut"?` already parsed and stored in + /// `mutability`. /// /// ```ebnf /// Static = "static" "mut"? $ident ":" $ty (= $expr)? ";" ; @@ -1379,7 +1376,7 @@ impl<'a> Parser<'a> { &mut self, safety: Safety, mutability: Mutability, - ) -> PResult<'a, StaticItem> { + ) -> PResult<'a, ItemKind> { let ident = self.parse_ident()?; if self.token == TokenKind::Lt && self.may_recover() { @@ -1391,7 +1388,8 @@ impl<'a> Parser<'a> { // FIXME: This could maybe benefit from `.may_recover()`? let ty = match (self.eat(exp!(Colon)), self.check(exp!(Eq)) | self.check(exp!(Semi))) { (true, false) => self.parse_ty()?, - // If there wasn't a `:` or the colon was followed by a `=` or `;`, recover a missing type. + // If there wasn't a `:` or the colon was followed by a `=` or `;`, recover a missing + // type. (colon, _) => self.recover_missing_global_item_type(colon, Some(mutability)), }; @@ -1399,7 +1397,8 @@ impl<'a> Parser<'a> { self.expect_semi()?; - Ok(StaticItem { ident, ty, safety, mutability, expr, define_opaque: None }) + let item = StaticItem { ident, ty, safety, mutability, expr, define_opaque: None }; + Ok(ItemKind::Static(Box::new(item))) } /// Parse a constant item with the prefix `"const"` already parsed. @@ -1537,7 +1536,7 @@ impl<'a> Parser<'a> { } let prev_span = self.prev_token.span; - let id = self.parse_ident()?; + let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; generics.where_clause = self.parse_where_clause()?; @@ -1548,10 +1547,10 @@ impl<'a> Parser<'a> { (thin_vec![], Trailing::No) } else { self.parse_delim_comma_seq(exp!(OpenBrace), exp!(CloseBrace), |p| { - p.parse_enum_variant(id.span) + p.parse_enum_variant(ident.span) }) .map_err(|mut err| { - err.span_label(id.span, "while parsing this enum"); + err.span_label(ident.span, "while parsing this enum"); if self.token == token::Colon { let snapshot = self.create_snapshot_for_diagnostic(); self.bump(); @@ -1577,7 +1576,7 @@ impl<'a> Parser<'a> { }; let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() }; - Ok(ItemKind::Enum(id, enum_definition, generics)) + Ok(ItemKind::Enum(ident, enum_definition, generics)) } fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option> { diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 7f29f1a084e6..4368f7882ff4 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -10,8 +10,8 @@ use std::sync::Arc; use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind}; use rustc_ast::{ - self as ast, AssocItem, AssocItemKind, Block, ConstItem, Delegation, ForeignItem, - ForeignItemKind, Impl, Item, ItemKind, MetaItemKind, NodeId, StaticItem, StmtKind, + self as ast, AssocItem, AssocItemKind, Block, ConstItem, Delegation, Fn, ForeignItem, + ForeignItemKind, Impl, Item, ItemKind, MetaItemKind, NodeId, StaticItem, StmtKind, TyAlias, }; use rustc_attr_parsing as attr; use rustc_expand::base::ResolverExpand; @@ -764,8 +764,8 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { ItemKind::ExternCrate(orig_name, ident) => { self.build_reduced_graph_for_extern_crate( orig_name, - ident, item, + ident, local_def_id, vis, parent, @@ -797,7 +797,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { | ItemKind::Static(box StaticItem { ident, .. }) => { self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion)); } - ItemKind::Fn(box ast::Fn { ident, .. }) => { + ItemKind::Fn(box Fn { ident, .. }) => { self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion)); // Functions introducing procedural macros reserve a slot @@ -806,7 +806,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } // These items live in the type namespace. - ItemKind::TyAlias(box ast::TyAlias { ident, .. }) | ItemKind::TraitAlias(ident, ..) => { + ItemKind::TyAlias(box TyAlias { ident, .. }) | ItemKind::TraitAlias(ident, ..) => { self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); } @@ -900,8 +900,8 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { fn build_reduced_graph_for_extern_crate( &mut self, orig_name: Option, - ident: Ident, item: &Item, + ident: Ident, local_def_id: LocalDefId, vis: ty::Visibility, parent: Module<'ra>, @@ -1362,14 +1362,16 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) { - if let ForeignItemKind::MacCall(_) = foreign_item.kind { - self.visit_invoc_in_module(foreign_item.id); - return; - } + let ident = match foreign_item.kind { + ForeignItemKind::Static(box StaticItem { ident, .. }) + | ForeignItemKind::Fn(box Fn { ident, .. }) + | ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => ident, + ForeignItemKind::MacCall(_) => { + self.visit_invoc_in_module(foreign_item.id); + return; + } + }; - // `unwrap` is safe because `MacCall` has been excluded, and other foreign item kinds have - // an ident. - let ident = foreign_item.kind.ident().unwrap(); self.build_reduced_graph_for_foreign_item(foreign_item, ident); visit::walk_item(self, foreign_item); } @@ -1384,26 +1386,35 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) { - if let AssocItemKind::MacCall(_) = item.kind { - match ctxt { - AssocCtxt::Trait => { - self.visit_invoc_in_module(item.id); - } - AssocCtxt::Impl { .. } => { - let invoc_id = item.id.placeholder_to_expn_id(); - if !self.r.glob_delegation_invoc_ids.contains(&invoc_id) { - self.r - .impl_unexpanded_invocations - .entry(self.r.invocation_parent(invoc_id)) - .or_default() - .insert(invoc_id); - } - self.visit_invoc(item.id); - } - } - return; - } + let (ident, ns) = match item.kind { + AssocItemKind::Const(box ConstItem { ident, .. }) + | AssocItemKind::Fn(box Fn { ident, .. }) + | AssocItemKind::Delegation(box Delegation { ident, .. }) => (ident, ValueNS), + AssocItemKind::Type(box TyAlias { ident, .. }) => (ident, TypeNS), + + AssocItemKind::MacCall(_) => { + match ctxt { + AssocCtxt::Trait => { + self.visit_invoc_in_module(item.id); + } + AssocCtxt::Impl { .. } => { + let invoc_id = item.id.placeholder_to_expn_id(); + if !self.r.glob_delegation_invoc_ids.contains(&invoc_id) { + self.r + .impl_unexpanded_invocations + .entry(self.r.invocation_parent(invoc_id)) + .or_default() + .insert(invoc_id); + } + self.visit_invoc(item.id); + } + } + return; + } + + AssocItemKind::DelegationMac(..) => bug!(), + }; let vis = self.resolve_visibility(&item.vis); let feed = self.r.feed(item.id); let local_def_id = feed.key(); @@ -1418,16 +1429,6 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { self.r.feed_visibility(feed, vis); } - let ns = match item.kind { - AssocItemKind::Const(..) | AssocItemKind::Delegation(..) | AssocItemKind::Fn(..) => { - ValueNS - } - AssocItemKind::Type(..) => TypeNS, - AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => bug!(), // handled above - }; - // `unwrap` is safe because `MacCall`/`DelegationMac` have been excluded, and other foreign - // item kinds have an ident. - let ident = item.kind.ident().unwrap(); if ctxt == AssocCtxt::Trait { let parent = self.parent_scope.module; let expansion = self.parent_scope.expansion; diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 6ad056edbaf8..13dfb59f27fc 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -186,8 +186,11 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { FnKind::Fn( _ctxt, _vis, - Fn { sig: FnSig { header, decl, span: _ }, generics, contract, body, .. }, + Fn { + sig: FnSig { header, decl, span: _ }, ident, generics, contract, body, .. + }, ) if let Some(coroutine_kind) = header.coroutine_kind => { + self.visit_ident(ident); self.visit_fn_header(header); self.visit_generics(generics); if let Some(contract) = contract { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index d4dd0800452a..20e19caf9096 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1025,9 +1025,10 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r match fn_kind { // Bail if the function is foreign, and thus cannot validly have // a body, or if there's no body for some other reason. - FnKind::Fn(FnCtxt::Foreign, _, Fn { sig, generics, .. }) - | FnKind::Fn(_, _, Fn { sig, generics, body: None, .. }) => { + FnKind::Fn(FnCtxt::Foreign, _, Fn { sig, ident, generics, .. }) + | FnKind::Fn(_, _, Fn { sig, ident, generics, body: None, .. }) => { self.visit_fn_header(&sig.header); + self.visit_ident(ident); self.visit_generics(generics); self.with_lifetime_rib( LifetimeRibKind::AnonymousCreateParameter { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 2a2b1ecef161..b62bc6c45e0c 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -227,14 +227,10 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = fn_kind && let Some(items) = self.diag_metadata.current_impl_items && let Some(item) = items.iter().find(|i| { - if let Some(ident) = i.kind.ident() - && ident.name == item_str.name - { + i.kind.ident().is_some_and(|ident| { // Don't suggest if the item is in Fn signature arguments (#112590). - !sig.span.contains(item_span) - } else { - false - } + ident.name == item_str.name && !sig.span.contains(item_span) + }) }) { let sp = item_span.shrink_to_lo(); diff --git a/src/tools/clippy/clippy_lints/src/empty_line_after.rs b/src/tools/clippy/clippy_lints/src/empty_line_after.rs index 899b5c595261..c67dcd3c82b5 100644 --- a/src/tools/clippy/clippy_lints/src/empty_line_after.rs +++ b/src/tools/clippy/clippy_lints/src/empty_line_after.rs @@ -8,8 +8,7 @@ use rustc_errors::{Applicability, Diag, SuggestionStyle}; use rustc_lexer::TokenKind; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::impl_lint_pass; -use rustc_span::symbol::kw; -use rustc_span::{BytePos, ExpnKind, Ident, InnerSpan, Span, SpanData, Symbol, sym}; +use rustc_span::{BytePos, ExpnKind, Ident, InnerSpan, Span, SpanData, Symbol, kw}; declare_clippy_lint! { /// ### What it does @@ -375,14 +374,16 @@ impl EmptyLineAfter { &mut self, cx: &EarlyContext<'_>, kind: &ItemKind, - ident: &Option, + ident: Option, span: Span, attrs: &[Attribute], id: NodeId, ) { self.items.push(ItemInfo { kind: kind.descr(), - name: if let Some(ident) = ident { ident.name } else { sym::dummy }, + // FIXME: this `sym::empty` can be leaked, see + // https://github.com/rust-lang/rust/pull/138740#discussion_r2021979899 + name: if let Some(ident) = ident { ident.name } else { kw::Empty }, span: if let Some(ident) = ident { span.with_hi(ident.span.hi()) } else { @@ -471,7 +472,7 @@ impl EarlyLintPass for EmptyLineAfter { self.check_item_kind( cx, &item.kind.clone().into(), - &item.kind.ident(), + item.kind.ident(), item.span, &item.attrs, item.id, @@ -482,7 +483,7 @@ impl EarlyLintPass for EmptyLineAfter { self.check_item_kind( cx, &item.kind.clone().into(), - &item.kind.ident(), + item.kind.ident(), item.span, &item.attrs, item.id, @@ -490,6 +491,6 @@ impl EarlyLintPass for EmptyLineAfter { } fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - self.check_item_kind(cx, &item.kind, &item.kind.ident(), item.span, &item.attrs, item.id); + self.check_item_kind(cx, &item.kind, item.kind.ident(), item.span, &item.attrs, item.id); } } diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs index ff63eb505a5c..eba576392ebc 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs @@ -567,20 +567,23 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { ( TyAlias(box ast::TyAlias { defaultness: ld, + ident: li, generics: lg, + where_clauses: _, bounds: lb, ty: lt, - .. }), TyAlias(box ast::TyAlias { defaultness: rd, + ident: ri, generics: rg, + where_clauses: _, bounds: rb, ty: rt, - .. }), ) => { eq_defaultness(*ld, *rd) + && eq_id(*li, *ri) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound) && both(lt.as_ref(), rt.as_ref(), |l, r| eq_ty(l, r)) @@ -647,20 +650,23 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { ( Type(box TyAlias { defaultness: ld, + ident: li, generics: lg, + where_clauses: _, bounds: lb, ty: lt, - .. }), Type(box TyAlias { defaultness: rd, + ident: ri, generics: rg, + where_clauses: _, bounds: rb, ty: rt, - .. }), ) => { eq_defaultness(*ld, *rd) + && eq_id(*li, *ri) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound) && both(lt.as_ref(), rt.as_ref(), |l, r| eq_ty(l, r)) diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index 1dc0a9069231..16d1f5105d5f 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -623,13 +623,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { fn visit_assoc_item(&mut self, ai: &ast::AssocItem, visitor_kind: ItemVisitorKind) { use ItemVisitorKind::*; - // TODO(calebcartwright): Not sure the skip spans are correct let assoc_ctxt = match visitor_kind { AssocTraitItem => visit::AssocCtxt::Trait, // There is no difference between trait and inherent assoc item formatting AssocImplItem => visit::AssocCtxt::Impl { of_trait: false }, _ => unreachable!(), }; + // TODO(calebcartwright): Not sure the skip spans are correct let skip_span = ai.span; skip_out_of_file_lines_range_visitor!(self, ai.span); diff --git a/tests/ui/custom_test_frameworks/full.rs b/tests/ui/custom_test_frameworks/full.rs index 6be29f0418d6..57b55e9437bf 100644 --- a/tests/ui/custom_test_frameworks/full.rs +++ b/tests/ui/custom_test_frameworks/full.rs @@ -28,12 +28,13 @@ const TEST_1: IsFoo = IsFoo("hello"); static TEST_2: IsFoo = IsFoo("foo"); // FIXME: `test_case` is currently ignored on anything other than -// fn/const/static. Should this be a warning/error? +// fn/const/static. This should be an error. Compare this with `#[test]` and +// #[bench] whose expanders emit "error: expected a non-associated function, +// found […]" if applied to invalid items. #[test_case] struct _S; -// FIXME: `test_case` is currently ignored on anything other than -// fn/const/static. Should this be a warning/error? +// FIXME: as above. #[test_case] impl _S { fn _f() {} From cb7ebf6f05a08a3dc7d2562eed1a3e3c5523ff3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 1 Apr 2025 07:57:05 +0200 Subject: [PATCH 711/745] Bump metadata version --- compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index bbdc986ef7a2..f4cf338ffb5d 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -56,7 +56,7 @@ pub(crate) fn rustc_version(cfg_version: &'static str) -> String { /// Metadata encoding version. /// N.B., increment this if you change the format of metadata such that /// the rustc version can't be found to compare with `rustc_version()`. -const METADATA_VERSION: u8 = 9; +const METADATA_VERSION: u8 = 10; /// Metadata header which includes `METADATA_VERSION`. /// From 27b866d59a3e5ccbaf9723a37d353db6d2079f16 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Tue, 1 Apr 2025 13:22:45 +0800 Subject: [PATCH 712/745] Add ui test ui/traits/object/suggestion-trait-object-issue-139174.rs Signed-off-by: xizheyin --- .../suggestion-trait-object-issue-139174.rs | 24 ++++++++ ...uggestion-trait-object-issue-139174.stderr | 55 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 tests/ui/traits/object/suggestion-trait-object-issue-139174.rs create mode 100644 tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr diff --git a/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs b/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs new file mode 100644 index 000000000000..f8fa410b7d49 --- /dev/null +++ b/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs @@ -0,0 +1,24 @@ +//@compile-flags: --edition 2021 + +fn f<'a>(x: Box Option>) -> usize { + //~^ ERROR expected trait, found builtin type `usize` + //~| ERROR expected a type, found a trait [E0782] + 0 +} + +fn create_adder<'a>(x: i32) -> usize + 'a { + //~^ ERROR expected trait, found builtin type `usize` + //~| ERROR expected a type, found a trait [E0782] + move |y| x + y +} + +struct Struct<'a>{ + x: usize + 'a, + //~^ ERROR expected trait, found builtin type `usize` + //~| ERROR expected a type, found a trait [E0782] +} + + +fn main() { + +} diff --git a/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr b/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr new file mode 100644 index 000000000000..ddee0d5586b0 --- /dev/null +++ b/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr @@ -0,0 +1,55 @@ +error[E0404]: expected trait, found builtin type `usize` + --> $DIR/suggestion-trait-object-issue-139174.rs:3:36 + | +LL | fn f<'a>(x: Box Option>) -> usize { + | ^^^^^ not a trait + +error[E0404]: expected trait, found builtin type `usize` + --> $DIR/suggestion-trait-object-issue-139174.rs:9:32 + | +LL | fn create_adder<'a>(x: i32) -> usize + 'a { + | ^^^^^ not a trait + +error[E0404]: expected trait, found builtin type `usize` + --> $DIR/suggestion-trait-object-issue-139174.rs:16:8 + | +LL | x: usize + 'a, + | ^^^^^ not a trait + +error[E0782]: expected a type, found a trait + --> $DIR/suggestion-trait-object-issue-139174.rs:3:36 + | +LL | fn f<'a>(x: Box Option>) -> usize { + | ^^^^^^^^^^ + | +help: you can add the `dyn` keyword if you want a trait object + | +LL | fn f<'a>(x: Box Option>) -> usize { + | +++ + +error[E0782]: expected a type, found a trait + --> $DIR/suggestion-trait-object-issue-139174.rs:9:32 + | +LL | fn create_adder<'a>(x: i32) -> usize + 'a { + | ^^^^^^^^^^ + | +help: `usize + 'a` is dyn-incompatible, use `impl usize + 'a` to return an opaque type, as long as you return a single underlying type + | +LL | fn create_adder<'a>(x: i32) -> impl usize + 'a { + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/suggestion-trait-object-issue-139174.rs:16:8 + | +LL | x: usize + 'a, + | ^^^^^^^^^^ + | +help: you can add the `dyn` keyword if you want a trait object + | +LL | x: dyn usize + 'a, + | +++ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0404, E0782. +For more information about an error, try `rustc --explain E0404`. From 12604fa071b01f7342520224507e43e432294c2c Mon Sep 17 00:00:00 2001 From: xizheyin Date: Tue, 1 Apr 2025 14:19:40 +0800 Subject: [PATCH 713/745] Skip suggest impl or dyn when poly trait is not a real trait Signed-off-by: xizheyin --- .../src/hir_ty_lowering/lint.rs | 1 + .../suggestion-trait-object-issue-139174.stderr | 15 --------------- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 558863122844..8e62dce21913 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -86,6 +86,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { "expected a type, found a trait" ); if self_ty.span.can_be_used_for_suggestions() + && poly_trait_ref.trait_ref.trait_def_id().is_some() && !self.maybe_suggest_impl_trait(self_ty, &mut diag) && !self.maybe_suggest_dyn_trait(self_ty, sugg, &mut diag) { diff --git a/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr b/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr index ddee0d5586b0..0d1ce85fc288 100644 --- a/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr +++ b/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr @@ -21,33 +21,18 @@ error[E0782]: expected a type, found a trait | LL | fn f<'a>(x: Box Option>) -> usize { | ^^^^^^^^^^ - | -help: you can add the `dyn` keyword if you want a trait object - | -LL | fn f<'a>(x: Box Option>) -> usize { - | +++ error[E0782]: expected a type, found a trait --> $DIR/suggestion-trait-object-issue-139174.rs:9:32 | LL | fn create_adder<'a>(x: i32) -> usize + 'a { | ^^^^^^^^^^ - | -help: `usize + 'a` is dyn-incompatible, use `impl usize + 'a` to return an opaque type, as long as you return a single underlying type - | -LL | fn create_adder<'a>(x: i32) -> impl usize + 'a { - | ++++ error[E0782]: expected a type, found a trait --> $DIR/suggestion-trait-object-issue-139174.rs:16:8 | LL | x: usize + 'a, | ^^^^^^^^^^ - | -help: you can add the `dyn` keyword if you want a trait object - | -LL | x: dyn usize + 'a, - | +++ error: aborting due to 6 previous errors From f0efb9748ea02b7e6f15bef45881403ddcfba125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 1 Apr 2025 08:59:04 +0200 Subject: [PATCH 714/745] Support metadata version 10 in proc-macro-srv --- .../rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs index 4e28aaced9b0..7668f419040c 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs @@ -110,7 +110,7 @@ pub fn read_version(obj: &object::File<'_>) -> io::Result { )); } let version = u32::from_be_bytes([dot_rustc[4], dot_rustc[5], dot_rustc[6], dot_rustc[7]]); - // Last supported version is: + // Last breaking version change is: // https://github.com/rust-lang/rust/commit/b94cfefc860715fb2adf72a6955423d384c69318 let (mut metadata_portion, bytes_before_version) = match version { 8 => { @@ -118,7 +118,7 @@ pub fn read_version(obj: &object::File<'_>) -> io::Result { let data_len = u32::from_be_bytes(len_bytes.try_into().unwrap()) as usize; (&dot_rustc[12..data_len + 12], 13) } - 9 => { + 9 | 10 => { let len_bytes = &dot_rustc[8..16]; let data_len = u64::from_le_bytes(len_bytes.try_into().unwrap()) as usize; (&dot_rustc[16..data_len + 12], 17) From f153685fd0478fbbc346cfeb49f57965a9bc43d1 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 25 Mar 2025 15:36:26 +0100 Subject: [PATCH 715/745] Improve docs of ValTreeKind --- compiler/rustc_middle/src/ty/consts/valtree.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs index 72263d845808..2f21d19e03c7 100644 --- a/compiler/rustc_middle/src/ty/consts/valtree.rs +++ b/compiler/rustc_middle/src/ty/consts/valtree.rs @@ -33,7 +33,7 @@ pub enum ValTreeKind<'tcx> { /// The fields of any kind of aggregate. Structs, tuples and arrays are represented by /// listing their fields' values in order. /// - /// Enums are represented by storing their discriminant as a field, followed by all + /// Enums are represented by storing their variant index as a u32 field, followed by all /// the fields of the variant. /// /// ZST types are represented as an empty slice. From a7b687c26ef55bfc3481761fef6e46154e5f95ea Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Mar 2025 11:48:06 +0000 Subject: [PATCH 716/745] Decouple trait impls of different traits wrt incremental --- compiler/rustc_hir_analysis/src/coherence/mod.rs | 5 ++++- compiler/rustc_middle/src/hir/map.rs | 2 +- compiler/rustc_middle/src/hir/mod.rs | 2 ++ compiler/rustc_middle/src/query/mod.rs | 5 +++++ src/tools/clippy/clippy_lints/src/derive.rs | 6 ++---- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 15e0a72fdcbd..16bac4304910 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -153,9 +153,12 @@ pub(crate) fn provide(providers: &mut Providers) { } fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> { + let impls = tcx.local_trait_impls(def_id); // If there are no impls for the trait, then "all impls" are trivially coherent and we won't check anything // anyway. Thus we bail out even before the specialization graph, avoiding the dep_graph edge. - let Some(impls) = tcx.all_local_trait_impls(()).get(&def_id) else { return Ok(()) }; + if impls.is_empty() { + return Ok(()); + } // Trigger building the specialization graph for the trait. This will detect and report any // overlap errors. let mut res = tcx.ensure_ok().specialization_graph_of(def_id); diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 52f155a16b86..80370910032d 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -368,7 +368,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn hir_trait_impls(self, trait_did: DefId) -> &'tcx [LocalDefId] { - self.all_local_trait_impls(()).get(&trait_did).map_or(&[], |xs| &xs[..]) + self.local_trait_impls(trait_did) } /// Gets the attributes on the crate. This is preferable to diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 347bc5ea3128..cae9b2fb5448 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -238,6 +238,8 @@ pub fn provide(providers: &mut Providers) { } }; providers.all_local_trait_impls = |tcx, ()| &tcx.resolutions(()).trait_impls; + providers.local_trait_impls = + |tcx, trait_id| tcx.resolutions(()).trait_impls.get(&trait_id).map_or(&[], |xs| &xs[..]); providers.expn_that_defined = |tcx, id| tcx.resolutions(()).expn_that_defined.get(&id).copied().unwrap_or(ExpnId::root()); providers.in_scope_traits_map = |tcx, id| { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index d7ed703f4ae3..4b3236e4b841 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1502,6 +1502,11 @@ rustc_queries! { desc { "finding local trait impls" } } + /// Return all `impl` blocks of the given trait in the current crate. + query local_trait_impls(trait_id: DefId) -> &'tcx [LocalDefId] { + desc { "finding local trait impls of `{}`", tcx.def_path_str(trait_id) } + } + /// Given a trait `trait_id`, return all known `impl` blocks. query trait_impls_of(trait_id: DefId) -> &'tcx ty::trait_def::TraitImpls { arena_cache diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index 2ae35b400557..fae01026487a 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -324,11 +324,9 @@ fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &h // there's a Copy impl for any instance of the adt. if !is_copy(cx, ty) { if ty_subs.non_erasable_generics().next().is_some() { - let has_copy_impl = cx.tcx.all_local_trait_impls(()).get(©_id).is_some_and(|impls| { - impls.iter().any(|&id| { - matches!(cx.tcx.type_of(id).instantiate_identity().kind(), ty::Adt(adt, _) + let has_copy_impl = cx.tcx.local_trait_impls(copy_id).iter().any(|&id| { + matches!(cx.tcx.type_of(id).instantiate_identity().kind(), ty::Adt(adt, _) if ty_adt.did() == adt.did()) - }) }); if !has_copy_impl { return; From aec77398378cc7af99043c3d1dd2394eb3d33c43 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Mar 2025 12:03:48 +0000 Subject: [PATCH 717/745] Remove an unnecessary dtor computation and use the cached query result instead --- compiler/rustc_mir_transform/src/check_const_item_mutation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs index ceea72c6755a..76d1e671c5d8 100644 --- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs +++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs @@ -53,7 +53,7 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> { // // #[const_mutation_allowed] // pub const LOG: Log = Log { msg: "" }; - match self.tcx.calculate_dtor(def_id, |_, _| Ok(())) { + match self.tcx.adt_destructor(def_id) { Some(_) => None, None => Some(def_id), } From c0fe46d6b72c96bda16bf62e7476e6d85ba68afe Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Mar 2025 12:08:00 +0000 Subject: [PATCH 718/745] Make missing optimized MIR error more informative --- compiler/rustc_monomorphize/messages.ftl | 2 +- compiler/rustc_monomorphize/src/collector.rs | 1 + compiler/rustc_monomorphize/src/errors.rs | 1 + tests/ui/rmeta/no_optitimized_mir.rs | 2 +- tests/ui/rmeta/no_optitimized_mir.stderr | 2 +- 5 files changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl index aae2d79c1610..6b6653e7de02 100644 --- a/compiler/rustc_monomorphize/messages.ftl +++ b/compiler/rustc_monomorphize/messages.ftl @@ -48,7 +48,7 @@ monomorphize_large_assignments = .note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` monomorphize_no_optimized_mir = - missing optimized MIR for an item in the crate `{$crate_name}` + missing optimized MIR for `{$instance}` in the crate `{$crate_name}` .note = missing optimized MIR for this item (was the crate `{$crate_name}` compiled with `--emit=metadata`?) monomorphize_recursion_limit = diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 2a1b20ba48b8..6e676ac6b8d5 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -989,6 +989,7 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> tcx.dcx().emit_fatal(NoOptimizedMir { span: tcx.def_span(def_id), crate_name: tcx.crate_name(def_id.krate), + instance: instance.to_string(), }); } diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index dffa372279f9..adfe096f0cdc 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -24,6 +24,7 @@ pub(crate) struct NoOptimizedMir { #[note] pub span: Span, pub crate_name: Symbol, + pub instance: String, } #[derive(LintDiagnostic)] diff --git a/tests/ui/rmeta/no_optitimized_mir.rs b/tests/ui/rmeta/no_optitimized_mir.rs index 708cdfc803fa..c8ed00b039b2 100644 --- a/tests/ui/rmeta/no_optitimized_mir.rs +++ b/tests/ui/rmeta/no_optitimized_mir.rs @@ -10,4 +10,4 @@ fn main() { rmeta_meta::missing_optimized_mir(); } -//~? ERROR missing optimized MIR for an item in the crate `rmeta_meta` +//~? ERROR missing optimized MIR for `missing_optimized_mir` in the crate `rmeta_meta` diff --git a/tests/ui/rmeta/no_optitimized_mir.stderr b/tests/ui/rmeta/no_optitimized_mir.stderr index 92f22d780005..254f100aa7b5 100644 --- a/tests/ui/rmeta/no_optitimized_mir.stderr +++ b/tests/ui/rmeta/no_optitimized_mir.stderr @@ -1,4 +1,4 @@ -error: missing optimized MIR for an item in the crate `rmeta_meta` +error: missing optimized MIR for `missing_optimized_mir` in the crate `rmeta_meta` | note: missing optimized MIR for this item (was the crate `rmeta_meta` compiled with `--emit=metadata`?) --> $DIR/auxiliary/rmeta-meta.rs:10:1 From 23f1fb58f201cce980128a0dae491c4e5393629a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Mar 2025 12:08:00 +0000 Subject: [PATCH 719/745] Store adt_destructor in metadata --- compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs | 5 +---- compiler/rustc_metadata/src/rmeta/encoder.rs | 4 ++++ compiler/rustc_metadata/src/rmeta/mod.rs | 1 + compiler/rustc_middle/src/ty/parameterized.rs | 1 + 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 776b081a4630..5c425e7a4185 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -330,10 +330,7 @@ provide! { tcx, def_id, other, cdata, visibility => { cdata.get_visibility(def_id.index) } adt_def => { cdata.get_adt_def(def_id.index, tcx) } - adt_destructor => { - let _ = cdata; - tcx.calculate_dtor(def_id, |_,_| Ok(())) - } + adt_destructor => { table } adt_async_destructor => { let _ = cdata; tcx.calculate_async_dtor(def_id, |_,_| Ok(())) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 7ab3d432bdf8..a9beab1a70a3 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1633,6 +1633,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.fn_sig[variant.def_id] <- fn_sig); } } + + if let Some(destructor) = tcx.adt_destructor(local_def_id) { + record!(self.tables.adt_destructor[def_id] <- destructor); + } } #[instrument(level = "debug", skip(self))] diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index dc453b1e747c..fb5fcff8d33d 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -446,6 +446,7 @@ define_tables! { fn_arg_names: Table>>, coroutine_kind: Table, coroutine_for_closure: Table, + adt_destructor: Table>, coroutine_by_move_body_def_id: Table, eval_static_initializer: Table>>, trait_def: Table>, diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 19e2b5745632..d6f181669563 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -68,6 +68,7 @@ trivially_parameterized_over_tcx! { ty::AssocItemContainer, ty::Asyncness, ty::DeducedParamAttrs, + ty::Destructor, ty::Generics, ty::ImplPolarity, ty::ImplTraitInTraitData, From 2b1c416da724a45f5a9c8e501c27a87ca4b536cc Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Mar 2025 12:46:04 +0000 Subject: [PATCH 720/745] Store adt_async_destructor in metadata --- compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs | 5 +---- compiler/rustc_metadata/src/rmeta/encoder.rs | 4 ++++ compiler/rustc_metadata/src/rmeta/mod.rs | 1 + compiler/rustc_middle/src/ty/parameterized.rs | 1 + 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 5c425e7a4185..3dc82ce9d183 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -331,10 +331,7 @@ provide! { tcx, def_id, other, cdata, visibility => { cdata.get_visibility(def_id.index) } adt_def => { cdata.get_adt_def(def_id.index, tcx) } adt_destructor => { table } - adt_async_destructor => { - let _ = cdata; - tcx.calculate_async_dtor(def_id, |_,_| Ok(())) - } + adt_async_destructor => { table } associated_item_def_ids => { tcx.arena.alloc_from_iter(cdata.get_associated_item_or_field_def_ids(def_id.index)) } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index a9beab1a70a3..b6f799e7ff79 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1637,6 +1637,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if let Some(destructor) = tcx.adt_destructor(local_def_id) { record!(self.tables.adt_destructor[def_id] <- destructor); } + + if let Some(destructor) = tcx.adt_async_destructor(local_def_id) { + record!(self.tables.adt_async_destructor[def_id] <- destructor); + } } #[instrument(level = "debug", skip(self))] diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index fb5fcff8d33d..8fef3ef23555 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -447,6 +447,7 @@ define_tables! { coroutine_kind: Table, coroutine_for_closure: Table, adt_destructor: Table>, + adt_async_destructor: Table>, coroutine_by_move_body_def_id: Table, eval_static_initializer: Table>>, trait_def: Table>, diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index d6f181669563..61b35b33a096 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -65,6 +65,7 @@ trivially_parameterized_over_tcx! { crate::middle::lib_features::FeatureStability, crate::middle::resolve_bound_vars::ObjectLifetimeDefault, crate::mir::ConstQualifs, + ty::AsyncDestructor, ty::AssocItemContainer, ty::Asyncness, ty::DeducedParamAttrs, From 51184c70c897619f6a2883538f8a85292306a0c8 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Mar 2025 12:48:54 +0000 Subject: [PATCH 721/745] Ensure `calculcate_dtor` is only ever called on local types --- compiler/rustc_hir_analysis/src/check/mod.rs | 4 ++-- compiler/rustc_middle/src/ty/util.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index d8ae42145275..ee1e78a79cd4 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -114,11 +114,11 @@ pub fn provide(providers: &mut Providers) { } fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { - tcx.calculate_dtor(def_id.to_def_id(), always_applicable::check_drop_impl) + tcx.calculate_dtor(def_id, always_applicable::check_drop_impl) } fn adt_async_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { - tcx.calculate_async_dtor(def_id.to_def_id(), always_applicable::check_drop_impl) + tcx.calculate_async_dtor(def_id, always_applicable::check_drop_impl) } /// Given a `DefId` for an opaque type in return position, find its parent item's return diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index c0d4130336e5..61d8b5ce52ed 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -389,7 +389,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Calculate the destructor of a given type. pub fn calculate_dtor( self, - adt_did: DefId, + adt_did: LocalDefId, validate: impl Fn(Self, DefId) -> Result<(), ErrorGuaranteed>, ) -> Option { let drop_trait = self.lang_items().drop_trait()?; @@ -426,7 +426,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Calculate the async destructor of a given type. pub fn calculate_async_dtor( self, - adt_did: DefId, + adt_did: LocalDefId, validate: impl Fn(Self, DefId) -> Result<(), ErrorGuaranteed>, ) -> Option { let async_drop_trait = self.lang_items().async_drop_trait()?; From 2dc650b97b240c0bd279704b01916970c2031c4b Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Fri, 28 Mar 2025 18:12:29 +0530 Subject: [PATCH 722/745] replace commit placeholder in vendor status with actual commit --- src/bootstrap/bootstrap.py | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 68400ba0ea02..140f601253c3 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -1162,6 +1162,30 @@ class RustBuild(object): config = self.get_toml("build") return config or default_build_triple(self.verbose) + def is_git_repository(self, repo_path): + return os.path.isdir(os.path.join(repo_path, ".git")) + + def get_latest_commit(self): + repo_path = self.rust_root + author_email = self.stage0_data.get("git_merge_commit_email") + if not self.is_git_repository(repo_path): + return "" + cmd = [ + "git", + "-C", + repo_path, + "rev-list", + "--author", + author_email, + "-n1", + "HEAD", + ] + try: + commit = subprocess.check_output(cmd, universal_newlines=True).strip() + return commit or "" + except subprocess.CalledProcessError: + return "" + def check_vendored_status(self): """Check that vendoring is configured properly""" # keep this consistent with the equivalent check in bootstrap: @@ -1174,7 +1198,8 @@ class RustBuild(object): eprint(" use vendored sources by default.") cargo_dir = os.path.join(self.rust_root, ".cargo") - url = "https://ci-artifacts.rust-lang.org/rustc-builds//rustc-nightly-src.tar.xz" + commit = self.get_latest_commit() + url = f"https://ci-artifacts.rust-lang.org/rustc-builds/{commit}/rustc-nightly-src.tar.xz" if self.use_vendored_sources: vendor_dir = os.path.join(self.rust_root, "vendor") if not os.path.exists(vendor_dir): From 624eb8550b8411a8b8773acf3fce0082f9554a7b Mon Sep 17 00:00:00 2001 From: highcloudwind Date: Tue, 1 Apr 2025 21:05:34 +0800 Subject: [PATCH 723/745] chore: remove redundant backtick Signed-off-by: highcloudwind --- src/etc/test-float-parse/src/ui.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/etc/test-float-parse/src/ui.rs b/src/etc/test-float-parse/src/ui.rs index 1ee57723e6a6..73473eef0bfd 100644 --- a/src/etc/test-float-parse/src/ui.rs +++ b/src/etc/test-float-parse/src/ui.rs @@ -157,7 +157,7 @@ pub fn set_panic_hook(drop_bars: &[ProgressBar]) { })); } -/// Allow non-Debug items in a `derive(Debug)` struct`. +/// Allow non-Debug items in a `derive(Debug)` struct. #[derive(Clone)] struct NoDebug(T); From d2358f7f2e1ec1a058308fc3149ecd5e7d3d4a12 Mon Sep 17 00:00:00 2001 From: futreall <86553580+futreall@users.noreply.github.com> Date: Tue, 1 Apr 2025 15:26:55 +0300 Subject: [PATCH 724/745] fix link in netbsd.md Update netbsd.md Update netbsd.md --- src/doc/rustc/src/platform-support/netbsd.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support/netbsd.md b/src/doc/rustc/src/platform-support/netbsd.md index ef9337befa64..5c2ce0ee9005 100644 --- a/src/doc/rustc/src/platform-support/netbsd.md +++ b/src/doc/rustc/src/platform-support/netbsd.md @@ -34,7 +34,7 @@ are built for NetBSD 8.x but also work on newer OS versions). ## Designated Developers - [@he32](https://github.com/he32), `he@NetBSD.org` -- [NetBSD/pkgsrc-wip's rust](https://github.com/NetBSD/pkgsrc-wip/blob/master/rust/Makefile) maintainer (see MAINTAINER variable). This package is part of "pkgsrc work-in-progress" and is used for deployment and testing of new versions of rust +- [NetBSD/pkgsrc-wip's rust](https://github.com/NetBSD/pkgsrc-wip/blob/master/rust185/Makefile) maintainer (see MAINTAINER variable). This package is part of "pkgsrc work-in-progress" and is used for deployment and testing of new versions of rust - [NetBSD's pkgsrc lang/rust](https://github.com/NetBSD/pkgsrc/tree/trunk/lang/rust) for the "proper" package in pkgsrc. - [NetBSD's pkgsrc lang/rust-bin](https://github.com/NetBSD/pkgsrc/tree/trunk/lang/rust-bin) which re-uses the bootstrap kit as a binary distribution and therefore avoids the rather protracted native build time of rust itself From 6c3be19f578f589431d0bcc8c0b71b204d2241c1 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 1 Apr 2025 06:47:55 -0700 Subject: [PATCH 725/745] Update mdbook to 0.4.48 This brings in several updates. Two significant ones are to halve the search index size, and the other introduces major changes to footnote rendering. Changelog: https://github.com/rust-lang/mdBook/blob/master/CHANGELOG.md#mdbook-0448 --- src/doc/rustc/src/SUMMARY.md | 3 +-- src/tools/rustbook/Cargo.lock | 4 ++-- src/tools/rustbook/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index d08e0bd1edf2..e1ba27c07dae 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -102,7 +102,7 @@ - [s390x-unknown-linux-gnu](platform-support/s390x-unknown-linux-gnu.md) - [s390x-unknown-linux-musl](platform-support/s390x-unknown-linux-musl.md) - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md) - - [sparcv9-sun-solaris](platform-support/solaris.md) + - [solaris](platform-support/solaris.md) - [\*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md) - [\*-nto-qnx-\*](platform-support/nto-qnx.md) - [\*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md) @@ -126,7 +126,6 @@ - [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md) - [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md) - [x86_64-pc-cygwin](platform-support/x86_64-pc-cygwin.md) - - [x86_64-pc-solaris](platform-support/solaris.md) - [x86_64-unknown-linux-none.md](platform-support/x86_64-unknown-linux-none.md) - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md) - [xtensa-\*-none-elf](platform-support/xtensa.md) diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock index e54747c129a0..a1ccaa487490 100644 --- a/src/tools/rustbook/Cargo.lock +++ b/src/tools/rustbook/Cargo.lock @@ -880,9 +880,9 @@ dependencies = [ [[package]] name = "mdbook" -version = "0.4.47" +version = "0.4.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e1a8fe3a4a01f28dab245c474cb7b95ccb4d3d2f17a5419a3d949f474c45e84" +checksum = "8b6fbb4ac2d9fd7aa987c3510309ea3c80004a968d063c42f0d34fea070817c1" dependencies = [ "ammonia", "anyhow", diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml index 831233e3065d..a0b220c3557d 100644 --- a/src/tools/rustbook/Cargo.toml +++ b/src/tools/rustbook/Cargo.toml @@ -15,6 +15,6 @@ mdbook-i18n-helpers = "0.3.3" mdbook-spec = { path = "../../doc/reference/mdbook-spec" } [dependencies.mdbook] -version = "0.4.47" +version = "0.4.48" default-features = false features = ["search"] From 770fcbf8c13871620b689fcadec36f5936c5fe5a Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 1 Apr 2025 14:11:58 +0000 Subject: [PATCH 726/745] Move test-float-parse to the 2024 edition --- src/etc/test-float-parse/Cargo.toml | 2 +- .../src/{gen => gen_}/exhaustive.rs | 0 .../src/{gen => gen_}/exponents.rs | 0 .../src/{gen => gen_}/fuzz.rs | 0 .../src/{gen => gen_}/integers.rs | 0 .../src/{gen => gen_}/long_fractions.rs | 0 .../src/{gen => gen_}/many_digits.rs | 0 .../src/{gen => gen_}/sparse.rs | 0 .../src/{gen => gen_}/spot_checks.rs | 0 .../src/{gen => gen_}/subnorm.rs | 0 src/etc/test-float-parse/src/lib.rs | 36 +++++++++---------- 11 files changed, 19 insertions(+), 19 deletions(-) rename src/etc/test-float-parse/src/{gen => gen_}/exhaustive.rs (100%) rename src/etc/test-float-parse/src/{gen => gen_}/exponents.rs (100%) rename src/etc/test-float-parse/src/{gen => gen_}/fuzz.rs (100%) rename src/etc/test-float-parse/src/{gen => gen_}/integers.rs (100%) rename src/etc/test-float-parse/src/{gen => gen_}/long_fractions.rs (100%) rename src/etc/test-float-parse/src/{gen => gen_}/many_digits.rs (100%) rename src/etc/test-float-parse/src/{gen => gen_}/sparse.rs (100%) rename src/etc/test-float-parse/src/{gen => gen_}/spot_checks.rs (100%) rename src/etc/test-float-parse/src/{gen => gen_}/subnorm.rs (100%) diff --git a/src/etc/test-float-parse/Cargo.toml b/src/etc/test-float-parse/Cargo.toml index bacb9e09f3f6..8a9c5322ef7b 100644 --- a/src/etc/test-float-parse/Cargo.toml +++ b/src/etc/test-float-parse/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "test-float-parse" version = "0.1.0" -edition = "2021" +edition = "2024" publish = false [dependencies] diff --git a/src/etc/test-float-parse/src/gen/exhaustive.rs b/src/etc/test-float-parse/src/gen_/exhaustive.rs similarity index 100% rename from src/etc/test-float-parse/src/gen/exhaustive.rs rename to src/etc/test-float-parse/src/gen_/exhaustive.rs diff --git a/src/etc/test-float-parse/src/gen/exponents.rs b/src/etc/test-float-parse/src/gen_/exponents.rs similarity index 100% rename from src/etc/test-float-parse/src/gen/exponents.rs rename to src/etc/test-float-parse/src/gen_/exponents.rs diff --git a/src/etc/test-float-parse/src/gen/fuzz.rs b/src/etc/test-float-parse/src/gen_/fuzz.rs similarity index 100% rename from src/etc/test-float-parse/src/gen/fuzz.rs rename to src/etc/test-float-parse/src/gen_/fuzz.rs diff --git a/src/etc/test-float-parse/src/gen/integers.rs b/src/etc/test-float-parse/src/gen_/integers.rs similarity index 100% rename from src/etc/test-float-parse/src/gen/integers.rs rename to src/etc/test-float-parse/src/gen_/integers.rs diff --git a/src/etc/test-float-parse/src/gen/long_fractions.rs b/src/etc/test-float-parse/src/gen_/long_fractions.rs similarity index 100% rename from src/etc/test-float-parse/src/gen/long_fractions.rs rename to src/etc/test-float-parse/src/gen_/long_fractions.rs diff --git a/src/etc/test-float-parse/src/gen/many_digits.rs b/src/etc/test-float-parse/src/gen_/many_digits.rs similarity index 100% rename from src/etc/test-float-parse/src/gen/many_digits.rs rename to src/etc/test-float-parse/src/gen_/many_digits.rs diff --git a/src/etc/test-float-parse/src/gen/sparse.rs b/src/etc/test-float-parse/src/gen_/sparse.rs similarity index 100% rename from src/etc/test-float-parse/src/gen/sparse.rs rename to src/etc/test-float-parse/src/gen_/sparse.rs diff --git a/src/etc/test-float-parse/src/gen/spot_checks.rs b/src/etc/test-float-parse/src/gen_/spot_checks.rs similarity index 100% rename from src/etc/test-float-parse/src/gen/spot_checks.rs rename to src/etc/test-float-parse/src/gen_/spot_checks.rs diff --git a/src/etc/test-float-parse/src/gen/subnorm.rs b/src/etc/test-float-parse/src/gen_/subnorm.rs similarity index 100% rename from src/etc/test-float-parse/src/gen/subnorm.rs rename to src/etc/test-float-parse/src/gen_/subnorm.rs diff --git a/src/etc/test-float-parse/src/lib.rs b/src/etc/test-float-parse/src/lib.rs index e2f84b085c6f..3c3ef5802b6a 100644 --- a/src/etc/test-float-parse/src/lib.rs +++ b/src/etc/test-float-parse/src/lib.rs @@ -17,7 +17,7 @@ use traits::{Float, Generator, Int}; use validate::CheckError; /// Test generators. -mod gen { +mod gen_ { pub mod exhaustive; pub mod exponents; pub mod fuzz; @@ -136,24 +136,24 @@ where { if F::BITS <= MAX_BITS_FOR_EXHAUUSTIVE { // Only run exhaustive tests if there is a chance of completion. - TestInfo::register::>(tests); + TestInfo::register::>(tests); } - gen::fuzz::Fuzz::::set_iterations(cfg.fuzz_count); + gen_::fuzz::Fuzz::::set_iterations(cfg.fuzz_count); - TestInfo::register::>(tests); - TestInfo::register::>(tests); - TestInfo::register::>(tests); - TestInfo::register::>(tests); - TestInfo::register::(tests); - TestInfo::register::(tests); - TestInfo::register::>(tests); - TestInfo::register::>(tests); - TestInfo::register::>(tests); - TestInfo::register::(tests); - TestInfo::register::(tests); - TestInfo::register::>(tests); - TestInfo::register::>(tests); + TestInfo::register::>(tests); + TestInfo::register::>(tests); + TestInfo::register::>(tests); + TestInfo::register::>(tests); + TestInfo::register::(tests); + TestInfo::register::(tests); + TestInfo::register::>(tests); + TestInfo::register::>(tests); + TestInfo::register::>(tests); + TestInfo::register::(tests); + TestInfo::register::(tests); + TestInfo::register::>(tests); + TestInfo::register::>(tests); } /// Configuration for a single test. @@ -343,7 +343,7 @@ fn launch_tests(tests: &mut [TestInfo], cfg: &Config) -> Duration { /// /// This calls the generator's iterator multiple times (in parallel) and validates each output. fn test_runner>(test: &TestInfo, cfg: &Config) { - let gen = G::new(); + let gen_ = G::new(); let executed = AtomicU64::new(0); let failures = AtomicU64::new(0); @@ -387,7 +387,7 @@ fn test_runner>(test: &TestInfo, cfg: &Config) { // Run the test iterations in parallel. Each thread gets a string buffer to write // its check values to. - let res = gen.par_bridge().try_for_each_init(String::new, check_one); + let res = gen_.par_bridge().try_for_each_init(String::new, check_one); let elapsed = started.elapsed(); let executed = executed.into_inner(); From f922e74f71371abe3eceda4a131c4d0137591548 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 1 Apr 2025 14:12:07 +0000 Subject: [PATCH 727/745] Make coroutine_drop_cleanup 2024 edition compatible --- tests/mir-opt/coroutine_drop_cleanup.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/mir-opt/coroutine_drop_cleanup.rs b/tests/mir-opt/coroutine_drop_cleanup.rs index 33fdd2dd0d9c..4ae97273cd90 100644 --- a/tests/mir-opt/coroutine_drop_cleanup.rs +++ b/tests/mir-opt/coroutine_drop_cleanup.rs @@ -8,7 +8,7 @@ // EMIT_MIR coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.mir fn main() { - let gen = #[coroutine] + let gen_ = #[coroutine] || { let _s = String::new(); yield; From a2f29439bf0fbf9823cf99cee61254875379e2c4 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 1 Apr 2025 14:12:30 +0000 Subject: [PATCH 728/745] Use the 2024 edition in ./x.py fmt --- src/bootstrap/src/core/build_steps/format.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 7aa5cb2b6e5e..b1a97bde97b5 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -31,7 +31,7 @@ fn rustfmt( // Avoid the submodule config paths from coming into play. We only allow a single global config // for the workspace for now. cmd.arg("--config-path").arg(src.canonicalize().unwrap()); - cmd.arg("--edition").arg("2021"); + cmd.arg("--edition").arg("2024"); cmd.arg("--unstable-features"); cmd.arg("--skip-children"); if check { From 242558058a0aa3d5b64d911f45a07f27930016e7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 1 Apr 2025 14:13:53 +0000 Subject: [PATCH 729/745] Allow formatting example/gen_block_iterate.rs --- .../example/gen_block_iterate.rs | 16 ++++++++++++---- compiler/rustc_codegen_cranelift/rustfmt.toml | 4 ---- rustfmt.toml | 1 - 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs b/compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs index 25bfe542d228..de9a3d550ecc 100644 --- a/compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs +++ b/compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs @@ -6,16 +6,25 @@ #![feature(gen_blocks)] fn foo() -> impl Iterator { - gen { yield 42; for x in 3..6 { yield x } } + gen { + yield 42; + for x in 3..6 { + yield x + } + } } fn moved() -> impl Iterator { let mut x = "foo".to_string(); gen move { yield 42; - if x == "foo" { return } + if x == "foo" { + return; + } x.clear(); - for x in 3..6 { yield x } + for x in 3..6 { + yield x + } } } @@ -32,5 +41,4 @@ fn main() { let mut iter = moved(); assert_eq!(iter.next(), Some(42)); assert_eq!(iter.next(), None); - } diff --git a/compiler/rustc_codegen_cranelift/rustfmt.toml b/compiler/rustc_codegen_cranelift/rustfmt.toml index f31fa9c76abc..35c92663eb90 100644 --- a/compiler/rustc_codegen_cranelift/rustfmt.toml +++ b/compiler/rustc_codegen_cranelift/rustfmt.toml @@ -1,7 +1,3 @@ -ignore = [ - "example/gen_block_iterate.rs", # uses edition 2024 -] - # Matches rustfmt.toml of rustc style_edition = "2024" use_small_heuristics = "Max" diff --git a/rustfmt.toml b/rustfmt.toml index 8feeb60ca12c..c884a33729c4 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -49,7 +49,6 @@ ignore = [ # These are ignored by a standard cargo fmt run. "compiler/rustc_codegen_cranelift/scripts", - "compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs", # uses edition 2024 "compiler/rustc_codegen_gcc/tests", # Code automatically generated and included. "compiler/rustc_codegen_gcc/src/intrinsic/archs.rs", From 49ed25b5d2d5dc88f9fa3e268d9bd210acc875de Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 18 Apr 2024 21:31:17 +1000 Subject: [PATCH 730/745] Remove `NtExpr` and `NtLiteral`. Notes about tests: - tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs: some messages are now duplicated due to repeated parsing. - tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs: ditto. - `tests/ui/proc-macro/macro-rules-derive-cfg.rs`: the diff looks large but the only difference is the insertion of a single invisible-delimited group around a metavar. - `tests/ui/attributes/nonterminal-expansion.rs`: a slight span degradation, somehow related to the recent massive attr parsing rewrite (#135726). I couldn't work out exactly what is going wrong, but I don't think it's worth holding things up for a single slightly suboptimal error message. --- compiler/rustc_ast/src/ast_traits.rs | 2 - compiler/rustc_ast/src/mut_visit.rs | 2 - compiler/rustc_ast/src/token.rs | 71 ++-- compiler/rustc_ast/src/tokenstream.rs | 1 - compiler/rustc_expand/src/mbe/transcribe.rs | 35 +- compiler/rustc_parse/messages.ftl | 2 +- compiler/rustc_parse/src/errors.rs | 4 +- compiler/rustc_parse/src/parser/expr.rs | 220 +++++++----- compiler/rustc_parse/src/parser/item.rs | 53 ++- compiler/rustc_parse/src/parser/mod.rs | 32 +- .../rustc_parse/src/parser/nonterminal.rs | 16 +- compiler/rustc_parse/src/parser/pat.rs | 2 +- tests/ui/attributes/nonterminal-expansion.rs | 4 +- .../attributes/nonterminal-expansion.stderr | 11 +- .../cfg-attr-syntax-validation.rs | 2 +- .../cfg-attr-syntax-validation.stderr | 2 +- tests/ui/macros/nonterminal-matching.rs | 4 +- tests/ui/macros/nonterminal-matching.stderr | 4 +- .../extern-abi-from-mac-literal-frag.rs | 4 + tests/ui/parser/float-field-interpolated.rs | 8 +- .../ui/parser/float-field-interpolated.stderr | 8 +- .../ui/parser/macro/trait-non-item-macros.rs | 2 +- .../parser/macro/trait-non-item-macros.stderr | 2 +- .../proc-macro/macro-rules-derive-cfg.stdout | 129 +++---- .../rfc-2294-if-let-guard/feature-gate.rs | 2 + .../rfc-2294-if-let-guard/feature-gate.stderr | 26 +- .../disallowed-positions.feature.stderr | 306 +++++++++-------- .../disallowed-positions.no_feature.stderr | 316 ++++++++++-------- .../disallowed-positions.nothing.stderr | 238 ++++++------- .../disallowed-positions.rs | 4 + 30 files changed, 864 insertions(+), 648 deletions(-) diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index 849cc650e9d6..c9e2e9911ef0 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -209,13 +209,11 @@ impl HasTokens for Attribute { impl HasTokens for Nonterminal { fn tokens(&self) -> Option<&LazyAttrTokenStream> { match self { - Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens(), Nonterminal::NtBlock(block) => block.tokens(), } } fn tokens_mut(&mut self) -> Option<&mut Option> { match self { - Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens_mut(), Nonterminal::NtBlock(block) => block.tokens_mut(), } } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 30af6d910bfa..f7d13acdfc40 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -899,8 +899,6 @@ pub fn visit_token(vis: &mut T, t: &mut Token) { fn visit_nonterminal(vis: &mut T, nt: &mut token::Nonterminal) { match nt { token::NtBlock(block) => vis.visit_block(block), - token::NtExpr(expr) => vis.visit_expr(expr), - token::NtLiteral(expr) => vis.visit_expr(expr), } } diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 6e6f0f1b2660..2081777fff35 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -198,16 +198,17 @@ impl Lit { } } - /// Keep this in sync with `Token::can_begin_literal_maybe_minus` excluding unary negation. + /// Keep this in sync with `Token::can_begin_literal_maybe_minus` and + /// `Parser::eat_token_lit` (excluding unary negation). pub fn from_token(token: &Token) -> Option { match token.uninterpolate().kind { Ident(name, IdentIsRaw::No) if name.is_bool_lit() => Some(Lit::new(Bool, name, None)), Literal(token_lit) => Some(token_lit), - Interpolated(ref nt) - if let NtExpr(expr) | NtLiteral(expr) = &**nt - && let ast::ExprKind::Lit(token_lit) = expr.kind => - { - Some(token_lit) + OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( + MetaVarKind::Literal | MetaVarKind::Expr { .. }, + ))) => { + // Unreachable with the current test suite. + panic!("from_token metavar"); } _ => None, } @@ -590,6 +591,9 @@ impl Token { /// for which spans affect name resolution and edition checks. /// Note that keywords are also identifiers, so they should use this /// if they keep spans or perform edition checks. + // + // Note: `Parser::uninterpolated_token_span` may give better information + // than this method does. pub fn uninterpolated_span(&self) -> Span { match self.kind { NtIdent(ident, _) | NtLifetime(ident, _) => ident.span, @@ -642,12 +646,7 @@ impl Token { PathSep | // global path Lifetime(..) | // labeled loop Pound => true, // expression attributes - Interpolated(ref nt) => - matches!(&**nt, - NtBlock(..) | - NtExpr(..) | - NtLiteral(..) - ), + Interpolated(ref nt) => matches!(&**nt, NtBlock(..)), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( MetaVarKind::Block | MetaVarKind::Expr { .. } | @@ -677,11 +676,6 @@ impl Token { Lt | // path (UFCS constant) Shl => true, // path (double UFCS) Or => matches!(pat_kind, PatWithOr), // leading vert `|` or-pattern - Interpolated(nt) => - matches!(&**nt, - | NtExpr(..) - | NtLiteral(..) - ), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( MetaVarKind::Expr { .. } | MetaVarKind::Literal | @@ -724,7 +718,7 @@ impl Token { match self.kind { OpenDelim(Delimiter::Brace) | Literal(..) | Minus => true, Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true, - Interpolated(ref nt) => matches!(&**nt, NtExpr(..) | NtBlock(..) | NtLiteral(..)), + Interpolated(ref nt) => matches!(&**nt, NtBlock(..)), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( MetaVarKind::Expr { .. } | MetaVarKind::Block | MetaVarKind::Literal, ))) => true, @@ -768,22 +762,12 @@ impl Token { /// /// In other words, would this token be a valid start of `parse_literal_maybe_minus`? /// - /// Keep this in sync with and `Lit::from_token`, excluding unary negation. + /// Keep this in sync with `Lit::from_token` and `Parser::eat_token_lit` + /// (excluding unary negation). pub fn can_begin_literal_maybe_minus(&self) -> bool { match self.uninterpolate().kind { Literal(..) | Minus => true, Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true, - Interpolated(ref nt) => match &**nt { - NtLiteral(_) => true, - NtExpr(e) => match &e.kind { - ast::ExprKind::Lit(_) => true, - ast::ExprKind::Unary(ast::UnOp::Neg, e) => { - matches!(&e.kind, ast::ExprKind::Lit(_)) - } - _ => false, - }, - _ => false, - }, OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind))) => match mv_kind { MetaVarKind::Literal => true, MetaVarKind::Expr { can_begin_literal_maybe_minus, .. } => { @@ -798,14 +782,6 @@ impl Token { pub fn can_begin_string_literal(&self) -> bool { match self.uninterpolate().kind { Literal(..) => true, - Interpolated(ref nt) => match &**nt { - NtLiteral(_) => true, - NtExpr(e) => match &e.kind { - ast::ExprKind::Lit(_) => true, - _ => false, - }, - _ => false, - }, OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind))) => match mv_kind { MetaVarKind::Literal => true, MetaVarKind::Expr { can_begin_string_literal, .. } => can_begin_string_literal, @@ -869,12 +845,17 @@ impl Token { /// Is this a pre-parsed expression dropped into the token stream /// (which happens while parsing the result of macro expansion)? - pub fn is_whole_expr(&self) -> bool { + pub fn is_metavar_expr(&self) -> bool { #[allow(irrefutable_let_patterns)] // FIXME: temporary if let Interpolated(nt) = &self.kind - && let NtExpr(_) | NtLiteral(_) | NtBlock(_) = &**nt + && let NtBlock(_) = &**nt { true + } else if matches!( + self.is_metavar_seq(), + Some(MetaVarKind::Expr { .. } | MetaVarKind::Literal | MetaVarKind::Path) + ) { + true } else { matches!(self.is_metavar_seq(), Some(MetaVarKind::Path)) } @@ -882,6 +863,7 @@ impl Token { /// Is the token an interpolated block (`$b:block`)? pub fn is_whole_block(&self) -> bool { + #[allow(irrefutable_let_patterns)] // FIXME: temporary if let Interpolated(nt) = &self.kind && let NtBlock(..) = &**nt { @@ -1100,8 +1082,6 @@ pub enum NtExprKind { /// For interpolation during macro expansion. pub enum Nonterminal { NtBlock(P), - NtExpr(P), - NtLiteral(P), } #[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)] @@ -1191,15 +1171,12 @@ impl Nonterminal { pub fn use_span(&self) -> Span { match self { NtBlock(block) => block.span, - NtExpr(expr) | NtLiteral(expr) => expr.span, } } pub fn descr(&self) -> &'static str { match self { NtBlock(..) => "block", - NtExpr(..) => "expression", - NtLiteral(..) => "literal", } } } @@ -1218,8 +1195,6 @@ impl fmt::Debug for Nonterminal { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { NtBlock(..) => f.pad("NtBlock(..)"), - NtExpr(..) => f.pad("NtExpr(..)"), - NtLiteral(..) => f.pad("NtLiteral(..)"), } } } @@ -1242,7 +1217,7 @@ mod size_asserts { // tidy-alphabetical-start static_assert_size!(Lit, 12); static_assert_size!(LitKind, 2); - static_assert_size!(Nonterminal, 16); + static_assert_size!(Nonterminal, 8); static_assert_size!(Token, 24); static_assert_size!(TokenKind, 16); // tidy-alphabetical-end diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index bdd244be6d1c..161f8e67551f 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -462,7 +462,6 @@ impl TokenStream { pub fn from_nonterminal_ast(nt: &Nonterminal) -> TokenStream { match nt { Nonterminal::NtBlock(block) => TokenStream::from_ast(block), - Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => TokenStream::from_ast(expr), } } diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index cffa4af6ac3d..6e47ed6eb67c 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -3,11 +3,10 @@ use std::sync::Arc; use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::token::{ - self, Delimiter, IdentIsRaw, InvisibleOrigin, Lit, LitKind, MetaVarKind, Nonterminal, Token, - TokenKind, + self, Delimiter, IdentIsRaw, InvisibleOrigin, Lit, LitKind, MetaVarKind, Token, TokenKind, }; use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; -use rustc_ast::{ExprKind, StmtKind, TyKind}; +use rustc_ast::{ExprKind, StmtKind, TyKind, UnOp}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Diag, DiagCtxtHandle, PResult, pluralize}; use rustc_parse::lexer::nfc_normalize; @@ -340,6 +339,30 @@ pub(super) fn transcribe<'a>( MetaVarKind::Pat(*pat_kind), TokenStream::from_ast(pat), ), + MatchedSingle(ParseNtResult::Expr(expr, kind)) => { + let (can_begin_literal_maybe_minus, can_begin_string_literal) = + match &expr.kind { + ExprKind::Lit(_) => (true, true), + ExprKind::Unary(UnOp::Neg, e) + if matches!(&e.kind, ExprKind::Lit(_)) => + { + (true, false) + } + _ => (false, false), + }; + mk_delimited( + expr.span, + MetaVarKind::Expr { + kind: *kind, + can_begin_literal_maybe_minus, + can_begin_string_literal, + }, + TokenStream::from_ast(expr), + ) + } + MatchedSingle(ParseNtResult::Literal(lit)) => { + mk_delimited(lit.span, MetaVarKind::Literal, TokenStream::from_ast(lit)) + } MatchedSingle(ParseNtResult::Ty(ty)) => { let is_path = matches!(&ty.kind, TyKind::Path(None, _path)); mk_delimited( @@ -869,10 +892,8 @@ fn extract_symbol_from_pnr<'a>( }, _, )) => Ok(*symbol), - ParseNtResult::Nt(nt) - if let Nonterminal::NtLiteral(expr) = &**nt - && let ExprKind::Lit(Lit { kind: LitKind::Str, symbol, suffix: None }) = - &expr.kind => + ParseNtResult::Literal(expr) + if let ExprKind::Lit(Lit { kind: LitKind::Str, symbol, suffix: None }) = &expr.kind => { Ok(*symbol) } diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 24679692a0b0..93fa89b68b97 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -858,7 +858,7 @@ parse_unexpected_parentheses_in_match_arm_pattern = unexpected parentheses surro parse_unexpected_self_in_generic_parameters = unexpected keyword `Self` in generic parameters .note = you cannot use `Self` as a generic parameter because it is reserved for associated items -parse_unexpected_token_after_dot = unexpected token: `{$actual}` +parse_unexpected_token_after_dot = unexpected token: {$actual} parse_unexpected_token_after_label = expected `while`, `for`, `loop` or `{"{"}` after a label .suggestion_remove_label = consider removing the label diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 55cb76878238..dfdef018bc37 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1696,10 +1696,10 @@ pub(crate) struct SelfArgumentPointer { #[derive(Diagnostic)] #[diag(parse_unexpected_token_after_dot)] -pub(crate) struct UnexpectedTokenAfterDot<'a> { +pub(crate) struct UnexpectedTokenAfterDot { #[primary_span] pub span: Span, - pub actual: Cow<'a, str>, + pub actual: String, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 00e75cc2c2fc..424fee968e1d 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -4,10 +4,10 @@ use core::mem; use core::ops::{Bound, ControlFlow}; use ast::mut_visit::{self, MutVisitor}; -use ast::token::{IdentIsRaw, MetaVarKind}; +use ast::token::IdentIsRaw; use ast::{CoroutineKind, ForLoopKind, GenBlockKind, MatchKind, Pat, Path, PathSegment, Recovered}; use rustc_ast::ptr::P; -use rustc_ast::token::{self, Delimiter, Token, TokenKind}; +use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, Token, TokenKind}; use rustc_ast::tokenstream::TokenTree; use rustc_ast::util::case::Case; use rustc_ast::util::classify; @@ -19,7 +19,6 @@ use rustc_ast::{ MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind, YieldKind, }; -use rustc_ast_pretty::pprust; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Applicability, Diag, PResult, StashKey, Subdiagnostic}; use rustc_lexer::unescape::unescape_char; @@ -605,7 +604,7 @@ impl<'a> Parser<'a> { // can't continue an expression after an ident token::Ident(name, is_raw) => token::ident_can_begin_expr(name, t.span, is_raw), token::Literal(..) | token::Pound => true, - _ => t.is_whole_expr(), + _ => t.is_metavar_expr(), }; self.token.is_ident_named(sym::not) && self.look_ahead(1, token_cannot_continue_expr) } @@ -641,6 +640,13 @@ impl<'a> Parser<'a> { TokenKind::NtIdent(..) | TokenKind::NtLifetime(..) | TokenKind::Interpolated(..) => { self.prev_token.span } + TokenKind::CloseDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))) => { + // `expr.span` is the interpolated span, because invisible open + // and close delims both get marked with the same span, one + // that covers the entire thing between them. (See + // `rustc_expand::mbe::transcribe::transcribe`.) + self.prev_token.span + } _ => expr.span, } } @@ -979,12 +985,30 @@ impl<'a> Parser<'a> { } fn error_unexpected_after_dot(&self) { - let actual = pprust::token_to_string(&self.token); + let actual = super::token_descr(&self.token); let span = self.token.span; let sm = self.psess.source_map(); let (span, actual) = match (&self.token.kind, self.subparser_name) { - (token::Eof, Some(_)) if let Ok(actual) = sm.span_to_snippet(sm.next_point(span)) => { - (span.shrink_to_hi(), actual.into()) + (token::Eof, Some(_)) if let Ok(snippet) = sm.span_to_snippet(sm.next_point(span)) => { + (span.shrink_to_hi(), format!("`{}`", snippet)) + } + (token::CloseDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))), _) => { + // No need to report an error. This case will only occur when parsing a pasted + // metavariable, and we should have emitted an error when parsing the macro call in + // the first place. E.g. in this code: + // ``` + // macro_rules! m { ($e:expr) => { $e }; } + // + // fn main() { + // let f = 1; + // m!(f.); + // } + // ``` + // we'll get an error "unexpected token: `)` when parsing the `m!(f.)`, so we don't + // want to issue a second error when parsing the expansion `«f.»` (where `«`/`»` + // represent the invisible delimiters). + self.dcx().span_delayed_bug(span, "bad dot expr in metavariable"); + return; } _ => (span, actual), }; @@ -1364,17 +1388,31 @@ impl<'a> Parser<'a> { let span = self.token.span; if let token::Interpolated(nt) = &self.token.kind { match &**nt { - token::NtExpr(e) | token::NtLiteral(e) => { - let e = e.clone(); - self.bump(); - return Ok(e); - } token::NtBlock(block) => { let block = block.clone(); self.bump(); return Ok(self.mk_expr(self.prev_token.span, ExprKind::Block(block, None))); } }; + } else if let Some(expr) = self.eat_metavar_seq_with_matcher( + |mv_kind| matches!(mv_kind, MetaVarKind::Expr { .. }), + |this| { + let expr = this.parse_expr(); + // FIXME(nnethercote) Sometimes with expressions we get a trailing comma, possibly + // related to the FIXME in `collect_tokens_for_expr`. Examples are the multi-line + // `assert_eq!` calls involving arguments annotated with `#[rustfmt::skip]` in + // `compiler/rustc_index/src/bit_set/tests.rs`. + if this.token.kind == token::Comma { + this.bump(); + } + expr + }, + ) { + return Ok(expr); + } else if let Some(lit) = + self.eat_metavar_seq(MetaVarKind::Literal, |this| this.parse_literal_maybe_minus()) + { + return Ok(lit); } else if let Some(path) = self.eat_metavar_seq(MetaVarKind::Path, |this| { this.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type)) }) { @@ -2062,87 +2100,107 @@ impl<'a> Parser<'a> { .or_else(|()| self.handle_missing_lit(Parser::mk_meta_item_lit_char)) } - fn recover_after_dot(&mut self) -> Option { - let mut recovered = None; + fn recover_after_dot(&mut self) { if self.token == token::Dot { // Attempt to recover `.4` as `0.4`. We don't currently have any syntax where // dot would follow an optional literal, so we do this unconditionally. - recovered = self.look_ahead(1, |next_token| { + let recovered = self.look_ahead(1, |next_token| { + // If it's an integer that looks like a float, then recover as such. + // + // We will never encounter the exponent part of a floating + // point literal here, since there's no use of the exponent + // syntax that also constitutes a valid integer, so we need + // not check for that. if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) = next_token.kind + && suffix.is_none_or(|s| s == sym::f32 || s == sym::f64) + && symbol.as_str().chars().all(|c| c.is_numeric() || c == '_') + && self.token.span.hi() == next_token.span.lo() { - // If this integer looks like a float, then recover as such. - // - // We will never encounter the exponent part of a floating - // point literal here, since there's no use of the exponent - // syntax that also constitutes a valid integer, so we need - // not check for that. - if suffix.is_none_or(|s| s == sym::f32 || s == sym::f64) - && symbol.as_str().chars().all(|c| c.is_numeric() || c == '_') - && self.token.span.hi() == next_token.span.lo() - { - let s = String::from("0.") + symbol.as_str(); - let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix); - return Some(Token::new(kind, self.token.span.to(next_token.span))); - } + let s = String::from("0.") + symbol.as_str(); + let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix); + Some(Token::new(kind, self.token.span.to(next_token.span))) + } else { + None } - None }); - if let Some(token) = &recovered { - self.bump(); + if let Some(recovered) = recovered { self.dcx().emit_err(errors::FloatLiteralRequiresIntegerPart { - span: token.span, - suggestion: token.span.shrink_to_lo(), + span: recovered.span, + suggestion: recovered.span.shrink_to_lo(), }); + self.bump(); + self.token = recovered; } } + } - recovered + /// Keep this in sync with `Token::can_begin_literal_maybe_minus` and + /// `Lit::from_token` (excluding unary negation). + fn eat_token_lit(&mut self) -> Option { + match self.token.uninterpolate().kind { + token::Ident(name, IdentIsRaw::No) if name.is_bool_lit() => { + self.bump(); + Some(token::Lit::new(token::Bool, name, None)) + } + token::Literal(token_lit) => { + self.bump(); + Some(token_lit) + } + token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( + MetaVarKind::Literal, + ))) => { + let lit = self + .eat_metavar_seq(MetaVarKind::Literal, |this| this.parse_literal_maybe_minus()) + .expect("metavar seq literal"); + let ast::ExprKind::Lit(token_lit) = lit.kind else { + panic!("didn't reparse a literal"); + }; + Some(token_lit) + } + token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( + mv_kind @ MetaVarKind::Expr { can_begin_literal_maybe_minus: true, .. }, + ))) => { + let expr = self + .eat_metavar_seq(mv_kind, |this| this.parse_expr()) + .expect("metavar seq expr"); + let ast::ExprKind::Lit(token_lit) = expr.kind else { + panic!("didn't reparse an expr"); + }; + Some(token_lit) + } + _ => None, + } } /// Matches `lit = true | false | token_lit`. /// Returns `None` if the next token is not a literal. - pub(super) fn parse_opt_token_lit(&mut self) -> Option<(token::Lit, Span)> { - let recovered = self.recover_after_dot(); - let token = recovered.as_ref().unwrap_or(&self.token); - let span = token.span; - - token::Lit::from_token(token).map(|token_lit| { - self.bump(); - (token_lit, span) - }) + fn parse_opt_token_lit(&mut self) -> Option<(token::Lit, Span)> { + self.recover_after_dot(); + let span = self.token.span; + self.eat_token_lit().map(|token_lit| (token_lit, span)) } /// Matches `lit = true | false | token_lit`. /// Returns `None` if the next token is not a literal. - pub(super) fn parse_opt_meta_item_lit(&mut self) -> Option { - let recovered = self.recover_after_dot(); - let token = recovered.as_ref().unwrap_or(&self.token); - match token::Lit::from_token(token) { - Some(lit) => { - match MetaItemLit::from_token_lit(lit, token.span) { - Ok(lit) => { - self.bump(); - Some(lit) - } - Err(err) => { - let span = token.uninterpolated_span(); - self.bump(); - let guar = report_lit_error(self.psess, err, lit, span); - // Pack possible quotes and prefixes from the original literal into - // the error literal's symbol so they can be pretty-printed faithfully. - let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None); - let symbol = Symbol::intern(&suffixless_lit.to_string()); - let lit = token::Lit::new(token::Err(guar), symbol, lit.suffix); - Some( - MetaItemLit::from_token_lit(lit, span) - .unwrap_or_else(|_| unreachable!()), - ) - } + fn parse_opt_meta_item_lit(&mut self) -> Option { + self.recover_after_dot(); + let span = self.token.span; + let uninterpolated_span = self.uninterpolated_token_span(); + self.eat_token_lit().map(|token_lit| { + match MetaItemLit::from_token_lit(token_lit, span) { + Ok(lit) => lit, + Err(err) => { + let guar = report_lit_error(&self.psess, err, token_lit, uninterpolated_span); + // Pack possible quotes and prefixes from the original literal into + // the error literal's symbol so they can be pretty-printed faithfully. + let suffixless_lit = token::Lit::new(token_lit.kind, token_lit.symbol, None); + let symbol = Symbol::intern(&suffixless_lit.to_string()); + let token_lit = token::Lit::new(token::Err(guar), symbol, token_lit.suffix); + MetaItemLit::from_token_lit(token_lit, uninterpolated_span).unwrap() } } - None => None, - } + }) } pub(super) fn expect_no_tuple_index_suffix(&self, span: Span, suffix: Symbol) { @@ -2166,9 +2224,10 @@ impl<'a> Parser<'a> { /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`). /// Keep this in sync with `Token::can_begin_literal_maybe_minus`. pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P> { - if let token::Interpolated(nt) = &self.token.kind { - match &**nt { - // FIXME(nnethercote) The `NtExpr` case should only match if + if let Some(expr) = self.eat_metavar_seq_with_matcher( + |mv_kind| matches!(mv_kind, MetaVarKind::Expr { .. }), + |this| { + // FIXME(nnethercote) The `expr` case should only match if // `e` is an `ExprKind::Lit` or an `ExprKind::Unary` containing // an `UnOp::Neg` and an `ExprKind::Lit`, like how // `can_begin_literal_maybe_minus` works. But this method has @@ -2178,13 +2237,14 @@ impl<'a> Parser<'a> { // `ExprKind::Path` must be accepted when parsing range // patterns. That requires some care. So for now, we continue // being less strict here than we should be. - token::NtExpr(e) | token::NtLiteral(e) => { - let e = e.clone(); - self.bump(); - return Ok(e); - } - _ => {} - }; + this.parse_expr() + }, + ) { + return Ok(expr); + } else if let Some(lit) = + self.eat_metavar_seq(MetaVarKind::Literal, |this| this.parse_literal_maybe_minus()) + { + return Ok(lit); } let lo = self.token.span; diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index e93fb2473fbf..20833a0f70f2 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1290,12 +1290,24 @@ impl<'a> Parser<'a> { } fn is_unsafe_foreign_mod(&self) -> bool { - self.token.is_keyword(kw::Unsafe) - && self.is_keyword_ahead(1, &[kw::Extern]) - && self.look_ahead( - 2 + self.look_ahead(2, |t| t.can_begin_string_literal() as usize), - |t| *t == token::OpenDelim(Delimiter::Brace), - ) + // Look for `unsafe`. + if !self.token.is_keyword(kw::Unsafe) { + return false; + } + // Look for `extern`. + if !self.is_keyword_ahead(1, &[kw::Extern]) { + return false; + } + + // Look for the optional ABI string literal. + let n = if self.look_ahead(2, |t| t.can_begin_string_literal()) { 3 } else { 2 }; + + // Look for the `{`. Use `tree_look_ahead` because the ABI (if present) + // might be a metavariable i.e. an invisible-delimited sequence, and + // `tree_look_ahead` will consider that a single element when looking + // ahead. + self.tree_look_ahead(n, |t| matches!(t, TokenTree::Delimited(_, _, Delimiter::Brace, _))) + == Some(true) } fn is_static_global(&mut self) -> bool { @@ -2604,13 +2616,36 @@ impl<'a> Parser<'a> { }) // `extern ABI fn` || self.check_keyword_case(exp!(Extern), case) + // Use `tree_look_ahead` because `ABI` might be a metavariable, + // i.e. an invisible-delimited sequence, and `tree_look_ahead` + // will consider that a single element when looking ahead. && self.look_ahead(1, |t| t.can_begin_string_literal()) - && (self.look_ahead(2, |t| t.is_keyword_case(kw::Fn, case)) || + && (self.tree_look_ahead(2, |tt| { + match tt { + TokenTree::Token(t, _) => t.is_keyword_case(kw::Fn, case), + TokenTree::Delimited(..) => false, + } + }) == Some(true) || // This branch is only for better diagnostics; `pub`, `unsafe`, etc. are not // allowed here. (self.may_recover() - && self.look_ahead(2, |t| ALL_QUALS.iter().any(|exp| t.is_keyword(exp.kw))) - && self.look_ahead(3, |t| t.is_keyword_case(kw::Fn, case)))) + && self.tree_look_ahead(2, |tt| { + match tt { + TokenTree::Token(t, _) => + ALL_QUALS.iter().any(|exp| { + t.is_keyword(exp.kw) + }), + TokenTree::Delimited(..) => false, + } + }) == Some(true) + && self.tree_look_ahead(3, |tt| { + match tt { + TokenTree::Token(t, _) => t.is_keyword_case(kw::Fn, case), + TokenTree::Delimited(..) => false, + } + }) == Some(true) + ) + ) } /// Parses all the "front matter" (or "qualifiers") for a `fn` declaration, diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index d865fd427641..a08fbde52a7c 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -24,8 +24,8 @@ pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma}; use path::PathStyle; use rustc_ast::ptr::P; use rustc_ast::token::{ - self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, Nonterminal, NtPatKind, Token, - TokenKind, + self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, Nonterminal, NtExprKind, NtPatKind, + Token, TokenKind, }; use rustc_ast::tokenstream::{AttrsTarget, Spacing, TokenStream, TokenTree}; use rustc_ast::util::case::Case; @@ -101,6 +101,7 @@ pub enum ForceCollect { #[macro_export] macro_rules! maybe_whole { ($p:expr, $constructor:ident, |$x:ident| $e:expr) => { + #[allow(irrefutable_let_patterns)] // FIXME: temporary if let token::Interpolated(nt) = &$p.token.kind && let token::$constructor(x) = &**nt { @@ -299,6 +300,10 @@ impl TokenTreeCursor { self.stream.get(self.index) } + fn look_ahead(&self, n: usize) -> Option<&TokenTree> { + self.stream.get(self.index + n) + } + #[inline] fn bump(&mut self) { self.index += 1; @@ -1290,6 +1295,17 @@ impl<'a> Parser<'a> { looker(&token) } + /// Like `lookahead`, but skips over token trees rather than tokens. Useful + /// when looking past possible metavariable pasting sites. + pub fn tree_look_ahead( + &self, + dist: usize, + looker: impl FnOnce(&TokenTree) -> R, + ) -> Option { + assert_ne!(dist, 0); + self.token_cursor.curr.look_ahead(dist - 1).map(looker) + } + /// Returns whether any of the given keywords are `dist` tokens ahead of the current one. pub(crate) fn is_keyword_ahead(&self, dist: usize, kws: &[Symbol]) -> bool { self.look_ahead(dist, |t| kws.iter().any(|&kw| t.is_keyword(kw))) @@ -1706,6 +1722,16 @@ impl<'a> Parser<'a> { pub fn approx_token_stream_pos(&self) -> u32 { self.num_bump_calls } + + pub fn uninterpolated_token_span(&self) -> Span { + match &self.token.kind { + token::Interpolated(nt) => nt.use_span(), + token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))) => { + self.look_ahead(1, |t| t.span) + } + _ => self.token.span, + } + } } pub(crate) fn make_unclosed_delims_error( @@ -1758,6 +1784,8 @@ pub enum ParseNtResult { Item(P), Stmt(P), Pat(P, NtPatKind), + Expr(P, NtExprKind), + Literal(P), Ty(P), Meta(P), Path(P), diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 1123755ce003..b4e540d670d1 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -48,10 +48,6 @@ impl<'a> Parser<'a> { /// Old variant of `may_be_ident`. Being phased out. fn nt_may_be_ident(nt: &Nonterminal) -> bool { match nt { - NtExpr(_) - | NtLiteral(_) // `true`, `false` - => true, - NtBlock(_) => false, } } @@ -95,7 +91,7 @@ impl<'a> Parser<'a> { token::OpenDelim(Delimiter::Brace) => true, token::NtLifetime(..) => true, token::Interpolated(nt) => match &**nt { - NtBlock(_) | NtExpr(_) | NtLiteral(_) => true, + NtBlock(_) => true, }, token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k { MetaVarKind::Block @@ -179,10 +175,14 @@ impl<'a> Parser<'a> { pat_kind, )); } - NonterminalKind::Expr(_) => NtExpr(self.parse_expr_force_collect()?), + NonterminalKind::Expr(expr_kind) => { + return Ok(ParseNtResult::Expr(self.parse_expr_force_collect()?, expr_kind)); + } NonterminalKind::Literal => { - // The `:literal` matcher does not support attributes - NtLiteral(self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?) + // The `:literal` matcher does not support attributes. + return Ok(ParseNtResult::Literal( + self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?, + )); } NonterminalKind::Ty => { return Ok(ParseNtResult::Ty( diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 174cc929fa70..9612f71b2af9 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1252,7 +1252,7 @@ impl<'a> Parser<'a> { || *t == token::Dot // e.g. `.5` for recovery; || matches!(t.kind, token::Literal(..) | token::Minus) || t.is_bool_lit() - || t.is_whole_expr() + || t.is_metavar_expr() || t.is_lifetime() // recover `'a` instead of `'a'` || (self.may_recover() // recover leading `(` && *t == token::OpenDelim(Delimiter::Parenthesis) diff --git a/tests/ui/attributes/nonterminal-expansion.rs b/tests/ui/attributes/nonterminal-expansion.rs index 83c8f00999a7..004a8a23fd61 100644 --- a/tests/ui/attributes/nonterminal-expansion.rs +++ b/tests/ui/attributes/nonterminal-expansion.rs @@ -5,8 +5,7 @@ macro_rules! pass_nonterminal { ($n:expr) => { #[repr(align($n))] - //~^ ERROR expected unsuffixed literal, found expression `n!()` - //~^^ ERROR incorrect `repr(align)` attribute format: `align` expects a literal integer as argument [E0693] + //~^ ERROR expected unsuffixed literal, found `expr` metavariable struct S; }; } @@ -16,5 +15,6 @@ macro_rules! n { } pass_nonterminal!(n!()); +//~^ ERROR incorrect `repr(align)` attribute format: `align` expects a literal integer as argument [E0693] fn main() {} diff --git a/tests/ui/attributes/nonterminal-expansion.stderr b/tests/ui/attributes/nonterminal-expansion.stderr index 8a85731bd5a1..9c6cb98f6196 100644 --- a/tests/ui/attributes/nonterminal-expansion.stderr +++ b/tests/ui/attributes/nonterminal-expansion.stderr @@ -1,4 +1,4 @@ -error: expected unsuffixed literal, found expression `n!()` +error: expected unsuffixed literal, found `expr` metavariable --> $DIR/nonterminal-expansion.rs:7:22 | LL | #[repr(align($n))] @@ -10,15 +10,10 @@ LL | pass_nonterminal!(n!()); = note: this error originates in the macro `pass_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0693]: incorrect `repr(align)` attribute format: `align` expects a literal integer as argument - --> $DIR/nonterminal-expansion.rs:7:22 + --> $DIR/nonterminal-expansion.rs:17:19 | -LL | #[repr(align($n))] - | ^^ -... LL | pass_nonterminal!(n!()); - | ----------------------- in this macro invocation - | - = note: this error originates in the macro `pass_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info) + | ^ error: aborting due to 2 previous errors diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs index 416145a0c156..47418b4e091b 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs @@ -28,7 +28,7 @@ struct S9; macro_rules! generate_s10 { ($expr: expr) => { #[cfg(feature = $expr)] - //~^ ERROR expected unsuffixed literal, found expression `concat!("nonexistent")` + //~^ ERROR expected unsuffixed literal, found `expr` metavariable struct S10; } } diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr index d02d0d70a8bc..66ce2ee98589 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr @@ -54,7 +54,7 @@ LL | #[cfg(a = b"hi")] | | | help: consider removing the prefix -error: expected unsuffixed literal, found expression `concat!("nonexistent")` +error: expected unsuffixed literal, found `expr` metavariable --> $DIR/cfg-attr-syntax-validation.rs:30:25 | LL | #[cfg(feature = $expr)] diff --git a/tests/ui/macros/nonterminal-matching.rs b/tests/ui/macros/nonterminal-matching.rs index b0a7f3e4650f..a03ede20c549 100644 --- a/tests/ui/macros/nonterminal-matching.rs +++ b/tests/ui/macros/nonterminal-matching.rs @@ -29,8 +29,8 @@ macro_rules! foo { (ident $x:ident) => { bar!(ident $x); }; (lifetime $x:lifetime) => { bar!(lifetime $x); }; (tt $x:tt) => { bar!(tt $x); }; - (expr $x:expr) => { bar!(expr $x); }; //~ ERROR: no rules expected expression `3` - (literal $x:literal) => { bar!(literal $x); }; //~ ERROR: no rules expected literal `4` + (expr $x:expr) => { bar!(expr $x); }; //~ ERROR: no rules expected `expr` metavariable + (literal $x:literal) => { bar!(literal $x); }; //~ ERROR: no rules expected `literal` metavariable (path $x:path) => { bar!(path $x); }; //~ ERROR: no rules expected `path` metavariable (stmt $x:stmt) => { bar!(stmt $x); }; //~ ERROR: no rules expected `stmt` metavariable } diff --git a/tests/ui/macros/nonterminal-matching.stderr b/tests/ui/macros/nonterminal-matching.stderr index 2d9252fbfc1f..d01561415664 100644 --- a/tests/ui/macros/nonterminal-matching.stderr +++ b/tests/ui/macros/nonterminal-matching.stderr @@ -23,7 +23,7 @@ LL | complex_nonterminal!(enum E {}); = help: try using `:tt` instead in the macro definition = note: this error originates in the macro `complex_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info) -error: no rules expected expression `3` +error: no rules expected `expr` metavariable --> $DIR/nonterminal-matching.rs:32:35 | LL | (expr $x:expr) => { bar!(expr $x); }; @@ -45,7 +45,7 @@ LL | (expr 3) => {}; = help: try using `:tt` instead in the macro definition = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) -error: no rules expected literal `4` +error: no rules expected `literal` metavariable --> $DIR/nonterminal-matching.rs:33:44 | LL | (literal $x:literal) => { bar!(literal $x); }; diff --git a/tests/ui/parser/extern-abi-from-mac-literal-frag.rs b/tests/ui/parser/extern-abi-from-mac-literal-frag.rs index a4e9134218ce..12b6c98705ce 100644 --- a/tests/ui/parser/extern-abi-from-mac-literal-frag.rs +++ b/tests/ui/parser/extern-abi-from-mac-literal-frag.rs @@ -12,6 +12,8 @@ macro_rules! abi_from_lit_frag { fn _import(); } + unsafe extern $abi {} + extern $abi fn _export() {} type _PTR = extern $abi fn(); @@ -24,6 +26,8 @@ macro_rules! abi_from_expr_frag { fn _import(); } + unsafe extern $abi {} + extern $abi fn _export() {} type _PTR = extern $abi fn(); diff --git a/tests/ui/parser/float-field-interpolated.rs b/tests/ui/parser/float-field-interpolated.rs index 990f2926dc86..bf7163039c42 100644 --- a/tests/ui/parser/float-field-interpolated.rs +++ b/tests/ui/parser/float-field-interpolated.rs @@ -5,10 +5,10 @@ macro_rules! generate_field_accesses { let s = S(0, (0, 0)); s.$a; // OK - { s.$b; } //~ ERROR unexpected token: `1.1` - //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found literal `1.1` - { s.$c; } //~ ERROR unexpected token: `1.1` - //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found expression `1.1` + { s.$b; } //~ ERROR unexpected token: `literal` metavariable + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `literal` metavariable + { s.$c; } //~ ERROR unexpected token: `expr` metavariable + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `expr` metavariable }; } diff --git a/tests/ui/parser/float-field-interpolated.stderr b/tests/ui/parser/float-field-interpolated.stderr index 2a1a4926cb3c..e2b7e3a7dbe7 100644 --- a/tests/ui/parser/float-field-interpolated.stderr +++ b/tests/ui/parser/float-field-interpolated.stderr @@ -1,4 +1,4 @@ -error: unexpected token: `1.1` +error: unexpected token: `literal` metavariable --> $DIR/float-field-interpolated.rs:8:13 | LL | { s.$b; } @@ -9,7 +9,7 @@ LL | generate_field_accesses!(1.1, 1.1, 1.1); | = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info) -error: expected one of `.`, `;`, `?`, `}`, or an operator, found literal `1.1` +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `literal` metavariable --> $DIR/float-field-interpolated.rs:8:13 | LL | { s.$b; } @@ -20,7 +20,7 @@ LL | generate_field_accesses!(1.1, 1.1, 1.1); | = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info) -error: unexpected token: `1.1` +error: unexpected token: `expr` metavariable --> $DIR/float-field-interpolated.rs:10:13 | LL | { s.$c; } @@ -31,7 +31,7 @@ LL | generate_field_accesses!(1.1, 1.1, 1.1); | = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info) -error: expected one of `.`, `;`, `?`, `}`, or an operator, found expression `1.1` +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `expr` metavariable --> $DIR/float-field-interpolated.rs:10:13 | LL | { s.$c; } diff --git a/tests/ui/parser/macro/trait-non-item-macros.rs b/tests/ui/parser/macro/trait-non-item-macros.rs index e93000193b6e..b4140613cbae 100644 --- a/tests/ui/parser/macro/trait-non-item-macros.rs +++ b/tests/ui/parser/macro/trait-non-item-macros.rs @@ -1,7 +1,7 @@ macro_rules! bah { ($a:expr) => { $a - }; //~^ ERROR macro expansion ignores expression `2` and any tokens following + }; //~^ ERROR macro expansion ignores `expr` metavariable and any tokens following } trait Bar { diff --git a/tests/ui/parser/macro/trait-non-item-macros.stderr b/tests/ui/parser/macro/trait-non-item-macros.stderr index 1a8284837789..62b42fa8b8dd 100644 --- a/tests/ui/parser/macro/trait-non-item-macros.stderr +++ b/tests/ui/parser/macro/trait-non-item-macros.stderr @@ -1,4 +1,4 @@ -error: macro expansion ignores expression `2` and any tokens following +error: macro expansion ignores `expr` metavariable and any tokens following --> $DIR/trait-non-item-macros.rs:3:9 | LL | $a diff --git a/tests/ui/proc-macro/macro-rules-derive-cfg.stdout b/tests/ui/proc-macro/macro-rules-derive-cfg.stdout index c1e46b50d40c..9482b2784d22 100644 --- a/tests/ui/proc-macro/macro-rules-derive-cfg.stdout +++ b/tests/ui/proc-macro/macro-rules-derive-cfg.stdout @@ -1,8 +1,9 @@ PRINT-DERIVE INPUT (DISPLAY): struct -Foo([bool; #[rustc_dummy(first)] #[rustc_dummy(second)] -{ #![rustc_dummy(third)] #[rustc_dummy(fourth)] 30 }]); +Foo([bool; #[rustc_dummy(first)] +#[rustc_dummy(second)] { #![rustc_dummy(third)] #[rustc_dummy(fourth)] 30 }]); PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): struct -Foo([bool; #[rustc_dummy(first)] #[rustc_dummy(second)] +Foo([bool; #[rustc_dummy(first)] +#[rustc_dummy(second)] { #! [rustc_dummy(third)] #[rustc_dummy(fourth)] 30 }]); PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { @@ -53,97 +54,103 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ ], span: $DIR/macro-rules-derive-cfg.rs:18:21: 18:63 (#3), }, - Punct { - ch: '#', - spacing: Alone, - span: $DIR/macro-rules-derive-cfg.rs:23:13: 23:14 (#0), - }, Group { - delimiter: Bracket, - stream: TokenStream [ - Ident { - ident: "rustc_dummy", - span: $DIR/macro-rules-derive-cfg.rs:23:36: 23:47 (#0), - }, - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - ident: "second", - span: $DIR/macro-rules-derive-cfg.rs:23:48: 23:54 (#0), - }, - ], - span: $DIR/macro-rules-derive-cfg.rs:23:47: 23:55 (#0), - }, - ], - span: $DIR/macro-rules-derive-cfg.rs:23:14: 23:57 (#0), - }, - Group { - delimiter: Brace, + delimiter: None, stream: TokenStream [ Punct { ch: '#', - spacing: Joint, - span: $DIR/macro-rules-derive-cfg.rs:24:5: 24:6 (#0), - }, - Punct { - ch: '!', spacing: Alone, - span: $DIR/macro-rules-derive-cfg.rs:24:6: 24:7 (#0), + span: $DIR/macro-rules-derive-cfg.rs:23:13: 23:14 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "rustc_dummy", - span: $DIR/macro-rules-derive-cfg.rs:24:29: 24:40 (#0), + span: $DIR/macro-rules-derive-cfg.rs:23:36: 23:47 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { - ident: "third", - span: $DIR/macro-rules-derive-cfg.rs:24:41: 24:46 (#0), + ident: "second", + span: $DIR/macro-rules-derive-cfg.rs:23:48: 23:54 (#0), }, ], - span: $DIR/macro-rules-derive-cfg.rs:24:40: 24:47 (#0), + span: $DIR/macro-rules-derive-cfg.rs:23:47: 23:55 (#0), }, ], - span: $DIR/macro-rules-derive-cfg.rs:24:7: 24:49 (#0), - }, - Punct { - ch: '#', - spacing: Alone, - span: $DIR/macro-rules-derive-cfg.rs:25:5: 25:6 (#0), + span: $DIR/macro-rules-derive-cfg.rs:23:14: 23:57 (#0), }, Group { - delimiter: Bracket, + delimiter: Brace, stream: TokenStream [ - Ident { - ident: "rustc_dummy", - span: $DIR/macro-rules-derive-cfg.rs:25:28: 25:39 (#0), + Punct { + ch: '#', + spacing: Joint, + span: $DIR/macro-rules-derive-cfg.rs:24:5: 24:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/macro-rules-derive-cfg.rs:24:6: 24:7 (#0), }, Group { - delimiter: Parenthesis, + delimiter: Bracket, stream: TokenStream [ Ident { - ident: "fourth", - span: $DIR/macro-rules-derive-cfg.rs:25:40: 25:46 (#0), + ident: "rustc_dummy", + span: $DIR/macro-rules-derive-cfg.rs:24:29: 24:40 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "third", + span: $DIR/macro-rules-derive-cfg.rs:24:41: 24:46 (#0), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:24:40: 24:47 (#0), }, ], - span: $DIR/macro-rules-derive-cfg.rs:25:39: 25:47 (#0), + span: $DIR/macro-rules-derive-cfg.rs:24:7: 24:49 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/macro-rules-derive-cfg.rs:25:5: 25:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/macro-rules-derive-cfg.rs:25:28: 25:39 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "fourth", + span: $DIR/macro-rules-derive-cfg.rs:25:40: 25:46 (#0), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:25:39: 25:47 (#0), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:25:6: 25:49 (#0), + }, + Literal { + kind: Integer, + symbol: "30", + suffix: None, + span: $DIR/macro-rules-derive-cfg.rs:26:5: 26:7 (#0), }, ], - span: $DIR/macro-rules-derive-cfg.rs:25:6: 25:49 (#0), - }, - Literal { - kind: Integer, - symbol: "30", - suffix: None, - span: $DIR/macro-rules-derive-cfg.rs:26:5: 26:7 (#0), + span: $DIR/macro-rules-derive-cfg.rs:23:58: 27:2 (#0), }, ], - span: $DIR/macro-rules-derive-cfg.rs:23:58: 27:2 (#0), + span: $DIR/macro-rules-derive-cfg.rs:18:64: 18:69 (#3), }, ], span: $DIR/macro-rules-derive-cfg.rs:18:13: 18:70 (#3), diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs index 4b2fc4a03b62..110c03d0e549 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs @@ -59,8 +59,10 @@ fn _macros() { } use_expr!((let 0 = 1 && 0 == 0)); //~^ ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement use_expr!((let 0 = 1)); //~^ ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement match () { #[cfg(FALSE)] () if let 0 = 1 => {} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr index 1c710b04897c..0997f0c81a01 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr @@ -124,15 +124,33 @@ LL | use_expr!((let 0 = 1 && 0 == 0)); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/feature-gate.rs:62:16 + --> $DIR/feature-gate.rs:60:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:63:16 | LL | use_expr!((let 0 = 1)); | ^^^ | = note: only supported directly in conditions of `if` and `while` expressions +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:63:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error: no rules expected keyword `let` - --> $DIR/feature-gate.rs:70:15 + --> $DIR/feature-gate.rs:72:15 | LL | macro_rules! use_expr { | --------------------- when calling this macro @@ -202,7 +220,7 @@ LL | () if let Range { start: _, end: _ } = (true..true) && false => {} = help: you can write `if matches!(, )` instead of `if let = ` error[E0658]: `if let` guards are experimental - --> $DIR/feature-gate.rs:66:12 + --> $DIR/feature-gate.rs:68:12 | LL | () if let 0 = 1 => {} | ^^^^^^^^^^^^ @@ -262,6 +280,6 @@ LL | () if let Range { start: _, end: _ } = (true..true) && false => {} = help: add `#![feature(let_chains)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 23 previous errors +error: aborting due to 25 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr index db32b8c1de4f..817e226bc45d 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr @@ -233,7 +233,7 @@ LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:99:9 + --> $DIR/disallowed-positions.rs:103:9 | LL | if &let 0 = 0 {} | ^^^^^^^^^ @@ -241,7 +241,7 @@ LL | if &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:102:9 + --> $DIR/disallowed-positions.rs:106:9 | LL | if !let 0 = 0 {} | ^^^^^^^^^ @@ -249,7 +249,7 @@ LL | if !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:104:9 + --> $DIR/disallowed-positions.rs:108:9 | LL | if *let 0 = 0 {} | ^^^^^^^^^ @@ -257,7 +257,7 @@ LL | if *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:106:9 + --> $DIR/disallowed-positions.rs:110:9 | LL | if -let 0 = 0 {} | ^^^^^^^^^ @@ -265,7 +265,7 @@ LL | if -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:114:9 + --> $DIR/disallowed-positions.rs:118:9 | LL | if (let 0 = 0)? {} | ^^^^^^^^^ @@ -273,20 +273,20 @@ LL | if (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:117:16 + --> $DIR/disallowed-positions.rs:121:16 | LL | if true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:117:13 + --> $DIR/disallowed-positions.rs:121:13 | LL | if true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:119:17 + --> $DIR/disallowed-positions.rs:123:17 | LL | if (true || let 0 = 0) {} | ^^^^^^^^^ @@ -294,7 +294,7 @@ LL | if (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:121:25 + --> $DIR/disallowed-positions.rs:125:25 | LL | if true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -302,7 +302,7 @@ LL | if true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:123:25 + --> $DIR/disallowed-positions.rs:127:25 | LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -310,7 +310,7 @@ LL | if true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:127:12 + --> $DIR/disallowed-positions.rs:131:12 | LL | if x = let 0 = 0 {} | ^^^ @@ -318,7 +318,7 @@ LL | if x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:130:15 + --> $DIR/disallowed-positions.rs:134:15 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^ @@ -326,7 +326,7 @@ LL | if true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:133:11 + --> $DIR/disallowed-positions.rs:137:11 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^ @@ -334,7 +334,7 @@ LL | if ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:135:9 + --> $DIR/disallowed-positions.rs:139:9 | LL | if (let 0 = 0).. {} | ^^^^^^^^^ @@ -342,7 +342,7 @@ LL | if (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:139:8 + --> $DIR/disallowed-positions.rs:143:8 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -350,7 +350,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:142:8 + --> $DIR/disallowed-positions.rs:146:8 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -358,7 +358,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:148:8 + --> $DIR/disallowed-positions.rs:152:8 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -366,7 +366,7 @@ LL | if let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:154:8 + --> $DIR/disallowed-positions.rs:158:8 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -374,7 +374,7 @@ LL | if let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:158:19 + --> $DIR/disallowed-positions.rs:162:19 | LL | if let true = let true = true {} | ^^^ @@ -382,7 +382,7 @@ LL | if let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:161:15 + --> $DIR/disallowed-positions.rs:165:15 | LL | if return let 0 = 0 {} | ^^^ @@ -390,7 +390,7 @@ LL | if return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:164:21 + --> $DIR/disallowed-positions.rs:168:21 | LL | loop { if break let 0 = 0 {} } | ^^^ @@ -398,7 +398,7 @@ LL | loop { if break let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:167:15 + --> $DIR/disallowed-positions.rs:171:15 | LL | if (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -406,7 +406,7 @@ LL | if (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:170:9 + --> $DIR/disallowed-positions.rs:174:9 | LL | if (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -414,7 +414,7 @@ LL | if (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:173:9 + --> $DIR/disallowed-positions.rs:177:9 | LL | if (let 0 = 0,) {} | ^^^^^^^^^ @@ -422,7 +422,7 @@ LL | if (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:177:13 + --> $DIR/disallowed-positions.rs:181:13 | LL | if (let 0 = 0).await {} | ^^^^^^^^^ @@ -430,7 +430,7 @@ LL | if (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:181:12 + --> $DIR/disallowed-positions.rs:185:12 | LL | if (|| let 0 = 0) {} | ^^^ @@ -438,7 +438,7 @@ LL | if (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:184:9 + --> $DIR/disallowed-positions.rs:188:9 | LL | if (let 0 = 0)() {} | ^^^^^^^^^ @@ -446,7 +446,7 @@ LL | if (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:190:12 + --> $DIR/disallowed-positions.rs:194:12 | LL | while &let 0 = 0 {} | ^^^^^^^^^ @@ -454,7 +454,7 @@ LL | while &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:193:12 + --> $DIR/disallowed-positions.rs:197:12 | LL | while !let 0 = 0 {} | ^^^^^^^^^ @@ -462,7 +462,7 @@ LL | while !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:195:12 + --> $DIR/disallowed-positions.rs:199:12 | LL | while *let 0 = 0 {} | ^^^^^^^^^ @@ -470,7 +470,7 @@ LL | while *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:197:12 + --> $DIR/disallowed-positions.rs:201:12 | LL | while -let 0 = 0 {} | ^^^^^^^^^ @@ -478,7 +478,7 @@ LL | while -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:205:12 + --> $DIR/disallowed-positions.rs:209:12 | LL | while (let 0 = 0)? {} | ^^^^^^^^^ @@ -486,20 +486,20 @@ LL | while (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:208:19 + --> $DIR/disallowed-positions.rs:212:19 | LL | while true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:208:16 + --> $DIR/disallowed-positions.rs:212:16 | LL | while true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:210:20 + --> $DIR/disallowed-positions.rs:214:20 | LL | while (true || let 0 = 0) {} | ^^^^^^^^^ @@ -507,7 +507,7 @@ LL | while (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:212:28 + --> $DIR/disallowed-positions.rs:216:28 | LL | while true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -515,7 +515,7 @@ LL | while true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:214:28 + --> $DIR/disallowed-positions.rs:218:28 | LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -523,7 +523,7 @@ LL | while true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:218:15 + --> $DIR/disallowed-positions.rs:222:15 | LL | while x = let 0 = 0 {} | ^^^ @@ -531,7 +531,7 @@ LL | while x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:221:18 + --> $DIR/disallowed-positions.rs:225:18 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^ @@ -539,7 +539,7 @@ LL | while true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:224:14 + --> $DIR/disallowed-positions.rs:228:14 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^ @@ -547,7 +547,7 @@ LL | while ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:226:12 + --> $DIR/disallowed-positions.rs:230:12 | LL | while (let 0 = 0).. {} | ^^^^^^^^^ @@ -555,7 +555,7 @@ LL | while (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:230:11 + --> $DIR/disallowed-positions.rs:234:11 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -563,7 +563,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:233:11 + --> $DIR/disallowed-positions.rs:237:11 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -571,7 +571,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:239:11 + --> $DIR/disallowed-positions.rs:243:11 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -579,7 +579,7 @@ LL | while let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:245:11 + --> $DIR/disallowed-positions.rs:249:11 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -587,7 +587,7 @@ LL | while let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:249:22 + --> $DIR/disallowed-positions.rs:253:22 | LL | while let true = let true = true {} | ^^^ @@ -595,7 +595,7 @@ LL | while let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:252:18 + --> $DIR/disallowed-positions.rs:256:18 | LL | while return let 0 = 0 {} | ^^^ @@ -603,7 +603,7 @@ LL | while return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:255:39 + --> $DIR/disallowed-positions.rs:259:39 | LL | 'outer: loop { while break 'outer let 0 = 0 {} } | ^^^ @@ -611,7 +611,7 @@ LL | 'outer: loop { while break 'outer let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:258:18 + --> $DIR/disallowed-positions.rs:262:18 | LL | while (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -619,7 +619,7 @@ LL | while (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:261:12 + --> $DIR/disallowed-positions.rs:265:12 | LL | while (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -627,7 +627,7 @@ LL | while (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:264:12 + --> $DIR/disallowed-positions.rs:268:12 | LL | while (let 0 = 0,) {} | ^^^^^^^^^ @@ -635,7 +635,7 @@ LL | while (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:268:16 + --> $DIR/disallowed-positions.rs:272:16 | LL | while (let 0 = 0).await {} | ^^^^^^^^^ @@ -643,7 +643,7 @@ LL | while (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:272:15 + --> $DIR/disallowed-positions.rs:276:15 | LL | while (|| let 0 = 0) {} | ^^^ @@ -651,7 +651,7 @@ LL | while (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:275:12 + --> $DIR/disallowed-positions.rs:279:12 | LL | while (let 0 = 0)() {} | ^^^^^^^^^ @@ -659,7 +659,7 @@ LL | while (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:292:6 + --> $DIR/disallowed-positions.rs:296:6 | LL | &let 0 = 0; | ^^^ @@ -667,7 +667,7 @@ LL | &let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:295:6 + --> $DIR/disallowed-positions.rs:299:6 | LL | !let 0 = 0; | ^^^ @@ -675,7 +675,7 @@ LL | !let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:297:6 + --> $DIR/disallowed-positions.rs:301:6 | LL | *let 0 = 0; | ^^^ @@ -683,7 +683,7 @@ LL | *let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:299:6 + --> $DIR/disallowed-positions.rs:303:6 | LL | -let 0 = 0; | ^^^ @@ -691,7 +691,7 @@ LL | -let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:301:13 + --> $DIR/disallowed-positions.rs:305:13 | LL | let _ = let _ = 3; | ^^^ @@ -699,7 +699,7 @@ LL | let _ = let _ = 3; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:309:6 + --> $DIR/disallowed-positions.rs:313:6 | LL | (let 0 = 0)?; | ^^^ @@ -707,7 +707,7 @@ LL | (let 0 = 0)?; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:312:13 + --> $DIR/disallowed-positions.rs:316:13 | LL | true || let 0 = 0; | ^^^ @@ -715,7 +715,7 @@ LL | true || let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:314:14 + --> $DIR/disallowed-positions.rs:318:14 | LL | (true || let 0 = 0); | ^^^ @@ -723,7 +723,7 @@ LL | (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:316:22 + --> $DIR/disallowed-positions.rs:320:22 | LL | true && (true || let 0 = 0); | ^^^ @@ -731,7 +731,7 @@ LL | true && (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:320:9 + --> $DIR/disallowed-positions.rs:324:9 | LL | x = let 0 = 0; | ^^^ @@ -739,7 +739,7 @@ LL | x = let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:323:12 + --> $DIR/disallowed-positions.rs:327:12 | LL | true..(let 0 = 0); | ^^^ @@ -747,7 +747,7 @@ LL | true..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:325:8 + --> $DIR/disallowed-positions.rs:329:8 | LL | ..(let 0 = 0); | ^^^ @@ -755,7 +755,7 @@ LL | ..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:327:6 + --> $DIR/disallowed-positions.rs:331:6 | LL | (let 0 = 0)..; | ^^^ @@ -763,7 +763,7 @@ LL | (let 0 = 0)..; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:330:6 + --> $DIR/disallowed-positions.rs:334:6 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^ @@ -771,7 +771,7 @@ LL | (let Range { start: _, end: _ } = true..true || false); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:334:6 + --> $DIR/disallowed-positions.rs:338:6 | LL | (let true = let true = true); | ^^^ @@ -779,7 +779,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:334:17 + --> $DIR/disallowed-positions.rs:338:17 | LL | (let true = let true = true); | ^^^ @@ -787,7 +787,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:340:25 + --> $DIR/disallowed-positions.rs:344:25 | LL | let x = true && let y = 1; | ^^^ @@ -795,7 +795,7 @@ LL | let x = true && let y = 1; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:346:19 + --> $DIR/disallowed-positions.rs:350:19 | LL | [1, 2, 3][let _ = ()] | ^^^ @@ -803,7 +803,7 @@ LL | [1, 2, 3][let _ = ()] = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:351:6 + --> $DIR/disallowed-positions.rs:355:6 | LL | &let 0 = 0 | ^^^ @@ -811,7 +811,7 @@ LL | &let 0 = 0 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:362:17 + --> $DIR/disallowed-positions.rs:366:17 | LL | true && let 1 = 1 | ^^^ @@ -819,7 +819,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:367:17 + --> $DIR/disallowed-positions.rs:371:17 | LL | true && let 1 = 1 | ^^^ @@ -827,7 +827,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:372:17 + --> $DIR/disallowed-positions.rs:376:17 | LL | true && let 1 = 1 | ^^^ @@ -835,7 +835,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:383:17 + --> $DIR/disallowed-positions.rs:387:17 | LL | true && let 1 = 1 | ^^^ @@ -843,7 +843,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/disallowed-positions.rs:383:9 + --> $DIR/disallowed-positions.rs:387:9 | LL | true && let 1 = 1 | ^^^^^^^^^^^^^^^^^ @@ -854,124 +854,124 @@ LL | { true && let 1 = 1 } | + + error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:393:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:393:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:401:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:401:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:400:9 + --> $DIR/disallowed-positions.rs:404:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:400:9 + --> $DIR/disallowed-positions.rs:404:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:400:32 + --> $DIR/disallowed-positions.rs:404:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:400:32 + --> $DIR/disallowed-positions.rs:404:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:408:9 + --> $DIR/disallowed-positions.rs:412:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:408:9 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:408:31 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { - | ^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:408:31 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { - | ^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement --> $DIR/disallowed-positions.rs:412:9 | -LL | if (let Some(a) = opt && (let Some(b) = a)) && true { - | ^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:412:9 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && true { +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement --> $DIR/disallowed-positions.rs:412:31 | -LL | if (let Some(a) = opt && (let Some(b) = a)) && true { +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains --> $DIR/disallowed-positions.rs:412:31 | -LL | if (let Some(a) = opt && (let Some(b) = a)) && true { +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement --> $DIR/disallowed-positions.rs:416:9 | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:416:9 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:416:31 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:416:31 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:420:9 + | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:416:9 + --> $DIR/disallowed-positions.rs:420:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:436:22 + --> $DIR/disallowed-positions.rs:440:22 | LL | let x = (true && let y = 1); | ^^^ @@ -979,7 +979,7 @@ LL | let x = (true && let y = 1); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:441:20 + --> $DIR/disallowed-positions.rs:445:20 | LL | ([1, 2, 3][let _ = ()]) | ^^^ @@ -995,15 +995,51 @@ LL | use_expr!((let 0 = 1 && 0 == 0)); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:93:16 + --> $DIR/disallowed-positions.rs:91:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:91:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:95:16 | LL | use_expr!((let 0 = 1)); | ^^^ | = note: only supported directly in conditions of `if` and `while` expressions +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:95:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:95:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:130:8 + --> $DIR/disallowed-positions.rs:134:8 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` @@ -1012,7 +1048,7 @@ LL | if true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:139:12 + --> $DIR/disallowed-positions.rs:143:12 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1023,7 +1059,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:142:12 + --> $DIR/disallowed-positions.rs:146:12 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1034,7 +1070,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:148:12 + --> $DIR/disallowed-positions.rs:152:12 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1045,7 +1081,7 @@ LL | if let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:154:12 + --> $DIR/disallowed-positions.rs:158:12 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1056,7 +1092,7 @@ LL | if let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:110:20 + --> $DIR/disallowed-positions.rs:114:20 | LL | if let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1064,7 +1100,7 @@ LL | if let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:221:11 + --> $DIR/disallowed-positions.rs:225:11 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` @@ -1073,7 +1109,7 @@ LL | while true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:230:15 + --> $DIR/disallowed-positions.rs:234:15 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1084,7 +1120,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:233:15 + --> $DIR/disallowed-positions.rs:237:15 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1095,7 +1131,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:239:15 + --> $DIR/disallowed-positions.rs:243:15 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1106,7 +1142,7 @@ LL | while let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:245:15 + --> $DIR/disallowed-positions.rs:249:15 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1117,7 +1153,7 @@ LL | while let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:201:23 + --> $DIR/disallowed-positions.rs:205:23 | LL | while let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1125,7 +1161,7 @@ LL | while let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:330:10 + --> $DIR/disallowed-positions.rs:334:10 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1136,14 +1172,14 @@ LL | (let Range { start: _, end: _ } = true..true || false); found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:305:17 + --> $DIR/disallowed-positions.rs:309:17 | LL | let 0 = 0?; | ^^ the `?` operator cannot be applied to type `{integer}` | = help: the trait `Try` is not implemented for `{integer}` -error: aborting due to 121 previous errors +error: aborting due to 125 previous errors Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr index ad16a0f8ed81..bab50c22c030 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr @@ -233,7 +233,7 @@ LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:99:9 + --> $DIR/disallowed-positions.rs:103:9 | LL | if &let 0 = 0 {} | ^^^^^^^^^ @@ -241,7 +241,7 @@ LL | if &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:102:9 + --> $DIR/disallowed-positions.rs:106:9 | LL | if !let 0 = 0 {} | ^^^^^^^^^ @@ -249,7 +249,7 @@ LL | if !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:104:9 + --> $DIR/disallowed-positions.rs:108:9 | LL | if *let 0 = 0 {} | ^^^^^^^^^ @@ -257,7 +257,7 @@ LL | if *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:106:9 + --> $DIR/disallowed-positions.rs:110:9 | LL | if -let 0 = 0 {} | ^^^^^^^^^ @@ -265,7 +265,7 @@ LL | if -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:114:9 + --> $DIR/disallowed-positions.rs:118:9 | LL | if (let 0 = 0)? {} | ^^^^^^^^^ @@ -273,20 +273,20 @@ LL | if (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:117:16 + --> $DIR/disallowed-positions.rs:121:16 | LL | if true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:117:13 + --> $DIR/disallowed-positions.rs:121:13 | LL | if true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:119:17 + --> $DIR/disallowed-positions.rs:123:17 | LL | if (true || let 0 = 0) {} | ^^^^^^^^^ @@ -294,7 +294,7 @@ LL | if (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:121:25 + --> $DIR/disallowed-positions.rs:125:25 | LL | if true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -302,7 +302,7 @@ LL | if true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:123:25 + --> $DIR/disallowed-positions.rs:127:25 | LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -310,7 +310,7 @@ LL | if true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:127:12 + --> $DIR/disallowed-positions.rs:131:12 | LL | if x = let 0 = 0 {} | ^^^ @@ -318,7 +318,7 @@ LL | if x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:130:15 + --> $DIR/disallowed-positions.rs:134:15 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^ @@ -326,7 +326,7 @@ LL | if true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:133:11 + --> $DIR/disallowed-positions.rs:137:11 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^ @@ -334,7 +334,7 @@ LL | if ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:135:9 + --> $DIR/disallowed-positions.rs:139:9 | LL | if (let 0 = 0).. {} | ^^^^^^^^^ @@ -342,7 +342,7 @@ LL | if (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:139:8 + --> $DIR/disallowed-positions.rs:143:8 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -350,7 +350,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:142:8 + --> $DIR/disallowed-positions.rs:146:8 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -358,7 +358,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:148:8 + --> $DIR/disallowed-positions.rs:152:8 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -366,7 +366,7 @@ LL | if let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:154:8 + --> $DIR/disallowed-positions.rs:158:8 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -374,7 +374,7 @@ LL | if let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:158:19 + --> $DIR/disallowed-positions.rs:162:19 | LL | if let true = let true = true {} | ^^^ @@ -382,7 +382,7 @@ LL | if let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:161:15 + --> $DIR/disallowed-positions.rs:165:15 | LL | if return let 0 = 0 {} | ^^^ @@ -390,7 +390,7 @@ LL | if return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:164:21 + --> $DIR/disallowed-positions.rs:168:21 | LL | loop { if break let 0 = 0 {} } | ^^^ @@ -398,7 +398,7 @@ LL | loop { if break let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:167:15 + --> $DIR/disallowed-positions.rs:171:15 | LL | if (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -406,7 +406,7 @@ LL | if (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:170:9 + --> $DIR/disallowed-positions.rs:174:9 | LL | if (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -414,7 +414,7 @@ LL | if (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:173:9 + --> $DIR/disallowed-positions.rs:177:9 | LL | if (let 0 = 0,) {} | ^^^^^^^^^ @@ -422,7 +422,7 @@ LL | if (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:177:13 + --> $DIR/disallowed-positions.rs:181:13 | LL | if (let 0 = 0).await {} | ^^^^^^^^^ @@ -430,7 +430,7 @@ LL | if (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:181:12 + --> $DIR/disallowed-positions.rs:185:12 | LL | if (|| let 0 = 0) {} | ^^^ @@ -438,7 +438,7 @@ LL | if (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:184:9 + --> $DIR/disallowed-positions.rs:188:9 | LL | if (let 0 = 0)() {} | ^^^^^^^^^ @@ -446,7 +446,7 @@ LL | if (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:190:12 + --> $DIR/disallowed-positions.rs:194:12 | LL | while &let 0 = 0 {} | ^^^^^^^^^ @@ -454,7 +454,7 @@ LL | while &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:193:12 + --> $DIR/disallowed-positions.rs:197:12 | LL | while !let 0 = 0 {} | ^^^^^^^^^ @@ -462,7 +462,7 @@ LL | while !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:195:12 + --> $DIR/disallowed-positions.rs:199:12 | LL | while *let 0 = 0 {} | ^^^^^^^^^ @@ -470,7 +470,7 @@ LL | while *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:197:12 + --> $DIR/disallowed-positions.rs:201:12 | LL | while -let 0 = 0 {} | ^^^^^^^^^ @@ -478,7 +478,7 @@ LL | while -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:205:12 + --> $DIR/disallowed-positions.rs:209:12 | LL | while (let 0 = 0)? {} | ^^^^^^^^^ @@ -486,20 +486,20 @@ LL | while (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:208:19 + --> $DIR/disallowed-positions.rs:212:19 | LL | while true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:208:16 + --> $DIR/disallowed-positions.rs:212:16 | LL | while true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:210:20 + --> $DIR/disallowed-positions.rs:214:20 | LL | while (true || let 0 = 0) {} | ^^^^^^^^^ @@ -507,7 +507,7 @@ LL | while (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:212:28 + --> $DIR/disallowed-positions.rs:216:28 | LL | while true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -515,7 +515,7 @@ LL | while true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:214:28 + --> $DIR/disallowed-positions.rs:218:28 | LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -523,7 +523,7 @@ LL | while true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:218:15 + --> $DIR/disallowed-positions.rs:222:15 | LL | while x = let 0 = 0 {} | ^^^ @@ -531,7 +531,7 @@ LL | while x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:221:18 + --> $DIR/disallowed-positions.rs:225:18 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^ @@ -539,7 +539,7 @@ LL | while true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:224:14 + --> $DIR/disallowed-positions.rs:228:14 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^ @@ -547,7 +547,7 @@ LL | while ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:226:12 + --> $DIR/disallowed-positions.rs:230:12 | LL | while (let 0 = 0).. {} | ^^^^^^^^^ @@ -555,7 +555,7 @@ LL | while (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:230:11 + --> $DIR/disallowed-positions.rs:234:11 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -563,7 +563,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:233:11 + --> $DIR/disallowed-positions.rs:237:11 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -571,7 +571,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:239:11 + --> $DIR/disallowed-positions.rs:243:11 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -579,7 +579,7 @@ LL | while let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:245:11 + --> $DIR/disallowed-positions.rs:249:11 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -587,7 +587,7 @@ LL | while let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:249:22 + --> $DIR/disallowed-positions.rs:253:22 | LL | while let true = let true = true {} | ^^^ @@ -595,7 +595,7 @@ LL | while let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:252:18 + --> $DIR/disallowed-positions.rs:256:18 | LL | while return let 0 = 0 {} | ^^^ @@ -603,7 +603,7 @@ LL | while return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:255:39 + --> $DIR/disallowed-positions.rs:259:39 | LL | 'outer: loop { while break 'outer let 0 = 0 {} } | ^^^ @@ -611,7 +611,7 @@ LL | 'outer: loop { while break 'outer let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:258:18 + --> $DIR/disallowed-positions.rs:262:18 | LL | while (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -619,7 +619,7 @@ LL | while (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:261:12 + --> $DIR/disallowed-positions.rs:265:12 | LL | while (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -627,7 +627,7 @@ LL | while (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:264:12 + --> $DIR/disallowed-positions.rs:268:12 | LL | while (let 0 = 0,) {} | ^^^^^^^^^ @@ -635,7 +635,7 @@ LL | while (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:268:16 + --> $DIR/disallowed-positions.rs:272:16 | LL | while (let 0 = 0).await {} | ^^^^^^^^^ @@ -643,7 +643,7 @@ LL | while (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:272:15 + --> $DIR/disallowed-positions.rs:276:15 | LL | while (|| let 0 = 0) {} | ^^^ @@ -651,7 +651,7 @@ LL | while (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:275:12 + --> $DIR/disallowed-positions.rs:279:12 | LL | while (let 0 = 0)() {} | ^^^^^^^^^ @@ -659,7 +659,7 @@ LL | while (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:292:6 + --> $DIR/disallowed-positions.rs:296:6 | LL | &let 0 = 0; | ^^^ @@ -667,7 +667,7 @@ LL | &let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:295:6 + --> $DIR/disallowed-positions.rs:299:6 | LL | !let 0 = 0; | ^^^ @@ -675,7 +675,7 @@ LL | !let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:297:6 + --> $DIR/disallowed-positions.rs:301:6 | LL | *let 0 = 0; | ^^^ @@ -683,7 +683,7 @@ LL | *let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:299:6 + --> $DIR/disallowed-positions.rs:303:6 | LL | -let 0 = 0; | ^^^ @@ -691,7 +691,7 @@ LL | -let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:301:13 + --> $DIR/disallowed-positions.rs:305:13 | LL | let _ = let _ = 3; | ^^^ @@ -699,7 +699,7 @@ LL | let _ = let _ = 3; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:309:6 + --> $DIR/disallowed-positions.rs:313:6 | LL | (let 0 = 0)?; | ^^^ @@ -707,7 +707,7 @@ LL | (let 0 = 0)?; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:312:13 + --> $DIR/disallowed-positions.rs:316:13 | LL | true || let 0 = 0; | ^^^ @@ -715,7 +715,7 @@ LL | true || let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:314:14 + --> $DIR/disallowed-positions.rs:318:14 | LL | (true || let 0 = 0); | ^^^ @@ -723,7 +723,7 @@ LL | (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:316:22 + --> $DIR/disallowed-positions.rs:320:22 | LL | true && (true || let 0 = 0); | ^^^ @@ -731,7 +731,7 @@ LL | true && (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:320:9 + --> $DIR/disallowed-positions.rs:324:9 | LL | x = let 0 = 0; | ^^^ @@ -739,7 +739,7 @@ LL | x = let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:323:12 + --> $DIR/disallowed-positions.rs:327:12 | LL | true..(let 0 = 0); | ^^^ @@ -747,7 +747,7 @@ LL | true..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:325:8 + --> $DIR/disallowed-positions.rs:329:8 | LL | ..(let 0 = 0); | ^^^ @@ -755,7 +755,7 @@ LL | ..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:327:6 + --> $DIR/disallowed-positions.rs:331:6 | LL | (let 0 = 0)..; | ^^^ @@ -763,7 +763,7 @@ LL | (let 0 = 0)..; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:330:6 + --> $DIR/disallowed-positions.rs:334:6 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^ @@ -771,7 +771,7 @@ LL | (let Range { start: _, end: _ } = true..true || false); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:334:6 + --> $DIR/disallowed-positions.rs:338:6 | LL | (let true = let true = true); | ^^^ @@ -779,7 +779,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:334:17 + --> $DIR/disallowed-positions.rs:338:17 | LL | (let true = let true = true); | ^^^ @@ -787,7 +787,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:340:25 + --> $DIR/disallowed-positions.rs:344:25 | LL | let x = true && let y = 1; | ^^^ @@ -795,7 +795,7 @@ LL | let x = true && let y = 1; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:346:19 + --> $DIR/disallowed-positions.rs:350:19 | LL | [1, 2, 3][let _ = ()] | ^^^ @@ -803,7 +803,7 @@ LL | [1, 2, 3][let _ = ()] = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:351:6 + --> $DIR/disallowed-positions.rs:355:6 | LL | &let 0 = 0 | ^^^ @@ -811,7 +811,7 @@ LL | &let 0 = 0 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:362:17 + --> $DIR/disallowed-positions.rs:366:17 | LL | true && let 1 = 1 | ^^^ @@ -819,7 +819,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:367:17 + --> $DIR/disallowed-positions.rs:371:17 | LL | true && let 1 = 1 | ^^^ @@ -827,7 +827,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:372:17 + --> $DIR/disallowed-positions.rs:376:17 | LL | true && let 1 = 1 | ^^^ @@ -835,7 +835,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:383:17 + --> $DIR/disallowed-positions.rs:387:17 | LL | true && let 1 = 1 | ^^^ @@ -843,7 +843,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/disallowed-positions.rs:383:9 + --> $DIR/disallowed-positions.rs:387:9 | LL | true && let 1 = 1 | ^^^^^^^^^^^^^^^^^ @@ -854,124 +854,124 @@ LL | { true && let 1 = 1 } | + + error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:393:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:393:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:401:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:401:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:400:9 + --> $DIR/disallowed-positions.rs:404:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:400:9 + --> $DIR/disallowed-positions.rs:404:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:400:32 + --> $DIR/disallowed-positions.rs:404:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:400:32 + --> $DIR/disallowed-positions.rs:404:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:408:9 + --> $DIR/disallowed-positions.rs:412:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:408:9 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:408:31 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { - | ^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:408:31 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { - | ^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement --> $DIR/disallowed-positions.rs:412:9 | -LL | if (let Some(a) = opt && (let Some(b) = a)) && true { - | ^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:412:9 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && true { +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement --> $DIR/disallowed-positions.rs:412:31 | -LL | if (let Some(a) = opt && (let Some(b) = a)) && true { +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains --> $DIR/disallowed-positions.rs:412:31 | -LL | if (let Some(a) = opt && (let Some(b) = a)) && true { +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement --> $DIR/disallowed-positions.rs:416:9 | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:416:9 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:416:31 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:416:31 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:420:9 + | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:416:9 + --> $DIR/disallowed-positions.rs:420:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:436:22 + --> $DIR/disallowed-positions.rs:440:22 | LL | let x = (true && let y = 1); | ^^^ @@ -979,7 +979,7 @@ LL | let x = (true && let y = 1); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:441:20 + --> $DIR/disallowed-positions.rs:445:20 | LL | ([1, 2, 3][let _ = ()]) | ^^^ @@ -995,13 +995,49 @@ LL | use_expr!((let 0 = 1 && 0 == 0)); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:93:16 + --> $DIR/disallowed-positions.rs:91:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:91:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:95:16 | LL | use_expr!((let 0 = 1)); | ^^^ | = note: only supported directly in conditions of `if` and `while` expressions +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:95:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:95:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0658]: `let` expressions in this position are unstable --> $DIR/disallowed-positions.rs:49:8 | @@ -1043,7 +1079,7 @@ LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:404:8 + --> $DIR/disallowed-positions.rs:408:8 | LL | if let Some(a) = opt && (true && true) { | ^^^^^^^^^^^^^^^^^ @@ -1053,7 +1089,7 @@ LL | if let Some(a) = opt && (true && true) { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:420:28 + --> $DIR/disallowed-positions.rs:424:28 | LL | if (true && (true)) && let Some(a) = opt { | ^^^^^^^^^^^^^^^^^ @@ -1063,7 +1099,7 @@ LL | if (true && (true)) && let Some(a) = opt { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:423:18 + --> $DIR/disallowed-positions.rs:427:18 | LL | if (true) && let Some(a) = opt { | ^^^^^^^^^^^^^^^^^ @@ -1073,7 +1109,7 @@ LL | if (true) && let Some(a) = opt { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:426:16 + --> $DIR/disallowed-positions.rs:430:16 | LL | if true && let Some(a) = opt { | ^^^^^^^^^^^^^^^^^ @@ -1083,7 +1119,7 @@ LL | if true && let Some(a) = opt { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:431:8 + --> $DIR/disallowed-positions.rs:435:8 | LL | if let true = (true && fun()) && (true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1093,7 +1129,7 @@ LL | if let true = (true && fun()) && (true) { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:130:8 + --> $DIR/disallowed-positions.rs:134:8 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` @@ -1102,7 +1138,7 @@ LL | if true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:139:12 + --> $DIR/disallowed-positions.rs:143:12 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1113,7 +1149,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:142:12 + --> $DIR/disallowed-positions.rs:146:12 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1124,7 +1160,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:148:12 + --> $DIR/disallowed-positions.rs:152:12 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1135,7 +1171,7 @@ LL | if let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:154:12 + --> $DIR/disallowed-positions.rs:158:12 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1146,7 +1182,7 @@ LL | if let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:110:20 + --> $DIR/disallowed-positions.rs:114:20 | LL | if let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1154,7 +1190,7 @@ LL | if let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:221:11 + --> $DIR/disallowed-positions.rs:225:11 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` @@ -1163,7 +1199,7 @@ LL | while true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:230:15 + --> $DIR/disallowed-positions.rs:234:15 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1174,7 +1210,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:233:15 + --> $DIR/disallowed-positions.rs:237:15 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1185,7 +1221,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:239:15 + --> $DIR/disallowed-positions.rs:243:15 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1196,7 +1232,7 @@ LL | while let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:245:15 + --> $DIR/disallowed-positions.rs:249:15 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1207,7 +1243,7 @@ LL | while let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:201:23 + --> $DIR/disallowed-positions.rs:205:23 | LL | while let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1215,7 +1251,7 @@ LL | while let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:330:10 + --> $DIR/disallowed-positions.rs:334:10 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1226,14 +1262,14 @@ LL | (let Range { start: _, end: _ } = true..true || false); found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:305:17 + --> $DIR/disallowed-positions.rs:309:17 | LL | let 0 = 0?; | ^^ the `?` operator cannot be applied to type `{integer}` | = help: the trait `Try` is not implemented for `{integer}` -error: aborting due to 130 previous errors +error: aborting due to 134 previous errors Some errors have detailed explanations: E0277, E0308, E0658. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr index 2d5fd1144add..943956feb4e0 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr @@ -233,7 +233,7 @@ LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:99:9 + --> $DIR/disallowed-positions.rs:103:9 | LL | if &let 0 = 0 {} | ^^^^^^^^^ @@ -241,7 +241,7 @@ LL | if &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:102:9 + --> $DIR/disallowed-positions.rs:106:9 | LL | if !let 0 = 0 {} | ^^^^^^^^^ @@ -249,7 +249,7 @@ LL | if !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:104:9 + --> $DIR/disallowed-positions.rs:108:9 | LL | if *let 0 = 0 {} | ^^^^^^^^^ @@ -257,7 +257,7 @@ LL | if *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:106:9 + --> $DIR/disallowed-positions.rs:110:9 | LL | if -let 0 = 0 {} | ^^^^^^^^^ @@ -265,7 +265,7 @@ LL | if -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:114:9 + --> $DIR/disallowed-positions.rs:118:9 | LL | if (let 0 = 0)? {} | ^^^^^^^^^ @@ -273,20 +273,20 @@ LL | if (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:117:16 + --> $DIR/disallowed-positions.rs:121:16 | LL | if true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:117:13 + --> $DIR/disallowed-positions.rs:121:13 | LL | if true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:119:17 + --> $DIR/disallowed-positions.rs:123:17 | LL | if (true || let 0 = 0) {} | ^^^^^^^^^ @@ -294,7 +294,7 @@ LL | if (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:121:25 + --> $DIR/disallowed-positions.rs:125:25 | LL | if true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -302,7 +302,7 @@ LL | if true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:123:25 + --> $DIR/disallowed-positions.rs:127:25 | LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -310,7 +310,7 @@ LL | if true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:127:12 + --> $DIR/disallowed-positions.rs:131:12 | LL | if x = let 0 = 0 {} | ^^^ @@ -318,7 +318,7 @@ LL | if x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:130:15 + --> $DIR/disallowed-positions.rs:134:15 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^ @@ -326,7 +326,7 @@ LL | if true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:133:11 + --> $DIR/disallowed-positions.rs:137:11 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^ @@ -334,7 +334,7 @@ LL | if ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:135:9 + --> $DIR/disallowed-positions.rs:139:9 | LL | if (let 0 = 0).. {} | ^^^^^^^^^ @@ -342,7 +342,7 @@ LL | if (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:139:8 + --> $DIR/disallowed-positions.rs:143:8 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -350,7 +350,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:142:8 + --> $DIR/disallowed-positions.rs:146:8 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -358,7 +358,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:148:8 + --> $DIR/disallowed-positions.rs:152:8 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -366,7 +366,7 @@ LL | if let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:154:8 + --> $DIR/disallowed-positions.rs:158:8 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -374,7 +374,7 @@ LL | if let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:158:19 + --> $DIR/disallowed-positions.rs:162:19 | LL | if let true = let true = true {} | ^^^ @@ -382,7 +382,7 @@ LL | if let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:161:15 + --> $DIR/disallowed-positions.rs:165:15 | LL | if return let 0 = 0 {} | ^^^ @@ -390,7 +390,7 @@ LL | if return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:164:21 + --> $DIR/disallowed-positions.rs:168:21 | LL | loop { if break let 0 = 0 {} } | ^^^ @@ -398,7 +398,7 @@ LL | loop { if break let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:167:15 + --> $DIR/disallowed-positions.rs:171:15 | LL | if (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -406,7 +406,7 @@ LL | if (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:170:9 + --> $DIR/disallowed-positions.rs:174:9 | LL | if (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -414,7 +414,7 @@ LL | if (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:173:9 + --> $DIR/disallowed-positions.rs:177:9 | LL | if (let 0 = 0,) {} | ^^^^^^^^^ @@ -422,7 +422,7 @@ LL | if (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:177:13 + --> $DIR/disallowed-positions.rs:181:13 | LL | if (let 0 = 0).await {} | ^^^^^^^^^ @@ -430,7 +430,7 @@ LL | if (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:181:12 + --> $DIR/disallowed-positions.rs:185:12 | LL | if (|| let 0 = 0) {} | ^^^ @@ -438,7 +438,7 @@ LL | if (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:184:9 + --> $DIR/disallowed-positions.rs:188:9 | LL | if (let 0 = 0)() {} | ^^^^^^^^^ @@ -446,7 +446,7 @@ LL | if (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:190:12 + --> $DIR/disallowed-positions.rs:194:12 | LL | while &let 0 = 0 {} | ^^^^^^^^^ @@ -454,7 +454,7 @@ LL | while &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:193:12 + --> $DIR/disallowed-positions.rs:197:12 | LL | while !let 0 = 0 {} | ^^^^^^^^^ @@ -462,7 +462,7 @@ LL | while !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:195:12 + --> $DIR/disallowed-positions.rs:199:12 | LL | while *let 0 = 0 {} | ^^^^^^^^^ @@ -470,7 +470,7 @@ LL | while *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:197:12 + --> $DIR/disallowed-positions.rs:201:12 | LL | while -let 0 = 0 {} | ^^^^^^^^^ @@ -478,7 +478,7 @@ LL | while -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:205:12 + --> $DIR/disallowed-positions.rs:209:12 | LL | while (let 0 = 0)? {} | ^^^^^^^^^ @@ -486,20 +486,20 @@ LL | while (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:208:19 + --> $DIR/disallowed-positions.rs:212:19 | LL | while true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:208:16 + --> $DIR/disallowed-positions.rs:212:16 | LL | while true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:210:20 + --> $DIR/disallowed-positions.rs:214:20 | LL | while (true || let 0 = 0) {} | ^^^^^^^^^ @@ -507,7 +507,7 @@ LL | while (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:212:28 + --> $DIR/disallowed-positions.rs:216:28 | LL | while true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -515,7 +515,7 @@ LL | while true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:214:28 + --> $DIR/disallowed-positions.rs:218:28 | LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -523,7 +523,7 @@ LL | while true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:218:15 + --> $DIR/disallowed-positions.rs:222:15 | LL | while x = let 0 = 0 {} | ^^^ @@ -531,7 +531,7 @@ LL | while x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:221:18 + --> $DIR/disallowed-positions.rs:225:18 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^ @@ -539,7 +539,7 @@ LL | while true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:224:14 + --> $DIR/disallowed-positions.rs:228:14 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^ @@ -547,7 +547,7 @@ LL | while ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:226:12 + --> $DIR/disallowed-positions.rs:230:12 | LL | while (let 0 = 0).. {} | ^^^^^^^^^ @@ -555,7 +555,7 @@ LL | while (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:230:11 + --> $DIR/disallowed-positions.rs:234:11 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -563,7 +563,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:233:11 + --> $DIR/disallowed-positions.rs:237:11 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -571,7 +571,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:239:11 + --> $DIR/disallowed-positions.rs:243:11 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -579,7 +579,7 @@ LL | while let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:245:11 + --> $DIR/disallowed-positions.rs:249:11 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -587,7 +587,7 @@ LL | while let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:249:22 + --> $DIR/disallowed-positions.rs:253:22 | LL | while let true = let true = true {} | ^^^ @@ -595,7 +595,7 @@ LL | while let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:252:18 + --> $DIR/disallowed-positions.rs:256:18 | LL | while return let 0 = 0 {} | ^^^ @@ -603,7 +603,7 @@ LL | while return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:255:39 + --> $DIR/disallowed-positions.rs:259:39 | LL | 'outer: loop { while break 'outer let 0 = 0 {} } | ^^^ @@ -611,7 +611,7 @@ LL | 'outer: loop { while break 'outer let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:258:18 + --> $DIR/disallowed-positions.rs:262:18 | LL | while (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -619,7 +619,7 @@ LL | while (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:261:12 + --> $DIR/disallowed-positions.rs:265:12 | LL | while (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -627,7 +627,7 @@ LL | while (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:264:12 + --> $DIR/disallowed-positions.rs:268:12 | LL | while (let 0 = 0,) {} | ^^^^^^^^^ @@ -635,7 +635,7 @@ LL | while (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:268:16 + --> $DIR/disallowed-positions.rs:272:16 | LL | while (let 0 = 0).await {} | ^^^^^^^^^ @@ -643,7 +643,7 @@ LL | while (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:272:15 + --> $DIR/disallowed-positions.rs:276:15 | LL | while (|| let 0 = 0) {} | ^^^ @@ -651,7 +651,7 @@ LL | while (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:275:12 + --> $DIR/disallowed-positions.rs:279:12 | LL | while (let 0 = 0)() {} | ^^^^^^^^^ @@ -659,7 +659,7 @@ LL | while (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:292:6 + --> $DIR/disallowed-positions.rs:296:6 | LL | &let 0 = 0; | ^^^ @@ -667,7 +667,7 @@ LL | &let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:295:6 + --> $DIR/disallowed-positions.rs:299:6 | LL | !let 0 = 0; | ^^^ @@ -675,7 +675,7 @@ LL | !let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:297:6 + --> $DIR/disallowed-positions.rs:301:6 | LL | *let 0 = 0; | ^^^ @@ -683,7 +683,7 @@ LL | *let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:299:6 + --> $DIR/disallowed-positions.rs:303:6 | LL | -let 0 = 0; | ^^^ @@ -691,7 +691,7 @@ LL | -let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:301:13 + --> $DIR/disallowed-positions.rs:305:13 | LL | let _ = let _ = 3; | ^^^ @@ -699,7 +699,7 @@ LL | let _ = let _ = 3; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:309:6 + --> $DIR/disallowed-positions.rs:313:6 | LL | (let 0 = 0)?; | ^^^ @@ -707,7 +707,7 @@ LL | (let 0 = 0)?; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:312:13 + --> $DIR/disallowed-positions.rs:316:13 | LL | true || let 0 = 0; | ^^^ @@ -715,7 +715,7 @@ LL | true || let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:314:14 + --> $DIR/disallowed-positions.rs:318:14 | LL | (true || let 0 = 0); | ^^^ @@ -723,7 +723,7 @@ LL | (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:316:22 + --> $DIR/disallowed-positions.rs:320:22 | LL | true && (true || let 0 = 0); | ^^^ @@ -731,7 +731,7 @@ LL | true && (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:320:9 + --> $DIR/disallowed-positions.rs:324:9 | LL | x = let 0 = 0; | ^^^ @@ -739,7 +739,7 @@ LL | x = let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:323:12 + --> $DIR/disallowed-positions.rs:327:12 | LL | true..(let 0 = 0); | ^^^ @@ -747,7 +747,7 @@ LL | true..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:325:8 + --> $DIR/disallowed-positions.rs:329:8 | LL | ..(let 0 = 0); | ^^^ @@ -755,7 +755,7 @@ LL | ..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:327:6 + --> $DIR/disallowed-positions.rs:331:6 | LL | (let 0 = 0)..; | ^^^ @@ -763,7 +763,7 @@ LL | (let 0 = 0)..; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:330:6 + --> $DIR/disallowed-positions.rs:334:6 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^ @@ -771,7 +771,7 @@ LL | (let Range { start: _, end: _ } = true..true || false); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:334:6 + --> $DIR/disallowed-positions.rs:338:6 | LL | (let true = let true = true); | ^^^ @@ -779,7 +779,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:334:17 + --> $DIR/disallowed-positions.rs:338:17 | LL | (let true = let true = true); | ^^^ @@ -787,7 +787,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:340:25 + --> $DIR/disallowed-positions.rs:344:25 | LL | let x = true && let y = 1; | ^^^ @@ -795,7 +795,7 @@ LL | let x = true && let y = 1; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:346:19 + --> $DIR/disallowed-positions.rs:350:19 | LL | [1, 2, 3][let _ = ()] | ^^^ @@ -803,7 +803,7 @@ LL | [1, 2, 3][let _ = ()] = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:351:6 + --> $DIR/disallowed-positions.rs:355:6 | LL | &let 0 = 0 | ^^^ @@ -811,7 +811,7 @@ LL | &let 0 = 0 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:362:17 + --> $DIR/disallowed-positions.rs:366:17 | LL | true && let 1 = 1 | ^^^ @@ -819,7 +819,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:367:17 + --> $DIR/disallowed-positions.rs:371:17 | LL | true && let 1 = 1 | ^^^ @@ -827,7 +827,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:372:17 + --> $DIR/disallowed-positions.rs:376:17 | LL | true && let 1 = 1 | ^^^ @@ -835,7 +835,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:383:17 + --> $DIR/disallowed-positions.rs:387:17 | LL | true && let 1 = 1 | ^^^ @@ -843,7 +843,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/disallowed-positions.rs:383:9 + --> $DIR/disallowed-positions.rs:387:9 | LL | true && let 1 = 1 | ^^^^^^^^^^^^^^^^^ @@ -854,124 +854,124 @@ LL | { true && let 1 = 1 } | + + error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:393:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:393:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:401:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:401:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:400:9 + --> $DIR/disallowed-positions.rs:404:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:400:9 + --> $DIR/disallowed-positions.rs:404:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:400:32 + --> $DIR/disallowed-positions.rs:404:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:400:32 + --> $DIR/disallowed-positions.rs:404:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:408:9 + --> $DIR/disallowed-positions.rs:412:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:408:9 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:408:31 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { - | ^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:408:31 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { - | ^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement --> $DIR/disallowed-positions.rs:412:9 | -LL | if (let Some(a) = opt && (let Some(b) = a)) && true { - | ^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:412:9 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && true { +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement --> $DIR/disallowed-positions.rs:412:31 | -LL | if (let Some(a) = opt && (let Some(b) = a)) && true { +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains --> $DIR/disallowed-positions.rs:412:31 | -LL | if (let Some(a) = opt && (let Some(b) = a)) && true { +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement --> $DIR/disallowed-positions.rs:416:9 | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:416:9 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:416:31 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:416:31 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:420:9 + | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:416:9 + --> $DIR/disallowed-positions.rs:420:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:436:22 + --> $DIR/disallowed-positions.rs:440:22 | LL | let x = (true && let y = 1); | ^^^ @@ -979,7 +979,7 @@ LL | let x = (true && let y = 1); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:441:20 + --> $DIR/disallowed-positions.rs:445:20 | LL | ([1, 2, 3][let _ = ()]) | ^^^ diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs index 8eb8d617d581..99f99c2be72d 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs @@ -90,8 +90,12 @@ fn _macros() { } use_expr!((let 0 = 1 && 0 == 0)); //[feature,no_feature]~^ ERROR expected expression, found `let` statement + //[feature,no_feature]~| ERROR expected expression, found `let` statement + //[feature,no_feature]~| ERROR expected expression, found `let` statement use_expr!((let 0 = 1)); //[feature,no_feature]~^ ERROR expected expression, found `let` statement + //[feature,no_feature]~| ERROR expected expression, found `let` statement + //[feature,no_feature]~| ERROR expected expression, found `let` statement } #[cfg(not(nothing))] From d59b17c5cdbf345d0088d90fc03faf2501a39757 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 26 Mar 2025 15:54:14 +1100 Subject: [PATCH 731/745] Remove `Token::uninterpolated_span`. In favour of the similar method on `Parser`, which works on things other than identifiers and lifetimes. --- compiler/rustc_ast/src/token.rs | 27 +++++-------------- compiler/rustc_parse/src/parser/expr.rs | 14 +++++----- compiler/rustc_parse/src/parser/item.rs | 10 +++---- compiler/rustc_parse/src/parser/mod.rs | 35 +++++++++++++++++++------ compiler/rustc_parse/src/parser/ty.rs | 6 ++--- 5 files changed, 48 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 2081777fff35..d57a369eebf2 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -448,8 +448,9 @@ pub enum TokenKind { /// Identifier token. /// Do not forget about `NtIdent` when you want to match on identifiers. - /// It's recommended to use `Token::(ident,uninterpolate,uninterpolated_span)` to - /// treat regular and interpolated identifiers in the same way. + /// It's recommended to use `Token::{ident,uninterpolate}` and + /// `Parser::token_uninterpolated_span` to treat regular and interpolated + /// identifiers in the same way. Ident(Symbol, IdentIsRaw), /// This identifier (and its span) is the identifier passed to the /// declarative macro. The span in the surrounding `Token` is the span of @@ -458,8 +459,9 @@ pub enum TokenKind { /// Lifetime identifier token. /// Do not forget about `NtLifetime` when you want to match on lifetime identifiers. - /// It's recommended to use `Token::(lifetime,uninterpolate,uninterpolated_span)` to - /// treat regular and interpolated lifetime identifiers in the same way. + /// It's recommended to use `Token::{ident,uninterpolate}` and + /// `Parser::token_uninterpolated_span` to treat regular and interpolated + /// identifiers in the same way. Lifetime(Symbol, IdentIsRaw), /// This identifier (and its span) is the lifetime passed to the /// declarative macro. The span in the surrounding `Token` is the span of @@ -585,23 +587,6 @@ impl Token { Token::new(Ident(ident.name, ident.is_raw_guess().into()), ident.span) } - /// For interpolated tokens, returns a span of the fragment to which the interpolated - /// token refers. For all other tokens this is just a regular span. - /// It is particularly important to use this for identifiers and lifetimes - /// for which spans affect name resolution and edition checks. - /// Note that keywords are also identifiers, so they should use this - /// if they keep spans or perform edition checks. - // - // Note: `Parser::uninterpolated_token_span` may give better information - // than this method does. - pub fn uninterpolated_span(&self) -> Span { - match self.kind { - NtIdent(ident, _) | NtLifetime(ident, _) => ident.span, - Interpolated(ref nt) => nt.use_span(), - _ => self.span, - } - } - pub fn is_range_separator(&self) -> bool { [DotDot, DotDotDot, DotDotEq].contains(&self.kind) } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 424fee968e1d..1c2df3ffcd10 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1318,7 +1318,7 @@ impl<'a> Parser<'a> { /// Assuming we have just parsed `.`, continue parsing into an expression. fn parse_dot_suffix(&mut self, self_arg: P, lo: Span) -> PResult<'a, P> { - if self.token.uninterpolated_span().at_least_rust_2018() && self.eat_keyword(exp!(Await)) { + if self.token_uninterpolated_span().at_least_rust_2018() && self.eat_keyword(exp!(Await)) { return Ok(self.mk_await_expr(self_arg, lo)); } @@ -1509,9 +1509,9 @@ impl<'a> Parser<'a> { this.parse_expr_let(restrictions) } else if this.eat_keyword(exp!(Underscore)) { Ok(this.mk_expr(this.prev_token.span, ExprKind::Underscore)) - } else if this.token.uninterpolated_span().at_least_rust_2018() { + } else if this.token_uninterpolated_span().at_least_rust_2018() { // `Span::at_least_rust_2018()` is somewhat expensive; don't get it repeatedly. - if this.token.uninterpolated_span().at_least_rust_2024() + if this.token_uninterpolated_span().at_least_rust_2024() // check for `gen {}` and `gen move {}` // or `async gen {}` and `async gen move {}` && (this.is_gen_block(kw::Gen, 0) @@ -2186,7 +2186,7 @@ impl<'a> Parser<'a> { fn parse_opt_meta_item_lit(&mut self) -> Option { self.recover_after_dot(); let span = self.token.span; - let uninterpolated_span = self.uninterpolated_token_span(); + let uninterpolated_span = self.token_uninterpolated_span(); self.eat_token_lit().map(|token_lit| { match MetaItemLit::from_token_lit(token_lit, span) { Ok(lit) => lit, @@ -2390,7 +2390,7 @@ impl<'a> Parser<'a> { let movability = if self.eat_keyword(exp!(Static)) { Movability::Static } else { Movability::Movable }; - let coroutine_kind = if self.token.uninterpolated_span().at_least_rust_2018() { + let coroutine_kind = if self.token_uninterpolated_span().at_least_rust_2018() { self.parse_coroutine_kind(Case::Sensitive) } else { None @@ -2939,7 +2939,7 @@ impl<'a> Parser<'a> { /// Parses `for await? in ` (`for` token already eaten). fn parse_expr_for(&mut self, opt_label: Option

).next()` on an `Iterator` - --> tests/ui/skip_while_next.rs:17:13 + --> tests/ui/skip_while_next.rs:18:13 | LL | let _ = v.iter().skip_while(|&x| { | _____________^ +LL | | LL | | *x < 0 LL | | } LL | | ).next(); diff --git a/tests/ui/sliced_string_as_bytes.fixed b/tests/ui/sliced_string_as_bytes.fixed index 469ad27a99b9..16c0daff78fd 100644 --- a/tests/ui/sliced_string_as_bytes.fixed +++ b/tests/ui/sliced_string_as_bytes.fixed @@ -26,8 +26,11 @@ fn main() { let string: String = "dolor sit amet".to_owned(); let bytes = &s.as_bytes()[1..5]; + //~^ sliced_string_as_bytes let bytes = &string.as_bytes()[1..]; + //~^ sliced_string_as_bytes let bytes = &"consectetur adipiscing".as_bytes()[..=5]; + //~^ sliced_string_as_bytes let f = Foo; let bytes = f[0..4].as_bytes(); diff --git a/tests/ui/sliced_string_as_bytes.rs b/tests/ui/sliced_string_as_bytes.rs index 4a4605e5a1ae..67985ae5b984 100644 --- a/tests/ui/sliced_string_as_bytes.rs +++ b/tests/ui/sliced_string_as_bytes.rs @@ -26,8 +26,11 @@ fn main() { let string: String = "dolor sit amet".to_owned(); let bytes = s[1..5].as_bytes(); + //~^ sliced_string_as_bytes let bytes = string[1..].as_bytes(); + //~^ sliced_string_as_bytes let bytes = "consectetur adipiscing"[..=5].as_bytes(); + //~^ sliced_string_as_bytes let f = Foo; let bytes = f[0..4].as_bytes(); diff --git a/tests/ui/sliced_string_as_bytes.stderr b/tests/ui/sliced_string_as_bytes.stderr index 1342f4c01a48..ae7f02781f4b 100644 --- a/tests/ui/sliced_string_as_bytes.stderr +++ b/tests/ui/sliced_string_as_bytes.stderr @@ -8,13 +8,13 @@ LL | let bytes = s[1..5].as_bytes(); = help: to override `-D warnings` add `#[allow(clippy::sliced_string_as_bytes)]` error: calling `as_bytes` after slicing a string - --> tests/ui/sliced_string_as_bytes.rs:29:17 + --> tests/ui/sliced_string_as_bytes.rs:30:17 | LL | let bytes = string[1..].as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&string.as_bytes()[1..]` error: calling `as_bytes` after slicing a string - --> tests/ui/sliced_string_as_bytes.rs:30:17 + --> tests/ui/sliced_string_as_bytes.rs:32:17 | LL | let bytes = "consectetur adipiscing"[..=5].as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&"consectetur adipiscing".as_bytes()[..=5]` diff --git a/tests/ui/slow_vector_initialization.rs b/tests/ui/slow_vector_initialization.rs index 4b30fad409e3..52f2a52fbbb8 100644 --- a/tests/ui/slow_vector_initialization.rs +++ b/tests/ui/slow_vector_initialization.rs @@ -12,13 +12,14 @@ fn extend_vector() { // Extend with constant expression let len = 300; let mut vec1 = Vec::with_capacity(len); - //~^ ERROR: slow zero-filling initialization - //~| NOTE: `-D clippy::slow-vector-initialization` implied by `-D warnings` + //~^ slow_vector_initialization + vec1.extend(repeat(0).take(len)); // Extend with len expression let mut vec2 = Vec::with_capacity(len - 10); - //~^ ERROR: slow zero-filling initialization + //~^ slow_vector_initialization + vec2.extend(repeat(0).take(len - 10)); // Extend with mismatching expression should not be warned @@ -26,7 +27,8 @@ fn extend_vector() { vec3.extend(repeat(0).take(2)); let mut vec4 = Vec::with_capacity(len); - //~^ ERROR: slow zero-filling initialization + //~^ slow_vector_initialization + vec4.extend(repeat(0).take(vec4.capacity())); } @@ -37,11 +39,13 @@ fn mixed_extend_resize_vector() { // Slow initialization let mut resized_vec = Vec::with_capacity(30); - //~^ ERROR: slow zero-filling initialization + //~^ slow_vector_initialization + resized_vec.resize(30, 0); let mut extend_vec = Vec::with_capacity(30); - //~^ ERROR: slow zero-filling initialization + //~^ slow_vector_initialization + extend_vec.extend(repeat(0).take(30)); } @@ -49,7 +53,8 @@ fn resize_vector() { // Resize with constant expression let len = 300; let mut vec1 = Vec::with_capacity(len); - //~^ ERROR: slow zero-filling initialization + //~^ slow_vector_initialization + vec1.resize(len, 0); // Resize mismatch len @@ -58,16 +63,19 @@ fn resize_vector() { // Resize with len expression let mut vec3 = Vec::with_capacity(len - 10); - //~^ ERROR: slow zero-filling initialization + //~^ slow_vector_initialization + vec3.resize(len - 10, 0); let mut vec4 = Vec::with_capacity(len); - //~^ ERROR: slow zero-filling initialization + //~^ slow_vector_initialization + vec4.resize(vec4.capacity(), 0); // Reinitialization should be warned vec1 = Vec::with_capacity(10); - //~^ ERROR: slow zero-filling initialization + //~^ slow_vector_initialization + vec1.resize(10, 0); } @@ -75,21 +83,25 @@ fn from_empty_vec() { // Resize with constant expression let len = 300; let mut vec1 = Vec::new(); - //~^ ERROR: slow zero-filling initialization + //~^ slow_vector_initialization + vec1.resize(len, 0); // Resize with len expression let mut vec3 = Vec::new(); - //~^ ERROR: slow zero-filling initialization + //~^ slow_vector_initialization + vec3.resize(len - 10, 0); // Reinitialization should be warned vec1 = Vec::new(); - //~^ ERROR: slow zero-filling initialization + //~^ slow_vector_initialization + vec1.resize(10, 0); vec1 = vec![]; - //~^ ERROR: slow zero-filling initialization + //~^ slow_vector_initialization + vec1.resize(10, 0); macro_rules! x { diff --git a/tests/ui/slow_vector_initialization.stderr b/tests/ui/slow_vector_initialization.stderr index 4a25cafcddf2..e83eef826472 100644 --- a/tests/ui/slow_vector_initialization.stderr +++ b/tests/ui/slow_vector_initialization.stderr @@ -15,106 +15,106 @@ error: slow zero-filling initialization | LL | let mut vec2 = Vec::with_capacity(len - 10); | ____________________^ -LL | | +... | LL | | vec2.extend(repeat(0).take(len - 10)); | |_________________________________________^ help: consider replacing this with: `vec![0; len - 10]` error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:28:20 + --> tests/ui/slow_vector_initialization.rs:29:20 | LL | let mut vec4 = Vec::with_capacity(len); | ____________________^ -LL | | +... | LL | | vec4.extend(repeat(0).take(vec4.capacity())); | |________________________________________________^ help: consider replacing this with: `vec![0; len]` error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:39:27 + --> tests/ui/slow_vector_initialization.rs:41:27 | LL | let mut resized_vec = Vec::with_capacity(30); | ___________________________^ -LL | | +... | LL | | resized_vec.resize(30, 0); | |_____________________________^ help: consider replacing this with: `vec![0; 30]` error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:43:26 + --> tests/ui/slow_vector_initialization.rs:46:26 | LL | let mut extend_vec = Vec::with_capacity(30); | __________________________^ -LL | | +... | LL | | extend_vec.extend(repeat(0).take(30)); | |_________________________________________^ help: consider replacing this with: `vec![0; 30]` error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:51:20 + --> tests/ui/slow_vector_initialization.rs:55:20 | LL | let mut vec1 = Vec::with_capacity(len); | ____________________^ -LL | | +... | LL | | vec1.resize(len, 0); | |_______________________^ help: consider replacing this with: `vec![0; len]` error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:60:20 + --> tests/ui/slow_vector_initialization.rs:65:20 | LL | let mut vec3 = Vec::with_capacity(len - 10); | ____________________^ -LL | | +... | LL | | vec3.resize(len - 10, 0); | |____________________________^ help: consider replacing this with: `vec![0; len - 10]` error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:64:20 + --> tests/ui/slow_vector_initialization.rs:70:20 | LL | let mut vec4 = Vec::with_capacity(len); | ____________________^ -LL | | +... | LL | | vec4.resize(vec4.capacity(), 0); | |___________________________________^ help: consider replacing this with: `vec![0; len]` error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:69:12 + --> tests/ui/slow_vector_initialization.rs:76:12 | LL | vec1 = Vec::with_capacity(10); | ____________^ -LL | | +... | LL | | vec1.resize(10, 0); | |______________________^ help: consider replacing this with: `vec![0; 10]` error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:77:20 + --> tests/ui/slow_vector_initialization.rs:85:20 | LL | let mut vec1 = Vec::new(); | ____________________^ -LL | | +... | LL | | vec1.resize(len, 0); | |_______________________^ help: consider replacing this with: `vec![0; len]` error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:82:20 + --> tests/ui/slow_vector_initialization.rs:91:20 | LL | let mut vec3 = Vec::new(); | ____________________^ -LL | | +... | LL | | vec3.resize(len - 10, 0); | |____________________________^ help: consider replacing this with: `vec![0; len - 10]` error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:87:12 + --> tests/ui/slow_vector_initialization.rs:97:12 | LL | vec1 = Vec::new(); | ____________^ -LL | | +... | LL | | vec1.resize(10, 0); | |______________________^ help: consider replacing this with: `vec![0; 10]` error: slow zero-filling initialization - --> tests/ui/slow_vector_initialization.rs:91:12 + --> tests/ui/slow_vector_initialization.rs:102:12 | LL | vec1 = vec![]; | ____________^ -LL | | +... | LL | | vec1.resize(10, 0); | |______________________^ help: consider replacing this with: `vec![0; 10]` diff --git a/tests/ui/stable_sort_primitive.fixed b/tests/ui/stable_sort_primitive.fixed index 97f3a92238d2..b4870ebad2b3 100644 --- a/tests/ui/stable_sort_primitive.fixed +++ b/tests/ui/stable_sort_primitive.fixed @@ -5,18 +5,25 @@ fn main() { // positive examples let mut vec = vec![1, 3, 2]; vec.sort_unstable(); + //~^ stable_sort_primitive let mut vec = vec![false, false, true]; vec.sort_unstable(); + //~^ stable_sort_primitive let mut vec = vec!['a', 'A', 'c']; vec.sort_unstable(); + //~^ stable_sort_primitive let mut vec = vec!["ab", "cd", "ab", "bc"]; vec.sort_unstable(); + //~^ stable_sort_primitive let mut vec = vec![(2, 1), (1, 2), (2, 5)]; vec.sort_unstable(); + //~^ stable_sort_primitive let mut vec = vec![[2, 1], [1, 2], [2, 5]]; vec.sort_unstable(); + //~^ stable_sort_primitive let mut arr = [1, 3, 2]; arr.sort_unstable(); + //~^ stable_sort_primitive // Negative examples: behavior changes if made unstable let mut vec = vec![1, 3, 2]; vec.sort_by_key(|i| i / 2); diff --git a/tests/ui/stable_sort_primitive.rs b/tests/ui/stable_sort_primitive.rs index 26e3d8e74f71..b3fe64efd620 100644 --- a/tests/ui/stable_sort_primitive.rs +++ b/tests/ui/stable_sort_primitive.rs @@ -5,18 +5,25 @@ fn main() { // positive examples let mut vec = vec![1, 3, 2]; vec.sort(); + //~^ stable_sort_primitive let mut vec = vec![false, false, true]; vec.sort(); + //~^ stable_sort_primitive let mut vec = vec!['a', 'A', 'c']; vec.sort(); + //~^ stable_sort_primitive let mut vec = vec!["ab", "cd", "ab", "bc"]; vec.sort(); + //~^ stable_sort_primitive let mut vec = vec![(2, 1), (1, 2), (2, 5)]; vec.sort(); + //~^ stable_sort_primitive let mut vec = vec![[2, 1], [1, 2], [2, 5]]; vec.sort(); + //~^ stable_sort_primitive let mut arr = [1, 3, 2]; arr.sort(); + //~^ stable_sort_primitive // Negative examples: behavior changes if made unstable let mut vec = vec![1, 3, 2]; vec.sort_by_key(|i| i / 2); diff --git a/tests/ui/stable_sort_primitive.stderr b/tests/ui/stable_sort_primitive.stderr index 66bd4c79bb28..00b45030139a 100644 --- a/tests/ui/stable_sort_primitive.stderr +++ b/tests/ui/stable_sort_primitive.stderr @@ -9,7 +9,7 @@ LL | vec.sort(); = help: to override `-D warnings` add `#[allow(clippy::stable_sort_primitive)]` error: used `sort` on primitive type `bool` - --> tests/ui/stable_sort_primitive.rs:9:5 + --> tests/ui/stable_sort_primitive.rs:10:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` @@ -17,14 +17,6 @@ LL | vec.sort(); = note: an unstable sort typically performs faster without any observable difference for this data type error: used `sort` on primitive type `char` - --> tests/ui/stable_sort_primitive.rs:11:5 - | -LL | vec.sort(); - | ^^^^^^^^^^ help: try: `vec.sort_unstable()` - | - = note: an unstable sort typically performs faster without any observable difference for this data type - -error: used `sort` on primitive type `str` --> tests/ui/stable_sort_primitive.rs:13:5 | LL | vec.sort(); @@ -32,8 +24,16 @@ LL | vec.sort(); | = note: an unstable sort typically performs faster without any observable difference for this data type +error: used `sort` on primitive type `str` + --> tests/ui/stable_sort_primitive.rs:16:5 + | +LL | vec.sort(); + | ^^^^^^^^^^ help: try: `vec.sort_unstable()` + | + = note: an unstable sort typically performs faster without any observable difference for this data type + error: used `sort` on primitive type `tuple` - --> tests/ui/stable_sort_primitive.rs:15:5 + --> tests/ui/stable_sort_primitive.rs:19:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` @@ -41,7 +41,7 @@ LL | vec.sort(); = note: an unstable sort typically performs faster without any observable difference for this data type error: used `sort` on primitive type `array` - --> tests/ui/stable_sort_primitive.rs:17:5 + --> tests/ui/stable_sort_primitive.rs:22:5 | LL | vec.sort(); | ^^^^^^^^^^ help: try: `vec.sort_unstable()` @@ -49,7 +49,7 @@ LL | vec.sort(); = note: an unstable sort typically performs faster without any observable difference for this data type error: used `sort` on primitive type `i32` - --> tests/ui/stable_sort_primitive.rs:19:5 + --> tests/ui/stable_sort_primitive.rs:25:5 | LL | arr.sort(); | ^^^^^^^^^^ help: try: `arr.sort_unstable()` diff --git a/tests/ui/starts_ends_with.fixed b/tests/ui/starts_ends_with.fixed index 252b6e5a98c0..b4f9d5867703 100644 --- a/tests/ui/starts_ends_with.fixed +++ b/tests/ui/starts_ends_with.fixed @@ -5,36 +5,46 @@ fn main() {} #[allow(clippy::unnecessary_operation)] fn starts_with() { "".starts_with(' '); + //~^ chars_next_cmp !"".starts_with(' '); + //~^ chars_next_cmp // Ensure that suggestion is escaped correctly "".starts_with('\n'); + //~^ chars_next_cmp !"".starts_with('\n'); + //~^ chars_next_cmp } fn chars_cmp_with_unwrap() { let s = String::from("foo"); if s.starts_with('f') { + //~^ chars_next_cmp // s.starts_with('f') // Nothing here } if s.ends_with('o') { + //~^ chars_last_cmp // s.ends_with('o') // Nothing here } if s.ends_with('o') { + //~^ chars_last_cmp // s.ends_with('o') // Nothing here } if !s.starts_with('f') { + //~^ chars_next_cmp // !s.starts_with('f') // Nothing here } if !s.ends_with('o') { + //~^ chars_last_cmp // !s.ends_with('o') // Nothing here } if !s.ends_with('\n') { + //~^ chars_last_cmp // !s.ends_with('o') // Nothing here } @@ -43,11 +53,17 @@ fn chars_cmp_with_unwrap() { #[allow(clippy::unnecessary_operation)] fn ends_with() { "".ends_with(' '); + //~^ chars_last_cmp !"".ends_with(' '); + //~^ chars_last_cmp "".ends_with(' '); + //~^ chars_last_cmp !"".ends_with(' '); + //~^ chars_last_cmp // Ensure that suggestion is escaped correctly "".ends_with('\n'); + //~^ chars_last_cmp !"".ends_with('\n'); + //~^ chars_last_cmp } diff --git a/tests/ui/starts_ends_with.rs b/tests/ui/starts_ends_with.rs index 6c5655f31782..dae04ac4a62d 100644 --- a/tests/ui/starts_ends_with.rs +++ b/tests/ui/starts_ends_with.rs @@ -5,36 +5,46 @@ fn main() {} #[allow(clippy::unnecessary_operation)] fn starts_with() { "".chars().next() == Some(' '); + //~^ chars_next_cmp Some(' ') != "".chars().next(); + //~^ chars_next_cmp // Ensure that suggestion is escaped correctly "".chars().next() == Some('\n'); + //~^ chars_next_cmp Some('\n') != "".chars().next(); + //~^ chars_next_cmp } fn chars_cmp_with_unwrap() { let s = String::from("foo"); if s.chars().next().unwrap() == 'f' { + //~^ chars_next_cmp // s.starts_with('f') // Nothing here } if s.chars().next_back().unwrap() == 'o' { + //~^ chars_last_cmp // s.ends_with('o') // Nothing here } if s.chars().last().unwrap() == 'o' { + //~^ chars_last_cmp // s.ends_with('o') // Nothing here } if s.chars().next().unwrap() != 'f' { + //~^ chars_next_cmp // !s.starts_with('f') // Nothing here } if s.chars().next_back().unwrap() != 'o' { + //~^ chars_last_cmp // !s.ends_with('o') // Nothing here } if s.chars().last().unwrap() != '\n' { + //~^ chars_last_cmp // !s.ends_with('o') // Nothing here } @@ -43,11 +53,17 @@ fn chars_cmp_with_unwrap() { #[allow(clippy::unnecessary_operation)] fn ends_with() { "".chars().last() == Some(' '); + //~^ chars_last_cmp Some(' ') != "".chars().last(); + //~^ chars_last_cmp "".chars().next_back() == Some(' '); + //~^ chars_last_cmp Some(' ') != "".chars().next_back(); + //~^ chars_last_cmp // Ensure that suggestion is escaped correctly "".chars().last() == Some('\n'); + //~^ chars_last_cmp Some('\n') != "".chars().last(); + //~^ chars_last_cmp } diff --git a/tests/ui/starts_ends_with.stderr b/tests/ui/starts_ends_with.stderr index cee31f1e4cdd..bcb38f2beb7b 100644 --- a/tests/ui/starts_ends_with.stderr +++ b/tests/ui/starts_ends_with.stderr @@ -8,31 +8,31 @@ LL | "".chars().next() == Some(' '); = help: to override `-D warnings` add `#[allow(clippy::chars_next_cmp)]` error: you should use the `starts_with` method - --> tests/ui/starts_ends_with.rs:8:5 + --> tests/ui/starts_ends_with.rs:9:5 | LL | Some(' ') != "".chars().next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".starts_with(' ')` error: you should use the `starts_with` method - --> tests/ui/starts_ends_with.rs:11:5 + --> tests/ui/starts_ends_with.rs:13:5 | LL | "".chars().next() == Some('\n'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".starts_with('\n')` error: you should use the `starts_with` method - --> tests/ui/starts_ends_with.rs:12:5 + --> tests/ui/starts_ends_with.rs:15:5 | LL | Some('\n') != "".chars().next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".starts_with('\n')` error: you should use the `starts_with` method - --> tests/ui/starts_ends_with.rs:17:8 + --> tests/ui/starts_ends_with.rs:21:8 | LL | if s.chars().next().unwrap() == 'f' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.starts_with('f')` error: you should use the `ends_with` method - --> tests/ui/starts_ends_with.rs:21:8 + --> tests/ui/starts_ends_with.rs:26:8 | LL | if s.chars().next_back().unwrap() == 'o' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` @@ -41,61 +41,61 @@ LL | if s.chars().next_back().unwrap() == 'o' { = help: to override `-D warnings` add `#[allow(clippy::chars_last_cmp)]` error: you should use the `ends_with` method - --> tests/ui/starts_ends_with.rs:25:8 + --> tests/ui/starts_ends_with.rs:31:8 | LL | if s.chars().last().unwrap() == 'o' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `s.ends_with('o')` error: you should use the `starts_with` method - --> tests/ui/starts_ends_with.rs:29:8 + --> tests/ui/starts_ends_with.rs:36:8 | LL | if s.chars().next().unwrap() != 'f' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.starts_with('f')` error: you should use the `ends_with` method - --> tests/ui/starts_ends_with.rs:33:8 + --> tests/ui/starts_ends_with.rs:41:8 | LL | if s.chars().next_back().unwrap() != 'o' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('o')` error: you should use the `ends_with` method - --> tests/ui/starts_ends_with.rs:37:8 + --> tests/ui/starts_ends_with.rs:46:8 | LL | if s.chars().last().unwrap() != '\n' { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!s.ends_with('\n')` error: you should use the `ends_with` method - --> tests/ui/starts_ends_with.rs:45:5 + --> tests/ui/starts_ends_with.rs:55:5 | LL | "".chars().last() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` error: you should use the `ends_with` method - --> tests/ui/starts_ends_with.rs:46:5 + --> tests/ui/starts_ends_with.rs:57:5 | LL | Some(' ') != "".chars().last(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` error: you should use the `ends_with` method - --> tests/ui/starts_ends_with.rs:47:5 + --> tests/ui/starts_ends_with.rs:59:5 | LL | "".chars().next_back() == Some(' '); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with(' ')` error: you should use the `ends_with` method - --> tests/ui/starts_ends_with.rs:48:5 + --> tests/ui/starts_ends_with.rs:61:5 | LL | Some(' ') != "".chars().next_back(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with(' ')` error: you should use the `ends_with` method - --> tests/ui/starts_ends_with.rs:51:5 + --> tests/ui/starts_ends_with.rs:65:5 | LL | "".chars().last() == Some('\n'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `"".ends_with('\n')` error: you should use the `ends_with` method - --> tests/ui/starts_ends_with.rs:52:5 + --> tests/ui/starts_ends_with.rs:67:5 | LL | Some('\n') != "".chars().last(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: like this: `!"".ends_with('\n')` diff --git a/tests/ui/std_instead_of_core.fixed b/tests/ui/std_instead_of_core.fixed index ec158ee02de8..ab2e801eee25 100644 --- a/tests/ui/std_instead_of_core.fixed +++ b/tests/ui/std_instead_of_core.fixed @@ -89,3 +89,4 @@ fn msrv_1_76(_: std::net::IpAddr) {} #[clippy::msrv = "1.77"] fn msrv_1_77(_: core::net::IpAddr) {} +//~^ std_instead_of_core diff --git a/tests/ui/std_instead_of_core.rs b/tests/ui/std_instead_of_core.rs index 9c3c1658d8fe..f760b3561aed 100644 --- a/tests/ui/std_instead_of_core.rs +++ b/tests/ui/std_instead_of_core.rs @@ -89,3 +89,4 @@ fn msrv_1_76(_: std::net::IpAddr) {} #[clippy::msrv = "1.77"] fn msrv_1_77(_: std::net::IpAddr) {} +//~^ std_instead_of_core diff --git a/tests/ui/str_split.fixed b/tests/ui/str_split.fixed index 57a3c315a877..6aca5051c570 100644 --- a/tests/ui/str_split.fixed +++ b/tests/ui/str_split.fixed @@ -58,25 +58,35 @@ fn main() { // Splitting a `str` variable at "\n" or "\r\n" after trimming should warn let _ = s1.lines(); + //~^ str_split_at_newline #[allow(clippy::single_char_pattern)] let _ = s1.lines(); + //~^ str_split_at_newline let _ = s1.lines(); + //~^ str_split_at_newline // Splitting a `String` variable at "\n" or "\r\n" after trimming should warn let _ = s2.lines(); + //~^ str_split_at_newline #[allow(clippy::single_char_pattern)] let _ = s2.lines(); + //~^ str_split_at_newline let _ = s2.lines(); + //~^ str_split_at_newline // Splitting a variable that derefs into `str` at "\n" or "\r\n" after trimming should warn. let s3 = DerefsIntoStr { s: s1 }; let _ = s3.lines(); + //~^ str_split_at_newline #[allow(clippy::single_char_pattern)] let _ = s3.lines(); + //~^ str_split_at_newline let _ = s3.lines(); + //~^ str_split_at_newline // If the `&str` is generated by a macro then the macro should not be expanded in the suggested fix. let _ = make_str!(s1).lines(); + //~^ str_split_at_newline // CASES THAT SHOULD NOT EMIT A LINT diff --git a/tests/ui/str_split.rs b/tests/ui/str_split.rs index fcff036f2649..11e9862da14b 100644 --- a/tests/ui/str_split.rs +++ b/tests/ui/str_split.rs @@ -58,25 +58,35 @@ fn main() { // Splitting a `str` variable at "\n" or "\r\n" after trimming should warn let _ = s1.trim().split('\n'); + //~^ str_split_at_newline #[allow(clippy::single_char_pattern)] let _ = s1.trim().split("\n"); + //~^ str_split_at_newline let _ = s1.trim().split("\r\n"); + //~^ str_split_at_newline // Splitting a `String` variable at "\n" or "\r\n" after trimming should warn let _ = s2.trim().split('\n'); + //~^ str_split_at_newline #[allow(clippy::single_char_pattern)] let _ = s2.trim().split("\n"); + //~^ str_split_at_newline let _ = s2.trim().split("\r\n"); + //~^ str_split_at_newline // Splitting a variable that derefs into `str` at "\n" or "\r\n" after trimming should warn. let s3 = DerefsIntoStr { s: s1 }; let _ = s3.trim().split('\n'); + //~^ str_split_at_newline #[allow(clippy::single_char_pattern)] let _ = s3.trim().split("\n"); + //~^ str_split_at_newline let _ = s3.trim().split("\r\n"); + //~^ str_split_at_newline // If the `&str` is generated by a macro then the macro should not be expanded in the suggested fix. let _ = make_str!(s1).trim().split('\n'); + //~^ str_split_at_newline // CASES THAT SHOULD NOT EMIT A LINT diff --git a/tests/ui/str_split.stderr b/tests/ui/str_split.stderr index 7b560468f126..c4eca81004c5 100644 --- a/tests/ui/str_split.stderr +++ b/tests/ui/str_split.stderr @@ -8,55 +8,55 @@ LL | let _ = s1.trim().split('\n'); = help: to override `-D warnings` add `#[allow(clippy::str_split_at_newline)]` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:62:13 + --> tests/ui/str_split.rs:63:13 | LL | let _ = s1.trim().split("\n"); | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:63:13 + --> tests/ui/str_split.rs:65:13 | LL | let _ = s1.trim().split("\r\n"); | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:66:13 + --> tests/ui/str_split.rs:69:13 | LL | let _ = s2.trim().split('\n'); | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:68:13 + --> tests/ui/str_split.rs:72:13 | LL | let _ = s2.trim().split("\n"); | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:69:13 + --> tests/ui/str_split.rs:74:13 | LL | let _ = s2.trim().split("\r\n"); | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:73:13 + --> tests/ui/str_split.rs:79:13 | LL | let _ = s3.trim().split('\n'); | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:75:13 + --> tests/ui/str_split.rs:82:13 | LL | let _ = s3.trim().split("\n"); | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:76:13 + --> tests/ui/str_split.rs:84:13 | LL | let _ = s3.trim().split("\r\n"); | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:79:13 + --> tests/ui/str_split.rs:88:13 | LL | let _ = make_str!(s1).trim().split('\n'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `make_str!(s1).lines()` diff --git a/tests/ui/str_to_string.fixed b/tests/ui/str_to_string.fixed index 52e40b45a8bd..2941c4dbd33d 100644 --- a/tests/ui/str_to_string.fixed +++ b/tests/ui/str_to_string.fixed @@ -2,8 +2,9 @@ fn main() { let hello = "hello world".to_owned(); - //~^ ERROR: `to_string()` called on a `&str` + //~^ str_to_string + let msg = &hello[..]; msg.to_owned(); - //~^ ERROR: `to_string()` called on a `&str` + //~^ str_to_string } diff --git a/tests/ui/str_to_string.rs b/tests/ui/str_to_string.rs index f93b289c29ab..4c4d2bb18062 100644 --- a/tests/ui/str_to_string.rs +++ b/tests/ui/str_to_string.rs @@ -2,8 +2,9 @@ fn main() { let hello = "hello world".to_string(); - //~^ ERROR: `to_string()` called on a `&str` + //~^ str_to_string + let msg = &hello[..]; msg.to_string(); - //~^ ERROR: `to_string()` called on a `&str` + //~^ str_to_string } diff --git a/tests/ui/str_to_string.stderr b/tests/ui/str_to_string.stderr index a761d96cd6b1..cb7b6b48843a 100644 --- a/tests/ui/str_to_string.stderr +++ b/tests/ui/str_to_string.stderr @@ -8,7 +8,7 @@ LL | let hello = "hello world".to_string(); = help: to override `-D warnings` add `#[allow(clippy::str_to_string)]` error: `to_string()` called on a `&str` - --> tests/ui/str_to_string.rs:7:5 + --> tests/ui/str_to_string.rs:8:5 | LL | msg.to_string(); | ^^^^^^^^^^^^^^^ help: try: `msg.to_owned()` diff --git a/tests/ui/string_add.rs b/tests/ui/string_add.rs index c535f2ebbfcb..5c7d13ebcd58 100644 --- a/tests/ui/string_add.rs +++ b/tests/ui/string_add.rs @@ -4,17 +4,19 @@ extern crate proc_macros; use proc_macros::external; #[warn(clippy::string_add)] -#[allow(clippy::string_add_assign, unused)] +#[allow(clippy::assign_op_pattern, clippy::string_add_assign, unused)] fn main() { // ignores assignment distinction let mut x = String::new(); for _ in 1..3 { x = x + "."; + //~^ string_add } let y = String::new(); let z = y + "..."; + //~^ string_add assert_eq!(&x, &z); diff --git a/tests/ui/string_add.stderr b/tests/ui/string_add.stderr index fe6849b894b5..084a439410f8 100644 --- a/tests/ui/string_add.stderr +++ b/tests/ui/string_add.stderr @@ -1,12 +1,3 @@ -error: manual implementation of an assign operation - --> tests/ui/string_add.rs:13:9 - | -LL | x = x + "."; - | ^^^^^^^^^^^ help: replace it with: `x += "."` - | - = note: `-D clippy::assign-op-pattern` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::assign_op_pattern)]` - error: you added something to a string. Consider using `String::push_str()` instead --> tests/ui/string_add.rs:13:13 | @@ -17,16 +8,10 @@ LL | x = x + "."; = help: to override `-D warnings` add `#[allow(clippy::string_add)]` error: you added something to a string. Consider using `String::push_str()` instead - --> tests/ui/string_add.rs:17:13 + --> tests/ui/string_add.rs:18:13 | LL | let z = y + "..."; | ^^^^^^^^^ -error: manual implementation of an assign operation - --> tests/ui/string_add.rs:22:5 - | -LL | x = x + 1; - | ^^^^^^^^^ help: replace it with: `x += 1` - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/string_add_assign.fixed b/tests/ui/string_add_assign.fixed index 31d84831d09a..a86a304684f2 100644 --- a/tests/ui/string_add_assign.fixed +++ b/tests/ui/string_add_assign.fixed @@ -6,6 +6,8 @@ fn main() { for _ in 1..3 { x += "."; + //~^ string_add_assign + //~| assign_op_pattern } let y = String::new(); @@ -15,5 +17,6 @@ fn main() { let mut x = 1; x += 1; + //~^ assign_op_pattern assert_eq!(2, x); } diff --git a/tests/ui/string_add_assign.rs b/tests/ui/string_add_assign.rs index cdea91573cc7..042e33cf8413 100644 --- a/tests/ui/string_add_assign.rs +++ b/tests/ui/string_add_assign.rs @@ -6,6 +6,8 @@ fn main() { for _ in 1..3 { x = x + "."; + //~^ string_add_assign + //~| assign_op_pattern } let y = String::new(); @@ -15,5 +17,6 @@ fn main() { let mut x = 1; x = x + 1; + //~^ assign_op_pattern assert_eq!(2, x); } diff --git a/tests/ui/string_add_assign.stderr b/tests/ui/string_add_assign.stderr index 50f970084e6b..198772747927 100644 --- a/tests/ui/string_add_assign.stderr +++ b/tests/ui/string_add_assign.stderr @@ -17,7 +17,7 @@ LL | x = x + "."; = help: to override `-D warnings` add `#[allow(clippy::assign_op_pattern)]` error: manual implementation of an assign operation - --> tests/ui/string_add_assign.rs:17:5 + --> tests/ui/string_add_assign.rs:19:5 | LL | x = x + 1; | ^^^^^^^^^ help: replace it with: `x += 1` diff --git a/tests/ui/string_extend.fixed b/tests/ui/string_extend.fixed index 142cb6a34980..17d3d927830f 100644 --- a/tests/ui/string_extend.fixed +++ b/tests/ui/string_extend.fixed @@ -14,12 +14,15 @@ fn main() { s.push_str(abc); s.push_str(abc); + //~^ string_extend_chars s.push_str("abc"); s.push_str("abc"); + //~^ string_extend_chars s.push_str(&def); s.push_str(&def); + //~^ string_extend_chars s.extend(abc.chars().skip(1)); s.extend("abc".chars().skip(1)); @@ -30,4 +33,5 @@ fn main() { // issue #9735 s.push_str(&abc[0..2]); + //~^ string_extend_chars } diff --git a/tests/ui/string_extend.rs b/tests/ui/string_extend.rs index 41c0d29fae9c..e2d54f479439 100644 --- a/tests/ui/string_extend.rs +++ b/tests/ui/string_extend.rs @@ -14,12 +14,15 @@ fn main() { s.push_str(abc); s.extend(abc.chars()); + //~^ string_extend_chars s.push_str("abc"); s.extend("abc".chars()); + //~^ string_extend_chars s.push_str(&def); s.extend(def.chars()); + //~^ string_extend_chars s.extend(abc.chars().skip(1)); s.extend("abc".chars().skip(1)); @@ -30,4 +33,5 @@ fn main() { // issue #9735 s.extend(abc[0..2].chars()); + //~^ string_extend_chars } diff --git a/tests/ui/string_extend.stderr b/tests/ui/string_extend.stderr index fadda786aacb..52aad5a02f6d 100644 --- a/tests/ui/string_extend.stderr +++ b/tests/ui/string_extend.stderr @@ -8,19 +8,19 @@ LL | s.extend(abc.chars()); = help: to override `-D warnings` add `#[allow(clippy::string_extend_chars)]` error: calling `.extend(_.chars())` - --> tests/ui/string_extend.rs:19:5 + --> tests/ui/string_extend.rs:20:5 | LL | s.extend("abc".chars()); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.push_str("abc")` error: calling `.extend(_.chars())` - --> tests/ui/string_extend.rs:22:5 + --> tests/ui/string_extend.rs:24:5 | LL | s.extend(def.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `s.push_str(&def)` error: calling `.extend(_.chars())` - --> tests/ui/string_extend.rs:32:5 + --> tests/ui/string_extend.rs:35:5 | LL | s.extend(abc[0..2].chars()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.push_str(&abc[0..2])` diff --git a/tests/ui/string_from_utf8_as_bytes.fixed b/tests/ui/string_from_utf8_as_bytes.fixed index 6aa5a95c6f40..193217114d88 100644 --- a/tests/ui/string_from_utf8_as_bytes.fixed +++ b/tests/ui/string_from_utf8_as_bytes.fixed @@ -2,4 +2,5 @@ fn main() { let _ = Some(&"Hello World!"[6..11]); + //~^ string_from_utf8_as_bytes } diff --git a/tests/ui/string_from_utf8_as_bytes.rs b/tests/ui/string_from_utf8_as_bytes.rs index c8717f7950bd..49beb19ee40f 100644 --- a/tests/ui/string_from_utf8_as_bytes.rs +++ b/tests/ui/string_from_utf8_as_bytes.rs @@ -2,4 +2,5 @@ fn main() { let _ = std::str::from_utf8(&"Hello World!".as_bytes()[6..11]); + //~^ string_from_utf8_as_bytes } diff --git a/tests/ui/string_lit_as_bytes.fixed b/tests/ui/string_lit_as_bytes.fixed index 225d4e90c4e2..2a86dffbc762 100644 --- a/tests/ui/string_lit_as_bytes.fixed +++ b/tests/ui/string_lit_as_bytes.fixed @@ -9,16 +9,21 @@ extern crate macro_rules; macro_rules! b { ($b:literal) => { const B: &[u8] = b"warning"; + //~^ string_lit_as_bytes }; } fn str_lit_as_bytes() { let bs = b"hello there"; + //~^ string_lit_as_bytes let bs = br###"raw string with 3# plus " ""###; + //~^ string_lit_as_bytes let bs = b"lit to string".to_vec(); + //~^ string_lit_as_bytes let bs = b"lit to owned".to_vec(); + //~^ string_lit_as_bytes b!("warning"); @@ -36,8 +41,10 @@ fn str_lit_as_bytes() { let current_version = env!("CARGO_PKG_VERSION").as_bytes(); let includestr = include_bytes!("string_lit_as_bytes.rs"); + //~^ string_lit_as_bytes let _ = b"string with newline\t\n"; + //~^ string_lit_as_bytes let _ = match "x".as_bytes() { b"xx" => 0, diff --git a/tests/ui/string_lit_as_bytes.rs b/tests/ui/string_lit_as_bytes.rs index 3d116214ca42..785d8f1e0f6b 100644 --- a/tests/ui/string_lit_as_bytes.rs +++ b/tests/ui/string_lit_as_bytes.rs @@ -9,16 +9,21 @@ extern crate macro_rules; macro_rules! b { ($b:literal) => { const B: &[u8] = $b.as_bytes(); + //~^ string_lit_as_bytes }; } fn str_lit_as_bytes() { let bs = "hello there".as_bytes(); + //~^ string_lit_as_bytes let bs = r###"raw string with 3# plus " ""###.as_bytes(); + //~^ string_lit_as_bytes let bs = "lit to string".to_string().into_bytes(); + //~^ string_lit_as_bytes let bs = "lit to owned".to_owned().into_bytes(); + //~^ string_lit_as_bytes b!("warning"); @@ -36,8 +41,10 @@ fn str_lit_as_bytes() { let current_version = env!("CARGO_PKG_VERSION").as_bytes(); let includestr = include_str!("string_lit_as_bytes.rs").as_bytes(); + //~^ string_lit_as_bytes let _ = "string with newline\t\n".as_bytes(); + //~^ string_lit_as_bytes let _ = match "x".as_bytes() { b"xx" => 0, diff --git a/tests/ui/string_lit_as_bytes.stderr b/tests/ui/string_lit_as_bytes.stderr index 66b3e6f9462d..9388fbdc775d 100644 --- a/tests/ui/string_lit_as_bytes.stderr +++ b/tests/ui/string_lit_as_bytes.stderr @@ -1,5 +1,5 @@ error: calling `as_bytes()` on a string literal - --> tests/ui/string_lit_as_bytes.rs:16:14 + --> tests/ui/string_lit_as_bytes.rs:17:14 | LL | let bs = "hello there".as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"hello there"` @@ -8,19 +8,19 @@ LL | let bs = "hello there".as_bytes(); = help: to override `-D warnings` add `#[allow(clippy::string_lit_as_bytes)]` error: calling `as_bytes()` on a string literal - --> tests/ui/string_lit_as_bytes.rs:18:14 + --> tests/ui/string_lit_as_bytes.rs:20:14 | LL | let bs = r###"raw string with 3# plus " ""###.as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `br###"raw string with 3# plus " ""###` error: calling `into_bytes()` on a string literal - --> tests/ui/string_lit_as_bytes.rs:20:14 + --> tests/ui/string_lit_as_bytes.rs:23:14 | LL | let bs = "lit to string".to_string().into_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"lit to string".to_vec()` error: calling `into_bytes()` on a string literal - --> tests/ui/string_lit_as_bytes.rs:21:14 + --> tests/ui/string_lit_as_bytes.rs:25:14 | LL | let bs = "lit to owned".to_owned().into_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"lit to owned".to_vec()` @@ -37,13 +37,13 @@ LL | b!("warning"); = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) error: calling `as_bytes()` on `include_str!(..)` - --> tests/ui/string_lit_as_bytes.rs:38:22 + --> tests/ui/string_lit_as_bytes.rs:43:22 | LL | let includestr = include_str!("string_lit_as_bytes.rs").as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `include_bytes!(..)` instead: `include_bytes!("string_lit_as_bytes.rs")` error: calling `as_bytes()` on a string literal - --> tests/ui/string_lit_as_bytes.rs:40:13 + --> tests/ui/string_lit_as_bytes.rs:46:13 | LL | let _ = "string with newline\t\n".as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"string with newline\t\n"` diff --git a/tests/ui/string_lit_chars_any.fixed b/tests/ui/string_lit_chars_any.fixed index 03e20c16ee63..cf05a2c2e835 100644 --- a/tests/ui/string_lit_chars_any.fixed +++ b/tests/ui/string_lit_chars_any.fixed @@ -16,11 +16,16 @@ impl NotStringLit { fn main() { let c = 'c'; matches!(c, '\\' | '.' | '+' | '*' | '?' | '(' | ')' | '|' | '[' | ']' | '{' | '}' | '^' | '$' | '#' | '&' | '-' | '~'); + //~^ string_lit_chars_any matches!(c, '\\' | '.' | '+' | '*' | '?' | '(' | ')' | '|' | '[' | ']' | '{' | '}' | '^' | '$' | '#' | '&' | '-' | '~'); + //~^ string_lit_chars_any matches!(c, '\\' | '.' | '+' | '*' | '?' | '(' | ')' | '|' | '[' | ']' | '{' | '}' | '^' | '$' | '#' | '&' | '-' | '~'); + //~^ string_lit_chars_any matches!(c, '\\' | '.' | '+' | '*' | '?' | '(' | ')' | '|' | '[' | ']' | '{' | '}' | '^' | '$' | '#' | '&' | '-' | '~'); + //~^ string_lit_chars_any #[rustfmt::skip] matches!(c, '\\' | '.' | '+' | '*' | '?' | '(' | ')' | '|' | '[' | ']' | '{' | '}' | '^' | '$' | '#' | '&' | '-' | '~'); + //~^ string_lit_chars_any // Do not lint NotStringLit.chars().any(|x| x == c); "\\.+*?()|[]{}^$#&-~".chars().any(|x| { diff --git a/tests/ui/string_lit_chars_any.rs b/tests/ui/string_lit_chars_any.rs index 12e6ffb6a9c4..22cfb784ed7d 100644 --- a/tests/ui/string_lit_chars_any.rs +++ b/tests/ui/string_lit_chars_any.rs @@ -16,11 +16,16 @@ impl NotStringLit { fn main() { let c = 'c'; "\\.+*?()|[]{}^$#&-~".chars().any(|x| x == c); + //~^ string_lit_chars_any r#"\.+*?()|[]{}^$#&-~"#.chars().any(|x| x == c); + //~^ string_lit_chars_any "\\.+*?()|[]{}^$#&-~".chars().any(|x| c == x); + //~^ string_lit_chars_any r#"\.+*?()|[]{}^$#&-~"#.chars().any(|x| c == x); + //~^ string_lit_chars_any #[rustfmt::skip] "\\.+*?()|[]{}^$#&-~".chars().any(|x| { x == c }); + //~^ string_lit_chars_any // Do not lint NotStringLit.chars().any(|x| x == c); "\\.+*?()|[]{}^$#&-~".chars().any(|x| { diff --git a/tests/ui/string_lit_chars_any.stderr b/tests/ui/string_lit_chars_any.stderr index 1e28ae7b163e..3ba447b3c36b 100644 --- a/tests/ui/string_lit_chars_any.stderr +++ b/tests/ui/string_lit_chars_any.stderr @@ -13,7 +13,7 @@ LL + matches!(c, '\\' | '.' | '+' | '*' | '?' | '(' | ')' | '|' | '[' | ']' | error: usage of `.chars().any(...)` to check if a char matches any from a string literal - --> tests/ui/string_lit_chars_any.rs:19:5 + --> tests/ui/string_lit_chars_any.rs:20:5 | LL | r#"\.+*?()|[]{}^$#&-~"#.chars().any(|x| x == c); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + matches!(c, '\\' | '.' | '+' | '*' | '?' | '(' | ')' | '|' | '[' | ']' | error: usage of `.chars().any(...)` to check if a char matches any from a string literal - --> tests/ui/string_lit_chars_any.rs:20:5 + --> tests/ui/string_lit_chars_any.rs:22:5 | LL | "\\.+*?()|[]{}^$#&-~".chars().any(|x| c == x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + matches!(c, '\\' | '.' | '+' | '*' | '?' | '(' | ')' | '|' | '[' | ']' | error: usage of `.chars().any(...)` to check if a char matches any from a string literal - --> tests/ui/string_lit_chars_any.rs:21:5 + --> tests/ui/string_lit_chars_any.rs:24:5 | LL | r#"\.+*?()|[]{}^$#&-~"#.chars().any(|x| c == x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + matches!(c, '\\' | '.' | '+' | '*' | '?' | '(' | ')' | '|' | '[' | ']' | error: usage of `.chars().any(...)` to check if a char matches any from a string literal - --> tests/ui/string_lit_chars_any.rs:23:5 + --> tests/ui/string_lit_chars_any.rs:27:5 | LL | "\\.+*?()|[]{}^$#&-~".chars().any(|x| { x == c }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/string_slice.rs b/tests/ui/string_slice.rs index dc519493a4dd..0acc48c1f412 100644 --- a/tests/ui/string_slice.rs +++ b/tests/ui/string_slice.rs @@ -5,15 +5,17 @@ use std::borrow::Cow; fn main() { &"Ölkanne"[1..]; - //~^ ERROR: indexing into a string may panic if the index is within a UTF-8 character - //~| NOTE: `-D clippy::string-slice` implied by `-D warnings` + //~^ string_slice + let m = "Mötörhead"; &m[2..5]; - //~^ ERROR: indexing into a string may panic if the index is within a UTF-8 character + //~^ string_slice + let s = String::from(m); &s[0..2]; - //~^ ERROR: indexing into a string may panic if the index is within a UTF-8 character + //~^ string_slice + let a = Cow::Borrowed("foo"); &a[0..3]; - //~^ ERROR: indexing into a string may panic if the index is within a UTF-8 character + //~^ string_slice } diff --git a/tests/ui/string_slice.stderr b/tests/ui/string_slice.stderr index bc0fcde34b82..f99413c6dfc6 100644 --- a/tests/ui/string_slice.stderr +++ b/tests/ui/string_slice.stderr @@ -14,13 +14,13 @@ LL | &m[2..5]; | ^^^^^^^ error: indexing into a string may panic if the index is within a UTF-8 character - --> tests/ui/string_slice.rs:14:6 + --> tests/ui/string_slice.rs:15:6 | LL | &s[0..2]; | ^^^^^^^ error: indexing into a string may panic if the index is within a UTF-8 character - --> tests/ui/string_slice.rs:17:6 + --> tests/ui/string_slice.rs:19:6 | LL | &a[0..3]; | ^^^^^^^ diff --git a/tests/ui/string_to_string.rs b/tests/ui/string_to_string.rs index 007685b60179..94174e1253b8 100644 --- a/tests/ui/string_to_string.rs +++ b/tests/ui/string_to_string.rs @@ -4,5 +4,5 @@ fn main() { let mut message = String::from("Hello"); let mut v = message.to_string(); - //~^ ERROR: `to_string()` called on a `String` + //~^ string_to_string } diff --git a/tests/ui/strlen_on_c_strings.fixed b/tests/ui/strlen_on_c_strings.fixed index 1e7d04ffb9df..31ed1cf03a2d 100644 --- a/tests/ui/strlen_on_c_strings.fixed +++ b/tests/ui/strlen_on_c_strings.fixed @@ -11,22 +11,29 @@ fn main() { // CString let cstring = CString::new("foo").expect("CString::new failed"); let _ = cstring.as_bytes().len(); + //~^ strlen_on_c_strings // CStr let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); let _ = cstr.to_bytes().len(); + //~^ strlen_on_c_strings let _ = cstr.to_bytes().len(); + //~^ strlen_on_c_strings let pcstr: *const &CStr = &cstr; let _ = unsafe { (*pcstr).to_bytes().len() }; + //~^ strlen_on_c_strings unsafe fn unsafe_identity(x: T) -> T { x } let _ = unsafe { unsafe_identity(cstr).to_bytes().len() }; + //~^ strlen_on_c_strings let _ = unsafe { unsafe_identity(cstr) }.to_bytes().len(); + //~^ strlen_on_c_strings let f: unsafe fn(_) -> _ = unsafe_identity; let _ = unsafe { f(cstr).to_bytes().len() }; + //~^ strlen_on_c_strings } diff --git a/tests/ui/strlen_on_c_strings.rs b/tests/ui/strlen_on_c_strings.rs index c3ad03591d4e..0f3798c9fd8a 100644 --- a/tests/ui/strlen_on_c_strings.rs +++ b/tests/ui/strlen_on_c_strings.rs @@ -11,22 +11,29 @@ fn main() { // CString let cstring = CString::new("foo").expect("CString::new failed"); let _ = unsafe { libc::strlen(cstring.as_ptr()) }; + //~^ strlen_on_c_strings // CStr let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); let _ = unsafe { libc::strlen(cstr.as_ptr()) }; + //~^ strlen_on_c_strings let _ = unsafe { strlen(cstr.as_ptr()) }; + //~^ strlen_on_c_strings let pcstr: *const &CStr = &cstr; let _ = unsafe { strlen((*pcstr).as_ptr()) }; + //~^ strlen_on_c_strings unsafe fn unsafe_identity(x: T) -> T { x } let _ = unsafe { strlen(unsafe_identity(cstr).as_ptr()) }; + //~^ strlen_on_c_strings let _ = unsafe { strlen(unsafe { unsafe_identity(cstr) }.as_ptr()) }; + //~^ strlen_on_c_strings let f: unsafe fn(_) -> _ = unsafe_identity; let _ = unsafe { strlen(f(cstr).as_ptr()) }; + //~^ strlen_on_c_strings } diff --git a/tests/ui/strlen_on_c_strings.stderr b/tests/ui/strlen_on_c_strings.stderr index 8c2a7692659c..b8619fa2df30 100644 --- a/tests/ui/strlen_on_c_strings.stderr +++ b/tests/ui/strlen_on_c_strings.stderr @@ -8,37 +8,37 @@ LL | let _ = unsafe { libc::strlen(cstring.as_ptr()) }; = help: to override `-D warnings` add `#[allow(clippy::strlen_on_c_strings)]` error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:17:13 + --> tests/ui/strlen_on_c_strings.rs:18:13 | LL | let _ = unsafe { libc::strlen(cstr.as_ptr()) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cstr.to_bytes().len()` error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:19:13 + --> tests/ui/strlen_on_c_strings.rs:21:13 | LL | let _ = unsafe { strlen(cstr.as_ptr()) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cstr.to_bytes().len()` error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:22:22 + --> tests/ui/strlen_on_c_strings.rs:25:22 | LL | let _ = unsafe { strlen((*pcstr).as_ptr()) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(*pcstr).to_bytes().len()` error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:27:22 + --> tests/ui/strlen_on_c_strings.rs:31:22 | LL | let _ = unsafe { strlen(unsafe_identity(cstr).as_ptr()) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unsafe_identity(cstr).to_bytes().len()` error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:28:13 + --> tests/ui/strlen_on_c_strings.rs:33:13 | LL | let _ = unsafe { strlen(unsafe { unsafe_identity(cstr) }.as_ptr()) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unsafe { unsafe_identity(cstr) }.to_bytes().len()` error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:31:22 + --> tests/ui/strlen_on_c_strings.rs:37:22 | LL | let _ = unsafe { strlen(f(cstr).as_ptr()) }; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `f(cstr).to_bytes().len()` diff --git a/tests/ui/struct_excessive_bools.rs b/tests/ui/struct_excessive_bools.rs index 8137ce7a81c5..36cbc6278030 100644 --- a/tests/ui/struct_excessive_bools.rs +++ b/tests/ui/struct_excessive_bools.rs @@ -20,7 +20,7 @@ struct Foo { } struct BadFoo { - //~^ ERROR: more than 3 bools in a struct + //~^ struct_excessive_bools a: bool, b: bool, c: bool, @@ -37,7 +37,7 @@ struct Bar { fn main() { struct FooFoo { - //~^ ERROR: more than 3 bools in a struct + //~^ struct_excessive_bools a: bool, b: bool, c: bool, diff --git a/tests/ui/struct_fields.rs b/tests/ui/struct_fields.rs index 7c8867bd0fa3..3dce530efffa 100644 --- a/tests/ui/struct_fields.rs +++ b/tests/ui/struct_fields.rs @@ -339,7 +339,9 @@ struct Use { use_foo: bool, //~^ ERROR: field name starts with the struct's name use_bar: bool, + //~^ struct_field_names use_baz: bool, + //~^ struct_field_names } fn main() {} diff --git a/tests/ui/struct_fields.stderr b/tests/ui/struct_fields.stderr index cfda18c708c0..79186cc1cfd8 100644 --- a/tests/ui/struct_fields.stderr +++ b/tests/ui/struct_fields.stderr @@ -276,7 +276,7 @@ LL | use_bar: bool, | ^^^^^^^^^^^^^ error: field name starts with the struct's name - --> tests/ui/struct_fields.rs:342:5 + --> tests/ui/struct_fields.rs:343:5 | LL | use_baz: bool, | ^^^^^^^^^^^^^ diff --git a/tests/ui/suspicious_arithmetic_impl.rs b/tests/ui/suspicious_arithmetic_impl.rs index 07280351e76c..9798d2049c62 100644 --- a/tests/ui/suspicious_arithmetic_impl.rs +++ b/tests/ui/suspicious_arithmetic_impl.rs @@ -12,16 +12,14 @@ impl Add for Foo { fn add(self, other: Self) -> Self { Foo(self.0 - other.0) - //~^ ERROR: suspicious use of `-` in `Add` impl - //~| NOTE: `-D clippy::suspicious-arithmetic-impl` implied by `-D warnings` + //~^ suspicious_arithmetic_impl } } impl AddAssign for Foo { fn add_assign(&mut self, other: Foo) { *self = *self - other; - //~^ ERROR: suspicious use of `-` in `AddAssign` impl - //~| NOTE: `-D clippy::suspicious-op-assign-impl` implied by `-D warnings` + //~^ suspicious_op_assign_impl } } @@ -35,7 +33,7 @@ impl BitOrAssign for Foo { impl MulAssign for Foo { fn mul_assign(&mut self, other: Foo) { self.0 /= other.0; - //~^ ERROR: suspicious use of `/` in `MulAssign` impl + //~^ suspicious_op_assign_impl } } @@ -74,7 +72,7 @@ impl Rem for Foo { fn rem(self, other: Self) -> Self { Foo(self.0 / other.0) - //~^ ERROR: suspicious use of `/` in `Rem` impl + //~^ suspicious_arithmetic_impl } } @@ -83,7 +81,7 @@ impl BitAnd for Foo { fn bitand(self, other: Self) -> Self { Foo(self.0 | other.0) - //~^ ERROR: suspicious use of `|` in `BitAnd` impl + //~^ suspicious_arithmetic_impl } } @@ -92,7 +90,7 @@ impl BitOr for Foo { fn bitor(self, other: Self) -> Self { Foo(self.0 ^ other.0) - //~^ ERROR: suspicious use of `^` in `BitOr` impl + //~^ suspicious_arithmetic_impl } } @@ -101,7 +99,7 @@ impl BitXor for Foo { fn bitxor(self, other: Self) -> Self { Foo(self.0 & other.0) - //~^ ERROR: suspicious use of `&` in `BitXor` impl + //~^ suspicious_arithmetic_impl } } @@ -110,7 +108,7 @@ impl Shl for Foo { fn shl(self, other: Self) -> Self { Foo(self.0 >> other.0) - //~^ ERROR: suspicious use of `>>` in `Shl` impl + //~^ suspicious_arithmetic_impl } } @@ -119,7 +117,7 @@ impl Shr for Foo { fn shr(self, other: Self) -> Self { Foo(self.0 << other.0) - //~^ ERROR: suspicious use of `<<` in `Shr` impl + //~^ suspicious_arithmetic_impl } } diff --git a/tests/ui/suspicious_arithmetic_impl.stderr b/tests/ui/suspicious_arithmetic_impl.stderr index 1bfca49a635d..2d8aac4db2a7 100644 --- a/tests/ui/suspicious_arithmetic_impl.stderr +++ b/tests/ui/suspicious_arithmetic_impl.stderr @@ -8,7 +8,7 @@ LL | Foo(self.0 - other.0) = help: to override `-D warnings` add `#[allow(clippy::suspicious_arithmetic_impl)]` error: suspicious use of `-` in `AddAssign` impl - --> tests/ui/suspicious_arithmetic_impl.rs:22:23 + --> tests/ui/suspicious_arithmetic_impl.rs:21:23 | LL | *self = *self - other; | ^ @@ -17,43 +17,43 @@ LL | *self = *self - other; = help: to override `-D warnings` add `#[allow(clippy::suspicious_op_assign_impl)]` error: suspicious use of `/` in `MulAssign` impl - --> tests/ui/suspicious_arithmetic_impl.rs:37:16 + --> tests/ui/suspicious_arithmetic_impl.rs:35:16 | LL | self.0 /= other.0; | ^^ error: suspicious use of `/` in `Rem` impl - --> tests/ui/suspicious_arithmetic_impl.rs:76:20 + --> tests/ui/suspicious_arithmetic_impl.rs:74:20 | LL | Foo(self.0 / other.0) | ^ error: suspicious use of `|` in `BitAnd` impl - --> tests/ui/suspicious_arithmetic_impl.rs:85:20 + --> tests/ui/suspicious_arithmetic_impl.rs:83:20 | LL | Foo(self.0 | other.0) | ^ error: suspicious use of `^` in `BitOr` impl - --> tests/ui/suspicious_arithmetic_impl.rs:94:20 + --> tests/ui/suspicious_arithmetic_impl.rs:92:20 | LL | Foo(self.0 ^ other.0) | ^ error: suspicious use of `&` in `BitXor` impl - --> tests/ui/suspicious_arithmetic_impl.rs:103:20 + --> tests/ui/suspicious_arithmetic_impl.rs:101:20 | LL | Foo(self.0 & other.0) | ^ error: suspicious use of `>>` in `Shl` impl - --> tests/ui/suspicious_arithmetic_impl.rs:112:20 + --> tests/ui/suspicious_arithmetic_impl.rs:110:20 | LL | Foo(self.0 >> other.0) | ^^ error: suspicious use of `<<` in `Shr` impl - --> tests/ui/suspicious_arithmetic_impl.rs:121:20 + --> tests/ui/suspicious_arithmetic_impl.rs:119:20 | LL | Foo(self.0 << other.0) | ^^ diff --git a/tests/ui/suspicious_command_arg_space.fixed b/tests/ui/suspicious_command_arg_space.fixed index 704d6ea1bb83..0a0d90f75e57 100644 --- a/tests/ui/suspicious_command_arg_space.fixed +++ b/tests/ui/suspicious_command_arg_space.fixed @@ -2,10 +2,10 @@ fn main() { // Things it should warn about: std::process::Command::new("echo").args(["-n", "hello"]).spawn().unwrap(); - //~^ ERROR: single argument that looks like it should be multiple arguments - //~| NOTE: `-D clippy::suspicious-command-arg-space` implied by `-D warnings` + //~^ suspicious_command_arg_space + std::process::Command::new("cat").args(["--number", "file"]).spawn().unwrap(); - //~^ ERROR: single argument that looks like it should be multiple arguments + //~^ suspicious_command_arg_space // Things it should not warn about: std::process::Command::new("echo").arg("hello world").spawn().unwrap(); diff --git a/tests/ui/suspicious_command_arg_space.rs b/tests/ui/suspicious_command_arg_space.rs index 2a2a7557381c..78bdfbdf0cb6 100644 --- a/tests/ui/suspicious_command_arg_space.rs +++ b/tests/ui/suspicious_command_arg_space.rs @@ -2,10 +2,10 @@ fn main() { // Things it should warn about: std::process::Command::new("echo").arg("-n hello").spawn().unwrap(); - //~^ ERROR: single argument that looks like it should be multiple arguments - //~| NOTE: `-D clippy::suspicious-command-arg-space` implied by `-D warnings` + //~^ suspicious_command_arg_space + std::process::Command::new("cat").arg("--number file").spawn().unwrap(); - //~^ ERROR: single argument that looks like it should be multiple arguments + //~^ suspicious_command_arg_space // Things it should not warn about: std::process::Command::new("echo").arg("hello world").spawn().unwrap(); diff --git a/tests/ui/suspicious_doc_comments.fixed b/tests/ui/suspicious_doc_comments.fixed index d3df6a41cb12..3696b0e066d2 100644 --- a/tests/ui/suspicious_doc_comments.fixed +++ b/tests/ui/suspicious_doc_comments.fixed @@ -4,10 +4,12 @@ //! Real module documentation. //! Fake module documentation. +//~^ suspicious_doc_comments fn baz() {} pub mod singleline_outer_doc { //! This module contains useful functions. + //~^ suspicious_doc_comments pub fn bar() {} } @@ -21,6 +23,7 @@ pub mod singleline_inner_doc { pub mod multiline_outer_doc { /*! This module contains useful functions. */ + //~^^ suspicious_doc_comments pub fn bar() {} } @@ -34,6 +37,7 @@ pub mod multiline_inner_doc { pub mod multiline_outer_doc2 { //! This module + //~^ suspicious_doc_comments //! contains //! useful functions. @@ -42,6 +46,7 @@ pub mod multiline_outer_doc2 { pub mod multiline_outer_doc3 { //! a + //~^ suspicious_doc_comments //! b /// c @@ -50,12 +55,14 @@ pub mod multiline_outer_doc3 { pub mod multiline_outer_doc4 { //! a + //~^ suspicious_doc_comments /// b pub fn bar() {} } pub mod multiline_outer_doc_gap { //! a + //~^ suspicious_doc_comments //! b pub fn bar() {} @@ -68,6 +75,7 @@ pub mod multiline_outer_doc_commented { pub mod outer_doc_macro { //! Very cool macro + //~^ suspicious_doc_comments macro_rules! x { () => {}; } @@ -75,6 +83,7 @@ pub mod outer_doc_macro { pub mod useless_outer_doc { //! Huh. + //~^ suspicious_doc_comments use std::mem; } diff --git a/tests/ui/suspicious_doc_comments.rs b/tests/ui/suspicious_doc_comments.rs index 04db2b199c09..4107f5526d13 100644 --- a/tests/ui/suspicious_doc_comments.rs +++ b/tests/ui/suspicious_doc_comments.rs @@ -4,10 +4,12 @@ //! Real module documentation. ///! Fake module documentation. +//~^ suspicious_doc_comments fn baz() {} pub mod singleline_outer_doc { ///! This module contains useful functions. + //~^ suspicious_doc_comments pub fn bar() {} } @@ -21,6 +23,7 @@ pub mod singleline_inner_doc { pub mod multiline_outer_doc { /**! This module contains useful functions. */ + //~^^ suspicious_doc_comments pub fn bar() {} } @@ -34,6 +37,7 @@ pub mod multiline_inner_doc { pub mod multiline_outer_doc2 { ///! This module + //~^ suspicious_doc_comments ///! contains ///! useful functions. @@ -42,6 +46,7 @@ pub mod multiline_outer_doc2 { pub mod multiline_outer_doc3 { ///! a + //~^ suspicious_doc_comments ///! b /// c @@ -50,12 +55,14 @@ pub mod multiline_outer_doc3 { pub mod multiline_outer_doc4 { ///! a + //~^ suspicious_doc_comments /// b pub fn bar() {} } pub mod multiline_outer_doc_gap { ///! a + //~^ suspicious_doc_comments ///! b pub fn bar() {} @@ -68,6 +75,7 @@ pub mod multiline_outer_doc_commented { pub mod outer_doc_macro { ///! Very cool macro + //~^ suspicious_doc_comments macro_rules! x { () => {}; } @@ -75,6 +83,7 @@ pub mod outer_doc_macro { pub mod useless_outer_doc { ///! Huh. + //~^ suspicious_doc_comments use std::mem; } diff --git a/tests/ui/suspicious_doc_comments.stderr b/tests/ui/suspicious_doc_comments.stderr index 7e5933df2376..df04d08537c9 100644 --- a/tests/ui/suspicious_doc_comments.stderr +++ b/tests/ui/suspicious_doc_comments.stderr @@ -13,7 +13,7 @@ LL + //! Fake module documentation. | error: this is an outer doc comment and does not apply to the parent module or crate - --> tests/ui/suspicious_doc_comments.rs:10:5 + --> tests/ui/suspicious_doc_comments.rs:11:5 | LL | ///! This module contains useful functions. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + //! This module contains useful functions. | error: this is an outer doc comment and does not apply to the parent module or crate - --> tests/ui/suspicious_doc_comments.rs:22:5 + --> tests/ui/suspicious_doc_comments.rs:24:5 | LL | / /**! This module contains useful functions. LL | | */ @@ -38,9 +38,10 @@ LL + */ | error: this is an outer doc comment and does not apply to the parent module or crate - --> tests/ui/suspicious_doc_comments.rs:36:5 + --> tests/ui/suspicious_doc_comments.rs:39:5 | LL | / ///! This module +LL | | LL | | ///! contains LL | | ///! useful functions. | |__________________________^ @@ -48,37 +49,13 @@ LL | | ///! useful functions. help: use an inner doc comment to document the parent module or crate | LL ~ //! This module +LL | LL ~ //! contains LL ~ //! useful functions. | error: this is an outer doc comment and does not apply to the parent module or crate - --> tests/ui/suspicious_doc_comments.rs:44:5 - | -LL | / ///! a -LL | | ///! b - | |__________^ - | -help: use an inner doc comment to document the parent module or crate - | -LL ~ //! a -LL ~ //! b - | - -error: this is an outer doc comment and does not apply to the parent module or crate - --> tests/ui/suspicious_doc_comments.rs:52:5 - | -LL | ///! a - | ^^^^^^ - | -help: use an inner doc comment to document the parent module or crate - | -LL - ///! a -LL + //! a - | - -error: this is an outer doc comment and does not apply to the parent module or crate - --> tests/ui/suspicious_doc_comments.rs:58:5 + --> tests/ui/suspicious_doc_comments.rs:48:5 | LL | / ///! a LL | | @@ -93,7 +70,35 @@ LL ~ //! b | error: this is an outer doc comment and does not apply to the parent module or crate - --> tests/ui/suspicious_doc_comments.rs:70:5 + --> tests/ui/suspicious_doc_comments.rs:57:5 + | +LL | ///! a + | ^^^^^^ + | +help: use an inner doc comment to document the parent module or crate + | +LL - ///! a +LL + //! a + | + +error: this is an outer doc comment and does not apply to the parent module or crate + --> tests/ui/suspicious_doc_comments.rs:64:5 + | +LL | / ///! a +... | +LL | | ///! b + | |__________^ + | +help: use an inner doc comment to document the parent module or crate + | +LL ~ //! a +LL | +LL | +LL ~ //! b + | + +error: this is an outer doc comment and does not apply to the parent module or crate + --> tests/ui/suspicious_doc_comments.rs:77:5 | LL | ///! Very cool macro | ^^^^^^^^^^^^^^^^^^^^ @@ -105,7 +110,7 @@ LL + //! Very cool macro | error: this is an outer doc comment and does not apply to the parent module or crate - --> tests/ui/suspicious_doc_comments.rs:77:5 + --> tests/ui/suspicious_doc_comments.rs:85:5 | LL | ///! Huh. | ^^^^^^^^^ diff --git a/tests/ui/suspicious_doc_comments_unfixable.rs b/tests/ui/suspicious_doc_comments_unfixable.rs index 9e9c4775748c..17c7cc15b170 100644 --- a/tests/ui/suspicious_doc_comments_unfixable.rs +++ b/tests/ui/suspicious_doc_comments_unfixable.rs @@ -1,16 +1,17 @@ -#![allow(unused)] +#![allow(unused, clippy::empty_line_after_doc_comments)] #![warn(clippy::suspicious_doc_comments)] //@no-rustfix ///! a -//~^ ERROR: this is an outer doc comment and does not apply to the parent module or crate -//~| NOTE: `-D clippy::suspicious-doc-comments` implied by `-D warnings` +//~^ suspicious_doc_comments + ///! b /// c ///! d pub fn foo() {} ///! a -//~^ ERROR: this is an outer doc comment and does not apply to the parent module or crate +//~^ suspicious_doc_comments + ///! b /// c ///! d diff --git a/tests/ui/suspicious_doc_comments_unfixable.stderr b/tests/ui/suspicious_doc_comments_unfixable.stderr index d15f16f7c503..234a22021df3 100644 --- a/tests/ui/suspicious_doc_comments_unfixable.stderr +++ b/tests/ui/suspicious_doc_comments_unfixable.stderr @@ -26,6 +26,7 @@ error: this is an outer doc comment and does not apply to the parent module or c | LL | / ///! a LL | | +LL | | LL | | ///! b LL | | /// c LL | | ///! d @@ -35,6 +36,7 @@ help: use an inner doc comment to document the parent module or crate | LL + //! a LL | +LL | LL + //! b LL | /// c LL + //! d diff --git a/tests/ui/suspicious_else_formatting.rs b/tests/ui/suspicious_else_formatting.rs index 3d5c892eb606..28a3b551116d 100644 --- a/tests/ui/suspicious_else_formatting.rs +++ b/tests/ui/suspicious_else_formatting.rs @@ -20,10 +20,12 @@ fn main() { // weird `else` formatting: if foo() { } { + //~^ suspicious_else_formatting } if foo() { } if foo() { + //~^ suspicious_else_formatting } let _ = { // if as the last expression @@ -31,6 +33,7 @@ fn main() { if foo() { } if foo() { + //~^ suspicious_else_formatting } else { } @@ -39,6 +42,7 @@ fn main() { let _ = { // if in the middle of a block if foo() { } if foo() { + //~^ suspicious_else_formatting } else { } @@ -50,6 +54,7 @@ fn main() { } else { } + //~^^^ suspicious_else_formatting // This is fine, though weird. Allman style braces on the else. if foo() { @@ -62,12 +67,14 @@ fn main() { } else if foo() { // the span of the above error should continue here } + //~^^^ suspicious_else_formatting if foo() { } else if foo() { // the span of the above error should continue here } + //~^^^^ suspicious_else_formatting // those are ok: if foo() { @@ -95,8 +102,8 @@ fn main() { else { - } + //~^^^^^ suspicious_else_formatting if foo() { } @@ -105,6 +112,7 @@ fn main() { { } + //~^^^^^^ suspicious_else_formatting // #3864 - Allman style braces if foo() diff --git a/tests/ui/suspicious_else_formatting.stderr b/tests/ui/suspicious_else_formatting.stderr index 28c5a2d904ce..affd20b22d9c 100644 --- a/tests/ui/suspicious_else_formatting.stderr +++ b/tests/ui/suspicious_else_formatting.stderr @@ -9,7 +9,7 @@ LL | } { = help: to override `-D warnings` add `#[allow(clippy::suspicious_else_formatting)]` error: this looks like an `else if` but the `else` is missing - --> tests/ui/suspicious_else_formatting.rs:26:6 + --> tests/ui/suspicious_else_formatting.rs:27:6 | LL | } if foo() { | ^ @@ -17,7 +17,7 @@ LL | } if foo() { = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this looks like an `else if` but the `else` is missing - --> tests/ui/suspicious_else_formatting.rs:33:10 + --> tests/ui/suspicious_else_formatting.rs:35:10 | LL | } if foo() { | ^ @@ -25,7 +25,7 @@ LL | } if foo() { = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this looks like an `else if` but the `else` is missing - --> tests/ui/suspicious_else_formatting.rs:41:10 + --> tests/ui/suspicious_else_formatting.rs:44:10 | LL | } if foo() { | ^ @@ -33,7 +33,7 @@ LL | } if foo() { = note: to remove this lint, add the missing `else` or add a new line before the second `if` error: this is an `else {..}` but the formatting might hide it - --> tests/ui/suspicious_else_formatting.rs:50:6 + --> tests/ui/suspicious_else_formatting.rs:54:6 | LL | } else | ______^ @@ -43,7 +43,7 @@ LL | | { = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}` error: this is an `else if` but the formatting might hide it - --> tests/ui/suspicious_else_formatting.rs:62:6 + --> tests/ui/suspicious_else_formatting.rs:67:6 | LL | } else | ______^ @@ -53,7 +53,7 @@ LL | | if foo() { // the span of the above error should continue here = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` error: this is an `else if` but the formatting might hide it - --> tests/ui/suspicious_else_formatting.rs:67:6 + --> tests/ui/suspicious_else_formatting.rs:73:6 | LL | } | ______^ @@ -64,7 +64,7 @@ LL | | if foo() { // the span of the above error should continue here = note: to remove this lint, remove the `else` or remove the new line between `else` and `if` error: this is an `else {..}` but the formatting might hide it - --> tests/ui/suspicious_else_formatting.rs:94:6 + --> tests/ui/suspicious_else_formatting.rs:101:6 | LL | } | ______^ @@ -76,7 +76,7 @@ LL | | { = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}` error: this is an `else {..}` but the formatting might hide it - --> tests/ui/suspicious_else_formatting.rs:102:6 + --> tests/ui/suspicious_else_formatting.rs:109:6 | LL | } | ______^ diff --git a/tests/ui/suspicious_map.rs b/tests/ui/suspicious_map.rs index d4a52cb110fb..86e48e29bb9e 100644 --- a/tests/ui/suspicious_map.rs +++ b/tests/ui/suspicious_map.rs @@ -3,11 +3,11 @@ fn main() { let _ = (0..3).map(|x| x + 2).count(); - //~^ ERROR: this call to `map()` won't have an effect on the call to `count()` + //~^ suspicious_map let f = |x| x + 1; let _ = (0..3).map(f).count(); - //~^ ERROR: this call to `map()` won't have an effect on the call to `count()` + //~^ suspicious_map } fn negative() { diff --git a/tests/ui/suspicious_operation_groupings.fixed b/tests/ui/suspicious_operation_groupings.fixed index 60fde6e22cb6..fa680e537d30 100644 --- a/tests/ui/suspicious_operation_groupings.fixed +++ b/tests/ui/suspicious_operation_groupings.fixed @@ -1,7 +1,7 @@ //@compile-flags: -Zdeduplicate-diagnostics=yes #![warn(clippy::suspicious_operation_groupings)] -#![allow(dead_code, unused_parens, clippy::eq_op)] +#![allow(dead_code, unused_parens, clippy::eq_op, clippy::manual_midpoint)] struct Vec3 { x: f64, @@ -15,6 +15,7 @@ impl PartialEq for Vec3 { fn eq(&self, other: &Self) -> bool { // This should trigger the lint because `self.x` is compared to `other.y` self.x == other.x && self.y == other.y && self.z == other.z + //~^ suspicious_operation_groupings } } @@ -28,6 +29,7 @@ struct S { fn buggy_ab_cmp(s1: &S, s2: &S) -> bool { // There's no `s1.b` s1.a < s2.a && s1.b < s2.b + //~^ suspicious_operation_groupings } struct SaOnly { @@ -76,31 +78,38 @@ fn permissable(s1: &S, s2: &S) -> bool { fn non_boolean_operators(s1: &S, s2: &S) -> i32 { // There's no `s2.c` s1.a * s2.a + s1.b * s2.b + s1.c * s2.c + s1.d * s2.d + //~^ suspicious_operation_groupings } fn odd_number_of_pairs(s1: &S, s2: &S) -> i32 { // There's no `s2.b` s1.a * s2.a + s1.b * s2.b + s1.c * s2.c + //~^ suspicious_operation_groupings + //~| suspicious_operation_groupings } fn not_caught_by_eq_op_middle_change_left(s1: &S, s2: &S) -> i32 { // There's no `s1.b` s1.a * s2.a + s1.b * s2.b + s1.c * s2.c + //~^ suspicious_operation_groupings } fn not_caught_by_eq_op_middle_change_right(s1: &S, s2: &S) -> i32 { // There's no `s2.b` s1.a * s2.a + s1.b * s2.b + s1.c * s2.c + //~^ suspicious_operation_groupings } fn not_caught_by_eq_op_start(s1: &S, s2: &S) -> i32 { // There's no `s2.a` s1.a * s2.a + s1.b * s2.b + s1.c * s2.c + //~^ suspicious_operation_groupings } fn not_caught_by_eq_op_end(s1: &S, s2: &S) -> i32 { // There's no `s2.c` s1.a * s2.a + s1.b * s2.b + s1.c * s2.c + //~^ suspicious_operation_groupings } fn the_cross_product_should_not_lint(s1: &S, s2: &S) -> (i32, i32, i32) { @@ -114,56 +123,68 @@ fn the_cross_product_should_not_lint(s1: &S, s2: &S) -> (i32, i32, i32) { fn outer_parens_simple(s1: &S, s2: &S) -> i32 { // There's no `s2.b` (s1.a * s2.a + s1.b * s2.b) + //~^ suspicious_operation_groupings } fn outer_parens(s1: &S, s2: &S) -> i32 { // There's no `s2.c` (s1.a * s2.a + s1.b * s2.b + s1.c * s2.c + s1.d * s2.d) + //~^ suspicious_operation_groupings } fn inner_parens(s1: &S, s2: &S) -> i32 { // There's no `s2.c` (s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.c) + (s1.d * s2.d) + //~^ suspicious_operation_groupings } fn outer_and_some_inner_parens(s1: &S, s2: &S) -> i32 { // There's no `s2.c` ((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.c) + (s1.d * s2.d)) + //~^ suspicious_operation_groupings } fn all_parens_balanced_tree(s1: &S, s2: &S) -> i32 { // There's no `s2.c` (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.c) + (s1.d * s2.d))) + //~^ suspicious_operation_groupings + //~| suspicious_operation_groupings } fn all_parens_left_tree(s1: &S, s2: &S) -> i32 { // There's no `s2.c` (((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.c)) + (s1.d * s2.d)) + //~^ suspicious_operation_groupings } fn all_parens_right_tree(s1: &S, s2: &S) -> i32 { // There's no `s2.c` ((s1.a * s2.a) + ((s1.b * s2.b) + (s1.c * s2.c) + (s1.d * s2.d))) + //~^ suspicious_operation_groupings } fn inside_other_binop_expression(s1: &S, s2: &S) -> i32 { // There's no `s1.b` (s1.a * s2.a + s1.b * s2.b) / 2 + //~^ suspicious_operation_groupings } fn inside_function_call(s1: &S, s2: &S) -> i32 { // There's no `s1.b` i32::swap_bytes(s1.a * s2.a + s1.b * s2.b) + //~^ suspicious_operation_groupings } fn inside_larger_boolean_expression(s1: &S, s2: &S) -> bool { // There's no `s1.c` s1.a > 0 && s1.b > 0 && s1.c == s2.c && s1.d == s2.d + //~^ suspicious_operation_groupings } fn inside_larger_boolean_expression_with_unsorted_ops(s1: &S, s2: &S) -> bool { // There's no `s1.c` s1.a > 0 && s1.c == s2.c && s1.b > 0 && s1.d == s2.d + //~^ suspicious_operation_groupings } struct Nested { @@ -173,6 +194,7 @@ struct Nested { fn changed_middle_ident(n1: &Nested, n2: &Nested) -> bool { // There's no `n2.inner.2.0` (n1.inner.0).0 == (n2.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.2).0 + //~^ suspicious_operation_groupings } // `eq_op` should catch this one. @@ -187,12 +209,14 @@ fn inside_fn_with_similar_expression(s1: &S, s2: &S, strict: bool) -> bool { } else { // There's no `s1.b` in this subexpression s1.a <= s2.a && s1.b <= s2.b + //~^ suspicious_operation_groupings } } fn inside_an_if_statement(s1: &mut S, s2: &S) { // There's no `s1.b` if s1.a < s2.a && s1.b < s2.b { + //~^ suspicious_operation_groupings s1.c = s2.c; } } @@ -200,11 +224,13 @@ fn inside_an_if_statement(s1: &mut S, s2: &S) { fn maximum_unary_minus_right_tree(s1: &S, s2: &S) -> i32 { // There's no `s2.c` -(-(-s1.a * -s2.a) + (-(-s1.b * -s2.b) + -(-s1.c * -s2.c) + -(-s1.d * -s2.d))) + //~^ suspicious_operation_groupings } fn unary_minus_and_an_if_expression(s1: &S, s2: &S) -> i32 { // There's no `s1.b` -(if -s1.a < -s2.a && -s1.b < -s2.b { s1.c } else { s2.a }) + //~^ suspicious_operation_groupings } fn main() {} diff --git a/tests/ui/suspicious_operation_groupings.rs b/tests/ui/suspicious_operation_groupings.rs index ce37148a853b..4ffee640e8bd 100644 --- a/tests/ui/suspicious_operation_groupings.rs +++ b/tests/ui/suspicious_operation_groupings.rs @@ -1,7 +1,7 @@ //@compile-flags: -Zdeduplicate-diagnostics=yes #![warn(clippy::suspicious_operation_groupings)] -#![allow(dead_code, unused_parens, clippy::eq_op)] +#![allow(dead_code, unused_parens, clippy::eq_op, clippy::manual_midpoint)] struct Vec3 { x: f64, @@ -15,6 +15,7 @@ impl PartialEq for Vec3 { fn eq(&self, other: &Self) -> bool { // This should trigger the lint because `self.x` is compared to `other.y` self.x == other.y && self.y == other.y && self.z == other.z + //~^ suspicious_operation_groupings } } @@ -28,6 +29,7 @@ struct S { fn buggy_ab_cmp(s1: &S, s2: &S) -> bool { // There's no `s1.b` s1.a < s2.a && s1.a < s2.b + //~^ suspicious_operation_groupings } struct SaOnly { @@ -76,31 +78,38 @@ fn permissable(s1: &S, s2: &S) -> bool { fn non_boolean_operators(s1: &S, s2: &S) -> i32 { // There's no `s2.c` s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d + //~^ suspicious_operation_groupings } fn odd_number_of_pairs(s1: &S, s2: &S) -> i32 { // There's no `s2.b` s1.a * s2.a + s1.b * s2.c + s1.c * s2.c + //~^ suspicious_operation_groupings + //~| suspicious_operation_groupings } fn not_caught_by_eq_op_middle_change_left(s1: &S, s2: &S) -> i32 { // There's no `s1.b` s1.a * s2.a + s2.b * s2.b + s1.c * s2.c + //~^ suspicious_operation_groupings } fn not_caught_by_eq_op_middle_change_right(s1: &S, s2: &S) -> i32 { // There's no `s2.b` s1.a * s2.a + s1.b * s1.b + s1.c * s2.c + //~^ suspicious_operation_groupings } fn not_caught_by_eq_op_start(s1: &S, s2: &S) -> i32 { // There's no `s2.a` s1.a * s1.a + s1.b * s2.b + s1.c * s2.c + //~^ suspicious_operation_groupings } fn not_caught_by_eq_op_end(s1: &S, s2: &S) -> i32 { // There's no `s2.c` s1.a * s2.a + s1.b * s2.b + s1.c * s1.c + //~^ suspicious_operation_groupings } fn the_cross_product_should_not_lint(s1: &S, s2: &S) -> (i32, i32, i32) { @@ -114,56 +123,68 @@ fn the_cross_product_should_not_lint(s1: &S, s2: &S) -> (i32, i32, i32) { fn outer_parens_simple(s1: &S, s2: &S) -> i32 { // There's no `s2.b` (s1.a * s2.a + s1.b * s1.b) + //~^ suspicious_operation_groupings } fn outer_parens(s1: &S, s2: &S) -> i32 { // There's no `s2.c` (s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d) + //~^ suspicious_operation_groupings } fn inner_parens(s1: &S, s2: &S) -> i32 { // There's no `s2.c` (s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d) + //~^ suspicious_operation_groupings } fn outer_and_some_inner_parens(s1: &S, s2: &S) -> i32 { // There's no `s2.c` ((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d)) + //~^ suspicious_operation_groupings } fn all_parens_balanced_tree(s1: &S, s2: &S) -> i32 { // There's no `s2.c` (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d))) + //~^ suspicious_operation_groupings + //~| suspicious_operation_groupings } fn all_parens_left_tree(s1: &S, s2: &S) -> i32 { // There's no `s2.c` (((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b)) + (s1.d * s2.d)) + //~^ suspicious_operation_groupings } fn all_parens_right_tree(s1: &S, s2: &S) -> i32 { // There's no `s2.c` ((s1.a * s2.a) + ((s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d))) + //~^ suspicious_operation_groupings } fn inside_other_binop_expression(s1: &S, s2: &S) -> i32 { // There's no `s1.b` (s1.a * s2.a + s2.b * s2.b) / 2 + //~^ suspicious_operation_groupings } fn inside_function_call(s1: &S, s2: &S) -> i32 { // There's no `s1.b` i32::swap_bytes(s1.a * s2.a + s2.b * s2.b) + //~^ suspicious_operation_groupings } fn inside_larger_boolean_expression(s1: &S, s2: &S) -> bool { // There's no `s1.c` s1.a > 0 && s1.b > 0 && s1.d == s2.c && s1.d == s2.d + //~^ suspicious_operation_groupings } fn inside_larger_boolean_expression_with_unsorted_ops(s1: &S, s2: &S) -> bool { // There's no `s1.c` s1.a > 0 && s1.d == s2.c && s1.b > 0 && s1.d == s2.d + //~^ suspicious_operation_groupings } struct Nested { @@ -173,6 +194,7 @@ struct Nested { fn changed_middle_ident(n1: &Nested, n2: &Nested) -> bool { // There's no `n2.inner.2.0` (n1.inner.0).0 == (n2.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.1).0 + //~^ suspicious_operation_groupings } // `eq_op` should catch this one. @@ -187,12 +209,14 @@ fn inside_fn_with_similar_expression(s1: &S, s2: &S, strict: bool) -> bool { } else { // There's no `s1.b` in this subexpression s1.a <= s2.a && s1.a <= s2.b + //~^ suspicious_operation_groupings } } fn inside_an_if_statement(s1: &mut S, s2: &S) { // There's no `s1.b` if s1.a < s2.a && s1.a < s2.b { + //~^ suspicious_operation_groupings s1.c = s2.c; } } @@ -200,11 +224,13 @@ fn inside_an_if_statement(s1: &mut S, s2: &S) { fn maximum_unary_minus_right_tree(s1: &S, s2: &S) -> i32 { // There's no `s2.c` -(-(-s1.a * -s2.a) + (-(-s1.b * -s2.b) + -(-s1.c * -s2.b) + -(-s1.d * -s2.d))) + //~^ suspicious_operation_groupings } fn unary_minus_and_an_if_expression(s1: &S, s2: &S) -> i32 { // There's no `s1.b` -(if -s1.a < -s2.a && -s1.a < -s2.b { s1.c } else { s2.a }) + //~^ suspicious_operation_groupings } fn main() {} diff --git a/tests/ui/suspicious_operation_groupings.stderr b/tests/ui/suspicious_operation_groupings.stderr index 7cb066d57e75..b640b2041cd3 100644 --- a/tests/ui/suspicious_operation_groupings.stderr +++ b/tests/ui/suspicious_operation_groupings.stderr @@ -8,151 +8,151 @@ LL | self.x == other.y && self.y == other.y && self.z == other.z = help: to override `-D warnings` add `#[allow(clippy::suspicious_operation_groupings)]` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:30:20 + --> tests/ui/suspicious_operation_groupings.rs:31:20 | LL | s1.a < s2.a && s1.a < s2.b | ^^^^^^^^^^^ help: did you mean: `s1.b < s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:78:33 + --> tests/ui/suspicious_operation_groupings.rs:80:33 | LL | s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:83:19 + --> tests/ui/suspicious_operation_groupings.rs:86:19 | LL | s1.a * s2.a + s1.b * s2.c + s1.c * s2.c | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:83:19 + --> tests/ui/suspicious_operation_groupings.rs:86:19 | LL | s1.a * s2.a + s1.b * s2.c + s1.c * s2.c | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` -error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:88:19 - | -LL | s1.a * s2.a + s2.b * s2.b + s1.c * s2.c - | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` - error: this sequence of operators looks suspiciously like a bug --> tests/ui/suspicious_operation_groupings.rs:93:19 | +LL | s1.a * s2.a + s2.b * s2.b + s1.c * s2.c + | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` + +error: this sequence of operators looks suspiciously like a bug + --> tests/ui/suspicious_operation_groupings.rs:99:19 + | LL | s1.a * s2.a + s1.b * s1.b + s1.c * s2.c | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:98:5 + --> tests/ui/suspicious_operation_groupings.rs:105:5 | LL | s1.a * s1.a + s1.b * s2.b + s1.c * s2.c | ^^^^^^^^^^^ help: did you mean: `s1.a * s2.a` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:103:33 + --> tests/ui/suspicious_operation_groupings.rs:111:33 | LL | s1.a * s2.a + s1.b * s2.b + s1.c * s1.c | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:116:20 + --> tests/ui/suspicious_operation_groupings.rs:125:20 | LL | (s1.a * s2.a + s1.b * s1.b) | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:121:34 + --> tests/ui/suspicious_operation_groupings.rs:131:34 | LL | (s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:126:38 + --> tests/ui/suspicious_operation_groupings.rs:137:38 | LL | (s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:131:39 + --> tests/ui/suspicious_operation_groupings.rs:143:39 | LL | ((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d)) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:136:42 + --> tests/ui/suspicious_operation_groupings.rs:149:42 | LL | (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d))) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:136:42 + --> tests/ui/suspicious_operation_groupings.rs:149:42 | LL | (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d))) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:141:40 + --> tests/ui/suspicious_operation_groupings.rs:156:40 | LL | (((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b)) + (s1.d * s2.d)) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:146:40 + --> tests/ui/suspicious_operation_groupings.rs:162:40 | LL | ((s1.a * s2.a) + ((s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d))) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:151:20 + --> tests/ui/suspicious_operation_groupings.rs:168:20 | LL | (s1.a * s2.a + s2.b * s2.b) / 2 | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:156:35 + --> tests/ui/suspicious_operation_groupings.rs:174:35 | LL | i32::swap_bytes(s1.a * s2.a + s2.b * s2.b) | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:161:29 + --> tests/ui/suspicious_operation_groupings.rs:180:29 | LL | s1.a > 0 && s1.b > 0 && s1.d == s2.c && s1.d == s2.d | ^^^^^^^^^^^^ help: did you mean: `s1.c == s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:166:17 + --> tests/ui/suspicious_operation_groupings.rs:186:17 | LL | s1.a > 0 && s1.d == s2.c && s1.b > 0 && s1.d == s2.d | ^^^^^^^^^^^^ help: did you mean: `s1.c == s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:175:77 + --> tests/ui/suspicious_operation_groupings.rs:196:77 | LL | (n1.inner.0).0 == (n2.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.1).0 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `(n1.inner.2).0 == (n2.inner.2).0` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:189:25 + --> tests/ui/suspicious_operation_groupings.rs:211:25 | LL | s1.a <= s2.a && s1.a <= s2.b | ^^^^^^^^^^^^ help: did you mean: `s1.b <= s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:195:23 + --> tests/ui/suspicious_operation_groupings.rs:218:23 | LL | if s1.a < s2.a && s1.a < s2.b { | ^^^^^^^^^^^ help: did you mean: `s1.b < s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:202:48 + --> tests/ui/suspicious_operation_groupings.rs:226:48 | LL | -(-(-s1.a * -s2.a) + (-(-s1.b * -s2.b) + -(-s1.c * -s2.b) + -(-s1.d * -s2.d))) | ^^^^^^^^^^^^^ help: did you mean: `-s1.c * -s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:207:27 + --> tests/ui/suspicious_operation_groupings.rs:232:27 | LL | -(if -s1.a < -s2.a && -s1.a < -s2.b { s1.c } else { s2.a }) | ^^^^^^^^^^^^^ help: did you mean: `-s1.b < -s2.b` diff --git a/tests/ui/suspicious_splitn.rs b/tests/ui/suspicious_splitn.rs index 7aa609706220..535f62c6bede 100644 --- a/tests/ui/suspicious_splitn.rs +++ b/tests/ui/suspicious_splitn.rs @@ -8,32 +8,30 @@ fn main() { let _ = [].splitn(0, |&x: &u32| x == 1); let _ = "a,b".splitn(0, ','); - //~^ ERROR: `splitn` called with `0` splits - //~| NOTE: the resulting iterator will always return `None` + //~^ suspicious_splitn + let _ = "a,b".rsplitn(0, ','); - //~^ ERROR: `rsplitn` called with `0` splits - //~| NOTE: the resulting iterator will always return `None` + //~^ suspicious_splitn + let _ = "a,b".splitn(1, ','); - //~^ ERROR: `splitn` called with `1` split - //~| NOTE: the resulting iterator will always return the entire string followed by `No + //~^ suspicious_splitn + let _ = [0, 1, 2].splitn(0, |&x| x == 1); - //~^ ERROR: `splitn` called with `0` splits - //~| NOTE: the resulting iterator will always return `None` + //~^ suspicious_splitn + let _ = [0, 1, 2].splitn_mut(0, |&x| x == 1); - //~^ ERROR: `splitn_mut` called with `0` splits - //~| NOTE: the resulting iterator will always return `None` + //~^ suspicious_splitn + let _ = [0, 1, 2].splitn(1, |&x| x == 1); - //~^ ERROR: `splitn` called with `1` split - //~| NOTE: the resulting iterator will always return the entire slice followed by `Non + //~^ suspicious_splitn + let _ = [0, 1, 2].rsplitn_mut(1, |&x| x == 1); - //~^ ERROR: `rsplitn_mut` called with `1` split - //~| NOTE: the resulting iterator will always return the entire slice followed by `Non + //~^ suspicious_splitn const X: usize = 0; let _ = "a,b".splitn(X + 1, ','); - //~^ ERROR: `splitn` called with `1` split - //~| NOTE: the resulting iterator will always return the entire string followed by `No + //~^ suspicious_splitn + let _ = "a,b".splitn(X, ','); - //~^ ERROR: `splitn` called with `0` splits - //~| NOTE: the resulting iterator will always return `None` + //~^ suspicious_splitn } diff --git a/tests/ui/suspicious_splitn.stderr b/tests/ui/suspicious_splitn.stderr index 6e05bc28d130..910c905bc990 100644 --- a/tests/ui/suspicious_splitn.stderr +++ b/tests/ui/suspicious_splitn.stderr @@ -57,7 +57,7 @@ LL | let _ = [0, 1, 2].rsplitn_mut(1, |&x| x == 1); = note: the resulting iterator will always return the entire slice followed by `None` error: `splitn` called with `1` split - --> tests/ui/suspicious_splitn.rs:33:13 + --> tests/ui/suspicious_splitn.rs:32:13 | LL | let _ = "a,b".splitn(X + 1, ','); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | let _ = "a,b".splitn(X + 1, ','); = note: the resulting iterator will always return the entire string followed by `None` error: `splitn` called with `0` splits - --> tests/ui/suspicious_splitn.rs:36:13 + --> tests/ui/suspicious_splitn.rs:35:13 | LL | let _ = "a,b".splitn(X, ','); | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/suspicious_to_owned.rs b/tests/ui/suspicious_to_owned.rs index 794c2e7174af..2eec05ccaf4c 100644 --- a/tests/ui/suspicious_to_owned.rs +++ b/tests/ui/suspicious_to_owned.rs @@ -15,8 +15,8 @@ fn main() { // we expect this to be linted let cow = Cow::Borrowed(moo); let _ = cow.to_owned(); - //~^ ERROR: this `to_owned` call clones the Cow<'_, str> itself and does not cause the - //~| NOTE: `-D clippy::suspicious-to-owned` implied by `-D warnings` + //~^ suspicious_to_owned + // we expect no lints for this let cow = Cow::Borrowed(moo); let _ = cow.into_owned(); @@ -27,7 +27,8 @@ fn main() { // we expect this to be linted let cow = Cow::Borrowed(&moos); let _ = cow.to_owned(); - //~^ ERROR: this `to_owned` call clones the Cow<'_, [char; 3]> itself and does not cau + //~^ suspicious_to_owned + // we expect no lints for this let cow = Cow::Borrowed(&moos); let _ = cow.into_owned(); @@ -38,7 +39,8 @@ fn main() { // we expect this to be linted let cow = Cow::Borrowed(&moos_vec); let _ = cow.to_owned(); - //~^ ERROR: this `to_owned` call clones the Cow<'_, Vec> itself and does not cau + //~^ suspicious_to_owned + // we expect no lints for this let cow = Cow::Borrowed(&moos_vec); let _ = cow.into_owned(); @@ -49,7 +51,8 @@ fn main() { // we expect this to be linted let cow = unsafe { CStr::from_ptr(c_moo_ptr) }.to_string_lossy(); let _ = cow.to_owned(); - //~^ ERROR: this `to_owned` call clones the Cow<'_, str> itself and does not cause the + //~^ suspicious_to_owned + // we expect no lints for this let cow = unsafe { CStr::from_ptr(c_moo_ptr) }.to_string_lossy(); let _ = cow.into_owned(); @@ -64,8 +67,8 @@ fn main() { // we expect implicit_clone lints for these let _ = String::from(moo).to_owned(); - //~^ ERROR: implicitly cloning a `String` by calling `to_owned` on its dereferenced ty - //~| NOTE: `-D clippy::implicit-clone` implied by `-D warnings` + //~^ implicit_clone + let _ = moos_vec.to_owned(); - //~^ ERROR: implicitly cloning a `Vec` by calling `to_owned` on its dereferenced type + //~^ implicit_clone } diff --git a/tests/ui/suspicious_to_owned.stderr b/tests/ui/suspicious_to_owned.stderr index 2c26565d5ef1..f90bea5fb8ff 100644 --- a/tests/ui/suspicious_to_owned.stderr +++ b/tests/ui/suspicious_to_owned.stderr @@ -33,7 +33,7 @@ LL + let _ = cow.clone(); | error: this `to_owned` call clones the Cow<'_, Vec> itself and does not cause the Cow<'_, Vec> contents to become owned - --> tests/ui/suspicious_to_owned.rs:40:13 + --> tests/ui/suspicious_to_owned.rs:41:13 | LL | let _ = cow.to_owned(); | ^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + let _ = cow.clone(); | error: this `to_owned` call clones the Cow<'_, str> itself and does not cause the Cow<'_, str> contents to become owned - --> tests/ui/suspicious_to_owned.rs:51:13 + --> tests/ui/suspicious_to_owned.rs:53:13 | LL | let _ = cow.to_owned(); | ^^^^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL + let _ = cow.clone(); | error: implicitly cloning a `String` by calling `to_owned` on its dereferenced type - --> tests/ui/suspicious_to_owned.rs:66:13 + --> tests/ui/suspicious_to_owned.rs:69:13 | LL | let _ = String::from(moo).to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `String::from(moo).clone()` @@ -74,7 +74,7 @@ LL | let _ = String::from(moo).to_owned(); = help: to override `-D warnings` add `#[allow(clippy::implicit_clone)]` error: implicitly cloning a `Vec` by calling `to_owned` on its dereferenced type - --> tests/ui/suspicious_to_owned.rs:69:13 + --> tests/ui/suspicious_to_owned.rs:72:13 | LL | let _ = moos_vec.to_owned(); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `moos_vec.clone()` diff --git a/tests/ui/suspicious_unary_op_formatting.rs b/tests/ui/suspicious_unary_op_formatting.rs index a7a62154ee0f..ab9bdde6cf90 100644 --- a/tests/ui/suspicious_unary_op_formatting.rs +++ b/tests/ui/suspicious_unary_op_formatting.rs @@ -7,18 +7,22 @@ fn main() { let a = 42; if a >- 30 {} - //~^ ERROR: by not having a space between `>` and `-` it looks like `>-` is a single o + //~^ suspicious_unary_op_formatting + if a >=- 30 {} - //~^ ERROR: by not having a space between `>=` and `-` it looks like `>=-` is a single + //~^ suspicious_unary_op_formatting + let b = true; let c = false; if b &&! c {} - //~^ ERROR: by not having a space between `&&` and `!` it looks like `&&!` is a single + //~^ suspicious_unary_op_formatting + if a >- 30 {} - //~^ ERROR: by not having a space between `>` and `-` it looks like `>-` is a single o + //~^ suspicious_unary_op_formatting + // those are ok: if a >-30 {} diff --git a/tests/ui/suspicious_unary_op_formatting.stderr b/tests/ui/suspicious_unary_op_formatting.stderr index 379fb17266a9..5fe18aa82435 100644 --- a/tests/ui/suspicious_unary_op_formatting.stderr +++ b/tests/ui/suspicious_unary_op_formatting.stderr @@ -9,7 +9,7 @@ LL | if a >- 30 {} = help: to override `-D warnings` add `#[allow(clippy::suspicious_unary_op_formatting)]` error: by not having a space between `>=` and `-` it looks like `>=-` is a single operator - --> tests/ui/suspicious_unary_op_formatting.rs:11:9 + --> tests/ui/suspicious_unary_op_formatting.rs:12:9 | LL | if a >=- 30 {} | ^^^^^ @@ -17,7 +17,7 @@ LL | if a >=- 30 {} = help: put a space between `>=` and `-` and remove the space after `-` error: by not having a space between `&&` and `!` it looks like `&&!` is a single operator - --> tests/ui/suspicious_unary_op_formatting.rs:17:9 + --> tests/ui/suspicious_unary_op_formatting.rs:19:9 | LL | if b &&! c {} | ^^^^^ @@ -25,7 +25,7 @@ LL | if b &&! c {} = help: put a space between `&&` and `!` and remove the space after `!` error: by not having a space between `>` and `-` it looks like `>-` is a single operator - --> tests/ui/suspicious_unary_op_formatting.rs:20:9 + --> tests/ui/suspicious_unary_op_formatting.rs:23:9 | LL | if a >- 30 {} | ^^^^^^ diff --git a/tests/ui/suspicious_xor_used_as_pow.rs b/tests/ui/suspicious_xor_used_as_pow.rs index a5319e1b2308..40a8d8c366ba 100644 --- a/tests/ui/suspicious_xor_used_as_pow.rs +++ b/tests/ui/suspicious_xor_used_as_pow.rs @@ -11,24 +11,31 @@ macro_rules! macro_test { macro_rules! macro_test_inside { () => { 1 ^ 2 // should warn even if inside macro + // + //~^^ suspicious_xor_used_as_pow }; } fn main() { // Should warn: let _ = 2 ^ 5; - //~^ ERROR: `^` is not the exponentiation operator - //~| NOTE: `-D clippy::suspicious-xor-used-as-pow` implied by `-D warnings` + //~^ suspicious_xor_used_as_pow + let _ = 2i32 ^ 9i32; - //~^ ERROR: `^` is not the exponentiation operator + //~^ suspicious_xor_used_as_pow + let _ = 2i32 ^ 2i32; - //~^ ERROR: `^` is not the exponentiation operator + //~^ suspicious_xor_used_as_pow + let _ = 50i32 ^ 3i32; - //~^ ERROR: `^` is not the exponentiation operator + //~^ suspicious_xor_used_as_pow + let _ = 5i32 ^ 8i32; - //~^ ERROR: `^` is not the exponentiation operator + //~^ suspicious_xor_used_as_pow + let _ = 2i32 ^ 32i32; - //~^ ERROR: `^` is not the exponentiation operator + //~^ suspicious_xor_used_as_pow + macro_test_inside!(); // Should not warn: diff --git a/tests/ui/suspicious_xor_used_as_pow.stderr b/tests/ui/suspicious_xor_used_as_pow.stderr index 2a153169bd34..efeafdb94acb 100644 --- a/tests/ui/suspicious_xor_used_as_pow.stderr +++ b/tests/ui/suspicious_xor_used_as_pow.stderr @@ -1,5 +1,5 @@ error: `^` is not the exponentiation operator - --> tests/ui/suspicious_xor_used_as_pow.rs:19:13 + --> tests/ui/suspicious_xor_used_as_pow.rs:21:13 | LL | let _ = 2 ^ 5; | ^^^^^ @@ -13,7 +13,7 @@ LL + let _ = 2.pow(5); | error: `^` is not the exponentiation operator - --> tests/ui/suspicious_xor_used_as_pow.rs:22:13 + --> tests/ui/suspicious_xor_used_as_pow.rs:24:13 | LL | let _ = 2i32 ^ 9i32; | ^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + let _ = 2i32.pow(9i32); | error: `^` is not the exponentiation operator - --> tests/ui/suspicious_xor_used_as_pow.rs:24:13 + --> tests/ui/suspicious_xor_used_as_pow.rs:27:13 | LL | let _ = 2i32 ^ 2i32; | ^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + let _ = 2i32.pow(2i32); | error: `^` is not the exponentiation operator - --> tests/ui/suspicious_xor_used_as_pow.rs:26:13 + --> tests/ui/suspicious_xor_used_as_pow.rs:30:13 | LL | let _ = 50i32 ^ 3i32; | ^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + let _ = 50i32.pow(3i32); | error: `^` is not the exponentiation operator - --> tests/ui/suspicious_xor_used_as_pow.rs:28:13 + --> tests/ui/suspicious_xor_used_as_pow.rs:33:13 | LL | let _ = 5i32 ^ 8i32; | ^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + let _ = 5i32.pow(8i32); | error: `^` is not the exponentiation operator - --> tests/ui/suspicious_xor_used_as_pow.rs:30:13 + --> tests/ui/suspicious_xor_used_as_pow.rs:36:13 | LL | let _ = 2i32 ^ 32i32; | ^^^^^^^^^^^^ diff --git a/tests/ui/swap.rs b/tests/ui/swap.rs index c9ad77629290..51af55ecd27c 100644 --- a/tests/ui/swap.rs +++ b/tests/ui/swap.rs @@ -26,6 +26,7 @@ fn field() { let mut bar = Bar { a: 1, b: 2 }; let temp = bar.a; + //~^ manual_swap bar.a = bar.b; bar.b = temp; @@ -38,6 +39,7 @@ fn field() { fn array() { let mut foo = [1, 2]; let temp = foo[0]; + //~^ manual_swap foo[0] = foo[1]; foo[1] = temp; @@ -47,6 +49,7 @@ fn array() { fn slice() { let foo = &mut [1, 2]; let temp = foo[0]; + //~^ manual_swap foo[0] = foo[1]; foo[1] = temp; @@ -66,6 +69,7 @@ fn unswappable_slice() { fn vec() { let mut foo = vec![1, 2]; let temp = foo[0]; + //~^ manual_swap foo[0] = foo[1]; foo[1] = temp; @@ -77,6 +81,7 @@ fn xor_swap_locals() { let mut a = 0; let mut b = 1; a ^= b; + //~^ manual_swap b ^= a; a ^= b; } @@ -85,6 +90,7 @@ fn xor_field_swap() { // This is an xor-based swap of fields in a struct. let mut bar = Bar { a: 0, b: 1 }; bar.a ^= bar.b; + //~^ manual_swap bar.b ^= bar.a; bar.a ^= bar.b; } @@ -93,6 +99,7 @@ fn xor_slice_swap() { // This is an xor-based swap of a slice let foo = &mut [1, 2]; foo[0] ^= foo[1]; + //~^ manual_swap foo[1] ^= foo[0]; foo[0] ^= foo[1]; } @@ -122,6 +129,7 @@ fn distinct_slice() { let foo = &mut [vec![1, 2], vec![3, 4]]; let bar = &mut [vec![1, 2], vec![3, 4]]; let temp = foo[0][1]; + //~^ manual_swap foo[0][1] = bar[1][0]; bar[1][0] = temp; } @@ -133,31 +141,38 @@ fn main() { let mut b = 1337; a = b; + //~^ almost_swapped b = a; ; let t = a; + //~^ manual_swap a = b; b = t; let mut c = Foo(42); c.0 = a; + //~^ almost_swapped a = c.0; ; let t = c.0; + //~^ manual_swap c.0 = a; a = t; let a = b; + //~^ almost_swapped let b = a; let mut c = 1; let mut d = 2; d = c; + //~^ almost_swapped c = d; let mut b = 1; let a = b; + //~^ almost_swapped b = a; let b = 1; @@ -171,6 +186,7 @@ fn main() { let mut a = 2; let t = b; + //~^ manual_swap b = a; a = t; } @@ -206,6 +222,7 @@ fn issue_8154() { let mut s = &mut s; let s = S3(&mut s); let t = s.0.x; + //~^ manual_swap s.0.x = s.0.y; s.0.y = t; } diff --git a/tests/ui/swap.stderr b/tests/ui/swap.stderr index fad356782479..15f7566d5896 100644 --- a/tests/ui/swap.stderr +++ b/tests/ui/swap.stderr @@ -2,6 +2,7 @@ error: this looks like you are swapping `bar.a` and `bar.b` manually --> tests/ui/swap.rs:28:5 | LL | / let temp = bar.a; +LL | | LL | | bar.a = bar.b; LL | | bar.b = temp; | |_________________^ help: try: `std::mem::swap(&mut bar.a, &mut bar.b);` @@ -11,57 +12,64 @@ LL | | bar.b = temp; = help: to override `-D warnings` add `#[allow(clippy::manual_swap)]` error: this looks like you are swapping elements of `foo` manually - --> tests/ui/swap.rs:40:5 + --> tests/ui/swap.rs:41:5 | LL | / let temp = foo[0]; +LL | | LL | | foo[0] = foo[1]; LL | | foo[1] = temp; | |__________________^ help: try: `foo.swap(0, 1);` error: this looks like you are swapping elements of `foo` manually - --> tests/ui/swap.rs:49:5 + --> tests/ui/swap.rs:51:5 | LL | / let temp = foo[0]; +LL | | LL | | foo[0] = foo[1]; LL | | foo[1] = temp; | |__________________^ help: try: `foo.swap(0, 1);` error: this looks like you are swapping elements of `foo` manually - --> tests/ui/swap.rs:68:5 + --> tests/ui/swap.rs:71:5 | LL | / let temp = foo[0]; +LL | | LL | | foo[0] = foo[1]; LL | | foo[1] = temp; | |__________________^ help: try: `foo.swap(0, 1);` error: this looks like you are swapping `a` and `b` manually - --> tests/ui/swap.rs:79:5 + --> tests/ui/swap.rs:83:5 | LL | / a ^= b; +LL | | LL | | b ^= a; LL | | a ^= b; | |___________^ help: try: `std::mem::swap(&mut a, &mut b);` error: this looks like you are swapping `bar.a` and `bar.b` manually - --> tests/ui/swap.rs:87:5 + --> tests/ui/swap.rs:92:5 | LL | / bar.a ^= bar.b; +LL | | LL | | bar.b ^= bar.a; LL | | bar.a ^= bar.b; | |___________________^ help: try: `std::mem::swap(&mut bar.a, &mut bar.b);` error: this looks like you are swapping elements of `foo` manually - --> tests/ui/swap.rs:95:5 + --> tests/ui/swap.rs:101:5 | LL | / foo[0] ^= foo[1]; +LL | | LL | | foo[1] ^= foo[0]; LL | | foo[0] ^= foo[1]; | |_____________________^ help: try: `foo.swap(0, 1);` error: this looks like you are swapping `foo[0][1]` and `bar[1][0]` manually - --> tests/ui/swap.rs:124:5 + --> tests/ui/swap.rs:131:5 | LL | / let temp = foo[0][1]; +LL | | LL | | foo[0][1] = bar[1][0]; LL | | bar[1][0] = temp; | |_____________________^ help: try: `std::mem::swap(&mut foo[0][1], &mut bar[1][0]);` @@ -69,10 +77,11 @@ LL | | bar[1][0] = temp; = note: or maybe you should use `std::mem::replace`? error: this looks like you are swapping `a` and `b` manually - --> tests/ui/swap.rs:138:7 + --> tests/ui/swap.rs:147:7 | LL | ; let t = a; | _______^ +LL | | LL | | a = b; LL | | b = t; | |__________^ help: try: `std::mem::swap(&mut a, &mut b);` @@ -80,10 +89,11 @@ LL | | b = t; = note: or maybe you should use `std::mem::replace`? error: this looks like you are swapping `c.0` and `a` manually - --> tests/ui/swap.rs:147:7 + --> tests/ui/swap.rs:158:7 | LL | ; let t = c.0; | _______^ +LL | | LL | | c.0 = a; LL | | a = t; | |__________^ help: try: `std::mem::swap(&mut c.0, &mut a);` @@ -91,9 +101,10 @@ LL | | a = t; = note: or maybe you should use `std::mem::replace`? error: this looks like you are swapping `b` and `a` manually - --> tests/ui/swap.rs:173:5 + --> tests/ui/swap.rs:188:5 | LL | / let t = b; +LL | | LL | | b = a; LL | | a = t; | |__________^ help: try: `std::mem::swap(&mut b, &mut a);` @@ -101,9 +112,10 @@ LL | | a = t; = note: or maybe you should use `std::mem::replace`? error: this looks like you are trying to swap `a` and `b` - --> tests/ui/swap.rs:135:5 + --> tests/ui/swap.rs:143:5 | LL | / a = b; +LL | | LL | | b = a; | |_________^ help: try: `std::mem::swap(&mut a, &mut b)` | @@ -112,45 +124,50 @@ LL | | b = a; = help: to override `-D warnings` add `#[allow(clippy::almost_swapped)]` error: this looks like you are trying to swap `c.0` and `a` - --> tests/ui/swap.rs:144:5 + --> tests/ui/swap.rs:154:5 | LL | / c.0 = a; +LL | | LL | | a = c.0; | |___________^ help: try: `std::mem::swap(&mut c.0, &mut a)` | = note: or maybe you should use `std::mem::replace`? error: this looks like you are trying to swap `a` and `b` - --> tests/ui/swap.rs:151:5 + --> tests/ui/swap.rs:163:5 | LL | / let a = b; +LL | | LL | | let b = a; | |_____________^ help: try: `std::mem::swap(&mut a, &mut b)` | = note: or maybe you should use `std::mem::replace`? error: this looks like you are trying to swap `d` and `c` - --> tests/ui/swap.rs:156:5 + --> tests/ui/swap.rs:169:5 | LL | / d = c; +LL | | LL | | c = d; | |_________^ help: try: `std::mem::swap(&mut d, &mut c)` | = note: or maybe you should use `std::mem::replace`? error: this looks like you are trying to swap `a` and `b` - --> tests/ui/swap.rs:160:5 + --> tests/ui/swap.rs:174:5 | LL | / let a = b; +LL | | LL | | b = a; | |_________^ help: try: `std::mem::swap(&mut a, &mut b)` | = note: or maybe you should use `std::mem::replace`? error: this looks like you are swapping `s.0.x` and `s.0.y` manually - --> tests/ui/swap.rs:208:5 + --> tests/ui/swap.rs:224:5 | LL | / let t = s.0.x; +LL | | LL | | s.0.x = s.0.y; LL | | s.0.y = t; | |______________^ help: try: `std::mem::swap(&mut s.0.x, &mut s.0.y);` diff --git a/tests/ui/swap_ptr_to_ref.fixed b/tests/ui/swap_ptr_to_ref.fixed index 599bb0e80443..ec46368a95ae 100644 --- a/tests/ui/swap_ptr_to_ref.fixed +++ b/tests/ui/swap_ptr_to_ref.fixed @@ -9,9 +9,13 @@ fn main() { unsafe { core::ptr::swap(y, z); + //~^ swap_ptr_to_ref core::ptr::swap(y, &mut x); + //~^ swap_ptr_to_ref core::ptr::swap(&mut x, y); + //~^ swap_ptr_to_ref core::ptr::swap(addr_of_mut!(x), addr_of_mut!(x)); + //~^ swap_ptr_to_ref } let y = &mut x; diff --git a/tests/ui/swap_ptr_to_ref.rs b/tests/ui/swap_ptr_to_ref.rs index 3a8a8daefddc..6a903ddb006d 100644 --- a/tests/ui/swap_ptr_to_ref.rs +++ b/tests/ui/swap_ptr_to_ref.rs @@ -9,9 +9,13 @@ fn main() { unsafe { core::mem::swap(&mut *y, &mut *z); + //~^ swap_ptr_to_ref core::mem::swap(&mut *y, &mut x); + //~^ swap_ptr_to_ref core::mem::swap(&mut x, &mut *y); + //~^ swap_ptr_to_ref core::mem::swap(&mut *addr_of_mut!(x), &mut *addr_of_mut!(x)); + //~^ swap_ptr_to_ref } let y = &mut x; diff --git a/tests/ui/swap_ptr_to_ref.stderr b/tests/ui/swap_ptr_to_ref.stderr index 019c2f91f0e9..6b851901f82e 100644 --- a/tests/ui/swap_ptr_to_ref.stderr +++ b/tests/ui/swap_ptr_to_ref.stderr @@ -8,19 +8,19 @@ LL | core::mem::swap(&mut *y, &mut *z); = help: to override `-D warnings` add `#[allow(clippy::swap_ptr_to_ref)]` error: call to `core::mem::swap` with a parameter derived from a raw pointer - --> tests/ui/swap_ptr_to_ref.rs:12:9 + --> tests/ui/swap_ptr_to_ref.rs:13:9 | LL | core::mem::swap(&mut *y, &mut x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use ptr::swap: `core::ptr::swap(y, &mut x)` error: call to `core::mem::swap` with a parameter derived from a raw pointer - --> tests/ui/swap_ptr_to_ref.rs:13:9 + --> tests/ui/swap_ptr_to_ref.rs:15:9 | LL | core::mem::swap(&mut x, &mut *y); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use ptr::swap: `core::ptr::swap(&mut x, y)` error: call to `core::mem::swap` with a parameter derived from a raw pointer - --> tests/ui/swap_ptr_to_ref.rs:14:9 + --> tests/ui/swap_ptr_to_ref.rs:17:9 | LL | core::mem::swap(&mut *addr_of_mut!(x), &mut *addr_of_mut!(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use ptr::swap: `core::ptr::swap(addr_of_mut!(x), addr_of_mut!(x))` diff --git a/tests/ui/swap_ptr_to_ref_unfixable.rs b/tests/ui/swap_ptr_to_ref_unfixable.rs index 08e56a5d01b2..9c7cf27096cc 100644 --- a/tests/ui/swap_ptr_to_ref_unfixable.rs +++ b/tests/ui/swap_ptr_to_ref_unfixable.rs @@ -12,11 +12,12 @@ fn main() { unsafe { core::mem::swap(addr_of_mut_to_ref!(x), &mut *y); - //~^ ERROR: call to `core::mem::swap` with a parameter derived from a raw pointer - //~| NOTE: `-D clippy::swap-ptr-to-ref` implied by `-D warnings` + //~^ swap_ptr_to_ref + core::mem::swap(&mut *y, addr_of_mut_to_ref!(x)); - //~^ ERROR: call to `core::mem::swap` with a parameter derived from a raw pointer + //~^ swap_ptr_to_ref + core::mem::swap(addr_of_mut_to_ref!(x), addr_of_mut_to_ref!(x)); - //~^ ERROR: call to `core::mem::swap` with a parameter derived from a raw pointer + //~^ swap_ptr_to_ref } } diff --git a/tests/ui/swap_ptr_to_ref_unfixable.stderr b/tests/ui/swap_ptr_to_ref_unfixable.stderr index 8a0352049483..3bb9d87b70a5 100644 --- a/tests/ui/swap_ptr_to_ref_unfixable.stderr +++ b/tests/ui/swap_ptr_to_ref_unfixable.stderr @@ -14,7 +14,7 @@ LL | core::mem::swap(&mut *y, addr_of_mut_to_ref!(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: call to `core::mem::swap` with a parameter derived from a raw pointer - --> tests/ui/swap_ptr_to_ref_unfixable.rs:19:9 + --> tests/ui/swap_ptr_to_ref_unfixable.rs:20:9 | LL | core::mem::swap(addr_of_mut_to_ref!(x), addr_of_mut_to_ref!(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/syntax-error-recovery/non_expressive_names_error_recovery.fixed b/tests/ui/syntax-error-recovery/non_expressive_names_error_recovery.fixed new file mode 100644 index 000000000000..c96a53ba2cd1 --- /dev/null +++ b/tests/ui/syntax-error-recovery/non_expressive_names_error_recovery.fixed @@ -0,0 +1,9 @@ +// https://github.com/rust-lang/rust-clippy/issues/12302 +use std::marker::PhantomData; + +pub struct Aa(PhantomData); + +fn aa(a: Aa) { +//~^ ERROR: expected one of + +} diff --git a/tests/ui/syntax-error-recovery/non_expressive_names_error_recovery.rs b/tests/ui/syntax-error-recovery/non_expressive_names_error_recovery.rs new file mode 100644 index 000000000000..a3a35eb26d10 --- /dev/null +++ b/tests/ui/syntax-error-recovery/non_expressive_names_error_recovery.rs @@ -0,0 +1,9 @@ +// https://github.com/rust-lang/rust-clippy/issues/12302 +use std::marker::PhantomData; + +pub struct Aa(PhantomData); + +fn aa(a: Aa`, found `)` + --> tests/ui/syntax-error-recovery/non_expressive_names_error_recovery.rs:6:19 + | +LL | fn aa(a: Aa) { + | + + +error: aborting due to 1 previous error + diff --git a/tests/ui/tabs_in_doc_comments.fixed b/tests/ui/tabs_in_doc_comments.fixed index 3536c1746df3..ed96cbaa6d3c 100644 --- a/tests/ui/tabs_in_doc_comments.fixed +++ b/tests/ui/tabs_in_doc_comments.fixed @@ -3,15 +3,23 @@ /// /// Struct to hold two strings: /// - first one +//~^ tabs_in_doc_comments +//~| tabs_in_doc_comments /// - second one +//~^ tabs_in_doc_comments +//~| tabs_in_doc_comments pub struct DoubleString { /// /// - First String: + //~^ tabs_in_doc_comments /// - needs to be inside here + //~^ tabs_in_doc_comments first_string: String, /// /// - Second String: + //~^ tabs_in_doc_comments /// - needs to be inside here + //~^ tabs_in_doc_comments second_string: String, } diff --git a/tests/ui/tabs_in_doc_comments.rs b/tests/ui/tabs_in_doc_comments.rs index 033a685066e1..73d4d92a862e 100644 --- a/tests/ui/tabs_in_doc_comments.rs +++ b/tests/ui/tabs_in_doc_comments.rs @@ -3,15 +3,23 @@ /// /// Struct to hold two strings: /// - first one +//~^ tabs_in_doc_comments +//~| tabs_in_doc_comments /// - second one +//~^ tabs_in_doc_comments +//~| tabs_in_doc_comments pub struct DoubleString { /// /// - First String: + //~^ tabs_in_doc_comments /// - needs to be inside here + //~^ tabs_in_doc_comments first_string: String, /// /// - Second String: + //~^ tabs_in_doc_comments /// - needs to be inside here + //~^ tabs_in_doc_comments second_string: String, } diff --git a/tests/ui/tabs_in_doc_comments.stderr b/tests/ui/tabs_in_doc_comments.stderr index f8d30b728e58..331bccaca92d 100644 --- a/tests/ui/tabs_in_doc_comments.stderr +++ b/tests/ui/tabs_in_doc_comments.stderr @@ -14,37 +14,37 @@ LL | /// - first one | ^^^^^^^^ help: consider using four spaces per tab error: using tabs in doc comments is not recommended - --> tests/ui/tabs_in_doc_comments.rs:6:5 + --> tests/ui/tabs_in_doc_comments.rs:8:5 | LL | /// - second one | ^^^^ help: consider using four spaces per tab error: using tabs in doc comments is not recommended - --> tests/ui/tabs_in_doc_comments.rs:6:14 + --> tests/ui/tabs_in_doc_comments.rs:8:14 | LL | /// - second one | ^^^^ help: consider using four spaces per tab error: using tabs in doc comments is not recommended - --> tests/ui/tabs_in_doc_comments.rs:9:9 + --> tests/ui/tabs_in_doc_comments.rs:13:9 | LL | /// - First String: | ^^^^ help: consider using four spaces per tab error: using tabs in doc comments is not recommended - --> tests/ui/tabs_in_doc_comments.rs:10:9 + --> tests/ui/tabs_in_doc_comments.rs:15:9 | LL | /// - needs to be inside here | ^^^^^^^^ help: consider using four spaces per tab error: using tabs in doc comments is not recommended - --> tests/ui/tabs_in_doc_comments.rs:13:9 + --> tests/ui/tabs_in_doc_comments.rs:19:9 | LL | /// - Second String: | ^^^^ help: consider using four spaces per tab error: using tabs in doc comments is not recommended - --> tests/ui/tabs_in_doc_comments.rs:14:9 + --> tests/ui/tabs_in_doc_comments.rs:21:9 | LL | /// - needs to be inside here | ^^^^^^^^ help: consider using four spaces per tab diff --git a/tests/ui/temporary_assignment.rs b/tests/ui/temporary_assignment.rs index d269f91b9fa8..ac9ed5d05f8f 100644 --- a/tests/ui/temporary_assignment.rs +++ b/tests/ui/temporary_assignment.rs @@ -46,18 +46,19 @@ fn main() { let mut t = (0, 0); Struct { field: 0 }.field = 1; - //~^ ERROR: assignment to temporary - //~| NOTE: `-D clippy::temporary-assignment` implied by `-D warnings` + //~^ temporary_assignment + MultiStruct { - //~^ ERROR: assignment to temporary + //~^ temporary_assignment structure: Struct { field: 0 }, } .structure .field = 1; ArrayStruct { array: [0] }.array[0] = 1; - //~^ ERROR: assignment to temporary + //~^ temporary_assignment + (0, 0).0 = 1; - //~^ ERROR: assignment to temporary + //~^ temporary_assignment // no error s.field = 1; diff --git a/tests/ui/temporary_assignment.stderr b/tests/ui/temporary_assignment.stderr index 7e6529cb2134..5f6a54003630 100644 --- a/tests/ui/temporary_assignment.stderr +++ b/tests/ui/temporary_assignment.stderr @@ -24,7 +24,7 @@ LL | ArrayStruct { array: [0] }.array[0] = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: assignment to temporary - --> tests/ui/temporary_assignment.rs:59:5 + --> tests/ui/temporary_assignment.rs:60:5 | LL | (0, 0).0 = 1; | ^^^^^^^^^^^^ diff --git a/tests/ui/test_attr_in_doctest.rs b/tests/ui/test_attr_in_doctest.rs index 4c904f7a09ac..6cffd813b835 100644 --- a/tests/ui/test_attr_in_doctest.rs +++ b/tests/ui/test_attr_in_doctest.rs @@ -4,46 +4,44 @@ /// /// ``` /// #[test] +//~^ test_attr_in_doctest /// fn should_be_linted() { /// assert_eq!(1, 1); /// } /// ``` -/// +/// /// Make sure we catch multiple tests in one example, /// and show that we really parse the attr: -/// /// ``` /// #[test] +//~^ test_attr_in_doctest /// fn should_also_be_linted() { /// #[cfg(test)] /// assert!(true); /// } /// /// #[test] +//~^ test_attr_in_doctest /// fn should_be_linted_too() { /// assert_eq!("#[test]", " /// #[test] /// "); /// } /// ``` -/// +/// /// We don't catch examples that aren't run: -/// /// ```ignore /// #[test] /// fn ignored() { todo!() } /// ``` -/// /// ```no_run /// #[test] /// fn ignored() { todo!() } /// ``` -/// /// ```compile_fail /// #[test] /// fn ignored() { Err(()) } /// ``` -/// /// ```txt /// #[test] /// fn not_even_rust() { panic!("Ouch") } diff --git a/tests/ui/test_attr_in_doctest.stderr b/tests/ui/test_attr_in_doctest.stderr index f950455f2908..166b9b417b62 100644 --- a/tests/ui/test_attr_in_doctest.stderr +++ b/tests/ui/test_attr_in_doctest.stderr @@ -3,6 +3,7 @@ error: unit tests in doctest are not executed | LL | /// #[test] | _____^ +LL | | LL | | /// fn should_be_linted() { | |_______________________^ | @@ -14,14 +15,16 @@ error: unit tests in doctest are not executed | LL | /// #[test] | _____^ +LL | | LL | | /// fn should_also_be_linted() { | |____________________________^ error: unit tests in doctest are not executed - --> tests/ui/test_attr_in_doctest.rs:22:5 + --> tests/ui/test_attr_in_doctest.rs:23:5 | LL | /// #[test] | _____^ +LL | | LL | | /// fn should_be_linted_too() { | |___________________________^ diff --git a/tests/ui/tests_outside_test_module.rs b/tests/ui/tests_outside_test_module.rs index 0abde4a57bf7..35126c46af08 100644 --- a/tests/ui/tests_outside_test_module.rs +++ b/tests/ui/tests_outside_test_module.rs @@ -1,3 +1,4 @@ +//@require-annotations-for-level: WARN #![allow(unused)] #![warn(clippy::tests_outside_test_module)] diff --git a/tests/ui/tests_outside_test_module.stderr b/tests/ui/tests_outside_test_module.stderr index 09feae6bf2aa..8602a63cc7a4 100644 --- a/tests/ui/tests_outside_test_module.stderr +++ b/tests/ui/tests_outside_test_module.stderr @@ -1,5 +1,5 @@ error: this function marked with #[test] is outside a #[cfg(test)] module - --> tests/ui/tests_outside_test_module.rs:10:1 + --> tests/ui/tests_outside_test_module.rs:11:1 | LL | fn my_test() {} | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/to_digit_is_some.fixed b/tests/ui/to_digit_is_some.fixed index 2ef4c05289fd..627d54c5f738 100644 --- a/tests/ui/to_digit_is_some.fixed +++ b/tests/ui/to_digit_is_some.fixed @@ -5,5 +5,7 @@ fn main() { let d = &c; let _ = d.is_digit(8); + //~^ to_digit_is_some let _ = char::is_digit(c, 8); + //~^ to_digit_is_some } diff --git a/tests/ui/to_digit_is_some.rs b/tests/ui/to_digit_is_some.rs index 54d9545809c5..d4eccc9931f1 100644 --- a/tests/ui/to_digit_is_some.rs +++ b/tests/ui/to_digit_is_some.rs @@ -5,5 +5,7 @@ fn main() { let d = &c; let _ = d.to_digit(8).is_some(); + //~^ to_digit_is_some let _ = char::to_digit(c, 8).is_some(); + //~^ to_digit_is_some } diff --git a/tests/ui/to_digit_is_some.stderr b/tests/ui/to_digit_is_some.stderr index e44106b2e188..f41382a60d53 100644 --- a/tests/ui/to_digit_is_some.stderr +++ b/tests/ui/to_digit_is_some.stderr @@ -8,7 +8,7 @@ LL | let _ = d.to_digit(8).is_some(); = help: to override `-D warnings` add `#[allow(clippy::to_digit_is_some)]` error: use of `.to_digit(..).is_some()` - --> tests/ui/to_digit_is_some.rs:8:13 + --> tests/ui/to_digit_is_some.rs:9:13 | LL | let _ = char::to_digit(c, 8).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `char::is_digit(c, 8)` diff --git a/tests/ui/to_string_trait_impl.rs b/tests/ui/to_string_trait_impl.rs index 7be9f7994f08..646ec4db1f11 100644 --- a/tests/ui/to_string_trait_impl.rs +++ b/tests/ui/to_string_trait_impl.rs @@ -9,6 +9,7 @@ struct Point { } impl ToString for Point { + //~^ to_string_trait_impl fn to_string(&self) -> String { format!("({}, {})", self.x, self.y) } diff --git a/tests/ui/to_string_trait_impl.stderr b/tests/ui/to_string_trait_impl.stderr index fe8afc215f0c..b24dfa39e011 100644 --- a/tests/ui/to_string_trait_impl.stderr +++ b/tests/ui/to_string_trait_impl.stderr @@ -2,6 +2,7 @@ error: direct implementation of `ToString` --> tests/ui/to_string_trait_impl.rs:11:1 | LL | / impl ToString for Point { +LL | | LL | | fn to_string(&self) -> String { LL | | format!("({}, {})", self.x, self.y) LL | | } diff --git a/tests/ui/too_long_first_doc_paragraph-fix.fixed b/tests/ui/too_long_first_doc_paragraph-fix.fixed index d4a0cdf3447f..7075aefd50b6 100644 --- a/tests/ui/too_long_first_doc_paragraph-fix.fixed +++ b/tests/ui/too_long_first_doc_paragraph-fix.fixed @@ -1,7 +1,9 @@ #![warn(clippy::too_long_first_doc_paragraph)] /// A very short summary. +//~^ too_long_first_doc_paragraph /// +//~^ too_long_first_doc_paragraph /// A much longer explanation that goes into a lot more detail about /// how the thing works, possibly with doclinks and so one, /// and probably spanning a many rows. Blablabla, it needs to be over diff --git a/tests/ui/too_long_first_doc_paragraph-fix.rs b/tests/ui/too_long_first_doc_paragraph-fix.rs index 5a3b6c42a328..844417d741ef 100644 --- a/tests/ui/too_long_first_doc_paragraph-fix.rs +++ b/tests/ui/too_long_first_doc_paragraph-fix.rs @@ -1,6 +1,7 @@ #![warn(clippy::too_long_first_doc_paragraph)] /// A very short summary. +//~^ too_long_first_doc_paragraph /// A much longer explanation that goes into a lot more detail about /// how the thing works, possibly with doclinks and so one, /// and probably spanning a many rows. Blablabla, it needs to be over diff --git a/tests/ui/too_long_first_doc_paragraph-fix.stderr b/tests/ui/too_long_first_doc_paragraph-fix.stderr index 84a574017a9b..bc2fbc2d14df 100644 --- a/tests/ui/too_long_first_doc_paragraph-fix.stderr +++ b/tests/ui/too_long_first_doc_paragraph-fix.stderr @@ -2,6 +2,7 @@ error: first doc comment paragraph is too long --> tests/ui/too_long_first_doc_paragraph-fix.rs:3:1 | LL | / /// A very short summary. +LL | | LL | | /// A much longer explanation that goes into a lot more detail about LL | | /// how the thing works, possibly with doclinks and so one, LL | | /// and probably spanning a many rows. Blablabla, it needs to be over @@ -13,7 +14,9 @@ LL | | /// 200 characters so I needed to write something longeeeeeeer. help: add an empty line | LL | /// A very short summary. +LL | LL + /// +LL + | error: aborting due to 1 previous error diff --git a/tests/ui/too_long_first_doc_paragraph.rs b/tests/ui/too_long_first_doc_paragraph.rs index 7d0a37cde46d..49420841c88c 100644 --- a/tests/ui/too_long_first_doc_paragraph.rs +++ b/tests/ui/too_long_first_doc_paragraph.rs @@ -6,6 +6,7 @@ pub mod foo { // in foo.rs //! A very short summary. + //~^ too_long_first_doc_paragraph //! A much longer explanation that goes into a lot more detail about //! how the thing works, possibly with doclinks and so one, //! and probably spanning a many rows. Blablabla, it needs to be over @@ -13,6 +14,7 @@ pub mod foo { } /// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia +//~^ too_long_first_doc_paragraph /// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero, /// gravida non lacinia at, rhoncus eu lacus. pub struct Bar; @@ -34,6 +36,7 @@ pub enum Enum { } /// Lorem +//~^ too_long_first_doc_paragraph /// ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia /// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero, /// gravida non lacinia at, rhoncus eu lacus. @@ -58,6 +61,13 @@ pub union Union2 { /// gravida non lacinia at, rhoncus eu lacus. fn f() {} +#[rustfmt::skip] +/// Some function. This doc-string paragraph is too long. Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. +//~^ too_long_first_doc_paragraph +/// +/// Here's a second paragraph. It would be preferable to put the details here. +pub fn issue_14274() {} + fn main() { // test code goes here } diff --git a/tests/ui/too_long_first_doc_paragraph.stderr b/tests/ui/too_long_first_doc_paragraph.stderr index 8bc853132ec0..f3f182aa5422 100644 --- a/tests/ui/too_long_first_doc_paragraph.stderr +++ b/tests/ui/too_long_first_doc_paragraph.stderr @@ -2,6 +2,7 @@ error: first doc comment paragraph is too long --> tests/ui/too_long_first_doc_paragraph.rs:8:5 | LL | / //! A very short summary. +LL | | LL | | //! A much longer explanation that goes into a lot more detail about LL | | //! how the thing works, possibly with doclinks and so one, LL | | //! and probably spanning a many rows. Blablabla, it needs to be over @@ -13,26 +14,39 @@ LL | | //! 200 characters so I needed to write something longeeeeeeer. help: add an empty line | LL | //! A very short summary. +LL | LL ~ //! +LL + LL ~ //! A much longer explanation that goes into a lot more detail about | error: first doc comment paragraph is too long - --> tests/ui/too_long_first_doc_paragraph.rs:15:1 + --> tests/ui/too_long_first_doc_paragraph.rs:16:1 | LL | / /// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia +LL | | LL | | /// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero, LL | | /// gravida non lacinia at, rhoncus eu lacus. | |_^ error: first doc comment paragraph is too long - --> tests/ui/too_long_first_doc_paragraph.rs:36:1 + --> tests/ui/too_long_first_doc_paragraph.rs:38:1 | LL | / /// Lorem +LL | | LL | | /// ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia LL | | /// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero, LL | | /// gravida non lacinia at, rhoncus eu lacus. | |_^ -error: aborting due to 3 previous errors +error: first doc comment paragraph is too long + --> tests/ui/too_long_first_doc_paragraph.rs:65:1 + | +LL | / /// Some function. This doc-string paragraph is too long. Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lore... +LL | | +LL | | /// +LL | | /// Here's a second paragraph. It would be preferable to put the details here. + | |_^ + +error: aborting due to 4 previous errors diff --git a/tests/ui/toplevel_ref_arg.fixed b/tests/ui/toplevel_ref_arg.fixed index 3eb47a5b5fd6..11d4eaaefda0 100644 --- a/tests/ui/toplevel_ref_arg.fixed +++ b/tests/ui/toplevel_ref_arg.fixed @@ -12,17 +12,22 @@ fn main() { y(1u8); let _x = &1; + //~^ toplevel_ref_arg let _y: &(&_, u8) = &(&1, 2); + //~^ toplevel_ref_arg let _z = &(1 + 2); + //~^ toplevel_ref_arg let _z = &mut (1 + 2); + //~^ toplevel_ref_arg let (ref x, _) = (1, 2); // ok, not top level println!("The answer is {}.", x); let _x = &vec![1, 2, 3]; + //~^ toplevel_ref_arg // Make sure that allowing the lint works #[allow(clippy::toplevel_ref_arg)] @@ -33,6 +38,7 @@ fn main() { // lint in macro inline!(let _y = &42;); + //~^ toplevel_ref_arg // do not lint in external macro external!(let ref _y = 42;); diff --git a/tests/ui/toplevel_ref_arg.rs b/tests/ui/toplevel_ref_arg.rs index cd731387de97..957dd542f5a9 100644 --- a/tests/ui/toplevel_ref_arg.rs +++ b/tests/ui/toplevel_ref_arg.rs @@ -12,17 +12,22 @@ fn main() { y(1u8); let ref _x = 1; + //~^ toplevel_ref_arg let ref _y: (&_, u8) = (&1, 2); + //~^ toplevel_ref_arg let ref _z = 1 + 2; + //~^ toplevel_ref_arg let ref mut _z = 1 + 2; + //~^ toplevel_ref_arg let (ref x, _) = (1, 2); // ok, not top level println!("The answer is {}.", x); let ref _x = vec![1, 2, 3]; + //~^ toplevel_ref_arg // Make sure that allowing the lint works #[allow(clippy::toplevel_ref_arg)] @@ -33,6 +38,7 @@ fn main() { // lint in macro inline!(let ref _y = 42;); + //~^ toplevel_ref_arg // do not lint in external macro external!(let ref _y = 42;); diff --git a/tests/ui/toplevel_ref_arg.stderr b/tests/ui/toplevel_ref_arg.stderr index 61f0fd4a6cd2..42e77f01495b 100644 --- a/tests/ui/toplevel_ref_arg.stderr +++ b/tests/ui/toplevel_ref_arg.stderr @@ -8,31 +8,31 @@ LL | let ref _x = 1; = help: to override `-D warnings` add `#[allow(clippy::toplevel_ref_arg)]` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> tests/ui/toplevel_ref_arg.rs:16:9 + --> tests/ui/toplevel_ref_arg.rs:17:9 | LL | let ref _y: (&_, u8) = (&1, 2); | ----^^^^^^--------------------- help: try: `let _y: &(&_, u8) = &(&1, 2);` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> tests/ui/toplevel_ref_arg.rs:18:9 + --> tests/ui/toplevel_ref_arg.rs:20:9 | LL | let ref _z = 1 + 2; | ----^^^^^^--------- help: try: `let _z = &(1 + 2);` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> tests/ui/toplevel_ref_arg.rs:20:9 + --> tests/ui/toplevel_ref_arg.rs:23:9 | LL | let ref mut _z = 1 + 2; | ----^^^^^^^^^^--------- help: try: `let _z = &mut (1 + 2);` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> tests/ui/toplevel_ref_arg.rs:25:9 + --> tests/ui/toplevel_ref_arg.rs:29:9 | LL | let ref _x = vec![1, 2, 3]; | ----^^^^^^----------------- help: try: `let _x = &vec![1, 2, 3];` error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead - --> tests/ui/toplevel_ref_arg.rs:35:17 + --> tests/ui/toplevel_ref_arg.rs:40:17 | LL | inline!(let ref _y = 42;); | ----^^^^^^------ help: try: `let _y = &42;` diff --git a/tests/ui/toplevel_ref_arg_non_rustfix.rs b/tests/ui/toplevel_ref_arg_non_rustfix.rs index 8aaf47b1bd0c..87c84a7ee14a 100644 --- a/tests/ui/toplevel_ref_arg_non_rustfix.rs +++ b/tests/ui/toplevel_ref_arg_non_rustfix.rs @@ -7,6 +7,7 @@ extern crate proc_macros; use proc_macros::{external, inline_macros}; fn the_answer(ref mut x: u8) { + //~^ toplevel_ref_arg *x = 42; } @@ -18,6 +19,7 @@ fn main() { // lint in macro inline! { fn fun_example(ref _x: usize) {} + //~^ toplevel_ref_arg } // do not lint in external macro diff --git a/tests/ui/toplevel_ref_arg_non_rustfix.stderr b/tests/ui/toplevel_ref_arg_non_rustfix.stderr index 26166e2fc8da..e17b2536874e 100644 --- a/tests/ui/toplevel_ref_arg_non_rustfix.stderr +++ b/tests/ui/toplevel_ref_arg_non_rustfix.stderr @@ -8,7 +8,7 @@ LL | fn the_answer(ref mut x: u8) { = help: to override `-D warnings` add `#[allow(clippy::toplevel_ref_arg)]` error: `ref` directly on a function parameter does not prevent taking ownership of the passed argument. Consider using a reference type instead - --> tests/ui/toplevel_ref_arg_non_rustfix.rs:20:24 + --> tests/ui/toplevel_ref_arg_non_rustfix.rs:21:24 | LL | fn fun_example(ref _x: usize) {} | ^^^^^^ diff --git a/tests/ui/track-diagnostics.rs b/tests/ui/track-diagnostics.rs index 6ab0bce770e2..723ea23e9a63 100644 --- a/tests/ui/track-diagnostics.rs +++ b/tests/ui/track-diagnostics.rs @@ -7,5 +7,6 @@ struct A; struct B; const S: A = B; +//~^ ERROR: mismatched types fn main() {} diff --git a/tests/ui/trailing_empty_array.rs b/tests/ui/trailing_empty_array.rs index ea3b8ff01afa..a8c3ffdb0dab 100644 --- a/tests/ui/trailing_empty_array.rs +++ b/tests/ui/trailing_empty_array.rs @@ -4,39 +4,39 @@ // Do lint: struct RarelyUseful { - //~^ ERROR: trailing zero-sized array in a struct which is not marked with a `repr` attrib + //~^ trailing_empty_array field: i32, last: [usize; 0], } struct OnlyField { - //~^ ERROR: trailing zero-sized array in a struct which is not marked with a `repr` attrib + //~^ trailing_empty_array first_and_last: [usize; 0], } struct GenericArrayType { - //~^ ERROR: trailing zero-sized array in a struct which is not marked with a `repr` attrib + //~^ trailing_empty_array field: i32, last: [T; 0], } #[must_use] struct OnlyAnotherAttribute { - //~^ ERROR: trailing zero-sized array in a struct which is not marked with a `repr` attrib + //~^ trailing_empty_array field: i32, last: [usize; 0], } #[derive(Debug)] struct OnlyADeriveAttribute { - //~^ ERROR: trailing zero-sized array in a struct which is not marked with a `repr` attrib + //~^ trailing_empty_array field: i32, last: [usize; 0], } const ZERO: usize = 0; struct ZeroSizedWithConst { - //~^ ERROR: trailing zero-sized array in a struct which is not marked with a `repr` attrib + //~^ trailing_empty_array field: i32, last: [usize; ZERO], } @@ -46,7 +46,7 @@ const fn compute_zero() -> usize { (4 + 6) - (2 * 5) } struct ZeroSizedWithConstFunction { - //~^ ERROR: trailing zero-sized array in a struct which is not marked with a `repr` attrib + //~^ trailing_empty_array field: i32, last: [usize; compute_zero()], } @@ -55,19 +55,19 @@ const fn compute_zero_from_arg(x: usize) -> usize { x - 1 } struct ZeroSizedWithConstFunction2 { - //~^ ERROR: trailing zero-sized array in a struct which is not marked with a `repr` attrib + //~^ trailing_empty_array field: i32, last: [usize; compute_zero_from_arg(1)], } struct ZeroSizedArrayWrapper([usize; 0]); -//~^ ERROR: trailing zero-sized array in a struct which is not marked with a `repr` attrib +//~^ trailing_empty_array struct TupleStruct(i32, [usize; 0]); -//~^ ERROR: trailing zero-sized array in a struct which is not marked with a `repr` attrib +//~^ trailing_empty_array struct LotsOfFields { - //~^ ERROR: trailing zero-sized array in a struct which is not marked with a `repr` attrib + //~^ trailing_empty_array f1: u32, f2: u32, f3: u32, diff --git a/tests/ui/trailing_zeros.fixed b/tests/ui/trailing_zeros.fixed index f7de976f1e00..8c30b062fb18 100644 --- a/tests/ui/trailing_zeros.fixed +++ b/tests/ui/trailing_zeros.fixed @@ -4,10 +4,11 @@ fn main() { let x: i32 = 42; let _ = x.trailing_zeros() >= 4; - //~^ ERROR: bit mask could be simplified with a call to `trailing_zeros` - //~| NOTE: `-D clippy::verbose-bit-mask` implied by `-D warnings` + //~^ verbose_bit_mask + let _ = x.trailing_zeros() >= 5; - //~^ ERROR: bit mask could be simplified with a call to `trailing_zeros` + //~^ verbose_bit_mask + let _ = x & 0b1_1010 == 0; // do not lint let _ = x & 1 == 0; // do not lint } diff --git a/tests/ui/trailing_zeros.rs b/tests/ui/trailing_zeros.rs index a05b09233e21..369a31557392 100644 --- a/tests/ui/trailing_zeros.rs +++ b/tests/ui/trailing_zeros.rs @@ -4,10 +4,11 @@ fn main() { let x: i32 = 42; let _ = (x & 0b1111 == 0); - //~^ ERROR: bit mask could be simplified with a call to `trailing_zeros` - //~| NOTE: `-D clippy::verbose-bit-mask` implied by `-D warnings` + //~^ verbose_bit_mask + let _ = x & 0b1_1111 == 0; - //~^ ERROR: bit mask could be simplified with a call to `trailing_zeros` + //~^ verbose_bit_mask + let _ = x & 0b1_1010 == 0; // do not lint let _ = x & 1 == 0; // do not lint } diff --git a/tests/ui/trait_duplication_in_bounds.fixed b/tests/ui/trait_duplication_in_bounds.fixed index 708512793d50..666ff78b2189 100644 --- a/tests/ui/trait_duplication_in_bounds.fixed +++ b/tests/ui/trait_duplication_in_bounds.fixed @@ -5,12 +5,14 @@ use std::any::Any; fn bad_foo(arg0: T, argo1: U) { + //~^ trait_duplication_in_bounds unimplemented!(); } fn bad_bar(arg0: T, arg1: U) where T: Clone + Copy, + //~^ trait_duplication_in_bounds U: Clone + Copy, { unimplemented!(); @@ -39,6 +41,7 @@ trait GoodSelfWhereClause { } trait BadSelfTraitBound: Clone { + //~^ trait_duplication_in_bounds fn f(); } @@ -46,6 +49,7 @@ trait BadSelfWhereClause { fn f() where Self: Clone; + //~^ trait_duplication_in_bounds } trait GoodTraitBound { @@ -60,6 +64,7 @@ trait GoodWhereClause { } trait BadTraitBound { + //~^ trait_duplication_in_bounds fn f(); } @@ -67,6 +72,7 @@ trait BadWhereClause { fn f() where T: Clone + Copy, + //~^ trait_duplication_in_bounds U: Clone + Copy; } @@ -100,6 +106,7 @@ fn good_generic + GenericTrait>(arg0: T) { } fn bad_generic + GenericTrait>(arg0: T) { + //~^ trait_duplication_in_bounds unimplemented!(); } @@ -108,6 +115,7 @@ mod foo { } fn qualified_path(arg0: T) { + //~^ trait_duplication_in_bounds unimplemented!(); } @@ -116,6 +124,7 @@ fn good_trait_object(arg0: &(dyn Any + Send)) { } fn bad_trait_object(arg0: &(dyn Any + Send)) { + //~^ trait_duplication_in_bounds unimplemented!(); } diff --git a/tests/ui/trait_duplication_in_bounds.rs b/tests/ui/trait_duplication_in_bounds.rs index 12db6b65a7ae..a1a86fe058e6 100644 --- a/tests/ui/trait_duplication_in_bounds.rs +++ b/tests/ui/trait_duplication_in_bounds.rs @@ -5,12 +5,14 @@ use std::any::Any; fn bad_foo(arg0: T, argo1: U) { + //~^ trait_duplication_in_bounds unimplemented!(); } fn bad_bar(arg0: T, arg1: U) where T: Clone + Clone + Clone + Copy, + //~^ trait_duplication_in_bounds U: Clone + Copy, { unimplemented!(); @@ -39,6 +41,7 @@ trait GoodSelfWhereClause { } trait BadSelfTraitBound: Clone + Clone + Clone { + //~^ trait_duplication_in_bounds fn f(); } @@ -46,6 +49,7 @@ trait BadSelfWhereClause { fn f() where Self: Clone + Clone + Clone; + //~^ trait_duplication_in_bounds } trait GoodTraitBound { @@ -60,6 +64,7 @@ trait GoodWhereClause { } trait BadTraitBound { + //~^ trait_duplication_in_bounds fn f(); } @@ -67,6 +72,7 @@ trait BadWhereClause { fn f() where T: Clone + Clone + Clone + Copy, + //~^ trait_duplication_in_bounds U: Clone + Copy; } @@ -100,6 +106,7 @@ fn good_generic + GenericTrait>(arg0: T) { } fn bad_generic + GenericTrait + GenericTrait>(arg0: T) { + //~^ trait_duplication_in_bounds unimplemented!(); } @@ -108,6 +115,7 @@ mod foo { } fn qualified_path(arg0: T) { + //~^ trait_duplication_in_bounds unimplemented!(); } @@ -116,6 +124,7 @@ fn good_trait_object(arg0: &(dyn Any + Send)) { } fn bad_trait_object(arg0: &(dyn Any + Send + Send)) { + //~^ trait_duplication_in_bounds unimplemented!(); } diff --git a/tests/ui/trait_duplication_in_bounds.stderr b/tests/ui/trait_duplication_in_bounds.stderr index 83c06eaccd4e..d76b4e458480 100644 --- a/tests/ui/trait_duplication_in_bounds.stderr +++ b/tests/ui/trait_duplication_in_bounds.stderr @@ -11,67 +11,67 @@ LL | #![deny(clippy::trait_duplication_in_bounds)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: these where clauses contain repeated elements - --> tests/ui/trait_duplication_in_bounds.rs:13:8 + --> tests/ui/trait_duplication_in_bounds.rs:14:8 | LL | T: Clone + Clone + Clone + Copy, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy` error: these bounds contain repeated elements - --> tests/ui/trait_duplication_in_bounds.rs:41:26 + --> tests/ui/trait_duplication_in_bounds.rs:43:26 | LL | trait BadSelfTraitBound: Clone + Clone + Clone { | ^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone` error: these where clauses contain repeated elements - --> tests/ui/trait_duplication_in_bounds.rs:48:15 + --> tests/ui/trait_duplication_in_bounds.rs:51:15 | LL | Self: Clone + Clone + Clone; | ^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone` error: these bounds contain repeated elements - --> tests/ui/trait_duplication_in_bounds.rs:62:24 + --> tests/ui/trait_duplication_in_bounds.rs:66:24 | LL | trait BadTraitBound { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy` error: these where clauses contain repeated elements - --> tests/ui/trait_duplication_in_bounds.rs:69:12 + --> tests/ui/trait_duplication_in_bounds.rs:74:12 | LL | T: Clone + Clone + Clone + Copy, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy` error: these bounds contain repeated elements - --> tests/ui/trait_duplication_in_bounds.rs:102:19 + --> tests/ui/trait_duplication_in_bounds.rs:108:19 | LL | fn bad_generic + GenericTrait + GenericTrait>(arg0: T) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `GenericTrait + GenericTrait` error: these bounds contain repeated elements - --> tests/ui/trait_duplication_in_bounds.rs:110:22 + --> tests/ui/trait_duplication_in_bounds.rs:117:22 | LL | fn qualified_path(arg0: T) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::clone::Clone + foo::Clone` error: this trait bound is already specified in trait declaration - --> tests/ui/trait_duplication_in_bounds.rs:118:33 + --> tests/ui/trait_duplication_in_bounds.rs:126:33 | LL | fn bad_trait_object(arg0: &(dyn Any + Send + Send)) { | ^^^^^^^^^^^^^^^^^ help: try: `Any + Send` error: these bounds contain repeated elements - --> tests/ui/trait_duplication_in_bounds.rs:165:36 + --> tests/ui/trait_duplication_in_bounds.rs:174:36 | LL | const fn const_trait_bounds_bad() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `~const ConstTrait` error: these where clauses contain repeated elements - --> tests/ui/trait_duplication_in_bounds.rs:172:8 + --> tests/ui/trait_duplication_in_bounds.rs:181:8 | LL | T: IntoIterator + IntoIterator, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `IntoIterator` error: these where clauses contain repeated elements - --> tests/ui/trait_duplication_in_bounds.rs:194:8 + --> tests/ui/trait_duplication_in_bounds.rs:203:8 | LL | T: AssocConstTrait + AssocConstTrait, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `AssocConstTrait` diff --git a/tests/ui/trait_duplication_in_bounds_unfixable.rs b/tests/ui/trait_duplication_in_bounds_unfixable.rs index b0095bb77b5a..cf72ed844a78 100644 --- a/tests/ui/trait_duplication_in_bounds_unfixable.rs +++ b/tests/ui/trait_duplication_in_bounds_unfixable.rs @@ -5,8 +5,8 @@ use std::collections::BTreeMap; use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; fn bad_foo(arg0: T, arg1: Z) -//~^ ERROR: this trait bound is already specified in the where clause -//~| ERROR: this trait bound is already specified in the where clause +//~^ trait_duplication_in_bounds +//~| trait_duplication_in_bounds where T: Clone, T: Default, @@ -36,7 +36,7 @@ trait T: Default { fn f() where Self: Default; - //~^ ERROR: this trait bound is already specified in trait declaration + //~^ trait_duplication_in_bounds } trait U: Default { @@ -51,19 +51,21 @@ trait ZZ: Default { fn f() where Self: Default + Clone; - //~^ ERROR: this trait bound is already specified in trait declaration + //~^ trait_duplication_in_bounds } trait BadTrait: Default + Clone { fn f() where Self: Default + Clone; - //~^ ERROR: this trait bound is already specified in trait declaration - //~| ERROR: this trait bound is already specified in trait declaration + //~^ trait_duplication_in_bounds + //~| trait_duplication_in_bounds + fn g() where Self: Default; - //~^ ERROR: this trait bound is already specified in trait declaration + //~^ trait_duplication_in_bounds + fn h() where Self: Copy; @@ -99,7 +101,7 @@ trait FooIter: Iterator { fn bar() where Self: Iterator, - //~^ ERROR: this trait bound is already specified in trait declaration + //~^ trait_duplication_in_bounds { } } diff --git a/tests/ui/trait_duplication_in_bounds_unfixable.stderr b/tests/ui/trait_duplication_in_bounds_unfixable.stderr index 41029007a98e..546d39518e1f 100644 --- a/tests/ui/trait_duplication_in_bounds_unfixable.stderr +++ b/tests/ui/trait_duplication_in_bounds_unfixable.stderr @@ -52,7 +52,7 @@ LL | Self: Default + Clone; = help: consider removing this trait bound error: this trait bound is already specified in trait declaration - --> tests/ui/trait_duplication_in_bounds_unfixable.rs:65:15 + --> tests/ui/trait_duplication_in_bounds_unfixable.rs:66:15 | LL | Self: Default; | ^^^^^^^ @@ -60,7 +60,7 @@ LL | Self: Default; = help: consider removing this trait bound error: this trait bound is already specified in trait declaration - --> tests/ui/trait_duplication_in_bounds_unfixable.rs:101:15 + --> tests/ui/trait_duplication_in_bounds_unfixable.rs:103:15 | LL | Self: Iterator, | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index 7f5bdea4acf3..3aecde398dc3 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -29,41 +29,40 @@ unsafe fn _generic<'a, T, U: 'a>(t: &'a T) { let _: &'a U = core::mem::transmute(t); let _: *const T = core::mem::transmute(t); - //~^ ERROR: transmute from a reference to a pointer - //~| NOTE: `-D clippy::useless-transmute` implied by `-D warnings` + //~^ useless_transmute let _: *mut T = core::mem::transmute(t); - //~^ ERROR: transmute from a reference to a pointer + //~^ useless_transmute let _: *const U = core::mem::transmute(t); - //~^ ERROR: transmute from a reference to a pointer + //~^ useless_transmute } #[warn(clippy::useless_transmute)] fn useless() { unsafe { let _: Vec = core::mem::transmute(my_vec()); - //~^ ERROR: transmute from a type (`std::vec::Vec`) to itself + //~^ useless_transmute let _: Vec = core::mem::transmute(my_vec()); - //~^ ERROR: transmute from a type (`std::vec::Vec`) to itself + //~^ useless_transmute let _: Vec = std::mem::transmute(my_vec()); - //~^ ERROR: transmute from a type (`std::vec::Vec`) to itself + //~^ useless_transmute let _: Vec = std::mem::transmute(my_vec()); - //~^ ERROR: transmute from a type (`std::vec::Vec`) to itself + //~^ useless_transmute let _: Vec = my_transmute(my_vec()); - //~^ ERROR: transmute from a type (`std::vec::Vec`) to itself + //~^ useless_transmute let _: *const usize = std::mem::transmute(5_isize); - //~^ ERROR: transmute from an integer to a pointer + //~^ useless_transmute let _ = 5_isize as *const usize; let _: *const usize = std::mem::transmute(1 + 1usize); - //~^ ERROR: transmute from an integer to a pointer + //~^ useless_transmute let _ = (1 + 1_usize) as *const usize; } @@ -95,77 +94,84 @@ fn crosspointer() { unsafe { let _: Usize = core::mem::transmute(int_const_ptr); - //~^ ERROR: transmute from a type (`*const Usize`) to the type that it points to ( - //~| NOTE: `-D clippy::crosspointer-transmute` implied by `-D warnings` + //~^ crosspointer_transmute let _: Usize = core::mem::transmute(int_mut_ptr); - //~^ ERROR: transmute from a type (`*mut Usize`) to the type that it points to (`U + //~^ crosspointer_transmute let _: *const Usize = core::mem::transmute(my_int()); - //~^ ERROR: transmute from a type (`Usize`) to a pointer to that type (`*const Usi + //~^ crosspointer_transmute let _: *mut Usize = core::mem::transmute(my_int()); - //~^ ERROR: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize + //~^ crosspointer_transmute } } #[warn(clippy::transmute_int_to_bool)] fn int_to_bool() { let _: bool = unsafe { std::mem::transmute(0_u8) }; - //~^ ERROR: transmute from a `u8` to a `bool` - //~| NOTE: `-D clippy::transmute-int-to-bool` implied by `-D warnings` + //~^ transmute_int_to_bool } #[warn(clippy::transmute_int_to_float)] mod int_to_float { fn test() { let _: f16 = unsafe { std::mem::transmute(0_u16) }; - //~^ ERROR: transmute from a `u16` to a `f16` - //~| NOTE: `-D clippy::transmute-int-to-float` implied by `-D warnings` + //~^ transmute_int_to_float + let _: f16 = unsafe { std::mem::transmute(0_i16) }; - //~^ ERROR: transmute from a `i16` to a `f16` + //~^ transmute_int_to_float + let _: f32 = unsafe { std::mem::transmute(0_u32) }; - //~^ ERROR: transmute from a `u32` to a `f32` + //~^ transmute_int_to_float + let _: f32 = unsafe { std::mem::transmute(0_i32) }; - //~^ ERROR: transmute from a `i32` to a `f32` + //~^ transmute_int_to_float + let _: f64 = unsafe { std::mem::transmute(0_u64) }; - //~^ ERROR: transmute from a `u64` to a `f64` + //~^ transmute_int_to_float + let _: f64 = unsafe { std::mem::transmute(0_i64) }; - //~^ ERROR: transmute from a `i64` to a `f64` + //~^ transmute_int_to_float + let _: f128 = unsafe { std::mem::transmute(0_u128) }; - //~^ ERROR: transmute from a `u128` to a `f128` + //~^ transmute_int_to_float + let _: f128 = unsafe { std::mem::transmute(0_i128) }; - //~^ ERROR: transmute from a `i128` to a `f128` + //~^ transmute_int_to_float } mod issue_5747 { const VALUE16: f16 = unsafe { std::mem::transmute(0_u16) }; - //~^ ERROR: transmute from a `u16` to a `f16` + //~^ transmute_int_to_float + const VALUE32: f32 = unsafe { std::mem::transmute(0_u32) }; - //~^ ERROR: transmute from a `u32` to a `f32` + //~^ transmute_int_to_float + const VALUE64: f64 = unsafe { std::mem::transmute(0_i64) }; - //~^ ERROR: transmute from a `i64` to a `f64` + //~^ transmute_int_to_float + const VALUE128: f128 = unsafe { std::mem::transmute(0_i128) }; - //~^ ERROR: transmute from a `i128` to a `f128` + //~^ transmute_int_to_float const fn from_bits_16(v: i16) -> f16 { unsafe { std::mem::transmute(v) } - //~^ ERROR: transmute from a `i16` to a `f16` + //~^ transmute_int_to_float } const fn from_bits_32(v: i32) -> f32 { unsafe { std::mem::transmute(v) } - //~^ ERROR: transmute from a `i32` to a `f32` + //~^ transmute_int_to_float } const fn from_bits_64(v: u64) -> f64 { unsafe { std::mem::transmute(v) } - //~^ ERROR: transmute from a `u64` to a `f64` + //~^ transmute_int_to_float } const fn from_bits_128(v: u128) -> f128 { unsafe { std::mem::transmute(v) } - //~^ ERROR: transmute from a `u128` to a `f128` + //~^ transmute_int_to_float } } } @@ -174,52 +180,67 @@ mod num_to_bytes { fn test() { unsafe { let _: [u8; 1] = std::mem::transmute(0u8); - //~^ ERROR: transmute from a `u8` to a `[u8; 1]` - //~| NOTE: `-D clippy::transmute-num-to-bytes` implied by `-D warnings` + //~^ transmute_num_to_bytes + let _: [u8; 4] = std::mem::transmute(0u32); - //~^ ERROR: transmute from a `u32` to a `[u8; 4]` + //~^ transmute_num_to_bytes + let _: [u8; 16] = std::mem::transmute(0u128); - //~^ ERROR: transmute from a `u128` to a `[u8; 16]` + //~^ transmute_num_to_bytes + let _: [u8; 1] = std::mem::transmute(0i8); - //~^ ERROR: transmute from a `i8` to a `[u8; 1]` + //~^ transmute_num_to_bytes + let _: [u8; 4] = std::mem::transmute(0i32); - //~^ ERROR: transmute from a `i32` to a `[u8; 4]` + //~^ transmute_num_to_bytes + let _: [u8; 16] = std::mem::transmute(0i128); - //~^ ERROR: transmute from a `i128` to a `[u8; 16]` + //~^ transmute_num_to_bytes let _: [u8; 2] = std::mem::transmute(0.0f16); - //~^ ERROR: transmute from a `f16` to a `[u8; 2]` + //~^ transmute_num_to_bytes + let _: [u8; 4] = std::mem::transmute(0.0f32); - //~^ ERROR: transmute from a `f32` to a `[u8; 4]` + //~^ transmute_num_to_bytes + let _: [u8; 8] = std::mem::transmute(0.0f64); - //~^ ERROR: transmute from a `f64` to a `[u8; 8]` + //~^ transmute_num_to_bytes + let _: [u8; 16] = std::mem::transmute(0.0f128); - //~^ ERROR: transmute from a `f128` to a `[u8; 16]` + //~^ transmute_num_to_bytes } } const fn test_const() { unsafe { let _: [u8; 1] = std::mem::transmute(0u8); - //~^ ERROR: transmute from a `u8` to a `[u8; 1]` + //~^ transmute_num_to_bytes + let _: [u8; 4] = std::mem::transmute(0u32); - //~^ ERROR: transmute from a `u32` to a `[u8; 4]` + //~^ transmute_num_to_bytes + let _: [u8; 16] = std::mem::transmute(0u128); - //~^ ERROR: transmute from a `u128` to a `[u8; 16]` + //~^ transmute_num_to_bytes + let _: [u8; 1] = std::mem::transmute(0i8); - //~^ ERROR: transmute from a `i8` to a `[u8; 1]` + //~^ transmute_num_to_bytes + let _: [u8; 4] = std::mem::transmute(0i32); - //~^ ERROR: transmute from a `i32` to a `[u8; 4]` + //~^ transmute_num_to_bytes + let _: [u8; 16] = std::mem::transmute(0i128); - //~^ ERROR: transmute from a `i128` to a `[u8; 16]` + //~^ transmute_num_to_bytes let _: [u8; 2] = std::mem::transmute(0.0f16); - //~^ ERROR: transmute from a `f16` to a `[u8; 2]` + //~^ transmute_num_to_bytes + let _: [u8; 4] = std::mem::transmute(0.0f32); - //~^ ERROR: transmute from a `f32` to a `[u8; 4]` + //~^ transmute_num_to_bytes + let _: [u8; 8] = std::mem::transmute(0.0f64); - //~^ ERROR: transmute from a `f64` to a `[u8; 8]` + //~^ transmute_num_to_bytes + let _: [u8; 16] = std::mem::transmute(0.0f128); - //~^ ERROR: transmute from a `f128` to a `[u8; 16]` + //~^ transmute_num_to_bytes } } } @@ -228,12 +249,13 @@ fn bytes_to_str(mb: &mut [u8]) { const B: &[u8] = b""; let _: &str = unsafe { std::mem::transmute(B) }; - //~^ ERROR: transmute from a `&[u8]` to a `&str` - //~| NOTE: `-D clippy::transmute-bytes-to-str` implied by `-D warnings` + //~^ transmute_bytes_to_str + let _: &mut str = unsafe { std::mem::transmute(mb) }; - //~^ ERROR: transmute from a `&mut [u8]` to a `&mut str` + //~^ transmute_bytes_to_str + const _: &str = unsafe { std::mem::transmute(B) }; - //~^ ERROR: transmute from a `&[u8]` to a `&str` + //~^ transmute_bytes_to_str } fn main() {} diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index b5032772856e..e0d28437aafc 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -8,61 +8,61 @@ LL | let _: *const T = core::mem::transmute(t); = help: to override `-D warnings` add `#[allow(clippy::useless_transmute)]` error: transmute from a reference to a pointer - --> tests/ui/transmute.rs:35:21 + --> tests/ui/transmute.rs:34:21 | LL | let _: *mut T = core::mem::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *mut T` error: transmute from a reference to a pointer - --> tests/ui/transmute.rs:38:23 + --> tests/ui/transmute.rs:37:23 | LL | let _: *const U = core::mem::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *const U` error: transmute from a type (`std::vec::Vec`) to itself - --> tests/ui/transmute.rs:45:27 + --> tests/ui/transmute.rs:44:27 | LL | let _: Vec = core::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> tests/ui/transmute.rs:48:27 + --> tests/ui/transmute.rs:47:27 | LL | let _: Vec = core::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> tests/ui/transmute.rs:51:27 + --> tests/ui/transmute.rs:50:27 | LL | let _: Vec = std::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> tests/ui/transmute.rs:54:27 + --> tests/ui/transmute.rs:53:27 | LL | let _: Vec = std::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> tests/ui/transmute.rs:57:27 + --> tests/ui/transmute.rs:56:27 | LL | let _: Vec = my_transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^ error: transmute from an integer to a pointer - --> tests/ui/transmute.rs:60:31 + --> tests/ui/transmute.rs:59:31 | LL | let _: *const usize = std::mem::transmute(5_isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `5_isize as *const usize` error: transmute from an integer to a pointer - --> tests/ui/transmute.rs:65:31 + --> tests/ui/transmute.rs:64:31 | LL | let _: *const usize = std::mem::transmute(1 + 1usize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(1 + 1usize) as *const usize` error: transmute from a type (`*const Usize`) to the type that it points to (`Usize`) - --> tests/ui/transmute.rs:97:24 + --> tests/ui/transmute.rs:96:24 | LL | let _: Usize = core::mem::transmute(int_const_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -71,25 +71,25 @@ LL | let _: Usize = core::mem::transmute(int_const_ptr); = help: to override `-D warnings` add `#[allow(clippy::crosspointer_transmute)]` error: transmute from a type (`*mut Usize`) to the type that it points to (`Usize`) - --> tests/ui/transmute.rs:101:24 + --> tests/ui/transmute.rs:99:24 | LL | let _: Usize = core::mem::transmute(int_mut_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`Usize`) to a pointer to that type (`*const Usize`) - --> tests/ui/transmute.rs:104:31 + --> tests/ui/transmute.rs:102:31 | LL | let _: *const Usize = core::mem::transmute(my_int()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`) - --> tests/ui/transmute.rs:107:29 + --> tests/ui/transmute.rs:105:29 | LL | let _: *mut Usize = core::mem::transmute(my_int()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a `u8` to a `bool` - --> tests/ui/transmute.rs:114:28 + --> tests/ui/transmute.rs:112:28 | LL | let _: bool = unsafe { std::mem::transmute(0_u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0` @@ -98,7 +98,7 @@ LL | let _: bool = unsafe { std::mem::transmute(0_u8) }; = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_bool)]` error: transmute from a `u16` to a `f16` - --> tests/ui/transmute.rs:122:31 + --> tests/ui/transmute.rs:119:31 | LL | let _: f16 = unsafe { std::mem::transmute(0_u16) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f16::from_bits(0_u16)` @@ -107,19 +107,19 @@ LL | let _: f16 = unsafe { std::mem::transmute(0_u16) }; = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_float)]` error: transmute from a `i16` to a `f16` - --> tests/ui/transmute.rs:125:31 + --> tests/ui/transmute.rs:122:31 | LL | let _: f16 = unsafe { std::mem::transmute(0_i16) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f16::from_bits(0_i16 as u16)` error: transmute from a `u32` to a `f32` - --> tests/ui/transmute.rs:127:31 + --> tests/ui/transmute.rs:125:31 | LL | let _: f32 = unsafe { std::mem::transmute(0_u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)` error: transmute from a `i32` to a `f32` - --> tests/ui/transmute.rs:129:31 + --> tests/ui/transmute.rs:128:31 | LL | let _: f32 = unsafe { std::mem::transmute(0_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)` @@ -131,73 +131,73 @@ LL | let _: f64 = unsafe { std::mem::transmute(0_u64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_u64)` error: transmute from a `i64` to a `f64` - --> tests/ui/transmute.rs:133:31 + --> tests/ui/transmute.rs:134:31 | LL | let _: f64 = unsafe { std::mem::transmute(0_i64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_i64 as u64)` error: transmute from a `u128` to a `f128` - --> tests/ui/transmute.rs:135:32 + --> tests/ui/transmute.rs:137:32 | LL | let _: f128 = unsafe { std::mem::transmute(0_u128) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(0_u128)` error: transmute from a `i128` to a `f128` - --> tests/ui/transmute.rs:137:32 + --> tests/ui/transmute.rs:140:32 | LL | let _: f128 = unsafe { std::mem::transmute(0_i128) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(0_i128 as u128)` error: transmute from a `u16` to a `f16` - --> tests/ui/transmute.rs:142:39 + --> tests/ui/transmute.rs:145:39 | LL | const VALUE16: f16 = unsafe { std::mem::transmute(0_u16) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f16::from_bits(0_u16)` error: transmute from a `u32` to a `f32` - --> tests/ui/transmute.rs:144:39 + --> tests/ui/transmute.rs:148:39 | LL | const VALUE32: f32 = unsafe { std::mem::transmute(0_u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)` error: transmute from a `i64` to a `f64` - --> tests/ui/transmute.rs:146:39 + --> tests/ui/transmute.rs:151:39 | LL | const VALUE64: f64 = unsafe { std::mem::transmute(0_i64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_i64 as u64)` error: transmute from a `i128` to a `f128` - --> tests/ui/transmute.rs:148:41 + --> tests/ui/transmute.rs:154:41 | LL | const VALUE128: f128 = unsafe { std::mem::transmute(0_i128) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(0_i128 as u128)` error: transmute from a `i16` to a `f16` - --> tests/ui/transmute.rs:152:22 + --> tests/ui/transmute.rs:158:22 | LL | unsafe { std::mem::transmute(v) } | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f16::from_bits(v as u16)` error: transmute from a `i32` to a `f32` - --> tests/ui/transmute.rs:157:22 + --> tests/ui/transmute.rs:163:22 | LL | unsafe { std::mem::transmute(v) } | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(v as u32)` error: transmute from a `u64` to a `f64` - --> tests/ui/transmute.rs:162:22 + --> tests/ui/transmute.rs:168:22 | LL | unsafe { std::mem::transmute(v) } | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(v)` error: transmute from a `u128` to a `f128` - --> tests/ui/transmute.rs:167:22 + --> tests/ui/transmute.rs:173:22 | LL | unsafe { std::mem::transmute(v) } | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(v)` error: transmute from a `u8` to a `[u8; 1]` - --> tests/ui/transmute.rs:176:30 + --> tests/ui/transmute.rs:182:30 | LL | let _: [u8; 1] = std::mem::transmute(0u8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()` @@ -206,121 +206,121 @@ LL | let _: [u8; 1] = std::mem::transmute(0u8); = help: to override `-D warnings` add `#[allow(clippy::transmute_num_to_bytes)]` error: transmute from a `u32` to a `[u8; 4]` - --> tests/ui/transmute.rs:179:30 + --> tests/ui/transmute.rs:185:30 | LL | let _: [u8; 4] = std::mem::transmute(0u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()` error: transmute from a `u128` to a `[u8; 16]` - --> tests/ui/transmute.rs:181:31 + --> tests/ui/transmute.rs:188:31 | LL | let _: [u8; 16] = std::mem::transmute(0u128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()` error: transmute from a `i8` to a `[u8; 1]` - --> tests/ui/transmute.rs:183:30 + --> tests/ui/transmute.rs:191:30 | LL | let _: [u8; 1] = std::mem::transmute(0i8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()` error: transmute from a `i32` to a `[u8; 4]` - --> tests/ui/transmute.rs:185:30 + --> tests/ui/transmute.rs:194:30 | LL | let _: [u8; 4] = std::mem::transmute(0i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()` error: transmute from a `i128` to a `[u8; 16]` - --> tests/ui/transmute.rs:187:31 + --> tests/ui/transmute.rs:197:31 | LL | let _: [u8; 16] = std::mem::transmute(0i128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()` error: transmute from a `f16` to a `[u8; 2]` - --> tests/ui/transmute.rs:190:30 + --> tests/ui/transmute.rs:200:30 | LL | let _: [u8; 2] = std::mem::transmute(0.0f16); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f16.to_ne_bytes()` error: transmute from a `f32` to a `[u8; 4]` - --> tests/ui/transmute.rs:192:30 + --> tests/ui/transmute.rs:203:30 | LL | let _: [u8; 4] = std::mem::transmute(0.0f32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f32.to_ne_bytes()` error: transmute from a `f64` to a `[u8; 8]` - --> tests/ui/transmute.rs:194:30 + --> tests/ui/transmute.rs:206:30 | LL | let _: [u8; 8] = std::mem::transmute(0.0f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f64.to_ne_bytes()` error: transmute from a `f128` to a `[u8; 16]` - --> tests/ui/transmute.rs:196:31 + --> tests/ui/transmute.rs:209:31 | LL | let _: [u8; 16] = std::mem::transmute(0.0f128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f128.to_ne_bytes()` error: transmute from a `u8` to a `[u8; 1]` - --> tests/ui/transmute.rs:202:30 + --> tests/ui/transmute.rs:215:30 | LL | let _: [u8; 1] = std::mem::transmute(0u8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()` error: transmute from a `u32` to a `[u8; 4]` - --> tests/ui/transmute.rs:204:30 + --> tests/ui/transmute.rs:218:30 | LL | let _: [u8; 4] = std::mem::transmute(0u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()` error: transmute from a `u128` to a `[u8; 16]` - --> tests/ui/transmute.rs:206:31 + --> tests/ui/transmute.rs:221:31 | LL | let _: [u8; 16] = std::mem::transmute(0u128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()` error: transmute from a `i8` to a `[u8; 1]` - --> tests/ui/transmute.rs:208:30 + --> tests/ui/transmute.rs:224:30 | LL | let _: [u8; 1] = std::mem::transmute(0i8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()` error: transmute from a `i32` to a `[u8; 4]` - --> tests/ui/transmute.rs:210:30 + --> tests/ui/transmute.rs:227:30 | LL | let _: [u8; 4] = std::mem::transmute(0i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()` error: transmute from a `i128` to a `[u8; 16]` - --> tests/ui/transmute.rs:212:31 + --> tests/ui/transmute.rs:230:31 | LL | let _: [u8; 16] = std::mem::transmute(0i128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()` error: transmute from a `f16` to a `[u8; 2]` - --> tests/ui/transmute.rs:215:30 + --> tests/ui/transmute.rs:233:30 | LL | let _: [u8; 2] = std::mem::transmute(0.0f16); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f16.to_ne_bytes()` error: transmute from a `f32` to a `[u8; 4]` - --> tests/ui/transmute.rs:217:30 + --> tests/ui/transmute.rs:236:30 | LL | let _: [u8; 4] = std::mem::transmute(0.0f32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f32.to_ne_bytes()` error: transmute from a `f64` to a `[u8; 8]` - --> tests/ui/transmute.rs:219:30 + --> tests/ui/transmute.rs:239:30 | LL | let _: [u8; 8] = std::mem::transmute(0.0f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f64.to_ne_bytes()` error: transmute from a `f128` to a `[u8; 16]` - --> tests/ui/transmute.rs:221:31 + --> tests/ui/transmute.rs:242:31 | LL | let _: [u8; 16] = std::mem::transmute(0.0f128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f128.to_ne_bytes()` error: transmute from a `&[u8]` to a `&str` - --> tests/ui/transmute.rs:230:28 + --> tests/ui/transmute.rs:251:28 | LL | let _: &str = unsafe { std::mem::transmute(B) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(B).unwrap()` @@ -329,13 +329,13 @@ LL | let _: &str = unsafe { std::mem::transmute(B) }; = help: to override `-D warnings` add `#[allow(clippy::transmute_bytes_to_str)]` error: transmute from a `&mut [u8]` to a `&mut str` - --> tests/ui/transmute.rs:233:32 + --> tests/ui/transmute.rs:254:32 | LL | let _: &mut str = unsafe { std::mem::transmute(mb) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` error: transmute from a `&[u8]` to a `&str` - --> tests/ui/transmute.rs:235:30 + --> tests/ui/transmute.rs:257:30 | LL | const _: &str = unsafe { std::mem::transmute(B) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_unchecked(B)` diff --git a/tests/ui/transmute_32bit.rs b/tests/ui/transmute_32bit.rs index e162bbb2d929..997f43ab12b5 100644 --- a/tests/ui/transmute_32bit.rs +++ b/tests/ui/transmute_32bit.rs @@ -3,12 +3,12 @@ #[warn(clippy::wrong_transmute)] fn main() { unsafe { - let _: *const usize = std::mem::transmute(6.0f32); + let _: *const usize = std::mem::transmute(6.0f32); //~ wrong_transmute - let _: *mut usize = std::mem::transmute(6.0f32); + let _: *mut usize = std::mem::transmute(6.0f32); //~ wrong_transmute - let _: *const usize = std::mem::transmute('x'); + let _: *const usize = std::mem::transmute('x'); //~ wrong_transmute - let _: *mut usize = std::mem::transmute('x'); + let _: *mut usize = std::mem::transmute('x'); //~ wrong_transmute } } diff --git a/tests/ui/transmute_64bit.rs b/tests/ui/transmute_64bit.rs index fd0ad74bcfa0..1a4bfffdc322 100644 --- a/tests/ui/transmute_64bit.rs +++ b/tests/ui/transmute_64bit.rs @@ -4,10 +4,9 @@ fn main() { unsafe { let _: *const usize = std::mem::transmute(6.0f64); - //~^ ERROR: transmute from a `f64` to a pointer - //~| NOTE: `-D clippy::wrong-transmute` implied by `-D warnings` + //~^ wrong_transmute let _: *mut usize = std::mem::transmute(6.0f64); - //~^ ERROR: transmute from a `f64` to a pointer + //~^ wrong_transmute } } diff --git a/tests/ui/transmute_64bit.stderr b/tests/ui/transmute_64bit.stderr index 65fff17f59fa..e75b81671e09 100644 --- a/tests/ui/transmute_64bit.stderr +++ b/tests/ui/transmute_64bit.stderr @@ -8,7 +8,7 @@ LL | let _: *const usize = std::mem::transmute(6.0f64); = help: to override `-D warnings` add `#[allow(clippy::wrong_transmute)]` error: transmute from a `f64` to a pointer - --> tests/ui/transmute_64bit.rs:10:29 + --> tests/ui/transmute_64bit.rs:9:29 | LL | let _: *mut usize = std::mem::transmute(6.0f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/transmute_collection.rs b/tests/ui/transmute_collection.rs index 6748b66e0eb6..74d7f5e38bf8 100644 --- a/tests/ui/transmute_collection.rs +++ b/tests/ui/transmute_collection.rs @@ -8,61 +8,71 @@ fn main() { unsafe { // wrong size let _ = transmute::<_, Vec>(vec![0u8]); - //~^ ERROR: transmute from `std::vec::Vec` to `std::vec::Vec` with mismat - //~| NOTE: `-D clippy::unsound-collection-transmute` implied by `-D warnings` + //~^ unsound_collection_transmute + // wrong layout let _ = transmute::<_, Vec<[u8; 4]>>(vec![1234u32]); - //~^ ERROR: transmute from `std::vec::Vec` to `std::vec::Vec<[u8; 4]>` with m + //~^ unsound_collection_transmute // wrong size let _ = transmute::<_, VecDeque>(VecDeque::::new()); - //~^ ERROR: transmute from `std::collections::VecDeque` to `std::collections:: + //~^ unsound_collection_transmute + // wrong layout let _ = transmute::<_, VecDeque>(VecDeque::<[u8; 4]>::new()); - //~^ ERROR: transmute from `std::collections::VecDeque<[u8; 4]>` to `std::collecti + //~^ unsound_collection_transmute // wrong size let _ = transmute::<_, BinaryHeap>(BinaryHeap::::new()); - //~^ ERROR: transmute from `std::collections::BinaryHeap` to `std::collections + //~^ unsound_collection_transmute + // wrong layout let _ = transmute::<_, BinaryHeap>(BinaryHeap::<[u8; 4]>::new()); - //~^ ERROR: transmute from `std::collections::BinaryHeap<[u8; 4]>` to `std::collec + //~^ unsound_collection_transmute // wrong size let _ = transmute::<_, BTreeSet>(BTreeSet::::new()); - //~^ ERROR: transmute from `std::collections::BTreeSet` to `std::collections:: + //~^ unsound_collection_transmute + // wrong layout let _ = transmute::<_, BTreeSet>(BTreeSet::<[u8; 4]>::new()); - //~^ ERROR: transmute from `std::collections::BTreeSet<[u8; 4]>` to `std::collecti + //~^ unsound_collection_transmute // wrong size let _ = transmute::<_, HashSet>(HashSet::::new()); - //~^ ERROR: transmute from `std::collections::HashSet` to `std::collections::H + //~^ unsound_collection_transmute + // wrong layout let _ = transmute::<_, HashSet>(HashSet::<[u8; 4]>::new()); - //~^ ERROR: transmute from `std::collections::HashSet<[u8; 4]>` to `std::collectio + //~^ unsound_collection_transmute // wrong size let _ = transmute::<_, BTreeMap>(BTreeMap::::new()); - //~^ ERROR: transmute from `std::collections::BTreeMap` to `std::collectio + //~^ unsound_collection_transmute + let _ = transmute::<_, BTreeMap>(BTreeMap::::new()); - //~^ ERROR: transmute from `std::collections::BTreeMap` to `std::collect + //~^ unsound_collection_transmute + // wrong layout let _ = transmute::<_, BTreeMap>(BTreeMap::::new()); - //~^ ERROR: transmute from `std::collections::BTreeMap` to `std::coll + //~^ unsound_collection_transmute + let _ = transmute::<_, BTreeMap>(BTreeMap::<[u8; 4], u32>::new()); - //~^ ERROR: transmute from `std::collections::BTreeMap<[u8; 4], u32>` to `std::col + //~^ unsound_collection_transmute // wrong size let _ = transmute::<_, HashMap>(HashMap::::new()); - //~^ ERROR: transmute from `std::collections::HashMap` to `std::collection + //~^ unsound_collection_transmute + let _ = transmute::<_, HashMap>(HashMap::::new()); - //~^ ERROR: transmute from `std::collections::HashMap` to `std::collecti + //~^ unsound_collection_transmute + // wrong layout let _ = transmute::<_, HashMap>(HashMap::::new()); - //~^ ERROR: transmute from `std::collections::HashMap` to `std::colle + //~^ unsound_collection_transmute + let _ = transmute::<_, HashMap>(HashMap::<[u8; 4], u32>::new()); - //~^ ERROR: transmute from `std::collections::HashMap<[u8; 4], u32>` to `std::coll + //~^ unsound_collection_transmute let _ = transmute::<_, Vec>(Vec::>::new()); let _ = transmute::<_, Vec<*mut u32>>(Vec::>::new()); diff --git a/tests/ui/transmute_collection.stderr b/tests/ui/transmute_collection.stderr index 06db9321064b..ac2de07f6bf2 100644 --- a/tests/ui/transmute_collection.stderr +++ b/tests/ui/transmute_collection.stderr @@ -20,91 +20,91 @@ LL | let _ = transmute::<_, VecDeque>(VecDeque::::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::VecDeque<[u8; 4]>` to `std::collections::VecDeque` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:21:17 + --> tests/ui/transmute_collection.rs:22:17 | LL | let _ = transmute::<_, VecDeque>(VecDeque::<[u8; 4]>::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::BinaryHeap` to `std::collections::BinaryHeap` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:25:17 + --> tests/ui/transmute_collection.rs:26:17 | LL | let _ = transmute::<_, BinaryHeap>(BinaryHeap::::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::BinaryHeap<[u8; 4]>` to `std::collections::BinaryHeap` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:28:17 + --> tests/ui/transmute_collection.rs:30:17 | LL | let _ = transmute::<_, BinaryHeap>(BinaryHeap::<[u8; 4]>::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::BTreeSet` to `std::collections::BTreeSet` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:32:17 + --> tests/ui/transmute_collection.rs:34:17 | LL | let _ = transmute::<_, BTreeSet>(BTreeSet::::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::BTreeSet<[u8; 4]>` to `std::collections::BTreeSet` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:35:17 + --> tests/ui/transmute_collection.rs:38:17 | LL | let _ = transmute::<_, BTreeSet>(BTreeSet::<[u8; 4]>::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::HashSet` to `std::collections::HashSet` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:39:17 + --> tests/ui/transmute_collection.rs:42:17 | LL | let _ = transmute::<_, HashSet>(HashSet::::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::HashSet<[u8; 4]>` to `std::collections::HashSet` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:42:17 + --> tests/ui/transmute_collection.rs:46:17 | LL | let _ = transmute::<_, HashSet>(HashSet::<[u8; 4]>::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::BTreeMap` to `std::collections::BTreeMap` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:46:17 + --> tests/ui/transmute_collection.rs:50:17 | LL | let _ = transmute::<_, BTreeMap>(BTreeMap::::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::BTreeMap` to `std::collections::BTreeMap` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:48:17 + --> tests/ui/transmute_collection.rs:53:17 | LL | let _ = transmute::<_, BTreeMap>(BTreeMap::::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::BTreeMap` to `std::collections::BTreeMap` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:51:17 + --> tests/ui/transmute_collection.rs:57:17 | LL | let _ = transmute::<_, BTreeMap>(BTreeMap::::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::BTreeMap<[u8; 4], u32>` to `std::collections::BTreeMap` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:53:17 + --> tests/ui/transmute_collection.rs:60:17 | LL | let _ = transmute::<_, BTreeMap>(BTreeMap::<[u8; 4], u32>::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::HashMap` to `std::collections::HashMap` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:57:17 + --> tests/ui/transmute_collection.rs:64:17 | LL | let _ = transmute::<_, HashMap>(HashMap::::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::HashMap` to `std::collections::HashMap` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:59:17 + --> tests/ui/transmute_collection.rs:67:17 | LL | let _ = transmute::<_, HashMap>(HashMap::::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::HashMap` to `std::collections::HashMap` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:62:17 + --> tests/ui/transmute_collection.rs:71:17 | LL | let _ = transmute::<_, HashMap>(HashMap::::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from `std::collections::HashMap<[u8; 4], u32>` to `std::collections::HashMap` with mismatched layout is unsound - --> tests/ui/transmute_collection.rs:64:17 + --> tests/ui/transmute_collection.rs:74:17 | LL | let _ = transmute::<_, HashMap>(HashMap::<[u8; 4], u32>::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/transmute_float_to_int.fixed b/tests/ui/transmute_float_to_int.fixed index 075a198918a0..1f97b997eaa0 100644 --- a/tests/ui/transmute_float_to_int.fixed +++ b/tests/ui/transmute_float_to_int.fixed @@ -5,48 +5,55 @@ fn float_to_int() { let _: u32 = unsafe { 1f32.to_bits() }; - //~^ ERROR: transmute from a `f32` to a `u32` - //~| NOTE: `-D clippy::transmute-float-to-int` implied by `-D warnings` + //~^ transmute_float_to_int + let _: i32 = unsafe { 1f32.to_bits() as i32 }; - //~^ ERROR: transmute from a `f32` to a `i32` + //~^ transmute_float_to_int + let _: u64 = unsafe { 1f64.to_bits() }; - //~^ ERROR: transmute from a `f64` to a `u64` + //~^ transmute_float_to_int + let _: i64 = unsafe { 1f64.to_bits() as i64 }; - //~^ ERROR: transmute from a `f64` to a `i64` + //~^ transmute_float_to_int + let _: u64 = unsafe { 1.0f64.to_bits() }; - //~^ ERROR: transmute from a `f64` to a `u64` + //~^ transmute_float_to_int + let _: u64 = unsafe { (-1.0f64).to_bits() }; - //~^ ERROR: transmute from a `f64` to a `u64` + //~^ transmute_float_to_int } mod issue_5747 { const VALUE16: i16 = unsafe { 1f16.to_bits() as i16 }; - //~^ ERROR: transmute from a `f16` to a `i16` + //~^ transmute_float_to_int + const VALUE32: i32 = unsafe { 1f32.to_bits() as i32 }; - //~^ ERROR: transmute from a `f32` to a `i32` + //~^ transmute_float_to_int + const VALUE64: u64 = unsafe { 1f64.to_bits() }; - //~^ ERROR: transmute from a `f64` to a `u64` + //~^ transmute_float_to_int + const VALUE128: u128 = unsafe { 1f128.to_bits() }; - //~^ ERROR: transmute from a `f128` to a `u128` + //~^ transmute_float_to_int const fn to_bits_16(v: f16) -> u16 { unsafe { v.to_bits() } - //~^ ERROR: transmute from a `f16` to a `u16` + //~^ transmute_float_to_int } const fn to_bits_32(v: f32) -> u32 { unsafe { v.to_bits() } - //~^ ERROR: transmute from a `f32` to a `u32` + //~^ transmute_float_to_int } const fn to_bits_64(v: f64) -> i64 { unsafe { v.to_bits() as i64 } - //~^ ERROR: transmute from a `f64` to a `i64` + //~^ transmute_float_to_int } const fn to_bits_128(v: f128) -> i128 { unsafe { v.to_bits() as i128 } - //~^ ERROR: transmute from a `f128` to a `i128` + //~^ transmute_float_to_int } } diff --git a/tests/ui/transmute_float_to_int.rs b/tests/ui/transmute_float_to_int.rs index 12541b2f7cf3..788a7e1026c6 100644 --- a/tests/ui/transmute_float_to_int.rs +++ b/tests/ui/transmute_float_to_int.rs @@ -5,48 +5,55 @@ fn float_to_int() { let _: u32 = unsafe { std::mem::transmute(1f32) }; - //~^ ERROR: transmute from a `f32` to a `u32` - //~| NOTE: `-D clippy::transmute-float-to-int` implied by `-D warnings` + //~^ transmute_float_to_int + let _: i32 = unsafe { std::mem::transmute(1f32) }; - //~^ ERROR: transmute from a `f32` to a `i32` + //~^ transmute_float_to_int + let _: u64 = unsafe { std::mem::transmute(1f64) }; - //~^ ERROR: transmute from a `f64` to a `u64` + //~^ transmute_float_to_int + let _: i64 = unsafe { std::mem::transmute(1f64) }; - //~^ ERROR: transmute from a `f64` to a `i64` + //~^ transmute_float_to_int + let _: u64 = unsafe { std::mem::transmute(1.0) }; - //~^ ERROR: transmute from a `f64` to a `u64` + //~^ transmute_float_to_int + let _: u64 = unsafe { std::mem::transmute(-1.0) }; - //~^ ERROR: transmute from a `f64` to a `u64` + //~^ transmute_float_to_int } mod issue_5747 { const VALUE16: i16 = unsafe { std::mem::transmute(1f16) }; - //~^ ERROR: transmute from a `f16` to a `i16` + //~^ transmute_float_to_int + const VALUE32: i32 = unsafe { std::mem::transmute(1f32) }; - //~^ ERROR: transmute from a `f32` to a `i32` + //~^ transmute_float_to_int + const VALUE64: u64 = unsafe { std::mem::transmute(1f64) }; - //~^ ERROR: transmute from a `f64` to a `u64` + //~^ transmute_float_to_int + const VALUE128: u128 = unsafe { std::mem::transmute(1f128) }; - //~^ ERROR: transmute from a `f128` to a `u128` + //~^ transmute_float_to_int const fn to_bits_16(v: f16) -> u16 { unsafe { std::mem::transmute(v) } - //~^ ERROR: transmute from a `f16` to a `u16` + //~^ transmute_float_to_int } const fn to_bits_32(v: f32) -> u32 { unsafe { std::mem::transmute(v) } - //~^ ERROR: transmute from a `f32` to a `u32` + //~^ transmute_float_to_int } const fn to_bits_64(v: f64) -> i64 { unsafe { std::mem::transmute(v) } - //~^ ERROR: transmute from a `f64` to a `i64` + //~^ transmute_float_to_int } const fn to_bits_128(v: f128) -> i128 { unsafe { std::mem::transmute(v) } - //~^ ERROR: transmute from a `f128` to a `i128` + //~^ transmute_float_to_int } } diff --git a/tests/ui/transmute_float_to_int.stderr b/tests/ui/transmute_float_to_int.stderr index 0cabab58ab08..223cbc4e90c0 100644 --- a/tests/ui/transmute_float_to_int.stderr +++ b/tests/ui/transmute_float_to_int.stderr @@ -14,73 +14,73 @@ LL | let _: i32 = unsafe { std::mem::transmute(1f32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f32.to_bits() as i32` error: transmute from a `f64` to a `u64` - --> tests/ui/transmute_float_to_int.rs:12:27 + --> tests/ui/transmute_float_to_int.rs:13:27 | LL | let _: u64 = unsafe { std::mem::transmute(1f64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f64.to_bits()` error: transmute from a `f64` to a `i64` - --> tests/ui/transmute_float_to_int.rs:14:27 + --> tests/ui/transmute_float_to_int.rs:16:27 | LL | let _: i64 = unsafe { std::mem::transmute(1f64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f64.to_bits() as i64` error: transmute from a `f64` to a `u64` - --> tests/ui/transmute_float_to_int.rs:16:27 + --> tests/ui/transmute_float_to_int.rs:19:27 | LL | let _: u64 = unsafe { std::mem::transmute(1.0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1.0f64.to_bits()` error: transmute from a `f64` to a `u64` - --> tests/ui/transmute_float_to_int.rs:18:27 + --> tests/ui/transmute_float_to_int.rs:22:27 | LL | let _: u64 = unsafe { std::mem::transmute(-1.0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-1.0f64).to_bits()` error: transmute from a `f16` to a `i16` - --> tests/ui/transmute_float_to_int.rs:23:35 + --> tests/ui/transmute_float_to_int.rs:27:35 | LL | const VALUE16: i16 = unsafe { std::mem::transmute(1f16) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f16.to_bits() as i16` error: transmute from a `f32` to a `i32` - --> tests/ui/transmute_float_to_int.rs:25:35 + --> tests/ui/transmute_float_to_int.rs:30:35 | LL | const VALUE32: i32 = unsafe { std::mem::transmute(1f32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f32.to_bits() as i32` error: transmute from a `f64` to a `u64` - --> tests/ui/transmute_float_to_int.rs:27:35 + --> tests/ui/transmute_float_to_int.rs:33:35 | LL | const VALUE64: u64 = unsafe { std::mem::transmute(1f64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f64.to_bits()` error: transmute from a `f128` to a `u128` - --> tests/ui/transmute_float_to_int.rs:29:37 + --> tests/ui/transmute_float_to_int.rs:36:37 | LL | const VALUE128: u128 = unsafe { std::mem::transmute(1f128) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f128.to_bits()` error: transmute from a `f16` to a `u16` - --> tests/ui/transmute_float_to_int.rs:33:18 + --> tests/ui/transmute_float_to_int.rs:40:18 | LL | unsafe { std::mem::transmute(v) } | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits()` error: transmute from a `f32` to a `u32` - --> tests/ui/transmute_float_to_int.rs:38:18 + --> tests/ui/transmute_float_to_int.rs:45:18 | LL | unsafe { std::mem::transmute(v) } | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits()` error: transmute from a `f64` to a `i64` - --> tests/ui/transmute_float_to_int.rs:43:18 + --> tests/ui/transmute_float_to_int.rs:50:18 | LL | unsafe { std::mem::transmute(v) } | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits() as i64` error: transmute from a `f128` to a `i128` - --> tests/ui/transmute_float_to_int.rs:48:18 + --> tests/ui/transmute_float_to_int.rs:55:18 | LL | unsafe { std::mem::transmute(v) } | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits() as i128` diff --git a/tests/ui/transmute_int_to_char.fixed b/tests/ui/transmute_int_to_char.fixed index d3277d1b8c73..b5425a2e9e85 100644 --- a/tests/ui/transmute_int_to_char.fixed +++ b/tests/ui/transmute_int_to_char.fixed @@ -3,10 +3,10 @@ fn int_to_char() { let _: char = unsafe { std::char::from_u32(0_u32).unwrap() }; - //~^ ERROR: transmute from a `u32` to a `char` - //~| NOTE: `-D clippy::transmute-int-to-char` implied by `-D warnings` + //~^ transmute_int_to_char + let _: char = unsafe { std::char::from_u32(0_i32 as u32).unwrap() }; - //~^ ERROR: transmute from a `i32` to a `char` + //~^ transmute_int_to_char // These shouldn't warn const _: char = unsafe { std::mem::transmute(0_u32) }; diff --git a/tests/ui/transmute_int_to_char.rs b/tests/ui/transmute_int_to_char.rs index d21c4fd6fea3..b24bb177c9fc 100644 --- a/tests/ui/transmute_int_to_char.rs +++ b/tests/ui/transmute_int_to_char.rs @@ -3,10 +3,10 @@ fn int_to_char() { let _: char = unsafe { std::mem::transmute(0_u32) }; - //~^ ERROR: transmute from a `u32` to a `char` - //~| NOTE: `-D clippy::transmute-int-to-char` implied by `-D warnings` + //~^ transmute_int_to_char + let _: char = unsafe { std::mem::transmute(0_i32) }; - //~^ ERROR: transmute from a `i32` to a `char` + //~^ transmute_int_to_char // These shouldn't warn const _: char = unsafe { std::mem::transmute(0_u32) }; diff --git a/tests/ui/transmute_int_to_char_no_std.fixed b/tests/ui/transmute_int_to_char_no_std.fixed index 32a57645b46f..e525751e306e 100644 --- a/tests/ui/transmute_int_to_char_no_std.fixed +++ b/tests/ui/transmute_int_to_char_no_std.fixed @@ -15,10 +15,10 @@ fn panic(info: &PanicInfo) -> ! { fn int_to_char() { let _: char = unsafe { core::char::from_u32(0_u32).unwrap() }; - //~^ ERROR: transmute from a `u32` to a `char` - //~| NOTE: `-D clippy::transmute-int-to-char` implied by `-D warnings` + //~^ transmute_int_to_char + let _: char = unsafe { core::char::from_u32(0_i32 as u32).unwrap() }; - //~^ ERROR: transmute from a `i32` to a `char` + //~^ transmute_int_to_char // These shouldn't warn const _: char = unsafe { core::mem::transmute(0_u32) }; diff --git a/tests/ui/transmute_int_to_char_no_std.rs b/tests/ui/transmute_int_to_char_no_std.rs index 942794c32f81..7cb508ceaf3b 100644 --- a/tests/ui/transmute_int_to_char_no_std.rs +++ b/tests/ui/transmute_int_to_char_no_std.rs @@ -15,10 +15,10 @@ fn panic(info: &PanicInfo) -> ! { fn int_to_char() { let _: char = unsafe { core::mem::transmute(0_u32) }; - //~^ ERROR: transmute from a `u32` to a `char` - //~| NOTE: `-D clippy::transmute-int-to-char` implied by `-D warnings` + //~^ transmute_int_to_char + let _: char = unsafe { core::mem::transmute(0_i32) }; - //~^ ERROR: transmute from a `i32` to a `char` + //~^ transmute_int_to_char // These shouldn't warn const _: char = unsafe { core::mem::transmute(0_u32) }; diff --git a/tests/ui/transmute_int_to_non_zero.fixed b/tests/ui/transmute_int_to_non_zero.fixed index 1a48051ec8c4..273090fef387 100644 --- a/tests/ui/transmute_int_to_non_zero.fixed +++ b/tests/ui/transmute_int_to_non_zero.fixed @@ -17,27 +17,34 @@ fn main() { let int_i128: i128 = 1; let _: NonZero = unsafe { NonZero::new_unchecked(int_u8) }; - //~^ ERROR: transmute from a `u8` to a `NonZero` - //~| NOTE: `-D clippy::transmute-int-to-non-zero` implied by `-D warnings` + //~^ transmute_int_to_non_zero + let _: NonZero = unsafe { NonZero::new_unchecked(int_u16) }; - //~^ ERROR: transmute from a `u16` to a `NonZero` + //~^ transmute_int_to_non_zero + let _: NonZero = unsafe { NonZero::new_unchecked(int_u32) }; - //~^ ERROR: transmute from a `u32` to a `NonZero` + //~^ transmute_int_to_non_zero + let _: NonZero = unsafe { NonZero::new_unchecked(int_u64) }; - //~^ ERROR: transmute from a `u64` to a `NonZero` + //~^ transmute_int_to_non_zero + let _: NonZero = unsafe { NonZero::new_unchecked(int_u128) }; - //~^ ERROR: transmute from a `u128` to a `NonZero` + //~^ transmute_int_to_non_zero let _: NonZero = unsafe { NonZero::new_unchecked(int_i8) }; - //~^ ERROR: transmute from a `i8` to a `NonZero` + //~^ transmute_int_to_non_zero + let _: NonZero = unsafe { NonZero::new_unchecked(int_i16) }; - //~^ ERROR: transmute from a `i16` to a `NonZero` + //~^ transmute_int_to_non_zero + let _: NonZero = unsafe { NonZero::new_unchecked(int_i32) }; - //~^ ERROR: transmute from a `i32` to a `NonZero` + //~^ transmute_int_to_non_zero + let _: NonZero = unsafe { NonZero::new_unchecked(int_i64) }; - //~^ ERROR: transmute from a `i64` to a `NonZero` + //~^ transmute_int_to_non_zero + let _: NonZero = unsafe { NonZero::new_unchecked(int_i128) }; - //~^ ERROR: transmute from a `i128` to a `NonZero` + //~^ transmute_int_to_non_zero let _: NonZero = unsafe { NonZero::new_unchecked(int_u8) }; let _: NonZero = unsafe { NonZero::new_unchecked(int_u16) }; diff --git a/tests/ui/transmute_int_to_non_zero.rs b/tests/ui/transmute_int_to_non_zero.rs index d8e842fb99ce..f27bc9b42d42 100644 --- a/tests/ui/transmute_int_to_non_zero.rs +++ b/tests/ui/transmute_int_to_non_zero.rs @@ -17,27 +17,34 @@ fn main() { let int_i128: i128 = 1; let _: NonZero = unsafe { std::mem::transmute(int_u8) }; - //~^ ERROR: transmute from a `u8` to a `NonZero` - //~| NOTE: `-D clippy::transmute-int-to-non-zero` implied by `-D warnings` + //~^ transmute_int_to_non_zero + let _: NonZero = unsafe { std::mem::transmute(int_u16) }; - //~^ ERROR: transmute from a `u16` to a `NonZero` + //~^ transmute_int_to_non_zero + let _: NonZero = unsafe { std::mem::transmute(int_u32) }; - //~^ ERROR: transmute from a `u32` to a `NonZero` + //~^ transmute_int_to_non_zero + let _: NonZero = unsafe { std::mem::transmute(int_u64) }; - //~^ ERROR: transmute from a `u64` to a `NonZero` + //~^ transmute_int_to_non_zero + let _: NonZero = unsafe { std::mem::transmute(int_u128) }; - //~^ ERROR: transmute from a `u128` to a `NonZero` + //~^ transmute_int_to_non_zero let _: NonZero = unsafe { std::mem::transmute(int_i8) }; - //~^ ERROR: transmute from a `i8` to a `NonZero` + //~^ transmute_int_to_non_zero + let _: NonZero = unsafe { std::mem::transmute(int_i16) }; - //~^ ERROR: transmute from a `i16` to a `NonZero` + //~^ transmute_int_to_non_zero + let _: NonZero = unsafe { std::mem::transmute(int_i32) }; - //~^ ERROR: transmute from a `i32` to a `NonZero` + //~^ transmute_int_to_non_zero + let _: NonZero = unsafe { std::mem::transmute(int_i64) }; - //~^ ERROR: transmute from a `i64` to a `NonZero` + //~^ transmute_int_to_non_zero + let _: NonZero = unsafe { std::mem::transmute(int_i128) }; - //~^ ERROR: transmute from a `i128` to a `NonZero` + //~^ transmute_int_to_non_zero let _: NonZero = unsafe { NonZero::new_unchecked(int_u8) }; let _: NonZero = unsafe { NonZero::new_unchecked(int_u16) }; diff --git a/tests/ui/transmute_int_to_non_zero.stderr b/tests/ui/transmute_int_to_non_zero.stderr index 199b8ec59d09..995ab11a5bc9 100644 --- a/tests/ui/transmute_int_to_non_zero.stderr +++ b/tests/ui/transmute_int_to_non_zero.stderr @@ -14,49 +14,49 @@ LL | let _: NonZero = unsafe { std::mem::transmute(int_u16) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZero::new_unchecked(int_u16)` error: transmute from a `u32` to a `NonZero` - --> tests/ui/transmute_int_to_non_zero.rs:24:36 + --> tests/ui/transmute_int_to_non_zero.rs:25:36 | LL | let _: NonZero = unsafe { std::mem::transmute(int_u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZero::new_unchecked(int_u32)` error: transmute from a `u64` to a `NonZero` - --> tests/ui/transmute_int_to_non_zero.rs:26:36 + --> tests/ui/transmute_int_to_non_zero.rs:28:36 | LL | let _: NonZero = unsafe { std::mem::transmute(int_u64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZero::new_unchecked(int_u64)` error: transmute from a `u128` to a `NonZero` - --> tests/ui/transmute_int_to_non_zero.rs:28:37 + --> tests/ui/transmute_int_to_non_zero.rs:31:37 | LL | let _: NonZero = unsafe { std::mem::transmute(int_u128) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZero::new_unchecked(int_u128)` error: transmute from a `i8` to a `NonZero` - --> tests/ui/transmute_int_to_non_zero.rs:31:35 + --> tests/ui/transmute_int_to_non_zero.rs:34:35 | LL | let _: NonZero = unsafe { std::mem::transmute(int_i8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZero::new_unchecked(int_i8)` error: transmute from a `i16` to a `NonZero` - --> tests/ui/transmute_int_to_non_zero.rs:33:36 + --> tests/ui/transmute_int_to_non_zero.rs:37:36 | LL | let _: NonZero = unsafe { std::mem::transmute(int_i16) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZero::new_unchecked(int_i16)` error: transmute from a `i32` to a `NonZero` - --> tests/ui/transmute_int_to_non_zero.rs:35:36 + --> tests/ui/transmute_int_to_non_zero.rs:40:36 | LL | let _: NonZero = unsafe { std::mem::transmute(int_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZero::new_unchecked(int_i32)` error: transmute from a `i64` to a `NonZero` - --> tests/ui/transmute_int_to_non_zero.rs:37:36 + --> tests/ui/transmute_int_to_non_zero.rs:43:36 | LL | let _: NonZero = unsafe { std::mem::transmute(int_i64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZero::new_unchecked(int_i64)` error: transmute from a `i128` to a `NonZero` - --> tests/ui/transmute_int_to_non_zero.rs:39:37 + --> tests/ui/transmute_int_to_non_zero.rs:46:37 | LL | let _: NonZero = unsafe { std::mem::transmute(int_i128) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZero::new_unchecked(int_i128)` diff --git a/tests/ui/transmute_null_to_fn.rs b/tests/ui/transmute_null_to_fn.rs index c0196ad52d43..e88f05bb662e 100644 --- a/tests/ui/transmute_null_to_fn.rs +++ b/tests/ui/transmute_null_to_fn.rs @@ -6,9 +6,10 @@ fn one_liners() { unsafe { let _: fn() = std::mem::transmute(0 as *const ()); - //~^ ERROR: transmuting a known null pointer into a function pointer + //~^ transmute_null_to_fn + let _: fn() = std::mem::transmute(std::ptr::null::<()>()); - //~^ ERROR: transmuting a known null pointer into a function pointer + //~^ transmute_null_to_fn } } @@ -19,7 +20,8 @@ fn transmute_const() { unsafe { // Should raise a lint. let _: fn() = std::mem::transmute(ZPTR); - //~^ ERROR: transmuting a known null pointer into a function pointer + //~^ transmute_null_to_fn + // Should NOT raise a lint. let _: fn() = std::mem::transmute(NOT_ZPTR); } @@ -28,11 +30,13 @@ fn transmute_const() { fn issue_11485() { unsafe { let _: fn() = std::mem::transmute(0 as *const u8 as *const ()); - //~^ ERROR: transmuting a known null pointer into a function pointer + //~^ transmute_null_to_fn + let _: fn() = std::mem::transmute(std::ptr::null::<()>() as *const u8); - //~^ ERROR: transmuting a known null pointer into a function pointer + //~^ transmute_null_to_fn + let _: fn() = std::mem::transmute(ZPTR as *const u8); - //~^ ERROR: transmuting a known null pointer into a function pointer + //~^ transmute_null_to_fn } } diff --git a/tests/ui/transmute_null_to_fn.stderr b/tests/ui/transmute_null_to_fn.stderr index cea7b42cb801..f7d80147445d 100644 --- a/tests/ui/transmute_null_to_fn.stderr +++ b/tests/ui/transmute_null_to_fn.stderr @@ -9,7 +9,7 @@ LL | let _: fn() = std::mem::transmute(0 as *const ()); = help: to override `-D warnings` add `#[allow(clippy::transmute_null_to_fn)]` error: transmuting a known null pointer into a function pointer - --> tests/ui/transmute_null_to_fn.rs:10:23 + --> tests/ui/transmute_null_to_fn.rs:11:23 | LL | let _: fn() = std::mem::transmute(std::ptr::null::<()>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior @@ -17,7 +17,7 @@ LL | let _: fn() = std::mem::transmute(std::ptr::null::<()>()); = help: try wrapping your function pointer type in `Option` instead, and using `None` as a null pointer value error: transmuting a known null pointer into a function pointer - --> tests/ui/transmute_null_to_fn.rs:21:23 + --> tests/ui/transmute_null_to_fn.rs:22:23 | LL | let _: fn() = std::mem::transmute(ZPTR); | ^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior @@ -25,7 +25,7 @@ LL | let _: fn() = std::mem::transmute(ZPTR); = help: try wrapping your function pointer type in `Option` instead, and using `None` as a null pointer value error: transmuting a known null pointer into a function pointer - --> tests/ui/transmute_null_to_fn.rs:30:23 + --> tests/ui/transmute_null_to_fn.rs:32:23 | LL | let _: fn() = std::mem::transmute(0 as *const u8 as *const ()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior @@ -33,7 +33,7 @@ LL | let _: fn() = std::mem::transmute(0 as *const u8 as *const ()); = help: try wrapping your function pointer type in `Option` instead, and using `None` as a null pointer value error: transmuting a known null pointer into a function pointer - --> tests/ui/transmute_null_to_fn.rs:32:23 + --> tests/ui/transmute_null_to_fn.rs:35:23 | LL | let _: fn() = std::mem::transmute(std::ptr::null::<()>() as *const u8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior @@ -41,7 +41,7 @@ LL | let _: fn() = std::mem::transmute(std::ptr::null::<()>() as *const = help: try wrapping your function pointer type in `Option` instead, and using `None` as a null pointer value error: transmuting a known null pointer into a function pointer - --> tests/ui/transmute_null_to_fn.rs:34:23 + --> tests/ui/transmute_null_to_fn.rs:38:23 | LL | let _: fn() = std::mem::transmute(ZPTR as *const u8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior diff --git a/tests/ui/transmute_ptr_to_ptr.fixed b/tests/ui/transmute_ptr_to_ptr.fixed index 39e67b250526..3a67be5f45d0 100644 --- a/tests/ui/transmute_ptr_to_ptr.fixed +++ b/tests/ui/transmute_ptr_to_ptr.fixed @@ -31,24 +31,32 @@ fn transmute_ptr_to_ptr() { // pointer-to-pointer transmutes; bad let _: *const f32 = ptr.cast::(); //~^ transmute_ptr_to_ptr + let _: *mut f32 = mut_ptr.cast::(); //~^ transmute_ptr_to_ptr + // ref-ref transmutes; bad let _: &f32 = &*(&1u32 as *const u32 as *const f32); //~^ transmute_ptr_to_ptr + let _: &f32 = &*(&1f64 as *const f64 as *const f32); //~^ transmute_ptr_to_ptr + //:^ this test is here because both f32 and f64 are the same TypeVariant, but they are not // the same type let _: &mut f32 = &mut *(&mut 1u32 as *mut u32 as *mut f32); //~^ transmute_ptr_to_ptr + let _: &GenericParam = &*(&GenericParam { t: 1u32 } as *const GenericParam as *const GenericParam); //~^ transmute_ptr_to_ptr + let u64_ref: &u64 = &0u64; let u8_ref: &u8 = &*(u64_ref as *const u64 as *const u8); //~^ transmute_ptr_to_ptr + let _: *const u32 = mut_ptr.cast_const(); //~^ transmute_ptr_to_ptr + let _: *mut u32 = ptr.cast_mut(); //~^ transmute_ptr_to_ptr } @@ -77,6 +85,7 @@ const _: &() = { fn msrv_1_37(ptr: *const u8) { unsafe { let _: *const i8 = ptr as *const i8; + //~^ transmute_ptr_to_ptr } } @@ -84,6 +93,7 @@ fn msrv_1_37(ptr: *const u8) { fn msrv_1_38(ptr: *const u8) { unsafe { let _: *const i8 = ptr.cast::(); + //~^ transmute_ptr_to_ptr } } @@ -91,7 +101,9 @@ fn msrv_1_38(ptr: *const u8) { fn msrv_1_64(ptr: *const u8, mut_ptr: *mut u8) { unsafe { let _: *mut u8 = ptr as *mut u8; + //~^ transmute_ptr_to_ptr let _: *const u8 = mut_ptr as *const u8; + //~^ transmute_ptr_to_ptr } } @@ -99,7 +111,9 @@ fn msrv_1_64(ptr: *const u8, mut_ptr: *mut u8) { fn msrv_1_65(ptr: *const u8, mut_ptr: *mut u8) { unsafe { let _: *mut u8 = ptr.cast_mut(); + //~^ transmute_ptr_to_ptr let _: *const u8 = mut_ptr.cast_const(); + //~^ transmute_ptr_to_ptr } } diff --git a/tests/ui/transmute_ptr_to_ptr.rs b/tests/ui/transmute_ptr_to_ptr.rs index 580b28551734..01ad3a3296b1 100644 --- a/tests/ui/transmute_ptr_to_ptr.rs +++ b/tests/ui/transmute_ptr_to_ptr.rs @@ -31,24 +31,32 @@ fn transmute_ptr_to_ptr() { // pointer-to-pointer transmutes; bad let _: *const f32 = transmute(ptr); //~^ transmute_ptr_to_ptr + let _: *mut f32 = transmute(mut_ptr); //~^ transmute_ptr_to_ptr + // ref-ref transmutes; bad let _: &f32 = transmute(&1u32); //~^ transmute_ptr_to_ptr + let _: &f32 = transmute(&1f64); //~^ transmute_ptr_to_ptr + //:^ this test is here because both f32 and f64 are the same TypeVariant, but they are not // the same type let _: &mut f32 = transmute(&mut 1u32); //~^ transmute_ptr_to_ptr + let _: &GenericParam = transmute(&GenericParam { t: 1u32 }); //~^ transmute_ptr_to_ptr + let u64_ref: &u64 = &0u64; let u8_ref: &u8 = transmute(u64_ref); //~^ transmute_ptr_to_ptr + let _: *const u32 = transmute(mut_ptr); //~^ transmute_ptr_to_ptr + let _: *mut u32 = transmute(ptr); //~^ transmute_ptr_to_ptr } @@ -77,6 +85,7 @@ const _: &() = { fn msrv_1_37(ptr: *const u8) { unsafe { let _: *const i8 = transmute(ptr); + //~^ transmute_ptr_to_ptr } } @@ -84,6 +93,7 @@ fn msrv_1_37(ptr: *const u8) { fn msrv_1_38(ptr: *const u8) { unsafe { let _: *const i8 = transmute(ptr); + //~^ transmute_ptr_to_ptr } } @@ -91,7 +101,9 @@ fn msrv_1_38(ptr: *const u8) { fn msrv_1_64(ptr: *const u8, mut_ptr: *mut u8) { unsafe { let _: *mut u8 = transmute(ptr); + //~^ transmute_ptr_to_ptr let _: *const u8 = transmute(mut_ptr); + //~^ transmute_ptr_to_ptr } } @@ -99,7 +111,9 @@ fn msrv_1_64(ptr: *const u8, mut_ptr: *mut u8) { fn msrv_1_65(ptr: *const u8, mut_ptr: *mut u8) { unsafe { let _: *mut u8 = transmute(ptr); + //~^ transmute_ptr_to_ptr let _: *const u8 = transmute(mut_ptr); + //~^ transmute_ptr_to_ptr } } diff --git a/tests/ui/transmute_ptr_to_ptr.stderr b/tests/ui/transmute_ptr_to_ptr.stderr index f4f83cd7ac6a..c8db4fe214fd 100644 --- a/tests/ui/transmute_ptr_to_ptr.stderr +++ b/tests/ui/transmute_ptr_to_ptr.stderr @@ -13,7 +13,7 @@ LL + let _: *const f32 = ptr.cast::(); | error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:34:27 + --> tests/ui/transmute_ptr_to_ptr.rs:35:27 | LL | let _: *mut f32 = transmute(mut_ptr); | ^^^^^^^^^^^^^^^^^^ @@ -25,37 +25,37 @@ LL + let _: *mut f32 = mut_ptr.cast::(); | error: transmute from a reference to a reference - --> tests/ui/transmute_ptr_to_ptr.rs:37:23 + --> tests/ui/transmute_ptr_to_ptr.rs:39:23 | LL | let _: &f32 = transmute(&1u32); | ^^^^^^^^^^^^^^^^ help: try: `&*(&1u32 as *const u32 as *const f32)` error: transmute from a reference to a reference - --> tests/ui/transmute_ptr_to_ptr.rs:39:23 + --> tests/ui/transmute_ptr_to_ptr.rs:42:23 | LL | let _: &f32 = transmute(&1f64); | ^^^^^^^^^^^^^^^^ help: try: `&*(&1f64 as *const f64 as *const f32)` error: transmute from a reference to a reference - --> tests/ui/transmute_ptr_to_ptr.rs:43:27 + --> tests/ui/transmute_ptr_to_ptr.rs:47:27 | LL | let _: &mut f32 = transmute(&mut 1u32); | ^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(&mut 1u32 as *mut u32 as *mut f32)` error: transmute from a reference to a reference - --> tests/ui/transmute_ptr_to_ptr.rs:45:37 + --> tests/ui/transmute_ptr_to_ptr.rs:50:37 | LL | let _: &GenericParam = transmute(&GenericParam { t: 1u32 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&GenericParam { t: 1u32 } as *const GenericParam as *const GenericParam)` error: transmute from a reference to a reference - --> tests/ui/transmute_ptr_to_ptr.rs:48:27 + --> tests/ui/transmute_ptr_to_ptr.rs:54:27 | LL | let u8_ref: &u8 = transmute(u64_ref); | ^^^^^^^^^^^^^^^^^^ help: try: `&*(u64_ref as *const u64 as *const u8)` error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:50:29 + --> tests/ui/transmute_ptr_to_ptr.rs:57:29 | LL | let _: *const u32 = transmute(mut_ptr); | ^^^^^^^^^^^^^^^^^^ @@ -67,7 +67,7 @@ LL + let _: *const u32 = mut_ptr.cast_const(); | error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:52:27 + --> tests/ui/transmute_ptr_to_ptr.rs:60:27 | LL | let _: *mut u32 = transmute(ptr); | ^^^^^^^^^^^^^^ @@ -79,7 +79,7 @@ LL + let _: *mut u32 = ptr.cast_mut(); | error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:64:14 + --> tests/ui/transmute_ptr_to_ptr.rs:72:14 | LL | unsafe { transmute(v) } | ^^^^^^^^^^^^ @@ -91,7 +91,7 @@ LL + unsafe { v as *const &() } | error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:79:28 + --> tests/ui/transmute_ptr_to_ptr.rs:87:28 | LL | let _: *const i8 = transmute(ptr); | ^^^^^^^^^^^^^^ @@ -103,7 +103,7 @@ LL + let _: *const i8 = ptr as *const i8; | error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:86:28 + --> tests/ui/transmute_ptr_to_ptr.rs:95:28 | LL | let _: *const i8 = transmute(ptr); | ^^^^^^^^^^^^^^ @@ -115,7 +115,7 @@ LL + let _: *const i8 = ptr.cast::(); | error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:93:26 + --> tests/ui/transmute_ptr_to_ptr.rs:103:26 | LL | let _: *mut u8 = transmute(ptr); | ^^^^^^^^^^^^^^ @@ -127,7 +127,7 @@ LL + let _: *mut u8 = ptr as *mut u8; | error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:94:28 + --> tests/ui/transmute_ptr_to_ptr.rs:105:28 | LL | let _: *const u8 = transmute(mut_ptr); | ^^^^^^^^^^^^^^^^^^ @@ -139,7 +139,7 @@ LL + let _: *const u8 = mut_ptr as *const u8; | error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:101:26 + --> tests/ui/transmute_ptr_to_ptr.rs:113:26 | LL | let _: *mut u8 = transmute(ptr); | ^^^^^^^^^^^^^^ @@ -151,7 +151,7 @@ LL + let _: *mut u8 = ptr.cast_mut(); | error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:102:28 + --> tests/ui/transmute_ptr_to_ptr.rs:115:28 | LL | let _: *const u8 = transmute(mut_ptr); | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/transmute_ptr_to_ref.fixed b/tests/ui/transmute_ptr_to_ref.fixed index 56330d719389..1bd45bc10a39 100644 --- a/tests/ui/transmute_ptr_to_ref.fixed +++ b/tests/ui/transmute_ptr_to_ref.fixed @@ -7,24 +7,31 @@ unsafe fn _ptr_to_ref(p: *const T, m: *mut T, o: *const U, om: *mut U) { let _: &T = &*p; + //~^ transmute_ptr_to_ref let _: &T = &*p; let _: &mut T = &mut *m; + //~^ transmute_ptr_to_ref let _: &mut T = &mut *m; let _: &T = &*m; + //~^ transmute_ptr_to_ref let _: &T = &*m; let _: &mut T = &mut *(p as *mut T); + //~^ transmute_ptr_to_ref let _ = &mut *(p as *mut T); let _: &T = &*(o as *const T); + //~^ transmute_ptr_to_ref let _: &T = &*(o as *const T); let _: &mut T = &mut *(om as *mut T); + //~^ transmute_ptr_to_ref let _: &mut T = &mut *(om as *mut T); let _: &T = &*(om as *const T); + //~^ transmute_ptr_to_ref let _: &T = &*(om as *const T); } @@ -35,20 +42,27 @@ fn _issue1231() { let raw = 42 as *const i32; let _: &Foo = unsafe { &*raw.cast::>() }; + //~^ transmute_ptr_to_ref let _: &Foo<&u8> = unsafe { &*raw.cast::>() }; + //~^ transmute_ptr_to_ref type Bar<'a> = &'a u8; let raw = 42 as *const i32; unsafe { &*(raw as *const u8) }; + //~^ transmute_ptr_to_ref } unsafe fn _issue8924<'a, 'b, 'c>(x: *const &'a u32, y: *const &'b u32) -> &'c &'b u32 { match 0 { 0 => &*x.cast::<&u32>(), + //~^ transmute_ptr_to_ref 1 => &*y.cast::<&u32>(), + //~^ transmute_ptr_to_ref 2 => &*x.cast::<&'b u32>(), + //~^ transmute_ptr_to_ref _ => &*y.cast::<&'b u32>(), + //~^ transmute_ptr_to_ref } } @@ -57,10 +71,14 @@ unsafe fn _meets_msrv<'a, 'b, 'c>(x: *const &'a u32) -> &'c &'b u32 { let a = 0u32; let a = &a as *const u32; let _: &u32 = &*a; + //~^ transmute_ptr_to_ref let _: &u32 = &*a.cast::(); + //~^ transmute_ptr_to_ref match 0 { 0 => &*x.cast::<&u32>(), + //~^ transmute_ptr_to_ref _ => &*x.cast::<&'b u32>(), + //~^ transmute_ptr_to_ref } } @@ -69,10 +87,14 @@ unsafe fn _under_msrv<'a, 'b, 'c>(x: *const &'a u32) -> &'c &'b u32 { let a = 0u32; let a = &a as *const u32; let _: &u32 = &*a; + //~^ transmute_ptr_to_ref let _: &u32 = &*(a as *const u32); + //~^ transmute_ptr_to_ref match 0 { 0 => &*(x as *const () as *const &u32), + //~^ transmute_ptr_to_ref _ => &*(x as *const () as *const &'b u32), + //~^ transmute_ptr_to_ref } } diff --git a/tests/ui/transmute_ptr_to_ref.rs b/tests/ui/transmute_ptr_to_ref.rs index ce1ee8bfbfae..cbe64bf1ea6b 100644 --- a/tests/ui/transmute_ptr_to_ref.rs +++ b/tests/ui/transmute_ptr_to_ref.rs @@ -7,24 +7,31 @@ unsafe fn _ptr_to_ref(p: *const T, m: *mut T, o: *const U, om: *mut U) { let _: &T = std::mem::transmute(p); + //~^ transmute_ptr_to_ref let _: &T = &*p; let _: &mut T = std::mem::transmute(m); + //~^ transmute_ptr_to_ref let _: &mut T = &mut *m; let _: &T = std::mem::transmute(m); + //~^ transmute_ptr_to_ref let _: &T = &*m; let _: &mut T = std::mem::transmute(p as *mut T); + //~^ transmute_ptr_to_ref let _ = &mut *(p as *mut T); let _: &T = std::mem::transmute(o); + //~^ transmute_ptr_to_ref let _: &T = &*(o as *const T); let _: &mut T = std::mem::transmute(om); + //~^ transmute_ptr_to_ref let _: &mut T = &mut *(om as *mut T); let _: &T = std::mem::transmute(om); + //~^ transmute_ptr_to_ref let _: &T = &*(om as *const T); } @@ -35,20 +42,27 @@ fn _issue1231() { let raw = 42 as *const i32; let _: &Foo = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) }; + //~^ transmute_ptr_to_ref let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) }; + //~^ transmute_ptr_to_ref type Bar<'a> = &'a u8; let raw = 42 as *const i32; unsafe { std::mem::transmute::<_, Bar>(raw) }; + //~^ transmute_ptr_to_ref } unsafe fn _issue8924<'a, 'b, 'c>(x: *const &'a u32, y: *const &'b u32) -> &'c &'b u32 { match 0 { 0 => std::mem::transmute(x), + //~^ transmute_ptr_to_ref 1 => std::mem::transmute(y), + //~^ transmute_ptr_to_ref 2 => std::mem::transmute::<_, &&'b u32>(x), + //~^ transmute_ptr_to_ref _ => std::mem::transmute::<_, &&'b u32>(y), + //~^ transmute_ptr_to_ref } } @@ -57,10 +71,14 @@ unsafe fn _meets_msrv<'a, 'b, 'c>(x: *const &'a u32) -> &'c &'b u32 { let a = 0u32; let a = &a as *const u32; let _: &u32 = std::mem::transmute(a); + //~^ transmute_ptr_to_ref let _: &u32 = std::mem::transmute::<_, &u32>(a); + //~^ transmute_ptr_to_ref match 0 { 0 => std::mem::transmute(x), + //~^ transmute_ptr_to_ref _ => std::mem::transmute::<_, &&'b u32>(x), + //~^ transmute_ptr_to_ref } } @@ -69,10 +87,14 @@ unsafe fn _under_msrv<'a, 'b, 'c>(x: *const &'a u32) -> &'c &'b u32 { let a = 0u32; let a = &a as *const u32; let _: &u32 = std::mem::transmute(a); + //~^ transmute_ptr_to_ref let _: &u32 = std::mem::transmute::<_, &u32>(a); + //~^ transmute_ptr_to_ref match 0 { 0 => std::mem::transmute(x), + //~^ transmute_ptr_to_ref _ => std::mem::transmute::<_, &&'b u32>(x), + //~^ transmute_ptr_to_ref } } diff --git a/tests/ui/transmute_ptr_to_ref.stderr b/tests/ui/transmute_ptr_to_ref.stderr index 44cda254c3f7..7fad9b4065a5 100644 --- a/tests/ui/transmute_ptr_to_ref.stderr +++ b/tests/ui/transmute_ptr_to_ref.stderr @@ -8,127 +8,127 @@ LL | let _: &T = std::mem::transmute(p); = help: to override `-D warnings` add `#[allow(clippy::transmute_ptr_to_ref)]` error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) - --> tests/ui/transmute_ptr_to_ref.rs:12:21 + --> tests/ui/transmute_ptr_to_ref.rs:13:21 | LL | let _: &mut T = std::mem::transmute(m); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *m` error: transmute from a pointer type (`*mut T`) to a reference type (`&T`) - --> tests/ui/transmute_ptr_to_ref.rs:15:17 + --> tests/ui/transmute_ptr_to_ref.rs:17:17 | LL | let _: &T = std::mem::transmute(m); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*m` error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`) - --> tests/ui/transmute_ptr_to_ref.rs:18:21 + --> tests/ui/transmute_ptr_to_ref.rs:21:21 | LL | let _: &mut T = std::mem::transmute(p as *mut T); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(p as *mut T)` error: transmute from a pointer type (`*const U`) to a reference type (`&T`) - --> tests/ui/transmute_ptr_to_ref.rs:21:17 + --> tests/ui/transmute_ptr_to_ref.rs:25:17 | LL | let _: &T = std::mem::transmute(o); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(o as *const T)` error: transmute from a pointer type (`*mut U`) to a reference type (`&mut T`) - --> tests/ui/transmute_ptr_to_ref.rs:24:21 + --> tests/ui/transmute_ptr_to_ref.rs:29:21 | LL | let _: &mut T = std::mem::transmute(om); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(om as *mut T)` error: transmute from a pointer type (`*mut U`) to a reference type (`&T`) - --> tests/ui/transmute_ptr_to_ref.rs:27:17 + --> tests/ui/transmute_ptr_to_ref.rs:33:17 | LL | let _: &T = std::mem::transmute(om); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(om as *const T)` error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, u8>`) - --> tests/ui/transmute_ptr_to_ref.rs:37:32 + --> tests/ui/transmute_ptr_to_ref.rs:44:32 | LL | let _: &Foo = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::>()` error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, &u8>`) - --> tests/ui/transmute_ptr_to_ref.rs:39:33 + --> tests/ui/transmute_ptr_to_ref.rs:47:33 | LL | let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::>()` error: transmute from a pointer type (`*const i32`) to a reference type (`&u8`) - --> tests/ui/transmute_ptr_to_ref.rs:43:14 + --> tests/ui/transmute_ptr_to_ref.rs:52:14 | LL | unsafe { std::mem::transmute::<_, Bar>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const u8)` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> tests/ui/transmute_ptr_to_ref.rs:48:14 + --> tests/ui/transmute_ptr_to_ref.rs:58:14 | LL | 0 => std::mem::transmute(x), | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> tests/ui/transmute_ptr_to_ref.rs:49:14 + --> tests/ui/transmute_ptr_to_ref.rs:60:14 | LL | 1 => std::mem::transmute(y), | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&u32>()` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> tests/ui/transmute_ptr_to_ref.rs:50:14 + --> tests/ui/transmute_ptr_to_ref.rs:62:14 | LL | 2 => std::mem::transmute::<_, &&'b u32>(x), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> tests/ui/transmute_ptr_to_ref.rs:51:14 + --> tests/ui/transmute_ptr_to_ref.rs:64:14 | LL | _ => std::mem::transmute::<_, &&'b u32>(y), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&'b u32>()` error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) - --> tests/ui/transmute_ptr_to_ref.rs:59:19 + --> tests/ui/transmute_ptr_to_ref.rs:73:19 | LL | let _: &u32 = std::mem::transmute(a); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a` error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) - --> tests/ui/transmute_ptr_to_ref.rs:60:19 + --> tests/ui/transmute_ptr_to_ref.rs:75:19 | LL | let _: &u32 = std::mem::transmute::<_, &u32>(a); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a.cast::()` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> tests/ui/transmute_ptr_to_ref.rs:62:14 + --> tests/ui/transmute_ptr_to_ref.rs:78:14 | LL | 0 => std::mem::transmute(x), | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> tests/ui/transmute_ptr_to_ref.rs:63:14 + --> tests/ui/transmute_ptr_to_ref.rs:80:14 | LL | _ => std::mem::transmute::<_, &&'b u32>(x), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()` error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) - --> tests/ui/transmute_ptr_to_ref.rs:71:19 + --> tests/ui/transmute_ptr_to_ref.rs:89:19 | LL | let _: &u32 = std::mem::transmute(a); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a` error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`) - --> tests/ui/transmute_ptr_to_ref.rs:72:19 + --> tests/ui/transmute_ptr_to_ref.rs:91:19 | LL | let _: &u32 = std::mem::transmute::<_, &u32>(a); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(a as *const u32)` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> tests/ui/transmute_ptr_to_ref.rs:74:14 + --> tests/ui/transmute_ptr_to_ref.rs:94:14 | LL | 0 => std::mem::transmute(x), | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &u32)` error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`) - --> tests/ui/transmute_ptr_to_ref.rs:75:14 + --> tests/ui/transmute_ptr_to_ref.rs:96:14 | LL | _ => std::mem::transmute::<_, &&'b u32>(x), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &'b u32)` diff --git a/tests/ui/transmute_ref_to_ref.rs b/tests/ui/transmute_ref_to_ref.rs index 44d7af44a805..8bdf07b4a428 100644 --- a/tests/ui/transmute_ref_to_ref.rs +++ b/tests/ui/transmute_ref_to_ref.rs @@ -7,12 +7,14 @@ fn main() { unsafe { let single_u64: &[u64] = &[0xDEAD_BEEF_DEAD_BEEF]; let bools: &[bool] = unsafe { std::mem::transmute(single_u64) }; - //~^ ERROR: transmute from a reference to a reference + //~^ transmute_ptr_to_ptr + let a: &[u32] = &[0x12345678, 0x90ABCDEF, 0xFEDCBA09, 0x87654321]; let b: &[u8] = unsafe { std::mem::transmute(a) }; - //~^ ERROR: transmute from a reference to a reference + //~^ transmute_ptr_to_ptr + let bytes = &[1u8, 2u8, 3u8, 4u8] as &[u8]; let alt_slice: &[u32] = unsafe { std::mem::transmute(bytes) }; - //~^ ERROR: transmute from a reference to a reference + //~^ transmute_ptr_to_ptr } } diff --git a/tests/ui/transmute_ref_to_ref.stderr b/tests/ui/transmute_ref_to_ref.stderr index e2d04cea8959..e8d659f9c5d8 100644 --- a/tests/ui/transmute_ref_to_ref.stderr +++ b/tests/ui/transmute_ref_to_ref.stderr @@ -11,13 +11,13 @@ LL | #![deny(clippy::transmute_ptr_to_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a reference to a reference - --> tests/ui/transmute_ref_to_ref.rs:12:33 + --> tests/ui/transmute_ref_to_ref.rs:13:33 | LL | let b: &[u8] = unsafe { std::mem::transmute(a) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(a as *const [u32] as *const [u8])` error: transmute from a reference to a reference - --> tests/ui/transmute_ref_to_ref.rs:15:42 + --> tests/ui/transmute_ref_to_ref.rs:17:42 | LL | let alt_slice: &[u32] = unsafe { std::mem::transmute(bytes) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(bytes as *const [u8] as *const [u32])` diff --git a/tests/ui/transmute_ref_to_ref_no_std.rs b/tests/ui/transmute_ref_to_ref_no_std.rs index 591770587549..faa776f2afce 100644 --- a/tests/ui/transmute_ref_to_ref_no_std.rs +++ b/tests/ui/transmute_ref_to_ref_no_std.rs @@ -19,12 +19,14 @@ fn main() { unsafe { let single_u64: &[u64] = &[0xDEAD_BEEF_DEAD_BEEF]; let bools: &[bool] = unsafe { core::mem::transmute(single_u64) }; - //~^ ERROR: transmute from a reference to a reference + //~^ transmute_ptr_to_ptr + let a: &[u32] = &[0x12345678, 0x90ABCDEF, 0xFEDCBA09, 0x87654321]; let b: &[u8] = unsafe { core::mem::transmute(a) }; - //~^ ERROR: transmute from a reference to a reference + //~^ transmute_ptr_to_ptr + let bytes = &[1u8, 2u8, 3u8, 4u8] as &[u8]; let alt_slice: &[u32] = unsafe { core::mem::transmute(bytes) }; - //~^ ERROR: transmute from a reference to a reference + //~^ transmute_ptr_to_ptr } } diff --git a/tests/ui/transmute_ref_to_ref_no_std.stderr b/tests/ui/transmute_ref_to_ref_no_std.stderr index 6a76d6729d05..9aa9ed928a4d 100644 --- a/tests/ui/transmute_ref_to_ref_no_std.stderr +++ b/tests/ui/transmute_ref_to_ref_no_std.stderr @@ -11,13 +11,13 @@ LL | #![deny(clippy::transmute_ptr_to_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a reference to a reference - --> tests/ui/transmute_ref_to_ref_no_std.rs:24:33 + --> tests/ui/transmute_ref_to_ref_no_std.rs:25:33 | LL | let b: &[u8] = unsafe { core::mem::transmute(a) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(a as *const [u32] as *const [u8])` error: transmute from a reference to a reference - --> tests/ui/transmute_ref_to_ref_no_std.rs:27:42 + --> tests/ui/transmute_ref_to_ref_no_std.rs:29:42 | LL | let alt_slice: &[u32] = unsafe { core::mem::transmute(bytes) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(bytes as *const [u8] as *const [u32])` diff --git a/tests/ui/transmute_undefined_repr.rs b/tests/ui/transmute_undefined_repr.rs index 5b16d71f1142..a449d6a4302f 100644 --- a/tests/ui/transmute_undefined_repr.rs +++ b/tests/ui/transmute_undefined_repr.rs @@ -32,11 +32,11 @@ fn main() { // Lint, Ty2 is unordered let _: Ty2C = transmute(value::>()); - //~^ ERROR: transmute from `Ty2` which has an undefined layout - //~| NOTE: `-D clippy::transmute-undefined-repr` implied by `-D warnings` + //~^ transmute_undefined_repr + // Lint, Ty2 is unordered let _: Ty2 = transmute(value::>()); - //~^ ERROR: transmute into `Ty2` which has an undefined layout + //~^ transmute_undefined_repr // Ok, Ty2 types are the same let _: Ty2 = transmute(value::>>()); @@ -45,24 +45,22 @@ fn main() { // Lint, different Ty2 instances let _: Ty2 = transmute(value::>>()); - //~^ ERROR: transmute from `Ty>` to `Ty2`, both of which h - //~| NOTE: two instances of the same generic type (`Ty2`) may have different layou + //~^ transmute_undefined_repr + // Lint, different Ty2 instances let _: Ty> = transmute(value::>()); - //~^ ERROR: transmute from `Ty2` to `Ty>`, both of which h - //~| NOTE: two instances of the same generic type (`Ty2`) may have different layou + //~^ transmute_undefined_repr let _: Ty<&()> = transmute(value::<&()>()); let _: &() = transmute(value::>()); // Lint, different Ty2 instances let _: &Ty2 = transmute(value::>>()); - //~^ ERROR: transmute from `Ty<&Ty2>` to `&Ty2`, both of which - //~| NOTE: two instances of the same generic type (`Ty2`) may have different layou + //~^ transmute_undefined_repr + // Lint, different Ty2 instances let _: Ty<&Ty2> = transmute(value::<&Ty2>()); - //~^ ERROR: transmute from `&Ty2` to `Ty<&Ty2>`, both of which - //~| NOTE: two instances of the same generic type (`Ty2`) may have different layou + //~^ transmute_undefined_repr // Ok, pointer to usize conversion let _: Ty = transmute(value::<&Ty2>()); @@ -91,12 +89,11 @@ fn main() { // Lint, different Ty2 instances let _: &'static mut Ty2 = transmute(value::>>()); - //~^ ERROR: transmute from `std::boxed::Box>` to `&mut Ty2 - //~| NOTE: two instances of the same generic type (`Ty2`) may have different layou + //~^ transmute_undefined_repr + // Lint, different Ty2 instances let _: Box> = transmute(value::<&'static mut Ty2>()); - //~^ ERROR: transmute from `&mut Ty2` to `std::boxed::Box> - //~| NOTE: two instances of the same generic type (`Ty2`) may have different layou + //~^ transmute_undefined_repr // Ok, type erasure let _: *const () = transmute(value::>>()); @@ -192,12 +189,11 @@ fn main() { // Err let _: *const Ty2 = transmute(value::<*const Ty2C>>()); - //~^ ERROR: transmute into `*const Ty2` which has an undefined layout - //~| NOTE: the contained type `Ty2` has an undefined layout + //~^ transmute_undefined_repr + // Err let _: *const Ty2C> = transmute(value::<*const Ty2>()); - //~^ ERROR: transmute from `*const Ty2` which has an undefined layout - //~| NOTE: the contained type `Ty2` has an undefined layout + //~^ transmute_undefined_repr // Ok let _: NonNull = transmute(value::>()); @@ -243,12 +239,11 @@ fn _with_generics() { // Err let _: Vec> = transmute(value::>>()); - //~^ ERROR: transmute from `std::vec::Vec>` to `std::vec::Vec> = transmute(value::>>()); - //~^ ERROR: transmute from `std::vec::Vec>` to `std::vec::Vec>()); diff --git a/tests/ui/transmute_undefined_repr.stderr b/tests/ui/transmute_undefined_repr.stderr index b41d37a5cd13..a259ef784c78 100644 --- a/tests/ui/transmute_undefined_repr.stderr +++ b/tests/ui/transmute_undefined_repr.stderr @@ -30,7 +30,7 @@ LL | let _: Ty> = transmute(value::>()); = note: two instances of the same generic type (`Ty2`) may have different layouts error: transmute from `Ty<&Ty2>` to `&Ty2`, both of which have an undefined layout - --> tests/ui/transmute_undefined_repr.rs:59:33 + --> tests/ui/transmute_undefined_repr.rs:58:33 | LL | let _: &Ty2 = transmute(value::>>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ LL | let _: &Ty2 = transmute(value::>>()); = note: two instances of the same generic type (`Ty2`) may have different layouts error: transmute from `&Ty2` to `Ty<&Ty2>`, both of which have an undefined layout - --> tests/ui/transmute_undefined_repr.rs:63:37 + --> tests/ui/transmute_undefined_repr.rs:62:37 | LL | let _: Ty<&Ty2> = transmute(value::<&Ty2>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -46,7 +46,7 @@ LL | let _: Ty<&Ty2> = transmute(value::<&Ty2>()); = note: two instances of the same generic type (`Ty2`) may have different layouts error: transmute from `std::boxed::Box>` to `&mut Ty2`, both of which have an undefined layout - --> tests/ui/transmute_undefined_repr.rs:93:45 + --> tests/ui/transmute_undefined_repr.rs:91:45 | LL | let _: &'static mut Ty2 = transmute(value::>>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -54,7 +54,7 @@ LL | let _: &'static mut Ty2 = transmute(value::` to `std::boxed::Box>`, both of which have an undefined layout - --> tests/ui/transmute_undefined_repr.rs:97:37 + --> tests/ui/transmute_undefined_repr.rs:95:37 | LL | let _: Box> = transmute(value::<&'static mut Ty2>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -62,7 +62,7 @@ LL | let _: Box> = transmute(value::<&'static mut Ty2` which has an undefined layout - --> tests/ui/transmute_undefined_repr.rs:194:39 + --> tests/ui/transmute_undefined_repr.rs:191:39 | LL | let _: *const Ty2 = transmute(value::<*const Ty2C>>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -70,7 +70,7 @@ LL | let _: *const Ty2 = transmute(value::<*const Ty2C` has an undefined layout error: transmute from `*const Ty2` which has an undefined layout - --> tests/ui/transmute_undefined_repr.rs:198:50 + --> tests/ui/transmute_undefined_repr.rs:195:50 | LL | let _: *const Ty2C> = transmute(value::<*const Ty2>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -78,7 +78,7 @@ LL | let _: *const Ty2C> = transmute(value::<*const T = note: the contained type `Ty2` has an undefined layout error: transmute from `std::vec::Vec>` to `std::vec::Vec>`, both of which have an undefined layout - --> tests/ui/transmute_undefined_repr.rs:245:35 + --> tests/ui/transmute_undefined_repr.rs:241:35 | LL | let _: Vec> = transmute(value::>>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -86,7 +86,7 @@ LL | let _: Vec> = transmute(value::>>()); = note: two instances of the same generic type (`Vec`) may have different layouts error: transmute from `std::vec::Vec>` to `std::vec::Vec>`, both of which have an undefined layout - --> tests/ui/transmute_undefined_repr.rs:249:35 + --> tests/ui/transmute_undefined_repr.rs:245:35 | LL | let _: Vec> = transmute(value::>>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/tests/ui/transmutes_expressible_as_ptr_casts.fixed index a4a3ca82e76c..e7ad2a1cbbcb 100644 --- a/tests/ui/transmutes_expressible_as_ptr_casts.fixed +++ b/tests/ui/transmutes_expressible_as_ptr_casts.fixed @@ -15,28 +15,33 @@ fn main() { // e is an integer and U is *U_0, while U_0: Sized; addr-ptr-cast let _ptr_i32_transmute = unsafe { usize::MAX as *const i32 }; + //~^ useless_transmute let ptr_i32 = usize::MAX as *const i32; // e has type *T, U is *U_0, and either U_0: Sized ... let _ptr_i8_transmute = unsafe { ptr_i32.cast::() }; + //~^ transmute_ptr_to_ptr let _ptr_i8 = ptr_i32 as *const i8; let slice_ptr = &[0, 1, 2, 3] as *const [i32]; // ... or pointer_kind(T) = pointer_kind(U_0); ptr-ptr-cast let _ptr_to_unsized_transmute = unsafe { slice_ptr as *const [u32] }; + //~^ transmute_ptr_to_ptr let _ptr_to_unsized = slice_ptr as *const [u32]; // TODO: We could try testing vtable casts here too, but maybe // we should wait until std::raw::TraitObject is stabilized? // e has type *T and U is a numeric type, while T: Sized; ptr-addr-cast let _usize_from_int_ptr_transmute = unsafe { ptr_i32 as usize }; + //~^ transmutes_expressible_as_ptr_casts let _usize_from_int_ptr = ptr_i32 as usize; let array_ref: &[i32; 4] = &[1, 2, 3, 4]; // e has type &[T; n] and U is *const T; array-ptr-cast let _array_ptr_transmute = unsafe { array_ref as *const [i32; 4] }; + //~^ useless_transmute let _array_ptr = array_ref as *const [i32; 4]; fn foo(_: usize) -> u8 { @@ -45,13 +50,16 @@ fn main() { // e is a function pointer type and U has type *T, while T: Sized; fptr-ptr-cast let _usize_ptr_transmute = unsafe { foo as *const usize }; + //~^ transmutes_expressible_as_ptr_casts let _usize_ptr_transmute = foo as *const usize; // e is a function pointer type and U is an integer; fptr-addr-cast let _usize_from_fn_ptr_transmute = unsafe { foo as usize }; + //~^ transmutes_expressible_as_ptr_casts let _usize_from_fn_ptr = foo as *const usize; let _usize_from_ref = unsafe { &1u32 as *const u32 as usize }; + //~^ transmutes_expressible_as_ptr_casts } // If a ref-to-ptr cast of this form where the pointer type points to a type other @@ -63,6 +71,7 @@ fn main() { // fall through into `do_check`. fn trigger_do_check_to_emit_error(in_param: &[i32; 1]) -> *const u8 { unsafe { in_param as *const [i32; 1] as *const u8 } + //~^ useless_transmute } #[repr(C)] @@ -81,6 +90,7 @@ fn issue_10449() { fn f() {} let _x: u8 = unsafe { *(f as *const u8) }; + //~^ transmutes_expressible_as_ptr_casts } // Pointers cannot be cast to integers in const contexts diff --git a/tests/ui/transmutes_expressible_as_ptr_casts.rs b/tests/ui/transmutes_expressible_as_ptr_casts.rs index 6aa8e384e268..42a81777a826 100644 --- a/tests/ui/transmutes_expressible_as_ptr_casts.rs +++ b/tests/ui/transmutes_expressible_as_ptr_casts.rs @@ -15,28 +15,33 @@ fn main() { // e is an integer and U is *U_0, while U_0: Sized; addr-ptr-cast let _ptr_i32_transmute = unsafe { transmute::(usize::MAX) }; + //~^ useless_transmute let ptr_i32 = usize::MAX as *const i32; // e has type *T, U is *U_0, and either U_0: Sized ... let _ptr_i8_transmute = unsafe { transmute::<*const i32, *const i8>(ptr_i32) }; + //~^ transmute_ptr_to_ptr let _ptr_i8 = ptr_i32 as *const i8; let slice_ptr = &[0, 1, 2, 3] as *const [i32]; // ... or pointer_kind(T) = pointer_kind(U_0); ptr-ptr-cast let _ptr_to_unsized_transmute = unsafe { transmute::<*const [i32], *const [u32]>(slice_ptr) }; + //~^ transmute_ptr_to_ptr let _ptr_to_unsized = slice_ptr as *const [u32]; // TODO: We could try testing vtable casts here too, but maybe // we should wait until std::raw::TraitObject is stabilized? // e has type *T and U is a numeric type, while T: Sized; ptr-addr-cast let _usize_from_int_ptr_transmute = unsafe { transmute::<*const i32, usize>(ptr_i32) }; + //~^ transmutes_expressible_as_ptr_casts let _usize_from_int_ptr = ptr_i32 as usize; let array_ref: &[i32; 4] = &[1, 2, 3, 4]; // e has type &[T; n] and U is *const T; array-ptr-cast let _array_ptr_transmute = unsafe { transmute::<&[i32; 4], *const [i32; 4]>(array_ref) }; + //~^ useless_transmute let _array_ptr = array_ref as *const [i32; 4]; fn foo(_: usize) -> u8 { @@ -45,13 +50,16 @@ fn main() { // e is a function pointer type and U has type *T, while T: Sized; fptr-ptr-cast let _usize_ptr_transmute = unsafe { transmute:: u8, *const usize>(foo) }; + //~^ transmutes_expressible_as_ptr_casts let _usize_ptr_transmute = foo as *const usize; // e is a function pointer type and U is an integer; fptr-addr-cast let _usize_from_fn_ptr_transmute = unsafe { transmute:: u8, usize>(foo) }; + //~^ transmutes_expressible_as_ptr_casts let _usize_from_fn_ptr = foo as *const usize; let _usize_from_ref = unsafe { transmute::<*const u32, usize>(&1u32) }; + //~^ transmutes_expressible_as_ptr_casts } // If a ref-to-ptr cast of this form where the pointer type points to a type other @@ -63,6 +71,7 @@ fn main() { // fall through into `do_check`. fn trigger_do_check_to_emit_error(in_param: &[i32; 1]) -> *const u8 { unsafe { transmute::<&[i32; 1], *const u8>(in_param) } + //~^ useless_transmute } #[repr(C)] @@ -81,6 +90,7 @@ fn issue_10449() { fn f() {} let _x: u8 = unsafe { *std::mem::transmute::(f) }; + //~^ transmutes_expressible_as_ptr_casts } // Pointers cannot be cast to integers in const contexts diff --git a/tests/ui/transmutes_expressible_as_ptr_casts.stderr b/tests/ui/transmutes_expressible_as_ptr_casts.stderr index 21edd39e7ad6..7746f087cc71 100644 --- a/tests/ui/transmutes_expressible_as_ptr_casts.stderr +++ b/tests/ui/transmutes_expressible_as_ptr_casts.stderr @@ -8,7 +8,7 @@ LL | let _ptr_i32_transmute = unsafe { transmute::(usize: = help: to override `-D warnings` add `#[allow(clippy::useless_transmute)]` error: transmute from a pointer to a pointer - --> tests/ui/transmutes_expressible_as_ptr_casts.rs:21:38 + --> tests/ui/transmutes_expressible_as_ptr_casts.rs:22:38 | LL | let _ptr_i8_transmute = unsafe { transmute::<*const i32, *const i8>(ptr_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL + let _ptr_i8_transmute = unsafe { ptr_i32.cast::() }; | error: transmute from a pointer to a pointer - --> tests/ui/transmutes_expressible_as_ptr_casts.rs:27:46 + --> tests/ui/transmutes_expressible_as_ptr_casts.rs:29:46 | LL | let _ptr_to_unsized_transmute = unsafe { transmute::<*const [i32], *const [u32]>(slice_ptr) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,7 +34,7 @@ LL + let _ptr_to_unsized_transmute = unsafe { slice_ptr as *const [u32] }; | error: transmute from `*const i32` to `usize` which could be expressed as a pointer cast instead - --> tests/ui/transmutes_expressible_as_ptr_casts.rs:33:50 + --> tests/ui/transmutes_expressible_as_ptr_casts.rs:36:50 | LL | let _usize_from_int_ptr_transmute = unsafe { transmute::<*const i32, usize>(ptr_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr_i32 as usize` @@ -43,37 +43,37 @@ LL | let _usize_from_int_ptr_transmute = unsafe { transmute::<*const i32, us = help: to override `-D warnings` add `#[allow(clippy::transmutes_expressible_as_ptr_casts)]` error: transmute from a reference to a pointer - --> tests/ui/transmutes_expressible_as_ptr_casts.rs:39:41 + --> tests/ui/transmutes_expressible_as_ptr_casts.rs:43:41 | LL | let _array_ptr_transmute = unsafe { transmute::<&[i32; 4], *const [i32; 4]>(array_ref) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `array_ref as *const [i32; 4]` error: transmute from `fn(usize) -> u8` to `*const usize` which could be expressed as a pointer cast instead - --> tests/ui/transmutes_expressible_as_ptr_casts.rs:47:41 + --> tests/ui/transmutes_expressible_as_ptr_casts.rs:52:41 | LL | let _usize_ptr_transmute = unsafe { transmute:: u8, *const usize>(foo) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `foo as *const usize` error: transmute from `fn(usize) -> u8` to `usize` which could be expressed as a pointer cast instead - --> tests/ui/transmutes_expressible_as_ptr_casts.rs:51:49 + --> tests/ui/transmutes_expressible_as_ptr_casts.rs:57:49 | LL | let _usize_from_fn_ptr_transmute = unsafe { transmute:: u8, usize>(foo) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `foo as usize` error: transmute from `*const u32` to `usize` which could be expressed as a pointer cast instead - --> tests/ui/transmutes_expressible_as_ptr_casts.rs:54:36 + --> tests/ui/transmutes_expressible_as_ptr_casts.rs:61:36 | LL | let _usize_from_ref = unsafe { transmute::<*const u32, usize>(&1u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&1u32 as *const u32 as usize` error: transmute from a reference to a pointer - --> tests/ui/transmutes_expressible_as_ptr_casts.rs:65:14 + --> tests/ui/transmutes_expressible_as_ptr_casts.rs:73:14 | LL | unsafe { transmute::<&[i32; 1], *const u8>(in_param) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `in_param as *const [i32; 1] as *const u8` error: transmute from `fn()` to `*const u8` which could be expressed as a pointer cast instead - --> tests/ui/transmutes_expressible_as_ptr_casts.rs:83:28 + --> tests/ui/transmutes_expressible_as_ptr_casts.rs:92:28 | LL | let _x: u8 = unsafe { *std::mem::transmute::(f) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(f as *const u8)` diff --git a/tests/ui/transmuting_null.rs b/tests/ui/transmuting_null.rs index c2deb6b6c460..bcd35bbd4e72 100644 --- a/tests/ui/transmuting_null.rs +++ b/tests/ui/transmuting_null.rs @@ -8,10 +8,10 @@ fn one_liners() { unsafe { let _: &u64 = std::mem::transmute(0 as *const u64); - //~^ ERROR: transmuting a known null pointer into a reference - //~| NOTE: `-D clippy::transmuting-null` implied by `-D warnings` + //~^ transmuting_null + let _: &u64 = std::mem::transmute(std::ptr::null::()); - //~^ ERROR: transmuting a known null pointer into a reference + //~^ transmuting_null } } @@ -22,7 +22,8 @@ fn transmute_const() { unsafe { // Should raise a lint. let _: &u64 = std::mem::transmute(ZPTR); - //~^ ERROR: transmuting a known null pointer into a reference + //~^ transmuting_null + // Should NOT raise a lint. let _: &u64 = std::mem::transmute(NOT_ZPTR); } diff --git a/tests/ui/trim_split_whitespace.fixed b/tests/ui/trim_split_whitespace.fixed index 6d3daf798a67..434e91b7d953 100644 --- a/tests/ui/trim_split_whitespace.fixed +++ b/tests/ui/trim_split_whitespace.fixed @@ -59,13 +59,25 @@ impl DerefStrAndCustomTrim { fn main() { // &str let _ = " A B C ".split_whitespace(); // should trigger lint + // + //~^^ trim_split_whitespace let _ = " A B C ".split_whitespace(); // should trigger lint + // + //~^^ trim_split_whitespace let _ = " A B C ".split_whitespace(); // should trigger lint + // + //~^^ trim_split_whitespace // String let _ = (" A B C ").to_string().split_whitespace(); // should trigger lint + // + //~^^ trim_split_whitespace let _ = (" A B C ").to_string().split_whitespace(); // should trigger lint + // + //~^^ trim_split_whitespace let _ = (" A B C ").to_string().split_whitespace(); // should trigger lint + // + //~^^ trim_split_whitespace // Custom let _ = Custom.trim().split_whitespace(); // should not trigger lint @@ -73,6 +85,8 @@ fn main() { // Deref let s = DerefStr(" A B C "); let _ = s.split_whitespace(); // should trigger lint + // + //~^^ trim_split_whitespace // Deref + custom impl let s = DerefStrAndCustom(" A B C "); @@ -81,6 +95,8 @@ fn main() { // Deref + only custom split_ws() impl let s = DerefStrAndCustomSplit(" A B C "); let _ = s.split_whitespace(); // should trigger lint + // + //~^^ trim_split_whitespace // Expl: trim() is called on str (deref) and returns &str. // Thus split_ws() is called on str as well and the custom impl on S is unused diff --git a/tests/ui/trim_split_whitespace.rs b/tests/ui/trim_split_whitespace.rs index b49d9e8b3fab..b939ecdfba85 100644 --- a/tests/ui/trim_split_whitespace.rs +++ b/tests/ui/trim_split_whitespace.rs @@ -59,13 +59,25 @@ impl DerefStrAndCustomTrim { fn main() { // &str let _ = " A B C ".trim().split_whitespace(); // should trigger lint + // + //~^^ trim_split_whitespace let _ = " A B C ".trim_start().split_whitespace(); // should trigger lint + // + //~^^ trim_split_whitespace let _ = " A B C ".trim_end().split_whitespace(); // should trigger lint + // + //~^^ trim_split_whitespace // String let _ = (" A B C ").to_string().trim().split_whitespace(); // should trigger lint + // + //~^^ trim_split_whitespace let _ = (" A B C ").to_string().trim_start().split_whitespace(); // should trigger lint + // + //~^^ trim_split_whitespace let _ = (" A B C ").to_string().trim_end().split_whitespace(); // should trigger lint + // + //~^^ trim_split_whitespace // Custom let _ = Custom.trim().split_whitespace(); // should not trigger lint @@ -73,6 +85,8 @@ fn main() { // Deref let s = DerefStr(" A B C "); let _ = s.trim().split_whitespace(); // should trigger lint + // + //~^^ trim_split_whitespace // Deref + custom impl let s = DerefStrAndCustom(" A B C "); @@ -81,6 +95,8 @@ fn main() { // Deref + only custom split_ws() impl let s = DerefStrAndCustomSplit(" A B C "); let _ = s.trim().split_whitespace(); // should trigger lint + // + //~^^ trim_split_whitespace // Expl: trim() is called on str (deref) and returns &str. // Thus split_ws() is called on str as well and the custom impl on S is unused diff --git a/tests/ui/trim_split_whitespace.stderr b/tests/ui/trim_split_whitespace.stderr index 6119d21a8e9a..f242dd802115 100644 --- a/tests/ui/trim_split_whitespace.stderr +++ b/tests/ui/trim_split_whitespace.stderr @@ -8,43 +8,43 @@ LL | let _ = " A B C ".trim().split_whitespace(); // should trigger lint = help: to override `-D warnings` add `#[allow(clippy::trim_split_whitespace)]` error: found call to `str::trim_start` before `str::split_whitespace` - --> tests/ui/trim_split_whitespace.rs:62:23 + --> tests/ui/trim_split_whitespace.rs:64:23 | LL | let _ = " A B C ".trim_start().split_whitespace(); // should trigger lint | ^^^^^^^^^^^^^ help: remove `trim_start()` error: found call to `str::trim_end` before `str::split_whitespace` - --> tests/ui/trim_split_whitespace.rs:63:23 + --> tests/ui/trim_split_whitespace.rs:67:23 | LL | let _ = " A B C ".trim_end().split_whitespace(); // should trigger lint | ^^^^^^^^^^^ help: remove `trim_end()` error: found call to `str::trim` before `str::split_whitespace` - --> tests/ui/trim_split_whitespace.rs:66:37 + --> tests/ui/trim_split_whitespace.rs:72:37 | LL | let _ = (" A B C ").to_string().trim().split_whitespace(); // should trigger lint | ^^^^^^^ help: remove `trim()` error: found call to `str::trim_start` before `str::split_whitespace` - --> tests/ui/trim_split_whitespace.rs:67:37 + --> tests/ui/trim_split_whitespace.rs:75:37 | LL | let _ = (" A B C ").to_string().trim_start().split_whitespace(); // should trigger lint | ^^^^^^^^^^^^^ help: remove `trim_start()` error: found call to `str::trim_end` before `str::split_whitespace` - --> tests/ui/trim_split_whitespace.rs:68:37 + --> tests/ui/trim_split_whitespace.rs:78:37 | LL | let _ = (" A B C ").to_string().trim_end().split_whitespace(); // should trigger lint | ^^^^^^^^^^^ help: remove `trim_end()` error: found call to `str::trim` before `str::split_whitespace` - --> tests/ui/trim_split_whitespace.rs:75:15 + --> tests/ui/trim_split_whitespace.rs:87:15 | LL | let _ = s.trim().split_whitespace(); // should trigger lint | ^^^^^^^ help: remove `trim()` error: found call to `str::trim` before `str::split_whitespace` - --> tests/ui/trim_split_whitespace.rs:83:15 + --> tests/ui/trim_split_whitespace.rs:97:15 | LL | let _ = s.trim().split_whitespace(); // should trigger lint | ^^^^^^^ help: remove `trim()` diff --git a/tests/ui/trivially_copy_pass_by_ref.rs b/tests/ui/trivially_copy_pass_by_ref.rs index 043a7b63af3c..37bc6f89a20a 100644 --- a/tests/ui/trivially_copy_pass_by_ref.rs +++ b/tests/ui/trivially_copy_pass_by_ref.rs @@ -52,6 +52,7 @@ fn good_return_explicit_lt_struct<'a>(foo: &'a Foo) -> FooRef<'a> { fn bad(x: &u32, y: &Foo, z: &Baz) {} //~^ ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by //~| ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by +//~| ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by impl Foo { fn good(self, a: &mut u32, b: u32, c: &Bar) {} diff --git a/tests/ui/trivially_copy_pass_by_ref.stderr b/tests/ui/trivially_copy_pass_by_ref.stderr index 4887fb00e742..e813fecf653a 100644 --- a/tests/ui/trivially_copy_pass_by_ref.stderr +++ b/tests/ui/trivially_copy_pass_by_ref.stderr @@ -23,91 +23,91 @@ LL | fn bad(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:61:12 + --> tests/ui/trivially_copy_pass_by_ref.rs:62:12 | LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^^ help: consider passing by value instead: `self` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:61:22 + --> tests/ui/trivially_copy_pass_by_ref.rs:62:22 | LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:61:31 + --> tests/ui/trivially_copy_pass_by_ref.rs:62:31 | LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Foo` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:61:40 + --> tests/ui/trivially_copy_pass_by_ref.rs:62:40 | LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:67:16 + --> tests/ui/trivially_copy_pass_by_ref.rs:68:16 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:67:25 + --> tests/ui/trivially_copy_pass_by_ref.rs:68:25 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Foo` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:67:34 + --> tests/ui/trivially_copy_pass_by_ref.rs:68:34 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:72:35 + --> tests/ui/trivially_copy_pass_by_ref.rs:73:35 | LL | fn bad_issue7518(self, other: &Self) {} | ^^^^^ help: consider passing by value instead: `Self` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:85:16 + --> tests/ui/trivially_copy_pass_by_ref.rs:86:16 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:85:25 + --> tests/ui/trivially_copy_pass_by_ref.rs:86:25 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Foo` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:85:34 + --> tests/ui/trivially_copy_pass_by_ref.rs:86:34 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:92:34 + --> tests/ui/trivially_copy_pass_by_ref.rs:93:34 | LL | fn trait_method(&self, _foo: &Foo); | ^^^^ help: consider passing by value instead: `Foo` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:125:21 + --> tests/ui/trivially_copy_pass_by_ref.rs:126:21 | LL | fn foo_never(x: &i32) { | ^^^^ help: consider passing by value instead: `i32` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:131:15 + --> tests/ui/trivially_copy_pass_by_ref.rs:132:15 | LL | fn foo(x: &i32) { | ^^^^ help: consider passing by value instead: `i32` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:159:37 + --> tests/ui/trivially_copy_pass_by_ref.rs:160:37 | LL | fn _unrelated_lifetimes<'a, 'b>(_x: &'a u32, y: &'b u32) -> &'b u32 { | ^^^^^^^ help: consider passing by value instead: `u32` diff --git a/tests/ui/try_err.fixed b/tests/ui/try_err.fixed index f149bfb77740..ea509f9a2da8 100644 --- a/tests/ui/try_err.fixed +++ b/tests/ui/try_err.fixed @@ -20,6 +20,7 @@ pub fn basic_test() -> Result { // To avoid warnings during rustfix if true { return Err(err); + //~^ try_err } Ok(0) } @@ -30,6 +31,7 @@ pub fn into_test() -> Result { // To avoid warnings during rustfix if true { return Err(err.into()); + //~^ try_err } Ok(0) } @@ -50,6 +52,7 @@ pub fn closure_matches_test() -> Result { // To avoid warnings during rustfix if true { return Err(err); + //~^ try_err } Ok(i) }) @@ -69,6 +72,7 @@ pub fn closure_into_test() -> Result { // To avoid warnings during rustfix if true { return Err(err.into()); + //~^ try_err } Ok(i) }) @@ -89,6 +93,7 @@ fn calling_macro() -> Result { match $(Ok::<_, i32>(5)) { Ok(_) => 0, Err(_) => return Err(1), + //~^ try_err } ); // `Err` arg is another macro @@ -96,6 +101,7 @@ fn calling_macro() -> Result { match $(Ok::<_, i32>(5)) { Ok(_) => 0, Err(_) => return Err(inline!(1)), + //~^ try_err } ); Ok(5) @@ -123,6 +129,7 @@ fn main() { pub fn macro_inside(fail: bool) -> Result { if fail { return Err(inline!(inline!(String::from("aasdfasdfasdfa")))); + //~^ try_err } Ok(0) } @@ -130,8 +137,10 @@ pub fn macro_inside(fail: bool) -> Result { pub fn poll_write(n: usize) -> Poll> { if n == 0 { return Poll::Ready(Err(io::ErrorKind::WriteZero.into())) + //~^ try_err } else if n == 1 { return Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, "error"))) + //~^ try_err }; Poll::Ready(Ok(n)) @@ -140,6 +149,7 @@ pub fn poll_write(n: usize) -> Poll> { pub fn poll_next(ready: bool) -> Poll>> { if !ready { return Poll::Ready(Some(Err(io::ErrorKind::NotFound.into()))) + //~^ try_err } Poll::Ready(None) @@ -149,6 +159,7 @@ pub fn poll_next(ready: bool) -> Poll>> { pub fn try_return(x: bool) -> Result { if x { return Err(42); + //~^ try_err } Ok(0) } diff --git a/tests/ui/try_err.rs b/tests/ui/try_err.rs index 841ec6b5d5c7..295f7bd7089b 100644 --- a/tests/ui/try_err.rs +++ b/tests/ui/try_err.rs @@ -20,6 +20,7 @@ pub fn basic_test() -> Result { // To avoid warnings during rustfix if true { Err(err)?; + //~^ try_err } Ok(0) } @@ -30,6 +31,7 @@ pub fn into_test() -> Result { // To avoid warnings during rustfix if true { Err(err)?; + //~^ try_err } Ok(0) } @@ -50,6 +52,7 @@ pub fn closure_matches_test() -> Result { // To avoid warnings during rustfix if true { Err(err)?; + //~^ try_err } Ok(i) }) @@ -69,6 +72,7 @@ pub fn closure_into_test() -> Result { // To avoid warnings during rustfix if true { Err(err)?; + //~^ try_err } Ok(i) }) @@ -89,6 +93,7 @@ fn calling_macro() -> Result { match $(Ok::<_, i32>(5)) { Ok(_) => 0, Err(_) => Err(1)?, + //~^ try_err } ); // `Err` arg is another macro @@ -96,6 +101,7 @@ fn calling_macro() -> Result { match $(Ok::<_, i32>(5)) { Ok(_) => 0, Err(_) => Err(inline!(1))?, + //~^ try_err } ); Ok(5) @@ -123,6 +129,7 @@ fn main() { pub fn macro_inside(fail: bool) -> Result { if fail { Err(inline!(inline!(String::from("aasdfasdfasdfa"))))?; + //~^ try_err } Ok(0) } @@ -130,8 +137,10 @@ pub fn macro_inside(fail: bool) -> Result { pub fn poll_write(n: usize) -> Poll> { if n == 0 { Err(io::ErrorKind::WriteZero)? + //~^ try_err } else if n == 1 { Err(io::Error::new(io::ErrorKind::InvalidInput, "error"))? + //~^ try_err }; Poll::Ready(Ok(n)) @@ -140,6 +149,7 @@ pub fn poll_write(n: usize) -> Poll> { pub fn poll_next(ready: bool) -> Poll>> { if !ready { Err(io::ErrorKind::NotFound)? + //~^ try_err } Poll::Ready(None) @@ -149,6 +159,7 @@ pub fn poll_next(ready: bool) -> Poll>> { pub fn try_return(x: bool) -> Result { if x { return Err(42)?; + //~^ try_err } Ok(0) } diff --git a/tests/ui/try_err.stderr b/tests/ui/try_err.stderr index fb563d407866..50c2b092d6c8 100644 --- a/tests/ui/try_err.stderr +++ b/tests/ui/try_err.stderr @@ -11,25 +11,25 @@ LL | #![deny(clippy::try_err)] | ^^^^^^^^^^^^^^^ error: returning an `Err(_)` with the `?` operator - --> tests/ui/try_err.rs:32:9 + --> tests/ui/try_err.rs:33:9 | LL | Err(err)?; | ^^^^^^^^^ help: try: `return Err(err.into())` error: returning an `Err(_)` with the `?` operator - --> tests/ui/try_err.rs:52:17 + --> tests/ui/try_err.rs:54:17 | LL | Err(err)?; | ^^^^^^^^^ help: try: `return Err(err)` error: returning an `Err(_)` with the `?` operator - --> tests/ui/try_err.rs:71:17 + --> tests/ui/try_err.rs:74:17 | LL | Err(err)?; | ^^^^^^^^^ help: try: `return Err(err.into())` error: returning an `Err(_)` with the `?` operator - --> tests/ui/try_err.rs:91:23 + --> tests/ui/try_err.rs:95:23 | LL | Err(_) => Err(1)?, | ^^^^^^^ help: try: `return Err(1)` @@ -37,7 +37,7 @@ LL | Err(_) => Err(1)?, = note: this error originates in the macro `__inline_mac_fn_calling_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: returning an `Err(_)` with the `?` operator - --> tests/ui/try_err.rs:98:23 + --> tests/ui/try_err.rs:103:23 | LL | Err(_) => Err(inline!(1))?, | ^^^^^^^^^^^^^^^^ help: try: `return Err(inline!(1))` @@ -45,31 +45,31 @@ LL | Err(_) => Err(inline!(1))?, = note: this error originates in the macro `__inline_mac_fn_calling_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: returning an `Err(_)` with the `?` operator - --> tests/ui/try_err.rs:125:9 + --> tests/ui/try_err.rs:131:9 | LL | Err(inline!(inline!(String::from("aasdfasdfasdfa"))))?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `return Err(inline!(inline!(String::from("aasdfasdfasdfa"))))` error: returning an `Err(_)` with the `?` operator - --> tests/ui/try_err.rs:132:9 + --> tests/ui/try_err.rs:139:9 | LL | Err(io::ErrorKind::WriteZero)? | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `return Poll::Ready(Err(io::ErrorKind::WriteZero.into()))` error: returning an `Err(_)` with the `?` operator - --> tests/ui/try_err.rs:134:9 + --> tests/ui/try_err.rs:142:9 | LL | Err(io::Error::new(io::ErrorKind::InvalidInput, "error"))? | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `return Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, "error")))` error: returning an `Err(_)` with the `?` operator - --> tests/ui/try_err.rs:142:9 + --> tests/ui/try_err.rs:151:9 | LL | Err(io::ErrorKind::NotFound)? | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `return Poll::Ready(Some(Err(io::ErrorKind::NotFound.into())))` error: returning an `Err(_)` with the `?` operator - --> tests/ui/try_err.rs:151:16 + --> tests/ui/try_err.rs:161:16 | LL | return Err(42)?; | ^^^^^^^^ help: try: `Err(42)` diff --git a/tests/ui/tuple_array_conversions.rs b/tests/ui/tuple_array_conversions.rs index ca79cc104f22..772c41df090e 100644 --- a/tests/ui/tuple_array_conversions.rs +++ b/tests/ui/tuple_array_conversions.rs @@ -8,15 +8,21 @@ extern crate proc_macros; fn main() { let x = [1, 2]; let x = (x[0], x[1]); + //~^ tuple_array_conversions let x = [x.0, x.1]; + //~^ tuple_array_conversions let x = &[1, 2]; let x = (x[0], x[1]); let t1: &[(u32, u32)] = &[(1, 2), (3, 4)]; let v1: Vec<[u32; 2]> = t1.iter().map(|&(a, b)| [a, b]).collect(); + //~^ tuple_array_conversions t1.iter().for_each(|&(a, b)| _ = [a, b]); + //~^ tuple_array_conversions let t2: Vec<(u32, u32)> = v1.iter().map(|&[a, b]| (a, b)).collect(); + //~^ tuple_array_conversions t1.iter().for_each(|&(a, b)| _ = [a, b]); + //~^ tuple_array_conversions // Do not lint let v2: Vec<[u32; 2]> = t1.iter().map(|&t| t.into()).collect(); let t3: Vec<(u32, u32)> = v2.iter().map(|&v| v.into()).collect(); @@ -55,9 +61,11 @@ fn main() { // FP #11082; needs discussion let (a, b) = (1.0f64, 2.0f64); let _: &[f64] = &[a, b]; + //~^ tuple_array_conversions // FP #11085; impossible to fix let [src, dest]: [_; 2] = [1, 2]; (src, dest); + //~^ tuple_array_conversions // FP #11100 fn issue_11100_array_to_tuple(this: [&mut i32; 2]) -> (&i32, &mut i32) { let [input, output] = this; @@ -102,7 +110,9 @@ fn msrv_too_low() { fn msrv_juust_right() { let x = [1, 2]; let x = (x[0], x[1]); + //~^ tuple_array_conversions let x = [x.0, x.1]; + //~^ tuple_array_conversions let x = &[1, 2]; let x = (x[0], x[1]); } diff --git a/tests/ui/tuple_array_conversions.stderr b/tests/ui/tuple_array_conversions.stderr index 9e022b3cfb25..6dafb8d285d4 100644 --- a/tests/ui/tuple_array_conversions.stderr +++ b/tests/ui/tuple_array_conversions.stderr @@ -9,7 +9,7 @@ LL | let x = (x[0], x[1]); = help: to override `-D warnings` add `#[allow(clippy::tuple_array_conversions)]` error: it looks like you're trying to convert a tuple to an array - --> tests/ui/tuple_array_conversions.rs:11:13 + --> tests/ui/tuple_array_conversions.rs:12:13 | LL | let x = [x.0, x.1]; | ^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | let x = [x.0, x.1]; = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed error: it looks like you're trying to convert a tuple to an array - --> tests/ui/tuple_array_conversions.rs:16:53 + --> tests/ui/tuple_array_conversions.rs:18:53 | LL | let v1: Vec<[u32; 2]> = t1.iter().map(|&(a, b)| [a, b]).collect(); | ^^^^^^ @@ -25,7 +25,7 @@ LL | let v1: Vec<[u32; 2]> = t1.iter().map(|&(a, b)| [a, b]).collect(); = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed error: it looks like you're trying to convert a tuple to an array - --> tests/ui/tuple_array_conversions.rs:17:38 + --> tests/ui/tuple_array_conversions.rs:20:38 | LL | t1.iter().for_each(|&(a, b)| _ = [a, b]); | ^^^^^^ @@ -33,7 +33,7 @@ LL | t1.iter().for_each(|&(a, b)| _ = [a, b]); = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed error: it looks like you're trying to convert an array to a tuple - --> tests/ui/tuple_array_conversions.rs:18:55 + --> tests/ui/tuple_array_conversions.rs:22:55 | LL | let t2: Vec<(u32, u32)> = v1.iter().map(|&[a, b]| (a, b)).collect(); | ^^^^^^ @@ -41,7 +41,7 @@ LL | let t2: Vec<(u32, u32)> = v1.iter().map(|&[a, b]| (a, b)).collect(); = help: use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed error: it looks like you're trying to convert a tuple to an array - --> tests/ui/tuple_array_conversions.rs:19:38 + --> tests/ui/tuple_array_conversions.rs:24:38 | LL | t1.iter().for_each(|&(a, b)| _ = [a, b]); | ^^^^^^ @@ -49,7 +49,7 @@ LL | t1.iter().for_each(|&(a, b)| _ = [a, b]); = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed error: it looks like you're trying to convert a tuple to an array - --> tests/ui/tuple_array_conversions.rs:57:22 + --> tests/ui/tuple_array_conversions.rs:63:22 | LL | let _: &[f64] = &[a, b]; | ^^^^^^ @@ -57,7 +57,7 @@ LL | let _: &[f64] = &[a, b]; = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed error: it looks like you're trying to convert an array to a tuple - --> tests/ui/tuple_array_conversions.rs:60:5 + --> tests/ui/tuple_array_conversions.rs:67:5 | LL | (src, dest); | ^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | (src, dest); = help: use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed error: it looks like you're trying to convert an array to a tuple - --> tests/ui/tuple_array_conversions.rs:104:13 + --> tests/ui/tuple_array_conversions.rs:112:13 | LL | let x = (x[0], x[1]); | ^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | let x = (x[0], x[1]); = help: use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed error: it looks like you're trying to convert a tuple to an array - --> tests/ui/tuple_array_conversions.rs:105:13 + --> tests/ui/tuple_array_conversions.rs:114:13 | LL | let x = [x.0, x.1]; | ^^^^^^^^^^ diff --git a/tests/ui/ty_fn_sig.rs b/tests/ui/ty_fn_sig.rs index 9e2753dcb18d..60767bfad135 100644 --- a/tests/ui/ty_fn_sig.rs +++ b/tests/ui/ty_fn_sig.rs @@ -1,3 +1,4 @@ +//@ check-pass // Regression test pub fn retry(f: F) { diff --git a/tests/ui/type_complexity.rs b/tests/ui/type_complexity.rs index be28ee2da0cd..89c4955c9f6f 100644 --- a/tests/ui/type_complexity.rs +++ b/tests/ui/type_complexity.rs @@ -5,42 +5,46 @@ type Alias = Vec>>; // no warning here const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); -//~^ ERROR: very complex type used. Consider factoring parts into `type` definitions -//~| NOTE: `-D clippy::type-complexity` implied by `-D warnings` +//~^ type_complexity + static ST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); -//~^ ERROR: very complex type used. Consider factoring parts into `type` definitions +//~^ type_complexity struct S { f: Vec>>, - //~^ ERROR: very complex type used. Consider factoring parts into `type` definitions + //~^ type_complexity } struct Ts(Vec>>); -//~^ ERROR: very complex type used. Consider factoring parts into `type` definitions +//~^ type_complexity enum E { Tuple(Vec>>), - //~^ ERROR: very complex type used. Consider factoring parts into `type` definitions + //~^ type_complexity Struct { f: Vec>> }, - //~^ ERROR: very complex type used. Consider factoring parts into `type` definitions + //~^ type_complexity } impl S { const A: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); - //~^ ERROR: very complex type used. Consider factoring parts into `type` definitions + //~^ type_complexity + fn impl_method(&self, p: Vec>>) {} - //~^ ERROR: very complex type used. Consider factoring parts into `type` definitions + //~^ type_complexity } trait T { const A: Vec>>; - //~^ ERROR: very complex type used. Consider factoring parts into `type` definitions + //~^ type_complexity + type B = Vec>>; - //~^ ERROR: very complex type used. Consider factoring parts into `type` definitions + //~^ type_complexity + fn method(&self, p: Vec>>); - //~^ ERROR: very complex type used. Consider factoring parts into `type` definitions + //~^ type_complexity + fn def_method(&self, p: Vec>>) {} - //~^ ERROR: very complex type used. Consider factoring parts into `type` definitions + //~^ type_complexity } // Should not warn since there is likely no way to simplify this (#1013) @@ -53,16 +57,17 @@ impl T for () { } fn test1() -> Vec>> { - //~^ ERROR: very complex type used. Consider factoring parts into `type` definitions + //~^ type_complexity + vec![] } fn test2(_x: Vec>>) {} -//~^ ERROR: very complex type used. Consider factoring parts into `type` definitions +//~^ type_complexity fn test3() { let _y: Vec>> = vec![]; - //~^ ERROR: very complex type used. Consider factoring parts into `type` definitions + //~^ type_complexity } #[repr(C)] diff --git a/tests/ui/type_complexity.stderr b/tests/ui/type_complexity.stderr index 9e27899e4f90..181e04d38e9a 100644 --- a/tests/ui/type_complexity.stderr +++ b/tests/ui/type_complexity.stderr @@ -44,49 +44,49 @@ LL | const A: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:31:30 + --> tests/ui/type_complexity.rs:32:30 | LL | fn impl_method(&self, p: Vec>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:36:14 + --> tests/ui/type_complexity.rs:37:14 | LL | const A: Vec>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:38:14 + --> tests/ui/type_complexity.rs:40:14 | LL | type B = Vec>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:40:25 + --> tests/ui/type_complexity.rs:43:25 | LL | fn method(&self, p: Vec>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:42:29 + --> tests/ui/type_complexity.rs:46:29 | LL | fn def_method(&self, p: Vec>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:55:15 + --> tests/ui/type_complexity.rs:59:15 | LL | fn test1() -> Vec>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:60:14 + --> tests/ui/type_complexity.rs:65:14 | LL | fn test2(_x: Vec>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:64:13 + --> tests/ui/type_complexity.rs:69:13 | LL | let _y: Vec>> = vec![]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/type_id_on_box.fixed b/tests/ui/type_id_on_box.fixed index 3656043700fa..2e241c36b34a 100644 --- a/tests/ui/type_id_on_box.fixed +++ b/tests/ui/type_id_on_box.fixed @@ -29,7 +29,7 @@ fn main() { let any_box: Box = Box::new(0usize); let _ = (*any_box).type_id(); - //~^ ERROR: calling `.type_id()` on + //~^ type_id_on_box // Don't lint. We explicitly say "do this instead" if this is intentional let _ = TypeId::of::>(); @@ -38,18 +38,18 @@ fn main() { // 2 derefs are needed here to get to the `dyn Any` let any_box: &Box = &(Box::new(0usize) as Box); let _ = (**any_box).type_id(); - //~^ ERROR: calling `.type_id()` on + //~^ type_id_on_box let b = existential(); let _ = b.type_id(); // Don't let b: Box = Box::new(1); let _ = (*b).type_id(); - //~^ ERROR: calling `.type_id()` on + //~^ type_id_on_box let b: SomeBox = Box::new(0usize); let _ = (*b).type_id(); - //~^ ERROR: calling `.type_id()` on + //~^ type_id_on_box let b = BadBox(Box::new(0usize)); let _ = b.type_id(); // Don't lint. This is a call to `::type_id`. Not `std::boxed::Box`! diff --git a/tests/ui/type_id_on_box.rs b/tests/ui/type_id_on_box.rs index 4bd9e73f2da0..46fac632894c 100644 --- a/tests/ui/type_id_on_box.rs +++ b/tests/ui/type_id_on_box.rs @@ -29,7 +29,7 @@ fn main() { let any_box: Box = Box::new(0usize); let _ = any_box.type_id(); - //~^ ERROR: calling `.type_id()` on + //~^ type_id_on_box // Don't lint. We explicitly say "do this instead" if this is intentional let _ = TypeId::of::>(); @@ -38,18 +38,18 @@ fn main() { // 2 derefs are needed here to get to the `dyn Any` let any_box: &Box = &(Box::new(0usize) as Box); let _ = any_box.type_id(); - //~^ ERROR: calling `.type_id()` on + //~^ type_id_on_box let b = existential(); let _ = b.type_id(); // Don't let b: Box = Box::new(1); let _ = b.type_id(); - //~^ ERROR: calling `.type_id()` on + //~^ type_id_on_box let b: SomeBox = Box::new(0usize); let _ = b.type_id(); - //~^ ERROR: calling `.type_id()` on + //~^ type_id_on_box let b = BadBox(Box::new(0usize)); let _ = b.type_id(); // Don't lint. This is a call to `::type_id`. Not `std::boxed::Box`! diff --git a/tests/ui/type_id_on_box_unfixable.rs b/tests/ui/type_id_on_box_unfixable.rs index 67e398e604b4..58d245d56aa5 100644 --- a/tests/ui/type_id_on_box_unfixable.rs +++ b/tests/ui/type_id_on_box_unfixable.rs @@ -23,9 +23,9 @@ fn main() { // could) let b: Box = Box::new(1); let _ = b.type_id(); - //~^ ERROR: calling `.type_id()` on + //~^ type_id_on_box let b: Box = Box::new(1); let _ = b.type_id(); - //~^ ERROR: calling `.type_id()` on + //~^ type_id_on_box } diff --git a/tests/ui/unbuffered_bytes.rs b/tests/ui/unbuffered_bytes.rs new file mode 100644 index 000000000000..87199c7e335d --- /dev/null +++ b/tests/ui/unbuffered_bytes.rs @@ -0,0 +1,41 @@ +#![warn(clippy::unbuffered_bytes)] + +use std::fs::File; +use std::io::{BufReader, Cursor, Read, Stdin, stdin}; +use std::net::TcpStream; + +fn main() { + // File is not buffered, should complain + let file = File::open("./bytes.txt").unwrap(); + file.bytes(); + //~^ unbuffered_bytes + + // TcpStream is not buffered, should complain + let tcp_stream: TcpStream = TcpStream::connect("127.0.0.1:80").unwrap(); + tcp_stream.bytes(); + //~^ unbuffered_bytes + + // BufReader is buffered, should not complain + let file = BufReader::new(File::open("./bytes.txt").unwrap()); + file.bytes(); + + // Cursor is buffered, should not complain + let cursor = Cursor::new(Vec::new()); + cursor.bytes(); + + // Stdio would acquire the lock for every byte, should complain + let s: Stdin = stdin(); + s.bytes(); + //~^ unbuffered_bytes + + // But when locking stdin, this is fine so should not complain + let s: Stdin = stdin(); + let s = s.lock(); + s.bytes(); +} + +fn use_read(r: R) { + // Callers of `use_read` may choose a `R` that is not buffered + r.bytes(); + //~^ unbuffered_bytes +} diff --git a/tests/ui/unbuffered_bytes.stderr b/tests/ui/unbuffered_bytes.stderr new file mode 100644 index 000000000000..7505eb9e363a --- /dev/null +++ b/tests/ui/unbuffered_bytes.stderr @@ -0,0 +1,36 @@ +error: calling .bytes() is very inefficient when data is not in memory + --> tests/ui/unbuffered_bytes.rs:10:5 + | +LL | file.bytes(); + | ^^^^^^^^^^^^ + | + = help: consider using `BufReader` + = note: `-D clippy::unbuffered-bytes` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::unbuffered_bytes)]` + +error: calling .bytes() is very inefficient when data is not in memory + --> tests/ui/unbuffered_bytes.rs:15:5 + | +LL | tcp_stream.bytes(); + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider using `BufReader` + +error: calling .bytes() is very inefficient when data is not in memory + --> tests/ui/unbuffered_bytes.rs:28:5 + | +LL | s.bytes(); + | ^^^^^^^^^ + | + = help: consider using `BufReader` + +error: calling .bytes() is very inefficient when data is not in memory + --> tests/ui/unbuffered_bytes.rs:39:5 + | +LL | r.bytes(); + | ^^^^^^^^^ + | + = help: consider using `BufReader` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/unchecked_duration_subtraction.fixed b/tests/ui/unchecked_duration_subtraction.fixed index a0c3330d1777..bddffe44ac4d 100644 --- a/tests/ui/unchecked_duration_subtraction.fixed +++ b/tests/ui/unchecked_duration_subtraction.fixed @@ -7,10 +7,14 @@ fn main() { let second = Duration::from_secs(3); let _ = _first.checked_sub(second).unwrap(); + //~^ unchecked_duration_subtraction let _ = Instant::now().checked_sub(Duration::from_secs(5)).unwrap(); + //~^ unchecked_duration_subtraction let _ = _first.checked_sub(Duration::from_secs(5)).unwrap(); + //~^ unchecked_duration_subtraction let _ = Instant::now().checked_sub(second).unwrap(); + //~^ unchecked_duration_subtraction } diff --git a/tests/ui/unchecked_duration_subtraction.rs b/tests/ui/unchecked_duration_subtraction.rs index fff1d13720d9..bb0f71239642 100644 --- a/tests/ui/unchecked_duration_subtraction.rs +++ b/tests/ui/unchecked_duration_subtraction.rs @@ -7,10 +7,14 @@ fn main() { let second = Duration::from_secs(3); let _ = _first - second; + //~^ unchecked_duration_subtraction let _ = Instant::now() - Duration::from_secs(5); + //~^ unchecked_duration_subtraction let _ = _first - Duration::from_secs(5); + //~^ unchecked_duration_subtraction let _ = Instant::now() - second; + //~^ unchecked_duration_subtraction } diff --git a/tests/ui/unchecked_duration_subtraction.stderr b/tests/ui/unchecked_duration_subtraction.stderr index b5e9bab86b47..be291c320e68 100644 --- a/tests/ui/unchecked_duration_subtraction.stderr +++ b/tests/ui/unchecked_duration_subtraction.stderr @@ -8,19 +8,19 @@ LL | let _ = _first - second; = help: to override `-D warnings` add `#[allow(clippy::unchecked_duration_subtraction)]` error: unchecked subtraction of a 'Duration' from an 'Instant' - --> tests/ui/unchecked_duration_subtraction.rs:11:13 + --> tests/ui/unchecked_duration_subtraction.rs:12:13 | LL | let _ = Instant::now() - Duration::from_secs(5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Instant::now().checked_sub(Duration::from_secs(5)).unwrap()` error: unchecked subtraction of a 'Duration' from an 'Instant' - --> tests/ui/unchecked_duration_subtraction.rs:13:13 + --> tests/ui/unchecked_duration_subtraction.rs:15:13 | LL | let _ = _first - Duration::from_secs(5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `_first.checked_sub(Duration::from_secs(5)).unwrap()` error: unchecked subtraction of a 'Duration' from an 'Instant' - --> tests/ui/unchecked_duration_subtraction.rs:15:13 + --> tests/ui/unchecked_duration_subtraction.rs:18:13 | LL | let _ = Instant::now() - second; | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Instant::now().checked_sub(second).unwrap()` diff --git a/tests/ui/unconditional_recursion.rs b/tests/ui/unconditional_recursion.rs index b8476a7088a1..d9f4c07dc902 100644 --- a/tests/ui/unconditional_recursion.rs +++ b/tests/ui/unconditional_recursion.rs @@ -15,11 +15,13 @@ enum Foo { impl PartialEq for Foo { fn ne(&self, other: &Self) -> bool { - //~^ ERROR: function cannot return without recursing + //~^ unconditional_recursion + self != other } fn eq(&self, other: &Self) -> bool { - //~^ ERROR: function cannot return without recursing + //~^ unconditional_recursion + self == other } } @@ -31,9 +33,11 @@ enum Foo2 { impl PartialEq for Foo2 { fn ne(&self, other: &Self) -> bool { + //~^ unconditional_recursion self != &Foo2::B // no error here } fn eq(&self, other: &Self) -> bool { + //~^ unconditional_recursion self == &Foo2::B // no error here } } @@ -45,11 +49,14 @@ enum Foo3 { impl PartialEq for Foo3 { fn ne(&self, other: &Self) -> bool { - //~^ ERROR: function cannot return without recursing + //~^ unconditional_recursion + //~| ERROR: function cannot return without recursing self.ne(other) } fn eq(&self, other: &Self) -> bool { - //~^ ERROR: function cannot return without recursing + //~^ unconditional_recursion + //~| ERROR: function cannot return without recursing + self.eq(other) } } @@ -93,11 +100,13 @@ struct S; // Check the order doesn't matter. impl PartialEq for S { fn ne(&self, other: &Self) -> bool { - //~^ ERROR: function cannot return without recursing + //~^ unconditional_recursion + other != self } fn eq(&self, other: &Self) -> bool { - //~^ ERROR: function cannot return without recursing + //~^ unconditional_recursion + other == self } } @@ -107,12 +116,16 @@ struct S2; // Check that if the same element is compared, it's also triggering the lint. impl PartialEq for S2 { fn ne(&self, other: &Self) -> bool { - //~^ ERROR: function cannot return without recursing + //~^ unconditional_recursion + other != other + //~^ eq_op } fn eq(&self, other: &Self) -> bool { - //~^ ERROR: function cannot return without recursing + //~^ unconditional_recursion + other == other + //~^ eq_op } } @@ -120,12 +133,16 @@ struct S3; impl PartialEq for S3 { fn ne(&self, _other: &Self) -> bool { - //~^ ERROR: function cannot return without recursing + //~^ unconditional_recursion + self != self + //~^ eq_op } fn eq(&self, _other: &Self) -> bool { - //~^ ERROR: function cannot return without recursing + //~^ unconditional_recursion + self == self + //~^ eq_op } } @@ -152,7 +169,8 @@ macro_rules! impl_partial_eq { ($ty:ident) => { impl PartialEq for $ty { fn eq(&self, other: &Self) -> bool { - //~^ ERROR: function cannot return without recursing + //~^ unconditional_recursion + self == other } } @@ -181,7 +199,8 @@ struct S7<'a> { impl<'a> PartialEq for S7<'a> { fn eq(&self, other: &Self) -> bool { - //~^ ERROR: function cannot return without recursing + //~^ unconditional_recursion + let mine = &self.field; let theirs = &other.field; mine == theirs @@ -250,7 +269,8 @@ impl std::default::Default for S12 { impl S12 { fn new() -> Self { - //~^ ERROR: function cannot return without recursing + //~^ unconditional_recursion + Self::default() } @@ -289,7 +309,8 @@ struct S15<'a> { impl PartialEq for S15<'_> { fn eq(&self, other: &Self) -> bool { - //~^ ERROR: function cannot return without recursing + //~^ unconditional_recursion + let mine = &self.field; let theirs = &other.field; mine.eq(theirs) @@ -360,6 +381,7 @@ struct BadFromTy1<'a>(&'a ()); struct BadIntoTy1<'b>(&'b ()); impl<'a> From> for BadIntoTy1<'static> { fn from(f: BadFromTy1<'a>) -> Self { + //~^ unconditional_recursion f.into() } } @@ -369,6 +391,7 @@ struct BadFromTy2<'a>(&'a ()); struct BadIntoTy2<'b>(&'b ()); impl<'a> From> for BadIntoTy2<'static> { fn from(f: BadFromTy2<'a>) -> Self { + //~^ unconditional_recursion Into::into(f) } } diff --git a/tests/ui/unconditional_recursion.stderr b/tests/ui/unconditional_recursion.stderr index 6a0078ee0906..c6eaa6a0775c 100644 --- a/tests/ui/unconditional_recursion.stderr +++ b/tests/ui/unconditional_recursion.stderr @@ -1,9 +1,9 @@ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:47:5 + --> tests/ui/unconditional_recursion.rs:51:5 | LL | fn ne(&self, other: &Self) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing -LL | +... LL | self.ne(other) | -------------- recursive call site | @@ -12,18 +12,18 @@ LL | self.ne(other) = help: to override `-D warnings` add `#[allow(unconditional_recursion)]` error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:51:5 + --> tests/ui/unconditional_recursion.rs:56:5 | LL | fn eq(&self, other: &Self) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing -LL | +... LL | self.eq(other) | -------------- recursive call site | = help: a `loop` may express intention better if this is on purpose error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:216:5 + --> tests/ui/unconditional_recursion.rs:235:5 | LL | fn to_string(&self) -> String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing @@ -34,7 +34,7 @@ LL | self.to_string() = help: a `loop` may express intention better if this is on purpose error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:226:5 + --> tests/ui/unconditional_recursion.rs:245:5 | LL | fn to_string(&self) -> String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing @@ -45,7 +45,7 @@ LL | x.to_string() = help: a `loop` may express intention better if this is on purpose error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:237:5 + --> tests/ui/unconditional_recursion.rs:256:5 | LL | fn to_string(&self) -> String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing @@ -60,12 +60,13 @@ error: function cannot return without recursing | LL | / fn ne(&self, other: &Self) -> bool { LL | | +LL | | LL | | self != other LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:19:9 + --> tests/ui/unconditional_recursion.rs:20:9 | LL | self != other | ^^^^^^^^^^^^^ @@ -73,125 +74,132 @@ LL | self != other = help: to override `-D warnings` add `#[allow(clippy::unconditional_recursion)]` error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:21:5 + --> tests/ui/unconditional_recursion.rs:22:5 | LL | / fn eq(&self, other: &Self) -> bool { LL | | +LL | | LL | | self == other LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:23:9 + --> tests/ui/unconditional_recursion.rs:25:9 | LL | self == other | ^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:33:5 + --> tests/ui/unconditional_recursion.rs:35:5 | LL | / fn ne(&self, other: &Self) -> bool { +LL | | LL | | self != &Foo2::B // no error here -LL | | } - | |_____^ - | -note: recursive call site - --> tests/ui/unconditional_recursion.rs:34:9 - | -LL | self != &Foo2::B // no error here - | ^^^^^^^^^^^^^^^^ - -error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:36:5 - | -LL | / fn eq(&self, other: &Self) -> bool { -LL | | self == &Foo2::B // no error here LL | | } | |_____^ | note: recursive call site --> tests/ui/unconditional_recursion.rs:37:9 | +LL | self != &Foo2::B // no error here + | ^^^^^^^^^^^^^^^^ + +error: function cannot return without recursing + --> tests/ui/unconditional_recursion.rs:39:5 + | +LL | / fn eq(&self, other: &Self) -> bool { +LL | | +LL | | self == &Foo2::B // no error here +LL | | } + | |_____^ + | +note: recursive call site + --> tests/ui/unconditional_recursion.rs:41:9 + | LL | self == &Foo2::B // no error here | ^^^^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:47:5 + --> tests/ui/unconditional_recursion.rs:51:5 | LL | / fn ne(&self, other: &Self) -> bool { LL | | +LL | | LL | | self.ne(other) LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:49:9 + --> tests/ui/unconditional_recursion.rs:54:9 | LL | self.ne(other) | ^^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:51:5 + --> tests/ui/unconditional_recursion.rs:56:5 | LL | / fn eq(&self, other: &Self) -> bool { -LL | | -LL | | self.eq(other) +... | LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:53:9 + --> tests/ui/unconditional_recursion.rs:60:9 | LL | self.eq(other) | ^^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:95:5 + --> tests/ui/unconditional_recursion.rs:102:5 | LL | / fn ne(&self, other: &Self) -> bool { LL | | +LL | | LL | | other != self LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:97:9 + --> tests/ui/unconditional_recursion.rs:105:9 | LL | other != self | ^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:99:5 + --> tests/ui/unconditional_recursion.rs:107:5 | LL | / fn eq(&self, other: &Self) -> bool { LL | | +LL | | LL | | other == self LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:101:9 + --> tests/ui/unconditional_recursion.rs:110:9 | LL | other == self | ^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:109:5 + --> tests/ui/unconditional_recursion.rs:118:5 | LL | / fn ne(&self, other: &Self) -> bool { LL | | +LL | | LL | | other != other +LL | | LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:111:9 + --> tests/ui/unconditional_recursion.rs:121:9 | LL | other != other | ^^^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> tests/ui/unconditional_recursion.rs:111:9 + --> tests/ui/unconditional_recursion.rs:121:9 | LL | other != other | ^^^^^^^^^^^^^^ @@ -199,73 +207,80 @@ LL | other != other = note: `#[deny(clippy::eq_op)]` on by default error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:113:5 + --> tests/ui/unconditional_recursion.rs:124:5 | LL | / fn eq(&self, other: &Self) -> bool { LL | | +LL | | LL | | other == other +LL | | LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:115:9 + --> tests/ui/unconditional_recursion.rs:127:9 | LL | other == other | ^^^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> tests/ui/unconditional_recursion.rs:115:9 + --> tests/ui/unconditional_recursion.rs:127:9 | LL | other == other | ^^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:122:5 + --> tests/ui/unconditional_recursion.rs:135:5 | LL | / fn ne(&self, _other: &Self) -> bool { LL | | +LL | | LL | | self != self +LL | | LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:124:9 + --> tests/ui/unconditional_recursion.rs:138:9 | LL | self != self | ^^^^^^^^^^^^ error: equal expressions as operands to `!=` - --> tests/ui/unconditional_recursion.rs:124:9 + --> tests/ui/unconditional_recursion.rs:138:9 | LL | self != self | ^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:126:5 + --> tests/ui/unconditional_recursion.rs:141:5 | LL | / fn eq(&self, _other: &Self) -> bool { LL | | +LL | | LL | | self == self +LL | | LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:128:9 + --> tests/ui/unconditional_recursion.rs:144:9 | LL | self == self | ^^^^^^^^^^^^ error: equal expressions as operands to `==` - --> tests/ui/unconditional_recursion.rs:128:9 + --> tests/ui/unconditional_recursion.rs:144:9 | LL | self == self | ^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:154:13 + --> tests/ui/unconditional_recursion.rs:171:13 | LL | / fn eq(&self, other: &Self) -> bool { LL | | +LL | | LL | | self == other LL | | } | |_____________^ @@ -274,7 +289,7 @@ LL | impl_partial_eq!(S5); | -------------------- in this macro invocation | note: recursive call site - --> tests/ui/unconditional_recursion.rs:156:17 + --> tests/ui/unconditional_recursion.rs:174:17 | LL | self == other | ^^^^^^^^^^^^^ @@ -284,10 +299,11 @@ LL | impl_partial_eq!(S5); = note: this error originates in the macro `impl_partial_eq` (in Nightly builds, run with -Z macro-backtrace for more info) error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:183:5 + --> tests/ui/unconditional_recursion.rs:201:5 | LL | / fn eq(&self, other: &Self) -> bool { LL | | +LL | | LL | | let mine = &self.field; LL | | let theirs = &other.field; LL | | mine == theirs @@ -295,31 +311,33 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:187:9 + --> tests/ui/unconditional_recursion.rs:206:9 | LL | mine == theirs | ^^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:252:5 + --> tests/ui/unconditional_recursion.rs:271:5 | LL | / fn new() -> Self { LL | | +LL | | LL | | Self::default() LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:254:9 + --> tests/ui/unconditional_recursion.rs:274:9 | LL | Self::default() | ^^^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:291:5 + --> tests/ui/unconditional_recursion.rs:311:5 | LL | / fn eq(&self, other: &Self) -> bool { LL | | +LL | | LL | | let mine = &self.field; LL | | let theirs = &other.field; LL | | mine.eq(theirs) @@ -327,35 +345,37 @@ LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:295:9 + --> tests/ui/unconditional_recursion.rs:316:9 | LL | mine.eq(theirs) | ^^^^^^^^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:362:5 + --> tests/ui/unconditional_recursion.rs:383:5 | LL | / fn from(f: BadFromTy1<'a>) -> Self { +LL | | LL | | f.into() LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:363:9 + --> tests/ui/unconditional_recursion.rs:385:9 | LL | f.into() | ^^^^^^^^ error: function cannot return without recursing - --> tests/ui/unconditional_recursion.rs:371:5 + --> tests/ui/unconditional_recursion.rs:393:5 | LL | / fn from(f: BadFromTy2<'a>) -> Self { +LL | | LL | | Into::into(f) LL | | } | |_____^ | note: recursive call site - --> tests/ui/unconditional_recursion.rs:372:9 + --> tests/ui/unconditional_recursion.rs:395:9 | LL | Into::into(f) | ^^^^^^^^^^^^^ diff --git a/tests/ui/unicode.fixed b/tests/ui/unicode.fixed index f9efb4ec34c6..9234b440d964 100644 --- a/tests/ui/unicode.fixed +++ b/tests/ui/unicode.fixed @@ -3,16 +3,20 @@ #[warn(clippy::invisible_characters)] fn zero() { print!("Here >\u{200B}< is a ZWS, and \u{200B}another"); + //~^ invisible_characters print!("This\u{200B}is\u{200B}fine"); print!("Here >\u{AD}< is a SHY, and \u{AD}another"); + //~^ invisible_characters print!("This\u{ad}is\u{ad}fine"); print!("Here >\u{2060}< is a WJ, and \u{2060}another"); + //~^ invisible_characters print!("This\u{2060}is\u{2060}fine"); } #[warn(clippy::unicode_not_nfc)] fn canon() { print!("̀àh?"); + //~^ unicode_not_nfc print!("a\u{0300}h?"); // also ok } @@ -21,13 +25,16 @@ mod non_ascii_literal { fn uni() { print!("\u{dc}ben!"); + //~^ non_ascii_literal print!("\u{DC}ben!"); // this is ok } // issue 8013 fn single_quote() { const _EMPTY_BLOCK: char = '\u{25b1}'; + //~^ non_ascii_literal const _FULL_BLOCK: char = '\u{25b0}'; + //~^ non_ascii_literal } #[test] @@ -48,6 +55,7 @@ mod non_ascii_literal { #[test] fn denied() { let _ = "\u{60b2}\u{3057}\u{3044}\u{304b}\u{306a}\u{3001}\u{3053}\u{3053}\u{306b}\u{65e5}\u{672c}\u{8a9e}\u{3092}\u{66f8}\u{304f}\u{3053}\u{3068}\u{306f}\u{3067}\u{304d}\u{306a}\u{3044}\u{3002}"; + //~^ non_ascii_literal } } } diff --git a/tests/ui/unicode.rs b/tests/ui/unicode.rs index bba613e228ed..ada8bac8e049 100644 --- a/tests/ui/unicode.rs +++ b/tests/ui/unicode.rs @@ -3,16 +3,20 @@ #[warn(clippy::invisible_characters)] fn zero() { print!("Here >​< is a ZWS, and ​another"); + //~^ invisible_characters print!("This\u{200B}is\u{200B}fine"); print!("Here >­< is a SHY, and ­another"); + //~^ invisible_characters print!("This\u{ad}is\u{ad}fine"); print!("Here >⁠< is a WJ, and ⁠another"); + //~^ invisible_characters print!("This\u{2060}is\u{2060}fine"); } #[warn(clippy::unicode_not_nfc)] fn canon() { print!("̀àh?"); + //~^ unicode_not_nfc print!("a\u{0300}h?"); // also ok } @@ -21,13 +25,16 @@ mod non_ascii_literal { fn uni() { print!("Üben!"); + //~^ non_ascii_literal print!("\u{DC}ben!"); // this is ok } // issue 8013 fn single_quote() { const _EMPTY_BLOCK: char = '▱'; + //~^ non_ascii_literal const _FULL_BLOCK: char = '▰'; + //~^ non_ascii_literal } #[test] @@ -48,6 +55,7 @@ mod non_ascii_literal { #[test] fn denied() { let _ = "悲しいかな、ここに日本語を書くことはできない。"; + //~^ non_ascii_literal } } } diff --git a/tests/ui/unicode.stderr b/tests/ui/unicode.stderr index b004493300ee..c761ec89602f 100644 --- a/tests/ui/unicode.stderr +++ b/tests/ui/unicode.stderr @@ -8,19 +8,19 @@ LL | print!("Here >​< is a ZWS, and ​another"); = help: to override `-D warnings` add `#[allow(clippy::invisible_characters)]` error: invisible character detected - --> tests/ui/unicode.rs:7:12 + --> tests/ui/unicode.rs:8:12 | LL | print!("Here >­< is a SHY, and ­another"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing the string with: `"Here >\u{AD}< is a SHY, and \u{AD}another"` error: invisible character detected - --> tests/ui/unicode.rs:9:12 + --> tests/ui/unicode.rs:11:12 | LL | print!("Here >⁠< is a WJ, and ⁠another"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing the string with: `"Here >\u{2060}< is a WJ, and \u{2060}another"` error: non-NFC Unicode sequence detected - --> tests/ui/unicode.rs:15:12 + --> tests/ui/unicode.rs:18:12 | LL | print!("̀àh?"); | ^^^^^ help: consider replacing the string with: `"̀àh?"` @@ -29,37 +29,37 @@ LL | print!("̀àh?"); = help: to override `-D warnings` add `#[allow(clippy::unicode_not_nfc)]` error: literal non-ASCII character detected - --> tests/ui/unicode.rs:23:16 + --> tests/ui/unicode.rs:27:16 | LL | print!("Üben!"); | ^^^^^^^ help: consider replacing the string with: `"\u{dc}ben!"` | note: the lint level is defined here - --> tests/ui/unicode.rs:20:13 + --> tests/ui/unicode.rs:24:13 | LL | #![deny(clippy::non_ascii_literal)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: literal non-ASCII character detected - --> tests/ui/unicode.rs:29:36 + --> tests/ui/unicode.rs:34:36 | LL | const _EMPTY_BLOCK: char = '▱'; | ^^^ help: consider replacing the string with: `'\u{25b1}'` error: literal non-ASCII character detected - --> tests/ui/unicode.rs:30:35 + --> tests/ui/unicode.rs:36:35 | LL | const _FULL_BLOCK: char = '▰'; | ^^^ help: consider replacing the string with: `'\u{25b0}'` error: literal non-ASCII character detected - --> tests/ui/unicode.rs:50:21 + --> tests/ui/unicode.rs:57:21 | LL | let _ = "悲しいかな、ここに日本語を書くことはできない。"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing the string with: `"\u{60b2}\u{3057}\u{3044}\u{304b}\u{306a}\u{3001}\u{3053}\u{3053}\u{306b}\u{65e5}\u{672c}\u{8a9e}\u{3092}\u{66f8}\u{304f}\u{3053}\u{3068}\u{306f}\u{3067}\u{304d}\u{306a}\u{3044}\u{3002}"` | note: the lint level is defined here - --> tests/ui/unicode.rs:39:17 + --> tests/ui/unicode.rs:46:17 | LL | #![deny(clippy::non_ascii_literal)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/uninhabited_references.rs b/tests/ui/uninhabited_references.rs index 3569366ed056..9b3616ad5187 100644 --- a/tests/ui/uninhabited_references.rs +++ b/tests/ui/uninhabited_references.rs @@ -3,13 +3,16 @@ #![feature(never_type)] fn ret_uninh_ref() -> &'static std::convert::Infallible { + //~^ uninhabited_references unsafe { std::mem::transmute(&()) } } macro_rules! ret_something { ($name:ident, $ty:ty) => { fn $name(x: &$ty) -> &$ty { + //~^ uninhabited_references &*x + //~^ uninhabited_references } }; } @@ -20,4 +23,5 @@ ret_something!(id_never, !); fn main() { let x = ret_uninh_ref(); let _ = *x; + //~^ uninhabited_references } diff --git a/tests/ui/uninhabited_references.stderr b/tests/ui/uninhabited_references.stderr index 8c9b206f4296..ac05ab5bb4d4 100644 --- a/tests/ui/uninhabited_references.stderr +++ b/tests/ui/uninhabited_references.stderr @@ -8,7 +8,7 @@ LL | fn ret_uninh_ref() -> &'static std::convert::Infallible { = help: to override `-D warnings` add `#[allow(clippy::uninhabited_references)]` error: dereferencing a reference to an uninhabited type would be undefined behavior - --> tests/ui/uninhabited_references.rs:11:30 + --> tests/ui/uninhabited_references.rs:12:30 | LL | fn $name(x: &$ty) -> &$ty { | ^^^^ @@ -19,7 +19,7 @@ LL | ret_something!(id_never, !); = note: this error originates in the macro `ret_something` (in Nightly builds, run with -Z macro-backtrace for more info) error: dereferencing a reference to an uninhabited type is undefined behavior - --> tests/ui/uninhabited_references.rs:12:14 + --> tests/ui/uninhabited_references.rs:14:14 | LL | &*x | ^^ @@ -30,7 +30,7 @@ LL | ret_something!(id_never, !); = note: this error originates in the macro `ret_something` (in Nightly builds, run with -Z macro-backtrace for more info) error: dereferencing a reference to an uninhabited type is undefined behavior - --> tests/ui/uninhabited_references.rs:22:13 + --> tests/ui/uninhabited_references.rs:25:13 | LL | let _ = *x; | ^^ diff --git a/tests/ui/uninit.rs b/tests/ui/uninit.rs index 10a4c22b5b91..f74248c8aea8 100644 --- a/tests/ui/uninit.rs +++ b/tests/ui/uninit.rs @@ -10,8 +10,7 @@ union MyOwnMaybeUninit { fn main() { let _: usize = unsafe { MaybeUninit::uninit().assume_init() }; - //~^ ERROR: this call for this type may be undefined behavior - //~| NOTE: `#[deny(clippy::uninit_assumed_init)]` on by default + //~^ uninit_assumed_init // This is OK, because ZSTs do not contain data. let _: () = unsafe { MaybeUninit::uninit().assume_init() }; @@ -33,7 +32,7 @@ fn main() { // Was a false negative. let _: usize = unsafe { MaybeUninit::uninit().assume_init() }; - //~^ ERROR: this call for this type may be undefined behavior + //~^ uninit_assumed_init polymorphic::<()>(); polymorphic_maybe_uninit_array::<10>(); @@ -42,7 +41,7 @@ fn main() { fn polymorphic() { // We are conservative around polymorphic types. let _: T = unsafe { MaybeUninit::uninit().assume_init() }; - //~^ ERROR: this call for this type may be undefined behavior + //~^ uninit_assumed_init } fn polymorphic_maybe_uninit_array() { diff --git a/tests/ui/uninit.stderr b/tests/ui/uninit.stderr index 81577fe3fd47..d6f54dd61ca0 100644 --- a/tests/ui/uninit.stderr +++ b/tests/ui/uninit.stderr @@ -7,13 +7,13 @@ LL | let _: usize = unsafe { MaybeUninit::uninit().assume_init() }; = note: `#[deny(clippy::uninit_assumed_init)]` on by default error: this call for this type may be undefined behavior - --> tests/ui/uninit.rs:35:29 + --> tests/ui/uninit.rs:34:29 | LL | let _: usize = unsafe { MaybeUninit::uninit().assume_init() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this call for this type may be undefined behavior - --> tests/ui/uninit.rs:44:29 + --> tests/ui/uninit.rs:43:29 | LL | let _: T = unsafe { MaybeUninit::uninit().assume_init() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/uninit_vec.rs b/tests/ui/uninit_vec.rs index 464f88140bdb..a48397137992 100644 --- a/tests/ui/uninit_vec.rs +++ b/tests/ui/uninit_vec.rs @@ -16,40 +16,46 @@ union MyOwnMaybeUninit { // https://github.com/rust-lang/rust/issues/119620 unsafe fn requires_paramenv() { let mut vec = Vec::>::with_capacity(1); + //~^ uninit_vec vec.set_len(1); } fn main() { // with_capacity() -> set_len() should be detected let mut vec: Vec = Vec::with_capacity(1000); - //~^ ERROR: calling `set_len()` immediately after reserving a buffer creates uninitial + //~^ uninit_vec + unsafe { vec.set_len(200); } // reserve() -> set_len() should be detected vec.reserve(1000); - //~^ ERROR: calling `set_len()` immediately after reserving a buffer creates uninitial + //~^ uninit_vec + unsafe { vec.set_len(200); } // new() -> set_len() should be detected let mut vec: Vec = Vec::new(); - //~^ ERROR: calling `set_len()` on empty `Vec` creates out-of-bound values + //~^ uninit_vec + unsafe { vec.set_len(200); } // default() -> set_len() should be detected let mut vec: Vec = Default::default(); - //~^ ERROR: calling `set_len()` on empty `Vec` creates out-of-bound values + //~^ uninit_vec + unsafe { vec.set_len(200); } let mut vec: Vec = Vec::default(); - //~^ ERROR: calling `set_len()` on empty `Vec` creates out-of-bound values + //~^ uninit_vec + unsafe { vec.set_len(200); } @@ -57,16 +63,19 @@ fn main() { // test when both calls are enclosed in the same unsafe block unsafe { let mut vec: Vec = Vec::with_capacity(1000); - //~^ ERROR: calling `set_len()` immediately after reserving a buffer creates unini + //~^ uninit_vec + vec.set_len(200); vec.reserve(1000); - //~^ ERROR: calling `set_len()` immediately after reserving a buffer creates unini + //~^ uninit_vec + vec.set_len(200); } let mut vec: Vec = Vec::with_capacity(1000); - //~^ ERROR: calling `set_len()` immediately after reserving a buffer creates uninitial + //~^ uninit_vec + unsafe { // test the case where there are other statements in the following unsafe block vec.set_len(200); @@ -76,13 +85,15 @@ fn main() { // handle vec stored in the field of a struct let mut my_vec = MyVec::default(); my_vec.vec.reserve(1000); - //~^ ERROR: calling `set_len()` immediately after reserving a buffer creates uninitial + //~^ uninit_vec + unsafe { my_vec.vec.set_len(200); } my_vec.vec = Vec::with_capacity(1000); - //~^ ERROR: calling `set_len()` immediately after reserving a buffer creates uninitial + //~^ uninit_vec + unsafe { my_vec.vec.set_len(200); } @@ -137,7 +148,8 @@ fn main() { fn polymorphic() { // We are conservative around polymorphic types. let mut vec: Vec = Vec::with_capacity(1000); - //~^ ERROR: calling `set_len()` immediately after reserving a buffer creates unini + //~^ uninit_vec + unsafe { vec.set_len(10); } @@ -165,6 +177,7 @@ fn main() { let mut vec: Vec> = Vec::with_capacity(1); //~^ uninit_vec + unsafe { vec.set_len(1); } @@ -178,6 +191,7 @@ fn main() { // Enums can have a discriminant that can't be uninit, so this should still warn let mut vec: Vec> = Vec::with_capacity(1); //~^ uninit_vec + unsafe { vec.set_len(1); } diff --git a/tests/ui/uninit_vec.stderr b/tests/ui/uninit_vec.stderr index e7c81cf792f2..7ff6140a2c3e 100644 --- a/tests/ui/uninit_vec.stderr +++ b/tests/ui/uninit_vec.stderr @@ -3,6 +3,7 @@ error: calling `set_len()` immediately after reserving a buffer creates uninitia | LL | let mut vec = Vec::>::with_capacity(1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | LL | vec.set_len(1); | ^^^^^^^^^^^^^^ | @@ -11,7 +12,7 @@ LL | vec.set_len(1); = help: to override `-D warnings` add `#[allow(clippy::uninit_vec)]` error: calling `set_len()` immediately after reserving a buffer creates uninitialized values - --> tests/ui/uninit_vec.rs:24:5 + --> tests/ui/uninit_vec.rs:25:5 | LL | let mut vec: Vec = Vec::with_capacity(1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +23,7 @@ LL | vec.set_len(200); = help: initialize the buffer or wrap the content in `MaybeUninit` error: calling `set_len()` immediately after reserving a buffer creates uninitialized values - --> tests/ui/uninit_vec.rs:31:5 + --> tests/ui/uninit_vec.rs:33:5 | LL | vec.reserve(1000); | ^^^^^^^^^^^^^^^^^^ @@ -33,7 +34,7 @@ LL | vec.set_len(200); = help: initialize the buffer or wrap the content in `MaybeUninit` error: calling `set_len()` on empty `Vec` creates out-of-bound values - --> tests/ui/uninit_vec.rs:38:5 + --> tests/ui/uninit_vec.rs:41:5 | LL | let mut vec: Vec = Vec::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -42,7 +43,7 @@ LL | vec.set_len(200); | ^^^^^^^^^^^^^^^^ error: calling `set_len()` on empty `Vec` creates out-of-bound values - --> tests/ui/uninit_vec.rs:45:5 + --> tests/ui/uninit_vec.rs:49:5 | LL | let mut vec: Vec = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -51,7 +52,7 @@ LL | vec.set_len(200); | ^^^^^^^^^^^^^^^^ error: calling `set_len()` on empty `Vec` creates out-of-bound values - --> tests/ui/uninit_vec.rs:51:5 + --> tests/ui/uninit_vec.rs:56:5 | LL | let mut vec: Vec = Vec::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +61,7 @@ LL | vec.set_len(200); | ^^^^^^^^^^^^^^^^ error: calling `set_len()` immediately after reserving a buffer creates uninitialized values - --> tests/ui/uninit_vec.rs:68:5 + --> tests/ui/uninit_vec.rs:76:5 | LL | let mut vec: Vec = Vec::with_capacity(1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -71,7 +72,7 @@ LL | vec.set_len(200); = help: initialize the buffer or wrap the content in `MaybeUninit` error: calling `set_len()` immediately after reserving a buffer creates uninitialized values - --> tests/ui/uninit_vec.rs:78:5 + --> tests/ui/uninit_vec.rs:87:5 | LL | my_vec.vec.reserve(1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -82,7 +83,7 @@ LL | my_vec.vec.set_len(200); = help: initialize the buffer or wrap the content in `MaybeUninit` error: calling `set_len()` immediately after reserving a buffer creates uninitialized values - --> tests/ui/uninit_vec.rs:84:5 + --> tests/ui/uninit_vec.rs:94:5 | LL | my_vec.vec = Vec::with_capacity(1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -93,29 +94,29 @@ LL | my_vec.vec.set_len(200); = help: initialize the buffer or wrap the content in `MaybeUninit` error: calling `set_len()` immediately after reserving a buffer creates uninitialized values - --> tests/ui/uninit_vec.rs:59:9 + --> tests/ui/uninit_vec.rs:65:9 | LL | let mut vec: Vec = Vec::with_capacity(1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | +... LL | vec.set_len(200); | ^^^^^^^^^^^^^^^^ | = help: initialize the buffer or wrap the content in `MaybeUninit` error: calling `set_len()` immediately after reserving a buffer creates uninitialized values - --> tests/ui/uninit_vec.rs:63:9 + --> tests/ui/uninit_vec.rs:70:9 | LL | vec.reserve(1000); | ^^^^^^^^^^^^^^^^^^ -LL | +... LL | vec.set_len(200); | ^^^^^^^^^^^^^^^^ | = help: initialize the buffer or wrap the content in `MaybeUninit` error: calling `set_len()` immediately after reserving a buffer creates uninitialized values - --> tests/ui/uninit_vec.rs:139:9 + --> tests/ui/uninit_vec.rs:150:9 | LL | let mut vec: Vec = Vec::with_capacity(1000); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -126,7 +127,7 @@ LL | vec.set_len(10); = help: initialize the buffer or wrap the content in `MaybeUninit` error: calling `set_len()` immediately after reserving a buffer creates uninitialized values - --> tests/ui/uninit_vec.rs:166:9 + --> tests/ui/uninit_vec.rs:178:9 | LL | let mut vec: Vec> = Vec::with_capacity(1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -137,7 +138,7 @@ LL | vec.set_len(1); = help: initialize the buffer or wrap the content in `MaybeUninit` error: calling `set_len()` immediately after reserving a buffer creates uninitialized values - --> tests/ui/uninit_vec.rs:179:9 + --> tests/ui/uninit_vec.rs:192:9 | LL | let mut vec: Vec> = Vec::with_capacity(1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/uninlined_format_args.fixed b/tests/ui/uninlined_format_args.fixed index 111a2e1987c8..7b609d9163a9 100644 --- a/tests/ui/uninlined_format_args.fixed +++ b/tests/ui/uninlined_format_args.fixed @@ -43,75 +43,141 @@ fn tester(fn_arg: i32) { let _: &[u8; 3] = b" "; // <- println!("val='{local_i32}'"); + //~^ uninlined_format_args println!("val='{local_i32}'"); // 3 spaces + // + //~^^ uninlined_format_args println!("val='{local_i32}'"); // tab + // + //~^^ uninlined_format_args println!("val='{local_i32}'"); // space+tab + // + //~^^ uninlined_format_args println!("val='{local_i32}'"); // tab+space + // + //~^^ uninlined_format_args println!( + //~^ uninlined_format_args "val='{local_i32}'" ); println!("{local_i32}"); + //~^ uninlined_format_args println!("{fn_arg}"); + //~^ uninlined_format_args println!("{local_i32:?}"); + //~^ uninlined_format_args println!("{local_i32:#?}"); + //~^ uninlined_format_args println!("{local_i32:4}"); + //~^ uninlined_format_args println!("{local_i32:04}"); + //~^ uninlined_format_args println!("{local_i32:<3}"); + //~^ uninlined_format_args println!("{local_i32:#010x}"); + //~^ uninlined_format_args println!("{local_f64:.1}"); + //~^ uninlined_format_args println!("Hello {} is {:.*}", "x", local_i32, local_f64); println!("Hello {} is {:.*}", local_i32, 5, local_f64); println!("Hello {} is {2:.*}", local_i32, 5, local_f64); println!("{local_i32} {local_f64}"); + //~^ uninlined_format_args println!("{}, {}", local_i32, local_opt.unwrap()); println!("{val}"); + //~^ uninlined_format_args println!("{val}"); + //~^ uninlined_format_args println!("{} {1}", local_i32, 42); println!("val='{local_i32}'"); + //~^ uninlined_format_args println!("val='{local_i32}'"); + //~^ uninlined_format_args println!("val='{local_i32}'"); + //~^ uninlined_format_args println!("val='{fn_arg}'"); + //~^ uninlined_format_args println!("{local_i32}"); + //~^ uninlined_format_args println!("{local_i32:?}"); + //~^ uninlined_format_args println!("{local_i32:#?}"); + //~^ uninlined_format_args println!("{local_i32:04}"); + //~^ uninlined_format_args println!("{local_i32:<3}"); + //~^ uninlined_format_args println!("{local_i32:#010x}"); + //~^ uninlined_format_args println!("{local_f64:.1}"); + //~^ uninlined_format_args println!("{local_i32} {local_i32}"); + //~^ uninlined_format_args println!("{local_f64} {local_i32} {local_i32} {local_f64}"); + //~^ uninlined_format_args println!("{local_i32} {local_f64}"); + //~^ uninlined_format_args println!("{local_f64} {local_i32}"); + //~^ uninlined_format_args println!("{local_f64} {local_i32} {local_f64} {local_i32}"); + //~^ uninlined_format_args println!("{1} {0}", "str", local_i32); println!("{local_i32}"); + //~^ uninlined_format_args println!("{local_i32:width$}"); + //~^ uninlined_format_args println!("{local_i32:width$}"); + //~^ uninlined_format_args println!("{local_i32:.prec$}"); + //~^ uninlined_format_args println!("{local_i32:.prec$}"); + //~^ uninlined_format_args println!("{val:val$}"); + //~^ uninlined_format_args println!("{val:val$}"); + //~^ uninlined_format_args println!("{val:val$.val$}"); + //~^ uninlined_format_args println!("{val:val$.val$}"); + //~^ uninlined_format_args println!("{val:val$.val$}"); + //~^ uninlined_format_args println!("{val:val$.val$}"); + //~^ uninlined_format_args println!("{val:val$.val$}"); + //~^ uninlined_format_args println!("{val:val$.val$}"); + //~^ uninlined_format_args println!("{val:val$.val$}"); + //~^ uninlined_format_args println!("{val:val$.val$}"); + //~^ uninlined_format_args println!("{width:width$}"); + //~^ uninlined_format_args println!("{local_i32:width$}"); + //~^ uninlined_format_args println!("{width:width$}"); + //~^ uninlined_format_args println!("{local_i32:width$}"); + //~^ uninlined_format_args println!("{prec:.prec$}"); + //~^ uninlined_format_args println!("{local_i32:.prec$}"); + //~^ uninlined_format_args println!("{prec:.prec$}"); + //~^ uninlined_format_args println!("{local_i32:.prec$}"); + //~^ uninlined_format_args println!("{width:width$.prec$}"); + //~^ uninlined_format_args println!("{width:width$.prec$}"); + //~^ uninlined_format_args println!("{local_f64:width$.prec$}"); + //~^ uninlined_format_args println!("{local_f64:width$.prec$} {local_f64} {width} {prec}"); + //~^ uninlined_format_args println!( + //~^ uninlined_format_args "{local_i32:width$.prec$} {local_i32:prec$.width$} {width:local_i32$.prec$} {width:prec$.local_i32$} {prec:local_i32$.width$} {prec:width$.local_i32$}", ); println!( @@ -122,8 +188,11 @@ fn tester(fn_arg: i32) { 1 + 2 ); println!("Width = {local_i32}, value with width = {local_f64:local_i32$}"); + //~^ uninlined_format_args println!("{local_i32:width$.prec$}"); + //~^ uninlined_format_args println!("{width:width$.prec$}"); + //~^ uninlined_format_args println!("{}", format!("{}", local_i32)); my_println!("{}", local_i32); my_println_args!("{}", local_i32); @@ -143,21 +212,26 @@ fn tester(fn_arg: i32) { println!(no_param_str!(), local_i32); println!( + //~^ uninlined_format_args "{val}", ); println!("{val}"); + //~^ uninlined_format_args println!(with_span!("{0} {1}" "{1} {0}"), local_i32, local_f64); println!("{}", with_span!(span val)); if local_i32 > 0 { panic!("p1 {local_i32}"); + //~^ uninlined_format_args } if local_i32 > 0 { panic!("p2 {local_i32}"); + //~^ uninlined_format_args } if local_i32 > 0 { panic!("p3 {local_i32}"); + //~^ uninlined_format_args } if local_i32 > 0 { panic!("p4 {local_i32}"); @@ -178,6 +252,7 @@ fn _under_msrv() { fn _meets_msrv() { let local_i32 = 1; println!("expand='{local_i32}'"); + //~^ uninlined_format_args } fn _do_not_fire() { @@ -280,7 +355,11 @@ fn user_format() { let local_f64 = 2.0; usr_println!(true, "val='{local_i32}'"); + //~^ uninlined_format_args usr_println!(true, "{local_i32}"); + //~^ uninlined_format_args usr_println!(true, "{local_i32:#010x}"); + //~^ uninlined_format_args usr_println!(true, "{local_f64:.1}"); + //~^ uninlined_format_args } diff --git a/tests/ui/uninlined_format_args.rs b/tests/ui/uninlined_format_args.rs index 81fe24765674..14e0b6caabc0 100644 --- a/tests/ui/uninlined_format_args.rs +++ b/tests/ui/uninlined_format_args.rs @@ -43,77 +43,143 @@ fn tester(fn_arg: i32) { let _: &[u8; 3] = b" "; // <- println!("val='{}'", local_i32); + //~^ uninlined_format_args println!("val='{ }'", local_i32); // 3 spaces + // + //~^^ uninlined_format_args println!("val='{ }'", local_i32); // tab + // + //~^^ uninlined_format_args println!("val='{ }'", local_i32); // space+tab + // + //~^^ uninlined_format_args println!("val='{ }'", local_i32); // tab+space + // + //~^^ uninlined_format_args println!( + //~^ uninlined_format_args "val='{ }'", local_i32 ); println!("{}", local_i32); + //~^ uninlined_format_args println!("{}", fn_arg); + //~^ uninlined_format_args println!("{:?}", local_i32); + //~^ uninlined_format_args println!("{:#?}", local_i32); + //~^ uninlined_format_args println!("{:4}", local_i32); + //~^ uninlined_format_args println!("{:04}", local_i32); + //~^ uninlined_format_args println!("{:<3}", local_i32); + //~^ uninlined_format_args println!("{:#010x}", local_i32); + //~^ uninlined_format_args println!("{:.1}", local_f64); + //~^ uninlined_format_args println!("Hello {} is {:.*}", "x", local_i32, local_f64); println!("Hello {} is {:.*}", local_i32, 5, local_f64); println!("Hello {} is {2:.*}", local_i32, 5, local_f64); println!("{} {}", local_i32, local_f64); + //~^ uninlined_format_args println!("{}, {}", local_i32, local_opt.unwrap()); println!("{}", val); + //~^ uninlined_format_args println!("{}", v = val); + //~^ uninlined_format_args println!("{} {1}", local_i32, 42); println!("val='{\t }'", local_i32); + //~^ uninlined_format_args println!("val='{\n }'", local_i32); + //~^ uninlined_format_args println!("val='{local_i32}'", local_i32 = local_i32); + //~^ uninlined_format_args println!("val='{local_i32}'", local_i32 = fn_arg); + //~^ uninlined_format_args println!("{0}", local_i32); + //~^ uninlined_format_args println!("{0:?}", local_i32); + //~^ uninlined_format_args println!("{0:#?}", local_i32); + //~^ uninlined_format_args println!("{0:04}", local_i32); + //~^ uninlined_format_args println!("{0:<3}", local_i32); + //~^ uninlined_format_args println!("{0:#010x}", local_i32); + //~^ uninlined_format_args println!("{0:.1}", local_f64); + //~^ uninlined_format_args println!("{0} {0}", local_i32); + //~^ uninlined_format_args println!("{1} {} {0} {}", local_i32, local_f64); + //~^ uninlined_format_args println!("{0} {1}", local_i32, local_f64); + //~^ uninlined_format_args println!("{1} {0}", local_i32, local_f64); + //~^ uninlined_format_args println!("{1} {0} {1} {0}", local_i32, local_f64); + //~^ uninlined_format_args println!("{1} {0}", "str", local_i32); println!("{v}", v = local_i32); + //~^ uninlined_format_args println!("{local_i32:0$}", width); + //~^ uninlined_format_args println!("{local_i32:w$}", w = width); + //~^ uninlined_format_args println!("{local_i32:.0$}", prec); + //~^ uninlined_format_args println!("{local_i32:.p$}", p = prec); + //~^ uninlined_format_args println!("{:0$}", v = val); + //~^ uninlined_format_args println!("{0:0$}", v = val); + //~^ uninlined_format_args println!("{:0$.0$}", v = val); + //~^ uninlined_format_args println!("{0:0$.0$}", v = val); + //~^ uninlined_format_args println!("{0:0$.v$}", v = val); + //~^ uninlined_format_args println!("{0:v$.0$}", v = val); + //~^ uninlined_format_args println!("{v:0$.0$}", v = val); + //~^ uninlined_format_args println!("{v:v$.0$}", v = val); + //~^ uninlined_format_args println!("{v:0$.v$}", v = val); + //~^ uninlined_format_args println!("{v:v$.v$}", v = val); + //~^ uninlined_format_args println!("{:0$}", width); + //~^ uninlined_format_args println!("{:1$}", local_i32, width); + //~^ uninlined_format_args println!("{:w$}", w = width); + //~^ uninlined_format_args println!("{:w$}", local_i32, w = width); + //~^ uninlined_format_args println!("{:.0$}", prec); + //~^ uninlined_format_args println!("{:.1$}", local_i32, prec); + //~^ uninlined_format_args println!("{:.p$}", p = prec); + //~^ uninlined_format_args println!("{:.p$}", local_i32, p = prec); + //~^ uninlined_format_args println!("{:0$.1$}", width, prec); + //~^ uninlined_format_args println!("{:0$.w$}", width, w = prec); + //~^ uninlined_format_args println!("{:1$.2$}", local_f64, width, prec); + //~^ uninlined_format_args println!("{:1$.2$} {0} {1} {2}", local_f64, width, prec); + //~^ uninlined_format_args println!( + //~^ uninlined_format_args "{0:1$.2$} {0:2$.1$} {1:0$.2$} {1:2$.0$} {2:0$.1$} {2:1$.0$}", local_i32, width, prec, ); @@ -125,8 +191,11 @@ fn tester(fn_arg: i32) { 1 + 2 ); println!("Width = {}, value with width = {:0$}", local_i32, local_f64); + //~^ uninlined_format_args println!("{:w$.p$}", local_i32, w = width, p = prec); + //~^ uninlined_format_args println!("{:w$.p$}", w = width, p = prec); + //~^ uninlined_format_args println!("{}", format!("{}", local_i32)); my_println!("{}", local_i32); my_println_args!("{}", local_i32); @@ -146,23 +215,28 @@ fn tester(fn_arg: i32) { println!(no_param_str!(), local_i32); println!( + //~^ uninlined_format_args "{}", // comment with a comma , in it val, ); println!("{}", /* comment with a comma , in it */ val); + //~^ uninlined_format_args println!(with_span!("{0} {1}" "{1} {0}"), local_i32, local_f64); println!("{}", with_span!(span val)); if local_i32 > 0 { panic!("p1 {}", local_i32); + //~^ uninlined_format_args } if local_i32 > 0 { panic!("p2 {0}", local_i32); + //~^ uninlined_format_args } if local_i32 > 0 { panic!("p3 {local_i32}", local_i32 = local_i32); + //~^ uninlined_format_args } if local_i32 > 0 { panic!("p4 {local_i32}"); @@ -183,6 +257,7 @@ fn _under_msrv() { fn _meets_msrv() { let local_i32 = 1; println!("expand='{}'", local_i32); + //~^ uninlined_format_args } fn _do_not_fire() { @@ -285,7 +360,11 @@ fn user_format() { let local_f64 = 2.0; usr_println!(true, "val='{}'", local_i32); + //~^ uninlined_format_args usr_println!(true, "{}", local_i32); + //~^ uninlined_format_args usr_println!(true, "{:#010x}", local_i32); + //~^ uninlined_format_args usr_println!(true, "{:.1}", local_f64); + //~^ uninlined_format_args } diff --git a/tests/ui/uninlined_format_args.stderr b/tests/ui/uninlined_format_args.stderr index 77961fea2c53..7e62a095eadf 100644 --- a/tests/ui/uninlined_format_args.stderr +++ b/tests/ui/uninlined_format_args.stderr @@ -13,7 +13,7 @@ LL + println!("val='{local_i32}'"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:46:5 + --> tests/ui/uninlined_format_args.rs:47:5 | LL | println!("val='{ }'", local_i32); // 3 spaces | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + println!("val='{local_i32}'"); // 3 spaces | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:47:5 + --> tests/ui/uninlined_format_args.rs:50:5 | LL | println!("val='{ }'", local_i32); // tab | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + println!("val='{local_i32}'"); // tab | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:48:5 + --> tests/ui/uninlined_format_args.rs:53:5 | LL | println!("val='{ }'", local_i32); // space+tab | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + println!("val='{local_i32}'"); // space+tab | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:49:5 + --> tests/ui/uninlined_format_args.rs:56:5 | LL | println!("val='{ }'", local_i32); // tab+space | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,9 +61,10 @@ LL + println!("val='{local_i32}'"); // tab+space | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:50:5 + --> tests/ui/uninlined_format_args.rs:59:5 | LL | / println!( +LL | | LL | | "val='{ LL | | }'", LL | | local_i32 @@ -71,7 +72,7 @@ LL | | ); | |_____^ error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:55:5 + --> tests/ui/uninlined_format_args.rs:65:5 | LL | println!("{}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -83,7 +84,7 @@ LL + println!("{local_i32}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:56:5 + --> tests/ui/uninlined_format_args.rs:67:5 | LL | println!("{}", fn_arg); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -95,7 +96,7 @@ LL + println!("{fn_arg}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:57:5 + --> tests/ui/uninlined_format_args.rs:69:5 | LL | println!("{:?}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -107,7 +108,7 @@ LL + println!("{local_i32:?}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:58:5 + --> tests/ui/uninlined_format_args.rs:71:5 | LL | println!("{:#?}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -119,7 +120,7 @@ LL + println!("{local_i32:#?}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:59:5 + --> tests/ui/uninlined_format_args.rs:73:5 | LL | println!("{:4}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -131,7 +132,7 @@ LL + println!("{local_i32:4}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:60:5 + --> tests/ui/uninlined_format_args.rs:75:5 | LL | println!("{:04}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -143,7 +144,7 @@ LL + println!("{local_i32:04}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:61:5 + --> tests/ui/uninlined_format_args.rs:77:5 | LL | println!("{:<3}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -155,7 +156,7 @@ LL + println!("{local_i32:<3}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:62:5 + --> tests/ui/uninlined_format_args.rs:79:5 | LL | println!("{:#010x}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -167,7 +168,7 @@ LL + println!("{local_i32:#010x}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:63:5 + --> tests/ui/uninlined_format_args.rs:81:5 | LL | println!("{:.1}", local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -179,7 +180,7 @@ LL + println!("{local_f64:.1}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:67:5 + --> tests/ui/uninlined_format_args.rs:86:5 | LL | println!("{} {}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -191,7 +192,7 @@ LL + println!("{local_i32} {local_f64}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:69:5 + --> tests/ui/uninlined_format_args.rs:89:5 | LL | println!("{}", val); | ^^^^^^^^^^^^^^^^^^^ @@ -203,7 +204,7 @@ LL + println!("{val}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:70:5 + --> tests/ui/uninlined_format_args.rs:91:5 | LL | println!("{}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -215,7 +216,7 @@ LL + println!("{val}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:72:5 + --> tests/ui/uninlined_format_args.rs:94:5 | LL | println!("val='{\t }'", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -227,7 +228,7 @@ LL + println!("val='{local_i32}'"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:73:5 + --> tests/ui/uninlined_format_args.rs:96:5 | LL | println!("val='{\n }'", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -239,7 +240,7 @@ LL + println!("val='{local_i32}'"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:74:5 + --> tests/ui/uninlined_format_args.rs:98:5 | LL | println!("val='{local_i32}'", local_i32 = local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -251,7 +252,7 @@ LL + println!("val='{local_i32}'"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:75:5 + --> tests/ui/uninlined_format_args.rs:100:5 | LL | println!("val='{local_i32}'", local_i32 = fn_arg); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -263,7 +264,7 @@ LL + println!("val='{fn_arg}'"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:76:5 + --> tests/ui/uninlined_format_args.rs:102:5 | LL | println!("{0}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -275,7 +276,7 @@ LL + println!("{local_i32}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:77:5 + --> tests/ui/uninlined_format_args.rs:104:5 | LL | println!("{0:?}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -287,7 +288,7 @@ LL + println!("{local_i32:?}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:78:5 + --> tests/ui/uninlined_format_args.rs:106:5 | LL | println!("{0:#?}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -299,7 +300,7 @@ LL + println!("{local_i32:#?}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:79:5 + --> tests/ui/uninlined_format_args.rs:108:5 | LL | println!("{0:04}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -311,7 +312,7 @@ LL + println!("{local_i32:04}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:80:5 + --> tests/ui/uninlined_format_args.rs:110:5 | LL | println!("{0:<3}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -323,7 +324,7 @@ LL + println!("{local_i32:<3}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:81:5 + --> tests/ui/uninlined_format_args.rs:112:5 | LL | println!("{0:#010x}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -335,7 +336,7 @@ LL + println!("{local_i32:#010x}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:82:5 + --> tests/ui/uninlined_format_args.rs:114:5 | LL | println!("{0:.1}", local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -347,7 +348,7 @@ LL + println!("{local_f64:.1}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:83:5 + --> tests/ui/uninlined_format_args.rs:116:5 | LL | println!("{0} {0}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -359,7 +360,7 @@ LL + println!("{local_i32} {local_i32}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:84:5 + --> tests/ui/uninlined_format_args.rs:118:5 | LL | println!("{1} {} {0} {}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -371,7 +372,7 @@ LL + println!("{local_f64} {local_i32} {local_i32} {local_f64}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:85:5 + --> tests/ui/uninlined_format_args.rs:120:5 | LL | println!("{0} {1}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -383,7 +384,7 @@ LL + println!("{local_i32} {local_f64}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:86:5 + --> tests/ui/uninlined_format_args.rs:122:5 | LL | println!("{1} {0}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -395,7 +396,7 @@ LL + println!("{local_f64} {local_i32}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:87:5 + --> tests/ui/uninlined_format_args.rs:124:5 | LL | println!("{1} {0} {1} {0}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -407,7 +408,7 @@ LL + println!("{local_f64} {local_i32} {local_f64} {local_i32}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:89:5 + --> tests/ui/uninlined_format_args.rs:127:5 | LL | println!("{v}", v = local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -419,7 +420,7 @@ LL + println!("{local_i32}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:90:5 + --> tests/ui/uninlined_format_args.rs:129:5 | LL | println!("{local_i32:0$}", width); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -431,7 +432,7 @@ LL + println!("{local_i32:width$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:91:5 + --> tests/ui/uninlined_format_args.rs:131:5 | LL | println!("{local_i32:w$}", w = width); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -443,7 +444,7 @@ LL + println!("{local_i32:width$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:92:5 + --> tests/ui/uninlined_format_args.rs:133:5 | LL | println!("{local_i32:.0$}", prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -455,7 +456,7 @@ LL + println!("{local_i32:.prec$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:93:5 + --> tests/ui/uninlined_format_args.rs:135:5 | LL | println!("{local_i32:.p$}", p = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -467,7 +468,7 @@ LL + println!("{local_i32:.prec$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:94:5 + --> tests/ui/uninlined_format_args.rs:137:5 | LL | println!("{:0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -479,7 +480,7 @@ LL + println!("{val:val$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:95:5 + --> tests/ui/uninlined_format_args.rs:139:5 | LL | println!("{0:0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -491,7 +492,7 @@ LL + println!("{val:val$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:96:5 + --> tests/ui/uninlined_format_args.rs:141:5 | LL | println!("{:0$.0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -503,7 +504,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:97:5 + --> tests/ui/uninlined_format_args.rs:143:5 | LL | println!("{0:0$.0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -515,7 +516,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:98:5 + --> tests/ui/uninlined_format_args.rs:145:5 | LL | println!("{0:0$.v$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -527,7 +528,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:99:5 + --> tests/ui/uninlined_format_args.rs:147:5 | LL | println!("{0:v$.0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -539,7 +540,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:100:5 + --> tests/ui/uninlined_format_args.rs:149:5 | LL | println!("{v:0$.0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -551,7 +552,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:101:5 + --> tests/ui/uninlined_format_args.rs:151:5 | LL | println!("{v:v$.0$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -563,7 +564,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:102:5 + --> tests/ui/uninlined_format_args.rs:153:5 | LL | println!("{v:0$.v$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -575,7 +576,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:103:5 + --> tests/ui/uninlined_format_args.rs:155:5 | LL | println!("{v:v$.v$}", v = val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -587,7 +588,7 @@ LL + println!("{val:val$.val$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:104:5 + --> tests/ui/uninlined_format_args.rs:157:5 | LL | println!("{:0$}", width); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -599,7 +600,7 @@ LL + println!("{width:width$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:105:5 + --> tests/ui/uninlined_format_args.rs:159:5 | LL | println!("{:1$}", local_i32, width); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -611,7 +612,7 @@ LL + println!("{local_i32:width$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:106:5 + --> tests/ui/uninlined_format_args.rs:161:5 | LL | println!("{:w$}", w = width); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -623,7 +624,7 @@ LL + println!("{width:width$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:107:5 + --> tests/ui/uninlined_format_args.rs:163:5 | LL | println!("{:w$}", local_i32, w = width); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -635,7 +636,7 @@ LL + println!("{local_i32:width$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:108:5 + --> tests/ui/uninlined_format_args.rs:165:5 | LL | println!("{:.0$}", prec); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -647,7 +648,7 @@ LL + println!("{prec:.prec$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:109:5 + --> tests/ui/uninlined_format_args.rs:167:5 | LL | println!("{:.1$}", local_i32, prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -659,7 +660,7 @@ LL + println!("{local_i32:.prec$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:110:5 + --> tests/ui/uninlined_format_args.rs:169:5 | LL | println!("{:.p$}", p = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -671,7 +672,7 @@ LL + println!("{prec:.prec$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:111:5 + --> tests/ui/uninlined_format_args.rs:171:5 | LL | println!("{:.p$}", local_i32, p = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -683,7 +684,7 @@ LL + println!("{local_i32:.prec$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:112:5 + --> tests/ui/uninlined_format_args.rs:173:5 | LL | println!("{:0$.1$}", width, prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -695,7 +696,7 @@ LL + println!("{width:width$.prec$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:113:5 + --> tests/ui/uninlined_format_args.rs:175:5 | LL | println!("{:0$.w$}", width, w = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -707,7 +708,7 @@ LL + println!("{width:width$.prec$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:114:5 + --> tests/ui/uninlined_format_args.rs:177:5 | LL | println!("{:1$.2$}", local_f64, width, prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -719,7 +720,7 @@ LL + println!("{local_f64:width$.prec$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:115:5 + --> tests/ui/uninlined_format_args.rs:179:5 | LL | println!("{:1$.2$} {0} {1} {2}", local_f64, width, prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -731,16 +732,17 @@ LL + println!("{local_f64:width$.prec$} {local_f64} {width} {prec}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:116:5 + --> tests/ui/uninlined_format_args.rs:181:5 | LL | / println!( +LL | | LL | | "{0:1$.2$} {0:2$.1$} {1:0$.2$} {1:2$.0$} {2:0$.1$} {2:1$.0$}", LL | | local_i32, width, prec, LL | | ); | |_____^ error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:127:5 + --> tests/ui/uninlined_format_args.rs:193:5 | LL | println!("Width = {}, value with width = {:0$}", local_i32, local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -752,7 +754,7 @@ LL + println!("Width = {local_i32}, value with width = {local_f64:local_i32$ | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:128:5 + --> tests/ui/uninlined_format_args.rs:195:5 | LL | println!("{:w$.p$}", local_i32, w = width, p = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -764,7 +766,7 @@ LL + println!("{local_i32:width$.prec$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:129:5 + --> tests/ui/uninlined_format_args.rs:197:5 | LL | println!("{:w$.p$}", w = width, p = prec); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -776,17 +778,17 @@ LL + println!("{width:width$.prec$}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:148:5 + --> tests/ui/uninlined_format_args.rs:217:5 | LL | / println!( +LL | | LL | | "{}", -LL | | // comment with a comma , in it -LL | | val, +... | LL | | ); | |_____^ error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:153:5 + --> tests/ui/uninlined_format_args.rs:223:5 | LL | println!("{}", /* comment with a comma , in it */ val); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -798,7 +800,7 @@ LL + println!("{val}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:159:9 + --> tests/ui/uninlined_format_args.rs:230:9 | LL | panic!("p1 {}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -810,7 +812,7 @@ LL + panic!("p1 {local_i32}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:162:9 + --> tests/ui/uninlined_format_args.rs:234:9 | LL | panic!("p2 {0}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -822,7 +824,7 @@ LL + panic!("p2 {local_i32}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:165:9 + --> tests/ui/uninlined_format_args.rs:238:9 | LL | panic!("p3 {local_i32}", local_i32 = local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -834,7 +836,7 @@ LL + panic!("p3 {local_i32}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:185:5 + --> tests/ui/uninlined_format_args.rs:259:5 | LL | println!("expand='{}'", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -846,7 +848,7 @@ LL + println!("expand='{local_i32}'"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:287:5 + --> tests/ui/uninlined_format_args.rs:362:5 | LL | usr_println!(true, "val='{}'", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -858,7 +860,7 @@ LL + usr_println!(true, "val='{local_i32}'"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:288:5 + --> tests/ui/uninlined_format_args.rs:364:5 | LL | usr_println!(true, "{}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -870,7 +872,7 @@ LL + usr_println!(true, "{local_i32}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:289:5 + --> tests/ui/uninlined_format_args.rs:366:5 | LL | usr_println!(true, "{:#010x}", local_i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -882,7 +884,7 @@ LL + usr_println!(true, "{local_i32:#010x}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args.rs:290:5 + --> tests/ui/uninlined_format_args.rs:368:5 | LL | usr_println!(true, "{:.1}", local_f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/uninlined_format_args_panic.edition2018.fixed b/tests/ui/uninlined_format_args_panic.edition2018.fixed index 9911d1317070..3710036c0589 100644 --- a/tests/ui/uninlined_format_args_panic.edition2018.fixed +++ b/tests/ui/uninlined_format_args_panic.edition2018.fixed @@ -9,15 +9,19 @@ fn main() { let var = 1; println!("val='{var}'"); + //~^ uninlined_format_args if var > 0 { panic!("p1 {}", var); + //~[edition2021]^ uninlined_format_args } if var > 0 { panic!("p2 {0}", var); + //~[edition2021]^ uninlined_format_args } if var > 0 { panic!("p3 {var}", var = var); + //~[edition2021]^ uninlined_format_args } #[allow(non_fmt_panics)] @@ -28,5 +32,7 @@ fn main() { } assert!(var == 1, "p5 {}", var); + //~[edition2021]^ uninlined_format_args debug_assert!(var == 1, "p6 {}", var); + //~[edition2021]^ uninlined_format_args } diff --git a/tests/ui/uninlined_format_args_panic.edition2021.fixed b/tests/ui/uninlined_format_args_panic.edition2021.fixed index 87b74670565f..8a754d313806 100644 --- a/tests/ui/uninlined_format_args_panic.edition2021.fixed +++ b/tests/ui/uninlined_format_args_panic.edition2021.fixed @@ -9,15 +9,19 @@ fn main() { let var = 1; println!("val='{var}'"); + //~^ uninlined_format_args if var > 0 { panic!("p1 {var}"); + //~[edition2021]^ uninlined_format_args } if var > 0 { panic!("p2 {var}"); + //~[edition2021]^ uninlined_format_args } if var > 0 { panic!("p3 {var}"); + //~[edition2021]^ uninlined_format_args } #[allow(non_fmt_panics)] @@ -28,5 +32,7 @@ fn main() { } assert!(var == 1, "p5 {var}"); + //~[edition2021]^ uninlined_format_args debug_assert!(var == 1, "p6 {var}"); + //~[edition2021]^ uninlined_format_args } diff --git a/tests/ui/uninlined_format_args_panic.edition2021.stderr b/tests/ui/uninlined_format_args_panic.edition2021.stderr index 7638d3f8bbad..4db6e6a99312 100644 --- a/tests/ui/uninlined_format_args_panic.edition2021.stderr +++ b/tests/ui/uninlined_format_args_panic.edition2021.stderr @@ -13,7 +13,7 @@ LL + println!("val='{var}'"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args_panic.rs:14:9 + --> tests/ui/uninlined_format_args_panic.rs:15:9 | LL | panic!("p1 {}", var); | ^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + panic!("p1 {var}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args_panic.rs:17:9 + --> tests/ui/uninlined_format_args_panic.rs:19:9 | LL | panic!("p2 {0}", var); | ^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + panic!("p2 {var}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args_panic.rs:20:9 + --> tests/ui/uninlined_format_args_panic.rs:23:9 | LL | panic!("p3 {var}", var = var); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + panic!("p3 {var}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args_panic.rs:30:5 + --> tests/ui/uninlined_format_args_panic.rs:34:5 | LL | assert!(var == 1, "p5 {}", var); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + assert!(var == 1, "p5 {var}"); | error: variables can be used directly in the `format!` string - --> tests/ui/uninlined_format_args_panic.rs:31:5 + --> tests/ui/uninlined_format_args_panic.rs:36:5 | LL | debug_assert!(var == 1, "p6 {}", var); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/uninlined_format_args_panic.rs b/tests/ui/uninlined_format_args_panic.rs index 647c69bc5c41..94de4f057e99 100644 --- a/tests/ui/uninlined_format_args_panic.rs +++ b/tests/ui/uninlined_format_args_panic.rs @@ -9,15 +9,19 @@ fn main() { let var = 1; println!("val='{}'", var); + //~^ uninlined_format_args if var > 0 { panic!("p1 {}", var); + //~[edition2021]^ uninlined_format_args } if var > 0 { panic!("p2 {0}", var); + //~[edition2021]^ uninlined_format_args } if var > 0 { panic!("p3 {var}", var = var); + //~[edition2021]^ uninlined_format_args } #[allow(non_fmt_panics)] @@ -28,5 +32,7 @@ fn main() { } assert!(var == 1, "p5 {}", var); + //~[edition2021]^ uninlined_format_args debug_assert!(var == 1, "p6 {}", var); + //~[edition2021]^ uninlined_format_args } diff --git a/tests/ui/unit_arg.rs b/tests/ui/unit_arg.rs index 2e1390621a6c..22a6a26dab62 100644 --- a/tests/ui/unit_arg.rs +++ b/tests/ui/unit_arg.rs @@ -61,23 +61,30 @@ impl Tr for B { fn bad() { foo({ + //~^ unit_arg 1; }); foo(foo(1)); + //~^ unit_arg foo({ + //~^ unit_arg foo(1); foo(2); }); let b = Bar; b.bar({ + //~^ unit_arg 1; }); taking_multiple_units(foo(0), foo(1)); + //~^ unit_arg taking_multiple_units(foo(0), { + //~^ unit_arg foo(1); foo(2); }); taking_multiple_units( + //~^ unit_arg { foo(0); foo(1); @@ -89,9 +96,11 @@ fn bad() { ); // here Some(foo(2)) isn't the top level statement expression, wrap the suggestion in a block None.or(Some(foo(2))); + //~^ unit_arg // in this case, the suggestion can be inlined, no need for a surrounding block // foo(()); foo(()) instead of { foo(()); foo(()) } foo(foo(())); + //~^ unit_arg } fn ok() { @@ -129,6 +138,7 @@ mod issue_2945 { #[allow(dead_code)] fn returning_expr() -> Option<()> { Some(foo(1)) + //~^ unit_arg } fn taking_multiple_units(a: (), b: ()) {} diff --git a/tests/ui/unit_arg.stderr b/tests/ui/unit_arg.stderr index bf79e93e4440..6c333d9792d4 100644 --- a/tests/ui/unit_arg.stderr +++ b/tests/ui/unit_arg.stderr @@ -2,6 +2,7 @@ error: passing a unit value to a function --> tests/ui/unit_arg.rs:63:5 | LL | / foo({ +LL | | LL | | 1; LL | | }); | |______^ @@ -16,13 +17,14 @@ LL + 1 help: or move the expression in front of the call and replace it with the unit literal `()` | LL ~ { +LL + LL + 1; LL + }; LL ~ foo(()); | error: passing a unit value to a function - --> tests/ui/unit_arg.rs:66:5 + --> tests/ui/unit_arg.rs:67:5 | LL | foo(foo(1)); | ^^^^^^^^^^^ @@ -34,9 +36,10 @@ LL ~ foo(()); | error: passing a unit value to a function - --> tests/ui/unit_arg.rs:67:5 + --> tests/ui/unit_arg.rs:69:5 | LL | / foo({ +LL | | LL | | foo(1); LL | | foo(2); LL | | }); @@ -50,6 +53,7 @@ LL + foo(2) help: or move the expression in front of the call and replace it with the unit literal `()` | LL ~ { +LL + LL + foo(1); LL + foo(2); LL + }; @@ -57,9 +61,10 @@ LL ~ foo(()); | error: passing a unit value to a function - --> tests/ui/unit_arg.rs:72:5 + --> tests/ui/unit_arg.rs:75:5 | LL | / b.bar({ +LL | | LL | | 1; LL | | }); | |______^ @@ -72,13 +77,14 @@ LL + 1 help: or move the expression in front of the call and replace it with the unit literal `()` | LL ~ { +LL + LL + 1; LL + }; LL ~ b.bar(()); | error: passing unit values to a function - --> tests/ui/unit_arg.rs:75:5 + --> tests/ui/unit_arg.rs:79:5 | LL | taking_multiple_units(foo(0), foo(1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -91,9 +97,10 @@ LL ~ taking_multiple_units((), ()); | error: passing unit values to a function - --> tests/ui/unit_arg.rs:76:5 + --> tests/ui/unit_arg.rs:81:5 | LL | / taking_multiple_units(foo(0), { +LL | | LL | | foo(1); LL | | foo(2); LL | | }); @@ -108,6 +115,7 @@ help: or move the expressions in front of the call and replace them with the uni | LL ~ foo(0); LL + { +LL + LL + foo(1); LL + foo(2); LL + }; @@ -115,12 +123,12 @@ LL ~ taking_multiple_units((), ()); | error: passing unit values to a function - --> tests/ui/unit_arg.rs:80:5 + --> tests/ui/unit_arg.rs:86:5 | LL | / taking_multiple_units( +LL | | LL | | { LL | | foo(0); -LL | | foo(1); ... | LL | | }, LL | | ); @@ -147,13 +155,14 @@ LL + foo(2); LL + foo(3); LL + }; LL + taking_multiple_units( +LL + LL + (), LL + (), LL ~ ); | error: passing a unit value to a function - --> tests/ui/unit_arg.rs:91:13 + --> tests/ui/unit_arg.rs:98:13 | LL | None.or(Some(foo(2))); | ^^^^^^^^^^^^ @@ -167,7 +176,7 @@ LL ~ }); | error: passing a unit value to a function - --> tests/ui/unit_arg.rs:94:5 + --> tests/ui/unit_arg.rs:102:5 | LL | foo(foo(())); | ^^^^^^^^^^^^ @@ -179,7 +188,7 @@ LL ~ foo(()); | error: passing a unit value to a function - --> tests/ui/unit_arg.rs:131:5 + --> tests/ui/unit_arg.rs:140:5 | LL | Some(foo(1)) | ^^^^^^^^^^^^ diff --git a/tests/ui/unit_arg_empty_blocks.fixed b/tests/ui/unit_arg_empty_blocks.fixed index a947ded7b1e7..b045a33608d7 100644 --- a/tests/ui/unit_arg_empty_blocks.fixed +++ b/tests/ui/unit_arg_empty_blocks.fixed @@ -14,12 +14,16 @@ fn foo3(t1: T1, t2: T2, t3: T3) { fn bad() { foo(()); + //~^ unit_arg foo3((), 2, 2); + //~^ unit_arg foo(0); taking_two_units((), ()); + //~^ unit_arg foo(0); foo(1); taking_three_units((), (), ()); + //~^ unit_arg } fn taking_two_units(a: (), b: ()) {} diff --git a/tests/ui/unit_arg_empty_blocks.rs b/tests/ui/unit_arg_empty_blocks.rs index 058c4f84a9e8..ab305913f3f6 100644 --- a/tests/ui/unit_arg_empty_blocks.rs +++ b/tests/ui/unit_arg_empty_blocks.rs @@ -14,9 +14,13 @@ fn foo3(t1: T1, t2: T2, t3: T3) { fn bad() { foo({}); + //~^ unit_arg foo3({}, 2, 2); + //~^ unit_arg taking_two_units({}, foo(0)); + //~^ unit_arg taking_three_units({}, foo(0), foo(1)); + //~^ unit_arg } fn taking_two_units(a: (), b: ()) {} diff --git a/tests/ui/unit_arg_empty_blocks.stderr b/tests/ui/unit_arg_empty_blocks.stderr index d971195dda26..2c686d58ecc1 100644 --- a/tests/ui/unit_arg_empty_blocks.stderr +++ b/tests/ui/unit_arg_empty_blocks.stderr @@ -10,7 +10,7 @@ LL | foo({}); = help: to override `-D warnings` add `#[allow(clippy::unit_arg)]` error: passing a unit value to a function - --> tests/ui/unit_arg_empty_blocks.rs:17:5 + --> tests/ui/unit_arg_empty_blocks.rs:18:5 | LL | foo3({}, 2, 2); | ^^^^^--^^^^^^^ @@ -18,7 +18,7 @@ LL | foo3({}, 2, 2); | help: use a unit literal instead: `()` error: passing unit values to a function - --> tests/ui/unit_arg_empty_blocks.rs:18:5 + --> tests/ui/unit_arg_empty_blocks.rs:20:5 | LL | taking_two_units({}, foo(0)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -30,7 +30,7 @@ LL ~ taking_two_units((), ()); | error: passing unit values to a function - --> tests/ui/unit_arg_empty_blocks.rs:19:5 + --> tests/ui/unit_arg_empty_blocks.rs:22:5 | LL | taking_three_units({}, foo(0), foo(1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unit_cmp.rs b/tests/ui/unit_cmp.rs index cea89026da6f..93f5b87c3d2a 100644 --- a/tests/ui/unit_cmp.rs +++ b/tests/ui/unit_cmp.rs @@ -15,22 +15,23 @@ fn main() { // this warns if { - //~^ ERROR: ==-comparison of unit values detected. This will always be true - //~| NOTE: `-D clippy::unit-cmp` implied by `-D warnings` + //~^ unit_cmp + true; } == { false; } {} if { - //~^ ERROR: >-comparison of unit values detected. This will always be false + //~^ unit_cmp + true; } > { false; } {} assert_eq!( - //~^ ERROR: `assert_eq` of unit values detected. This will always succeed + //~^ unit_cmp { true; }, @@ -39,7 +40,7 @@ fn main() { } ); debug_assert_eq!( - //~^ ERROR: `debug_assert_eq` of unit values detected. This will always succeed + //~^ unit_cmp { true; }, @@ -49,7 +50,7 @@ fn main() { ); assert_ne!( - //~^ ERROR: `assert_ne` of unit values detected. This will always fail + //~^ unit_cmp { true; }, @@ -58,7 +59,7 @@ fn main() { } ); debug_assert_ne!( - //~^ ERROR: `debug_assert_ne` of unit values detected. This will always fail + //~^ unit_cmp { true; }, diff --git a/tests/ui/unit_cmp.stderr b/tests/ui/unit_cmp.stderr index 9e067edb8467..8f26749fd860 100644 --- a/tests/ui/unit_cmp.stderr +++ b/tests/ui/unit_cmp.stderr @@ -20,6 +20,7 @@ error: >-comparison of unit values detected. This will always be false LL | if { | ________^ LL | | +LL | | LL | | true; LL | | } > { LL | | false; @@ -27,7 +28,7 @@ LL | | } {} | |_____^ error: `assert_eq` of unit values detected. This will always succeed - --> tests/ui/unit_cmp.rs:32:5 + --> tests/ui/unit_cmp.rs:33:5 | LL | / assert_eq!( LL | | @@ -38,7 +39,7 @@ LL | | ); | |_____^ error: `debug_assert_eq` of unit values detected. This will always succeed - --> tests/ui/unit_cmp.rs:41:5 + --> tests/ui/unit_cmp.rs:42:5 | LL | / debug_assert_eq!( LL | | @@ -49,7 +50,7 @@ LL | | ); | |_____^ error: `assert_ne` of unit values detected. This will always fail - --> tests/ui/unit_cmp.rs:51:5 + --> tests/ui/unit_cmp.rs:52:5 | LL | / assert_ne!( LL | | @@ -60,7 +61,7 @@ LL | | ); | |_____^ error: `debug_assert_ne` of unit values detected. This will always fail - --> tests/ui/unit_cmp.rs:60:5 + --> tests/ui/unit_cmp.rs:61:5 | LL | / debug_assert_ne!( LL | | diff --git a/tests/ui/unit_hash.fixed b/tests/ui/unit_hash.fixed index ed0facf1b963..25c90e6ddc4c 100644 --- a/tests/ui/unit_hash.fixed +++ b/tests/ui/unit_hash.fixed @@ -17,18 +17,15 @@ fn main() { match my_enum { Foo::Empty => 0_u8.hash(&mut state), - //~^ ERROR: this call to `hash` on the unit type will do nothing - //~| NOTE: the implementation of `Hash` for `()` is a no-op + //~^ unit_hash Foo::WithValue(x) => x.hash(&mut state), } let res = (); 0_u8.hash(&mut state); - //~^ ERROR: this call to `hash` on the unit type will do nothing - //~| NOTE: the implementation of `Hash` for `()` is a no-op + //~^ unit_hash #[allow(clippy::unit_arg)] 0_u8.hash(&mut state); - //~^ ERROR: this call to `hash` on the unit type will do nothing - //~| NOTE: the implementation of `Hash` for `()` is a no-op + //~^ unit_hash } diff --git a/tests/ui/unit_hash.rs b/tests/ui/unit_hash.rs index f3636d1644da..b04cca6adf2a 100644 --- a/tests/ui/unit_hash.rs +++ b/tests/ui/unit_hash.rs @@ -17,18 +17,15 @@ fn main() { match my_enum { Foo::Empty => ().hash(&mut state), - //~^ ERROR: this call to `hash` on the unit type will do nothing - //~| NOTE: the implementation of `Hash` for `()` is a no-op + //~^ unit_hash Foo::WithValue(x) => x.hash(&mut state), } let res = (); res.hash(&mut state); - //~^ ERROR: this call to `hash` on the unit type will do nothing - //~| NOTE: the implementation of `Hash` for `()` is a no-op + //~^ unit_hash #[allow(clippy::unit_arg)] do_nothing().hash(&mut state); - //~^ ERROR: this call to `hash` on the unit type will do nothing - //~| NOTE: the implementation of `Hash` for `()` is a no-op + //~^ unit_hash } diff --git a/tests/ui/unit_hash.stderr b/tests/ui/unit_hash.stderr index b48f3a543b76..d1cabf89f8e7 100644 --- a/tests/ui/unit_hash.stderr +++ b/tests/ui/unit_hash.stderr @@ -9,7 +9,7 @@ LL | Foo::Empty => ().hash(&mut state), = help: to override `-D warnings` add `#[allow(clippy::unit_hash)]` error: this call to `hash` on the unit type will do nothing - --> tests/ui/unit_hash.rs:26:5 + --> tests/ui/unit_hash.rs:25:5 | LL | res.hash(&mut state); | ^^^^^^^^^^^^^^^^^^^^ help: remove the call to `hash` or consider using: `0_u8.hash(&mut state)` @@ -17,7 +17,7 @@ LL | res.hash(&mut state); = note: the implementation of `Hash` for `()` is a no-op error: this call to `hash` on the unit type will do nothing - --> tests/ui/unit_hash.rs:31:5 + --> tests/ui/unit_hash.rs:29:5 | LL | do_nothing().hash(&mut state); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `hash` or consider using: `0_u8.hash(&mut state)` diff --git a/tests/ui/unit_return_expecting_ord.rs b/tests/ui/unit_return_expecting_ord.rs index 5f62157dd6d5..74cd30472684 100644 --- a/tests/ui/unit_return_expecting_ord.rs +++ b/tests/ui/unit_return_expecting_ord.rs @@ -16,16 +16,19 @@ fn unit(_i: isize) {} fn main() { let mut structs = vec![Struct { field: 2 }, Struct { field: 1 }]; structs.sort_by_key(|s| { - //~^ ERROR: this closure returns the unit type which also implements Ord + //~^ unit_return_expecting_ord + double(s.field); }); structs.sort_by_key(|s| double(s.field)); structs.is_sorted_by_key(|s| { - //~^ ERROR: this closure returns the unit type which also implements PartialOrd + //~^ unit_return_expecting_ord + double(s.field); }); structs.is_sorted_by_key(|s| { - //~^ ERROR: this closure returns the unit type which also implements PartialOrd + //~^ unit_return_expecting_ord + if s.field > 0 { () } else { @@ -36,5 +39,5 @@ fn main() { return double(s.field); }); structs.sort_by_key(|s| unit(s.field)); - //~^ ERROR: this closure returns the unit type which also implements Ord + //~^ unit_return_expecting_ord } diff --git a/tests/ui/unit_return_expecting_ord.stderr b/tests/ui/unit_return_expecting_ord.stderr index 329832048e88..d5ce2fb0b51d 100644 --- a/tests/ui/unit_return_expecting_ord.stderr +++ b/tests/ui/unit_return_expecting_ord.stderr @@ -5,7 +5,7 @@ LL | structs.sort_by_key(|s| { | ^^^ | help: probably caused by this trailing semicolon - --> tests/ui/unit_return_expecting_ord.rs:20:24 + --> tests/ui/unit_return_expecting_ord.rs:21:24 | LL | double(s.field); | ^ @@ -13,25 +13,25 @@ LL | double(s.field); = help: to override `-D warnings` add `#[allow(clippy::unit_return_expecting_ord)]` error: this closure returns the unit type which also implements PartialOrd - --> tests/ui/unit_return_expecting_ord.rs:23:30 + --> tests/ui/unit_return_expecting_ord.rs:24:30 | LL | structs.is_sorted_by_key(|s| { | ^^^ | help: probably caused by this trailing semicolon - --> tests/ui/unit_return_expecting_ord.rs:25:24 + --> tests/ui/unit_return_expecting_ord.rs:27:24 | LL | double(s.field); | ^ error: this closure returns the unit type which also implements PartialOrd - --> tests/ui/unit_return_expecting_ord.rs:27:30 + --> tests/ui/unit_return_expecting_ord.rs:29:30 | LL | structs.is_sorted_by_key(|s| { | ^^^ error: this closure returns the unit type which also implements Ord - --> tests/ui/unit_return_expecting_ord.rs:38:25 + --> tests/ui/unit_return_expecting_ord.rs:41:25 | LL | structs.sort_by_key(|s| unit(s.field)); | ^^^ diff --git a/tests/ui/unknown_clippy_lints.fixed b/tests/ui/unknown_clippy_lints.fixed index c0ccd41c19ab..f97452c34eb5 100644 --- a/tests/ui/unknown_clippy_lints.fixed +++ b/tests/ui/unknown_clippy_lints.fixed @@ -1,18 +1,27 @@ #![warn(clippy::pedantic)] // Should suggest lowercase #![allow(clippy::all)] +//~^ ERROR: unknown lint #![warn(clippy::cmp_owned)] +//~^ ERROR: unknown lint // Should suggest similar clippy lint name #[warn(clippy::if_not_else)] +//~^ ERROR: unknown lint #[warn(clippy::unnecessary_cast)] +//~^ ERROR: unknown lint #[warn(clippy::useless_transmute)] +//~^ ERROR: unknown lint // Should suggest rustc lint name(`dead_code`) #[warn(dead_code)] +//~^ ERROR: unknown lint // Shouldn't suggest removed/deprecated clippy lint name(`unused_collect`) #[warn(clippy::unused_self)] +//~^ ERROR: unknown lint // Shouldn't suggest renamed clippy lint name(`const_static_lifetime`) #[warn(clippy::redundant_static_lifetimes)] +//~^ ERROR: unknown lint // issue #118183, should report `missing_docs` from rustc lint #[warn(missing_docs)] +//~^ ERROR: unknown lint fn main() {} diff --git a/tests/ui/unknown_clippy_lints.rs b/tests/ui/unknown_clippy_lints.rs index 7a59ad364aa7..2ff4dd80bddc 100644 --- a/tests/ui/unknown_clippy_lints.rs +++ b/tests/ui/unknown_clippy_lints.rs @@ -1,18 +1,27 @@ #![warn(clippy::pedantic)] // Should suggest lowercase #![allow(clippy::All)] +//~^ ERROR: unknown lint #![warn(clippy::CMP_OWNED)] +//~^ ERROR: unknown lint // Should suggest similar clippy lint name #[warn(clippy::if_not_els)] +//~^ ERROR: unknown lint #[warn(clippy::UNNecsaRy_cAst)] +//~^ ERROR: unknown lint #[warn(clippy::useles_transute)] +//~^ ERROR: unknown lint // Should suggest rustc lint name(`dead_code`) #[warn(clippy::dead_cod)] +//~^ ERROR: unknown lint // Shouldn't suggest removed/deprecated clippy lint name(`unused_collect`) #[warn(clippy::unused_colle)] +//~^ ERROR: unknown lint // Shouldn't suggest renamed clippy lint name(`const_static_lifetime`) #[warn(clippy::const_static_lifetim)] +//~^ ERROR: unknown lint // issue #118183, should report `missing_docs` from rustc lint #[warn(clippy::missing_docs)] +//~^ ERROR: unknown lint fn main() {} diff --git a/tests/ui/unknown_clippy_lints.stderr b/tests/ui/unknown_clippy_lints.stderr index ea925cd3a9fc..592fdfbebd43 100644 --- a/tests/ui/unknown_clippy_lints.stderr +++ b/tests/ui/unknown_clippy_lints.stderr @@ -8,31 +8,31 @@ LL | #![allow(clippy::All)] = help: to override `-D warnings` add `#[allow(unknown_lints)]` error: unknown lint: `clippy::CMP_OWNED` - --> tests/ui/unknown_clippy_lints.rs:4:9 + --> tests/ui/unknown_clippy_lints.rs:5:9 | LL | #![warn(clippy::CMP_OWNED)] | ^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::cmp_owned` error: unknown lint: `clippy::if_not_els` - --> tests/ui/unknown_clippy_lints.rs:7:8 + --> tests/ui/unknown_clippy_lints.rs:9:8 | LL | #[warn(clippy::if_not_els)] | ^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::if_not_else` error: unknown lint: `clippy::UNNecsaRy_cAst` - --> tests/ui/unknown_clippy_lints.rs:8:8 + --> tests/ui/unknown_clippy_lints.rs:11:8 | LL | #[warn(clippy::UNNecsaRy_cAst)] | ^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::unnecessary_cast` error: unknown lint: `clippy::useles_transute` - --> tests/ui/unknown_clippy_lints.rs:9:8 + --> tests/ui/unknown_clippy_lints.rs:13:8 | LL | #[warn(clippy::useles_transute)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::useless_transmute` error: unknown lint: `clippy::dead_cod` - --> tests/ui/unknown_clippy_lints.rs:11:8 + --> tests/ui/unknown_clippy_lints.rs:16:8 | LL | #[warn(clippy::dead_cod)] | ^^^^^^^^^^^^^^^^ @@ -44,19 +44,19 @@ LL + #[warn(dead_code)] | error: unknown lint: `clippy::unused_colle` - --> tests/ui/unknown_clippy_lints.rs:13:8 + --> tests/ui/unknown_clippy_lints.rs:19:8 | LL | #[warn(clippy::unused_colle)] | ^^^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::unused_self` error: unknown lint: `clippy::const_static_lifetim` - --> tests/ui/unknown_clippy_lints.rs:15:8 + --> tests/ui/unknown_clippy_lints.rs:22:8 | LL | #[warn(clippy::const_static_lifetim)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::redundant_static_lifetimes` error: unknown lint: `clippy::missing_docs` - --> tests/ui/unknown_clippy_lints.rs:17:8 + --> tests/ui/unknown_clippy_lints.rs:25:8 | LL | #[warn(clippy::missing_docs)] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unnecessary_box_returns.rs b/tests/ui/unnecessary_box_returns.rs index bcdaca33b644..a7ab7e90be06 100644 --- a/tests/ui/unnecessary_box_returns.rs +++ b/tests/ui/unnecessary_box_returns.rs @@ -3,7 +3,7 @@ trait Bar { // lint fn baz(&self) -> Box; - //~^ ERROR: boxed return of the sized type `usize` + //~^ unnecessary_box_returns } pub struct Foo {} @@ -17,7 +17,8 @@ impl Bar for Foo { impl Foo { fn baz(&self) -> Box { - //~^ ERROR: boxed return of the sized type `usize` + //~^ unnecessary_box_returns + // lint Box::new(13) } @@ -25,13 +26,15 @@ impl Foo { // lint fn bxed_usize() -> Box { - //~^ ERROR: boxed return of the sized type `usize` + //~^ unnecessary_box_returns + Box::new(5) } // lint fn _bxed_foo() -> Box { - //~^ ERROR: boxed return of the sized type `Foo` + //~^ unnecessary_box_returns + Box::new(Foo {}) } diff --git a/tests/ui/unnecessary_box_returns.stderr b/tests/ui/unnecessary_box_returns.stderr index cb88ba1b0016..ab1d90f13b92 100644 --- a/tests/ui/unnecessary_box_returns.stderr +++ b/tests/ui/unnecessary_box_returns.stderr @@ -17,7 +17,7 @@ LL | fn baz(&self) -> Box { = help: changing this also requires a change to the return expressions in this function error: boxed return of the sized type `usize` - --> tests/ui/unnecessary_box_returns.rs:27:20 + --> tests/ui/unnecessary_box_returns.rs:28:20 | LL | fn bxed_usize() -> Box { | ^^^^^^^^^^ help: try: `usize` @@ -25,7 +25,7 @@ LL | fn bxed_usize() -> Box { = help: changing this also requires a change to the return expressions in this function error: boxed return of the sized type `Foo` - --> tests/ui/unnecessary_box_returns.rs:33:19 + --> tests/ui/unnecessary_box_returns.rs:35:19 | LL | fn _bxed_foo() -> Box { | ^^^^^^^^ help: try: `Foo` diff --git a/tests/ui/unnecessary_cast.fixed b/tests/ui/unnecessary_cast.fixed index c43e50761bd5..ba167e79a308 100644 --- a/tests/ui/unnecessary_cast.fixed +++ b/tests/ui/unnecessary_cast.fixed @@ -17,6 +17,7 @@ type PtrMutU8 = *mut u8; fn owo(ptr: *const T) -> *const T { ptr + //~^ unnecessary_cast } fn uwu(ptr: *const T) -> *const U { @@ -52,21 +53,32 @@ fn bbb() -> UnsignedThirtyTwoBitInteger { fn main() { // Test cast_unnecessary 1_i32; + //~^ unnecessary_cast 1_f32; + //~^ unnecessary_cast false; + //~^ unnecessary_cast &1i32 as &i32; -1_i32; + //~^ unnecessary_cast - 1_i32; + //~^ unnecessary_cast -1_f32; + //~^ unnecessary_cast 1_i32; + //~^ unnecessary_cast 1_f32; + //~^ unnecessary_cast let _: *mut u8 = [1u8, 2].as_ptr() as *mut u8; + //~^ unnecessary_cast [1u8, 2].as_ptr(); + //~^ unnecessary_cast [1u8, 2].as_ptr() as *mut u8; [1u8, 2].as_mut_ptr(); + //~^ unnecessary_cast [1u8, 2].as_mut_ptr() as *const u8; [1u8, 2].as_ptr() as PtrConstU8; [1u8, 2].as_ptr() as PtrMutU8; @@ -78,9 +90,12 @@ fn main() { let _: *mut u8 = [1u8, 2].as_mut_ptr() as *mut _; owo::([1u32].as_ptr()); + //~^ unnecessary_cast uwu::([1u32].as_ptr()); + //~^ unnecessary_cast // this will not lint in the function body even though they have the same type, instead here uwu::([1u32].as_ptr()); + //~^ unnecessary_cast // macro version macro_rules! foo { @@ -116,8 +131,10 @@ fn main() { let pid = unsafe { fake_libc::getpid() }; pid as i32; aaa(); + //~^ unnecessary_cast let x = aaa(); aaa(); + //~^ unnecessary_cast // Will not lint currently. bbb() as u32; let x = bbb(); @@ -154,13 +171,21 @@ mod fixable { fn main() { // casting integer literal to float is unnecessary 100_f32; + //~^ unnecessary_cast 100_f64; + //~^ unnecessary_cast 100_f64; + //~^ unnecessary_cast let _ = -100_f32; + //~^ unnecessary_cast let _ = -100_f64; + //~^ unnecessary_cast let _ = -100_f64; + //~^ unnecessary_cast 100_f32; + //~^ unnecessary_cast 100_f64; + //~^ unnecessary_cast // Should not trigger #[rustfmt::skip] let v = vec!(1); @@ -173,32 +198,44 @@ mod fixable { 0b11 as f64; 1_u32; + //~^ unnecessary_cast 0x10_i32; + //~^ unnecessary_cast 0b10_usize; + //~^ unnecessary_cast 0o73_u16; + //~^ unnecessary_cast 1_000_000_000_u32; + //~^ unnecessary_cast 1.0_f64; + //~^ unnecessary_cast 0.5_f32; + //~^ unnecessary_cast 1.0 as u16; let _ = -1_i32; + //~^ unnecessary_cast let _ = -1.0_f32; + //~^ unnecessary_cast let _ = 1 as I32Alias; let _ = &1 as &I32Alias; let x = 1i32; let _ = &{ x }; + //~^ unnecessary_cast } type I32Alias = i32; fn issue_9380() { let _: i32 = -1_i32; + //~^ unnecessary_cast let _: f32 = -(1) as f32; let _: i64 = -1_i64; + //~^ unnecessary_cast let _: i64 = -(1.0) as i64; let _ = -(1 + 1) as i64; @@ -206,8 +243,11 @@ mod fixable { fn issue_9563() { let _: f64 = (-8.0_f64).exp(); + //~^ unnecessary_cast #[allow(ambiguous_negative_literals)] let _: f64 = -8.0_f64.exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior + // + //~^^ unnecessary_cast } fn issue_9562_non_literal() { @@ -216,6 +256,7 @@ mod fixable { } let _num = foo(); + //~^ unnecessary_cast } fn issue_9603() { @@ -226,5 +267,6 @@ mod fixable { // `*x.pow(2)` which tries to dereference the return value rather than `x`. fn issue_11968(x: &usize) -> usize { { *x }.pow(2) + //~^ unnecessary_cast } } diff --git a/tests/ui/unnecessary_cast.rs b/tests/ui/unnecessary_cast.rs index 4a5ca231315e..0f90a8b05965 100644 --- a/tests/ui/unnecessary_cast.rs +++ b/tests/ui/unnecessary_cast.rs @@ -17,6 +17,7 @@ type PtrMutU8 = *mut u8; fn owo(ptr: *const T) -> *const T { ptr as *const T + //~^ unnecessary_cast } fn uwu(ptr: *const T) -> *const U { @@ -52,21 +53,32 @@ fn bbb() -> UnsignedThirtyTwoBitInteger { fn main() { // Test cast_unnecessary 1i32 as i32; + //~^ unnecessary_cast 1f32 as f32; + //~^ unnecessary_cast false as bool; + //~^ unnecessary_cast &1i32 as &i32; -1_i32 as i32; + //~^ unnecessary_cast - 1_i32 as i32; + //~^ unnecessary_cast -1f32 as f32; + //~^ unnecessary_cast 1_i32 as i32; + //~^ unnecessary_cast 1_f32 as f32; + //~^ unnecessary_cast let _: *mut u8 = [1u8, 2].as_ptr() as *const u8 as *mut u8; + //~^ unnecessary_cast [1u8, 2].as_ptr() as *const u8; + //~^ unnecessary_cast [1u8, 2].as_ptr() as *mut u8; [1u8, 2].as_mut_ptr() as *mut u8; + //~^ unnecessary_cast [1u8, 2].as_mut_ptr() as *const u8; [1u8, 2].as_ptr() as PtrConstU8; [1u8, 2].as_ptr() as PtrMutU8; @@ -78,9 +90,12 @@ fn main() { let _: *mut u8 = [1u8, 2].as_mut_ptr() as *mut _; owo::([1u32].as_ptr()) as *const u32; + //~^ unnecessary_cast uwu::([1u32].as_ptr()) as *const u8; + //~^ unnecessary_cast // this will not lint in the function body even though they have the same type, instead here uwu::([1u32].as_ptr()) as *const u32; + //~^ unnecessary_cast // macro version macro_rules! foo { @@ -116,8 +131,10 @@ fn main() { let pid = unsafe { fake_libc::getpid() }; pid as i32; aaa() as u32; + //~^ unnecessary_cast let x = aaa(); aaa() as u32; + //~^ unnecessary_cast // Will not lint currently. bbb() as u32; let x = bbb(); @@ -154,13 +171,21 @@ mod fixable { fn main() { // casting integer literal to float is unnecessary 100 as f32; + //~^ unnecessary_cast 100 as f64; + //~^ unnecessary_cast 100_i32 as f64; + //~^ unnecessary_cast let _ = -100 as f32; + //~^ unnecessary_cast let _ = -100 as f64; + //~^ unnecessary_cast let _ = -100_i32 as f64; + //~^ unnecessary_cast 100. as f32; + //~^ unnecessary_cast 100. as f64; + //~^ unnecessary_cast // Should not trigger #[rustfmt::skip] let v = vec!(1); @@ -173,32 +198,44 @@ mod fixable { 0b11 as f64; 1 as u32; + //~^ unnecessary_cast 0x10 as i32; + //~^ unnecessary_cast 0b10 as usize; + //~^ unnecessary_cast 0o73 as u16; + //~^ unnecessary_cast 1_000_000_000 as u32; + //~^ unnecessary_cast 1.0 as f64; + //~^ unnecessary_cast 0.5 as f32; + //~^ unnecessary_cast 1.0 as u16; let _ = -1 as i32; + //~^ unnecessary_cast let _ = -1.0 as f32; + //~^ unnecessary_cast let _ = 1 as I32Alias; let _ = &1 as &I32Alias; let x = 1i32; let _ = &(x as i32); + //~^ unnecessary_cast } type I32Alias = i32; fn issue_9380() { let _: i32 = -(1) as i32; + //~^ unnecessary_cast let _: f32 = -(1) as f32; let _: i64 = -(1) as i64; + //~^ unnecessary_cast let _: i64 = -(1.0) as i64; let _ = -(1 + 1) as i64; @@ -206,8 +243,11 @@ mod fixable { fn issue_9563() { let _: f64 = (-8.0 as f64).exp(); + //~^ unnecessary_cast #[allow(ambiguous_negative_literals)] let _: f64 = -(8.0 as f64).exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior + // + //~^^ unnecessary_cast } fn issue_9562_non_literal() { @@ -216,6 +256,7 @@ mod fixable { } let _num = foo() as f32; + //~^ unnecessary_cast } fn issue_9603() { @@ -226,5 +267,6 @@ mod fixable { // `*x.pow(2)` which tries to dereference the return value rather than `x`. fn issue_11968(x: &usize) -> usize { (*x as usize).pow(2) + //~^ unnecessary_cast } } diff --git a/tests/ui/unnecessary_cast.stderr b/tests/ui/unnecessary_cast.stderr index 80fd5c13d818..c83770c1a299 100644 --- a/tests/ui/unnecessary_cast.stderr +++ b/tests/ui/unnecessary_cast.stderr @@ -8,241 +8,241 @@ LL | ptr as *const T = help: to override `-D warnings` add `#[allow(clippy::unnecessary_cast)]` error: casting integer literal to `i32` is unnecessary - --> tests/ui/unnecessary_cast.rs:54:5 + --> tests/ui/unnecessary_cast.rs:55:5 | LL | 1i32 as i32; | ^^^^^^^^^^^ help: try: `1_i32` error: casting float literal to `f32` is unnecessary - --> tests/ui/unnecessary_cast.rs:55:5 + --> tests/ui/unnecessary_cast.rs:57:5 | LL | 1f32 as f32; | ^^^^^^^^^^^ help: try: `1_f32` error: casting to the same type is unnecessary (`bool` -> `bool`) - --> tests/ui/unnecessary_cast.rs:56:5 + --> tests/ui/unnecessary_cast.rs:59:5 | LL | false as bool; | ^^^^^^^^^^^^^ help: try: `false` error: casting integer literal to `i32` is unnecessary - --> tests/ui/unnecessary_cast.rs:59:5 + --> tests/ui/unnecessary_cast.rs:63:5 | LL | -1_i32 as i32; | ^^^^^^^^^^^^^ help: try: `-1_i32` error: casting integer literal to `i32` is unnecessary - --> tests/ui/unnecessary_cast.rs:60:5 + --> tests/ui/unnecessary_cast.rs:65:5 | LL | - 1_i32 as i32; | ^^^^^^^^^^^^^^ help: try: `- 1_i32` error: casting float literal to `f32` is unnecessary - --> tests/ui/unnecessary_cast.rs:61:5 + --> tests/ui/unnecessary_cast.rs:67:5 | LL | -1f32 as f32; | ^^^^^^^^^^^^ help: try: `-1_f32` error: casting integer literal to `i32` is unnecessary - --> tests/ui/unnecessary_cast.rs:62:5 + --> tests/ui/unnecessary_cast.rs:69:5 | LL | 1_i32 as i32; | ^^^^^^^^^^^^ help: try: `1_i32` error: casting float literal to `f32` is unnecessary - --> tests/ui/unnecessary_cast.rs:63:5 + --> tests/ui/unnecessary_cast.rs:71:5 | LL | 1_f32 as f32; | ^^^^^^^^^^^^ help: try: `1_f32` error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`) - --> tests/ui/unnecessary_cast.rs:65:22 + --> tests/ui/unnecessary_cast.rs:74:22 | LL | let _: *mut u8 = [1u8, 2].as_ptr() as *const u8 as *mut u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_ptr()` error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`) - --> tests/ui/unnecessary_cast.rs:67:5 + --> tests/ui/unnecessary_cast.rs:77:5 | LL | [1u8, 2].as_ptr() as *const u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_ptr()` error: casting raw pointers to the same type and constness is unnecessary (`*mut u8` -> `*mut u8`) - --> tests/ui/unnecessary_cast.rs:69:5 + --> tests/ui/unnecessary_cast.rs:80:5 | LL | [1u8, 2].as_mut_ptr() as *mut u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_mut_ptr()` error: casting raw pointers to the same type and constness is unnecessary (`*const u32` -> `*const u32`) - --> tests/ui/unnecessary_cast.rs:80:5 + --> tests/ui/unnecessary_cast.rs:92:5 | LL | owo::([1u32].as_ptr()) as *const u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `owo::([1u32].as_ptr())` error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`) - --> tests/ui/unnecessary_cast.rs:81:5 + --> tests/ui/unnecessary_cast.rs:94:5 | LL | uwu::([1u32].as_ptr()) as *const u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `uwu::([1u32].as_ptr())` error: casting raw pointers to the same type and constness is unnecessary (`*const u32` -> `*const u32`) - --> tests/ui/unnecessary_cast.rs:83:5 + --> tests/ui/unnecessary_cast.rs:97:5 | LL | uwu::([1u32].as_ptr()) as *const u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `uwu::([1u32].as_ptr())` error: casting to the same type is unnecessary (`u32` -> `u32`) - --> tests/ui/unnecessary_cast.rs:118:5 + --> tests/ui/unnecessary_cast.rs:133:5 | LL | aaa() as u32; | ^^^^^^^^^^^^ help: try: `aaa()` error: casting to the same type is unnecessary (`u32` -> `u32`) - --> tests/ui/unnecessary_cast.rs:120:5 + --> tests/ui/unnecessary_cast.rs:136:5 | LL | aaa() as u32; | ^^^^^^^^^^^^ help: try: `aaa()` error: casting integer literal to `f32` is unnecessary - --> tests/ui/unnecessary_cast.rs:156:9 + --> tests/ui/unnecessary_cast.rs:173:9 | LL | 100 as f32; | ^^^^^^^^^^ help: try: `100_f32` error: casting integer literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:157:9 + --> tests/ui/unnecessary_cast.rs:175:9 | LL | 100 as f64; | ^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:158:9 + --> tests/ui/unnecessary_cast.rs:177:9 | LL | 100_i32 as f64; | ^^^^^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `f32` is unnecessary - --> tests/ui/unnecessary_cast.rs:159:17 + --> tests/ui/unnecessary_cast.rs:179:17 | LL | let _ = -100 as f32; | ^^^^^^^^^^^ help: try: `-100_f32` error: casting integer literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:160:17 + --> tests/ui/unnecessary_cast.rs:181:17 | LL | let _ = -100 as f64; | ^^^^^^^^^^^ help: try: `-100_f64` error: casting integer literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:161:17 + --> tests/ui/unnecessary_cast.rs:183:17 | LL | let _ = -100_i32 as f64; | ^^^^^^^^^^^^^^^ help: try: `-100_f64` error: casting float literal to `f32` is unnecessary - --> tests/ui/unnecessary_cast.rs:162:9 + --> tests/ui/unnecessary_cast.rs:185:9 | LL | 100. as f32; | ^^^^^^^^^^^ help: try: `100_f32` error: casting float literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:163:9 + --> tests/ui/unnecessary_cast.rs:187:9 | LL | 100. as f64; | ^^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `u32` is unnecessary - --> tests/ui/unnecessary_cast.rs:175:9 + --> tests/ui/unnecessary_cast.rs:200:9 | LL | 1 as u32; | ^^^^^^^^ help: try: `1_u32` error: casting integer literal to `i32` is unnecessary - --> tests/ui/unnecessary_cast.rs:176:9 + --> tests/ui/unnecessary_cast.rs:202:9 | LL | 0x10 as i32; | ^^^^^^^^^^^ help: try: `0x10_i32` error: casting integer literal to `usize` is unnecessary - --> tests/ui/unnecessary_cast.rs:177:9 + --> tests/ui/unnecessary_cast.rs:204:9 | LL | 0b10 as usize; | ^^^^^^^^^^^^^ help: try: `0b10_usize` error: casting integer literal to `u16` is unnecessary - --> tests/ui/unnecessary_cast.rs:178:9 + --> tests/ui/unnecessary_cast.rs:206:9 | LL | 0o73 as u16; | ^^^^^^^^^^^ help: try: `0o73_u16` error: casting integer literal to `u32` is unnecessary - --> tests/ui/unnecessary_cast.rs:179:9 + --> tests/ui/unnecessary_cast.rs:208:9 | LL | 1_000_000_000 as u32; | ^^^^^^^^^^^^^^^^^^^^ help: try: `1_000_000_000_u32` error: casting float literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:181:9 + --> tests/ui/unnecessary_cast.rs:211:9 | LL | 1.0 as f64; | ^^^^^^^^^^ help: try: `1.0_f64` error: casting float literal to `f32` is unnecessary - --> tests/ui/unnecessary_cast.rs:182:9 + --> tests/ui/unnecessary_cast.rs:213:9 | LL | 0.5 as f32; | ^^^^^^^^^^ help: try: `0.5_f32` error: casting integer literal to `i32` is unnecessary - --> tests/ui/unnecessary_cast.rs:186:17 + --> tests/ui/unnecessary_cast.rs:218:17 | LL | let _ = -1 as i32; | ^^^^^^^^^ help: try: `-1_i32` error: casting float literal to `f32` is unnecessary - --> tests/ui/unnecessary_cast.rs:187:17 + --> tests/ui/unnecessary_cast.rs:220:17 | LL | let _ = -1.0 as f32; | ^^^^^^^^^^^ help: try: `-1.0_f32` error: casting to the same type is unnecessary (`i32` -> `i32`) - --> tests/ui/unnecessary_cast.rs:193:18 + --> tests/ui/unnecessary_cast.rs:227:18 | LL | let _ = &(x as i32); | ^^^^^^^^^^ help: try: `{ x }` error: casting integer literal to `i32` is unnecessary - --> tests/ui/unnecessary_cast.rs:199:22 + --> tests/ui/unnecessary_cast.rs:234:22 | LL | let _: i32 = -(1) as i32; | ^^^^^^^^^^^ help: try: `-1_i32` error: casting integer literal to `i64` is unnecessary - --> tests/ui/unnecessary_cast.rs:201:22 + --> tests/ui/unnecessary_cast.rs:237:22 | LL | let _: i64 = -(1) as i64; | ^^^^^^^^^^^ help: try: `-1_i64` error: casting float literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:208:22 + --> tests/ui/unnecessary_cast.rs:245:22 | LL | let _: f64 = (-8.0 as f64).exp(); | ^^^^^^^^^^^^^ help: try: `(-8.0_f64)` error: casting float literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:210:23 + --> tests/ui/unnecessary_cast.rs:248:23 | LL | let _: f64 = -(8.0 as f64).exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior | ^^^^^^^^^^^^ help: try: `8.0_f64` error: casting to the same type is unnecessary (`f32` -> `f32`) - --> tests/ui/unnecessary_cast.rs:218:20 + --> tests/ui/unnecessary_cast.rs:258:20 | LL | let _num = foo() as f32; | ^^^^^^^^^^^^ help: try: `foo()` error: casting to the same type is unnecessary (`usize` -> `usize`) - --> tests/ui/unnecessary_cast.rs:228:9 + --> tests/ui/unnecessary_cast.rs:269:9 | LL | (*x as usize).pow(2) | ^^^^^^^^^^^^^ help: try: `{ *x }` diff --git a/tests/ui/unnecessary_cast_unfixable.rs b/tests/ui/unnecessary_cast_unfixable.rs index 36adf19c91ca..2bb64c3e80e3 100644 --- a/tests/ui/unnecessary_cast_unfixable.rs +++ b/tests/ui/unnecessary_cast_unfixable.rs @@ -2,8 +2,7 @@ //@no-rustfix fn main() { let _ = std::ptr::null() as *const u8; - //~^ ERROR: casting raw pointers to the same type and constness is unnecessary (`*cons - //~| NOTE: `-D clippy::unnecessary-cast` implied by `-D warnings` + //~^ unnecessary_cast } mod issue11113 { @@ -19,7 +18,7 @@ mod issue11113 { impl TearOff { unsafe fn query(&self) { ((*(*(self.object as *mut *mut _) as *mut Vtbl)).query)() - //~^ ERROR: casting raw pointers to the same type and constness is unnecessary + //~^ unnecessary_cast } } } diff --git a/tests/ui/unnecessary_cast_unfixable.stderr b/tests/ui/unnecessary_cast_unfixable.stderr index cafaffeae6c3..6ba1c7873066 100644 --- a/tests/ui/unnecessary_cast_unfixable.stderr +++ b/tests/ui/unnecessary_cast_unfixable.stderr @@ -8,7 +8,7 @@ LL | let _ = std::ptr::null() as *const u8; = help: to override `-D warnings` add `#[allow(clippy::unnecessary_cast)]` error: casting raw pointers to the same type and constness is unnecessary (`*mut issue11113::Vtbl` -> `*mut issue11113::Vtbl`) - --> tests/ui/unnecessary_cast_unfixable.rs:21:16 + --> tests/ui/unnecessary_cast_unfixable.rs:20:16 | LL | ((*(*(self.object as *mut *mut _) as *mut Vtbl)).query)() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `*(self.object as *mut *mut _)` diff --git a/tests/ui/unnecessary_clippy_cfg.rs b/tests/ui/unnecessary_clippy_cfg.rs index 9915f8b843ef..e7e01248dfbe 100644 --- a/tests/ui/unnecessary_clippy_cfg.rs +++ b/tests/ui/unnecessary_clippy_cfg.rs @@ -2,22 +2,25 @@ #![warn(clippy::unnecessary_clippy_cfg)] #![cfg_attr(clippy, deny(clippy::non_minimal_cfg))] -//~^ ERROR: no need to put clippy lints behind a `clippy` cfg +//~^ unnecessary_clippy_cfg #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] -//~^ ERROR: no need to put clippy lints behind a `clippy` cfg +//~^ unnecessary_clippy_cfg #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] -//~^ ERROR: no need to put clippy lints behind a `clippy` cfg +//~^ unnecessary_clippy_cfg +//~| duplicated_attributes #![cfg_attr(clippy, deny(clippy::non_minimal_cfg))] -//~^ ERROR: no need to put clippy lints behind a `clippy` cfg +//~^ unnecessary_clippy_cfg #[cfg_attr(clippy, deny(clippy::non_minimal_cfg))] -//~^ ERROR: no need to put clippy lints behind a `clippy` cfg +//~^ unnecessary_clippy_cfg #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] -//~^ ERROR: no need to put clippy lints behind a `clippy` cfg +//~^ unnecessary_clippy_cfg #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] -//~^ ERROR: no need to put clippy lints behind a `clippy` cfg +//~^ unnecessary_clippy_cfg +//~| duplicated_attributes #[cfg_attr(clippy, deny(clippy::non_minimal_cfg))] -//~^ ERROR: no need to put clippy lints behind a `clippy` cfg +//~^ unnecessary_clippy_cfg + pub struct Bar; fn main() {} diff --git a/tests/ui/unnecessary_clippy_cfg.stderr b/tests/ui/unnecessary_clippy_cfg.stderr index 01f842a657de..f66c68949548 100644 --- a/tests/ui/unnecessary_clippy_cfg.stderr +++ b/tests/ui/unnecessary_clippy_cfg.stderr @@ -24,19 +24,19 @@ LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] = note: write instead: `#![deny(clippy::non_minimal_cfg)]` error: no need to put clippy lints behind a `clippy` cfg - --> tests/ui/unnecessary_clippy_cfg.rs:10:1 + --> tests/ui/unnecessary_clippy_cfg.rs:11:1 | LL | #![cfg_attr(clippy, deny(clippy::non_minimal_cfg))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#![deny(clippy::non_minimal_cfg)]` error: no need to put clippy lints behind a `clippy` cfg - --> tests/ui/unnecessary_clippy_cfg.rs:13:1 + --> tests/ui/unnecessary_clippy_cfg.rs:14:1 | LL | #[cfg_attr(clippy, deny(clippy::non_minimal_cfg))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#[deny(clippy::non_minimal_cfg)]` error: no need to put clippy lints behind a `clippy` cfg - --> tests/ui/unnecessary_clippy_cfg.rs:15:36 + --> tests/ui/unnecessary_clippy_cfg.rs:16:36 | LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] = note: write instead: `#[deny(clippy::non_minimal_cfg)]` error: no need to put clippy lints behind a `clippy` cfg - --> tests/ui/unnecessary_clippy_cfg.rs:17:36 + --> tests/ui/unnecessary_clippy_cfg.rs:18:36 | LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,7 +52,7 @@ LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] = note: write instead: `#[deny(clippy::non_minimal_cfg)]` error: no need to put clippy lints behind a `clippy` cfg - --> tests/ui/unnecessary_clippy_cfg.rs:19:1 + --> tests/ui/unnecessary_clippy_cfg.rs:21:1 | LL | #[cfg_attr(clippy, deny(clippy::non_minimal_cfg))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#[deny(clippy::non_minimal_cfg)]` @@ -77,18 +77,18 @@ LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] = help: to override `-D warnings` add `#[allow(clippy::duplicated_attributes)]` error: duplicated attribute - --> tests/ui/unnecessary_clippy_cfg.rs:17:25 + --> tests/ui/unnecessary_clippy_cfg.rs:18:25 | LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] | ^^^^^^^^^ | note: first defined here - --> tests/ui/unnecessary_clippy_cfg.rs:15:25 + --> tests/ui/unnecessary_clippy_cfg.rs:16:25 | LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] | ^^^^^^^^^ help: remove this attribute - --> tests/ui/unnecessary_clippy_cfg.rs:17:25 + --> tests/ui/unnecessary_clippy_cfg.rs:18:25 | LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] | ^^^^^^^^^ diff --git a/tests/ui/unnecessary_clone.rs b/tests/ui/unnecessary_clone.rs index 12ac96aa64ca..7335b6f9f039 100644 --- a/tests/ui/unnecessary_clone.rs +++ b/tests/ui/unnecessary_clone.rs @@ -21,34 +21,36 @@ fn clone_on_ref_ptr() { let arc_weak = Arc::downgrade(&arc); rc.clone(); - //~^ ERROR: using `.clone()` on a ref-counted pointer - //~| NOTE: `-D clippy::clone-on-ref-ptr` implied by `-D warnings` + //~^ clone_on_ref_ptr + Rc::clone(&rc); arc.clone(); - //~^ ERROR: using `.clone()` on a ref-counted pointer + //~^ clone_on_ref_ptr + Arc::clone(&arc); rcweak.clone(); - //~^ ERROR: using `.clone()` on a ref-counted pointer + //~^ clone_on_ref_ptr + rc::Weak::clone(&rcweak); arc_weak.clone(); - //~^ ERROR: using `.clone()` on a ref-counted pointer + //~^ clone_on_ref_ptr + sync::Weak::clone(&arc_weak); let x = Arc::new(SomeImpl); let _: Arc = x.clone(); - //~^ ERROR: using `.clone()` on a ref-counted pointer + //~^ clone_on_ref_ptr } fn clone_on_copy_generic(t: T) { t.clone(); - //~^ ERROR: using `clone` on type `T` which implements the `Copy` trait - //~| NOTE: `-D clippy::clone-on-copy` implied by `-D warnings` + //~^ clone_on_copy Some(t).clone(); - //~^ ERROR: using `clone` on type `Option` which implements the `Copy` trait + //~^ clone_on_copy } mod many_derefs { @@ -83,7 +85,8 @@ mod many_derefs { fn go1() { let a = A; let _: E = a.clone(); - //~^ ERROR: using `clone` on type `E` which implements the `Copy` trait + //~^ clone_on_copy + let _: E = *****a; } } @@ -103,6 +106,6 @@ mod issue2076 { fn func() -> Option> { let rc = Rc::new(42); Some(try_opt!(Some(rc)).clone()) - //~^ ERROR: using `.clone()` on a ref-counted pointer + //~^ clone_on_ref_ptr } } diff --git a/tests/ui/unnecessary_clone.stderr b/tests/ui/unnecessary_clone.stderr index e34a387c77e2..a4fdf09cd5dc 100644 --- a/tests/ui/unnecessary_clone.stderr +++ b/tests/ui/unnecessary_clone.stderr @@ -14,25 +14,25 @@ LL | arc.clone(); | ^^^^^^^^^^^ help: try: `Arc::::clone(&arc)` error: using `.clone()` on a ref-counted pointer - --> tests/ui/unnecessary_clone.rs:32:5 + --> tests/ui/unnecessary_clone.rs:33:5 | LL | rcweak.clone(); | ^^^^^^^^^^^^^^ help: try: `Weak::::clone(&rcweak)` error: using `.clone()` on a ref-counted pointer - --> tests/ui/unnecessary_clone.rs:36:5 + --> tests/ui/unnecessary_clone.rs:38:5 | LL | arc_weak.clone(); | ^^^^^^^^^^^^^^^^ help: try: `Weak::::clone(&arc_weak)` error: using `.clone()` on a ref-counted pointer - --> tests/ui/unnecessary_clone.rs:41:33 + --> tests/ui/unnecessary_clone.rs:44:33 | LL | let _: Arc = x.clone(); | ^^^^^^^^^ help: try: `Arc::::clone(&x)` error: using `clone` on type `T` which implements the `Copy` trait - --> tests/ui/unnecessary_clone.rs:46:5 + --> tests/ui/unnecessary_clone.rs:49:5 | LL | t.clone(); | ^^^^^^^^^ help: try removing the `clone` call: `t` @@ -41,19 +41,19 @@ LL | t.clone(); = help: to override `-D warnings` add `#[allow(clippy::clone_on_copy)]` error: using `clone` on type `Option` which implements the `Copy` trait - --> tests/ui/unnecessary_clone.rs:50:5 + --> tests/ui/unnecessary_clone.rs:52:5 | LL | Some(t).clone(); | ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)` error: using `clone` on type `E` which implements the `Copy` trait - --> tests/ui/unnecessary_clone.rs:85:20 + --> tests/ui/unnecessary_clone.rs:87:20 | LL | let _: E = a.clone(); | ^^^^^^^^^ help: try dereferencing it: `*****a` error: using `.clone()` on a ref-counted pointer - --> tests/ui/unnecessary_clone.rs:105:14 + --> tests/ui/unnecessary_clone.rs:108:14 | LL | Some(try_opt!(Some(rc)).clone()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Rc::::clone(&try_opt!(Some(rc)))` diff --git a/tests/ui/unnecessary_fallible_conversions.fixed b/tests/ui/unnecessary_fallible_conversions.fixed index b6dd1f267743..bae8f066cf12 100644 --- a/tests/ui/unnecessary_fallible_conversions.fixed +++ b/tests/ui/unnecessary_fallible_conversions.fixed @@ -4,40 +4,40 @@ fn main() { // --- TryFromMethod `T::try_from(u)` --- let _: i64 = 0i32.into(); - //~^ ERROR: use of a fallible conversion when an infallible one could be used + //~^ unnecessary_fallible_conversions let _: i64 = 0i32.into(); - //~^ ERROR: use of a fallible conversion when an infallible one could be used + //~^ unnecessary_fallible_conversions // --- TryFromFunction `T::try_from(U)` --- let _ = i64::from(0i32); - //~^ ERROR: use of a fallible conversion when an infallible one could be used + //~^ unnecessary_fallible_conversions let _ = i64::from(0i32); - //~^ ERROR: use of a fallible conversion when an infallible one could be used + //~^ unnecessary_fallible_conversions // --- TryIntoFunction `U::try_into(t)` --- let _: i64 = i32::into(0); - //~^ ERROR: use of a fallible conversion when an infallible one could be used + //~^ unnecessary_fallible_conversions let _: i64 = i32::into(0i32); - //~^ ERROR: use of a fallible conversion when an infallible one could be used + //~^ unnecessary_fallible_conversions // --- TryFromFunction `>::try_from(U)` --- let _ = >::from(0); - //~^ ERROR: use of a fallible conversion when an infallible one could be used + //~^ unnecessary_fallible_conversions let _ = >::from(0); - //~^ ERROR: use of a fallible conversion when an infallible one could be used + //~^ unnecessary_fallible_conversions // --- TryIntoFunction `>::try_into(U)` --- let _: i64 = >::into(0); - //~^ ERROR: use of a fallible conversion when an infallible one could be used + //~^ unnecessary_fallible_conversions let _: i64 = >::into(0); - //~^ ERROR: use of a fallible conversion when an infallible one could be used + //~^ unnecessary_fallible_conversions } diff --git a/tests/ui/unnecessary_fallible_conversions.rs b/tests/ui/unnecessary_fallible_conversions.rs index 6f8df7365e89..04c9826f3765 100644 --- a/tests/ui/unnecessary_fallible_conversions.rs +++ b/tests/ui/unnecessary_fallible_conversions.rs @@ -4,40 +4,40 @@ fn main() { // --- TryFromMethod `T::try_from(u)` --- let _: i64 = 0i32.try_into().unwrap(); - //~^ ERROR: use of a fallible conversion when an infallible one could be used + //~^ unnecessary_fallible_conversions let _: i64 = 0i32.try_into().expect("can't happen"); - //~^ ERROR: use of a fallible conversion when an infallible one could be used + //~^ unnecessary_fallible_conversions // --- TryFromFunction `T::try_from(U)` --- let _ = i64::try_from(0i32).unwrap(); - //~^ ERROR: use of a fallible conversion when an infallible one could be used + //~^ unnecessary_fallible_conversions let _ = i64::try_from(0i32).expect("can't happen"); - //~^ ERROR: use of a fallible conversion when an infallible one could be used + //~^ unnecessary_fallible_conversions // --- TryIntoFunction `U::try_into(t)` --- let _: i64 = i32::try_into(0).unwrap(); - //~^ ERROR: use of a fallible conversion when an infallible one could be used + //~^ unnecessary_fallible_conversions let _: i64 = i32::try_into(0i32).expect("can't happen"); - //~^ ERROR: use of a fallible conversion when an infallible one could be used + //~^ unnecessary_fallible_conversions // --- TryFromFunction `>::try_from(U)` --- let _ = >::try_from(0).unwrap(); - //~^ ERROR: use of a fallible conversion when an infallible one could be used + //~^ unnecessary_fallible_conversions let _ = >::try_from(0).expect("can't happen"); - //~^ ERROR: use of a fallible conversion when an infallible one could be used + //~^ unnecessary_fallible_conversions // --- TryIntoFunction `>::try_into(U)` --- let _: i64 = >::try_into(0).unwrap(); - //~^ ERROR: use of a fallible conversion when an infallible one could be used + //~^ unnecessary_fallible_conversions let _: i64 = >::try_into(0).expect("can't happen"); - //~^ ERROR: use of a fallible conversion when an infallible one could be used + //~^ unnecessary_fallible_conversions } diff --git a/tests/ui/unnecessary_filter_map.rs b/tests/ui/unnecessary_filter_map.rs index 8cf102ab0a55..c4f1b6bc7e3d 100644 --- a/tests/ui/unnecessary_filter_map.rs +++ b/tests/ui/unnecessary_filter_map.rs @@ -3,29 +3,33 @@ fn main() { let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None }); - //~^ ERROR: this `.filter_map` can be written more simply - //~| NOTE: `-D clippy::unnecessary-filter-map` implied by `-D warnings` + //~^ unnecessary_filter_map + let _ = (0..4).filter_map(|x| { - //~^ ERROR: this `.filter_map` can be written more simply + //~^ unnecessary_filter_map + if x > 1 { return Some(x); }; None }); let _ = (0..4).filter_map(|x| match x { - //~^ ERROR: this `.filter_map` can be written more simply + //~^ unnecessary_filter_map 0 | 1 => None, _ => Some(x), }); let _ = (0..4).filter_map(|x| Some(x + 1)); - //~^ ERROR: this `.filter_map` can be written more simply + //~^ unnecessary_filter_map let _ = (0..4).filter_map(i32::checked_abs); let _ = (0..4).filter_map(Some); let _ = vec![Some(10), None].into_iter().filter_map(|x| Some(x)); + //~^ redundant_closure + //~| unnecessary_filter_map + //~| unnecessary_filter_map } fn filter_map_none_changes_item_type() -> impl Iterator { @@ -163,4 +167,5 @@ fn issue11260() { // #11260 is about unnecessary_find_map, but the fix also kind of applies to // unnecessary_filter_map let _x = std::iter::once(1).filter_map(|n| (n > 1).then_some(n)); + //~^ unnecessary_filter_map } diff --git a/tests/ui/unnecessary_filter_map.stderr b/tests/ui/unnecessary_filter_map.stderr index b21589c5f844..6683444b7273 100644 --- a/tests/ui/unnecessary_filter_map.stderr +++ b/tests/ui/unnecessary_filter_map.stderr @@ -13,15 +13,15 @@ error: this `.filter_map` can be written more simply LL | let _ = (0..4).filter_map(|x| { | _____________^ LL | | +LL | | LL | | if x > 1 { -LL | | return Some(x); -LL | | }; +... | LL | | None LL | | }); | |______^ help: try instead: `filter` error: this `.filter_map` can be written more simply - --> tests/ui/unnecessary_filter_map.rs:15:13 + --> tests/ui/unnecessary_filter_map.rs:16:13 | LL | let _ = (0..4).filter_map(|x| match x { | _____________^ @@ -32,13 +32,13 @@ LL | | }); | |______^ help: try instead: `filter` error: this `.filter_map` can be written more simply - --> tests/ui/unnecessary_filter_map.rs:21:13 + --> tests/ui/unnecessary_filter_map.rs:22:13 | LL | let _ = (0..4).filter_map(|x| Some(x + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `map` error: redundant closure - --> tests/ui/unnecessary_filter_map.rs:28:57 + --> tests/ui/unnecessary_filter_map.rs:29:57 | LL | let _ = vec![Some(10), None].into_iter().filter_map(|x| Some(x)); | ^^^^^^^^^^^ help: replace the closure with the function itself: `Some` @@ -47,19 +47,19 @@ LL | let _ = vec![Some(10), None].into_iter().filter_map(|x| Some(x)); = help: to override `-D warnings` add `#[allow(clippy::redundant_closure)]` error: filter_map is unnecessary - --> tests/ui/unnecessary_filter_map.rs:28:61 + --> tests/ui/unnecessary_filter_map.rs:29:61 | LL | let _ = vec![Some(10), None].into_iter().filter_map(|x| Some(x)); | ^^^^ help: try removing the filter_map error: this `.filter_map` can be written more simply - --> tests/ui/unnecessary_filter_map.rs:28:13 + --> tests/ui/unnecessary_filter_map.rs:29:13 | LL | let _ = vec![Some(10), None].into_iter().filter_map(|x| Some(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `map` error: this `.filter_map` can be written more simply - --> tests/ui/unnecessary_filter_map.rs:165:14 + --> tests/ui/unnecessary_filter_map.rs:169:14 | LL | let _x = std::iter::once(1).filter_map(|n| (n > 1).then_some(n)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `filter` diff --git a/tests/ui/unnecessary_find_map.rs b/tests/ui/unnecessary_find_map.rs index c357d8532481..8c8a3799f021 100644 --- a/tests/ui/unnecessary_find_map.rs +++ b/tests/ui/unnecessary_find_map.rs @@ -3,23 +3,24 @@ fn main() { let _ = (0..4).find_map(|x| if x > 1 { Some(x) } else { None }); - //~^ ERROR: this `.find_map` can be written more simply - //~| NOTE: `-D clippy::unnecessary-find-map` implied by `-D warnings` + //~^ unnecessary_find_map + let _ = (0..4).find_map(|x| { - //~^ ERROR: this `.find_map` can be written more simply + //~^ unnecessary_find_map + if x > 1 { return Some(x); }; None }); let _ = (0..4).find_map(|x| match x { - //~^ ERROR: this `.find_map` can be written more simply + //~^ unnecessary_find_map 0 | 1 => None, _ => Some(x), }); let _ = (0..4).find_map(|x| Some(x + 1)); - //~^ ERROR: this `.find_map` can be written more simply + //~^ unnecessary_find_map let _ = (0..4).find_map(i32::checked_abs); } @@ -31,5 +32,6 @@ fn find_map_none_changes_item_type() -> Option { fn issue11260() { let y = Some(1); let _x = std::iter::once(1).find_map(|n| (n > 1).then_some(n)); + //~^ unnecessary_find_map let _x = std::iter::once(1).find_map(|n| (n > 1).then_some(y)); // different option, so can't be just `.find()` } diff --git a/tests/ui/unnecessary_find_map.stderr b/tests/ui/unnecessary_find_map.stderr index 98a6c3d164a6..94e320773a6f 100644 --- a/tests/ui/unnecessary_find_map.stderr +++ b/tests/ui/unnecessary_find_map.stderr @@ -13,15 +13,15 @@ error: this `.find_map` can be written more simply LL | let _ = (0..4).find_map(|x| { | _____________^ LL | | +LL | | LL | | if x > 1 { -LL | | return Some(x); -LL | | }; +... | LL | | None LL | | }); | |______^ help: try instead: `find` error: this `.find_map` can be written more simply - --> tests/ui/unnecessary_find_map.rs:15:13 + --> tests/ui/unnecessary_find_map.rs:16:13 | LL | let _ = (0..4).find_map(|x| match x { | _____________^ @@ -32,13 +32,13 @@ LL | | }); | |______^ help: try instead: `find` error: this `.find_map` can be written more simply - --> tests/ui/unnecessary_find_map.rs:21:13 + --> tests/ui/unnecessary_find_map.rs:22:13 | LL | let _ = (0..4).find_map(|x| Some(x + 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `map(..).next()` error: this `.find_map` can be written more simply - --> tests/ui/unnecessary_find_map.rs:33:14 + --> tests/ui/unnecessary_find_map.rs:34:14 | LL | let _x = std::iter::once(1).find_map(|n| (n > 1).then_some(n)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `find` diff --git a/tests/ui/unnecessary_first_then_check.fixed b/tests/ui/unnecessary_first_then_check.fixed index 7202e1bbd179..aa049eb33751 100644 --- a/tests/ui/unnecessary_first_then_check.fixed +++ b/tests/ui/unnecessary_first_then_check.fixed @@ -4,19 +4,26 @@ fn main() { let s = [1, 2, 3]; let _: bool = !s.is_empty(); + //~^ unnecessary_first_then_check let _: bool = s.is_empty(); + //~^ unnecessary_first_then_check let v = vec![1, 2, 3]; let _: bool = !v.is_empty(); + //~^ unnecessary_first_then_check let n = [[1, 2, 3], [4, 5, 6]]; let _: bool = !n[0].is_empty(); + //~^ unnecessary_first_then_check let _: bool = n[0].is_empty(); + //~^ unnecessary_first_then_check struct Foo { bar: &'static [i32], } let f = [Foo { bar: &[] }]; let _: bool = !f[0].bar.is_empty(); + //~^ unnecessary_first_then_check let _: bool = f[0].bar.is_empty(); + //~^ unnecessary_first_then_check } diff --git a/tests/ui/unnecessary_first_then_check.rs b/tests/ui/unnecessary_first_then_check.rs index 762b95999288..4c2ac3ba40a2 100644 --- a/tests/ui/unnecessary_first_then_check.rs +++ b/tests/ui/unnecessary_first_then_check.rs @@ -4,19 +4,26 @@ fn main() { let s = [1, 2, 3]; let _: bool = s.first().is_some(); + //~^ unnecessary_first_then_check let _: bool = s.first().is_none(); + //~^ unnecessary_first_then_check let v = vec![1, 2, 3]; let _: bool = v.first().is_some(); + //~^ unnecessary_first_then_check let n = [[1, 2, 3], [4, 5, 6]]; let _: bool = n[0].first().is_some(); + //~^ unnecessary_first_then_check let _: bool = n[0].first().is_none(); + //~^ unnecessary_first_then_check struct Foo { bar: &'static [i32], } let f = [Foo { bar: &[] }]; let _: bool = f[0].bar.first().is_some(); + //~^ unnecessary_first_then_check let _: bool = f[0].bar.first().is_none(); + //~^ unnecessary_first_then_check } diff --git a/tests/ui/unnecessary_first_then_check.stderr b/tests/ui/unnecessary_first_then_check.stderr index bbaf7e68edab..408b388ecf71 100644 --- a/tests/ui/unnecessary_first_then_check.stderr +++ b/tests/ui/unnecessary_first_then_check.stderr @@ -8,37 +8,37 @@ LL | let _: bool = s.first().is_some(); = help: to override `-D warnings` add `#[allow(clippy::unnecessary_first_then_check)]` error: unnecessary use of `first().is_none()` to check if slice is empty - --> tests/ui/unnecessary_first_then_check.rs:7:21 + --> tests/ui/unnecessary_first_then_check.rs:8:21 | LL | let _: bool = s.first().is_none(); | ^^^^^^^^^^^^^^^^^ help: replace this with: `is_empty()` error: unnecessary use of `first().is_some()` to check if slice is not empty - --> tests/ui/unnecessary_first_then_check.rs:10:19 + --> tests/ui/unnecessary_first_then_check.rs:12:19 | LL | let _: bool = v.first().is_some(); | ^^^^^^^^^^^^^^^^^^^ help: replace this with: `!v.is_empty()` error: unnecessary use of `first().is_some()` to check if slice is not empty - --> tests/ui/unnecessary_first_then_check.rs:13:19 + --> tests/ui/unnecessary_first_then_check.rs:16:19 | LL | let _: bool = n[0].first().is_some(); | ^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `!n[0].is_empty()` error: unnecessary use of `first().is_none()` to check if slice is empty - --> tests/ui/unnecessary_first_then_check.rs:14:24 + --> tests/ui/unnecessary_first_then_check.rs:18:24 | LL | let _: bool = n[0].first().is_none(); | ^^^^^^^^^^^^^^^^^ help: replace this with: `is_empty()` error: unnecessary use of `first().is_some()` to check if slice is not empty - --> tests/ui/unnecessary_first_then_check.rs:20:19 + --> tests/ui/unnecessary_first_then_check.rs:25:19 | LL | let _: bool = f[0].bar.first().is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `!f[0].bar.is_empty()` error: unnecessary use of `first().is_none()` to check if slice is empty - --> tests/ui/unnecessary_first_then_check.rs:21:28 + --> tests/ui/unnecessary_first_then_check.rs:27:28 | LL | let _: bool = f[0].bar.first().is_none(); | ^^^^^^^^^^^^^^^^^ help: replace this with: `is_empty()` diff --git a/tests/ui/unnecessary_fold.fixed b/tests/ui/unnecessary_fold.fixed index c5bc11b55ab5..1c331be75094 100644 --- a/tests/ui/unnecessary_fold.fixed +++ b/tests/ui/unnecessary_fold.fixed @@ -8,19 +8,25 @@ fn is_any(acc: bool, x: usize) -> bool { fn unnecessary_fold() { // Can be replaced by .any let _ = (0..3).any(|x| x > 2); + //~^ unnecessary_fold // Can be replaced by .any (checking suggestion) let _ = (0..3).fold(false, is_any); + //~^ redundant_closure // Can be replaced by .all let _ = (0..3).all(|x| x > 2); + //~^ unnecessary_fold // Can be replaced by .sum let _: i32 = (0..3).sum(); + //~^ unnecessary_fold // Can be replaced by .product let _: i32 = (0..3).product(); + //~^ unnecessary_fold } /// Should trigger the `UNNECESSARY_FOLD` lint, with an error span including exactly `.fold(...)` fn unnecessary_fold_span_for_multi_element_chain() { let _: bool = (0..3).map(|x| 2 * x).any(|x| x > 2); + //~^ unnecessary_fold } /// Calls which should not trigger the `UNNECESSARY_FOLD` lint @@ -51,6 +57,7 @@ fn unnecessary_fold_over_multiple_lines() { .map(|x| x + 1) .filter(|x| x % 2 == 0) .any(|x| x > 2); + //~^ unnecessary_fold } fn issue10000() { @@ -62,16 +69,25 @@ fn issue10000() { fn smoketest_map(mut map: HashMap) { map.insert(0, 0); assert_eq!(map.values().sum::(), 0); + //~^ unnecessary_fold // more cases: let _ = map.values().sum::(); + //~^ unnecessary_fold let _ = map.values().product::(); + //~^ unnecessary_fold let _: i32 = map.values().sum(); + //~^ unnecessary_fold let _: i32 = map.values().product(); + //~^ unnecessary_fold anything(map.values().sum::()); + //~^ unnecessary_fold anything(map.values().product::()); + //~^ unnecessary_fold num(map.values().sum()); + //~^ unnecessary_fold num(map.values().product()); + //~^ unnecessary_fold } smoketest_map(HashMap::new()); diff --git a/tests/ui/unnecessary_fold.rs b/tests/ui/unnecessary_fold.rs index 3a5136eeeaeb..e2050e37e3b1 100644 --- a/tests/ui/unnecessary_fold.rs +++ b/tests/ui/unnecessary_fold.rs @@ -8,19 +8,25 @@ fn is_any(acc: bool, x: usize) -> bool { fn unnecessary_fold() { // Can be replaced by .any let _ = (0..3).fold(false, |acc, x| acc || x > 2); + //~^ unnecessary_fold // Can be replaced by .any (checking suggestion) let _ = (0..3).fold(false, |acc, x| is_any(acc, x)); + //~^ redundant_closure // Can be replaced by .all let _ = (0..3).fold(true, |acc, x| acc && x > 2); + //~^ unnecessary_fold // Can be replaced by .sum let _: i32 = (0..3).fold(0, |acc, x| acc + x); + //~^ unnecessary_fold // Can be replaced by .product let _: i32 = (0..3).fold(1, |acc, x| acc * x); + //~^ unnecessary_fold } /// Should trigger the `UNNECESSARY_FOLD` lint, with an error span including exactly `.fold(...)` fn unnecessary_fold_span_for_multi_element_chain() { let _: bool = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); + //~^ unnecessary_fold } /// Calls which should not trigger the `UNNECESSARY_FOLD` lint @@ -51,6 +57,7 @@ fn unnecessary_fold_over_multiple_lines() { .map(|x| x + 1) .filter(|x| x % 2 == 0) .fold(false, |acc, x| acc || x > 2); + //~^ unnecessary_fold } fn issue10000() { @@ -62,16 +69,25 @@ fn issue10000() { fn smoketest_map(mut map: HashMap) { map.insert(0, 0); assert_eq!(map.values().fold(0, |x, y| x + y), 0); + //~^ unnecessary_fold // more cases: let _ = map.values().fold(0, |x, y| x + y); + //~^ unnecessary_fold let _ = map.values().fold(1, |x, y| x * y); + //~^ unnecessary_fold let _: i32 = map.values().fold(0, |x, y| x + y); + //~^ unnecessary_fold let _: i32 = map.values().fold(1, |x, y| x * y); + //~^ unnecessary_fold anything(map.values().fold(0, |x, y| x + y)); + //~^ unnecessary_fold anything(map.values().fold(1, |x, y| x * y)); + //~^ unnecessary_fold num(map.values().fold(0, |x, y| x + y)); + //~^ unnecessary_fold num(map.values().fold(1, |x, y| x * y)); + //~^ unnecessary_fold } smoketest_map(HashMap::new()); diff --git a/tests/ui/unnecessary_fold.stderr b/tests/ui/unnecessary_fold.stderr index 31abab62f4c6..d82b1f39b48b 100644 --- a/tests/ui/unnecessary_fold.stderr +++ b/tests/ui/unnecessary_fold.stderr @@ -8,7 +8,7 @@ LL | let _ = (0..3).fold(false, |acc, x| acc || x > 2); = help: to override `-D warnings` add `#[allow(clippy::unnecessary_fold)]` error: redundant closure - --> tests/ui/unnecessary_fold.rs:12:32 + --> tests/ui/unnecessary_fold.rs:13:32 | LL | let _ = (0..3).fold(false, |acc, x| is_any(acc, x)); | ^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `is_any` @@ -17,85 +17,85 @@ LL | let _ = (0..3).fold(false, |acc, x| is_any(acc, x)); = help: to override `-D warnings` add `#[allow(clippy::redundant_closure)]` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:14:20 + --> tests/ui/unnecessary_fold.rs:16:20 | LL | let _ = (0..3).fold(true, |acc, x| acc && x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `all(|x| x > 2)` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:16:25 + --> tests/ui/unnecessary_fold.rs:19:25 | LL | let _: i32 = (0..3).fold(0, |acc, x| acc + x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `sum()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:18:25 + --> tests/ui/unnecessary_fold.rs:22:25 | LL | let _: i32 = (0..3).fold(1, |acc, x| acc * x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `product()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:23:41 + --> tests/ui/unnecessary_fold.rs:28:41 | LL | let _: bool = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `any(|x| x > 2)` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:53:10 + --> tests/ui/unnecessary_fold.rs:59:10 | LL | .fold(false, |acc, x| acc || x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `any(|x| x > 2)` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:64:33 + --> tests/ui/unnecessary_fold.rs:71:33 | LL | assert_eq!(map.values().fold(0, |x, y| x + y), 0); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:67:30 + --> tests/ui/unnecessary_fold.rs:75:30 | LL | let _ = map.values().fold(0, |x, y| x + y); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:68:30 + --> tests/ui/unnecessary_fold.rs:77:30 | LL | let _ = map.values().fold(1, |x, y| x * y); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `product::()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:69:35 + --> tests/ui/unnecessary_fold.rs:79:35 | LL | let _: i32 = map.values().fold(0, |x, y| x + y); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:70:35 + --> tests/ui/unnecessary_fold.rs:81:35 | LL | let _: i32 = map.values().fold(1, |x, y| x * y); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `product()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:71:31 + --> tests/ui/unnecessary_fold.rs:83:31 | LL | anything(map.values().fold(0, |x, y| x + y)); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:72:31 + --> tests/ui/unnecessary_fold.rs:85:31 | LL | anything(map.values().fold(1, |x, y| x * y)); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `product::()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:73:26 + --> tests/ui/unnecessary_fold.rs:87:26 | LL | num(map.values().fold(0, |x, y| x + y)); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum()` error: this `.fold` can be written more succinctly using another method - --> tests/ui/unnecessary_fold.rs:74:26 + --> tests/ui/unnecessary_fold.rs:89:26 | LL | num(map.values().fold(1, |x, y| x * y)); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `product()` diff --git a/tests/ui/unnecessary_get_then_check.fixed b/tests/ui/unnecessary_get_then_check.fixed index 178a3300c346..c6da769544e0 100644 --- a/tests/ui/unnecessary_get_then_check.fixed +++ b/tests/ui/unnecessary_get_then_check.fixed @@ -4,23 +4,33 @@ use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; fn main() { let s: HashSet = HashSet::new(); - let _ = s.contains("a"); //~ ERROR: unnecessary use of `get("a").is_some()` - let _ = !s.contains("a"); //~ ERROR: unnecessary use of `get("a").is_none()` + let _ = s.contains("a"); + //~^ unnecessary_get_then_check + let _ = !s.contains("a"); + //~^ unnecessary_get_then_check let s: HashMap = HashMap::new(); - let _ = s.contains_key("a"); //~ ERROR: unnecessary use of `get("a").is_some()` - let _ = !s.contains_key("a"); //~ ERROR: unnecessary use of `get("a").is_none()` + let _ = s.contains_key("a"); + //~^ unnecessary_get_then_check + let _ = !s.contains_key("a"); + //~^ unnecessary_get_then_check let s: BTreeSet = BTreeSet::new(); - let _ = s.contains("a"); //~ ERROR: unnecessary use of `get("a").is_some()` - let _ = !s.contains("a"); //~ ERROR: unnecessary use of `get("a").is_none()` + let _ = s.contains("a"); + //~^ unnecessary_get_then_check + let _ = !s.contains("a"); + //~^ unnecessary_get_then_check let s: BTreeMap = BTreeMap::new(); - let _ = s.contains_key("a"); //~ ERROR: unnecessary use of `get("a").is_some()` - let _ = !s.contains_key("a"); //~ ERROR: unnecessary use of `get("a").is_none()` + let _ = s.contains_key("a"); + //~^ unnecessary_get_then_check + let _ = !s.contains_key("a"); + //~^ unnecessary_get_then_check // Import to check that the generic annotations are kept! let s: HashSet = HashSet::new(); - let _ = s.contains::("a"); //~ ERROR: unnecessary use of `get::("a").is_some()` - let _ = !s.contains::("a"); //~ ERROR: unnecessary use of `get::("a").is_none()` + let _ = s.contains::("a"); + //~^ unnecessary_get_then_check + let _ = !s.contains::("a"); + //~^ unnecessary_get_then_check } diff --git a/tests/ui/unnecessary_get_then_check.rs b/tests/ui/unnecessary_get_then_check.rs index c197bdef47ea..323ccc2136ce 100644 --- a/tests/ui/unnecessary_get_then_check.rs +++ b/tests/ui/unnecessary_get_then_check.rs @@ -4,23 +4,33 @@ use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; fn main() { let s: HashSet = HashSet::new(); - let _ = s.get("a").is_some(); //~ ERROR: unnecessary use of `get("a").is_some()` - let _ = s.get("a").is_none(); //~ ERROR: unnecessary use of `get("a").is_none()` + let _ = s.get("a").is_some(); + //~^ unnecessary_get_then_check + let _ = s.get("a").is_none(); + //~^ unnecessary_get_then_check let s: HashMap = HashMap::new(); - let _ = s.get("a").is_some(); //~ ERROR: unnecessary use of `get("a").is_some()` - let _ = s.get("a").is_none(); //~ ERROR: unnecessary use of `get("a").is_none()` + let _ = s.get("a").is_some(); + //~^ unnecessary_get_then_check + let _ = s.get("a").is_none(); + //~^ unnecessary_get_then_check let s: BTreeSet = BTreeSet::new(); - let _ = s.get("a").is_some(); //~ ERROR: unnecessary use of `get("a").is_some()` - let _ = s.get("a").is_none(); //~ ERROR: unnecessary use of `get("a").is_none()` + let _ = s.get("a").is_some(); + //~^ unnecessary_get_then_check + let _ = s.get("a").is_none(); + //~^ unnecessary_get_then_check let s: BTreeMap = BTreeMap::new(); - let _ = s.get("a").is_some(); //~ ERROR: unnecessary use of `get("a").is_some()` - let _ = s.get("a").is_none(); //~ ERROR: unnecessary use of `get("a").is_none()` + let _ = s.get("a").is_some(); + //~^ unnecessary_get_then_check + let _ = s.get("a").is_none(); + //~^ unnecessary_get_then_check // Import to check that the generic annotations are kept! let s: HashSet = HashSet::new(); - let _ = s.get::("a").is_some(); //~ ERROR: unnecessary use of `get::("a").is_some()` - let _ = s.get::("a").is_none(); //~ ERROR: unnecessary use of `get::("a").is_none()` + let _ = s.get::("a").is_some(); + //~^ unnecessary_get_then_check + let _ = s.get::("a").is_none(); + //~^ unnecessary_get_then_check } diff --git a/tests/ui/unnecessary_get_then_check.stderr b/tests/ui/unnecessary_get_then_check.stderr index 0477c03d16dd..5ecb3d4e29dd 100644 --- a/tests/ui/unnecessary_get_then_check.stderr +++ b/tests/ui/unnecessary_get_then_check.stderr @@ -8,7 +8,7 @@ LL | let _ = s.get("a").is_some(); = help: to override `-D warnings` add `#[allow(clippy::unnecessary_get_then_check)]` error: unnecessary use of `get("a").is_none()` - --> tests/ui/unnecessary_get_then_check.rs:8:15 + --> tests/ui/unnecessary_get_then_check.rs:9:15 | LL | let _ = s.get("a").is_none(); | --^^^^^^^^^^^^^^^^^^ @@ -16,13 +16,13 @@ LL | let _ = s.get("a").is_none(); | help: replace it with: `!s.contains("a")` error: unnecessary use of `get("a").is_some()` - --> tests/ui/unnecessary_get_then_check.rs:11:15 + --> tests/ui/unnecessary_get_then_check.rs:13:15 | LL | let _ = s.get("a").is_some(); | ^^^^^^^^^^^^^^^^^^ help: replace it with: `contains_key("a")` error: unnecessary use of `get("a").is_none()` - --> tests/ui/unnecessary_get_then_check.rs:12:15 + --> tests/ui/unnecessary_get_then_check.rs:15:15 | LL | let _ = s.get("a").is_none(); | --^^^^^^^^^^^^^^^^^^ @@ -30,13 +30,13 @@ LL | let _ = s.get("a").is_none(); | help: replace it with: `!s.contains_key("a")` error: unnecessary use of `get("a").is_some()` - --> tests/ui/unnecessary_get_then_check.rs:15:15 + --> tests/ui/unnecessary_get_then_check.rs:19:15 | LL | let _ = s.get("a").is_some(); | ^^^^^^^^^^^^^^^^^^ help: replace it with: `contains("a")` error: unnecessary use of `get("a").is_none()` - --> tests/ui/unnecessary_get_then_check.rs:16:15 + --> tests/ui/unnecessary_get_then_check.rs:21:15 | LL | let _ = s.get("a").is_none(); | --^^^^^^^^^^^^^^^^^^ @@ -44,13 +44,13 @@ LL | let _ = s.get("a").is_none(); | help: replace it with: `!s.contains("a")` error: unnecessary use of `get("a").is_some()` - --> tests/ui/unnecessary_get_then_check.rs:19:15 + --> tests/ui/unnecessary_get_then_check.rs:25:15 | LL | let _ = s.get("a").is_some(); | ^^^^^^^^^^^^^^^^^^ help: replace it with: `contains_key("a")` error: unnecessary use of `get("a").is_none()` - --> tests/ui/unnecessary_get_then_check.rs:20:15 + --> tests/ui/unnecessary_get_then_check.rs:27:15 | LL | let _ = s.get("a").is_none(); | --^^^^^^^^^^^^^^^^^^ @@ -58,13 +58,13 @@ LL | let _ = s.get("a").is_none(); | help: replace it with: `!s.contains_key("a")` error: unnecessary use of `get::("a").is_some()` - --> tests/ui/unnecessary_get_then_check.rs:24:15 + --> tests/ui/unnecessary_get_then_check.rs:32:15 | LL | let _ = s.get::("a").is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `contains::("a")` error: unnecessary use of `get::("a").is_none()` - --> tests/ui/unnecessary_get_then_check.rs:25:15 + --> tests/ui/unnecessary_get_then_check.rs:34:15 | LL | let _ = s.get::("a").is_none(); | --^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unnecessary_iter_cloned.fixed b/tests/ui/unnecessary_iter_cloned.fixed index dc5e163ff04e..aed2dbe1f1ce 100644 --- a/tests/ui/unnecessary_iter_cloned.fixed +++ b/tests/ui/unnecessary_iter_cloned.fixed @@ -29,6 +29,7 @@ fn main() { // https://github.com/breard-r/acmed/blob/1f0dcc32aadbc5e52de6d23b9703554c0f925113/acmed/src/storage.rs#L262 fn check_files(files: &[(FileType, &std::path::Path)]) -> bool { for (t, path) in files { + //~^ unnecessary_to_owned let other = match get_file_path(t) { Ok(p) => p, Err(_) => { @@ -44,6 +45,7 @@ fn check_files(files: &[(FileType, &std::path::Path)]) -> bool { fn check_files_vec(files: Vec<(FileType, &std::path::Path)>) -> bool { for (t, path) in files.iter() { + //~^ unnecessary_to_owned let other = match get_file_path(t) { Ok(p) => p, Err(_) => { @@ -175,7 +177,8 @@ mod issue_12821 { fn foo() { let v: Vec<_> = "hello".chars().collect(); for c in v.iter() { - //~^ ERROR: unnecessary use of `cloned` + //~^ unnecessary_to_owned + println!("{c}"); // should not suggest to remove `&` } } @@ -183,8 +186,9 @@ mod issue_12821 { fn bar() { let v: Vec<_> = "hello".chars().collect(); for c in v.iter() { - //~^ ERROR: unnecessary use of `cloned` - let ref_c = c; //~ HELP: remove any references to the binding + //~^ unnecessary_to_owned + + let ref_c = c; println!("{ref_c}"); } } @@ -192,8 +196,9 @@ mod issue_12821 { fn baz() { let v: Vec<_> = "hello".chars().enumerate().collect(); for (i, c) in v.iter() { - //~^ ERROR: unnecessary use of `cloned` - let ref_c = c; //~ HELP: remove any references to the binding + //~^ unnecessary_to_owned + + let ref_c = c; let ref_i = i; println!("{i} {ref_c}"); // should not suggest to remove `&` from `i` } diff --git a/tests/ui/unnecessary_iter_cloned.rs b/tests/ui/unnecessary_iter_cloned.rs index 8f797ac717fb..12fdd150e423 100644 --- a/tests/ui/unnecessary_iter_cloned.rs +++ b/tests/ui/unnecessary_iter_cloned.rs @@ -29,6 +29,7 @@ fn main() { // https://github.com/breard-r/acmed/blob/1f0dcc32aadbc5e52de6d23b9703554c0f925113/acmed/src/storage.rs#L262 fn check_files(files: &[(FileType, &std::path::Path)]) -> bool { for (t, path) in files.iter().copied() { + //~^ unnecessary_to_owned let other = match get_file_path(&t) { Ok(p) => p, Err(_) => { @@ -44,6 +45,7 @@ fn check_files(files: &[(FileType, &std::path::Path)]) -> bool { fn check_files_vec(files: Vec<(FileType, &std::path::Path)>) -> bool { for (t, path) in files.iter().copied() { + //~^ unnecessary_to_owned let other = match get_file_path(&t) { Ok(p) => p, Err(_) => { @@ -175,7 +177,8 @@ mod issue_12821 { fn foo() { let v: Vec<_> = "hello".chars().collect(); for c in v.iter().cloned() { - //~^ ERROR: unnecessary use of `cloned` + //~^ unnecessary_to_owned + println!("{c}"); // should not suggest to remove `&` } } @@ -183,8 +186,9 @@ mod issue_12821 { fn bar() { let v: Vec<_> = "hello".chars().collect(); for c in v.iter().cloned() { - //~^ ERROR: unnecessary use of `cloned` - let ref_c = &c; //~ HELP: remove any references to the binding + //~^ unnecessary_to_owned + + let ref_c = &c; println!("{ref_c}"); } } @@ -192,8 +196,9 @@ mod issue_12821 { fn baz() { let v: Vec<_> = "hello".chars().enumerate().collect(); for (i, c) in v.iter().cloned() { - //~^ ERROR: unnecessary use of `cloned` - let ref_c = &c; //~ HELP: remove any references to the binding + //~^ unnecessary_to_owned + + let ref_c = &c; let ref_i = &i; println!("{i} {ref_c}"); // should not suggest to remove `&` from `i` } diff --git a/tests/ui/unnecessary_iter_cloned.stderr b/tests/ui/unnecessary_iter_cloned.stderr index 6f2ae0ab1f35..632c8f371106 100644 --- a/tests/ui/unnecessary_iter_cloned.stderr +++ b/tests/ui/unnecessary_iter_cloned.stderr @@ -9,11 +9,12 @@ LL | for (t, path) in files.iter().copied() { help: remove any references to the binding | LL ~ for (t, path) in files { +LL | LL ~ let other = match get_file_path(t) { | error: unnecessary use of `copied` - --> tests/ui/unnecessary_iter_cloned.rs:46:22 + --> tests/ui/unnecessary_iter_cloned.rs:47:22 | LL | for (t, path) in files.iter().copied() { | ^^^^^^^^^^^^^^^^^^^^^ @@ -21,17 +22,18 @@ LL | for (t, path) in files.iter().copied() { help: remove any references to the binding | LL ~ for (t, path) in files.iter() { +LL | LL ~ let other = match get_file_path(t) { | error: unnecessary use of `cloned` - --> tests/ui/unnecessary_iter_cloned.rs:177:18 + --> tests/ui/unnecessary_iter_cloned.rs:179:18 | LL | for c in v.iter().cloned() { | ^^^^^^^^^^^^^^^^^ help: remove any references to the binding: `v.iter()` error: unnecessary use of `cloned` - --> tests/ui/unnecessary_iter_cloned.rs:185:18 + --> tests/ui/unnecessary_iter_cloned.rs:188:18 | LL | for c in v.iter().cloned() { | ^^^^^^^^^^^^^^^^^ @@ -40,11 +42,12 @@ help: remove any references to the binding | LL ~ for c in v.iter() { LL | +LL | LL ~ let ref_c = c; | error: unnecessary use of `cloned` - --> tests/ui/unnecessary_iter_cloned.rs:194:23 + --> tests/ui/unnecessary_iter_cloned.rs:198:23 | LL | for (i, c) in v.iter().cloned() { | ^^^^^^^^^^^^^^^^^ @@ -53,6 +56,7 @@ help: remove any references to the binding | LL ~ for (i, c) in v.iter() { LL | +LL | LL ~ let ref_c = c; LL ~ let ref_i = i; | diff --git a/tests/ui/unnecessary_join.rs b/tests/ui/unnecessary_join.rs index d042d9e5c212..e58b2696645a 100644 --- a/tests/ui/unnecessary_join.rs +++ b/tests/ui/unnecessary_join.rs @@ -8,6 +8,7 @@ fn main() { .iter() .map(|item| item.to_uppercase()) .collect::>() + //~^ unnecessary_join .join(""); println!("{}", output); @@ -17,6 +18,7 @@ fn main() { .iter() .map(|item| item.to_uppercase()) .collect::>() + //~^ unnecessary_join .join(""); println!("{}", output); diff --git a/tests/ui/unnecessary_join.stderr b/tests/ui/unnecessary_join.stderr index a06a1059033b..a7677fe2f9eb 100644 --- a/tests/ui/unnecessary_join.stderr +++ b/tests/ui/unnecessary_join.stderr @@ -3,6 +3,7 @@ error: called `.collect::>().join("")` on an iterator | LL | .collect::>() | __________^ +LL | | LL | | .join(""); | |_________________^ help: consider using: `collect::()` | @@ -10,10 +11,11 @@ LL | | .join(""); = help: to override `-D warnings` add `#[allow(clippy::unnecessary_join)]` error: called `.collect::>().join("")` on an iterator - --> tests/ui/unnecessary_join.rs:19:10 + --> tests/ui/unnecessary_join.rs:20:10 | LL | .collect::>() | __________^ +LL | | LL | | .join(""); | |_________________^ help: consider using: `collect::()` diff --git a/tests/ui/unnecessary_lazy_eval.fixed b/tests/ui/unnecessary_lazy_eval.fixed index d8031c484e5e..9a3290816389 100644 --- a/tests/ui/unnecessary_lazy_eval.fixed +++ b/tests/ui/unnecessary_lazy_eval.fixed @@ -81,42 +81,69 @@ fn main() { // Should lint - Option let _ = opt.unwrap_or(2); + //~^ unnecessary_lazy_evaluations let _ = opt.unwrap_or(astronomers_pi); + //~^ unnecessary_lazy_evaluations let _ = opt.unwrap_or(ext_str.some_field); + //~^ unnecessary_lazy_evaluations let _ = opt.unwrap_or_else(|| ext_arr[0]); let _ = opt.and(ext_opt); + //~^ unnecessary_lazy_evaluations let _ = opt.or(ext_opt); + //~^ unnecessary_lazy_evaluations let _ = opt.or(None); + //~^ unnecessary_lazy_evaluations let _ = opt.get_or_insert(2); + //~^ unnecessary_lazy_evaluations let _ = opt.ok_or(2); + //~^ unnecessary_lazy_evaluations let _ = nested_tuple_opt.unwrap_or(Some((1, 2))); + //~^ unnecessary_lazy_evaluations let _ = cond.then_some(astronomers_pi); + //~^ unnecessary_lazy_evaluations let _ = true.then_some({}); + //~^ unnecessary_lazy_evaluations let _ = true.then_some({}); + //~^ unnecessary_lazy_evaluations // Should lint - Builtin deref let r = &1; let _ = Some(1).unwrap_or(*r); + //~^ unnecessary_lazy_evaluations let b = Box::new(1); let _ = Some(1).unwrap_or(*b); + //~^ unnecessary_lazy_evaluations // Should lint - Builtin deref through autoderef let _ = Some(1).as_ref().unwrap_or(&r); + //~^ unnecessary_lazy_evaluations let _ = Some(1).as_ref().unwrap_or(&b); + //~^ unnecessary_lazy_evaluations // Cases when unwrap is not called on a simple variable let _ = Some(10).unwrap_or(2); + //~^ unnecessary_lazy_evaluations let _ = Some(10).and(ext_opt); + //~^ unnecessary_lazy_evaluations let _: Option = None.or(ext_opt); + //~^ unnecessary_lazy_evaluations let _ = None.get_or_insert(2); + //~^ unnecessary_lazy_evaluations let _: Result = None.ok_or(2); + //~^ unnecessary_lazy_evaluations let _: Option = None.or(None); + //~^ unnecessary_lazy_evaluations let mut deep = Deep(Some(42)); let _ = deep.0.unwrap_or(2); + //~^ unnecessary_lazy_evaluations let _ = deep.0.and(ext_opt); + //~^ unnecessary_lazy_evaluations let _ = deep.0.or(None); + //~^ unnecessary_lazy_evaluations let _ = deep.0.get_or_insert(2); + //~^ unnecessary_lazy_evaluations let _ = deep.0.ok_or(2); + //~^ unnecessary_lazy_evaluations // Should not lint - Option let _ = opt.unwrap_or_else(|| ext_str.return_some_field()); @@ -148,16 +175,22 @@ fn main() { // should lint, bind_instead_of_map doesn't apply let _: Option = None.or(Some(3)); + //~^ unnecessary_lazy_evaluations let _ = deep.0.or(Some(3)); + //~^ unnecessary_lazy_evaluations let _ = opt.or(Some(3)); + //~^ unnecessary_lazy_evaluations // Should lint - Result let res: Result = Err(5); let res2: Result = Err(SomeStruct { some_field: 5 }); let _ = res2.unwrap_or(2); + //~^ unnecessary_lazy_evaluations let _ = res2.unwrap_or(astronomers_pi); + //~^ unnecessary_lazy_evaluations let _ = res2.unwrap_or(ext_str.some_field); + //~^ unnecessary_lazy_evaluations // Should not lint - Result let _ = res.unwrap_or_else(|err| err); @@ -180,13 +213,20 @@ fn main() { // should lint, bind_instead_of_map doesn't apply let _: Result = res.and(Err(2)); + //~^ unnecessary_lazy_evaluations let _: Result = res.and(Err(astronomers_pi)); + //~^ unnecessary_lazy_evaluations let _: Result = res.and(Err(ext_str.some_field)); + //~^ unnecessary_lazy_evaluations let _: Result = res.or(Ok(2)); + //~^ unnecessary_lazy_evaluations let _: Result = res.or(Ok(astronomers_pi)); + //~^ unnecessary_lazy_evaluations let _: Result = res.or(Ok(ext_str.some_field)); + //~^ unnecessary_lazy_evaluations let _: Result = res. + //~^ unnecessary_lazy_evaluations // some lines // some lines // some lines @@ -217,39 +257,39 @@ fn panicky_arithmetic_ops(x: usize, y: isize) { // See comments in `eager_or_lazy.rs` for the rules that this is meant to follow let _x = false.then_some(i32::MAX + 1); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then_some(i32::MAX * 2); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then_some(i32::MAX - 1); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then_some(i32::MIN - 1); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then_some((1 + 2 * 3 - 2 / 3 + 9) << 2); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then_some(255u8 << 7); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then_some(255u8 << 8); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then_some(255u8 >> 8); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| 255u8 >> x); let _x = false.then_some(i32::MAX + -1); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then_some(-i32::MAX); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then_some(-i32::MIN); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| -y); let _x = false.then_some(255 >> -7); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then_some(255 << -1); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then_some(1 / 0); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then_some(x << -1); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then_some(x << 2); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| x + x); let _x = false.then(|| x * x); let _x = false.then(|| x - x); @@ -259,19 +299,19 @@ fn panicky_arithmetic_ops(x: usize, y: isize) { let _x = false.then(|| 1 + x); let _x = false.then_some(x / 0); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then_some(x % 0); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| y / -1); let _x = false.then_some(1 / -1); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then_some(i32::MIN / -1); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| i32::MIN / x as i32); let _x = false.then_some(i32::MIN / 0); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then_some(4 / 2); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| 1 / x); // const eval doesn't read variables, but floating point math never panics, so we can still emit a @@ -279,5 +319,5 @@ fn panicky_arithmetic_ops(x: usize, y: isize) { let f1 = 1.0; let f2 = 2.0; let _x = false.then_some(f1 + f2); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations } diff --git a/tests/ui/unnecessary_lazy_eval.rs b/tests/ui/unnecessary_lazy_eval.rs index ea55b1d9a905..2d05ef5c2917 100644 --- a/tests/ui/unnecessary_lazy_eval.rs +++ b/tests/ui/unnecessary_lazy_eval.rs @@ -81,42 +81,69 @@ fn main() { // Should lint - Option let _ = opt.unwrap_or_else(|| 2); + //~^ unnecessary_lazy_evaluations let _ = opt.unwrap_or_else(|| astronomers_pi); + //~^ unnecessary_lazy_evaluations let _ = opt.unwrap_or_else(|| ext_str.some_field); + //~^ unnecessary_lazy_evaluations let _ = opt.unwrap_or_else(|| ext_arr[0]); let _ = opt.and_then(|_| ext_opt); + //~^ unnecessary_lazy_evaluations let _ = opt.or_else(|| ext_opt); + //~^ unnecessary_lazy_evaluations let _ = opt.or_else(|| None); + //~^ unnecessary_lazy_evaluations let _ = opt.get_or_insert_with(|| 2); + //~^ unnecessary_lazy_evaluations let _ = opt.ok_or_else(|| 2); + //~^ unnecessary_lazy_evaluations let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2))); + //~^ unnecessary_lazy_evaluations let _ = cond.then(|| astronomers_pi); + //~^ unnecessary_lazy_evaluations let _ = true.then(|| -> _ {}); + //~^ unnecessary_lazy_evaluations let _ = true.then(|| {}); + //~^ unnecessary_lazy_evaluations // Should lint - Builtin deref let r = &1; let _ = Some(1).unwrap_or_else(|| *r); + //~^ unnecessary_lazy_evaluations let b = Box::new(1); let _ = Some(1).unwrap_or_else(|| *b); + //~^ unnecessary_lazy_evaluations // Should lint - Builtin deref through autoderef let _ = Some(1).as_ref().unwrap_or_else(|| &r); + //~^ unnecessary_lazy_evaluations let _ = Some(1).as_ref().unwrap_or_else(|| &b); + //~^ unnecessary_lazy_evaluations // Cases when unwrap is not called on a simple variable let _ = Some(10).unwrap_or_else(|| 2); + //~^ unnecessary_lazy_evaluations let _ = Some(10).and_then(|_| ext_opt); + //~^ unnecessary_lazy_evaluations let _: Option = None.or_else(|| ext_opt); + //~^ unnecessary_lazy_evaluations let _ = None.get_or_insert_with(|| 2); + //~^ unnecessary_lazy_evaluations let _: Result = None.ok_or_else(|| 2); + //~^ unnecessary_lazy_evaluations let _: Option = None.or_else(|| None); + //~^ unnecessary_lazy_evaluations let mut deep = Deep(Some(42)); let _ = deep.0.unwrap_or_else(|| 2); + //~^ unnecessary_lazy_evaluations let _ = deep.0.and_then(|_| ext_opt); + //~^ unnecessary_lazy_evaluations let _ = deep.0.or_else(|| None); + //~^ unnecessary_lazy_evaluations let _ = deep.0.get_or_insert_with(|| 2); + //~^ unnecessary_lazy_evaluations let _ = deep.0.ok_or_else(|| 2); + //~^ unnecessary_lazy_evaluations // Should not lint - Option let _ = opt.unwrap_or_else(|| ext_str.return_some_field()); @@ -148,16 +175,22 @@ fn main() { // should lint, bind_instead_of_map doesn't apply let _: Option = None.or_else(|| Some(3)); + //~^ unnecessary_lazy_evaluations let _ = deep.0.or_else(|| Some(3)); + //~^ unnecessary_lazy_evaluations let _ = opt.or_else(|| Some(3)); + //~^ unnecessary_lazy_evaluations // Should lint - Result let res: Result = Err(5); let res2: Result = Err(SomeStruct { some_field: 5 }); let _ = res2.unwrap_or_else(|_| 2); + //~^ unnecessary_lazy_evaluations let _ = res2.unwrap_or_else(|_| astronomers_pi); + //~^ unnecessary_lazy_evaluations let _ = res2.unwrap_or_else(|_| ext_str.some_field); + //~^ unnecessary_lazy_evaluations // Should not lint - Result let _ = res.unwrap_or_else(|err| err); @@ -180,13 +213,20 @@ fn main() { // should lint, bind_instead_of_map doesn't apply let _: Result = res.and_then(|_| Err(2)); + //~^ unnecessary_lazy_evaluations let _: Result = res.and_then(|_| Err(astronomers_pi)); + //~^ unnecessary_lazy_evaluations let _: Result = res.and_then(|_| Err(ext_str.some_field)); + //~^ unnecessary_lazy_evaluations let _: Result = res.or_else(|_| Ok(2)); + //~^ unnecessary_lazy_evaluations let _: Result = res.or_else(|_| Ok(astronomers_pi)); + //~^ unnecessary_lazy_evaluations let _: Result = res.or_else(|_| Ok(ext_str.some_field)); + //~^ unnecessary_lazy_evaluations let _: Result = res. + //~^ unnecessary_lazy_evaluations // some lines // some lines // some lines @@ -217,39 +257,39 @@ fn panicky_arithmetic_ops(x: usize, y: isize) { // See comments in `eager_or_lazy.rs` for the rules that this is meant to follow let _x = false.then(|| i32::MAX + 1); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| i32::MAX * 2); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| i32::MAX - 1); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| i32::MIN - 1); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| (1 + 2 * 3 - 2 / 3 + 9) << 2); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| 255u8 << 7); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| 255u8 << 8); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| 255u8 >> 8); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| 255u8 >> x); let _x = false.then(|| i32::MAX + -1); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| -i32::MAX); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| -i32::MIN); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| -y); let _x = false.then(|| 255 >> -7); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| 255 << -1); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| 1 / 0); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| x << -1); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| x << 2); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| x + x); let _x = false.then(|| x * x); let _x = false.then(|| x - x); @@ -259,19 +299,19 @@ fn panicky_arithmetic_ops(x: usize, y: isize) { let _x = false.then(|| 1 + x); let _x = false.then(|| x / 0); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| x % 0); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| y / -1); let _x = false.then(|| 1 / -1); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| i32::MIN / -1); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| i32::MIN / x as i32); let _x = false.then(|| i32::MIN / 0); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| 4 / 2); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations let _x = false.then(|| 1 / x); // const eval doesn't read variables, but floating point math never panics, so we can still emit a @@ -279,5 +319,5 @@ fn panicky_arithmetic_ops(x: usize, y: isize) { let f1 = 1.0; let f2 = 2.0; let _x = false.then(|| f1 + f2); - //~^ ERROR: unnecessary closure used with `bool::then` + //~^ unnecessary_lazy_evaluations } diff --git a/tests/ui/unnecessary_lazy_eval.stderr b/tests/ui/unnecessary_lazy_eval.stderr index 9bb1b71f0ed5..75a06a419c71 100644 --- a/tests/ui/unnecessary_lazy_eval.stderr +++ b/tests/ui/unnecessary_lazy_eval.stderr @@ -13,7 +13,7 @@ LL + let _ = opt.unwrap_or(2); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:84:13 + --> tests/ui/unnecessary_lazy_eval.rs:85:13 | LL | let _ = opt.unwrap_or_else(|| astronomers_pi); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + let _ = opt.unwrap_or(astronomers_pi); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:85:13 + --> tests/ui/unnecessary_lazy_eval.rs:87:13 | LL | let _ = opt.unwrap_or_else(|| ext_str.some_field); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + let _ = opt.unwrap_or(ext_str.some_field); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:87:13 + --> tests/ui/unnecessary_lazy_eval.rs:90:13 | LL | let _ = opt.and_then(|_| ext_opt); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + let _ = opt.and(ext_opt); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:88:13 + --> tests/ui/unnecessary_lazy_eval.rs:92:13 | LL | let _ = opt.or_else(|| ext_opt); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + let _ = opt.or(ext_opt); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:89:13 + --> tests/ui/unnecessary_lazy_eval.rs:94:13 | LL | let _ = opt.or_else(|| None); | ^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + let _ = opt.or(None); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:90:13 + --> tests/ui/unnecessary_lazy_eval.rs:96:13 | LL | let _ = opt.get_or_insert_with(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + let _ = opt.get_or_insert(2); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:91:13 + --> tests/ui/unnecessary_lazy_eval.rs:98:13 | LL | let _ = opt.ok_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL + let _ = opt.ok_or(2); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:92:13 + --> tests/ui/unnecessary_lazy_eval.rs:100:13 | LL | let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL + let _ = nested_tuple_opt.unwrap_or(Some((1, 2))); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:93:13 + --> tests/ui/unnecessary_lazy_eval.rs:102:13 | LL | let _ = cond.then(|| astronomers_pi); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL + let _ = cond.then_some(astronomers_pi); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:94:13 + --> tests/ui/unnecessary_lazy_eval.rs:104:13 | LL | let _ = true.then(|| -> _ {}); | ^^^^^^^^^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL + let _ = true.then_some({}); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:95:13 + --> tests/ui/unnecessary_lazy_eval.rs:106:13 | LL | let _ = true.then(|| {}); | ^^^^^^^^^^^^^^^^ @@ -145,7 +145,7 @@ LL + let _ = true.then_some({}); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:99:13 + --> tests/ui/unnecessary_lazy_eval.rs:111:13 | LL | let _ = Some(1).unwrap_or_else(|| *r); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL + let _ = Some(1).unwrap_or(*r); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:101:13 + --> tests/ui/unnecessary_lazy_eval.rs:114:13 | LL | let _ = Some(1).unwrap_or_else(|| *b); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -169,7 +169,7 @@ LL + let _ = Some(1).unwrap_or(*b); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:103:13 + --> tests/ui/unnecessary_lazy_eval.rs:117:13 | LL | let _ = Some(1).as_ref().unwrap_or_else(|| &r); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -181,7 +181,7 @@ LL + let _ = Some(1).as_ref().unwrap_or(&r); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:104:13 + --> tests/ui/unnecessary_lazy_eval.rs:119:13 | LL | let _ = Some(1).as_ref().unwrap_or_else(|| &b); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -193,7 +193,7 @@ LL + let _ = Some(1).as_ref().unwrap_or(&b); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:107:13 + --> tests/ui/unnecessary_lazy_eval.rs:123:13 | LL | let _ = Some(10).unwrap_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -205,7 +205,7 @@ LL + let _ = Some(10).unwrap_or(2); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:108:13 + --> tests/ui/unnecessary_lazy_eval.rs:125:13 | LL | let _ = Some(10).and_then(|_| ext_opt); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +217,7 @@ LL + let _ = Some(10).and(ext_opt); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:109:28 + --> tests/ui/unnecessary_lazy_eval.rs:127:28 | LL | let _: Option = None.or_else(|| ext_opt); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -229,7 +229,7 @@ LL + let _: Option = None.or(ext_opt); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:110:13 + --> tests/ui/unnecessary_lazy_eval.rs:129:13 | LL | let _ = None.get_or_insert_with(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,7 +241,7 @@ LL + let _ = None.get_or_insert(2); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:111:35 + --> tests/ui/unnecessary_lazy_eval.rs:131:35 | LL | let _: Result = None.ok_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^^ @@ -253,7 +253,7 @@ LL + let _: Result = None.ok_or(2); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:112:28 + --> tests/ui/unnecessary_lazy_eval.rs:133:28 | LL | let _: Option = None.or_else(|| None); | ^^^^^^^^^^^^^^^^^^^^^ @@ -265,7 +265,7 @@ LL + let _: Option = None.or(None); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:115:13 + --> tests/ui/unnecessary_lazy_eval.rs:137:13 | LL | let _ = deep.0.unwrap_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -277,7 +277,7 @@ LL + let _ = deep.0.unwrap_or(2); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:116:13 + --> tests/ui/unnecessary_lazy_eval.rs:139:13 | LL | let _ = deep.0.and_then(|_| ext_opt); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -289,7 +289,7 @@ LL + let _ = deep.0.and(ext_opt); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:117:13 + --> tests/ui/unnecessary_lazy_eval.rs:141:13 | LL | let _ = deep.0.or_else(|| None); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -301,7 +301,7 @@ LL + let _ = deep.0.or(None); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:118:13 + --> tests/ui/unnecessary_lazy_eval.rs:143:13 | LL | let _ = deep.0.get_or_insert_with(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -313,7 +313,7 @@ LL + let _ = deep.0.get_or_insert(2); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:119:13 + --> tests/ui/unnecessary_lazy_eval.rs:145:13 | LL | let _ = deep.0.ok_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -325,7 +325,7 @@ LL + let _ = deep.0.ok_or(2); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:150:28 + --> tests/ui/unnecessary_lazy_eval.rs:177:28 | LL | let _: Option = None.or_else(|| Some(3)); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -337,7 +337,7 @@ LL + let _: Option = None.or(Some(3)); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:151:13 + --> tests/ui/unnecessary_lazy_eval.rs:179:13 | LL | let _ = deep.0.or_else(|| Some(3)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -349,7 +349,7 @@ LL + let _ = deep.0.or(Some(3)); | error: unnecessary closure used to substitute value for `Option::None` - --> tests/ui/unnecessary_lazy_eval.rs:152:13 + --> tests/ui/unnecessary_lazy_eval.rs:181:13 | LL | let _ = opt.or_else(|| Some(3)); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -361,7 +361,7 @@ LL + let _ = opt.or(Some(3)); | error: unnecessary closure used to substitute value for `Result::Err` - --> tests/ui/unnecessary_lazy_eval.rs:158:13 + --> tests/ui/unnecessary_lazy_eval.rs:188:13 | LL | let _ = res2.unwrap_or_else(|_| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -373,7 +373,7 @@ LL + let _ = res2.unwrap_or(2); | error: unnecessary closure used to substitute value for `Result::Err` - --> tests/ui/unnecessary_lazy_eval.rs:159:13 + --> tests/ui/unnecessary_lazy_eval.rs:190:13 | LL | let _ = res2.unwrap_or_else(|_| astronomers_pi); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -385,7 +385,7 @@ LL + let _ = res2.unwrap_or(astronomers_pi); | error: unnecessary closure used to substitute value for `Result::Err` - --> tests/ui/unnecessary_lazy_eval.rs:160:13 + --> tests/ui/unnecessary_lazy_eval.rs:192:13 | LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -397,7 +397,7 @@ LL + let _ = res2.unwrap_or(ext_str.some_field); | error: unnecessary closure used to substitute value for `Result::Err` - --> tests/ui/unnecessary_lazy_eval.rs:182:35 + --> tests/ui/unnecessary_lazy_eval.rs:215:35 | LL | let _: Result = res.and_then(|_| Err(2)); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -409,7 +409,7 @@ LL + let _: Result = res.and(Err(2)); | error: unnecessary closure used to substitute value for `Result::Err` - --> tests/ui/unnecessary_lazy_eval.rs:183:35 + --> tests/ui/unnecessary_lazy_eval.rs:217:35 | LL | let _: Result = res.and_then(|_| Err(astronomers_pi)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -421,7 +421,7 @@ LL + let _: Result = res.and(Err(astronomers_pi)); | error: unnecessary closure used to substitute value for `Result::Err` - --> tests/ui/unnecessary_lazy_eval.rs:184:35 + --> tests/ui/unnecessary_lazy_eval.rs:219:35 | LL | let _: Result = res.and_then(|_| Err(ext_str.some_field)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -433,7 +433,7 @@ LL + let _: Result = res.and(Err(ext_str.some_field)); | error: unnecessary closure used to substitute value for `Result::Err` - --> tests/ui/unnecessary_lazy_eval.rs:186:35 + --> tests/ui/unnecessary_lazy_eval.rs:222:35 | LL | let _: Result = res.or_else(|_| Ok(2)); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -445,7 +445,7 @@ LL + let _: Result = res.or(Ok(2)); | error: unnecessary closure used to substitute value for `Result::Err` - --> tests/ui/unnecessary_lazy_eval.rs:187:35 + --> tests/ui/unnecessary_lazy_eval.rs:224:35 | LL | let _: Result = res.or_else(|_| Ok(astronomers_pi)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -457,7 +457,7 @@ LL + let _: Result = res.or(Ok(astronomers_pi)); | error: unnecessary closure used to substitute value for `Result::Err` - --> tests/ui/unnecessary_lazy_eval.rs:188:35 + --> tests/ui/unnecessary_lazy_eval.rs:226:35 | LL | let _: Result = res.or_else(|_| Ok(ext_str.some_field)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -469,7 +469,7 @@ LL + let _: Result = res.or(Ok(ext_str.some_field)); | error: unnecessary closure used to substitute value for `Result::Err` - --> tests/ui/unnecessary_lazy_eval.rs:189:35 + --> tests/ui/unnecessary_lazy_eval.rs:228:35 | LL | let _: Result = res. | ___________________________________^ @@ -484,7 +484,7 @@ LL + or(Ok(ext_str.some_field)); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:219:14 + --> tests/ui/unnecessary_lazy_eval.rs:259:14 | LL | let _x = false.then(|| i32::MAX + 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -496,7 +496,7 @@ LL + let _x = false.then_some(i32::MAX + 1); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:221:14 + --> tests/ui/unnecessary_lazy_eval.rs:261:14 | LL | let _x = false.then(|| i32::MAX * 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -508,7 +508,7 @@ LL + let _x = false.then_some(i32::MAX * 2); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:223:14 + --> tests/ui/unnecessary_lazy_eval.rs:263:14 | LL | let _x = false.then(|| i32::MAX - 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -520,7 +520,7 @@ LL + let _x = false.then_some(i32::MAX - 1); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:225:14 + --> tests/ui/unnecessary_lazy_eval.rs:265:14 | LL | let _x = false.then(|| i32::MIN - 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -532,7 +532,7 @@ LL + let _x = false.then_some(i32::MIN - 1); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:227:14 + --> tests/ui/unnecessary_lazy_eval.rs:267:14 | LL | let _x = false.then(|| (1 + 2 * 3 - 2 / 3 + 9) << 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -544,7 +544,7 @@ LL + let _x = false.then_some((1 + 2 * 3 - 2 / 3 + 9) << 2); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:229:14 + --> tests/ui/unnecessary_lazy_eval.rs:269:14 | LL | let _x = false.then(|| 255u8 << 7); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -556,7 +556,7 @@ LL + let _x = false.then_some(255u8 << 7); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:231:14 + --> tests/ui/unnecessary_lazy_eval.rs:271:14 | LL | let _x = false.then(|| 255u8 << 8); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -568,7 +568,7 @@ LL + let _x = false.then_some(255u8 << 8); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:233:14 + --> tests/ui/unnecessary_lazy_eval.rs:273:14 | LL | let _x = false.then(|| 255u8 >> 8); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -580,7 +580,7 @@ LL + let _x = false.then_some(255u8 >> 8); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:236:14 + --> tests/ui/unnecessary_lazy_eval.rs:276:14 | LL | let _x = false.then(|| i32::MAX + -1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -592,7 +592,7 @@ LL + let _x = false.then_some(i32::MAX + -1); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:238:14 + --> tests/ui/unnecessary_lazy_eval.rs:278:14 | LL | let _x = false.then(|| -i32::MAX); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -604,7 +604,7 @@ LL + let _x = false.then_some(-i32::MAX); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:240:14 + --> tests/ui/unnecessary_lazy_eval.rs:280:14 | LL | let _x = false.then(|| -i32::MIN); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -616,7 +616,7 @@ LL + let _x = false.then_some(-i32::MIN); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:243:14 + --> tests/ui/unnecessary_lazy_eval.rs:283:14 | LL | let _x = false.then(|| 255 >> -7); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -628,7 +628,7 @@ LL + let _x = false.then_some(255 >> -7); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:245:14 + --> tests/ui/unnecessary_lazy_eval.rs:285:14 | LL | let _x = false.then(|| 255 << -1); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -640,7 +640,7 @@ LL + let _x = false.then_some(255 << -1); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:247:14 + --> tests/ui/unnecessary_lazy_eval.rs:287:14 | LL | let _x = false.then(|| 1 / 0); | ^^^^^^^^^^^^^^^^^^^^ @@ -652,7 +652,7 @@ LL + let _x = false.then_some(1 / 0); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:249:14 + --> tests/ui/unnecessary_lazy_eval.rs:289:14 | LL | let _x = false.then(|| x << -1); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -664,7 +664,7 @@ LL + let _x = false.then_some(x << -1); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:251:14 + --> tests/ui/unnecessary_lazy_eval.rs:291:14 | LL | let _x = false.then(|| x << 2); | ^^^^^^^^^^^^^^^^^^^^^ @@ -676,7 +676,7 @@ LL + let _x = false.then_some(x << 2); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:261:14 + --> tests/ui/unnecessary_lazy_eval.rs:301:14 | LL | let _x = false.then(|| x / 0); | ^^^^^^^^^^^^^^^^^^^^ @@ -688,7 +688,7 @@ LL + let _x = false.then_some(x / 0); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:263:14 + --> tests/ui/unnecessary_lazy_eval.rs:303:14 | LL | let _x = false.then(|| x % 0); | ^^^^^^^^^^^^^^^^^^^^ @@ -700,7 +700,7 @@ LL + let _x = false.then_some(x % 0); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:266:14 + --> tests/ui/unnecessary_lazy_eval.rs:306:14 | LL | let _x = false.then(|| 1 / -1); | ^^^^^^^^^^^^^^^^^^^^^ @@ -712,7 +712,7 @@ LL + let _x = false.then_some(1 / -1); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:268:14 + --> tests/ui/unnecessary_lazy_eval.rs:308:14 | LL | let _x = false.then(|| i32::MIN / -1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -724,7 +724,7 @@ LL + let _x = false.then_some(i32::MIN / -1); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:271:14 + --> tests/ui/unnecessary_lazy_eval.rs:311:14 | LL | let _x = false.then(|| i32::MIN / 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -736,7 +736,7 @@ LL + let _x = false.then_some(i32::MIN / 0); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:273:14 + --> tests/ui/unnecessary_lazy_eval.rs:313:14 | LL | let _x = false.then(|| 4 / 2); | ^^^^^^^^^^^^^^^^^^^^ @@ -748,7 +748,7 @@ LL + let _x = false.then_some(4 / 2); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval.rs:281:14 + --> tests/ui/unnecessary_lazy_eval.rs:321:14 | LL | let _x = false.then(|| f1 + f2); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unnecessary_lazy_eval_unfixable.rs b/tests/ui/unnecessary_lazy_eval_unfixable.rs index 412d4aaafb4a..6d28d544dfe0 100644 --- a/tests/ui/unnecessary_lazy_eval_unfixable.rs +++ b/tests/ui/unnecessary_lazy_eval_unfixable.rs @@ -11,15 +11,16 @@ struct SomeStruct { fn main() { // fix will break type inference let _ = Ok(1).unwrap_or_else(|()| 2); - //~^ ERROR: unnecessary closure used to substitute value for `Result::Err` - //~| NOTE: `-D clippy::unnecessary-lazy-evaluations` implied by `-D warnings` + //~^ unnecessary_lazy_evaluations + mod e { pub struct E; } let _ = Ok(1).unwrap_or_else(|e::E| 2); - //~^ ERROR: unnecessary closure used to substitute value for `Result::Err` + //~^ unnecessary_lazy_evaluations + let _ = Ok(1).unwrap_or_else(|SomeStruct { .. }| 2); - //~^ ERROR: unnecessary closure used to substitute value for `Result::Err` + //~^ unnecessary_lazy_evaluations // Fix #6343 let arr = [(Some(1),)]; @@ -29,4 +30,5 @@ fn main() { fn issue11672() { // Return type annotation helps type inference and removing it can break code let _ = true.then(|| -> &[u8] { &[] }); + //~^ unnecessary_lazy_evaluations } diff --git a/tests/ui/unnecessary_lazy_eval_unfixable.stderr b/tests/ui/unnecessary_lazy_eval_unfixable.stderr index 9688c44c9145..5174acc1e9f9 100644 --- a/tests/ui/unnecessary_lazy_eval_unfixable.stderr +++ b/tests/ui/unnecessary_lazy_eval_unfixable.stderr @@ -25,7 +25,7 @@ LL + let _ = Ok(1).unwrap_or(2); | error: unnecessary closure used to substitute value for `Result::Err` - --> tests/ui/unnecessary_lazy_eval_unfixable.rs:21:13 + --> tests/ui/unnecessary_lazy_eval_unfixable.rs:22:13 | LL | let _ = Ok(1).unwrap_or_else(|SomeStruct { .. }| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + let _ = Ok(1).unwrap_or(2); | error: unnecessary closure used with `bool::then` - --> tests/ui/unnecessary_lazy_eval_unfixable.rs:31:13 + --> tests/ui/unnecessary_lazy_eval_unfixable.rs:32:13 | LL | let _ = true.then(|| -> &[u8] { &[] }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unnecessary_literal_bound.fixed b/tests/ui/unnecessary_literal_bound.fixed index 107e397466d0..ec0d2db154ce 100644 --- a/tests/ui/unnecessary_literal_bound.fixed +++ b/tests/ui/unnecessary_literal_bound.fixed @@ -7,6 +7,7 @@ struct Struct<'a> { impl Struct<'_> { // Should warn fn returns_lit(&self) -> &'static str { + //~^ unnecessary_literal_bound "Hello" } @@ -27,6 +28,7 @@ impl Struct<'_> { // Should warn fn contionally_returns_literals_explicit(&self, cond: bool) -> &'static str { + //~^ unnecessary_literal_bound if cond { return "Literal"; } @@ -51,6 +53,7 @@ trait ReturnsStr { impl ReturnsStr for u8 { // Should warn, even though not useful without trait refinement fn trait_method(&self) -> &'static str { + //~^ unnecessary_literal_bound "Literal" } } diff --git a/tests/ui/unnecessary_literal_bound.rs b/tests/ui/unnecessary_literal_bound.rs index b371ff9d3a2e..713dee4d30a6 100644 --- a/tests/ui/unnecessary_literal_bound.rs +++ b/tests/ui/unnecessary_literal_bound.rs @@ -7,6 +7,7 @@ struct Struct<'a> { impl Struct<'_> { // Should warn fn returns_lit(&self) -> &str { + //~^ unnecessary_literal_bound "Hello" } @@ -27,6 +28,7 @@ impl Struct<'_> { // Should warn fn contionally_returns_literals_explicit(&self, cond: bool) -> &str { + //~^ unnecessary_literal_bound if cond { return "Literal"; } @@ -51,6 +53,7 @@ trait ReturnsStr { impl ReturnsStr for u8 { // Should warn, even though not useful without trait refinement fn trait_method(&self) -> &str { + //~^ unnecessary_literal_bound "Literal" } } diff --git a/tests/ui/unnecessary_literal_bound.stderr b/tests/ui/unnecessary_literal_bound.stderr index 512b2f9a0afa..e510d86622d6 100644 --- a/tests/ui/unnecessary_literal_bound.stderr +++ b/tests/ui/unnecessary_literal_bound.stderr @@ -8,13 +8,13 @@ LL | fn returns_lit(&self) -> &str { = help: to override `-D warnings` add `#[allow(clippy::unnecessary_literal_bound)]` error: returning a `str` unnecessarily tied to the lifetime of arguments - --> tests/ui/unnecessary_literal_bound.rs:29:68 + --> tests/ui/unnecessary_literal_bound.rs:30:68 | LL | fn contionally_returns_literals_explicit(&self, cond: bool) -> &str { | ^^^^ help: try: `&'static str` error: returning a `str` unnecessarily tied to the lifetime of arguments - --> tests/ui/unnecessary_literal_bound.rs:53:31 + --> tests/ui/unnecessary_literal_bound.rs:55:31 | LL | fn trait_method(&self) -> &str { | ^^^^ help: try: `&'static str` diff --git a/tests/ui/unnecessary_literal_unwrap.fixed b/tests/ui/unnecessary_literal_unwrap.fixed index b17343aa9ba5..877f4ad41c7e 100644 --- a/tests/ui/unnecessary_literal_unwrap.fixed +++ b/tests/ui/unnecessary_literal_unwrap.fixed @@ -9,73 +9,119 @@ fn unwrap_option_some() { let _val = 1; + //~^ unnecessary_literal_unwrap let _val = 1; + //~^ unnecessary_literal_unwrap 1; + //~^ unnecessary_literal_unwrap 1; + //~^ unnecessary_literal_unwrap } #[rustfmt::skip] // force rustfmt not to remove braces in `|| { 234 }` fn unwrap_option_none() { let _val = panic!(); + //~^ unnecessary_literal_unwrap let _val = panic!("this always happens"); + //~^ unnecessary_literal_unwrap let _val: String = String::default(); + //~^ unnecessary_literal_unwrap let _val: u16 = 234; + //~^ unnecessary_literal_unwrap let _val: u16 = 234; + //~^ unnecessary_literal_unwrap let _val: u16 = { 234 }; + //~^ unnecessary_literal_unwrap let _val: u16 = { 234 }; + //~^ unnecessary_literal_unwrap panic!(); + //~^ unnecessary_literal_unwrap panic!("this always happens"); + //~^ unnecessary_literal_unwrap String::default(); + //~^ unnecessary_literal_unwrap 234; + //~^ unnecessary_literal_unwrap 234; + //~^ unnecessary_literal_unwrap { 234 }; + //~^ unnecessary_literal_unwrap { 234 }; + //~^ unnecessary_literal_unwrap } fn unwrap_result_ok() { let _val = 1; + //~^ unnecessary_literal_unwrap let _val = 1; + //~^ unnecessary_literal_unwrap let _val = panic!("{:?}", 1); + //~^ unnecessary_literal_unwrap let _val = panic!("{1}: {:?}", 1, "this always happens"); + //~^ unnecessary_literal_unwrap 1; + //~^ unnecessary_literal_unwrap 1; + //~^ unnecessary_literal_unwrap panic!("{:?}", 1); + //~^ unnecessary_literal_unwrap panic!("{1}: {:?}", 1, "this always happens"); + //~^ unnecessary_literal_unwrap } fn unwrap_result_err() { let _val = 1; + //~^ unnecessary_literal_unwrap let _val = 1; + //~^ unnecessary_literal_unwrap let _val = panic!("{:?}", 1); + //~^ unnecessary_literal_unwrap let _val = panic!("{1}: {:?}", 1, "this always happens"); + //~^ unnecessary_literal_unwrap 1; + //~^ unnecessary_literal_unwrap 1; + //~^ unnecessary_literal_unwrap panic!("{:?}", 1); + //~^ unnecessary_literal_unwrap panic!("{1}: {:?}", 1, "this always happens"); + //~^ unnecessary_literal_unwrap } fn unwrap_methods_option() { let _val = 1; + //~^ unnecessary_literal_unwrap let _val = 1; + //~^ unnecessary_literal_unwrap let _val = 1; + //~^ unnecessary_literal_unwrap 1; + //~^ unnecessary_literal_unwrap 1; + //~^ unnecessary_literal_unwrap 1; + //~^ unnecessary_literal_unwrap } fn unwrap_methods_result() { let _val = 1; + //~^ unnecessary_literal_unwrap let _val = 1; + //~^ unnecessary_literal_unwrap let _val = 1; + //~^ unnecessary_literal_unwrap 1; + //~^ unnecessary_literal_unwrap 1; + //~^ unnecessary_literal_unwrap 1; + //~^ unnecessary_literal_unwrap } fn unwrap_from_binding() { @@ -90,12 +136,20 @@ fn unwrap_from_binding() { fn unwrap_unchecked() { let _ = 1; + //~^ unnecessary_literal_unwrap let _ = unsafe { 1 + *(&1 as *const i32) }; // needs to keep the unsafe block + // + //~^^ unnecessary_literal_unwrap let _ = 1 + 1; + //~^ unnecessary_literal_unwrap let _ = 1; + //~^ unnecessary_literal_unwrap let _ = unsafe { 1 + *(&1 as *const i32) }; + //~^ unnecessary_literal_unwrap let _ = 1 + 1; + //~^ unnecessary_literal_unwrap let _ = 123; + //~^ unnecessary_literal_unwrap } fn main() { diff --git a/tests/ui/unnecessary_literal_unwrap.rs b/tests/ui/unnecessary_literal_unwrap.rs index 7bd8deea4d1b..c0a35ae78a71 100644 --- a/tests/ui/unnecessary_literal_unwrap.rs +++ b/tests/ui/unnecessary_literal_unwrap.rs @@ -9,73 +9,119 @@ fn unwrap_option_some() { let _val = Some(1).unwrap(); + //~^ unnecessary_literal_unwrap let _val = Some(1).expect("this never happens"); + //~^ unnecessary_literal_unwrap Some(1).unwrap(); + //~^ unnecessary_literal_unwrap Some(1).expect("this never happens"); + //~^ unnecessary_literal_unwrap } #[rustfmt::skip] // force rustfmt not to remove braces in `|| { 234 }` fn unwrap_option_none() { let _val = None::<()>.unwrap(); + //~^ unnecessary_literal_unwrap let _val = None::<()>.expect("this always happens"); + //~^ unnecessary_literal_unwrap let _val: String = None.unwrap_or_default(); + //~^ unnecessary_literal_unwrap let _val: u16 = None.unwrap_or(234); + //~^ unnecessary_literal_unwrap let _val: u16 = None.unwrap_or_else(|| 234); + //~^ unnecessary_literal_unwrap let _val: u16 = None.unwrap_or_else(|| { 234 }); + //~^ unnecessary_literal_unwrap let _val: u16 = None.unwrap_or_else(|| -> u16 { 234 }); + //~^ unnecessary_literal_unwrap None::<()>.unwrap(); + //~^ unnecessary_literal_unwrap None::<()>.expect("this always happens"); + //~^ unnecessary_literal_unwrap None::.unwrap_or_default(); + //~^ unnecessary_literal_unwrap None::.unwrap_or(234); + //~^ unnecessary_literal_unwrap None::.unwrap_or_else(|| 234); + //~^ unnecessary_literal_unwrap None::.unwrap_or_else(|| { 234 }); + //~^ unnecessary_literal_unwrap None::.unwrap_or_else(|| -> u16 { 234 }); + //~^ unnecessary_literal_unwrap } fn unwrap_result_ok() { let _val = Ok::<_, ()>(1).unwrap(); + //~^ unnecessary_literal_unwrap let _val = Ok::<_, ()>(1).expect("this never happens"); + //~^ unnecessary_literal_unwrap let _val = Ok::<_, ()>(1).unwrap_err(); + //~^ unnecessary_literal_unwrap let _val = Ok::<_, ()>(1).expect_err("this always happens"); + //~^ unnecessary_literal_unwrap Ok::<_, ()>(1).unwrap(); + //~^ unnecessary_literal_unwrap Ok::<_, ()>(1).expect("this never happens"); + //~^ unnecessary_literal_unwrap Ok::<_, ()>(1).unwrap_err(); + //~^ unnecessary_literal_unwrap Ok::<_, ()>(1).expect_err("this always happens"); + //~^ unnecessary_literal_unwrap } fn unwrap_result_err() { let _val = Err::<(), _>(1).unwrap_err(); + //~^ unnecessary_literal_unwrap let _val = Err::<(), _>(1).expect_err("this never happens"); + //~^ unnecessary_literal_unwrap let _val = Err::<(), _>(1).unwrap(); + //~^ unnecessary_literal_unwrap let _val = Err::<(), _>(1).expect("this always happens"); + //~^ unnecessary_literal_unwrap Err::<(), _>(1).unwrap_err(); + //~^ unnecessary_literal_unwrap Err::<(), _>(1).expect_err("this never happens"); + //~^ unnecessary_literal_unwrap Err::<(), _>(1).unwrap(); + //~^ unnecessary_literal_unwrap Err::<(), _>(1).expect("this always happens"); + //~^ unnecessary_literal_unwrap } fn unwrap_methods_option() { let _val = Some(1).unwrap_or(2); + //~^ unnecessary_literal_unwrap let _val = Some(1).unwrap_or_default(); + //~^ unnecessary_literal_unwrap let _val = Some(1).unwrap_or_else(|| 2); + //~^ unnecessary_literal_unwrap Some(1).unwrap_or(2); + //~^ unnecessary_literal_unwrap Some(1).unwrap_or_default(); + //~^ unnecessary_literal_unwrap Some(1).unwrap_or_else(|| 2); + //~^ unnecessary_literal_unwrap } fn unwrap_methods_result() { let _val = Ok::<_, ()>(1).unwrap_or(2); + //~^ unnecessary_literal_unwrap let _val = Ok::<_, ()>(1).unwrap_or_default(); + //~^ unnecessary_literal_unwrap let _val = Ok::<_, ()>(1).unwrap_or_else(|_| 2); + //~^ unnecessary_literal_unwrap Ok::<_, ()>(1).unwrap_or(2); + //~^ unnecessary_literal_unwrap Ok::<_, ()>(1).unwrap_or_default(); + //~^ unnecessary_literal_unwrap Ok::<_, ()>(1).unwrap_or_else(|_| 2); + //~^ unnecessary_literal_unwrap } fn unwrap_from_binding() { @@ -90,12 +136,20 @@ fn unwrap_from_binding() { fn unwrap_unchecked() { let _ = unsafe { Some(1).unwrap_unchecked() }; + //~^ unnecessary_literal_unwrap let _ = unsafe { Some(1).unwrap_unchecked() + *(&1 as *const i32) }; // needs to keep the unsafe block + // + //~^^ unnecessary_literal_unwrap let _ = unsafe { Some(1).unwrap_unchecked() } + 1; + //~^ unnecessary_literal_unwrap let _ = unsafe { Ok::<_, ()>(1).unwrap_unchecked() }; + //~^ unnecessary_literal_unwrap let _ = unsafe { Ok::<_, ()>(1).unwrap_unchecked() + *(&1 as *const i32) }; + //~^ unnecessary_literal_unwrap let _ = unsafe { Ok::<_, ()>(1).unwrap_unchecked() } + 1; + //~^ unnecessary_literal_unwrap let _ = unsafe { Err::<(), i32>(123).unwrap_err_unchecked() }; + //~^ unnecessary_literal_unwrap } fn main() { diff --git a/tests/ui/unnecessary_literal_unwrap.stderr b/tests/ui/unnecessary_literal_unwrap.stderr index 631bf0837266..cd90763263e9 100644 --- a/tests/ui/unnecessary_literal_unwrap.stderr +++ b/tests/ui/unnecessary_literal_unwrap.stderr @@ -13,7 +13,7 @@ LL + let _val = 1; | error: used `expect()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap.rs:12:16 + --> tests/ui/unnecessary_literal_unwrap.rs:13:16 | LL | let _val = Some(1).expect("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + let _val = 1; | error: used `unwrap()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap.rs:14:5 + --> tests/ui/unnecessary_literal_unwrap.rs:16:5 | LL | Some(1).unwrap(); | ^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + 1; | error: used `expect()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap.rs:15:5 + --> tests/ui/unnecessary_literal_unwrap.rs:18:5 | LL | Some(1).expect("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,13 +49,13 @@ LL + 1; | error: used `unwrap()` on `None` value - --> tests/ui/unnecessary_literal_unwrap.rs:20:16 + --> tests/ui/unnecessary_literal_unwrap.rs:24:16 | LL | let _val = None::<()>.unwrap(); | ^^^^^^^^^^^^^^^^^^^ help: remove the `None` and `unwrap()`: `panic!()` error: used `expect()` on `None` value - --> tests/ui/unnecessary_literal_unwrap.rs:21:16 + --> tests/ui/unnecessary_literal_unwrap.rs:26:16 | LL | let _val = None::<()>.expect("this always happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -67,13 +67,13 @@ LL + let _val = panic!("this always happens"); | error: used `unwrap_or_default()` on `None` value - --> tests/ui/unnecessary_literal_unwrap.rs:22:24 + --> tests/ui/unnecessary_literal_unwrap.rs:28:24 | LL | let _val: String = None.unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the `None` and `unwrap_or_default()`: `String::default()` error: used `unwrap_or()` on `None` value - --> tests/ui/unnecessary_literal_unwrap.rs:23:21 + --> tests/ui/unnecessary_literal_unwrap.rs:30:21 | LL | let _val: u16 = None.unwrap_or(234); | ^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + let _val: u16 = 234; | error: used `unwrap_or_else()` on `None` value - --> tests/ui/unnecessary_literal_unwrap.rs:24:21 + --> tests/ui/unnecessary_literal_unwrap.rs:32:21 | LL | let _val: u16 = None.unwrap_or_else(|| 234); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL + let _val: u16 = 234; | error: used `unwrap_or_else()` on `None` value - --> tests/ui/unnecessary_literal_unwrap.rs:25:21 + --> tests/ui/unnecessary_literal_unwrap.rs:34:21 | LL | let _val: u16 = None.unwrap_or_else(|| { 234 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL + let _val: u16 = { 234 }; | error: used `unwrap_or_else()` on `None` value - --> tests/ui/unnecessary_literal_unwrap.rs:26:21 + --> tests/ui/unnecessary_literal_unwrap.rs:36:21 | LL | let _val: u16 = None.unwrap_or_else(|| -> u16 { 234 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,13 +121,13 @@ LL + let _val: u16 = { 234 }; | error: used `unwrap()` on `None` value - --> tests/ui/unnecessary_literal_unwrap.rs:28:5 + --> tests/ui/unnecessary_literal_unwrap.rs:39:5 | LL | None::<()>.unwrap(); | ^^^^^^^^^^^^^^^^^^^ help: remove the `None` and `unwrap()`: `panic!()` error: used `expect()` on `None` value - --> tests/ui/unnecessary_literal_unwrap.rs:29:5 + --> tests/ui/unnecessary_literal_unwrap.rs:41:5 | LL | None::<()>.expect("this always happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -139,13 +139,13 @@ LL + panic!("this always happens"); | error: used `unwrap_or_default()` on `None` value - --> tests/ui/unnecessary_literal_unwrap.rs:30:5 + --> tests/ui/unnecessary_literal_unwrap.rs:43:5 | LL | None::.unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the `None` and `unwrap_or_default()`: `String::default()` error: used `unwrap_or()` on `None` value - --> tests/ui/unnecessary_literal_unwrap.rs:31:5 + --> tests/ui/unnecessary_literal_unwrap.rs:45:5 | LL | None::.unwrap_or(234); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL + 234; | error: used `unwrap_or_else()` on `None` value - --> tests/ui/unnecessary_literal_unwrap.rs:32:5 + --> tests/ui/unnecessary_literal_unwrap.rs:47:5 | LL | None::.unwrap_or_else(|| 234); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -169,7 +169,7 @@ LL + 234; | error: used `unwrap_or_else()` on `None` value - --> tests/ui/unnecessary_literal_unwrap.rs:33:5 + --> tests/ui/unnecessary_literal_unwrap.rs:49:5 | LL | None::.unwrap_or_else(|| { 234 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -181,7 +181,7 @@ LL + { 234 }; | error: used `unwrap_or_else()` on `None` value - --> tests/ui/unnecessary_literal_unwrap.rs:34:5 + --> tests/ui/unnecessary_literal_unwrap.rs:51:5 | LL | None::.unwrap_or_else(|| -> u16 { 234 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -193,7 +193,7 @@ LL + { 234 }; | error: used `unwrap()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap.rs:38:16 + --> tests/ui/unnecessary_literal_unwrap.rs:56:16 | LL | let _val = Ok::<_, ()>(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -205,7 +205,7 @@ LL + let _val = 1; | error: used `expect()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap.rs:39:16 + --> tests/ui/unnecessary_literal_unwrap.rs:58:16 | LL | let _val = Ok::<_, ()>(1).expect("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +217,7 @@ LL + let _val = 1; | error: used `unwrap_err()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap.rs:40:16 + --> tests/ui/unnecessary_literal_unwrap.rs:60:16 | LL | let _val = Ok::<_, ()>(1).unwrap_err(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -229,7 +229,7 @@ LL + let _val = panic!("{:?}", 1); | error: used `expect_err()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap.rs:41:16 + --> tests/ui/unnecessary_literal_unwrap.rs:62:16 | LL | let _val = Ok::<_, ()>(1).expect_err("this always happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,7 +241,7 @@ LL + let _val = panic!("{1}: {:?}", 1, "this always happens"); | error: used `unwrap()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap.rs:43:5 + --> tests/ui/unnecessary_literal_unwrap.rs:65:5 | LL | Ok::<_, ()>(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -253,7 +253,7 @@ LL + 1; | error: used `expect()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap.rs:44:5 + --> tests/ui/unnecessary_literal_unwrap.rs:67:5 | LL | Ok::<_, ()>(1).expect("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -265,7 +265,7 @@ LL + 1; | error: used `unwrap_err()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap.rs:45:5 + --> tests/ui/unnecessary_literal_unwrap.rs:69:5 | LL | Ok::<_, ()>(1).unwrap_err(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -277,7 +277,7 @@ LL + panic!("{:?}", 1); | error: used `expect_err()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap.rs:46:5 + --> tests/ui/unnecessary_literal_unwrap.rs:71:5 | LL | Ok::<_, ()>(1).expect_err("this always happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -289,7 +289,7 @@ LL + panic!("{1}: {:?}", 1, "this always happens"); | error: used `unwrap_err()` on `Err` value - --> tests/ui/unnecessary_literal_unwrap.rs:50:16 + --> tests/ui/unnecessary_literal_unwrap.rs:76:16 | LL | let _val = Err::<(), _>(1).unwrap_err(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -301,7 +301,7 @@ LL + let _val = 1; | error: used `expect_err()` on `Err` value - --> tests/ui/unnecessary_literal_unwrap.rs:51:16 + --> tests/ui/unnecessary_literal_unwrap.rs:78:16 | LL | let _val = Err::<(), _>(1).expect_err("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -313,7 +313,7 @@ LL + let _val = 1; | error: used `unwrap()` on `Err` value - --> tests/ui/unnecessary_literal_unwrap.rs:52:16 + --> tests/ui/unnecessary_literal_unwrap.rs:80:16 | LL | let _val = Err::<(), _>(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -325,7 +325,7 @@ LL + let _val = panic!("{:?}", 1); | error: used `expect()` on `Err` value - --> tests/ui/unnecessary_literal_unwrap.rs:53:16 + --> tests/ui/unnecessary_literal_unwrap.rs:82:16 | LL | let _val = Err::<(), _>(1).expect("this always happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -337,7 +337,7 @@ LL + let _val = panic!("{1}: {:?}", 1, "this always happens"); | error: used `unwrap_err()` on `Err` value - --> tests/ui/unnecessary_literal_unwrap.rs:55:5 + --> tests/ui/unnecessary_literal_unwrap.rs:85:5 | LL | Err::<(), _>(1).unwrap_err(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -349,7 +349,7 @@ LL + 1; | error: used `expect_err()` on `Err` value - --> tests/ui/unnecessary_literal_unwrap.rs:56:5 + --> tests/ui/unnecessary_literal_unwrap.rs:87:5 | LL | Err::<(), _>(1).expect_err("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -361,7 +361,7 @@ LL + 1; | error: used `unwrap()` on `Err` value - --> tests/ui/unnecessary_literal_unwrap.rs:57:5 + --> tests/ui/unnecessary_literal_unwrap.rs:89:5 | LL | Err::<(), _>(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -373,7 +373,7 @@ LL + panic!("{:?}", 1); | error: used `expect()` on `Err` value - --> tests/ui/unnecessary_literal_unwrap.rs:58:5 + --> tests/ui/unnecessary_literal_unwrap.rs:91:5 | LL | Err::<(), _>(1).expect("this always happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -385,7 +385,7 @@ LL + panic!("{1}: {:?}", 1, "this always happens"); | error: used `unwrap_or()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap.rs:62:16 + --> tests/ui/unnecessary_literal_unwrap.rs:96:16 | LL | let _val = Some(1).unwrap_or(2); | ^^^^^^^^^^^^^^^^^^^^ @@ -397,7 +397,7 @@ LL + let _val = 1; | error: used `unwrap_or_default()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap.rs:63:16 + --> tests/ui/unnecessary_literal_unwrap.rs:98:16 | LL | let _val = Some(1).unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -409,7 +409,7 @@ LL + let _val = 1; | error: used `unwrap_or_else()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap.rs:64:16 + --> tests/ui/unnecessary_literal_unwrap.rs:100:16 | LL | let _val = Some(1).unwrap_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -421,7 +421,7 @@ LL + let _val = 1; | error: used `unwrap_or()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap.rs:66:5 + --> tests/ui/unnecessary_literal_unwrap.rs:103:5 | LL | Some(1).unwrap_or(2); | ^^^^^^^^^^^^^^^^^^^^ @@ -433,7 +433,7 @@ LL + 1; | error: used `unwrap_or_default()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap.rs:67:5 + --> tests/ui/unnecessary_literal_unwrap.rs:105:5 | LL | Some(1).unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -445,7 +445,7 @@ LL + 1; | error: used `unwrap_or_else()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap.rs:68:5 + --> tests/ui/unnecessary_literal_unwrap.rs:107:5 | LL | Some(1).unwrap_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -457,7 +457,7 @@ LL + 1; | error: used `unwrap_or()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap.rs:72:16 + --> tests/ui/unnecessary_literal_unwrap.rs:112:16 | LL | let _val = Ok::<_, ()>(1).unwrap_or(2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -469,7 +469,7 @@ LL + let _val = 1; | error: used `unwrap_or_default()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap.rs:73:16 + --> tests/ui/unnecessary_literal_unwrap.rs:114:16 | LL | let _val = Ok::<_, ()>(1).unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -481,7 +481,7 @@ LL + let _val = 1; | error: used `unwrap_or_else()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap.rs:74:16 + --> tests/ui/unnecessary_literal_unwrap.rs:116:16 | LL | let _val = Ok::<_, ()>(1).unwrap_or_else(|_| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -493,7 +493,7 @@ LL + let _val = 1; | error: used `unwrap_or()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap.rs:76:5 + --> tests/ui/unnecessary_literal_unwrap.rs:119:5 | LL | Ok::<_, ()>(1).unwrap_or(2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -505,7 +505,7 @@ LL + 1; | error: used `unwrap_or_default()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap.rs:77:5 + --> tests/ui/unnecessary_literal_unwrap.rs:121:5 | LL | Ok::<_, ()>(1).unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -517,7 +517,7 @@ LL + 1; | error: used `unwrap_or_else()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap.rs:78:5 + --> tests/ui/unnecessary_literal_unwrap.rs:123:5 | LL | Ok::<_, ()>(1).unwrap_or_else(|_| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -529,7 +529,7 @@ LL + 1; | error: used `unwrap_unchecked()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap.rs:92:22 + --> tests/ui/unnecessary_literal_unwrap.rs:138:22 | LL | let _ = unsafe { Some(1).unwrap_unchecked() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -541,7 +541,7 @@ LL + let _ = 1; | error: used `unwrap_unchecked()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap.rs:93:22 + --> tests/ui/unnecessary_literal_unwrap.rs:140:22 | LL | let _ = unsafe { Some(1).unwrap_unchecked() + *(&1 as *const i32) }; // needs to keep the unsafe block | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -553,7 +553,7 @@ LL + let _ = unsafe { 1 + *(&1 as *const i32) }; // needs to keep the unsafe | error: used `unwrap_unchecked()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap.rs:94:22 + --> tests/ui/unnecessary_literal_unwrap.rs:143:22 | LL | let _ = unsafe { Some(1).unwrap_unchecked() } + 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -565,7 +565,7 @@ LL + let _ = 1 + 1; | error: used `unwrap_unchecked()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap.rs:95:22 + --> tests/ui/unnecessary_literal_unwrap.rs:145:22 | LL | let _ = unsafe { Ok::<_, ()>(1).unwrap_unchecked() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -577,7 +577,7 @@ LL + let _ = 1; | error: used `unwrap_unchecked()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap.rs:96:22 + --> tests/ui/unnecessary_literal_unwrap.rs:147:22 | LL | let _ = unsafe { Ok::<_, ()>(1).unwrap_unchecked() + *(&1 as *const i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -589,7 +589,7 @@ LL + let _ = unsafe { 1 + *(&1 as *const i32) }; | error: used `unwrap_unchecked()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap.rs:97:22 + --> tests/ui/unnecessary_literal_unwrap.rs:149:22 | LL | let _ = unsafe { Ok::<_, ()>(1).unwrap_unchecked() } + 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -601,7 +601,7 @@ LL + let _ = 1 + 1; | error: used `unwrap_err_unchecked()` on `Err` value - --> tests/ui/unnecessary_literal_unwrap.rs:98:22 + --> tests/ui/unnecessary_literal_unwrap.rs:151:22 | LL | let _ = unsafe { Err::<(), i32>(123).unwrap_err_unchecked() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unnecessary_literal_unwrap_unfixable.rs b/tests/ui/unnecessary_literal_unwrap_unfixable.rs index 61058b7988a2..b6cba4e6a568 100644 --- a/tests/ui/unnecessary_literal_unwrap_unfixable.rs +++ b/tests/ui/unnecessary_literal_unwrap_unfixable.rs @@ -5,154 +5,190 @@ fn unwrap_option_some() { let val = Some(1); let _val2 = val.unwrap(); - //~^ ERROR: used `unwrap()` on `Some` value + //~^ unnecessary_literal_unwrap + let _val2 = val.expect("this never happens"); - //~^ ERROR: used `expect()` on `Some` value + //~^ unnecessary_literal_unwrap } fn unwrap_option_some_context() { let _val = Some::([1, 2, 3].iter().sum()).unwrap(); - //~^ ERROR: used `unwrap()` on `Some` value + //~^ unnecessary_literal_unwrap + let _val = Some::([1, 2, 3].iter().sum()).expect("this never happens"); - //~^ ERROR: used `expect()` on `Some` value + //~^ unnecessary_literal_unwrap let val = Some::([1, 2, 3].iter().sum()); let _val2 = val.unwrap(); - //~^ ERROR: used `unwrap()` on `Some` value + //~^ unnecessary_literal_unwrap + let _val2 = val.expect("this never happens"); - //~^ ERROR: used `expect()` on `Some` value + //~^ unnecessary_literal_unwrap } fn unwrap_option_none() { let val = None::<()>; let _val2 = val.unwrap(); - //~^ ERROR: used `unwrap()` on `None` value + //~^ unnecessary_literal_unwrap + let _val2 = val.expect("this always happens"); - //~^ ERROR: used `expect()` on `None` value + //~^ unnecessary_literal_unwrap + let _val3: u8 = None.unwrap_or_default(); - //~^ ERROR: used `unwrap_or_default()` on `None` value + //~^ unnecessary_literal_unwrap + None::<()>.unwrap_or_default(); - //~^ ERROR: used `unwrap_or_default()` on `None` value + //~^ unnecessary_literal_unwrap } fn unwrap_result_ok() { let val = Ok::<_, ()>(1); let _val2 = val.unwrap(); - //~^ ERROR: used `unwrap()` on `Ok` value + //~^ unnecessary_literal_unwrap + let _val2 = val.expect("this never happens"); - //~^ ERROR: used `expect()` on `Ok` value + //~^ unnecessary_literal_unwrap + let _val2 = val.unwrap_err(); - //~^ ERROR: used `unwrap_err()` on `Ok` value + //~^ unnecessary_literal_unwrap + let _val2 = val.expect_err("this always happens"); - //~^ ERROR: used `expect_err()` on `Ok` value + //~^ unnecessary_literal_unwrap } fn unwrap_result_ok_context() { let _val = Ok::([1, 2, 3].iter().sum()).unwrap(); - //~^ ERROR: used `unwrap()` on `Ok` value + //~^ unnecessary_literal_unwrap + let _val = Ok::([1, 2, 3].iter().sum()).expect("this never happens"); - //~^ ERROR: used `expect()` on `Ok` value + //~^ unnecessary_literal_unwrap + let _val = Ok::([1, 2, 3].iter().sum()).unwrap_err(); - //~^ ERROR: used `unwrap_err()` on `Ok` value + //~^ unnecessary_literal_unwrap + let _val = Ok::([1, 2, 3].iter().sum()).expect_err("this always happens"); - //~^ ERROR: used `expect_err()` on `Ok` value + //~^ unnecessary_literal_unwrap let val = Ok::([1, 2, 3].iter().sum()); let _val2 = val.unwrap(); - //~^ ERROR: used `unwrap()` on `Ok` value + //~^ unnecessary_literal_unwrap + let _val2 = val.expect("this never happens"); - //~^ ERROR: used `expect()` on `Ok` value + //~^ unnecessary_literal_unwrap + let _val2 = val.unwrap_err(); - //~^ ERROR: used `unwrap_err()` on `Ok` value + //~^ unnecessary_literal_unwrap + let _val2 = val.expect_err("this always happens"); - //~^ ERROR: used `expect_err()` on `Ok` value + //~^ unnecessary_literal_unwrap } fn unwrap_result_err() { let val = Err::<(), _>(1); let _val2 = val.unwrap_err(); - //~^ ERROR: used `unwrap_err()` on `Err` value + //~^ unnecessary_literal_unwrap + let _val2 = val.expect_err("this never happens"); - //~^ ERROR: used `expect_err()` on `Err` value + //~^ unnecessary_literal_unwrap + let _val2 = val.unwrap(); - //~^ ERROR: used `unwrap()` on `Err` value + //~^ unnecessary_literal_unwrap + let _val2 = val.expect("this always happens"); - //~^ ERROR: used `expect()` on `Err` value + //~^ unnecessary_literal_unwrap } fn unwrap_result_err_context() { let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap_err(); - //~^ ERROR: used `unwrap_err()` on `Err` value + //~^ unnecessary_literal_unwrap + let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect_err("this never happens"); - //~^ ERROR: used `expect_err()` on `Err` value + //~^ unnecessary_literal_unwrap + let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap(); - //~^ ERROR: used `unwrap()` on `Err` value + //~^ unnecessary_literal_unwrap + let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect("this always happens"); - //~^ ERROR: used `expect()` on `Err` value + //~^ unnecessary_literal_unwrap let val = Err::<(), usize>([1, 2, 3].iter().sum()); let _val2 = val.unwrap_err(); - //~^ ERROR: used `unwrap_err()` on `Err` value + //~^ unnecessary_literal_unwrap + let _val2 = val.expect_err("this never happens"); - //~^ ERROR: used `expect_err()` on `Err` value + //~^ unnecessary_literal_unwrap + let _val2 = val.unwrap(); - //~^ ERROR: used `unwrap()` on `Err` value + //~^ unnecessary_literal_unwrap + let _val2 = val.expect("this always happens"); - //~^ ERROR: used `expect()` on `Err` value + //~^ unnecessary_literal_unwrap } fn unwrap_methods_option() { let val = Some(1); let _val2 = val.unwrap_or(2); - //~^ ERROR: used `unwrap_or()` on `Some` value + //~^ unnecessary_literal_unwrap + let _val2 = val.unwrap_or_default(); - //~^ ERROR: used `unwrap_or_default()` on `Some` value + //~^ unnecessary_literal_unwrap + let _val2 = val.unwrap_or_else(|| 2); - //~^ ERROR: used `unwrap_or_else()` on `Some` value + //~^ unnecessary_literal_unwrap } fn unwrap_methods_option_context() { let _val = Some::([1, 2, 3].iter().sum()).unwrap_or(2); - //~^ ERROR: used `unwrap_or()` on `Some` value + //~^ unnecessary_literal_unwrap + let _val = Some::([1, 2, 3].iter().sum()).unwrap_or_default(); - //~^ ERROR: used `unwrap_or_default()` on `Some` value + //~^ unnecessary_literal_unwrap + let _val = Some::([1, 2, 3].iter().sum()).unwrap_or_else(|| 2); - //~^ ERROR: used `unwrap_or_else()` on `Some` value + //~^ unnecessary_literal_unwrap let val = Some::([1, 2, 3].iter().sum()); let _val2 = val.unwrap_or(2); - //~^ ERROR: used `unwrap_or()` on `Some` value + //~^ unnecessary_literal_unwrap + let _val2 = val.unwrap_or_default(); - //~^ ERROR: used `unwrap_or_default()` on `Some` value + //~^ unnecessary_literal_unwrap + let _val2 = val.unwrap_or_else(|| 2); - //~^ ERROR: used `unwrap_or_else()` on `Some` value + //~^ unnecessary_literal_unwrap } fn unwrap_methods_result() { let val = Ok::<_, ()>(1); let _val2 = val.unwrap_or(2); - //~^ ERROR: used `unwrap_or()` on `Ok` value + //~^ unnecessary_literal_unwrap + let _val2 = val.unwrap_or_default(); - //~^ ERROR: used `unwrap_or_default()` on `Ok` value + //~^ unnecessary_literal_unwrap + let _val2 = val.unwrap_or_else(|_| 2); - //~^ ERROR: used `unwrap_or_else()` on `Ok` value + //~^ unnecessary_literal_unwrap } fn unwrap_methods_result_context() { let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or(2); - //~^ ERROR: used `unwrap_or()` on `Ok` value + //~^ unnecessary_literal_unwrap + let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or_default(); - //~^ ERROR: used `unwrap_or_default()` on `Ok` value + //~^ unnecessary_literal_unwrap + let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or_else(|_| 2); - //~^ ERROR: used `unwrap_or_else()` on `Ok` value + //~^ unnecessary_literal_unwrap let val = Ok::([1, 2, 3].iter().sum()); let _val2 = val.unwrap_or(2); - //~^ ERROR: used `unwrap_or()` on `Ok` value + //~^ unnecessary_literal_unwrap + let _val2 = val.unwrap_or_default(); - //~^ ERROR: used `unwrap_or_default()` on `Ok` value + //~^ unnecessary_literal_unwrap + let _val2 = val.unwrap_or_else(|_| 2); - //~^ ERROR: used `unwrap_or_else()` on `Ok` value + //~^ unnecessary_literal_unwrap } fn main() { diff --git a/tests/ui/unnecessary_literal_unwrap_unfixable.stderr b/tests/ui/unnecessary_literal_unwrap_unfixable.stderr index b7dd7ae729fd..4994eeded776 100644 --- a/tests/ui/unnecessary_literal_unwrap_unfixable.stderr +++ b/tests/ui/unnecessary_literal_unwrap_unfixable.stderr @@ -13,7 +13,7 @@ LL | let val = Some(1); = help: to override `-D warnings` add `#[allow(clippy::unnecessary_literal_unwrap)]` error: used `expect()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:9:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:10:17 | LL | let _val2 = val.expect("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,589 +25,589 @@ LL | let val = Some(1); | ^^^^^^^ error: used `unwrap()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:14:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:15:16 | LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Some` and `unwrap()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:14:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:15:16 | LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `expect()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:16:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:18:16 | LL | let _val = Some::([1, 2, 3].iter().sum()).expect("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Some` and `expect()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:16:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:18:16 | LL | let _val = Some::([1, 2, 3].iter().sum()).expect("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:20:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:22:17 | LL | let _val2 = val.unwrap(); | ^^^^^^^^^^^^ | help: remove the `Some` and `unwrap()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:19:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:21:15 | LL | let val = Some::([1, 2, 3].iter().sum()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `expect()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:22:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:25:17 | LL | let _val2 = val.expect("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Some` and `expect()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:19:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:21:15 | LL | let val = Some::([1, 2, 3].iter().sum()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap()` on `None` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:28:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:31:17 | LL | let _val2 = val.unwrap(); | ^^^^^^^^^^^^ | help: remove the `None` and `unwrap()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:27:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:30:15 | LL | let val = None::<()>; | ^^^^^^^^^^ error: used `expect()` on `None` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:30:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:34:17 | LL | let _val2 = val.expect("this always happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `None` and `expect()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:27:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:30:15 | LL | let val = None::<()>; | ^^^^^^^^^^ error: used `unwrap_or_default()` on `None` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:32:21 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:37:21 | LL | let _val3: u8 = None.unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the `None` and `unwrap_or_default()`: `Default::default()` error: used `unwrap_or_default()` on `None` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:34:5 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:40:5 | LL | None::<()>.unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the `None` and `unwrap_or_default()`: `Default::default()` error: used `unwrap()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:40:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:46:17 | LL | let _val2 = val.unwrap(); | ^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:39:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:45:15 | LL | let val = Ok::<_, ()>(1); | ^^^^^^^^^^^^^^ error: used `expect()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:42:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:49:17 | LL | let _val2 = val.expect("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `expect()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:39:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:45:15 | LL | let val = Ok::<_, ()>(1); | ^^^^^^^^^^^^^^ error: used `unwrap_err()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:44:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:52:17 | LL | let _val2 = val.unwrap_err(); | ^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap_err()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:39:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:45:15 | LL | let val = Ok::<_, ()>(1); | ^^^^^^^^^^^^^^ error: used `expect_err()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:46:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:55:17 | LL | let _val2 = val.expect_err("this always happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `expect_err()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:39:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:45:15 | LL | let val = Ok::<_, ()>(1); | ^^^^^^^^^^^^^^ error: used `unwrap()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:51:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:60:16 | LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:51:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:60:16 | LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `expect()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:53:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:63:16 | LL | let _val = Ok::([1, 2, 3].iter().sum()).expect("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `expect()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:53:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:63:16 | LL | let _val = Ok::([1, 2, 3].iter().sum()).expect("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap_err()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:55:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:66:16 | LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_err(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap_err()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:55:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:66:16 | LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_err(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `expect_err()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:57:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:69:16 | LL | let _val = Ok::([1, 2, 3].iter().sum()).expect_err("this always happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `expect_err()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:57:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:69:16 | LL | let _val = Ok::([1, 2, 3].iter().sum()).expect_err("this always happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:61:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:73:17 | LL | let _val2 = val.unwrap(); | ^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:60:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:72:15 | LL | let val = Ok::([1, 2, 3].iter().sum()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `expect()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:63:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:76:17 | LL | let _val2 = val.expect("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `expect()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:60:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:72:15 | LL | let val = Ok::([1, 2, 3].iter().sum()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap_err()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:65:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:79:17 | LL | let _val2 = val.unwrap_err(); | ^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap_err()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:60:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:72:15 | LL | let val = Ok::([1, 2, 3].iter().sum()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `expect_err()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:67:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:82:17 | LL | let _val2 = val.expect_err("this always happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `expect_err()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:60:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:72:15 | LL | let val = Ok::([1, 2, 3].iter().sum()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap_err()` on `Err` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:73:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:88:17 | LL | let _val2 = val.unwrap_err(); | ^^^^^^^^^^^^^^^^ | help: remove the `Err` and `unwrap_err()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:72:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:87:15 | LL | let val = Err::<(), _>(1); | ^^^^^^^^^^^^^^^ error: used `expect_err()` on `Err` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:75:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:91:17 | LL | let _val2 = val.expect_err("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Err` and `expect_err()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:72:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:87:15 | LL | let val = Err::<(), _>(1); | ^^^^^^^^^^^^^^^ error: used `unwrap()` on `Err` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:77:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:94:17 | LL | let _val2 = val.unwrap(); | ^^^^^^^^^^^^ | help: remove the `Err` and `unwrap()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:72:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:87:15 | LL | let val = Err::<(), _>(1); | ^^^^^^^^^^^^^^^ error: used `expect()` on `Err` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:79:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:97:17 | LL | let _val2 = val.expect("this always happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Err` and `expect()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:72:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:87:15 | LL | let val = Err::<(), _>(1); | ^^^^^^^^^^^^^^^ error: used `unwrap_err()` on `Err` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:84:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:102:16 | LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap_err(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Err` and `unwrap_err()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:84:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:102:16 | LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap_err(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `expect_err()` on `Err` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:86:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:105:16 | LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect_err("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Err` and `expect_err()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:86:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:105:16 | LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect_err("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap()` on `Err` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:88:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:108:16 | LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Err` and `unwrap()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:88:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:108:16 | LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `expect()` on `Err` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:90:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:111:16 | LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect("this always happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Err` and `expect()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:90:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:111:16 | LL | let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect("this always happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap_err()` on `Err` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:94:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:115:17 | LL | let _val2 = val.unwrap_err(); | ^^^^^^^^^^^^^^^^ | help: remove the `Err` and `unwrap_err()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:93:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:114:15 | LL | let val = Err::<(), usize>([1, 2, 3].iter().sum()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `expect_err()` on `Err` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:96:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:118:17 | LL | let _val2 = val.expect_err("this never happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Err` and `expect_err()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:93:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:114:15 | LL | let val = Err::<(), usize>([1, 2, 3].iter().sum()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap()` on `Err` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:98:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:121:17 | LL | let _val2 = val.unwrap(); | ^^^^^^^^^^^^ | help: remove the `Err` and `unwrap()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:93:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:114:15 | LL | let val = Err::<(), usize>([1, 2, 3].iter().sum()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `expect()` on `Err` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:100:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:124:17 | LL | let _val2 = val.expect("this always happens"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Err` and `expect()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:93:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:114:15 | LL | let val = Err::<(), usize>([1, 2, 3].iter().sum()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap_or()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:106:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:130:17 | LL | let _val2 = val.unwrap_or(2); | ^^^^^^^^^^^^^^^^ | help: remove the `Some` and `unwrap_or()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:105:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:129:15 | LL | let val = Some(1); | ^^^^^^^ error: used `unwrap_or_default()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:108:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:133:17 | LL | let _val2 = val.unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Some` and `unwrap_or_default()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:105:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:129:15 | LL | let val = Some(1); | ^^^^^^^ error: used `unwrap_or_else()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:110:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:136:17 | LL | let _val2 = val.unwrap_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Some` and `unwrap_or_else()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:105:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:129:15 | LL | let val = Some(1); | ^^^^^^^ error: used `unwrap_or()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:115:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:141:16 | LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap_or(2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Some` and `unwrap_or()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:115:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:141:16 | LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap_or(2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap_or_default()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:117:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:144:16 | LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Some` and `unwrap_or_default()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:117:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:144:16 | LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap_or_else()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:119:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:147:16 | LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Some` and `unwrap_or_else()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:119:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:147:16 | LL | let _val = Some::([1, 2, 3].iter().sum()).unwrap_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap_or()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:123:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:151:17 | LL | let _val2 = val.unwrap_or(2); | ^^^^^^^^^^^^^^^^ | help: remove the `Some` and `unwrap_or()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:122:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:150:15 | LL | let val = Some::([1, 2, 3].iter().sum()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap_or_default()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:125:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:154:17 | LL | let _val2 = val.unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Some` and `unwrap_or_default()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:122:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:150:15 | LL | let val = Some::([1, 2, 3].iter().sum()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap_or_else()` on `Some` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:127:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:157:17 | LL | let _val2 = val.unwrap_or_else(|| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Some` and `unwrap_or_else()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:122:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:150:15 | LL | let val = Some::([1, 2, 3].iter().sum()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap_or()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:133:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:163:17 | LL | let _val2 = val.unwrap_or(2); | ^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap_or()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:132:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:162:15 | LL | let val = Ok::<_, ()>(1); | ^^^^^^^^^^^^^^ error: used `unwrap_or_default()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:135:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:166:17 | LL | let _val2 = val.unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap_or_default()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:132:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:162:15 | LL | let val = Ok::<_, ()>(1); | ^^^^^^^^^^^^^^ error: used `unwrap_or_else()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:137:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:169:17 | LL | let _val2 = val.unwrap_or_else(|_| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap_or_else()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:132:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:162:15 | LL | let val = Ok::<_, ()>(1); | ^^^^^^^^^^^^^^ error: used `unwrap_or()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:142:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:174:16 | LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or(2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap_or()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:142:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:174:16 | LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or(2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap_or_default()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:144:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:177:16 | LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap_or_default()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:144:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:177:16 | LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap_or_else()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:146:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:180:16 | LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or_else(|_| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap_or_else()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:146:16 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:180:16 | LL | let _val = Ok::([1, 2, 3].iter().sum()).unwrap_or_else(|_| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap_or()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:150:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:184:17 | LL | let _val2 = val.unwrap_or(2); | ^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap_or()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:149:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:183:15 | LL | let val = Ok::([1, 2, 3].iter().sum()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap_or_default()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:152:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:187:17 | LL | let _val2 = val.unwrap_or_default(); | ^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap_or_default()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:149:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:183:15 | LL | let val = Ok::([1, 2, 3].iter().sum()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used `unwrap_or_else()` on `Ok` value - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:154:17 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:190:17 | LL | let _val2 = val.unwrap_or_else(|_| 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove the `Ok` and `unwrap_or_else()` - --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:149:15 + --> tests/ui/unnecessary_literal_unwrap_unfixable.rs:183:15 | LL | let val = Ok::([1, 2, 3].iter().sum()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unnecessary_map_on_constructor.fixed b/tests/ui/unnecessary_map_on_constructor.fixed index d0ba7ed749e4..4452fda38c40 100644 --- a/tests/ui/unnecessary_map_on_constructor.fixed +++ b/tests/ui/unnecessary_map_on_constructor.fixed @@ -30,14 +30,22 @@ fn main() { let c: SimpleResult = Err(err); let a = Some(fun(x)); + //~^ unnecessary_map_on_constructor let b: SimpleResult = Ok(fun(x)); + //~^ unnecessary_map_on_constructor let c: SimpleResult = Err(notfun(err)); + //~^ unnecessary_map_on_constructor let a = Option::Some(fun(x)); + //~^ unnecessary_map_on_constructor let b: SimpleResult = SimpleResult::Ok(fun(x)); + //~^ unnecessary_map_on_constructor let c: SimpleResult = SimpleResult::Err(notfun(err)); + //~^ unnecessary_map_on_constructor let b: std::result::Result = Ok(fun(x)); + //~^ unnecessary_map_on_constructor let c: std::result::Result = Err(notfun(err)); + //~^ unnecessary_map_on_constructor let a = Some(fun(x)); let b: SimpleResult = Ok(fun(x)); diff --git a/tests/ui/unnecessary_map_on_constructor.rs b/tests/ui/unnecessary_map_on_constructor.rs index e89e7aad4c40..0cd41f2b363a 100644 --- a/tests/ui/unnecessary_map_on_constructor.rs +++ b/tests/ui/unnecessary_map_on_constructor.rs @@ -30,14 +30,22 @@ fn main() { let c: SimpleResult = Err(err); let a = Some(x).map(fun); + //~^ unnecessary_map_on_constructor let b: SimpleResult = Ok(x).map(fun); + //~^ unnecessary_map_on_constructor let c: SimpleResult = Err(err).map_err(notfun); + //~^ unnecessary_map_on_constructor let a = Option::Some(x).map(fun); + //~^ unnecessary_map_on_constructor let b: SimpleResult = SimpleResult::Ok(x).map(fun); + //~^ unnecessary_map_on_constructor let c: SimpleResult = SimpleResult::Err(err).map_err(notfun); + //~^ unnecessary_map_on_constructor let b: std::result::Result = Ok(x).map(fun); + //~^ unnecessary_map_on_constructor let c: std::result::Result = Err(err).map_err(notfun); + //~^ unnecessary_map_on_constructor let a = Some(fun(x)); let b: SimpleResult = Ok(fun(x)); diff --git a/tests/ui/unnecessary_map_on_constructor.stderr b/tests/ui/unnecessary_map_on_constructor.stderr index ecbf65244154..f29bfec60f72 100644 --- a/tests/ui/unnecessary_map_on_constructor.stderr +++ b/tests/ui/unnecessary_map_on_constructor.stderr @@ -8,43 +8,43 @@ LL | let a = Some(x).map(fun); = help: to override `-D warnings` add `#[allow(clippy::unnecessary_map_on_constructor)]` error: unnecessary map on constructor Ok(_) - --> tests/ui/unnecessary_map_on_constructor.rs:33:27 + --> tests/ui/unnecessary_map_on_constructor.rs:34:27 | LL | let b: SimpleResult = Ok(x).map(fun); | ^^^^^^^^^^^^^^ help: try: `Ok(fun(x))` error: unnecessary map_err on constructor Err(_) - --> tests/ui/unnecessary_map_on_constructor.rs:34:27 + --> tests/ui/unnecessary_map_on_constructor.rs:36:27 | LL | let c: SimpleResult = Err(err).map_err(notfun); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Err(notfun(err))` error: unnecessary map on constructor Option::Some(_) - --> tests/ui/unnecessary_map_on_constructor.rs:36:13 + --> tests/ui/unnecessary_map_on_constructor.rs:39:13 | LL | let a = Option::Some(x).map(fun); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Option::Some(fun(x))` error: unnecessary map on constructor SimpleResult::Ok(_) - --> tests/ui/unnecessary_map_on_constructor.rs:37:27 + --> tests/ui/unnecessary_map_on_constructor.rs:41:27 | LL | let b: SimpleResult = SimpleResult::Ok(x).map(fun); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `SimpleResult::Ok(fun(x))` error: unnecessary map_err on constructor SimpleResult::Err(_) - --> tests/ui/unnecessary_map_on_constructor.rs:38:27 + --> tests/ui/unnecessary_map_on_constructor.rs:43:27 | LL | let c: SimpleResult = SimpleResult::Err(err).map_err(notfun); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `SimpleResult::Err(notfun(err))` error: unnecessary map on constructor Ok(_) - --> tests/ui/unnecessary_map_on_constructor.rs:39:52 + --> tests/ui/unnecessary_map_on_constructor.rs:45:52 | LL | let b: std::result::Result = Ok(x).map(fun); | ^^^^^^^^^^^^^^ help: try: `Ok(fun(x))` error: unnecessary map_err on constructor Err(_) - --> tests/ui/unnecessary_map_on_constructor.rs:40:52 + --> tests/ui/unnecessary_map_on_constructor.rs:47:52 | LL | let c: std::result::Result = Err(err).map_err(notfun); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Err(notfun(err))` diff --git a/tests/ui/unnecessary_map_or.fixed b/tests/ui/unnecessary_map_or.fixed index 5a6e77a06b8f..3c7243972845 100644 --- a/tests/ui/unnecessary_map_or.fixed +++ b/tests/ui/unnecessary_map_or.fixed @@ -11,24 +11,39 @@ extern crate proc_macros; fn main() { // should trigger let _ = Some(5) == Some(5); + //~^ unnecessary_map_or let _ = Some(5) != Some(5); + //~^ unnecessary_map_or let _ = Some(5) == Some(5); let _ = Some(5).is_some_and(|n| { + //~^ unnecessary_map_or let _ = n; 6 >= 5 }); let _ = Some(vec![5]).is_some_and(|n| n == [5]); + //~^ unnecessary_map_or let _ = Some(vec![1]).is_some_and(|n| vec![2] == n); + //~^ unnecessary_map_or let _ = Some(5).is_some_and(|n| n == n); + //~^ unnecessary_map_or let _ = Some(5).is_some_and(|n| n == if 2 > 1 { n } else { 0 }); + //~^ unnecessary_map_or let _ = Ok::, i32>(vec![5]).is_ok_and(|n| n == [5]); + //~^ unnecessary_map_or let _ = Ok::(5) == Ok(5); + //~^ unnecessary_map_or let _ = (Some(5) == Some(5)).then(|| 1); + //~^ unnecessary_map_or let _ = Some(5).is_none_or(|n| n == 5); + //~^ unnecessary_map_or let _ = Some(5).is_none_or(|n| 5 == n); + //~^ unnecessary_map_or let _ = !(Some(5) == Some(5)); + //~^ unnecessary_map_or let _ = (Some(5) == Some(5)) || false; + //~^ unnecessary_map_or let _ = (Some(5) == Some(5)) as usize; + //~^ unnecessary_map_or macro_rules! x { () => { @@ -53,18 +68,23 @@ fn main() { struct S; let r: Result = Ok(3); let _ = r.is_ok_and(|x| x == 7); + //~^ unnecessary_map_or // lint constructs that are not comparaisons as well let func = |_x| true; let r: Result = Ok(3); let _ = r.is_ok_and(func); + //~^ unnecessary_map_or let _ = Some(5).is_some_and(func); + //~^ unnecessary_map_or let _ = Some(5).is_none_or(func); + //~^ unnecessary_map_or #[derive(PartialEq)] struct S2; let r: Result = Ok(4); let _ = r == Ok(8); + //~^ unnecessary_map_or // do not lint `Result::map_or(true, …)` let r: Result = Ok(4); @@ -85,6 +105,8 @@ fn msrv_1_81() { fn with_refs(o: &mut Option) -> bool { o.is_none_or(|n| n > 5) || (o as &Option).is_none_or(|n| n < 5) + //~^ unnecessary_map_or + //~| unnecessary_map_or } struct S; @@ -98,4 +120,13 @@ impl std::ops::Deref for S { fn with_deref(o: &S) -> bool { o.is_none_or(|n| n > 5) + //~^ unnecessary_map_or +} + +fn issue14201(a: Option, b: Option, s: &String) -> bool { + let x = a.is_some_and(|a| a == *s); + //~^ unnecessary_map_or + let y = b.is_none_or(|b| b == *s); + //~^ unnecessary_map_or + x && y } diff --git a/tests/ui/unnecessary_map_or.rs b/tests/ui/unnecessary_map_or.rs index 5ba63121659f..e734a27badab 100644 --- a/tests/ui/unnecessary_map_or.rs +++ b/tests/ui/unnecessary_map_or.rs @@ -11,27 +11,43 @@ extern crate proc_macros; fn main() { // should trigger let _ = Some(5).map_or(false, |n| n == 5); + //~^ unnecessary_map_or let _ = Some(5).map_or(true, |n| n != 5); + //~^ unnecessary_map_or let _ = Some(5).map_or(false, |n| { + //~^ unnecessary_map_or let _ = 1; n == 5 }); let _ = Some(5).map_or(false, |n| { + //~^ unnecessary_map_or let _ = n; 6 >= 5 }); let _ = Some(vec![5]).map_or(false, |n| n == [5]); + //~^ unnecessary_map_or let _ = Some(vec![1]).map_or(false, |n| vec![2] == n); + //~^ unnecessary_map_or let _ = Some(5).map_or(false, |n| n == n); + //~^ unnecessary_map_or let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 }); + //~^ unnecessary_map_or let _ = Ok::, i32>(vec![5]).map_or(false, |n| n == [5]); + //~^ unnecessary_map_or let _ = Ok::(5).map_or(false, |n| n == 5); + //~^ unnecessary_map_or let _ = Some(5).map_or(false, |n| n == 5).then(|| 1); + //~^ unnecessary_map_or let _ = Some(5).map_or(true, |n| n == 5); + //~^ unnecessary_map_or let _ = Some(5).map_or(true, |n| 5 == n); + //~^ unnecessary_map_or let _ = !Some(5).map_or(false, |n| n == 5); + //~^ unnecessary_map_or let _ = Some(5).map_or(false, |n| n == 5) || false; + //~^ unnecessary_map_or let _ = Some(5).map_or(false, |n| n == 5) as usize; + //~^ unnecessary_map_or macro_rules! x { () => { @@ -56,18 +72,23 @@ fn main() { struct S; let r: Result = Ok(3); let _ = r.map_or(false, |x| x == 7); + //~^ unnecessary_map_or // lint constructs that are not comparaisons as well let func = |_x| true; let r: Result = Ok(3); let _ = r.map_or(false, func); + //~^ unnecessary_map_or let _ = Some(5).map_or(false, func); + //~^ unnecessary_map_or let _ = Some(5).map_or(true, func); + //~^ unnecessary_map_or #[derive(PartialEq)] struct S2; let r: Result = Ok(4); let _ = r.map_or(false, |x| x == 8); + //~^ unnecessary_map_or // do not lint `Result::map_or(true, …)` let r: Result = Ok(4); @@ -88,6 +109,8 @@ fn msrv_1_81() { fn with_refs(o: &mut Option) -> bool { o.map_or(true, |n| n > 5) || (o as &Option).map_or(true, |n| n < 5) + //~^ unnecessary_map_or + //~| unnecessary_map_or } struct S; @@ -101,4 +124,13 @@ impl std::ops::Deref for S { fn with_deref(o: &S) -> bool { o.map_or(true, |n| n > 5) + //~^ unnecessary_map_or +} + +fn issue14201(a: Option, b: Option, s: &String) -> bool { + let x = a.map_or(false, |a| a == *s); + //~^ unnecessary_map_or + let y = b.map_or(true, |b| b == *s); + //~^ unnecessary_map_or + x && y } diff --git a/tests/ui/unnecessary_map_or.stderr b/tests/ui/unnecessary_map_or.stderr index 9f38b8c8d93a..0f9466a6a6b3 100644 --- a/tests/ui/unnecessary_map_or.stderr +++ b/tests/ui/unnecessary_map_or.stderr @@ -13,7 +13,7 @@ LL + let _ = Some(5) == Some(5); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:14:13 + --> tests/ui/unnecessary_map_or.rs:15:13 | LL | let _ = Some(5).map_or(true, |n| n != 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,10 +25,11 @@ LL + let _ = Some(5) != Some(5); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:15:13 + --> tests/ui/unnecessary_map_or.rs:17:13 | LL | let _ = Some(5).map_or(false, |n| { | _____________^ +LL | | LL | | let _ = 1; LL | | n == 5 LL | | }); @@ -37,6 +38,7 @@ LL | | }); help: use a standard comparison instead | LL - let _ = Some(5).map_or(false, |n| { +LL - LL - let _ = 1; LL - n == 5 LL - }); @@ -44,10 +46,11 @@ LL + let _ = Some(5) == Some(5); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:19:13 + --> tests/ui/unnecessary_map_or.rs:22:13 | LL | let _ = Some(5).map_or(false, |n| { | _____________^ +LL | | LL | | let _ = n; LL | | 6 >= 5 LL | | }); @@ -60,7 +63,7 @@ LL + let _ = Some(5).is_some_and(|n| { | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:23:13 + --> tests/ui/unnecessary_map_or.rs:27:13 | LL | let _ = Some(vec![5]).map_or(false, |n| n == [5]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -72,7 +75,7 @@ LL + let _ = Some(vec![5]).is_some_and(|n| n == [5]); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:24:13 + --> tests/ui/unnecessary_map_or.rs:29:13 | LL | let _ = Some(vec![1]).map_or(false, |n| vec![2] == n); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -84,7 +87,7 @@ LL + let _ = Some(vec![1]).is_some_and(|n| vec![2] == n); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:25:13 + --> tests/ui/unnecessary_map_or.rs:31:13 | LL | let _ = Some(5).map_or(false, |n| n == n); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -96,7 +99,7 @@ LL + let _ = Some(5).is_some_and(|n| n == n); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:26:13 + --> tests/ui/unnecessary_map_or.rs:33:13 | LL | let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -108,7 +111,7 @@ LL + let _ = Some(5).is_some_and(|n| n == if 2 > 1 { n } else { 0 }); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:27:13 + --> tests/ui/unnecessary_map_or.rs:35:13 | LL | let _ = Ok::, i32>(vec![5]).map_or(false, |n| n == [5]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -120,7 +123,7 @@ LL + let _ = Ok::, i32>(vec![5]).is_ok_and(|n| n == [5]); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:28:13 + --> tests/ui/unnecessary_map_or.rs:37:13 | LL | let _ = Ok::(5).map_or(false, |n| n == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -132,7 +135,7 @@ LL + let _ = Ok::(5) == Ok(5); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:29:13 + --> tests/ui/unnecessary_map_or.rs:39:13 | LL | let _ = Some(5).map_or(false, |n| n == 5).then(|| 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -144,7 +147,7 @@ LL + let _ = (Some(5) == Some(5)).then(|| 1); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:30:13 + --> tests/ui/unnecessary_map_or.rs:41:13 | LL | let _ = Some(5).map_or(true, |n| n == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -156,7 +159,7 @@ LL + let _ = Some(5).is_none_or(|n| n == 5); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:31:13 + --> tests/ui/unnecessary_map_or.rs:43:13 | LL | let _ = Some(5).map_or(true, |n| 5 == n); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -168,7 +171,7 @@ LL + let _ = Some(5).is_none_or(|n| 5 == n); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:32:14 + --> tests/ui/unnecessary_map_or.rs:45:14 | LL | let _ = !Some(5).map_or(false, |n| n == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -180,7 +183,7 @@ LL + let _ = !(Some(5) == Some(5)); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:33:13 + --> tests/ui/unnecessary_map_or.rs:47:13 | LL | let _ = Some(5).map_or(false, |n| n == 5) || false; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -192,7 +195,7 @@ LL + let _ = (Some(5) == Some(5)) || false; | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:34:13 + --> tests/ui/unnecessary_map_or.rs:49:13 | LL | let _ = Some(5).map_or(false, |n| n == 5) as usize; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -204,7 +207,7 @@ LL + let _ = (Some(5) == Some(5)) as usize; | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:58:13 + --> tests/ui/unnecessary_map_or.rs:74:13 | LL | let _ = r.map_or(false, |x| x == 7); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -216,7 +219,7 @@ LL + let _ = r.is_ok_and(|x| x == 7); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:63:13 + --> tests/ui/unnecessary_map_or.rs:80:13 | LL | let _ = r.map_or(false, func); | ^^^^^^^^^^^^^^^^^^^^^ @@ -228,7 +231,7 @@ LL + let _ = r.is_ok_and(func); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:64:13 + --> tests/ui/unnecessary_map_or.rs:82:13 | LL | let _ = Some(5).map_or(false, func); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -240,7 +243,7 @@ LL + let _ = Some(5).is_some_and(func); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:65:13 + --> tests/ui/unnecessary_map_or.rs:84:13 | LL | let _ = Some(5).map_or(true, func); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -252,7 +255,7 @@ LL + let _ = Some(5).is_none_or(func); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:70:13 + --> tests/ui/unnecessary_map_or.rs:90:13 | LL | let _ = r.map_or(false, |x| x == 8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -264,7 +267,7 @@ LL + let _ = r == Ok(8); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:90:5 + --> tests/ui/unnecessary_map_or.rs:111:5 | LL | o.map_or(true, |n| n > 5) || (o as &Option).map_or(true, |n| n < 5) | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -276,7 +279,7 @@ LL + o.is_none_or(|n| n > 5) || (o as &Option).map_or(true, |n| n < 5) | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:90:34 + --> tests/ui/unnecessary_map_or.rs:111:34 | LL | o.map_or(true, |n| n > 5) || (o as &Option).map_or(true, |n| n < 5) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -288,7 +291,7 @@ LL + o.map_or(true, |n| n > 5) || (o as &Option).is_none_or(|n| n < 5) | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:103:5 + --> tests/ui/unnecessary_map_or.rs:126:5 | LL | o.map_or(true, |n| n > 5) | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -299,5 +302,29 @@ LL - o.map_or(true, |n| n > 5) LL + o.is_none_or(|n| n > 5) | -error: aborting due to 24 previous errors +error: this `map_or` can be simplified + --> tests/ui/unnecessary_map_or.rs:131:13 + | +LL | let x = a.map_or(false, |a| a == *s); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use is_some_and instead + | +LL - let x = a.map_or(false, |a| a == *s); +LL + let x = a.is_some_and(|a| a == *s); + | + +error: this `map_or` can be simplified + --> tests/ui/unnecessary_map_or.rs:133:13 + | +LL | let y = b.map_or(true, |b| b == *s); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use is_none_or instead + | +LL - let y = b.map_or(true, |b| b == *s); +LL + let y = b.is_none_or(|b| b == *s); + | + +error: aborting due to 26 previous errors diff --git a/tests/ui/unnecessary_min_or_max.fixed b/tests/ui/unnecessary_min_or_max.fixed index 1f3e131516ce..2650cae5baf4 100644 --- a/tests/ui/unnecessary_min_or_max.fixed +++ b/tests/ui/unnecessary_min_or_max.fixed @@ -11,30 +11,47 @@ const X: i32 = 1; fn main() { // Both are Literals let _ = (-6_i32); + //~^ unnecessary_min_or_max let _ = 9; + //~^ unnecessary_min_or_max let _ = 6; + //~^ unnecessary_min_or_max let _ = 9_u32; + //~^ unnecessary_min_or_max let _ = 6; + //~^ unnecessary_min_or_max let _ = 7_u8; + //~^ unnecessary_min_or_max let x: u32 = 42; // unsigned with zero let _ = 0; + //~^ unnecessary_min_or_max let _ = x; + //~^ unnecessary_min_or_max let _ = 0_u32; + //~^ unnecessary_min_or_max let _ = x; + //~^ unnecessary_min_or_max let x: i32 = 42; // signed MIN let _ = i32::MIN; + //~^ unnecessary_min_or_max let _ = x; + //~^ unnecessary_min_or_max let _ = i32::MIN; + //~^ unnecessary_min_or_max let _ = x; + //~^ unnecessary_min_or_max let _ = i32::MIN - 0; + //~^ unnecessary_min_or_max let _ = x; + //~^ unnecessary_min_or_max let _ = i32::MIN - 0; + //~^ unnecessary_min_or_max // The below cases shouldn't be lint let mut min = u32::MAX; diff --git a/tests/ui/unnecessary_min_or_max.rs b/tests/ui/unnecessary_min_or_max.rs index 58356b9d49e7..2f3c480b3d15 100644 --- a/tests/ui/unnecessary_min_or_max.rs +++ b/tests/ui/unnecessary_min_or_max.rs @@ -11,30 +11,47 @@ const X: i32 = 1; fn main() { // Both are Literals let _ = (-6_i32).min(9); + //~^ unnecessary_min_or_max let _ = (-6_i32).max(9); + //~^ unnecessary_min_or_max let _ = 9_u32.min(6); + //~^ unnecessary_min_or_max let _ = 9_u32.max(6); + //~^ unnecessary_min_or_max let _ = 6.min(7_u8); + //~^ unnecessary_min_or_max let _ = 6.max(7_u8); + //~^ unnecessary_min_or_max let x: u32 = 42; // unsigned with zero let _ = 0.min(x); + //~^ unnecessary_min_or_max let _ = 0.max(x); + //~^ unnecessary_min_or_max let _ = x.min(0_u32); + //~^ unnecessary_min_or_max let _ = x.max(0_u32); + //~^ unnecessary_min_or_max let x: i32 = 42; // signed MIN let _ = i32::MIN.min(x); + //~^ unnecessary_min_or_max let _ = i32::MIN.max(x); + //~^ unnecessary_min_or_max let _ = x.min(i32::MIN); + //~^ unnecessary_min_or_max let _ = x.max(i32::MIN); + //~^ unnecessary_min_or_max let _ = x.min(i32::MIN - 0); + //~^ unnecessary_min_or_max let _ = x.max(i32::MIN); + //~^ unnecessary_min_or_max let _ = x.min(i32::MIN - 0); + //~^ unnecessary_min_or_max // The below cases shouldn't be lint let mut min = u32::MAX; diff --git a/tests/ui/unnecessary_min_or_max.stderr b/tests/ui/unnecessary_min_or_max.stderr index f5cd31fbaf24..dfe6910dfa5c 100644 --- a/tests/ui/unnecessary_min_or_max.stderr +++ b/tests/ui/unnecessary_min_or_max.stderr @@ -8,97 +8,97 @@ LL | let _ = (-6_i32).min(9); = help: to override `-D warnings` add `#[allow(clippy::unnecessary_min_or_max)]` error: `(-6_i32)` is never greater than `9` and has therefore no effect - --> tests/ui/unnecessary_min_or_max.rs:14:13 + --> tests/ui/unnecessary_min_or_max.rs:15:13 | LL | let _ = (-6_i32).max(9); | ^^^^^^^^^^^^^^^ help: try: `9` error: `9_u32` is never smaller than `6` and has therefore no effect - --> tests/ui/unnecessary_min_or_max.rs:15:13 + --> tests/ui/unnecessary_min_or_max.rs:17:13 | LL | let _ = 9_u32.min(6); | ^^^^^^^^^^^^ help: try: `6` error: `9_u32` is never smaller than `6` and has therefore no effect - --> tests/ui/unnecessary_min_or_max.rs:16:13 + --> tests/ui/unnecessary_min_or_max.rs:19:13 | LL | let _ = 9_u32.max(6); | ^^^^^^^^^^^^ help: try: `9_u32` error: `6` is never greater than `7_u8` and has therefore no effect - --> tests/ui/unnecessary_min_or_max.rs:17:13 + --> tests/ui/unnecessary_min_or_max.rs:21:13 | LL | let _ = 6.min(7_u8); | ^^^^^^^^^^^ help: try: `6` error: `6` is never greater than `7_u8` and has therefore no effect - --> tests/ui/unnecessary_min_or_max.rs:18:13 + --> tests/ui/unnecessary_min_or_max.rs:23:13 | LL | let _ = 6.max(7_u8); | ^^^^^^^^^^^ help: try: `7_u8` error: `0` is never greater than `x` and has therefore no effect - --> tests/ui/unnecessary_min_or_max.rs:22:13 + --> tests/ui/unnecessary_min_or_max.rs:28:13 | LL | let _ = 0.min(x); | ^^^^^^^^ help: try: `0` error: `0` is never greater than `x` and has therefore no effect - --> tests/ui/unnecessary_min_or_max.rs:23:13 + --> tests/ui/unnecessary_min_or_max.rs:30:13 | LL | let _ = 0.max(x); | ^^^^^^^^ help: try: `x` error: `x` is never smaller than `0_u32` and has therefore no effect - --> tests/ui/unnecessary_min_or_max.rs:24:13 + --> tests/ui/unnecessary_min_or_max.rs:32:13 | LL | let _ = x.min(0_u32); | ^^^^^^^^^^^^ help: try: `0_u32` error: `x` is never smaller than `0_u32` and has therefore no effect - --> tests/ui/unnecessary_min_or_max.rs:25:13 + --> tests/ui/unnecessary_min_or_max.rs:34:13 | LL | let _ = x.max(0_u32); | ^^^^^^^^^^^^ help: try: `x` error: `i32::MIN` is never greater than `x` and has therefore no effect - --> tests/ui/unnecessary_min_or_max.rs:29:13 + --> tests/ui/unnecessary_min_or_max.rs:39:13 | LL | let _ = i32::MIN.min(x); | ^^^^^^^^^^^^^^^ help: try: `i32::MIN` error: `i32::MIN` is never greater than `x` and has therefore no effect - --> tests/ui/unnecessary_min_or_max.rs:30:13 + --> tests/ui/unnecessary_min_or_max.rs:41:13 | LL | let _ = i32::MIN.max(x); | ^^^^^^^^^^^^^^^ help: try: `x` error: `x` is never smaller than `i32::MIN` and has therefore no effect - --> tests/ui/unnecessary_min_or_max.rs:31:13 + --> tests/ui/unnecessary_min_or_max.rs:43:13 | LL | let _ = x.min(i32::MIN); | ^^^^^^^^^^^^^^^ help: try: `i32::MIN` error: `x` is never smaller than `i32::MIN` and has therefore no effect - --> tests/ui/unnecessary_min_or_max.rs:32:13 + --> tests/ui/unnecessary_min_or_max.rs:45:13 | LL | let _ = x.max(i32::MIN); | ^^^^^^^^^^^^^^^ help: try: `x` error: `x` is never smaller than `i32::MIN - 0` and has therefore no effect - --> tests/ui/unnecessary_min_or_max.rs:34:13 + --> tests/ui/unnecessary_min_or_max.rs:48:13 | LL | let _ = x.min(i32::MIN - 0); | ^^^^^^^^^^^^^^^^^^^ help: try: `i32::MIN - 0` error: `x` is never smaller than `i32::MIN` and has therefore no effect - --> tests/ui/unnecessary_min_or_max.rs:35:13 + --> tests/ui/unnecessary_min_or_max.rs:50:13 | LL | let _ = x.max(i32::MIN); | ^^^^^^^^^^^^^^^ help: try: `x` error: `x` is never smaller than `i32::MIN - 0` and has therefore no effect - --> tests/ui/unnecessary_min_or_max.rs:37:13 + --> tests/ui/unnecessary_min_or_max.rs:53:13 | LL | let _ = x.min(i32::MIN - 0); | ^^^^^^^^^^^^^^^^^^^ help: try: `i32::MIN - 0` diff --git a/tests/ui/unnecessary_operation.fixed b/tests/ui/unnecessary_operation.fixed index 006f123cbcdf..05dfb72f48d2 100644 --- a/tests/ui/unnecessary_operation.fixed +++ b/tests/ui/unnecessary_operation.fixed @@ -68,22 +68,39 @@ where fn main() { get_number(); + //~^ unnecessary_operation get_number(); + //~^ unnecessary_operation get_struct(); + //~^ unnecessary_operation get_number(); + //~^ unnecessary_operation get_number(); + //~^ unnecessary_operation 5;get_number(); + //~^ unnecessary_operation get_number(); + //~^ unnecessary_operation get_number(); + //~^ unnecessary_operation 5;6;get_number(); + //~^ unnecessary_operation get_number(); + //~^ unnecessary_operation get_number(); + //~^ unnecessary_operation 5;get_number(); + //~^ unnecessary_operation 42;get_number(); + //~^ unnecessary_operation assert!([42, 55].len() > get_usize()); + //~^ unnecessary_operation 42;get_number(); + //~^ unnecessary_operation get_number(); + //~^ unnecessary_operation assert!([42; 55].len() > get_usize()); + //~^ unnecessary_operation get_number(); String::from("blah"); @@ -124,5 +141,5 @@ const _: () = { const fn foo() { assert!([42, 55].len() > get_usize()); - //~^ ERROR: unnecessary operation + //~^ unnecessary_operation } diff --git a/tests/ui/unnecessary_operation.rs b/tests/ui/unnecessary_operation.rs index b4067c740741..6ef74c3eb1c1 100644 --- a/tests/ui/unnecessary_operation.rs +++ b/tests/ui/unnecessary_operation.rs @@ -68,26 +68,45 @@ where fn main() { Tuple(get_number()); + //~^ unnecessary_operation Struct { field: get_number() }; + //~^ unnecessary_operation Struct { ..get_struct() }; + //~^ unnecessary_operation Enum::Tuple(get_number()); + //~^ unnecessary_operation Enum::Struct { field: get_number() }; + //~^ unnecessary_operation 5 + get_number(); + //~^ unnecessary_operation *&get_number(); + //~^ unnecessary_operation &get_number(); + //~^ unnecessary_operation (5, 6, get_number()); + //~^ unnecessary_operation get_number()..; + //~^ unnecessary_operation ..get_number(); + //~^ unnecessary_operation 5..get_number(); + //~^ unnecessary_operation [42, get_number()]; + //~^ unnecessary_operation [42, 55][get_usize()]; + //~^ unnecessary_operation (42, get_number()).1; + //~^ unnecessary_operation [get_number(); 55]; + //~^ unnecessary_operation [42; 55][get_usize()]; + //~^ unnecessary_operation { + //~^ unnecessary_operation get_number() }; FooString { + //~^ unnecessary_operation s: String::from("blah"), }; @@ -128,5 +147,5 @@ const _: () = { const fn foo() { [42, 55][get_usize()]; - //~^ ERROR: unnecessary operation + //~^ unnecessary_operation } diff --git a/tests/ui/unnecessary_operation.stderr b/tests/ui/unnecessary_operation.stderr index 036a9a44bbad..eb98af09e7a3 100644 --- a/tests/ui/unnecessary_operation.stderr +++ b/tests/ui/unnecessary_operation.stderr @@ -8,119 +8,121 @@ LL | Tuple(get_number()); = help: to override `-D warnings` add `#[allow(clippy::unnecessary_operation)]` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:71:5 + --> tests/ui/unnecessary_operation.rs:72:5 | LL | Struct { field: get_number() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:72:5 + --> tests/ui/unnecessary_operation.rs:74:5 | LL | Struct { ..get_struct() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_struct();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:73:5 + --> tests/ui/unnecessary_operation.rs:76:5 | LL | Enum::Tuple(get_number()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:74:5 + --> tests/ui/unnecessary_operation.rs:78:5 | LL | Enum::Struct { field: get_number() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:75:5 + --> tests/ui/unnecessary_operation.rs:80:5 | LL | 5 + get_number(); | ^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:76:5 + --> tests/ui/unnecessary_operation.rs:82:5 | LL | *&get_number(); | ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:77:5 + --> tests/ui/unnecessary_operation.rs:84:5 | LL | &get_number(); | ^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:78:5 + --> tests/ui/unnecessary_operation.rs:86:5 | LL | (5, 6, get_number()); | ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;6;get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:79:5 + --> tests/ui/unnecessary_operation.rs:88:5 | LL | get_number()..; | ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:80:5 + --> tests/ui/unnecessary_operation.rs:90:5 | LL | ..get_number(); | ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:81:5 + --> tests/ui/unnecessary_operation.rs:92:5 | LL | 5..get_number(); | ^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:82:5 + --> tests/ui/unnecessary_operation.rs:94:5 | LL | [42, get_number()]; | ^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42;get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:83:5 + --> tests/ui/unnecessary_operation.rs:96:5 | LL | [42, 55][get_usize()]; | ^^^^^^^^^^^^^^^^^^^^^^ help: statement can be written as: `assert!([42, 55].len() > get_usize());` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:84:5 + --> tests/ui/unnecessary_operation.rs:98:5 | LL | (42, get_number()).1; | ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42;get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:85:5 + --> tests/ui/unnecessary_operation.rs:100:5 | LL | [get_number(); 55]; | ^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:86:5 + --> tests/ui/unnecessary_operation.rs:102:5 | LL | [42; 55][get_usize()]; | ^^^^^^^^^^^^^^^^^^^^^^ help: statement can be written as: `assert!([42; 55].len() > get_usize());` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:87:5 + --> tests/ui/unnecessary_operation.rs:104:5 | LL | / { +LL | | LL | | get_number() LL | | }; | |______^ help: statement can be reduced to: `get_number();` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:90:5 + --> tests/ui/unnecessary_operation.rs:108:5 | LL | / FooString { +LL | | LL | | s: String::from("blah"), LL | | }; | |______^ help: statement can be reduced to: `String::from("blah");` error: unnecessary operation - --> tests/ui/unnecessary_operation.rs:130:5 + --> tests/ui/unnecessary_operation.rs:149:5 | LL | [42, 55][get_usize()]; | ^^^^^^^^^^^^^^^^^^^^^^ help: statement can be written as: `assert!([42, 55].len() > get_usize());` diff --git a/tests/ui/unnecessary_os_str_debug_formatting.rs b/tests/ui/unnecessary_os_str_debug_formatting.rs new file mode 100644 index 000000000000..12663ec9a528 --- /dev/null +++ b/tests/ui/unnecessary_os_str_debug_formatting.rs @@ -0,0 +1,22 @@ +#![warn(clippy::unnecessary_debug_formatting)] + +use std::ffi::{OsStr, OsString}; + +fn main() { + let os_str = OsStr::new("abc"); + let os_string = os_str.to_os_string(); + + // negative tests + println!("{}", os_str.display()); + println!("{}", os_string.display()); + + // positive tests + println!("{:?}", os_str); //~ unnecessary_debug_formatting + println!("{:?}", os_string); //~ unnecessary_debug_formatting + + println!("{os_str:?}"); //~ unnecessary_debug_formatting + println!("{os_string:?}"); //~ unnecessary_debug_formatting + + let _: String = format!("{:?}", os_str); //~ unnecessary_debug_formatting + let _: String = format!("{:?}", os_string); //~ unnecessary_debug_formatting +} diff --git a/tests/ui/unnecessary_os_str_debug_formatting.stderr b/tests/ui/unnecessary_os_str_debug_formatting.stderr new file mode 100644 index 000000000000..001309ab817a --- /dev/null +++ b/tests/ui/unnecessary_os_str_debug_formatting.stderr @@ -0,0 +1,58 @@ +error: unnecessary `Debug` formatting in `println!` args + --> tests/ui/unnecessary_os_str_debug_formatting.rs:14:22 + | +LL | println!("{:?}", os_str); + | ^^^^^^ + | + = help: use `Display` formatting and change this to `os_str.display()` + = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed + = note: `-D clippy::unnecessary-debug-formatting` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::unnecessary_debug_formatting)]` + +error: unnecessary `Debug` formatting in `println!` args + --> tests/ui/unnecessary_os_str_debug_formatting.rs:15:22 + | +LL | println!("{:?}", os_string); + | ^^^^^^^^^ + | + = help: use `Display` formatting and change this to `os_string.display()` + = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed + +error: unnecessary `Debug` formatting in `println!` args + --> tests/ui/unnecessary_os_str_debug_formatting.rs:17:16 + | +LL | println!("{os_str:?}"); + | ^^^^^^ + | + = help: use `Display` formatting and change this to `os_str.display()` + = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed + +error: unnecessary `Debug` formatting in `println!` args + --> tests/ui/unnecessary_os_str_debug_formatting.rs:18:16 + | +LL | println!("{os_string:?}"); + | ^^^^^^^^^ + | + = help: use `Display` formatting and change this to `os_string.display()` + = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed + +error: unnecessary `Debug` formatting in `format!` args + --> tests/ui/unnecessary_os_str_debug_formatting.rs:20:37 + | +LL | let _: String = format!("{:?}", os_str); + | ^^^^^^ + | + = help: use `Display` formatting and change this to `os_str.display()` + = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed + +error: unnecessary `Debug` formatting in `format!` args + --> tests/ui/unnecessary_os_str_debug_formatting.rs:21:37 + | +LL | let _: String = format!("{:?}", os_string); + | ^^^^^^^^^ + | + = help: use `Display` formatting and change this to `os_string.display()` + = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed + +error: aborting due to 6 previous errors + diff --git a/tests/ui/unnecessary_owned_empty_strings.fixed b/tests/ui/unnecessary_owned_empty_strings.fixed index 75cd63db8a1a..dc0e495be30f 100644 --- a/tests/ui/unnecessary_owned_empty_strings.fixed +++ b/tests/ui/unnecessary_owned_empty_strings.fixed @@ -8,10 +8,12 @@ fn ref_string_argument(_value: &String) {} fn main() { // should be linted ref_str_argument(""); + //~^ unnecessary_owned_empty_strings // should be linted #[allow(clippy::manual_string_new)] ref_str_argument(""); + //~^ unnecessary_owned_empty_strings // should not be linted ref_str_argument(""); diff --git a/tests/ui/unnecessary_owned_empty_strings.rs b/tests/ui/unnecessary_owned_empty_strings.rs index 2edc0bd86d38..e2c5de447444 100644 --- a/tests/ui/unnecessary_owned_empty_strings.rs +++ b/tests/ui/unnecessary_owned_empty_strings.rs @@ -8,10 +8,12 @@ fn ref_string_argument(_value: &String) {} fn main() { // should be linted ref_str_argument(&String::new()); + //~^ unnecessary_owned_empty_strings // should be linted #[allow(clippy::manual_string_new)] ref_str_argument(&String::from("")); + //~^ unnecessary_owned_empty_strings // should not be linted ref_str_argument(""); diff --git a/tests/ui/unnecessary_owned_empty_strings.stderr b/tests/ui/unnecessary_owned_empty_strings.stderr index 1820ea4ef5d8..8bcf3ee88765 100644 --- a/tests/ui/unnecessary_owned_empty_strings.stderr +++ b/tests/ui/unnecessary_owned_empty_strings.stderr @@ -8,7 +8,7 @@ LL | ref_str_argument(&String::new()); = help: to override `-D warnings` add `#[allow(clippy::unnecessary_owned_empty_strings)]` error: usage of `&String::from("")` for a function expecting a `&str` argument - --> tests/ui/unnecessary_owned_empty_strings.rs:14:22 + --> tests/ui/unnecessary_owned_empty_strings.rs:15:22 | LL | ref_str_argument(&String::from("")); | ^^^^^^^^^^^^^^^^^ help: try: `""` diff --git a/tests/ui/unnecessary_path_debug_formatting.rs b/tests/ui/unnecessary_path_debug_formatting.rs new file mode 100644 index 000000000000..02adeece2809 --- /dev/null +++ b/tests/ui/unnecessary_path_debug_formatting.rs @@ -0,0 +1,43 @@ +#![warn(clippy::unnecessary_debug_formatting)] + +use std::ffi::{OsStr, OsString}; +use std::ops::Deref; +use std::path::{Path, PathBuf}; + +struct DerefPath<'a> { + path: &'a Path, +} + +impl Deref for DerefPath<'_> { + type Target = Path; + fn deref(&self) -> &Self::Target { + self.path + } +} + +fn main() { + let path = Path::new("/a/b/c"); + let path_buf = path.to_path_buf(); + let os_str = OsStr::new("abc"); + let os_string = os_str.to_os_string(); + + // negative tests + println!("{}", path.display()); + println!("{}", path_buf.display()); + + // positive tests + println!("{:?}", os_str); //~ unnecessary_debug_formatting + println!("{:?}", os_string); //~ unnecessary_debug_formatting + + println!("{:?}", path); //~ unnecessary_debug_formatting + println!("{:?}", path_buf); //~ unnecessary_debug_formatting + + println!("{path:?}"); //~ unnecessary_debug_formatting + println!("{path_buf:?}"); //~ unnecessary_debug_formatting + + let _: String = format!("{:?}", path); //~ unnecessary_debug_formatting + let _: String = format!("{:?}", path_buf); //~ unnecessary_debug_formatting + + let deref_path = DerefPath { path }; + println!("{:?}", &*deref_path); //~ unnecessary_debug_formatting +} diff --git a/tests/ui/unnecessary_path_debug_formatting.stderr b/tests/ui/unnecessary_path_debug_formatting.stderr new file mode 100644 index 000000000000..f12fa72c84b3 --- /dev/null +++ b/tests/ui/unnecessary_path_debug_formatting.stderr @@ -0,0 +1,85 @@ +error: unnecessary `Debug` formatting in `println!` args + --> tests/ui/unnecessary_path_debug_formatting.rs:29:22 + | +LL | println!("{:?}", os_str); + | ^^^^^^ + | + = help: use `Display` formatting and change this to `os_str.display()` + = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed + = note: `-D clippy::unnecessary-debug-formatting` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::unnecessary_debug_formatting)]` + +error: unnecessary `Debug` formatting in `println!` args + --> tests/ui/unnecessary_path_debug_formatting.rs:30:22 + | +LL | println!("{:?}", os_string); + | ^^^^^^^^^ + | + = help: use `Display` formatting and change this to `os_string.display()` + = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed + +error: unnecessary `Debug` formatting in `println!` args + --> tests/ui/unnecessary_path_debug_formatting.rs:32:22 + | +LL | println!("{:?}", path); + | ^^^^ + | + = help: use `Display` formatting and change this to `path.display()` + = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed + +error: unnecessary `Debug` formatting in `println!` args + --> tests/ui/unnecessary_path_debug_formatting.rs:33:22 + | +LL | println!("{:?}", path_buf); + | ^^^^^^^^ + | + = help: use `Display` formatting and change this to `path_buf.display()` + = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed + +error: unnecessary `Debug` formatting in `println!` args + --> tests/ui/unnecessary_path_debug_formatting.rs:35:16 + | +LL | println!("{path:?}"); + | ^^^^ + | + = help: use `Display` formatting and change this to `path.display()` + = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed + +error: unnecessary `Debug` formatting in `println!` args + --> tests/ui/unnecessary_path_debug_formatting.rs:36:16 + | +LL | println!("{path_buf:?}"); + | ^^^^^^^^ + | + = help: use `Display` formatting and change this to `path_buf.display()` + = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed + +error: unnecessary `Debug` formatting in `format!` args + --> tests/ui/unnecessary_path_debug_formatting.rs:38:37 + | +LL | let _: String = format!("{:?}", path); + | ^^^^ + | + = help: use `Display` formatting and change this to `path.display()` + = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed + +error: unnecessary `Debug` formatting in `format!` args + --> tests/ui/unnecessary_path_debug_formatting.rs:39:37 + | +LL | let _: String = format!("{:?}", path_buf); + | ^^^^^^^^ + | + = help: use `Display` formatting and change this to `path_buf.display()` + = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed + +error: unnecessary `Debug` formatting in `println!` args + --> tests/ui/unnecessary_path_debug_formatting.rs:42:22 + | +LL | println!("{:?}", &*deref_path); + | ^^^^^^^^^^^^ + | + = help: use `Display` formatting and change this to `&*deref_path.display()` + = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed + +error: aborting due to 9 previous errors + diff --git a/tests/ui/unnecessary_result_map_or_else.fixed b/tests/ui/unnecessary_result_map_or_else.fixed index 224e0b52d75d..5d7e3fa355fd 100644 --- a/tests/ui/unnecessary_result_map_or_else.fixed +++ b/tests/ui/unnecessary_result_map_or_else.fixed @@ -3,16 +3,19 @@ fn main() { let x: Result<(), ()> = Ok(()); - x.unwrap_or_else(|err| err); //~ ERROR: unused "map closure" when calling + x.unwrap_or_else(|err| err); + //~^ unnecessary_result_map_or_else // Type ascribtion. let x: Result<(), ()> = Ok(()); - x.unwrap_or_else(|err: ()| err); //~ ERROR: unused "map closure" when calling + x.unwrap_or_else(|err: ()| err); + //~^ unnecessary_result_map_or_else // Auto-deref. let y = String::new(); let x: Result<&String, &String> = Ok(&y); - let y: &str = x.unwrap_or_else(|err| err); //~ ERROR: unused "map closure" when calling + let y: &str = x.unwrap_or_else(|err| err); + //~^ unnecessary_result_map_or_else // Temporary variable. let x: Result<(), ()> = Ok(()); diff --git a/tests/ui/unnecessary_result_map_or_else.rs b/tests/ui/unnecessary_result_map_or_else.rs index 4fe950a4cfa6..d2bab0f9d9c1 100644 --- a/tests/ui/unnecessary_result_map_or_else.rs +++ b/tests/ui/unnecessary_result_map_or_else.rs @@ -3,21 +3,24 @@ fn main() { let x: Result<(), ()> = Ok(()); - x.map_or_else(|err| err, |n| n); //~ ERROR: unused "map closure" when calling + x.map_or_else(|err| err, |n| n); + //~^ unnecessary_result_map_or_else // Type ascribtion. let x: Result<(), ()> = Ok(()); - x.map_or_else(|err: ()| err, |n: ()| n); //~ ERROR: unused "map closure" when calling + x.map_or_else(|err: ()| err, |n: ()| n); + //~^ unnecessary_result_map_or_else // Auto-deref. let y = String::new(); let x: Result<&String, &String> = Ok(&y); - let y: &str = x.map_or_else(|err| err, |n| n); //~ ERROR: unused "map closure" when calling + let y: &str = x.map_or_else(|err| err, |n| n); + //~^ unnecessary_result_map_or_else // Temporary variable. let x: Result<(), ()> = Ok(()); x.map_or_else( - //~^ ERROR: unused "map closure" when calling + //~^ unnecessary_result_map_or_else |err| err, |n| { let tmp = n; diff --git a/tests/ui/unnecessary_result_map_or_else.stderr b/tests/ui/unnecessary_result_map_or_else.stderr index e3a6dbf8ecd8..e6afa50217cc 100644 --- a/tests/ui/unnecessary_result_map_or_else.stderr +++ b/tests/ui/unnecessary_result_map_or_else.stderr @@ -8,19 +8,19 @@ LL | x.map_or_else(|err| err, |n| n); = help: to override `-D warnings` add `#[allow(clippy::unnecessary_result_map_or_else)]` error: unused "map closure" when calling `Result::map_or_else` value - --> tests/ui/unnecessary_result_map_or_else.rs:10:5 + --> tests/ui/unnecessary_result_map_or_else.rs:11:5 | LL | x.map_or_else(|err: ()| err, |n: ()| n); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `unwrap_or_else`: `x.unwrap_or_else(|err: ()| err)` error: unused "map closure" when calling `Result::map_or_else` value - --> tests/ui/unnecessary_result_map_or_else.rs:15:19 + --> tests/ui/unnecessary_result_map_or_else.rs:17:19 | LL | let y: &str = x.map_or_else(|err| err, |n| n); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `unwrap_or_else`: `x.unwrap_or_else(|err| err)` error: unused "map closure" when calling `Result::map_or_else` value - --> tests/ui/unnecessary_result_map_or_else.rs:19:5 + --> tests/ui/unnecessary_result_map_or_else.rs:22:5 | LL | / x.map_or_else( LL | | diff --git a/tests/ui/unnecessary_safety_comment.rs b/tests/ui/unnecessary_safety_comment.rs index bdc6fa0f46bb..4440089b3633 100644 --- a/tests/ui/unnecessary_safety_comment.rs +++ b/tests/ui/unnecessary_safety_comment.rs @@ -4,19 +4,23 @@ mod unsafe_items_invalid_comment { // SAFETY: const CONST: u32 = 0; - //~^ ERROR: constant item has unnecessary safety comment + //~^ unnecessary_safety_comment + // SAFETY: static STATIC: u32 = 0; - //~^ ERROR: static item has unnecessary safety comment + //~^ unnecessary_safety_comment + // SAFETY: struct Struct; - //~^ ERROR: struct has unnecessary safety comment + //~^ unnecessary_safety_comment + // SAFETY: enum Enum {} - //~^ ERROR: enum has unnecessary safety comment + //~^ unnecessary_safety_comment + // SAFETY: mod module {} - //~^ ERROR: module has unnecessary safety comment + //~^ unnecessary_safety_comment } mod unnecessary_from_macro { @@ -36,6 +40,7 @@ mod unnecessary_from_macro { ($t:ty) => { // Safety: unnecessary impl T for $t {} + //~^ unnecessary_safety_comment }; } @@ -45,15 +50,15 @@ mod unnecessary_from_macro { fn unnecessary_on_stmt_and_expr() -> u32 { // SAFETY: unnecessary let num = 42; - //~^ ERROR: statement has unnecessary safety comment + //~^ unnecessary_safety_comment // SAFETY: unnecessary if num > 24 {} - //~^ ERROR: statement has unnecessary safety comment + //~^ unnecessary_safety_comment // SAFETY: unnecessary 24 - //~^ ERROR: expression has unnecessary safety comment + //~^ unnecessary_safety_comment } mod issue_10084 { diff --git a/tests/ui/unnecessary_safety_comment.stderr b/tests/ui/unnecessary_safety_comment.stderr index 139ed769975b..b56e8b354931 100644 --- a/tests/ui/unnecessary_safety_comment.stderr +++ b/tests/ui/unnecessary_safety_comment.stderr @@ -13,55 +13,55 @@ LL | // SAFETY: = help: to override `-D warnings` add `#[allow(clippy::unnecessary_safety_comment)]` error: static item has unnecessary safety comment - --> tests/ui/unnecessary_safety_comment.rs:9:5 + --> tests/ui/unnecessary_safety_comment.rs:10:5 | LL | static STATIC: u32 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui/unnecessary_safety_comment.rs:8:5 + --> tests/ui/unnecessary_safety_comment.rs:9:5 | LL | // SAFETY: | ^^^^^^^^^^ error: struct has unnecessary safety comment - --> tests/ui/unnecessary_safety_comment.rs:12:5 + --> tests/ui/unnecessary_safety_comment.rs:14:5 | LL | struct Struct; | ^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui/unnecessary_safety_comment.rs:11:5 + --> tests/ui/unnecessary_safety_comment.rs:13:5 | LL | // SAFETY: | ^^^^^^^^^^ error: enum has unnecessary safety comment - --> tests/ui/unnecessary_safety_comment.rs:15:5 + --> tests/ui/unnecessary_safety_comment.rs:18:5 | LL | enum Enum {} | ^^^^^^^^^^^^ | -help: consider removing the safety comment - --> tests/ui/unnecessary_safety_comment.rs:14:5 - | -LL | // SAFETY: - | ^^^^^^^^^^ - -error: module has unnecessary safety comment - --> tests/ui/unnecessary_safety_comment.rs:18:5 - | -LL | mod module {} - | ^^^^^^^^^^^^^ - | help: consider removing the safety comment --> tests/ui/unnecessary_safety_comment.rs:17:5 | LL | // SAFETY: | ^^^^^^^^^^ +error: module has unnecessary safety comment + --> tests/ui/unnecessary_safety_comment.rs:22:5 + | +LL | mod module {} + | ^^^^^^^^^^^^^ + | +help: consider removing the safety comment + --> tests/ui/unnecessary_safety_comment.rs:21:5 + | +LL | // SAFETY: + | ^^^^^^^^^^ + error: impl has unnecessary safety comment - --> tests/ui/unnecessary_safety_comment.rs:38:13 + --> tests/ui/unnecessary_safety_comment.rs:42:13 | LL | impl T for $t {} | ^^^^^^^^^^^^^^^^ @@ -70,44 +70,44 @@ LL | with_safety_comment!(i32); | ------------------------- in this macro invocation | help: consider removing the safety comment - --> tests/ui/unnecessary_safety_comment.rs:37:13 + --> tests/ui/unnecessary_safety_comment.rs:41:13 | LL | // Safety: unnecessary | ^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `with_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: expression has unnecessary safety comment - --> tests/ui/unnecessary_safety_comment.rs:55:5 + --> tests/ui/unnecessary_safety_comment.rs:60:5 | LL | 24 | ^^ | help: consider removing the safety comment - --> tests/ui/unnecessary_safety_comment.rs:54:5 + --> tests/ui/unnecessary_safety_comment.rs:59:5 | LL | // SAFETY: unnecessary | ^^^^^^^^^^^^^^^^^^^^^^ error: statement has unnecessary safety comment - --> tests/ui/unnecessary_safety_comment.rs:47:5 + --> tests/ui/unnecessary_safety_comment.rs:52:5 | LL | let num = 42; | ^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui/unnecessary_safety_comment.rs:46:5 + --> tests/ui/unnecessary_safety_comment.rs:51:5 | LL | // SAFETY: unnecessary | ^^^^^^^^^^^^^^^^^^^^^^ error: statement has unnecessary safety comment - --> tests/ui/unnecessary_safety_comment.rs:51:5 + --> tests/ui/unnecessary_safety_comment.rs:56:5 | LL | if num > 24 {} | ^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui/unnecessary_safety_comment.rs:50:5 + --> tests/ui/unnecessary_safety_comment.rs:55:5 | LL | // SAFETY: unnecessary | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unnecessary_self_imports.fixed b/tests/ui/unnecessary_self_imports.fixed index c265dcd2414f..0fd74705bde0 100644 --- a/tests/ui/unnecessary_self_imports.fixed +++ b/tests/ui/unnecessary_self_imports.fixed @@ -3,7 +3,9 @@ use std::collections::hash_map::{self, *}; use std::fs as alias; +//~^ unnecessary_self_imports use std::io::{self, Read}; use std::rc; +//~^ unnecessary_self_imports fn main() {} diff --git a/tests/ui/unnecessary_self_imports.rs b/tests/ui/unnecessary_self_imports.rs index c3fcf7c951a1..d09c5fcb8caa 100644 --- a/tests/ui/unnecessary_self_imports.rs +++ b/tests/ui/unnecessary_self_imports.rs @@ -3,7 +3,9 @@ use std::collections::hash_map::{self, *}; use std::fs::{self as alias}; +//~^ unnecessary_self_imports use std::io::{self, Read}; use std::rc::{self}; +//~^ unnecessary_self_imports fn main() {} diff --git a/tests/ui/unnecessary_self_imports.stderr b/tests/ui/unnecessary_self_imports.stderr index 9b143b48c9a6..1bb22c46a6c1 100644 --- a/tests/ui/unnecessary_self_imports.stderr +++ b/tests/ui/unnecessary_self_imports.stderr @@ -11,7 +11,7 @@ LL | use std::fs::{self as alias}; = help: to override `-D warnings` add `#[allow(clippy::unnecessary_self_imports)]` error: import ending with `::{self}` - --> tests/ui/unnecessary_self_imports.rs:7:1 + --> tests/ui/unnecessary_self_imports.rs:8:1 | LL | use std::rc::{self}; | ^^^^^^^^^----------- diff --git a/tests/ui/unnecessary_semicolon.edition2021.fixed b/tests/ui/unnecessary_semicolon.edition2021.fixed index 343c88b98155..f10d804c8ccc 100644 --- a/tests/ui/unnecessary_semicolon.edition2021.fixed +++ b/tests/ui/unnecessary_semicolon.edition2021.fixed @@ -27,13 +27,13 @@ fn main() { if a == 2 { println!("This is weird"); } - //~^ ERROR: unnecessary semicolon + //~^ unnecessary_semicolon a.match { 3 => println!("three"), _ => println!("not three"), } - //~^ ERROR: unnecessary semicolon + //~^ unnecessary_semicolon } // This is a problem in edition 2021 and below @@ -45,6 +45,7 @@ fn borrow_issue() { }, None => {}, }; + //~[edition2024]^ unnecessary_semicolon } fn no_borrow_issue(a: u32, b: u32) { @@ -54,6 +55,7 @@ fn no_borrow_issue(a: u32, b: u32) { }, None => {}, } + //~^ unnecessary_semicolon } fn issue14100() -> bool { diff --git a/tests/ui/unnecessary_semicolon.edition2021.stderr b/tests/ui/unnecessary_semicolon.edition2021.stderr index ccff33084172..a3b139f73805 100644 --- a/tests/ui/unnecessary_semicolon.edition2021.stderr +++ b/tests/ui/unnecessary_semicolon.edition2021.stderr @@ -14,7 +14,7 @@ LL | }; | ^ help: remove error: unnecessary semicolon - --> tests/ui/unnecessary_semicolon.rs:56:6 + --> tests/ui/unnecessary_semicolon.rs:57:6 | LL | }; | ^ help: remove diff --git a/tests/ui/unnecessary_semicolon.edition2024.fixed b/tests/ui/unnecessary_semicolon.edition2024.fixed index 1cba5760eb0a..32a3bb9b4081 100644 --- a/tests/ui/unnecessary_semicolon.edition2024.fixed +++ b/tests/ui/unnecessary_semicolon.edition2024.fixed @@ -27,13 +27,13 @@ fn main() { if a == 2 { println!("This is weird"); } - //~^ ERROR: unnecessary semicolon + //~^ unnecessary_semicolon a.match { 3 => println!("three"), _ => println!("not three"), } - //~^ ERROR: unnecessary semicolon + //~^ unnecessary_semicolon } // This is a problem in edition 2021 and below @@ -45,6 +45,7 @@ fn borrow_issue() { }, None => {}, } + //~[edition2024]^ unnecessary_semicolon } fn no_borrow_issue(a: u32, b: u32) { @@ -54,6 +55,7 @@ fn no_borrow_issue(a: u32, b: u32) { }, None => {}, } + //~^ unnecessary_semicolon } fn issue14100() -> bool { diff --git a/tests/ui/unnecessary_semicolon.edition2024.stderr b/tests/ui/unnecessary_semicolon.edition2024.stderr index 4e526af2147d..d5ccae7fdf58 100644 --- a/tests/ui/unnecessary_semicolon.edition2024.stderr +++ b/tests/ui/unnecessary_semicolon.edition2024.stderr @@ -20,7 +20,7 @@ LL | }; | ^ help: remove error: unnecessary semicolon - --> tests/ui/unnecessary_semicolon.rs:56:6 + --> tests/ui/unnecessary_semicolon.rs:57:6 | LL | }; | ^ help: remove diff --git a/tests/ui/unnecessary_semicolon.rs b/tests/ui/unnecessary_semicolon.rs index 6abbbd79aaf2..91b282180224 100644 --- a/tests/ui/unnecessary_semicolon.rs +++ b/tests/ui/unnecessary_semicolon.rs @@ -27,13 +27,13 @@ fn main() { if a == 2 { println!("This is weird"); }; - //~^ ERROR: unnecessary semicolon + //~^ unnecessary_semicolon a.match { 3 => println!("three"), _ => println!("not three"), }; - //~^ ERROR: unnecessary semicolon + //~^ unnecessary_semicolon } // This is a problem in edition 2021 and below @@ -45,6 +45,7 @@ fn borrow_issue() { }, None => {}, }; + //~[edition2024]^ unnecessary_semicolon } fn no_borrow_issue(a: u32, b: u32) { @@ -54,6 +55,7 @@ fn no_borrow_issue(a: u32, b: u32) { }, None => {}, }; + //~^ unnecessary_semicolon } fn issue14100() -> bool { diff --git a/tests/ui/unnecessary_sort_by.fixed b/tests/ui/unnecessary_sort_by.fixed index 6b667e00c978..5255ab173efb 100644 --- a/tests/ui/unnecessary_sort_by.fixed +++ b/tests/ui/unnecessary_sort_by.fixed @@ -10,13 +10,19 @@ fn unnecessary_sort_by() { let mut vec: Vec = vec![3, 6, 1, 2, 5]; // Forward examples vec.sort(); + //~^ unnecessary_sort_by vec.sort_unstable(); + //~^ unnecessary_sort_by vec.sort_by_key(|a| (a + 5).abs()); + //~^ unnecessary_sort_by vec.sort_unstable_by_key(|a| id(-a)); + //~^ unnecessary_sort_by // Reverse examples vec.sort_by(|a, b| b.cmp(a)); // not linted to avoid suggesting `Reverse(b)` which would borrow vec.sort_by_key(|b| std::cmp::Reverse((b + 5).abs())); + //~^ unnecessary_sort_by vec.sort_unstable_by_key(|b| std::cmp::Reverse(id(-b))); + //~^ unnecessary_sort_by // Negative examples (shouldn't be changed) let c = &7; vec.sort_by(|a, b| (b - a).cmp(&(a - b))); @@ -27,7 +33,9 @@ fn unnecessary_sort_by() { // Vectors of references are fine as long as the resulting key does not borrow let mut vec: Vec<&&&isize> = vec![&&&3, &&&6, &&&1, &&&2, &&&5]; vec.sort_by_key(|a| (***a).abs()); + //~^ unnecessary_sort_by vec.sort_unstable_by_key(|a| (***a).abs()); + //~^ unnecessary_sort_by // `Reverse(b)` would borrow in the following cases, don't lint vec.sort_by(|a, b| b.cmp(a)); vec.sort_unstable_by(|a, b| b.cmp(a)); @@ -87,10 +95,14 @@ mod issue_6001 { // Forward args.sort_by_key(|a| a.name()); + //~^ unnecessary_sort_by args.sort_unstable_by_key(|a| a.name()); + //~^ unnecessary_sort_by // Reverse args.sort_by_key(|b| std::cmp::Reverse(b.name())); + //~^ unnecessary_sort_by args.sort_unstable_by_key(|b| std::cmp::Reverse(b.name())); + //~^ unnecessary_sort_by } } diff --git a/tests/ui/unnecessary_sort_by.rs b/tests/ui/unnecessary_sort_by.rs index 0ff20fb9ef28..65db7ca3f137 100644 --- a/tests/ui/unnecessary_sort_by.rs +++ b/tests/ui/unnecessary_sort_by.rs @@ -10,13 +10,19 @@ fn unnecessary_sort_by() { let mut vec: Vec = vec![3, 6, 1, 2, 5]; // Forward examples vec.sort_by(|a, b| a.cmp(b)); + //~^ unnecessary_sort_by vec.sort_unstable_by(|a, b| a.cmp(b)); + //~^ unnecessary_sort_by vec.sort_by(|a, b| (a + 5).abs().cmp(&(b + 5).abs())); + //~^ unnecessary_sort_by vec.sort_unstable_by(|a, b| id(-a).cmp(&id(-b))); + //~^ unnecessary_sort_by // Reverse examples vec.sort_by(|a, b| b.cmp(a)); // not linted to avoid suggesting `Reverse(b)` which would borrow vec.sort_by(|a, b| (b + 5).abs().cmp(&(a + 5).abs())); + //~^ unnecessary_sort_by vec.sort_unstable_by(|a, b| id(-b).cmp(&id(-a))); + //~^ unnecessary_sort_by // Negative examples (shouldn't be changed) let c = &7; vec.sort_by(|a, b| (b - a).cmp(&(a - b))); @@ -27,7 +33,9 @@ fn unnecessary_sort_by() { // Vectors of references are fine as long as the resulting key does not borrow let mut vec: Vec<&&&isize> = vec![&&&3, &&&6, &&&1, &&&2, &&&5]; vec.sort_by(|a, b| (***a).abs().cmp(&(***b).abs())); + //~^ unnecessary_sort_by vec.sort_unstable_by(|a, b| (***a).abs().cmp(&(***b).abs())); + //~^ unnecessary_sort_by // `Reverse(b)` would borrow in the following cases, don't lint vec.sort_by(|a, b| b.cmp(a)); vec.sort_unstable_by(|a, b| b.cmp(a)); @@ -87,10 +95,14 @@ mod issue_6001 { // Forward args.sort_by(|a, b| a.name().cmp(&b.name())); + //~^ unnecessary_sort_by args.sort_unstable_by(|a, b| a.name().cmp(&b.name())); + //~^ unnecessary_sort_by // Reverse args.sort_by(|a, b| b.name().cmp(&a.name())); + //~^ unnecessary_sort_by args.sort_unstable_by(|a, b| b.name().cmp(&a.name())); + //~^ unnecessary_sort_by } } diff --git a/tests/ui/unnecessary_sort_by.stderr b/tests/ui/unnecessary_sort_by.stderr index e2013a4e6f9d..9a38d3746da8 100644 --- a/tests/ui/unnecessary_sort_by.stderr +++ b/tests/ui/unnecessary_sort_by.stderr @@ -8,67 +8,67 @@ LL | vec.sort_by(|a, b| a.cmp(b)); = help: to override `-D warnings` add `#[allow(clippy::unnecessary_sort_by)]` error: consider using `sort` - --> tests/ui/unnecessary_sort_by.rs:13:5 + --> tests/ui/unnecessary_sort_by.rs:14:5 | LL | vec.sort_unstable_by(|a, b| a.cmp(b)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable()` error: consider using `sort_by_key` - --> tests/ui/unnecessary_sort_by.rs:14:5 + --> tests/ui/unnecessary_sort_by.rs:16:5 | LL | vec.sort_by(|a, b| (a + 5).abs().cmp(&(b + 5).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| (a + 5).abs())` error: consider using `sort_by_key` - --> tests/ui/unnecessary_sort_by.rs:15:5 + --> tests/ui/unnecessary_sort_by.rs:18:5 | LL | vec.sort_unstable_by(|a, b| id(-a).cmp(&id(-b))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|a| id(-a))` error: consider using `sort_by_key` - --> tests/ui/unnecessary_sort_by.rs:18:5 + --> tests/ui/unnecessary_sort_by.rs:22:5 | LL | vec.sort_by(|a, b| (b + 5).abs().cmp(&(a + 5).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|b| std::cmp::Reverse((b + 5).abs()))` error: consider using `sort_by_key` - --> tests/ui/unnecessary_sort_by.rs:19:5 + --> tests/ui/unnecessary_sort_by.rs:24:5 | LL | vec.sort_unstable_by(|a, b| id(-b).cmp(&id(-a))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|b| std::cmp::Reverse(id(-b)))` error: consider using `sort_by_key` - --> tests/ui/unnecessary_sort_by.rs:29:5 + --> tests/ui/unnecessary_sort_by.rs:35:5 | LL | vec.sort_by(|a, b| (***a).abs().cmp(&(***b).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| (***a).abs())` error: consider using `sort_by_key` - --> tests/ui/unnecessary_sort_by.rs:30:5 + --> tests/ui/unnecessary_sort_by.rs:37:5 | LL | vec.sort_unstable_by(|a, b| (***a).abs().cmp(&(***b).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|a| (***a).abs())` error: consider using `sort_by_key` - --> tests/ui/unnecessary_sort_by.rs:89:9 + --> tests/ui/unnecessary_sort_by.rs:97:9 | LL | args.sort_by(|a, b| a.name().cmp(&b.name())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_by_key(|a| a.name())` error: consider using `sort_by_key` - --> tests/ui/unnecessary_sort_by.rs:90:9 + --> tests/ui/unnecessary_sort_by.rs:99:9 | LL | args.sort_unstable_by(|a, b| a.name().cmp(&b.name())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_unstable_by_key(|a| a.name())` error: consider using `sort_by_key` - --> tests/ui/unnecessary_sort_by.rs:92:9 + --> tests/ui/unnecessary_sort_by.rs:102:9 | LL | args.sort_by(|a, b| b.name().cmp(&a.name())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_by_key(|b| std::cmp::Reverse(b.name()))` error: consider using `sort_by_key` - --> tests/ui/unnecessary_sort_by.rs:93:9 + --> tests/ui/unnecessary_sort_by.rs:104:9 | LL | args.sort_unstable_by(|a, b| b.name().cmp(&a.name())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_unstable_by_key(|b| std::cmp::Reverse(b.name()))` diff --git a/tests/ui/unnecessary_sort_by_no_std.fixed b/tests/ui/unnecessary_sort_by_no_std.fixed index c7be000b820c..40e6aecd1b6d 100644 --- a/tests/ui/unnecessary_sort_by_no_std.fixed +++ b/tests/ui/unnecessary_sort_by_no_std.fixed @@ -8,6 +8,7 @@ fn issue_11524() -> Vec { // Should lint and suggest `vec.sort_by_key(|a| a + 1);` vec.sort_by_key(|a| a + 1); + //~^ unnecessary_sort_by vec } @@ -16,5 +17,6 @@ fn issue_11524_2() -> Vec { // Should lint and suggest `vec.sort_by_key(|b| core::cmp::Reverse(b + 1));` vec.sort_by_key(|b| core::cmp::Reverse(b + 1)); + //~^ unnecessary_sort_by vec } diff --git a/tests/ui/unnecessary_sort_by_no_std.rs b/tests/ui/unnecessary_sort_by_no_std.rs index 5f44be97c61f..184c90d959eb 100644 --- a/tests/ui/unnecessary_sort_by_no_std.rs +++ b/tests/ui/unnecessary_sort_by_no_std.rs @@ -8,6 +8,7 @@ fn issue_11524() -> Vec { // Should lint and suggest `vec.sort_by_key(|a| a + 1);` vec.sort_by(|a, b| (a + 1).cmp(&(b + 1))); + //~^ unnecessary_sort_by vec } @@ -16,5 +17,6 @@ fn issue_11524_2() -> Vec { // Should lint and suggest `vec.sort_by_key(|b| core::cmp::Reverse(b + 1));` vec.sort_by(|a, b| (b + 1).cmp(&(a + 1))); + //~^ unnecessary_sort_by vec } diff --git a/tests/ui/unnecessary_sort_by_no_std.stderr b/tests/ui/unnecessary_sort_by_no_std.stderr index a57fbc7a6328..de3ef4123514 100644 --- a/tests/ui/unnecessary_sort_by_no_std.stderr +++ b/tests/ui/unnecessary_sort_by_no_std.stderr @@ -8,7 +8,7 @@ LL | vec.sort_by(|a, b| (a + 1).cmp(&(b + 1))); = help: to override `-D warnings` add `#[allow(clippy::unnecessary_sort_by)]` error: consider using `sort_by_key` - --> tests/ui/unnecessary_sort_by_no_std.rs:18:5 + --> tests/ui/unnecessary_sort_by_no_std.rs:19:5 | LL | vec.sort_by(|a, b| (b + 1).cmp(&(a + 1))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|b| core::cmp::Reverse(b + 1))` diff --git a/tests/ui/unnecessary_struct_initialization.fixed b/tests/ui/unnecessary_struct_initialization.fixed index b0e8f4546353..07dc90acfa30 100644 --- a/tests/ui/unnecessary_struct_initialization.fixed +++ b/tests/ui/unnecessary_struct_initialization.fixed @@ -35,6 +35,7 @@ impl Clone for V { fn clone(&self) -> Self { // Lint: `Self` implements `Copy` *self + //~^ unnecessary_struct_initialization } } @@ -42,9 +43,11 @@ fn main() { // Should lint: `a` would be consumed anyway let a = S { f: String::from("foo") }; let mut b = a; + //~^ unnecessary_struct_initialization // Should lint: `b` would be consumed, and is mutable let c = &mut b; + //~^ unnecessary_struct_initialization // Should not lint as `d` is not mutable let d = S { f: String::from("foo") }; @@ -53,6 +56,7 @@ fn main() { // Should lint as `f` would be consumed anyway let f = S { f: String::from("foo") }; let g = &f; + //~^ unnecessary_struct_initialization // Should lint: the result of an expression is mutable let h = &mut *Box::new(S { f: String::from("foo") }); @@ -77,6 +81,7 @@ fn main() { // Should lint: all fields of `q` would be consumed anyway let q = W { f1: 42, f2: 1337 }; let r = q; + //~^ unnecessary_struct_initialization // Should not lint: not all fields of `t` from same source let s = W { f1: 1337, f2: 42 }; @@ -88,6 +93,7 @@ fn main() { // Should lint: all fields of `v` would be consumed anyway let v = W { f1: 42, f2: 1337 }; let w = v; + //~^ unnecessary_struct_initialization // Should not lint: source differs between fields and base let x = W { f1: 42, f2: 1337 }; @@ -96,6 +102,7 @@ fn main() { // Should lint: range desugars to struct let r1 = 0..5; let r2 = r1; + //~^ unnecessary_struct_initialization references(); shorthand(); @@ -109,6 +116,7 @@ fn references() { // Should lint as `d` is a shared reference let c = W { f1: 42, f2: 1337 }; let d = &c; + //~^ unnecessary_struct_initialization // Should not lint as `e` is not mutable let e = W { f1: 42, f2: 1337 }; @@ -117,6 +125,7 @@ fn references() { // Should lint as `h` is a shared reference let g = W { f1: 42, f2: 1337 }; let h = &g; + //~^ unnecessary_struct_initialization // Should not lint as `j` is copy let i = V { f: 0x1701d }; diff --git a/tests/ui/unnecessary_struct_initialization.rs b/tests/ui/unnecessary_struct_initialization.rs index b0db71af4d4c..12a444fc878b 100644 --- a/tests/ui/unnecessary_struct_initialization.rs +++ b/tests/ui/unnecessary_struct_initialization.rs @@ -35,6 +35,7 @@ impl Clone for V { fn clone(&self) -> Self { // Lint: `Self` implements `Copy` Self { ..*self } + //~^ unnecessary_struct_initialization } } @@ -42,9 +43,11 @@ fn main() { // Should lint: `a` would be consumed anyway let a = S { f: String::from("foo") }; let mut b = S { ..a }; + //~^ unnecessary_struct_initialization // Should lint: `b` would be consumed, and is mutable let c = &mut S { ..b }; + //~^ unnecessary_struct_initialization // Should not lint as `d` is not mutable let d = S { f: String::from("foo") }; @@ -53,9 +56,11 @@ fn main() { // Should lint as `f` would be consumed anyway let f = S { f: String::from("foo") }; let g = &S { ..f }; + //~^ unnecessary_struct_initialization // Should lint: the result of an expression is mutable let h = &mut S { + //~^ unnecessary_struct_initialization ..*Box::new(S { f: String::from("foo") }) }; @@ -75,12 +80,14 @@ fn main() { // Should lint: the result of an expression is mutable and temporary let p = &mut T { + //~^ unnecessary_struct_initialization ..*Box::new(T { f: 5 }) }; // Should lint: all fields of `q` would be consumed anyway let q = W { f1: 42, f2: 1337 }; let r = W { f1: q.f1, f2: q.f2 }; + //~^ unnecessary_struct_initialization // Should not lint: not all fields of `t` from same source let s = W { f1: 1337, f2: 42 }; @@ -92,6 +99,7 @@ fn main() { // Should lint: all fields of `v` would be consumed anyway let v = W { f1: 42, f2: 1337 }; let w = W { f1: v.f1, ..v }; + //~^ unnecessary_struct_initialization // Should not lint: source differs between fields and base let x = W { f1: 42, f2: 1337 }; @@ -100,6 +108,7 @@ fn main() { // Should lint: range desugars to struct let r1 = 0..5; let r2 = r1.start..r1.end; + //~^ unnecessary_struct_initialization references(); shorthand(); @@ -113,6 +122,7 @@ fn references() { // Should lint as `d` is a shared reference let c = W { f1: 42, f2: 1337 }; let d = &W { f1: c.f1, f2: c.f2 }; + //~^ unnecessary_struct_initialization // Should not lint as `e` is not mutable let e = W { f1: 42, f2: 1337 }; @@ -121,6 +131,7 @@ fn references() { // Should lint as `h` is a shared reference let g = W { f1: 42, f2: 1337 }; let h = &W { f1: g.f1, ..g }; + //~^ unnecessary_struct_initialization // Should not lint as `j` is copy let i = V { f: 0x1701d }; diff --git a/tests/ui/unnecessary_struct_initialization.stderr b/tests/ui/unnecessary_struct_initialization.stderr index 56982cc0a39f..5177b3252547 100644 --- a/tests/ui/unnecessary_struct_initialization.stderr +++ b/tests/ui/unnecessary_struct_initialization.stderr @@ -8,67 +8,69 @@ LL | Self { ..*self } = help: to override `-D warnings` add `#[allow(clippy::unnecessary_struct_initialization)]` error: unnecessary struct building - --> tests/ui/unnecessary_struct_initialization.rs:44:17 + --> tests/ui/unnecessary_struct_initialization.rs:45:17 | LL | let mut b = S { ..a }; | ^^^^^^^^^ help: replace with: `a` error: unnecessary struct building - --> tests/ui/unnecessary_struct_initialization.rs:47:18 + --> tests/ui/unnecessary_struct_initialization.rs:49:18 | LL | let c = &mut S { ..b }; | ^^^^^^^^^ help: replace with: `b` error: unnecessary struct building - --> tests/ui/unnecessary_struct_initialization.rs:55:14 + --> tests/ui/unnecessary_struct_initialization.rs:58:14 | LL | let g = &S { ..f }; | ^^^^^^^^^ help: replace with: `f` error: unnecessary struct building - --> tests/ui/unnecessary_struct_initialization.rs:58:18 + --> tests/ui/unnecessary_struct_initialization.rs:62:18 | LL | let h = &mut S { | __________________^ +LL | | LL | | ..*Box::new(S { f: String::from("foo") }) LL | | }; | |_____^ help: replace with: `*Box::new(S { f: String::from("foo") })` error: unnecessary struct building - --> tests/ui/unnecessary_struct_initialization.rs:77:18 + --> tests/ui/unnecessary_struct_initialization.rs:82:18 | LL | let p = &mut T { | __________________^ +LL | | LL | | ..*Box::new(T { f: 5 }) LL | | }; | |_____^ help: replace with: `*Box::new(T { f: 5 })` error: unnecessary struct building - --> tests/ui/unnecessary_struct_initialization.rs:83:13 + --> tests/ui/unnecessary_struct_initialization.rs:89:13 | LL | let r = W { f1: q.f1, f2: q.f2 }; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `q` error: unnecessary struct building - --> tests/ui/unnecessary_struct_initialization.rs:94:13 + --> tests/ui/unnecessary_struct_initialization.rs:101:13 | LL | let w = W { f1: v.f1, ..v }; | ^^^^^^^^^^^^^^^^^^^ help: replace with: `v` error: unnecessary struct building - --> tests/ui/unnecessary_struct_initialization.rs:102:14 + --> tests/ui/unnecessary_struct_initialization.rs:110:14 | LL | let r2 = r1.start..r1.end; | ^^^^^^^^^^^^^^^^ help: replace with: `r1` error: unnecessary struct building - --> tests/ui/unnecessary_struct_initialization.rs:115:14 + --> tests/ui/unnecessary_struct_initialization.rs:124:14 | LL | let d = &W { f1: c.f1, f2: c.f2 }; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `c` error: unnecessary struct building - --> tests/ui/unnecessary_struct_initialization.rs:123:14 + --> tests/ui/unnecessary_struct_initialization.rs:133:14 | LL | let h = &W { f1: g.f1, ..g }; | ^^^^^^^^^^^^^^^^^^^ help: replace with: `g` diff --git a/tests/ui/unnecessary_to_owned.fixed b/tests/ui/unnecessary_to_owned.fixed index 027dac419375..bf271aef763b 100644 --- a/tests/ui/unnecessary_to_owned.fixed +++ b/tests/ui/unnecessary_to_owned.fixed @@ -3,7 +3,8 @@ clippy::needless_borrows_for_generic_args, clippy::ptr_arg, clippy::manual_async_fn, - clippy::needless_lifetimes + clippy::needless_lifetimes, + clippy::owned_cow )] #![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)] @@ -62,82 +63,151 @@ fn main() { let x_ref = &x; require_c_str(&Cow::from(c_str)); + //~^ unnecessary_to_owned require_c_str(c_str); + //~^ unnecessary_to_owned require_os_str(os_str); + //~^ unnecessary_to_owned require_os_str(&Cow::from(os_str)); + //~^ unnecessary_to_owned require_os_str(os_str); + //~^ unnecessary_to_owned require_path(path); + //~^ unnecessary_to_owned require_path(&Cow::from(path)); + //~^ unnecessary_to_owned require_path(path); + //~^ unnecessary_to_owned require_str(s); + //~^ unnecessary_to_owned require_str(&Cow::from(s)); + //~^ unnecessary_to_owned require_str(s); + //~^ unnecessary_to_owned require_str(x_ref.as_ref()); + //~^ unnecessary_to_owned require_slice(slice); + //~^ unnecessary_to_owned require_slice(&Cow::from(slice)); + //~^ unnecessary_to_owned require_slice(array.as_ref()); + //~^ unnecessary_to_owned require_slice(array_ref.as_ref()); + //~^ unnecessary_to_owned require_slice(slice); + //~^ unnecessary_to_owned require_slice(&x_ref.to_owned()); // No longer flagged because of #8759. require_x(&Cow::::Owned(x.clone())); + //~^ unnecessary_to_owned require_x(&x_ref.to_owned()); // No longer flagged because of #8759. require_deref_c_str(c_str); + //~^ unnecessary_to_owned require_deref_os_str(os_str); + //~^ unnecessary_to_owned require_deref_path(path); + //~^ unnecessary_to_owned require_deref_str(s); + //~^ unnecessary_to_owned require_deref_slice(slice); + //~^ unnecessary_to_owned require_impl_deref_c_str(c_str); + //~^ unnecessary_to_owned require_impl_deref_os_str(os_str); + //~^ unnecessary_to_owned require_impl_deref_path(path); + //~^ unnecessary_to_owned require_impl_deref_str(s); + //~^ unnecessary_to_owned require_impl_deref_slice(slice); + //~^ unnecessary_to_owned require_deref_str_slice(s, slice); + //~^ unnecessary_to_owned + //~| unnecessary_to_owned require_deref_slice_str(slice, s); + //~^ unnecessary_to_owned + //~| unnecessary_to_owned require_as_ref_c_str(c_str); + //~^ unnecessary_to_owned require_as_ref_os_str(os_str); + //~^ unnecessary_to_owned require_as_ref_path(path); + //~^ unnecessary_to_owned require_as_ref_str(s); + //~^ unnecessary_to_owned require_as_ref_str(&x); + //~^ unnecessary_to_owned require_as_ref_slice(array); + //~^ unnecessary_to_owned require_as_ref_slice(array_ref); + //~^ unnecessary_to_owned require_as_ref_slice(slice); + //~^ unnecessary_to_owned require_impl_as_ref_c_str(c_str); + //~^ unnecessary_to_owned require_impl_as_ref_os_str(os_str); + //~^ unnecessary_to_owned require_impl_as_ref_path(path); + //~^ unnecessary_to_owned require_impl_as_ref_str(s); + //~^ unnecessary_to_owned require_impl_as_ref_str(&x); + //~^ unnecessary_to_owned require_impl_as_ref_slice(array); + //~^ unnecessary_to_owned require_impl_as_ref_slice(array_ref); + //~^ unnecessary_to_owned require_impl_as_ref_slice(slice); + //~^ unnecessary_to_owned require_as_ref_str_slice(s, array); + //~^ unnecessary_to_owned + //~| unnecessary_to_owned require_as_ref_str_slice(s, array_ref); + //~^ unnecessary_to_owned + //~| unnecessary_to_owned require_as_ref_str_slice(s, slice); + //~^ unnecessary_to_owned + //~| unnecessary_to_owned require_as_ref_slice_str(array, s); + //~^ unnecessary_to_owned + //~| unnecessary_to_owned require_as_ref_slice_str(array_ref, s); + //~^ unnecessary_to_owned + //~| unnecessary_to_owned require_as_ref_slice_str(slice, s); + //~^ unnecessary_to_owned + //~| unnecessary_to_owned let _ = x.join(x_ref); + //~^ unnecessary_to_owned let _ = slice.iter().copied(); + //~^ unnecessary_to_owned let _ = slice.iter().copied(); + //~^ unnecessary_to_owned let _ = [std::path::PathBuf::new()][..].iter().cloned(); + //~^ unnecessary_to_owned let _ = [std::path::PathBuf::new()][..].iter().cloned(); + //~^ unnecessary_to_owned let _ = slice.iter().copied(); + //~^ unnecessary_to_owned let _ = slice.iter().copied(); + //~^ unnecessary_to_owned let _ = [std::path::PathBuf::new()][..].iter().cloned(); + //~^ unnecessary_to_owned let _ = [std::path::PathBuf::new()][..].iter().cloned(); + //~^ unnecessary_to_owned let _ = check_files(&[FileType::Account]); @@ -153,15 +223,23 @@ fn main() { // The following should be flagged by `redundant_clone`, but not by this lint. require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap()); + //~^ redundant_clone require_os_str(&OsString::from("x")); + //~^ redundant_clone require_path(&std::path::PathBuf::from("x")); + //~^ redundant_clone require_str(&String::from("x")); + //~^ redundant_clone require_slice(&[String::from("x")]); + //~^ redundant_clone let slice = [0u8; 1024]; let _ref_str: &str = core::str::from_utf8(&slice).expect("not UTF-8"); + //~^ unnecessary_to_owned let _ref_str: &str = core::str::from_utf8(b"foo").unwrap(); + //~^ unnecessary_to_owned let _ref_str: &str = core::str::from_utf8(b"foo".as_slice()).unwrap(); + //~^ unnecessary_to_owned // Expression is of type `&String`, can't suggest `str::from_utf8` here let _ref_string = &String::from_utf8(b"foo".to_vec()).unwrap(); macro_rules! arg_from_macro { @@ -219,6 +297,7 @@ fn require_as_ref_slice_str, V: AsRef>(_: U, _: V) {} // https://github.com/breard-r/acmed/blob/1f0dcc32aadbc5e52de6d23b9703554c0f925113/acmed/src/storage.rs#L262 fn check_files(file_types: &[FileType]) -> bool { for t in file_types { + //~^ unnecessary_to_owned let path = match get_file_path(t) { Ok(p) => p, Err(_) => { @@ -242,11 +321,13 @@ fn require_string(_: &String) {} fn _msrv_1_35() { // `copied` was stabilized in 1.36, so clippy should use `cloned`. let _ = &["x"][..].iter().cloned(); + //~^ unnecessary_to_owned } #[clippy::msrv = "1.36"] fn _msrv_1_36() { let _ = &["x"][..].iter().copied(); + //~^ unnecessary_to_owned } // https://github.com/rust-lang/rust-clippy/issues/8507 @@ -295,6 +376,7 @@ mod issue_8507 { // Should lint because Y is copy. fn test_y(y: Y) -> Box { Box::new(build(y)) + //~^ unnecessary_to_owned } } @@ -404,6 +486,7 @@ mod issue_9351 { // Should lint fn single_return() -> impl AsRef { id("abc") + //~^ unnecessary_to_owned } // Should not lint @@ -547,6 +630,7 @@ mod issue_11952 { fn bar() { IntoFuture::into_future(foo([], &0)); + //~^ unnecessary_to_owned } } @@ -556,18 +640,23 @@ fn borrow_checks() { fn inner(a: &[&str]) { let mut s = HashSet::from([vec!["a"]]); - s.remove(a); //~ ERROR: unnecessary use of `to_vec` + s.remove(a); + //~^ unnecessary_to_owned } let mut s = HashSet::from(["a".to_string()]); - s.remove("b"); //~ ERROR: unnecessary use of `to_owned` - s.remove("b"); //~ ERROR: unnecessary use of `to_string` + s.remove("b"); + //~^ unnecessary_to_owned + s.remove("b"); + //~^ unnecessary_to_owned // Should not warn. s.remove("b"); let mut s = HashSet::from([vec!["a"]]); - s.remove(["b"].as_slice()); //~ ERROR: unnecessary use of `to_vec` - s.remove((&["b"]).as_slice()); //~ ERROR: unnecessary use of `to_vec` + s.remove(["b"].as_slice()); + //~^ unnecessary_to_owned + s.remove((&["b"]).as_slice()); + //~^ unnecessary_to_owned // Should not warn. s.remove(&["b"].to_vec().clone()); diff --git a/tests/ui/unnecessary_to_owned.rs b/tests/ui/unnecessary_to_owned.rs index b89f3d552f84..95b95ab6bd22 100644 --- a/tests/ui/unnecessary_to_owned.rs +++ b/tests/ui/unnecessary_to_owned.rs @@ -3,7 +3,8 @@ clippy::needless_borrows_for_generic_args, clippy::ptr_arg, clippy::manual_async_fn, - clippy::needless_lifetimes + clippy::needless_lifetimes, + clippy::owned_cow )] #![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)] @@ -62,82 +63,151 @@ fn main() { let x_ref = &x; require_c_str(&Cow::from(c_str).into_owned()); + //~^ unnecessary_to_owned require_c_str(&c_str.to_owned()); + //~^ unnecessary_to_owned require_os_str(&os_str.to_os_string()); + //~^ unnecessary_to_owned require_os_str(&Cow::from(os_str).into_owned()); + //~^ unnecessary_to_owned require_os_str(&os_str.to_owned()); + //~^ unnecessary_to_owned require_path(&path.to_path_buf()); + //~^ unnecessary_to_owned require_path(&Cow::from(path).into_owned()); + //~^ unnecessary_to_owned require_path(&path.to_owned()); + //~^ unnecessary_to_owned require_str(&s.to_string()); + //~^ unnecessary_to_owned require_str(&Cow::from(s).into_owned()); + //~^ unnecessary_to_owned require_str(&s.to_owned()); + //~^ unnecessary_to_owned require_str(&x_ref.to_string()); + //~^ unnecessary_to_owned require_slice(&slice.to_vec()); + //~^ unnecessary_to_owned require_slice(&Cow::from(slice).into_owned()); + //~^ unnecessary_to_owned require_slice(&array.to_owned()); + //~^ unnecessary_to_owned require_slice(&array_ref.to_owned()); + //~^ unnecessary_to_owned require_slice(&slice.to_owned()); + //~^ unnecessary_to_owned require_slice(&x_ref.to_owned()); // No longer flagged because of #8759. require_x(&Cow::::Owned(x.clone()).into_owned()); + //~^ unnecessary_to_owned require_x(&x_ref.to_owned()); // No longer flagged because of #8759. require_deref_c_str(c_str.to_owned()); + //~^ unnecessary_to_owned require_deref_os_str(os_str.to_owned()); + //~^ unnecessary_to_owned require_deref_path(path.to_owned()); + //~^ unnecessary_to_owned require_deref_str(s.to_owned()); + //~^ unnecessary_to_owned require_deref_slice(slice.to_owned()); + //~^ unnecessary_to_owned require_impl_deref_c_str(c_str.to_owned()); + //~^ unnecessary_to_owned require_impl_deref_os_str(os_str.to_owned()); + //~^ unnecessary_to_owned require_impl_deref_path(path.to_owned()); + //~^ unnecessary_to_owned require_impl_deref_str(s.to_owned()); + //~^ unnecessary_to_owned require_impl_deref_slice(slice.to_owned()); + //~^ unnecessary_to_owned require_deref_str_slice(s.to_owned(), slice.to_owned()); + //~^ unnecessary_to_owned + //~| unnecessary_to_owned require_deref_slice_str(slice.to_owned(), s.to_owned()); + //~^ unnecessary_to_owned + //~| unnecessary_to_owned require_as_ref_c_str(c_str.to_owned()); + //~^ unnecessary_to_owned require_as_ref_os_str(os_str.to_owned()); + //~^ unnecessary_to_owned require_as_ref_path(path.to_owned()); + //~^ unnecessary_to_owned require_as_ref_str(s.to_owned()); + //~^ unnecessary_to_owned require_as_ref_str(x.to_owned()); + //~^ unnecessary_to_owned require_as_ref_slice(array.to_owned()); + //~^ unnecessary_to_owned require_as_ref_slice(array_ref.to_owned()); + //~^ unnecessary_to_owned require_as_ref_slice(slice.to_owned()); + //~^ unnecessary_to_owned require_impl_as_ref_c_str(c_str.to_owned()); + //~^ unnecessary_to_owned require_impl_as_ref_os_str(os_str.to_owned()); + //~^ unnecessary_to_owned require_impl_as_ref_path(path.to_owned()); + //~^ unnecessary_to_owned require_impl_as_ref_str(s.to_owned()); + //~^ unnecessary_to_owned require_impl_as_ref_str(x.to_owned()); + //~^ unnecessary_to_owned require_impl_as_ref_slice(array.to_owned()); + //~^ unnecessary_to_owned require_impl_as_ref_slice(array_ref.to_owned()); + //~^ unnecessary_to_owned require_impl_as_ref_slice(slice.to_owned()); + //~^ unnecessary_to_owned require_as_ref_str_slice(s.to_owned(), array.to_owned()); + //~^ unnecessary_to_owned + //~| unnecessary_to_owned require_as_ref_str_slice(s.to_owned(), array_ref.to_owned()); + //~^ unnecessary_to_owned + //~| unnecessary_to_owned require_as_ref_str_slice(s.to_owned(), slice.to_owned()); + //~^ unnecessary_to_owned + //~| unnecessary_to_owned require_as_ref_slice_str(array.to_owned(), s.to_owned()); + //~^ unnecessary_to_owned + //~| unnecessary_to_owned require_as_ref_slice_str(array_ref.to_owned(), s.to_owned()); + //~^ unnecessary_to_owned + //~| unnecessary_to_owned require_as_ref_slice_str(slice.to_owned(), s.to_owned()); + //~^ unnecessary_to_owned + //~| unnecessary_to_owned let _ = x.join(&x_ref.to_string()); + //~^ unnecessary_to_owned let _ = slice.to_vec().into_iter(); + //~^ unnecessary_to_owned let _ = slice.to_owned().into_iter(); + //~^ unnecessary_to_owned let _ = [std::path::PathBuf::new()][..].to_vec().into_iter(); + //~^ unnecessary_to_owned let _ = [std::path::PathBuf::new()][..].to_owned().into_iter(); + //~^ unnecessary_to_owned let _ = IntoIterator::into_iter(slice.to_vec()); + //~^ unnecessary_to_owned let _ = IntoIterator::into_iter(slice.to_owned()); + //~^ unnecessary_to_owned let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_vec()); + //~^ unnecessary_to_owned let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_owned()); + //~^ unnecessary_to_owned let _ = check_files(&[FileType::Account]); @@ -153,15 +223,23 @@ fn main() { // The following should be flagged by `redundant_clone`, but not by this lint. require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned()); + //~^ redundant_clone require_os_str(&OsString::from("x").to_os_string()); + //~^ redundant_clone require_path(&std::path::PathBuf::from("x").to_path_buf()); + //~^ redundant_clone require_str(&String::from("x").to_string()); + //~^ redundant_clone require_slice(&[String::from("x")].to_owned()); + //~^ redundant_clone let slice = [0u8; 1024]; let _ref_str: &str = &String::from_utf8(slice.to_vec()).expect("not UTF-8"); + //~^ unnecessary_to_owned let _ref_str: &str = &String::from_utf8(b"foo".to_vec()).unwrap(); + //~^ unnecessary_to_owned let _ref_str: &str = &String::from_utf8(b"foo".as_slice().to_owned()).unwrap(); + //~^ unnecessary_to_owned // Expression is of type `&String`, can't suggest `str::from_utf8` here let _ref_string = &String::from_utf8(b"foo".to_vec()).unwrap(); macro_rules! arg_from_macro { @@ -219,6 +297,7 @@ fn require_as_ref_slice_str, V: AsRef>(_: U, _: V) {} // https://github.com/breard-r/acmed/blob/1f0dcc32aadbc5e52de6d23b9703554c0f925113/acmed/src/storage.rs#L262 fn check_files(file_types: &[FileType]) -> bool { for t in file_types.to_vec() { + //~^ unnecessary_to_owned let path = match get_file_path(&t) { Ok(p) => p, Err(_) => { @@ -242,11 +321,13 @@ fn require_string(_: &String) {} fn _msrv_1_35() { // `copied` was stabilized in 1.36, so clippy should use `cloned`. let _ = &["x"][..].to_vec().into_iter(); + //~^ unnecessary_to_owned } #[clippy::msrv = "1.36"] fn _msrv_1_36() { let _ = &["x"][..].to_vec().into_iter(); + //~^ unnecessary_to_owned } // https://github.com/rust-lang/rust-clippy/issues/8507 @@ -295,6 +376,7 @@ mod issue_8507 { // Should lint because Y is copy. fn test_y(y: Y) -> Box { Box::new(build(y.to_string())) + //~^ unnecessary_to_owned } } @@ -404,6 +486,7 @@ mod issue_9351 { // Should lint fn single_return() -> impl AsRef { id("abc".to_string()) + //~^ unnecessary_to_owned } // Should not lint @@ -547,6 +630,7 @@ mod issue_11952 { fn bar() { IntoFuture::into_future(foo([].to_vec(), &0)); + //~^ unnecessary_to_owned } } @@ -556,18 +640,23 @@ fn borrow_checks() { fn inner(a: &[&str]) { let mut s = HashSet::from([vec!["a"]]); - s.remove(&a.to_vec()); //~ ERROR: unnecessary use of `to_vec` + s.remove(&a.to_vec()); + //~^ unnecessary_to_owned } let mut s = HashSet::from(["a".to_string()]); - s.remove(&"b".to_owned()); //~ ERROR: unnecessary use of `to_owned` - s.remove(&"b".to_string()); //~ ERROR: unnecessary use of `to_string` + s.remove(&"b".to_owned()); + //~^ unnecessary_to_owned + s.remove(&"b".to_string()); + //~^ unnecessary_to_owned // Should not warn. s.remove("b"); let mut s = HashSet::from([vec!["a"]]); - s.remove(&["b"].to_vec()); //~ ERROR: unnecessary use of `to_vec` - s.remove(&(&["b"]).to_vec()); //~ ERROR: unnecessary use of `to_vec` + s.remove(&["b"].to_vec()); + //~^ unnecessary_to_owned + s.remove(&(&["b"]).to_vec()); + //~^ unnecessary_to_owned // Should not warn. s.remove(&["b"].to_vec().clone()); diff --git a/tests/ui/unnecessary_to_owned.stderr b/tests/ui/unnecessary_to_owned.stderr index 498ac68cdaa0..4daa3876e60e 100644 --- a/tests/ui/unnecessary_to_owned.stderr +++ b/tests/ui/unnecessary_to_owned.stderr @@ -1,11 +1,11 @@ error: redundant clone - --> tests/ui/unnecessary_to_owned.rs:155:64 + --> tests/ui/unnecessary_to_owned.rs:225:64 | LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned()); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/unnecessary_to_owned.rs:155:20 + --> tests/ui/unnecessary_to_owned.rs:225:20 | LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,55 +13,55 @@ LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned()) = help: to override `-D warnings` add `#[allow(clippy::redundant_clone)]` error: redundant clone - --> tests/ui/unnecessary_to_owned.rs:156:40 + --> tests/ui/unnecessary_to_owned.rs:227:40 | LL | require_os_str(&OsString::from("x").to_os_string()); | ^^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/unnecessary_to_owned.rs:156:21 + --> tests/ui/unnecessary_to_owned.rs:227:21 | LL | require_os_str(&OsString::from("x").to_os_string()); | ^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> tests/ui/unnecessary_to_owned.rs:157:48 + --> tests/ui/unnecessary_to_owned.rs:229:48 | LL | require_path(&std::path::PathBuf::from("x").to_path_buf()); | ^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/unnecessary_to_owned.rs:157:19 + --> tests/ui/unnecessary_to_owned.rs:229:19 | LL | require_path(&std::path::PathBuf::from("x").to_path_buf()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> tests/ui/unnecessary_to_owned.rs:158:35 + --> tests/ui/unnecessary_to_owned.rs:231:35 | LL | require_str(&String::from("x").to_string()); | ^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/unnecessary_to_owned.rs:158:18 + --> tests/ui/unnecessary_to_owned.rs:231:18 | LL | require_str(&String::from("x").to_string()); | ^^^^^^^^^^^^^^^^^ error: redundant clone - --> tests/ui/unnecessary_to_owned.rs:159:39 + --> tests/ui/unnecessary_to_owned.rs:233:39 | LL | require_slice(&[String::from("x")].to_owned()); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/unnecessary_to_owned.rs:159:20 + --> tests/ui/unnecessary_to_owned.rs:233:20 | LL | require_slice(&[String::from("x")].to_owned()); | ^^^^^^^^^^^^^^^^^^^ error: unnecessary use of `into_owned` - --> tests/ui/unnecessary_to_owned.rs:64:36 + --> tests/ui/unnecessary_to_owned.rs:65:36 | LL | require_c_str(&Cow::from(c_str).into_owned()); | ^^^^^^^^^^^^^ help: remove this @@ -70,415 +70,415 @@ LL | require_c_str(&Cow::from(c_str).into_owned()); = help: to override `-D warnings` add `#[allow(clippy::unnecessary_to_owned)]` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:65:19 + --> tests/ui/unnecessary_to_owned.rs:67:19 | LL | require_c_str(&c_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_os_string` - --> tests/ui/unnecessary_to_owned.rs:67:20 + --> tests/ui/unnecessary_to_owned.rs:70:20 | LL | require_os_str(&os_str.to_os_string()); | ^^^^^^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `into_owned` - --> tests/ui/unnecessary_to_owned.rs:68:38 + --> tests/ui/unnecessary_to_owned.rs:72:38 | LL | require_os_str(&Cow::from(os_str).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:69:20 + --> tests/ui/unnecessary_to_owned.rs:74:20 | LL | require_os_str(&os_str.to_owned()); | ^^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_path_buf` - --> tests/ui/unnecessary_to_owned.rs:71:18 + --> tests/ui/unnecessary_to_owned.rs:77:18 | LL | require_path(&path.to_path_buf()); | ^^^^^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `into_owned` - --> tests/ui/unnecessary_to_owned.rs:72:34 + --> tests/ui/unnecessary_to_owned.rs:79:34 | LL | require_path(&Cow::from(path).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:73:18 + --> tests/ui/unnecessary_to_owned.rs:81:18 | LL | require_path(&path.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_string` - --> tests/ui/unnecessary_to_owned.rs:75:17 + --> tests/ui/unnecessary_to_owned.rs:84:17 | LL | require_str(&s.to_string()); | ^^^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `into_owned` - --> tests/ui/unnecessary_to_owned.rs:76:30 + --> tests/ui/unnecessary_to_owned.rs:86:30 | LL | require_str(&Cow::from(s).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:77:17 + --> tests/ui/unnecessary_to_owned.rs:88:17 | LL | require_str(&s.to_owned()); | ^^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_string` - --> tests/ui/unnecessary_to_owned.rs:78:17 + --> tests/ui/unnecessary_to_owned.rs:90:17 | LL | require_str(&x_ref.to_string()); | ^^^^^^^^^^^^^^^^^^ help: use: `x_ref.as_ref()` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:80:19 + --> tests/ui/unnecessary_to_owned.rs:93:19 | LL | require_slice(&slice.to_vec()); | ^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `into_owned` - --> tests/ui/unnecessary_to_owned.rs:81:36 + --> tests/ui/unnecessary_to_owned.rs:95:36 | LL | require_slice(&Cow::from(slice).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:82:19 + --> tests/ui/unnecessary_to_owned.rs:97:19 | LL | require_slice(&array.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `array.as_ref()` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:83:19 + --> tests/ui/unnecessary_to_owned.rs:99:19 | LL | require_slice(&array_ref.to_owned()); | ^^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref.as_ref()` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:84:19 + --> tests/ui/unnecessary_to_owned.rs:101:19 | LL | require_slice(&slice.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `into_owned` - --> tests/ui/unnecessary_to_owned.rs:87:42 + --> tests/ui/unnecessary_to_owned.rs:105:42 | LL | require_x(&Cow::::Owned(x.clone()).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:90:25 + --> tests/ui/unnecessary_to_owned.rs:109:25 | LL | require_deref_c_str(c_str.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:91:26 + --> tests/ui/unnecessary_to_owned.rs:111:26 | LL | require_deref_os_str(os_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:92:24 + --> tests/ui/unnecessary_to_owned.rs:113:24 | LL | require_deref_path(path.to_owned()); | ^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:93:23 + --> tests/ui/unnecessary_to_owned.rs:115:23 | LL | require_deref_str(s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:94:25 + --> tests/ui/unnecessary_to_owned.rs:117:25 | LL | require_deref_slice(slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:96:30 + --> tests/ui/unnecessary_to_owned.rs:120:30 | LL | require_impl_deref_c_str(c_str.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:97:31 + --> tests/ui/unnecessary_to_owned.rs:122:31 | LL | require_impl_deref_os_str(os_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:98:29 + --> tests/ui/unnecessary_to_owned.rs:124:29 | LL | require_impl_deref_path(path.to_owned()); | ^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:99:28 + --> tests/ui/unnecessary_to_owned.rs:126:28 | LL | require_impl_deref_str(s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:100:30 + --> tests/ui/unnecessary_to_owned.rs:128:30 | LL | require_impl_deref_slice(slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:102:29 + --> tests/ui/unnecessary_to_owned.rs:131:29 | LL | require_deref_str_slice(s.to_owned(), slice.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:102:43 + --> tests/ui/unnecessary_to_owned.rs:131:43 | LL | require_deref_str_slice(s.to_owned(), slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:103:29 + --> tests/ui/unnecessary_to_owned.rs:134:29 | LL | require_deref_slice_str(slice.to_owned(), s.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:103:47 + --> tests/ui/unnecessary_to_owned.rs:134:47 | LL | require_deref_slice_str(slice.to_owned(), s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:105:26 + --> tests/ui/unnecessary_to_owned.rs:138:26 | LL | require_as_ref_c_str(c_str.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:106:27 + --> tests/ui/unnecessary_to_owned.rs:140:27 | LL | require_as_ref_os_str(os_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:107:25 + --> tests/ui/unnecessary_to_owned.rs:142:25 | LL | require_as_ref_path(path.to_owned()); | ^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:108:24 + --> tests/ui/unnecessary_to_owned.rs:144:24 | LL | require_as_ref_str(s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:109:24 + --> tests/ui/unnecessary_to_owned.rs:146:24 | LL | require_as_ref_str(x.to_owned()); | ^^^^^^^^^^^^ help: use: `&x` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:110:26 + --> tests/ui/unnecessary_to_owned.rs:148:26 | LL | require_as_ref_slice(array.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `array` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:111:26 + --> tests/ui/unnecessary_to_owned.rs:150:26 | LL | require_as_ref_slice(array_ref.to_owned()); | ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:112:26 + --> tests/ui/unnecessary_to_owned.rs:152:26 | LL | require_as_ref_slice(slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:114:31 + --> tests/ui/unnecessary_to_owned.rs:155:31 | LL | require_impl_as_ref_c_str(c_str.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:115:32 + --> tests/ui/unnecessary_to_owned.rs:157:32 | LL | require_impl_as_ref_os_str(os_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:116:30 + --> tests/ui/unnecessary_to_owned.rs:159:30 | LL | require_impl_as_ref_path(path.to_owned()); | ^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:117:29 + --> tests/ui/unnecessary_to_owned.rs:161:29 | LL | require_impl_as_ref_str(s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:118:29 + --> tests/ui/unnecessary_to_owned.rs:163:29 | LL | require_impl_as_ref_str(x.to_owned()); | ^^^^^^^^^^^^ help: use: `&x` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:119:31 + --> tests/ui/unnecessary_to_owned.rs:165:31 | LL | require_impl_as_ref_slice(array.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `array` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:120:31 + --> tests/ui/unnecessary_to_owned.rs:167:31 | LL | require_impl_as_ref_slice(array_ref.to_owned()); | ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:121:31 + --> tests/ui/unnecessary_to_owned.rs:169:31 | LL | require_impl_as_ref_slice(slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:123:30 + --> tests/ui/unnecessary_to_owned.rs:172:30 | LL | require_as_ref_str_slice(s.to_owned(), array.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:123:44 + --> tests/ui/unnecessary_to_owned.rs:172:44 | LL | require_as_ref_str_slice(s.to_owned(), array.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `array` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:124:30 + --> tests/ui/unnecessary_to_owned.rs:175:30 | LL | require_as_ref_str_slice(s.to_owned(), array_ref.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:124:44 + --> tests/ui/unnecessary_to_owned.rs:175:44 | LL | require_as_ref_str_slice(s.to_owned(), array_ref.to_owned()); | ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:125:30 + --> tests/ui/unnecessary_to_owned.rs:178:30 | LL | require_as_ref_str_slice(s.to_owned(), slice.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:125:44 + --> tests/ui/unnecessary_to_owned.rs:178:44 | LL | require_as_ref_str_slice(s.to_owned(), slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:126:30 + --> tests/ui/unnecessary_to_owned.rs:181:30 | LL | require_as_ref_slice_str(array.to_owned(), s.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `array` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:126:48 + --> tests/ui/unnecessary_to_owned.rs:181:48 | LL | require_as_ref_slice_str(array.to_owned(), s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:127:30 + --> tests/ui/unnecessary_to_owned.rs:184:30 | LL | require_as_ref_slice_str(array_ref.to_owned(), s.to_owned()); | ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:127:52 + --> tests/ui/unnecessary_to_owned.rs:184:52 | LL | require_as_ref_slice_str(array_ref.to_owned(), s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:128:30 + --> tests/ui/unnecessary_to_owned.rs:187:30 | LL | require_as_ref_slice_str(slice.to_owned(), s.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:128:48 + --> tests/ui/unnecessary_to_owned.rs:187:48 | LL | require_as_ref_slice_str(slice.to_owned(), s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_string` - --> tests/ui/unnecessary_to_owned.rs:130:20 + --> tests/ui/unnecessary_to_owned.rs:191:20 | LL | let _ = x.join(&x_ref.to_string()); | ^^^^^^^^^^^^^^^^^^ help: use: `x_ref` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:132:13 + --> tests/ui/unnecessary_to_owned.rs:194:13 | LL | let _ = slice.to_vec().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:133:13 + --> tests/ui/unnecessary_to_owned.rs:196:13 | LL | let _ = slice.to_owned().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:134:13 + --> tests/ui/unnecessary_to_owned.rs:198:13 | LL | let _ = [std::path::PathBuf::new()][..].to_vec().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:135:13 + --> tests/ui/unnecessary_to_owned.rs:200:13 | LL | let _ = [std::path::PathBuf::new()][..].to_owned().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:137:13 + --> tests/ui/unnecessary_to_owned.rs:203:13 | LL | let _ = IntoIterator::into_iter(slice.to_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:138:13 + --> tests/ui/unnecessary_to_owned.rs:205:13 | LL | let _ = IntoIterator::into_iter(slice.to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:139:13 + --> tests/ui/unnecessary_to_owned.rs:207:13 | LL | let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:140:13 + --> tests/ui/unnecessary_to_owned.rs:209:13 | LL | let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` error: allocating a new `String` only to create a temporary `&str` from it - --> tests/ui/unnecessary_to_owned.rs:162:26 + --> tests/ui/unnecessary_to_owned.rs:237:26 | LL | let _ref_str: &str = &String::from_utf8(slice.to_vec()).expect("not UTF-8"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -490,7 +490,7 @@ LL + let _ref_str: &str = core::str::from_utf8(&slice).expect("not UTF-8"); | error: allocating a new `String` only to create a temporary `&str` from it - --> tests/ui/unnecessary_to_owned.rs:163:26 + --> tests/ui/unnecessary_to_owned.rs:239:26 | LL | let _ref_str: &str = &String::from_utf8(b"foo".to_vec()).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -502,7 +502,7 @@ LL + let _ref_str: &str = core::str::from_utf8(b"foo").unwrap(); | error: allocating a new `String` only to create a temporary `&str` from it - --> tests/ui/unnecessary_to_owned.rs:164:26 + --> tests/ui/unnecessary_to_owned.rs:241:26 | LL | let _ref_str: &str = &String::from_utf8(b"foo".as_slice().to_owned()).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -514,7 +514,7 @@ LL + let _ref_str: &str = core::str::from_utf8(b"foo".as_slice()).unwrap(); | error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:221:14 + --> tests/ui/unnecessary_to_owned.rs:299:14 | LL | for t in file_types.to_vec() { | ^^^^^^^^^^^^^^^^^^^ @@ -522,65 +522,66 @@ LL | for t in file_types.to_vec() { help: remove any references to the binding | LL ~ for t in file_types { +LL | LL ~ let path = match get_file_path(t) { | error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:244:14 + --> tests/ui/unnecessary_to_owned.rs:323:14 | LL | let _ = &["x"][..].to_vec().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `["x"][..].iter().cloned()` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:249:14 + --> tests/ui/unnecessary_to_owned.rs:329:14 | LL | let _ = &["x"][..].to_vec().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `["x"][..].iter().copied()` error: unnecessary use of `to_string` - --> tests/ui/unnecessary_to_owned.rs:297:24 + --> tests/ui/unnecessary_to_owned.rs:378:24 | LL | Box::new(build(y.to_string())) | ^^^^^^^^^^^^^ help: use: `y` error: unnecessary use of `to_string` - --> tests/ui/unnecessary_to_owned.rs:406:12 + --> tests/ui/unnecessary_to_owned.rs:488:12 | LL | id("abc".to_string()) | ^^^^^^^^^^^^^^^^^ help: use: `"abc"` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:549:37 + --> tests/ui/unnecessary_to_owned.rs:632:37 | LL | IntoFuture::into_future(foo([].to_vec(), &0)); | ^^^^^^^^^^^ help: use: `[]` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:559:18 + --> tests/ui/unnecessary_to_owned.rs:643:18 | LL | s.remove(&a.to_vec()); | ^^^^^^^^^^^ help: replace it with: `a` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:563:14 + --> tests/ui/unnecessary_to_owned.rs:648:14 | LL | s.remove(&"b".to_owned()); | ^^^^^^^^^^^^^^^ help: replace it with: `"b"` error: unnecessary use of `to_string` - --> tests/ui/unnecessary_to_owned.rs:564:14 + --> tests/ui/unnecessary_to_owned.rs:650:14 | LL | s.remove(&"b".to_string()); | ^^^^^^^^^^^^^^^^ help: replace it with: `"b"` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:569:14 + --> tests/ui/unnecessary_to_owned.rs:656:14 | LL | s.remove(&["b"].to_vec()); | ^^^^^^^^^^^^^^^ help: replace it with: `["b"].as_slice()` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:570:14 + --> tests/ui/unnecessary_to_owned.rs:658:14 | LL | s.remove(&(&["b"]).to_vec()); | ^^^^^^^^^^^^^^^^^^ help: replace it with: `(&["b"]).as_slice()` diff --git a/tests/ui/unnecessary_to_owned_on_split.fixed b/tests/ui/unnecessary_to_owned_on_split.fixed index e0ba216f41bf..f43d92a2d9ba 100644 --- a/tests/ui/unnecessary_to_owned_on_split.fixed +++ b/tests/ui/unnecessary_to_owned_on_split.fixed @@ -17,22 +17,29 @@ impl ToString for Issue12068 { fn main() { let _ = "a".split('a').next().unwrap(); - //~^ ERROR: unnecessary use of `to_string` + //~^ unnecessary_to_owned + let _ = "a".split("a").next().unwrap(); - //~^ ERROR: unnecessary use of `to_string` + //~^ unnecessary_to_owned + let _ = "a".split('a').next().unwrap(); - //~^ ERROR: unnecessary use of `to_owned` + //~^ unnecessary_to_owned + let _ = "a".split("a").next().unwrap(); - //~^ ERROR: unnecessary use of `to_owned` + //~^ unnecessary_to_owned + let _ = Issue12068.as_ref().split('a').next().unwrap(); - //~^ ERROR: unnecessary use of `to_string` + //~^ unnecessary_to_owned let _ = [1].split(|x| *x == 2).next().unwrap(); - //~^ ERROR: unnecessary use of `to_vec` + //~^ unnecessary_to_owned + let _ = [1].split(|x| *x == 2).next().unwrap(); - //~^ ERROR: unnecessary use of `to_vec` + //~^ unnecessary_to_owned + let _ = [1].split(|x| *x == 2).next().unwrap(); - //~^ ERROR: unnecessary use of `to_owned` + //~^ unnecessary_to_owned + let _ = [1].split(|x| *x == 2).next().unwrap(); - //~^ ERROR: unnecessary use of `to_owned` + //~^ unnecessary_to_owned } diff --git a/tests/ui/unnecessary_to_owned_on_split.rs b/tests/ui/unnecessary_to_owned_on_split.rs index 70efc6ebba5d..bdf5f98bf61e 100644 --- a/tests/ui/unnecessary_to_owned_on_split.rs +++ b/tests/ui/unnecessary_to_owned_on_split.rs @@ -17,22 +17,29 @@ impl ToString for Issue12068 { fn main() { let _ = "a".to_string().split('a').next().unwrap(); - //~^ ERROR: unnecessary use of `to_string` + //~^ unnecessary_to_owned + let _ = "a".to_string().split("a").next().unwrap(); - //~^ ERROR: unnecessary use of `to_string` + //~^ unnecessary_to_owned + let _ = "a".to_owned().split('a').next().unwrap(); - //~^ ERROR: unnecessary use of `to_owned` + //~^ unnecessary_to_owned + let _ = "a".to_owned().split("a").next().unwrap(); - //~^ ERROR: unnecessary use of `to_owned` + //~^ unnecessary_to_owned + let _ = Issue12068.to_string().split('a').next().unwrap(); - //~^ ERROR: unnecessary use of `to_string` + //~^ unnecessary_to_owned let _ = [1].to_vec().split(|x| *x == 2).next().unwrap(); - //~^ ERROR: unnecessary use of `to_vec` + //~^ unnecessary_to_owned + let _ = [1].to_vec().split(|x| *x == 2).next().unwrap(); - //~^ ERROR: unnecessary use of `to_vec` + //~^ unnecessary_to_owned + let _ = [1].to_owned().split(|x| *x == 2).next().unwrap(); - //~^ ERROR: unnecessary use of `to_owned` + //~^ unnecessary_to_owned + let _ = [1].to_owned().split(|x| *x == 2).next().unwrap(); - //~^ ERROR: unnecessary use of `to_owned` + //~^ unnecessary_to_owned } diff --git a/tests/ui/unnecessary_to_owned_on_split.stderr b/tests/ui/unnecessary_to_owned_on_split.stderr index cf5c964bcf3c..5e4fbb1035d6 100644 --- a/tests/ui/unnecessary_to_owned_on_split.stderr +++ b/tests/ui/unnecessary_to_owned_on_split.stderr @@ -8,49 +8,49 @@ LL | let _ = "a".to_string().split('a').next().unwrap(); = help: to override `-D warnings` add `#[allow(clippy::unnecessary_to_owned)]` error: unnecessary use of `to_string` - --> tests/ui/unnecessary_to_owned_on_split.rs:21:13 + --> tests/ui/unnecessary_to_owned_on_split.rs:22:13 | LL | let _ = "a".to_string().split("a").next().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `"a".split("a")` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned_on_split.rs:23:13 + --> tests/ui/unnecessary_to_owned_on_split.rs:25:13 | LL | let _ = "a".to_owned().split('a').next().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `"a".split('a')` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned_on_split.rs:25:13 + --> tests/ui/unnecessary_to_owned_on_split.rs:28:13 | LL | let _ = "a".to_owned().split("a").next().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `"a".split("a")` error: unnecessary use of `to_string` - --> tests/ui/unnecessary_to_owned_on_split.rs:27:13 + --> tests/ui/unnecessary_to_owned_on_split.rs:31:13 | LL | let _ = Issue12068.to_string().split('a').next().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Issue12068.as_ref().split('a')` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned_on_split.rs:30:13 + --> tests/ui/unnecessary_to_owned_on_split.rs:34:13 | LL | let _ = [1].to_vec().split(|x| *x == 2).next().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[1].split(|x| *x == 2)` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned_on_split.rs:32:13 + --> tests/ui/unnecessary_to_owned_on_split.rs:37:13 | LL | let _ = [1].to_vec().split(|x| *x == 2).next().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[1].split(|x| *x == 2)` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned_on_split.rs:34:13 + --> tests/ui/unnecessary_to_owned_on_split.rs:40:13 | LL | let _ = [1].to_owned().split(|x| *x == 2).next().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[1].split(|x| *x == 2)` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned_on_split.rs:36:13 + --> tests/ui/unnecessary_to_owned_on_split.rs:43:13 | LL | let _ = [1].to_owned().split(|x| *x == 2).next().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[1].split(|x| *x == 2)` diff --git a/tests/ui/unnecessary_unsafety_doc.rs b/tests/ui/unnecessary_unsafety_doc.rs index 5ad117eb8db6..7a847d2e3b50 100644 --- a/tests/ui/unnecessary_unsafety_doc.rs +++ b/tests/ui/unnecessary_unsafety_doc.rs @@ -17,6 +17,7 @@ pub fn destroy_the_planet() { /// /// This function shouldn't be called unless the horsemen are ready pub fn apocalypse(universe: &mut ()) { + //~^ unnecessary_safety_doc unimplemented!(); } @@ -43,6 +44,7 @@ mod private_mod { /// /// Unnecessary safety! pub fn republished() { + //~^ unnecessary_safety_doc unimplemented!(); } } @@ -56,6 +58,7 @@ pub trait SafeTraitSafeMethods { /// /// Unnecessary! fn documented(self); + //~^ unnecessary_safety_doc } pub trait SafeTrait { @@ -66,6 +69,7 @@ pub trait SafeTrait { /// /// Unnecessary! pub trait DocumentedSafeTrait { + //~^ unnecessary_safety_doc fn method2(); } @@ -94,6 +98,7 @@ impl Struct { /// /// Unnecessary! pub fn documented() -> Self { + //~^ unnecessary_safety_doc unimplemented!(); } @@ -121,6 +126,7 @@ macro_rules! very_safe { /// /// Driving is very safe already! pub fn drive() { + //~^ unnecessary_safety_doc whee() } }; @@ -149,5 +155,6 @@ pub mod __macro { /// # Implementation safety pub trait DocumentedSafeTraitWithImplementationHeader { + //~^ unnecessary_safety_doc fn method(); } diff --git a/tests/ui/unnecessary_unsafety_doc.stderr b/tests/ui/unnecessary_unsafety_doc.stderr index d8a9f0aa38c3..dd9d8b65f75e 100644 --- a/tests/ui/unnecessary_unsafety_doc.stderr +++ b/tests/ui/unnecessary_unsafety_doc.stderr @@ -8,31 +8,31 @@ LL | pub fn apocalypse(universe: &mut ()) { = help: to override `-D warnings` add `#[allow(clippy::unnecessary_safety_doc)]` error: safe function's docs have unnecessary `# Safety` section - --> tests/ui/unnecessary_unsafety_doc.rs:45:5 + --> tests/ui/unnecessary_unsafety_doc.rs:46:5 | LL | pub fn republished() { | ^^^^^^^^^^^^^^^^^^^^ error: safe function's docs have unnecessary `# Safety` section - --> tests/ui/unnecessary_unsafety_doc.rs:58:5 + --> tests/ui/unnecessary_unsafety_doc.rs:60:5 | LL | fn documented(self); | ^^^^^^^^^^^^^^^^^^^^ error: docs for safe trait have unnecessary `# Safety` section - --> tests/ui/unnecessary_unsafety_doc.rs:68:1 + --> tests/ui/unnecessary_unsafety_doc.rs:71:1 | LL | pub trait DocumentedSafeTrait { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: safe function's docs have unnecessary `# Safety` section - --> tests/ui/unnecessary_unsafety_doc.rs:96:5 + --> tests/ui/unnecessary_unsafety_doc.rs:100:5 | LL | pub fn documented() -> Self { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: safe function's docs have unnecessary `# Safety` section - --> tests/ui/unnecessary_unsafety_doc.rs:123:9 + --> tests/ui/unnecessary_unsafety_doc.rs:128:9 | LL | pub fn drive() { | ^^^^^^^^^^^^^^ @@ -43,7 +43,7 @@ LL | very_safe!(); = note: this error originates in the macro `very_safe` (in Nightly builds, run with -Z macro-backtrace for more info) error: docs for safe trait have unnecessary `# Safety` section - --> tests/ui/unnecessary_unsafety_doc.rs:151:1 + --> tests/ui/unnecessary_unsafety_doc.rs:157:1 | LL | pub trait DocumentedSafeTraitWithImplementationHeader { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unnecessary_wraps.rs b/tests/ui/unnecessary_wraps.rs index 200aefff1bbf..4770ef3b4830 100644 --- a/tests/ui/unnecessary_wraps.rs +++ b/tests/ui/unnecessary_wraps.rs @@ -7,8 +7,8 @@ // should be linted fn func1(a: bool, b: bool) -> Option { - //~^ ERROR: this function's return value is unnecessarily wrapped by `Option` - //~| NOTE: `-D clippy::unnecessary-wraps` implied by `-D warnings` + //~^ unnecessary_wraps + if a && b { return Some(42); } @@ -22,7 +22,8 @@ fn func1(a: bool, b: bool) -> Option { // should be linted fn func2(a: bool, b: bool) -> Option { - //~^ ERROR: this function's return value is unnecessarily wrapped by `Option` + //~^ unnecessary_wraps + if a && b { return Some(10); } @@ -41,7 +42,8 @@ fn func4(a: bool) -> Option { // should be linted fn func5() -> Option { - //~^ ERROR: this function's return value is unnecessarily wrapped by `Option` + //~^ unnecessary_wraps + Some(1) } @@ -52,7 +54,8 @@ fn func6() -> Option { // should be linted fn func7() -> Result { - //~^ ERROR: this function's return value is unnecessarily wrapped by `Result` + //~^ unnecessary_wraps + Ok(1) } @@ -81,7 +84,8 @@ impl A { // should be linted fn func12() -> Option { - //~^ ERROR: this function's return value is unnecessarily wrapped by `Option` + //~^ unnecessary_wraps + Some(1) } } @@ -109,7 +113,8 @@ fn issue_6384(s: &str) -> Option<&str> { // should be linted fn issue_6640_1(a: bool, b: bool) -> Option<()> { - //~^ ERROR: this function's return value is unnecessary + //~^ unnecessary_wraps + if a && b { return Some(()); } @@ -123,7 +128,8 @@ fn issue_6640_1(a: bool, b: bool) -> Option<()> { // should be linted fn issue_6640_2(a: bool, b: bool) -> Result<(), i32> { - //~^ ERROR: this function's return value is unnecessary + //~^ unnecessary_wraps + if a && b { return Ok(()); } diff --git a/tests/ui/unnecessary_wraps.stderr b/tests/ui/unnecessary_wraps.stderr index b06ab91dc8de..ba562f5a50be 100644 --- a/tests/ui/unnecessary_wraps.stderr +++ b/tests/ui/unnecessary_wraps.stderr @@ -32,9 +32,9 @@ error: this function's return value is unnecessarily wrapped by `Option` | LL | / fn func2(a: bool, b: bool) -> Option { LL | | +LL | | LL | | if a && b { -LL | | return Some(10); -LL | | } +... | LL | | if a { Some(20) } else { Some(30) } LL | | } | |_^ @@ -52,10 +52,11 @@ LL ~ if a { 20 } else { 30 } | error: this function's return value is unnecessarily wrapped by `Option` - --> tests/ui/unnecessary_wraps.rs:43:1 + --> tests/ui/unnecessary_wraps.rs:44:1 | LL | / fn func5() -> Option { LL | | +LL | | LL | | Some(1) LL | | } | |_^ @@ -72,10 +73,11 @@ LL + 1 | error: this function's return value is unnecessarily wrapped by `Result` - --> tests/ui/unnecessary_wraps.rs:54:1 + --> tests/ui/unnecessary_wraps.rs:56:1 | LL | / fn func7() -> Result { LL | | +LL | | LL | | Ok(1) LL | | } | |_^ @@ -92,10 +94,11 @@ LL + 1 | error: this function's return value is unnecessarily wrapped by `Option` - --> tests/ui/unnecessary_wraps.rs:83:5 + --> tests/ui/unnecessary_wraps.rs:86:5 | LL | / fn func12() -> Option { LL | | +LL | | LL | | Some(1) LL | | } | |_____^ @@ -112,12 +115,12 @@ LL + 1 | error: this function's return value is unnecessary - --> tests/ui/unnecessary_wraps.rs:111:1 + --> tests/ui/unnecessary_wraps.rs:115:1 | LL | / fn issue_6640_1(a: bool, b: bool) -> Option<()> { LL | | +LL | | LL | | if a && b { -LL | | return Some(()); ... | LL | | } | |_^ @@ -139,12 +142,12 @@ LL ~ return ; | error: this function's return value is unnecessary - --> tests/ui/unnecessary_wraps.rs:125:1 + --> tests/ui/unnecessary_wraps.rs:130:1 | LL | / fn issue_6640_2(a: bool, b: bool) -> Result<(), i32> { LL | | +LL | | LL | | if a && b { -LL | | return Ok(()); ... | LL | | } | |_^ diff --git a/tests/ui/unneeded_field_pattern.rs b/tests/ui/unneeded_field_pattern.rs index 1d42f81711bd..327b64e7c4aa 100644 --- a/tests/ui/unneeded_field_pattern.rs +++ b/tests/ui/unneeded_field_pattern.rs @@ -16,8 +16,9 @@ fn main() { match f { Foo { a: _, b: 0, .. } => {}, - + //~^ unneeded_field_pattern Foo { a: _, b: _, c: _ } => {}, + //~^ unneeded_field_pattern } match f { Foo { b: 0, .. } => {}, // should be OK diff --git a/tests/ui/unneeded_struct_pattern.fixed b/tests/ui/unneeded_struct_pattern.fixed index 5bd269896a6b..665ab98913be 100644 --- a/tests/ui/unneeded_struct_pattern.fixed +++ b/tests/ui/unneeded_struct_pattern.fixed @@ -15,11 +15,13 @@ fn main() { match Some(114514) { Some(v) => v, None => 0, + //~^ unneeded_struct_pattern }; match Some(1919810) { Some(v) => v, None => 0, + //~^ unneeded_struct_pattern }; match Some(123456) { @@ -30,15 +32,23 @@ fn main() { match Some(Some(123456)) { Some(Some(v)) => v, Some(None) => 0, + //~^ unneeded_struct_pattern None => 0, + //~^ unneeded_struct_pattern }; if let None = Some(0) {} + //~^ unneeded_struct_pattern if let None = Some(0) {} + //~^ unneeded_struct_pattern if let Some(None) = Some(Some(0)) {} + //~^ unneeded_struct_pattern let None = Some(0) else { panic!() }; + //~^ unneeded_struct_pattern let None = Some(0) else { panic!() }; + //~^ unneeded_struct_pattern let Some(None) = Some(Some(0)) else { panic!() }; + //~^ unneeded_struct_pattern enum Custom { HasFields { @@ -54,26 +64,28 @@ fn main() { match Custom::Init { Custom::HasFields { field: value } => value, Custom::HasBracketsNoFields {} => 0, - Custom::NoBrackets => 0, //~ ERROR: struct pattern is not needed for a unit variant - Custom::NoBracketsNonExhaustive => 0, //~ ERROR: struct pattern is not needed for a unit variant + Custom::NoBrackets => 0, //~ unneeded_struct_pattern + Custom::NoBracketsNonExhaustive => 0, //~ unneeded_struct_pattern _ => 0, }; match Custom::Init { Custom::HasFields { field: value } => value, Custom::HasBracketsNoFields { .. } => 0, - Custom::NoBrackets => 0, //~ ERROR: struct pattern is not needed for a unit variant - Custom::NoBracketsNonExhaustive => 0, //~ ERROR: struct pattern is not needed for a unit variant + Custom::NoBrackets => 0, //~ unneeded_struct_pattern + Custom::NoBracketsNonExhaustive => 0, //~ unneeded_struct_pattern _ => 0, }; match Custom::Init { - Custom::NoBrackets if true => 0, //~ ERROR: struct pattern is not needed for a unit variant + Custom::NoBrackets if true => 0, //~ unneeded_struct_pattern _ => 0, }; match Custom::Init { - Custom::NoBrackets | Custom::NoBracketsNonExhaustive => 0, //~ ERROR: struct pattern is not needed for a unit variant + Custom::NoBrackets | Custom::NoBracketsNonExhaustive => 0, + //~^ unneeded_struct_pattern + //~| unneeded_struct_pattern _ => 0, }; @@ -87,23 +99,24 @@ fn main() { noop(); } if let Custom::NoBrackets = Custom::Init { - //~^ ERROR: struct pattern is not needed for a unit variant + //~^ unneeded_struct_pattern noop(); } if let Custom::NoBrackets = Custom::Init { - //~^ ERROR: struct pattern is not needed for a unit variant + //~^ unneeded_struct_pattern noop(); } if let Custom::NoBrackets | Custom::NoBracketsNonExhaustive = Custom::Init { - //~^ ERROR: struct pattern is not needed for a unit variant + //~^ unneeded_struct_pattern + //~| unneeded_struct_pattern noop(); } if let Custom::NoBracketsNonExhaustive = Custom::Init { - //~^ ERROR: struct pattern is not needed for a unit variant + //~^ unneeded_struct_pattern noop(); } if let Custom::NoBracketsNonExhaustive = Custom::Init { - //~^ ERROR: struct pattern is not needed for a unit variant + //~^ unneeded_struct_pattern noop(); } @@ -118,18 +131,18 @@ fn main() { let Custom::HasBracketsNoFields { .. } = Custom::Init else { panic!() }; - let Custom::NoBrackets = Custom::Init else { panic!() }; //~ ERROR: struct pattern is not needed for a unit variant + let Custom::NoBrackets = Custom::Init else { panic!() }; //~ unneeded_struct_pattern let Custom::NoBrackets = Custom::Init else { - //~^ ERROR: struct pattern is not needed for a unit variant + //~^ unneeded_struct_pattern panic!() }; let Custom::NoBracketsNonExhaustive = Custom::Init else { - //~^ ERROR: struct pattern is not needed for a unit variant + //~^ unneeded_struct_pattern panic!() }; let Custom::NoBracketsNonExhaustive = Custom::Init else { - //~^ ERROR: struct pattern is not needed for a unit variant + //~^ unneeded_struct_pattern panic!() }; @@ -137,11 +150,11 @@ fn main() { Variant, } - fn pat_in_fn_param_1(Refutable::Variant: Refutable) {} //~ ERROR: struct pattern is not needed for a unit variant - fn pat_in_fn_param_2(Refutable::Variant: Refutable) {} //~ ERROR: struct pattern is not needed for a unit variant + fn pat_in_fn_param_1(Refutable::Variant: Refutable) {} //~ unneeded_struct_pattern + fn pat_in_fn_param_2(Refutable::Variant: Refutable) {} //~ unneeded_struct_pattern - for Refutable::Variant in [] {} //~ ERROR: struct pattern is not needed for a unit variant - for Refutable::Variant in [] {} //~ ERROR: struct pattern is not needed for a unit variant + for Refutable::Variant in [] {} //~ unneeded_struct_pattern + for Refutable::Variant in [] {} //~ unneeded_struct_pattern } fn external_crate() { @@ -155,13 +168,13 @@ fn external_crate() { match ExhaustiveUnit { // Exhaustive variant - ExhaustiveUnit => 0, //~ ERROR: struct pattern is not needed for a unit variant + ExhaustiveUnit => 0, //~ unneeded_struct_pattern _ => 0, }; match ExhaustiveUnit { // Exhaustive variant - ExhaustiveUnit => 0, //~ ERROR: struct pattern is not needed for a unit variant + ExhaustiveUnit => 0, //~ unneeded_struct_pattern _ => 0, }; diff --git a/tests/ui/unneeded_struct_pattern.rs b/tests/ui/unneeded_struct_pattern.rs index c7658617ad37..7cadb6c7fbb5 100644 --- a/tests/ui/unneeded_struct_pattern.rs +++ b/tests/ui/unneeded_struct_pattern.rs @@ -15,11 +15,13 @@ fn main() { match Some(114514) { Some(v) => v, None {} => 0, + //~^ unneeded_struct_pattern }; match Some(1919810) { Some(v) => v, None { .. } => 0, + //~^ unneeded_struct_pattern }; match Some(123456) { @@ -30,15 +32,23 @@ fn main() { match Some(Some(123456)) { Some(Some(v)) => v, Some(None {}) => 0, + //~^ unneeded_struct_pattern None {} => 0, + //~^ unneeded_struct_pattern }; if let None {} = Some(0) {} + //~^ unneeded_struct_pattern if let None { .. } = Some(0) {} + //~^ unneeded_struct_pattern if let Some(None {}) = Some(Some(0)) {} + //~^ unneeded_struct_pattern let None {} = Some(0) else { panic!() }; + //~^ unneeded_struct_pattern let None { .. } = Some(0) else { panic!() }; + //~^ unneeded_struct_pattern let Some(None {}) = Some(Some(0)) else { panic!() }; + //~^ unneeded_struct_pattern enum Custom { HasFields { @@ -54,26 +64,28 @@ fn main() { match Custom::Init { Custom::HasFields { field: value } => value, Custom::HasBracketsNoFields {} => 0, - Custom::NoBrackets {} => 0, //~ ERROR: struct pattern is not needed for a unit variant - Custom::NoBracketsNonExhaustive {} => 0, //~ ERROR: struct pattern is not needed for a unit variant + Custom::NoBrackets {} => 0, //~ unneeded_struct_pattern + Custom::NoBracketsNonExhaustive {} => 0, //~ unneeded_struct_pattern _ => 0, }; match Custom::Init { Custom::HasFields { field: value } => value, Custom::HasBracketsNoFields { .. } => 0, - Custom::NoBrackets { .. } => 0, //~ ERROR: struct pattern is not needed for a unit variant - Custom::NoBracketsNonExhaustive { .. } => 0, //~ ERROR: struct pattern is not needed for a unit variant + Custom::NoBrackets { .. } => 0, //~ unneeded_struct_pattern + Custom::NoBracketsNonExhaustive { .. } => 0, //~ unneeded_struct_pattern _ => 0, }; match Custom::Init { - Custom::NoBrackets {} if true => 0, //~ ERROR: struct pattern is not needed for a unit variant + Custom::NoBrackets {} if true => 0, //~ unneeded_struct_pattern _ => 0, }; match Custom::Init { - Custom::NoBrackets {} | Custom::NoBracketsNonExhaustive {} => 0, //~ ERROR: struct pattern is not needed for a unit variant + Custom::NoBrackets {} | Custom::NoBracketsNonExhaustive {} => 0, + //~^ unneeded_struct_pattern + //~| unneeded_struct_pattern _ => 0, }; @@ -87,23 +99,24 @@ fn main() { noop(); } if let Custom::NoBrackets {} = Custom::Init { - //~^ ERROR: struct pattern is not needed for a unit variant + //~^ unneeded_struct_pattern noop(); } if let Custom::NoBrackets { .. } = Custom::Init { - //~^ ERROR: struct pattern is not needed for a unit variant + //~^ unneeded_struct_pattern noop(); } if let Custom::NoBrackets {} | Custom::NoBracketsNonExhaustive {} = Custom::Init { - //~^ ERROR: struct pattern is not needed for a unit variant + //~^ unneeded_struct_pattern + //~| unneeded_struct_pattern noop(); } if let Custom::NoBracketsNonExhaustive {} = Custom::Init { - //~^ ERROR: struct pattern is not needed for a unit variant + //~^ unneeded_struct_pattern noop(); } if let Custom::NoBracketsNonExhaustive { .. } = Custom::Init { - //~^ ERROR: struct pattern is not needed for a unit variant + //~^ unneeded_struct_pattern noop(); } @@ -118,18 +131,18 @@ fn main() { let Custom::HasBracketsNoFields { .. } = Custom::Init else { panic!() }; - let Custom::NoBrackets {} = Custom::Init else { panic!() }; //~ ERROR: struct pattern is not needed for a unit variant + let Custom::NoBrackets {} = Custom::Init else { panic!() }; //~ unneeded_struct_pattern let Custom::NoBrackets { .. } = Custom::Init else { - //~^ ERROR: struct pattern is not needed for a unit variant + //~^ unneeded_struct_pattern panic!() }; let Custom::NoBracketsNonExhaustive {} = Custom::Init else { - //~^ ERROR: struct pattern is not needed for a unit variant + //~^ unneeded_struct_pattern panic!() }; let Custom::NoBracketsNonExhaustive { .. } = Custom::Init else { - //~^ ERROR: struct pattern is not needed for a unit variant + //~^ unneeded_struct_pattern panic!() }; @@ -137,11 +150,11 @@ fn main() { Variant, } - fn pat_in_fn_param_1(Refutable::Variant {}: Refutable) {} //~ ERROR: struct pattern is not needed for a unit variant - fn pat_in_fn_param_2(Refutable::Variant { .. }: Refutable) {} //~ ERROR: struct pattern is not needed for a unit variant + fn pat_in_fn_param_1(Refutable::Variant {}: Refutable) {} //~ unneeded_struct_pattern + fn pat_in_fn_param_2(Refutable::Variant { .. }: Refutable) {} //~ unneeded_struct_pattern - for Refutable::Variant {} in [] {} //~ ERROR: struct pattern is not needed for a unit variant - for Refutable::Variant { .. } in [] {} //~ ERROR: struct pattern is not needed for a unit variant + for Refutable::Variant {} in [] {} //~ unneeded_struct_pattern + for Refutable::Variant { .. } in [] {} //~ unneeded_struct_pattern } fn external_crate() { @@ -155,13 +168,13 @@ fn external_crate() { match ExhaustiveUnit { // Exhaustive variant - ExhaustiveUnit { .. } => 0, //~ ERROR: struct pattern is not needed for a unit variant + ExhaustiveUnit { .. } => 0, //~ unneeded_struct_pattern _ => 0, }; match ExhaustiveUnit { // Exhaustive variant - ExhaustiveUnit {} => 0, //~ ERROR: struct pattern is not needed for a unit variant + ExhaustiveUnit {} => 0, //~ unneeded_struct_pattern _ => 0, }; diff --git a/tests/ui/unneeded_struct_pattern.stderr b/tests/ui/unneeded_struct_pattern.stderr index 3a7f59583802..7c0c3c9e4462 100644 --- a/tests/ui/unneeded_struct_pattern.stderr +++ b/tests/ui/unneeded_struct_pattern.stderr @@ -8,193 +8,193 @@ LL | None {} => 0, = help: to override `-D warnings` add `#[allow(clippy::unneeded_struct_pattern)]` error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:22:13 + --> tests/ui/unneeded_struct_pattern.rs:23:13 | LL | None { .. } => 0, | ^^^^^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:32:18 + --> tests/ui/unneeded_struct_pattern.rs:34:18 | LL | Some(None {}) => 0, | ^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:33:13 + --> tests/ui/unneeded_struct_pattern.rs:36:13 | LL | None {} => 0, | ^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:36:16 + --> tests/ui/unneeded_struct_pattern.rs:40:16 | LL | if let None {} = Some(0) {} | ^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:37:16 + --> tests/ui/unneeded_struct_pattern.rs:42:16 | LL | if let None { .. } = Some(0) {} | ^^^^^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:38:21 + --> tests/ui/unneeded_struct_pattern.rs:44:21 | LL | if let Some(None {}) = Some(Some(0)) {} | ^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:39:13 + --> tests/ui/unneeded_struct_pattern.rs:46:13 | LL | let None {} = Some(0) else { panic!() }; | ^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:40:13 + --> tests/ui/unneeded_struct_pattern.rs:48:13 | LL | let None { .. } = Some(0) else { panic!() }; | ^^^^^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:41:18 + --> tests/ui/unneeded_struct_pattern.rs:50:18 | LL | let Some(None {}) = Some(Some(0)) else { panic!() }; | ^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:57:27 + --> tests/ui/unneeded_struct_pattern.rs:67:27 | LL | Custom::NoBrackets {} => 0, | ^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:58:40 + --> tests/ui/unneeded_struct_pattern.rs:68:40 | LL | Custom::NoBracketsNonExhaustive {} => 0, | ^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:65:27 + --> tests/ui/unneeded_struct_pattern.rs:75:27 | LL | Custom::NoBrackets { .. } => 0, | ^^^^^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:66:40 + --> tests/ui/unneeded_struct_pattern.rs:76:40 | LL | Custom::NoBracketsNonExhaustive { .. } => 0, | ^^^^^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:71:27 + --> tests/ui/unneeded_struct_pattern.rs:81:27 | LL | Custom::NoBrackets {} if true => 0, | ^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:76:27 + --> tests/ui/unneeded_struct_pattern.rs:86:27 | LL | Custom::NoBrackets {} | Custom::NoBracketsNonExhaustive {} => 0, | ^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:76:64 + --> tests/ui/unneeded_struct_pattern.rs:86:64 | LL | Custom::NoBrackets {} | Custom::NoBracketsNonExhaustive {} => 0, | ^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:89:30 + --> tests/ui/unneeded_struct_pattern.rs:101:30 | LL | if let Custom::NoBrackets {} = Custom::Init { | ^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:93:30 + --> tests/ui/unneeded_struct_pattern.rs:105:30 | LL | if let Custom::NoBrackets { .. } = Custom::Init { | ^^^^^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:97:30 + --> tests/ui/unneeded_struct_pattern.rs:109:30 | LL | if let Custom::NoBrackets {} | Custom::NoBracketsNonExhaustive {} = Custom::Init { | ^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:97:67 + --> tests/ui/unneeded_struct_pattern.rs:109:67 | LL | if let Custom::NoBrackets {} | Custom::NoBracketsNonExhaustive {} = Custom::Init { | ^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:101:43 + --> tests/ui/unneeded_struct_pattern.rs:114:43 | LL | if let Custom::NoBracketsNonExhaustive {} = Custom::Init { | ^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:105:43 + --> tests/ui/unneeded_struct_pattern.rs:118:43 | LL | if let Custom::NoBracketsNonExhaustive { .. } = Custom::Init { | ^^^^^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:121:27 + --> tests/ui/unneeded_struct_pattern.rs:134:27 | LL | let Custom::NoBrackets {} = Custom::Init else { panic!() }; | ^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:123:27 + --> tests/ui/unneeded_struct_pattern.rs:136:27 | LL | let Custom::NoBrackets { .. } = Custom::Init else { | ^^^^^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:127:40 + --> tests/ui/unneeded_struct_pattern.rs:140:40 | LL | let Custom::NoBracketsNonExhaustive {} = Custom::Init else { | ^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:131:40 + --> tests/ui/unneeded_struct_pattern.rs:144:40 | LL | let Custom::NoBracketsNonExhaustive { .. } = Custom::Init else { | ^^^^^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:140:44 + --> tests/ui/unneeded_struct_pattern.rs:153:44 | LL | fn pat_in_fn_param_1(Refutable::Variant {}: Refutable) {} | ^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:141:44 + --> tests/ui/unneeded_struct_pattern.rs:154:44 | LL | fn pat_in_fn_param_2(Refutable::Variant { .. }: Refutable) {} | ^^^^^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:143:27 + --> tests/ui/unneeded_struct_pattern.rs:156:27 | LL | for Refutable::Variant {} in [] {} | ^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:144:27 + --> tests/ui/unneeded_struct_pattern.rs:157:27 | LL | for Refutable::Variant { .. } in [] {} | ^^^^^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:158:23 + --> tests/ui/unneeded_struct_pattern.rs:171:23 | LL | ExhaustiveUnit { .. } => 0, | ^^^^^^^ help: remove the struct pattern error: struct pattern is not needed for a unit variant - --> tests/ui/unneeded_struct_pattern.rs:164:23 + --> tests/ui/unneeded_struct_pattern.rs:177:23 | LL | ExhaustiveUnit {} => 0, | ^^^ help: remove the struct pattern diff --git a/tests/ui/unneeded_wildcard_pattern.fixed b/tests/ui/unneeded_wildcard_pattern.fixed index cbf91ed4910a..7e6a493b86c1 100644 --- a/tests/ui/unneeded_wildcard_pattern.fixed +++ b/tests/ui/unneeded_wildcard_pattern.fixed @@ -10,11 +10,17 @@ fn main() { let t = (0, 1, 2, 3); if let (0, ..) = t {}; + //~^ unneeded_wildcard_pattern if let (0, ..) = t {}; + //~^ unneeded_wildcard_pattern if let (.., 0) = t {}; + //~^ unneeded_wildcard_pattern if let (.., 0) = t {}; + //~^ unneeded_wildcard_pattern if let (0, ..) = t {}; + //~^ unneeded_wildcard_pattern if let (0, ..) = t {}; + //~^ unneeded_wildcard_pattern if let (_, 0, ..) = t {}; if let (.., 0, _) = t {}; if let (0, _, _, _) = t {}; @@ -24,6 +30,7 @@ fn main() { #[rustfmt::skip] { if let (0, ..,) = t {}; + //~^ unneeded_wildcard_pattern } struct S(usize, usize, usize, usize); @@ -31,11 +38,17 @@ fn main() { let s = S(0, 1, 2, 3); if let S(0, ..) = s {}; + //~^ unneeded_wildcard_pattern if let S(0, ..) = s {}; + //~^ unneeded_wildcard_pattern if let S(.., 0) = s {}; + //~^ unneeded_wildcard_pattern if let S(.., 0) = s {}; + //~^ unneeded_wildcard_pattern if let S(0, ..) = s {}; + //~^ unneeded_wildcard_pattern if let S(0, ..) = s {}; + //~^ unneeded_wildcard_pattern if let S(_, 0, ..) = s {}; if let S(.., 0, _) = s {}; if let S(0, _, _, _) = s {}; @@ -45,6 +58,7 @@ fn main() { #[rustfmt::skip] { if let S(0, ..,) = s {}; + //~^ unneeded_wildcard_pattern } external! { let t = (0, 1, 2, 3); diff --git a/tests/ui/unneeded_wildcard_pattern.rs b/tests/ui/unneeded_wildcard_pattern.rs index 10df2b93d5e0..c91383e2cca5 100644 --- a/tests/ui/unneeded_wildcard_pattern.rs +++ b/tests/ui/unneeded_wildcard_pattern.rs @@ -10,11 +10,17 @@ fn main() { let t = (0, 1, 2, 3); if let (0, .., _) = t {}; + //~^ unneeded_wildcard_pattern if let (0, _, ..) = t {}; + //~^ unneeded_wildcard_pattern if let (_, .., 0) = t {}; + //~^ unneeded_wildcard_pattern if let (.., _, 0) = t {}; + //~^ unneeded_wildcard_pattern if let (0, _, _, ..) = t {}; + //~^ unneeded_wildcard_pattern if let (0, .., _, _) = t {}; + //~^ unneeded_wildcard_pattern if let (_, 0, ..) = t {}; if let (.., 0, _) = t {}; if let (0, _, _, _) = t {}; @@ -24,6 +30,7 @@ fn main() { #[rustfmt::skip] { if let (0, .., _, _,) = t {}; + //~^ unneeded_wildcard_pattern } struct S(usize, usize, usize, usize); @@ -31,11 +38,17 @@ fn main() { let s = S(0, 1, 2, 3); if let S(0, .., _) = s {}; + //~^ unneeded_wildcard_pattern if let S(0, _, ..) = s {}; + //~^ unneeded_wildcard_pattern if let S(_, .., 0) = s {}; + //~^ unneeded_wildcard_pattern if let S(.., _, 0) = s {}; + //~^ unneeded_wildcard_pattern if let S(0, _, _, ..) = s {}; + //~^ unneeded_wildcard_pattern if let S(0, .., _, _) = s {}; + //~^ unneeded_wildcard_pattern if let S(_, 0, ..) = s {}; if let S(.., 0, _) = s {}; if let S(0, _, _, _) = s {}; @@ -45,6 +58,7 @@ fn main() { #[rustfmt::skip] { if let S(0, .., _, _,) = s {}; + //~^ unneeded_wildcard_pattern } external! { let t = (0, 1, 2, 3); diff --git a/tests/ui/unneeded_wildcard_pattern.stderr b/tests/ui/unneeded_wildcard_pattern.stderr index ceb7d7fe9e09..20666268a8ca 100644 --- a/tests/ui/unneeded_wildcard_pattern.stderr +++ b/tests/ui/unneeded_wildcard_pattern.stderr @@ -11,79 +11,79 @@ LL | #![deny(clippy::unneeded_wildcard_pattern)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this pattern is unneeded as the `..` pattern can match that element - --> tests/ui/unneeded_wildcard_pattern.rs:13:16 + --> tests/ui/unneeded_wildcard_pattern.rs:14:16 | LL | if let (0, _, ..) = t {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> tests/ui/unneeded_wildcard_pattern.rs:14:13 + --> tests/ui/unneeded_wildcard_pattern.rs:16:13 | LL | if let (_, .., 0) = t {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> tests/ui/unneeded_wildcard_pattern.rs:15:15 + --> tests/ui/unneeded_wildcard_pattern.rs:18:15 | LL | if let (.., _, 0) = t {}; | ^^^ help: remove it error: these patterns are unneeded as the `..` pattern can match those elements - --> tests/ui/unneeded_wildcard_pattern.rs:16:16 + --> tests/ui/unneeded_wildcard_pattern.rs:20:16 | LL | if let (0, _, _, ..) = t {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> tests/ui/unneeded_wildcard_pattern.rs:17:18 + --> tests/ui/unneeded_wildcard_pattern.rs:22:18 | LL | if let (0, .., _, _) = t {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> tests/ui/unneeded_wildcard_pattern.rs:26:22 + --> tests/ui/unneeded_wildcard_pattern.rs:32:22 | LL | if let (0, .., _, _,) = t {}; | ^^^^^^ help: remove them error: this pattern is unneeded as the `..` pattern can match that element - --> tests/ui/unneeded_wildcard_pattern.rs:33:19 + --> tests/ui/unneeded_wildcard_pattern.rs:40:19 | LL | if let S(0, .., _) = s {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> tests/ui/unneeded_wildcard_pattern.rs:34:17 + --> tests/ui/unneeded_wildcard_pattern.rs:42:17 | LL | if let S(0, _, ..) = s {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> tests/ui/unneeded_wildcard_pattern.rs:35:14 + --> tests/ui/unneeded_wildcard_pattern.rs:44:14 | LL | if let S(_, .., 0) = s {}; | ^^^ help: remove it error: this pattern is unneeded as the `..` pattern can match that element - --> tests/ui/unneeded_wildcard_pattern.rs:36:16 + --> tests/ui/unneeded_wildcard_pattern.rs:46:16 | LL | if let S(.., _, 0) = s {}; | ^^^ help: remove it error: these patterns are unneeded as the `..` pattern can match those elements - --> tests/ui/unneeded_wildcard_pattern.rs:37:17 + --> tests/ui/unneeded_wildcard_pattern.rs:48:17 | LL | if let S(0, _, _, ..) = s {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> tests/ui/unneeded_wildcard_pattern.rs:38:19 + --> tests/ui/unneeded_wildcard_pattern.rs:50:19 | LL | if let S(0, .., _, _) = s {}; | ^^^^^^ help: remove them error: these patterns are unneeded as the `..` pattern can match those elements - --> tests/ui/unneeded_wildcard_pattern.rs:47:23 + --> tests/ui/unneeded_wildcard_pattern.rs:60:23 | LL | if let S(0, .., _, _,) = s {}; | ^^^^^^ help: remove them diff --git a/tests/ui/unnested_or_patterns.fixed b/tests/ui/unnested_or_patterns.fixed index 53ec556d1008..791b2fa131f2 100644 --- a/tests/ui/unnested_or_patterns.fixed +++ b/tests/ui/unnested_or_patterns.fixed @@ -14,27 +14,43 @@ fn main() { if let &0 | &2 = &0 {} if let box (0 | 2) = Box::new(0) {} + //~^ unnested_or_patterns if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} + //~^ unnested_or_patterns const C0: Option = Some(1); if let Some(1 | 2) | C0 = None {} + //~^ unnested_or_patterns if let &mut (0 | 2) = &mut 0 {} + //~^ unnested_or_patterns if let x @ (0 | 2) = 0 {} + //~^ unnested_or_patterns if let (0, 1 | 2 | 3) = (0, 0) {} + //~^ unnested_or_patterns if let (1 | 2 | 3, 0) = (0, 0) {} + //~^ unnested_or_patterns if let (x, ..) | (x, 1 | 2) = (0, 1) {} + //~^ unnested_or_patterns if let [0 | 1] = [0] {} + //~^ unnested_or_patterns if let [x, 0 | 1] = [0, 1] {} + //~^ unnested_or_patterns if let [x, 0 | 1 | 2] = [0, 1] {} + //~^ unnested_or_patterns if let [x, ..] | [x, 1 | 2] = [0, 1] {} + //~^ unnested_or_patterns struct TS(u8, u8); if let TS(0 | 1, x) = TS(0, 0) {} + //~^ unnested_or_patterns if let TS(1 | 2 | 3, 0) = TS(0, 0) {} + //~^ unnested_or_patterns if let TS(x, ..) | TS(x, 1 | 2) = TS(0, 0) {} + //~^ unnested_or_patterns struct S { x: u8, y: u8, } if let S { x: 0 | 1, y } = (S { x: 0, y: 1 }) {} + //~^ unnested_or_patterns if let S { x: 0, y, .. } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} } @@ -46,4 +62,5 @@ fn msrv_1_52() { #[clippy::msrv = "1.53"] fn msrv_1_53() { if let [1 | 53] = [0] {} + //~^ unnested_or_patterns } diff --git a/tests/ui/unnested_or_patterns.rs b/tests/ui/unnested_or_patterns.rs index e5e378e922af..e7e7c7cd2e49 100644 --- a/tests/ui/unnested_or_patterns.rs +++ b/tests/ui/unnested_or_patterns.rs @@ -14,27 +14,43 @@ fn main() { if let &0 | &2 = &0 {} if let box 0 | box 2 = Box::new(0) {} + //~^ unnested_or_patterns if let box ((0 | 1)) | box (2 | 3) | box 4 = Box::new(0) {} + //~^ unnested_or_patterns const C0: Option = Some(1); if let Some(1) | C0 | Some(2) = None {} + //~^ unnested_or_patterns if let &mut 0 | &mut 2 = &mut 0 {} + //~^ unnested_or_patterns if let x @ 0 | x @ 2 = 0 {} + //~^ unnested_or_patterns if let (0, 1) | (0, 2) | (0, 3) = (0, 0) {} + //~^ unnested_or_patterns if let (1, 0) | (2, 0) | (3, 0) = (0, 0) {} + //~^ unnested_or_patterns if let (x, ..) | (x, 1) | (x, 2) = (0, 1) {} + //~^ unnested_or_patterns if let [0] | [1] = [0] {} + //~^ unnested_or_patterns if let [x, 0] | [x, 1] = [0, 1] {} + //~^ unnested_or_patterns if let [x, 0] | [x, 1] | [x, 2] = [0, 1] {} + //~^ unnested_or_patterns if let [x, ..] | [x, 1] | [x, 2] = [0, 1] {} + //~^ unnested_or_patterns struct TS(u8, u8); if let TS(0, x) | TS(1, x) = TS(0, 0) {} + //~^ unnested_or_patterns if let TS(1, 0) | TS(2, 0) | TS(3, 0) = TS(0, 0) {} + //~^ unnested_or_patterns if let TS(x, ..) | TS(x, 1) | TS(x, 2) = TS(0, 0) {} + //~^ unnested_or_patterns struct S { x: u8, y: u8, } if let S { x: 0, y } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} + //~^ unnested_or_patterns if let S { x: 0, y, .. } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} } @@ -46,4 +62,5 @@ fn msrv_1_52() { #[clippy::msrv = "1.53"] fn msrv_1_53() { if let [1] | [53] = [0] {} + //~^ unnested_or_patterns } diff --git a/tests/ui/unnested_or_patterns.stderr b/tests/ui/unnested_or_patterns.stderr index 4325df143042..ec5eb983c5a0 100644 --- a/tests/ui/unnested_or_patterns.stderr +++ b/tests/ui/unnested_or_patterns.stderr @@ -13,7 +13,7 @@ LL + if let box (0 | 2) = Box::new(0) {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:17:12 + --> tests/ui/unnested_or_patterns.rs:18:12 | LL | if let box ((0 | 1)) | box (2 | 3) | box 4 = Box::new(0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:19:12 + --> tests/ui/unnested_or_patterns.rs:21:12 | LL | if let Some(1) | C0 | Some(2) = None {} | ^^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + if let Some(1 | 2) | C0 = None {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:20:12 + --> tests/ui/unnested_or_patterns.rs:23:12 | LL | if let &mut 0 | &mut 2 = &mut 0 {} | ^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + if let &mut (0 | 2) = &mut 0 {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:21:12 + --> tests/ui/unnested_or_patterns.rs:25:12 | LL | if let x @ 0 | x @ 2 = 0 {} | ^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + if let x @ (0 | 2) = 0 {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:22:12 + --> tests/ui/unnested_or_patterns.rs:27:12 | LL | if let (0, 1) | (0, 2) | (0, 3) = (0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + if let (0, 1 | 2 | 3) = (0, 0) {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:23:12 + --> tests/ui/unnested_or_patterns.rs:29:12 | LL | if let (1, 0) | (2, 0) | (3, 0) = (0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + if let (1 | 2 | 3, 0) = (0, 0) {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:24:12 + --> tests/ui/unnested_or_patterns.rs:31:12 | LL | if let (x, ..) | (x, 1) | (x, 2) = (0, 1) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL + if let (x, ..) | (x, 1 | 2) = (0, 1) {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:25:12 + --> tests/ui/unnested_or_patterns.rs:33:12 | LL | if let [0] | [1] = [0] {} | ^^^^^^^^^ @@ -109,7 +109,7 @@ LL + if let [0 | 1] = [0] {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:26:12 + --> tests/ui/unnested_or_patterns.rs:35:12 | LL | if let [x, 0] | [x, 1] = [0, 1] {} | ^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL + if let [x, 0 | 1] = [0, 1] {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:27:12 + --> tests/ui/unnested_or_patterns.rs:37:12 | LL | if let [x, 0] | [x, 1] | [x, 2] = [0, 1] {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL + if let [x, 0 | 1 | 2] = [0, 1] {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:28:12 + --> tests/ui/unnested_or_patterns.rs:39:12 | LL | if let [x, ..] | [x, 1] | [x, 2] = [0, 1] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -145,7 +145,7 @@ LL + if let [x, ..] | [x, 1 | 2] = [0, 1] {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:30:12 + --> tests/ui/unnested_or_patterns.rs:42:12 | LL | if let TS(0, x) | TS(1, x) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL + if let TS(0 | 1, x) = TS(0, 0) {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:31:12 + --> tests/ui/unnested_or_patterns.rs:44:12 | LL | if let TS(1, 0) | TS(2, 0) | TS(3, 0) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -169,7 +169,7 @@ LL + if let TS(1 | 2 | 3, 0) = TS(0, 0) {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:32:12 + --> tests/ui/unnested_or_patterns.rs:46:12 | LL | if let TS(x, ..) | TS(x, 1) | TS(x, 2) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -181,7 +181,7 @@ LL + if let TS(x, ..) | TS(x, 1 | 2) = TS(0, 0) {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:37:12 + --> tests/ui/unnested_or_patterns.rs:52:12 | LL | if let S { x: 0, y } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -193,7 +193,7 @@ LL + if let S { x: 0 | 1, y } = (S { x: 0, y: 1 }) {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:48:12 + --> tests/ui/unnested_or_patterns.rs:64:12 | LL | if let [1] | [53] = [0] {} | ^^^^^^^^^^ diff --git a/tests/ui/unnested_or_patterns2.fixed b/tests/ui/unnested_or_patterns2.fixed index b2a4e83dadc3..6d601ea5e57f 100644 --- a/tests/ui/unnested_or_patterns2.fixed +++ b/tests/ui/unnested_or_patterns2.fixed @@ -10,11 +10,19 @@ fn main() { if let Some(Some(0 | 1)) = None {} + //~^ unnested_or_patterns if let Some(Some(0 | 1 | 2)) = None {} + //~^ unnested_or_patterns if let Some(Some(0 | 1 | 2 | 3 | 4)) = None {} + //~^ unnested_or_patterns if let Some(Some(0 | 1 | 2)) = None {} + //~^ unnested_or_patterns if let ((0 | 1 | 2,),) = ((0,),) {} + //~^ unnested_or_patterns if let 0 | 1 | 2 = 0 {} + //~^ unnested_or_patterns if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} + //~^ unnested_or_patterns if let box box (0 | 2 | 4) = Box::new(Box::new(0)) {} + //~^ unnested_or_patterns } diff --git a/tests/ui/unnested_or_patterns2.rs b/tests/ui/unnested_or_patterns2.rs index 58435f8990d2..7e5ea0161bff 100644 --- a/tests/ui/unnested_or_patterns2.rs +++ b/tests/ui/unnested_or_patterns2.rs @@ -10,11 +10,19 @@ fn main() { if let Some(Some(0)) | Some(Some(1)) = None {} + //~^ unnested_or_patterns if let Some(Some(0)) | Some(Some(1) | Some(2)) = None {} + //~^ unnested_or_patterns if let Some(Some(0 | 1) | Some(2)) | Some(Some(3) | Some(4)) = None {} + //~^ unnested_or_patterns if let Some(Some(0) | Some(1 | 2)) = None {} + //~^ unnested_or_patterns if let ((0,),) | ((1,) | (2,),) = ((0,),) {} + //~^ unnested_or_patterns if let 0 | (1 | 2) = 0 {} + //~^ unnested_or_patterns if let box (0 | 1) | (box 2 | box (3 | 4)) = Box::new(0) {} + //~^ unnested_or_patterns if let box box 0 | box (box 2 | box 4) = Box::new(Box::new(0)) {} + //~^ unnested_or_patterns } diff --git a/tests/ui/unnested_or_patterns2.stderr b/tests/ui/unnested_or_patterns2.stderr index 3d8968551b96..3fc8fa174c93 100644 --- a/tests/ui/unnested_or_patterns2.stderr +++ b/tests/ui/unnested_or_patterns2.stderr @@ -13,7 +13,7 @@ LL + if let Some(Some(0 | 1)) = None {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns2.rs:13:12 + --> tests/ui/unnested_or_patterns2.rs:14:12 | LL | if let Some(Some(0)) | Some(Some(1) | Some(2)) = None {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + if let Some(Some(0 | 1 | 2)) = None {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns2.rs:14:12 + --> tests/ui/unnested_or_patterns2.rs:16:12 | LL | if let Some(Some(0 | 1) | Some(2)) | Some(Some(3) | Some(4)) = None {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + if let Some(Some(0 | 1 | 2 | 3 | 4)) = None {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns2.rs:15:12 + --> tests/ui/unnested_or_patterns2.rs:18:12 | LL | if let Some(Some(0) | Some(1 | 2)) = None {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + if let Some(Some(0 | 1 | 2)) = None {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns2.rs:16:12 + --> tests/ui/unnested_or_patterns2.rs:20:12 | LL | if let ((0,),) | ((1,) | (2,),) = ((0,),) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + if let ((0 | 1 | 2,),) = ((0,),) {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns2.rs:17:12 + --> tests/ui/unnested_or_patterns2.rs:22:12 | LL | if let 0 | (1 | 2) = 0 {} | ^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + if let 0 | 1 | 2 = 0 {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns2.rs:18:12 + --> tests/ui/unnested_or_patterns2.rs:24:12 | LL | if let box (0 | 1) | (box 2 | box (3 | 4)) = Box::new(0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns2.rs:19:12 + --> tests/ui/unnested_or_patterns2.rs:26:12 | LL | if let box box 0 | box (box 2 | box 4) = Box::new(Box::new(0)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unreadable_literal.fixed b/tests/ui/unreadable_literal.fixed index fb9c2672db82..646481ab040b 100644 --- a/tests/ui/unreadable_literal.fixed +++ b/tests/ui/unreadable_literal.fixed @@ -29,14 +29,24 @@ fn main() { 1.123_4_f32, ); let _bad = (0b11_0110_i64, 0x1234_5678_usize, 123_456_f32, 1.234_567_f32); + //~^ unreadable_literal + //~| unreadable_literal + //~| unreadable_literal + //~| unreadable_literal let _good_sci = 1.1234e1; let _bad_sci = 1.123_456e1; + //~^ unreadable_literal let _fail1 = 0x00ab_cdef; + //~^ unreadable_literal let _fail2: u32 = 0xBAFE_BAFE; + //~^ unreadable_literal let _fail3 = 0x0abc_deff; + //~^ unreadable_literal let _fail4: i128 = 0x00ab_cabc_abca_bcab_cabc; + //~^ unreadable_literal let _fail5 = 1.100_300_400; + //~^ unreadable_literal let _ = foo!(); let _ = bar!(); diff --git a/tests/ui/unreadable_literal.rs b/tests/ui/unreadable_literal.rs index 0a24fa852546..973d1a8e196a 100644 --- a/tests/ui/unreadable_literal.rs +++ b/tests/ui/unreadable_literal.rs @@ -29,14 +29,24 @@ fn main() { 1.123_4_f32, ); let _bad = (0b110110_i64, 0x12345678_usize, 123456_f32, 1.234567_f32); + //~^ unreadable_literal + //~| unreadable_literal + //~| unreadable_literal + //~| unreadable_literal let _good_sci = 1.1234e1; let _bad_sci = 1.123456e1; + //~^ unreadable_literal let _fail1 = 0xabcdef; + //~^ unreadable_literal let _fail2: u32 = 0xBAFEBAFE; + //~^ unreadable_literal let _fail3 = 0xabcdeff; + //~^ unreadable_literal let _fail4: i128 = 0xabcabcabcabcabcabc; + //~^ unreadable_literal let _fail5 = 1.100300400; + //~^ unreadable_literal let _ = foo!(); let _ = bar!(); diff --git a/tests/ui/unreadable_literal.stderr b/tests/ui/unreadable_literal.stderr index 5e350d760643..d019bf1b1feb 100644 --- a/tests/ui/unreadable_literal.stderr +++ b/tests/ui/unreadable_literal.stderr @@ -26,37 +26,37 @@ LL | let _bad = (0b110110_i64, 0x12345678_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^^^ help: consider: `1.234_567_f32` error: long literal lacking separators - --> tests/ui/unreadable_literal.rs:33:20 + --> tests/ui/unreadable_literal.rs:37:20 | LL | let _bad_sci = 1.123456e1; | ^^^^^^^^^^ help: consider: `1.123_456e1` error: long literal lacking separators - --> tests/ui/unreadable_literal.rs:35:18 + --> tests/ui/unreadable_literal.rs:40:18 | LL | let _fail1 = 0xabcdef; | ^^^^^^^^ help: consider: `0x00ab_cdef` error: long literal lacking separators - --> tests/ui/unreadable_literal.rs:36:23 + --> tests/ui/unreadable_literal.rs:42:23 | LL | let _fail2: u32 = 0xBAFEBAFE; | ^^^^^^^^^^ help: consider: `0xBAFE_BAFE` error: long literal lacking separators - --> tests/ui/unreadable_literal.rs:37:18 + --> tests/ui/unreadable_literal.rs:44:18 | LL | let _fail3 = 0xabcdeff; | ^^^^^^^^^ help: consider: `0x0abc_deff` error: long literal lacking separators - --> tests/ui/unreadable_literal.rs:38:24 + --> tests/ui/unreadable_literal.rs:46:24 | LL | let _fail4: i128 = 0xabcabcabcabcabcabc; | ^^^^^^^^^^^^^^^^^^^^ help: consider: `0x00ab_cabc_abca_bcab_cabc` error: long literal lacking separators - --> tests/ui/unreadable_literal.rs:39:18 + --> tests/ui/unreadable_literal.rs:48:18 | LL | let _fail5 = 1.100300400; | ^^^^^^^^^^^ help: consider: `1.100_300_400` diff --git a/tests/ui/unsafe_removed_from_name.rs b/tests/ui/unsafe_removed_from_name.rs index e9e6c8312f5e..2e1d8b60a0e2 100644 --- a/tests/ui/unsafe_removed_from_name.rs +++ b/tests/ui/unsafe_removed_from_name.rs @@ -3,11 +3,10 @@ #![warn(clippy::unsafe_removed_from_name)] use std::cell::UnsafeCell as TotallySafeCell; -//~^ ERROR: removed `unsafe` from the name of `UnsafeCell` in use as `TotallySafeCell` -//~| NOTE: `-D clippy::unsafe-removed-from-name` implied by `-D warnings` +//~^ unsafe_removed_from_name use std::cell::UnsafeCell as TotallySafeCellAgain; -//~^ ERROR: removed `unsafe` from the name of `UnsafeCell` in use as `TotallySafeCellAgain` +//~^ unsafe_removed_from_name // Shouldn't error use std::cell::RefCell as ProbablyNotUnsafe; @@ -26,12 +25,12 @@ mod mod_with_some_unsafe_things { } use mod_with_some_unsafe_things::Unsafe as LieAboutModSafety; -//~^ ERROR: removed `unsafe` from the name of `Unsafe` in use as `LieAboutModSafety` +//~^ unsafe_removed_from_name // merged imports use mod_with_some_unsafe_things::{Unsafe as A, Unsafe as B}; -//~^ ERROR: removed `unsafe` from the name of `Unsafe` in use as `A` -//~| ERROR: removed `unsafe` from the name of `Unsafe` in use as `B` +//~^ unsafe_removed_from_name +//~| unsafe_removed_from_name // Shouldn't error use mod_with_some_unsafe_things::Safe as IPromiseItsSafeThisTime; diff --git a/tests/ui/unsafe_removed_from_name.stderr b/tests/ui/unsafe_removed_from_name.stderr index 998cdbb579f6..5268c16ec9ba 100644 --- a/tests/ui/unsafe_removed_from_name.stderr +++ b/tests/ui/unsafe_removed_from_name.stderr @@ -8,25 +8,25 @@ LL | use std::cell::UnsafeCell as TotallySafeCell; = help: to override `-D warnings` add `#[allow(clippy::unsafe_removed_from_name)]` error: removed `unsafe` from the name of `UnsafeCell` in use as `TotallySafeCellAgain` - --> tests/ui/unsafe_removed_from_name.rs:9:1 + --> tests/ui/unsafe_removed_from_name.rs:8:1 | LL | use std::cell::UnsafeCell as TotallySafeCellAgain; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: removed `unsafe` from the name of `Unsafe` in use as `LieAboutModSafety` - --> tests/ui/unsafe_removed_from_name.rs:28:1 + --> tests/ui/unsafe_removed_from_name.rs:27:1 | LL | use mod_with_some_unsafe_things::Unsafe as LieAboutModSafety; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: removed `unsafe` from the name of `Unsafe` in use as `A` - --> tests/ui/unsafe_removed_from_name.rs:32:1 + --> tests/ui/unsafe_removed_from_name.rs:31:1 | LL | use mod_with_some_unsafe_things::{Unsafe as A, Unsafe as B}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: removed `unsafe` from the name of `Unsafe` in use as `B` - --> tests/ui/unsafe_removed_from_name.rs:32:1 + --> tests/ui/unsafe_removed_from_name.rs:31:1 | LL | use mod_with_some_unsafe_things::{Unsafe as A, Unsafe as B}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unseparated_prefix_literals.fixed b/tests/ui/unseparated_prefix_literals.fixed index 93f7f747b7cd..e13dd561d627 100644 --- a/tests/ui/unseparated_prefix_literals.fixed +++ b/tests/ui/unseparated_prefix_literals.fixed @@ -13,6 +13,7 @@ struct Foo; macro_rules! lit_from_macro { () => { 42_usize + //~^ unseparated_literal_suffix }; } @@ -21,15 +22,22 @@ fn main() { let _ok2 = 1234_isize; let _ok3 = 0x123_isize; let _fail1 = 1234_i32; + //~^ unseparated_literal_suffix let _fail2 = 1234_u32; + //~^ unseparated_literal_suffix let _fail3 = 1234_isize; + //~^ unseparated_literal_suffix let _fail4 = 1234_usize; + //~^ unseparated_literal_suffix let _fail5 = 0x123_isize; + //~^ unseparated_literal_suffix let _okf1 = 1.5_f32; let _okf2 = 1_f32; let _failf1 = 1.5_f32; + //~^ unseparated_literal_suffix let _failf2 = 1_f32; + //~^ unseparated_literal_suffix // Test for macro let _ = lit_from_macro!(); @@ -38,4 +46,5 @@ fn main() { let _ = line!(); // Because `assert!` contains `line!()` macro. assert_eq!(4897_u32, 32223); + //~^ unseparated_literal_suffix } diff --git a/tests/ui/unseparated_prefix_literals.rs b/tests/ui/unseparated_prefix_literals.rs index c960ff6b5dcc..6f7b16ccba54 100644 --- a/tests/ui/unseparated_prefix_literals.rs +++ b/tests/ui/unseparated_prefix_literals.rs @@ -13,6 +13,7 @@ struct Foo; macro_rules! lit_from_macro { () => { 42usize + //~^ unseparated_literal_suffix }; } @@ -21,15 +22,22 @@ fn main() { let _ok2 = 1234_isize; let _ok3 = 0x123_isize; let _fail1 = 1234i32; + //~^ unseparated_literal_suffix let _fail2 = 1234u32; + //~^ unseparated_literal_suffix let _fail3 = 1234isize; + //~^ unseparated_literal_suffix let _fail4 = 1234usize; + //~^ unseparated_literal_suffix let _fail5 = 0x123isize; + //~^ unseparated_literal_suffix let _okf1 = 1.5_f32; let _okf2 = 1_f32; let _failf1 = 1.5f32; + //~^ unseparated_literal_suffix let _failf2 = 1f32; + //~^ unseparated_literal_suffix // Test for macro let _ = lit_from_macro!(); @@ -38,4 +46,5 @@ fn main() { let _ = line!(); // Because `assert!` contains `line!()` macro. assert_eq!(4897u32, 32223); + //~^ unseparated_literal_suffix } diff --git a/tests/ui/unseparated_prefix_literals.stderr b/tests/ui/unseparated_prefix_literals.stderr index 1c51f7ada91f..4cfbf5e4b74e 100644 --- a/tests/ui/unseparated_prefix_literals.stderr +++ b/tests/ui/unseparated_prefix_literals.stderr @@ -1,5 +1,5 @@ error: integer type suffix should be separated by an underscore - --> tests/ui/unseparated_prefix_literals.rs:23:18 + --> tests/ui/unseparated_prefix_literals.rs:24:18 | LL | let _fail1 = 1234i32; | ^^^^^^^ help: add an underscore: `1234_i32` @@ -8,37 +8,37 @@ LL | let _fail1 = 1234i32; = help: to override `-D warnings` add `#[allow(clippy::unseparated_literal_suffix)]` error: integer type suffix should be separated by an underscore - --> tests/ui/unseparated_prefix_literals.rs:24:18 + --> tests/ui/unseparated_prefix_literals.rs:26:18 | LL | let _fail2 = 1234u32; | ^^^^^^^ help: add an underscore: `1234_u32` error: integer type suffix should be separated by an underscore - --> tests/ui/unseparated_prefix_literals.rs:25:18 + --> tests/ui/unseparated_prefix_literals.rs:28:18 | LL | let _fail3 = 1234isize; | ^^^^^^^^^ help: add an underscore: `1234_isize` error: integer type suffix should be separated by an underscore - --> tests/ui/unseparated_prefix_literals.rs:26:18 + --> tests/ui/unseparated_prefix_literals.rs:30:18 | LL | let _fail4 = 1234usize; | ^^^^^^^^^ help: add an underscore: `1234_usize` error: integer type suffix should be separated by an underscore - --> tests/ui/unseparated_prefix_literals.rs:27:18 + --> tests/ui/unseparated_prefix_literals.rs:32:18 | LL | let _fail5 = 0x123isize; | ^^^^^^^^^^ help: add an underscore: `0x123_isize` error: float type suffix should be separated by an underscore - --> tests/ui/unseparated_prefix_literals.rs:31:19 + --> tests/ui/unseparated_prefix_literals.rs:37:19 | LL | let _failf1 = 1.5f32; | ^^^^^^ help: add an underscore: `1.5_f32` error: float type suffix should be separated by an underscore - --> tests/ui/unseparated_prefix_literals.rs:32:19 + --> tests/ui/unseparated_prefix_literals.rs:39:19 | LL | let _failf2 = 1f32; | ^^^^ help: add an underscore: `1_f32` @@ -55,7 +55,7 @@ LL | let _ = lit_from_macro!(); = note: this error originates in the macro `lit_from_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: integer type suffix should be separated by an underscore - --> tests/ui/unseparated_prefix_literals.rs:40:16 + --> tests/ui/unseparated_prefix_literals.rs:48:16 | LL | assert_eq!(4897u32, 32223); | ^^^^^^^ help: add an underscore: `4897_u32` diff --git a/tests/ui/unused_async.rs b/tests/ui/unused_async.rs index 838d6f0aa971..5aaf7b9f5b59 100644 --- a/tests/ui/unused_async.rs +++ b/tests/ui/unused_async.rs @@ -10,7 +10,8 @@ mod issue10800 { use std::future::ready; async fn async_block_await() { - //~^ ERROR: unused `async` for function with no await statements + //~^ unused_async + async { ready(()).await; }; @@ -43,7 +44,7 @@ mod issue9695 { async fn f() {} async fn f2() {} async fn f3() {} - //~^ ERROR: unused `async` for function with no await statements + //~^ unused_async fn needs_async_fn>(_: fn() -> F) {} @@ -72,7 +73,8 @@ mod issue13466 { } async fn foo() -> i32 { - //~^ ERROR: unused `async` for function with no await statements + //~^ unused_async + 4 } @@ -84,7 +86,8 @@ struct S; impl S { async fn unused(&self) -> i32 { - //~^ ERROR: unused `async` for function with no await statements + //~^ unused_async + 1 } diff --git a/tests/ui/unused_async.stderr b/tests/ui/unused_async.stderr index 4811df63658a..f95fdd865300 100644 --- a/tests/ui/unused_async.stderr +++ b/tests/ui/unused_async.stderr @@ -3,6 +3,7 @@ error: unused `async` for function with no await statements | LL | / async fn async_block_await() { LL | | +LL | | LL | | async { LL | | ready(()).await; LL | | }; @@ -11,7 +12,7 @@ LL | | } | = help: consider removing the `async` from this function note: `await` used in an async block, which does not require the enclosing function to be `async` - --> tests/ui/unused_async.rs:15:23 + --> tests/ui/unused_async.rs:16:23 | LL | ready(()).await; | ^^^^^ @@ -19,7 +20,7 @@ LL | ready(()).await; = help: to override `-D warnings` add `#[allow(clippy::unused_async)]` error: unused `async` for function with no await statements - --> tests/ui/unused_async.rs:45:5 + --> tests/ui/unused_async.rs:46:5 | LL | async fn f3() {} | ^^^^^^^^^^^^^^^^ @@ -27,10 +28,11 @@ LL | async fn f3() {} = help: consider removing the `async` from this function error: unused `async` for function with no await statements - --> tests/ui/unused_async.rs:74:1 + --> tests/ui/unused_async.rs:75:1 | LL | / async fn foo() -> i32 { LL | | +LL | | LL | | 4 LL | | } | |_^ @@ -38,10 +40,11 @@ LL | | } = help: consider removing the `async` from this function error: unused `async` for function with no await statements - --> tests/ui/unused_async.rs:86:5 + --> tests/ui/unused_async.rs:88:5 | LL | / async fn unused(&self) -> i32 { LL | | +LL | | LL | | 1 LL | | } | |_____^ diff --git a/tests/ui/unused_enumerate_index.fixed b/tests/ui/unused_enumerate_index.fixed index cffd02b0acc8..258e52971cea 100644 --- a/tests/ui/unused_enumerate_index.fixed +++ b/tests/ui/unused_enumerate_index.fixed @@ -10,6 +10,7 @@ fn get_enumerate() -> Enumerate> { fn main() { let v = [1, 2, 3]; for x in v.iter() { + //~^ unused_enumerate_index println!("{x}"); } @@ -57,12 +58,15 @@ fn main() { let dummy = Dummy3(vec![1, 2, 3].into_iter()); for x in dummy { + //~^ unused_enumerate_index println!("{x}"); } let _ = vec![1, 2, 3].into_iter().map(|x| println!("{x}")); + //~^ unused_enumerate_index let p = vec![1, 2, 3].into_iter(); + //~^ unused_enumerate_index p.map(|x| println!("{x}")); // This shouldn't trigger the lint. `get_enumerate` may come from an external library on which we @@ -84,6 +88,7 @@ fn main() { }; } _ = mac2!().map(|_v| {}); + //~^ unused_enumerate_index // This shouldn't trigger the lint because of the `allow`. #[allow(clippy::unused_enumerate_index)] @@ -92,15 +97,18 @@ fn main() { // This should keep the explicit type of `x`. let v = [1, 2, 3].iter().copied(); + //~^ unused_enumerate_index let x = v.map(|x: i32| x).sum::(); assert_eq!(x, 6); // This should keep the explicit type of `x`. let v = [1, 2, 3].iter().copied(); + //~^ unused_enumerate_index let x = v.map(|x: i32| x).sum::(); assert_eq!(x, 6); let v = [1, 2, 3].iter().copied(); + //~^ unused_enumerate_index let x = v.map(|x| x).sum::(); assert_eq!(x, 6); } diff --git a/tests/ui/unused_enumerate_index.rs b/tests/ui/unused_enumerate_index.rs index f2b5f8b91247..a17e3259a9b0 100644 --- a/tests/ui/unused_enumerate_index.rs +++ b/tests/ui/unused_enumerate_index.rs @@ -10,6 +10,7 @@ fn get_enumerate() -> Enumerate> { fn main() { let v = [1, 2, 3]; for (_, x) in v.iter().enumerate() { + //~^ unused_enumerate_index println!("{x}"); } @@ -57,12 +58,15 @@ fn main() { let dummy = Dummy3(vec![1, 2, 3].into_iter()); for (_, x) in dummy.enumerate() { + //~^ unused_enumerate_index println!("{x}"); } let _ = vec![1, 2, 3].into_iter().enumerate().map(|(_, x)| println!("{x}")); + //~^ unused_enumerate_index let p = vec![1, 2, 3].into_iter().enumerate(); + //~^ unused_enumerate_index p.map(|(_, x)| println!("{x}")); // This shouldn't trigger the lint. `get_enumerate` may come from an external library on which we @@ -84,6 +88,7 @@ fn main() { }; } _ = mac2!().enumerate().map(|(_, _v)| {}); + //~^ unused_enumerate_index // This shouldn't trigger the lint because of the `allow`. #[allow(clippy::unused_enumerate_index)] @@ -92,15 +97,18 @@ fn main() { // This should keep the explicit type of `x`. let v = [1, 2, 3].iter().copied().enumerate(); + //~^ unused_enumerate_index let x = v.map(|(_, x): (usize, i32)| x).sum::(); assert_eq!(x, 6); // This should keep the explicit type of `x`. let v = [1, 2, 3].iter().copied().enumerate(); + //~^ unused_enumerate_index let x = v.map(|(_, x): (_, i32)| x).sum::(); assert_eq!(x, 6); let v = [1, 2, 3].iter().copied().enumerate(); + //~^ unused_enumerate_index let x = v.map(|(_, x)| x).sum::(); assert_eq!(x, 6); } diff --git a/tests/ui/unused_enumerate_index.stderr b/tests/ui/unused_enumerate_index.stderr index 02d65f064308..14d1d20a66e4 100644 --- a/tests/ui/unused_enumerate_index.stderr +++ b/tests/ui/unused_enumerate_index.stderr @@ -13,7 +13,7 @@ LL + for x in v.iter() { | error: you seem to use `.enumerate()` and immediately discard the index - --> tests/ui/unused_enumerate_index.rs:59:19 + --> tests/ui/unused_enumerate_index.rs:60:19 | LL | for (_, x) in dummy.enumerate() { | ^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + for x in dummy { | error: you seem to use `.enumerate()` and immediately discard the index - --> tests/ui/unused_enumerate_index.rs:63:39 + --> tests/ui/unused_enumerate_index.rs:65:39 | LL | let _ = vec![1, 2, 3].into_iter().enumerate().map(|(_, x)| println!("{x}")); | ^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + let _ = vec![1, 2, 3].into_iter().map(|x| println!("{x}")); | error: you seem to use `.enumerate()` and immediately discard the index - --> tests/ui/unused_enumerate_index.rs:65:39 + --> tests/ui/unused_enumerate_index.rs:68:39 | LL | let p = vec![1, 2, 3].into_iter().enumerate(); | ^^^^^^^^^^^ @@ -45,11 +45,12 @@ LL | let p = vec![1, 2, 3].into_iter().enumerate(); help: remove the `.enumerate()` call | LL ~ let p = vec![1, 2, 3].into_iter(); +LL | LL ~ p.map(|x| println!("{x}")); | error: you seem to use `.enumerate()` and immediately discard the index - --> tests/ui/unused_enumerate_index.rs:86:17 + --> tests/ui/unused_enumerate_index.rs:90:17 | LL | _ = mac2!().enumerate().map(|(_, _v)| {}); | ^^^^^^^^^^^ @@ -60,18 +61,6 @@ LL - _ = mac2!().enumerate().map(|(_, _v)| {}); LL + _ = mac2!().map(|_v| {}); | -error: you seem to use `.enumerate()` and immediately discard the index - --> tests/ui/unused_enumerate_index.rs:94:39 - | -LL | let v = [1, 2, 3].iter().copied().enumerate(); - | ^^^^^^^^^^^ - | -help: remove the `.enumerate()` call - | -LL ~ let v = [1, 2, 3].iter().copied(); -LL ~ let x = v.map(|x: i32| x).sum::(); - | - error: you seem to use `.enumerate()` and immediately discard the index --> tests/ui/unused_enumerate_index.rs:99:39 | @@ -81,11 +70,12 @@ LL | let v = [1, 2, 3].iter().copied().enumerate(); help: remove the `.enumerate()` call | LL ~ let v = [1, 2, 3].iter().copied(); +LL | LL ~ let x = v.map(|x: i32| x).sum::(); | error: you seem to use `.enumerate()` and immediately discard the index - --> tests/ui/unused_enumerate_index.rs:103:39 + --> tests/ui/unused_enumerate_index.rs:105:39 | LL | let v = [1, 2, 3].iter().copied().enumerate(); | ^^^^^^^^^^^ @@ -93,6 +83,20 @@ LL | let v = [1, 2, 3].iter().copied().enumerate(); help: remove the `.enumerate()` call | LL ~ let v = [1, 2, 3].iter().copied(); +LL | +LL ~ let x = v.map(|x: i32| x).sum::(); + | + +error: you seem to use `.enumerate()` and immediately discard the index + --> tests/ui/unused_enumerate_index.rs:110:39 + | +LL | let v = [1, 2, 3].iter().copied().enumerate(); + | ^^^^^^^^^^^ + | +help: remove the `.enumerate()` call + | +LL ~ let v = [1, 2, 3].iter().copied(); +LL | LL ~ let x = v.map(|x| x).sum::(); | diff --git a/tests/ui/unused_format_specs.1.fixed b/tests/ui/unused_format_specs.1.fixed index 157c2b08d3cf..05bd1df9a523 100644 --- a/tests/ui/unused_format_specs.1.fixed +++ b/tests/ui/unused_format_specs.1.fixed @@ -10,18 +10,18 @@ macro_rules! format_args_from_macro { fn main() { // prints `.`, not ` .` println!("{:5}.", format!("")); - //~^ ERROR: format specifiers have no effect on `format_args!()` - //~| NOTE: `-D clippy::unused-format-specs` implied by `-D warnings` + //~^ unused_format_specs + //prints `abcde`, not `abc` println!("{:.3}", format!("abcde")); - //~^ ERROR: format specifiers have no effect on `format_args!()` + //~^ unused_format_specs println!("{}.", format_args_from_macro!()); - //~^ ERROR: format specifiers have no effect on `format_args!()` + //~^ unused_format_specs let args = format_args!(""); println!("{args}"); - //~^ ERROR: format specifiers have no effect on `format_args!()` + //~^ unused_format_specs } fn should_not_lint() { @@ -46,17 +46,18 @@ macro_rules! usr_println { fn should_lint_user() { // prints `.`, not ` .` usr_println!(true, "{:5}.", format!("")); - //~^ ERROR: format specifiers have no effect on `format_args!()` + //~^ unused_format_specs + //prints `abcde`, not `abc` usr_println!(true, "{:.3}", format!("abcde")); - //~^ ERROR: format specifiers have no effect on `format_args!()` + //~^ unused_format_specs usr_println!(true, "{}.", format_args_from_macro!()); - //~^ ERROR: format specifiers have no effect on `format_args!()` + //~^ unused_format_specs let args = format_args!(""); usr_println!(true, "{args}"); - //~^ ERROR: format specifiers have no effect on `format_args!()` + //~^ unused_format_specs } fn should_not_lint_user() { diff --git a/tests/ui/unused_format_specs.2.fixed b/tests/ui/unused_format_specs.2.fixed index 92c7b951f3ca..c1f3d4fa20c6 100644 --- a/tests/ui/unused_format_specs.2.fixed +++ b/tests/ui/unused_format_specs.2.fixed @@ -10,18 +10,18 @@ macro_rules! format_args_from_macro { fn main() { // prints `.`, not ` .` println!("{}.", format_args!("")); - //~^ ERROR: format specifiers have no effect on `format_args!()` - //~| NOTE: `-D clippy::unused-format-specs` implied by `-D warnings` + //~^ unused_format_specs + //prints `abcde`, not `abc` println!("{}", format_args!("abcde")); - //~^ ERROR: format specifiers have no effect on `format_args!()` + //~^ unused_format_specs println!("{}.", format_args_from_macro!()); - //~^ ERROR: format specifiers have no effect on `format_args!()` + //~^ unused_format_specs let args = format_args!(""); println!("{args}"); - //~^ ERROR: format specifiers have no effect on `format_args!()` + //~^ unused_format_specs } fn should_not_lint() { @@ -46,17 +46,18 @@ macro_rules! usr_println { fn should_lint_user() { // prints `.`, not ` .` usr_println!(true, "{}.", format_args!("")); - //~^ ERROR: format specifiers have no effect on `format_args!()` + //~^ unused_format_specs + //prints `abcde`, not `abc` usr_println!(true, "{}", format_args!("abcde")); - //~^ ERROR: format specifiers have no effect on `format_args!()` + //~^ unused_format_specs usr_println!(true, "{}.", format_args_from_macro!()); - //~^ ERROR: format specifiers have no effect on `format_args!()` + //~^ unused_format_specs let args = format_args!(""); usr_println!(true, "{args}"); - //~^ ERROR: format specifiers have no effect on `format_args!()` + //~^ unused_format_specs } fn should_not_lint_user() { diff --git a/tests/ui/unused_format_specs.rs b/tests/ui/unused_format_specs.rs index a5df4d8a8668..b47047ba34e5 100644 --- a/tests/ui/unused_format_specs.rs +++ b/tests/ui/unused_format_specs.rs @@ -10,18 +10,18 @@ macro_rules! format_args_from_macro { fn main() { // prints `.`, not ` .` println!("{:5}.", format_args!("")); - //~^ ERROR: format specifiers have no effect on `format_args!()` - //~| NOTE: `-D clippy::unused-format-specs` implied by `-D warnings` + //~^ unused_format_specs + //prints `abcde`, not `abc` println!("{:.3}", format_args!("abcde")); - //~^ ERROR: format specifiers have no effect on `format_args!()` + //~^ unused_format_specs println!("{:5}.", format_args_from_macro!()); - //~^ ERROR: format specifiers have no effect on `format_args!()` + //~^ unused_format_specs let args = format_args!(""); println!("{args:5}"); - //~^ ERROR: format specifiers have no effect on `format_args!()` + //~^ unused_format_specs } fn should_not_lint() { @@ -46,17 +46,18 @@ macro_rules! usr_println { fn should_lint_user() { // prints `.`, not ` .` usr_println!(true, "{:5}.", format_args!("")); - //~^ ERROR: format specifiers have no effect on `format_args!()` + //~^ unused_format_specs + //prints `abcde`, not `abc` usr_println!(true, "{:.3}", format_args!("abcde")); - //~^ ERROR: format specifiers have no effect on `format_args!()` + //~^ unused_format_specs usr_println!(true, "{:5}.", format_args_from_macro!()); - //~^ ERROR: format specifiers have no effect on `format_args!()` + //~^ unused_format_specs let args = format_args!(""); usr_println!(true, "{args:5}"); - //~^ ERROR: format specifiers have no effect on `format_args!()` + //~^ unused_format_specs } fn should_not_lint_user() { diff --git a/tests/ui/unused_format_specs.stderr b/tests/ui/unused_format_specs.stderr index d3c0530ced46..b07058fd568d 100644 --- a/tests/ui/unused_format_specs.stderr +++ b/tests/ui/unused_format_specs.stderr @@ -78,7 +78,7 @@ LL + usr_println!(true, "{}.", format_args!("")); | error: format specifiers have no effect on `format_args!()` - --> tests/ui/unused_format_specs.rs:51:25 + --> tests/ui/unused_format_specs.rs:52:25 | LL | usr_println!(true, "{:.3}", format_args!("abcde")); | ^^^^^ @@ -95,7 +95,7 @@ LL + usr_println!(true, "{}", format_args!("abcde")); | error: format specifiers have no effect on `format_args!()` - --> tests/ui/unused_format_specs.rs:54:25 + --> tests/ui/unused_format_specs.rs:55:25 | LL | usr_println!(true, "{:5}.", format_args_from_macro!()); | ^^^^ @@ -108,7 +108,7 @@ LL + usr_println!(true, "{}.", format_args_from_macro!()); | error: format specifiers have no effect on `format_args!()` - --> tests/ui/unused_format_specs.rs:58:25 + --> tests/ui/unused_format_specs.rs:59:25 | LL | usr_println!(true, "{args:5}"); | ^^^^^^^^ diff --git a/tests/ui/unused_io_amount.rs b/tests/ui/unused_io_amount.rs index 175c4ca76895..32a50375806a 100644 --- a/tests/ui/unused_io_amount.rs +++ b/tests/ui/unused_io_amount.rs @@ -8,26 +8,26 @@ use std::io::{self, Read}; fn question_mark(s: &mut T) -> io::Result<()> { s.write(b"test")?; - //~^ ERROR: written amount is not handled + //~^ unused_io_amount let mut buf = [0u8; 4]; s.read(&mut buf)?; - //~^ ERROR: read amount is not handled + //~^ unused_io_amount Ok(()) } fn unwrap(s: &mut T) { s.write(b"test").unwrap(); - //~^ ERROR: written amount is not handled + //~^ unused_io_amount let mut buf = [0u8; 4]; s.read(&mut buf).unwrap(); - //~^ ERROR: read amount is not handled + //~^ unused_io_amount } fn vectored(s: &mut T) -> io::Result<()> { s.read_vectored(&mut [io::IoSliceMut::new(&mut [])])?; - //~^ ERROR: read amount is not handled + //~^ unused_io_amount s.write_vectored(&[io::IoSlice::new(&[])])?; - //~^ ERROR: written amount is not handled + //~^ unused_io_amount Ok(()) } @@ -35,7 +35,7 @@ fn ok(file: &str) -> Option<()> { let mut reader = std::fs::File::open(file).ok()?; let mut result = [0u8; 0]; reader.read(&mut result).ok()?; - //~^ ERROR: read amount is not handled + //~^ unused_io_amount Some(()) } @@ -45,7 +45,7 @@ fn or_else(file: &str) -> io::Result<()> { let mut reader = std::fs::File::open(file)?; let mut result = [0u8; 0]; reader.read(&mut result).or_else(|err| Err(err))?; - //~^ ERROR: read amount is not handled + //~^ unused_io_amount Ok(()) } @@ -58,7 +58,7 @@ fn or(file: &str) -> Result<(), Error> { let mut reader = std::fs::File::open(file).unwrap(); let mut result = [0u8; 0]; reader.read(&mut result).or(Err(Error::Kind))?; - //~^ ERROR: read amount is not handled + //~^ unused_io_amount Ok(()) } @@ -66,7 +66,7 @@ fn combine_or(file: &str) -> Result<(), Error> { let mut reader = std::fs::File::open(file).unwrap(); let mut result = [0u8; 0]; reader - //~^ ERROR: read amount is not handled + //~^ unused_io_amount .read(&mut result) .or(Err(Error::Kind)) .or(Err(Error::Kind)) @@ -76,25 +76,25 @@ fn combine_or(file: &str) -> Result<(), Error> { fn is_ok_err(s: &mut T) { s.write(b"ok").is_ok(); - //~^ ERROR: written amount is not handled + //~^ unused_io_amount s.write(b"err").is_err(); - //~^ ERROR: written amount is not handled + //~^ unused_io_amount let mut buf = [0u8; 0]; s.read(&mut buf).is_ok(); - //~^ ERROR: read amount is not handled + //~^ unused_io_amount s.read(&mut buf).is_err(); - //~^ ERROR: read amount is not handled + //~^ unused_io_amount } async fn bad_async_write(w: &mut W) { w.write(b"hello world").await.unwrap(); - //~^ ERROR: written amount is not handled + //~^ unused_io_amount } async fn bad_async_read(r: &mut R) { let mut buf = [0u8; 0]; r.read(&mut buf[..]).await.unwrap(); - //~^ ERROR: read amount is not handled + //~^ unused_io_amount } async fn io_not_ignored_async_write(mut w: W) { @@ -102,13 +102,14 @@ async fn io_not_ignored_async_write(mut w: W) { // warning about _that_ (or we would, if it were enabled), but we // won't get one about ignoring the return value. w.write(b"hello world"); + //~^ unused_io_amount } fn bad_async_write_closure(w: W) -> impl futures::Future> { let mut w = w; async move { w.write(b"hello world").await?; - //~^ ERROR: written amount is not handled + //~^ unused_io_amount Ok(()) } } @@ -117,7 +118,7 @@ async fn async_read_nested_or(r: &mut R, do_it: bool) -> R let mut buf = [0u8; 1]; if do_it { r.read(&mut buf[..]).await.or(Err(Error::Kind))?; - //~^ ERROR: read amount is not handled + //~^ unused_io_amount } Ok(buf) } @@ -126,13 +127,13 @@ use tokio::io::{AsyncRead as TokioAsyncRead, AsyncReadExt as _, AsyncWrite as To async fn bad_async_write_tokio(w: &mut W) { w.write(b"hello world").await.unwrap(); - //~^ ERROR: written amount is not handled + //~^ unused_io_amount } async fn bad_async_read_tokio(r: &mut R) { let mut buf = [0u8; 0]; r.read(&mut buf[..]).await.unwrap(); - //~^ ERROR: read amount is not handled + //~^ unused_io_amount } async fn undetected_bad_async_write(w: &mut W) { @@ -145,35 +146,31 @@ async fn undetected_bad_async_write(w: &mut W) { fn match_okay_underscore(s: &mut T) { match s.write(b"test") { - //~^ ERROR: written amount is not handled + //~^ unused_io_amount Ok(_) => todo!(), - //~^ NOTE: the result is consumed here, but the amount of I/O bytes remains unhandled Err(_) => todo!(), }; let mut buf = [0u8; 4]; match s.read(&mut buf) { - //~^ ERROR: read amount is not handled + //~^ unused_io_amount Ok(_) => todo!(), - //~^ NOTE: the result is consumed here, but the amount of I/O bytes remains unhandled Err(_) => todo!(), } } fn match_okay_underscore_read_expr(s: &mut T) { match s.read(&mut [0u8; 4]) { - //~^ ERROR: read amount is not handled + //~^ unused_io_amount Ok(_) => todo!(), - //~^ NOTE: the result is consumed here, but the amount of I/O bytes remains unhandled Err(_) => todo!(), } } fn match_okay_underscore_write_expr(s: &mut T) { match s.write(b"test") { - //~^ ERROR: written amount is not handled + //~^ unused_io_amount Ok(_) => todo!(), - //~^ NOTE: the result is consumed here, but the amount of I/O bytes remains unhandled Err(_) => todo!(), } } @@ -184,21 +181,21 @@ fn returned_value_should_not_lint(s: &mut T) -> Result< fn if_okay_underscore_read_expr(s: &mut T) { if let Ok(_) = s.read(&mut [0u8; 4]) { - //~^ ERROR: read amount is not handled + //~^ unused_io_amount todo!() } } fn if_okay_underscore_write_expr(s: &mut T) { if let Ok(_) = s.write(b"test") { - //~^ ERROR: written amount is not handled + //~^ unused_io_amount todo!() } } fn if_okay_dots_write_expr(s: &mut T) { if let Ok(..) = s.write(b"test") { - //~^ ERROR: written amount is not handled + //~^ unused_io_amount todo!() } } diff --git a/tests/ui/unused_io_amount.stderr b/tests/ui/unused_io_amount.stderr index 771e463ca010..71bb4c40de84 100644 --- a/tests/ui/unused_io_amount.stderr +++ b/tests/ui/unused_io_amount.stderr @@ -138,7 +138,7 @@ LL | w.write(b"hello world"); = help: use `AsyncWriteExt::write_all` instead, or handle partial writes error: written amount is not handled - --> tests/ui/unused_io_amount.rs:110:9 + --> tests/ui/unused_io_amount.rs:111:9 | LL | w.write(b"hello world").await?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -146,7 +146,7 @@ LL | w.write(b"hello world").await?; = help: use `AsyncWriteExt::write_all` instead, or handle partial writes error: read amount is not handled - --> tests/ui/unused_io_amount.rs:119:9 + --> tests/ui/unused_io_amount.rs:120:9 | LL | r.read(&mut buf[..]).await.or(Err(Error::Kind))?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -154,7 +154,7 @@ LL | r.read(&mut buf[..]).await.or(Err(Error::Kind))?; = help: use `AsyncReadExt::read_exact` instead, or handle partial reads error: written amount is not handled - --> tests/ui/unused_io_amount.rs:128:5 + --> tests/ui/unused_io_amount.rs:129:5 | LL | w.write(b"hello world").await.unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -162,7 +162,7 @@ LL | w.write(b"hello world").await.unwrap(); = help: use `AsyncWriteExt::write_all` instead, or handle partial writes error: read amount is not handled - --> tests/ui/unused_io_amount.rs:134:5 + --> tests/ui/unused_io_amount.rs:135:5 | LL | r.read(&mut buf[..]).await.unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -170,14 +170,14 @@ LL | r.read(&mut buf[..]).await.unwrap(); = help: use `AsyncReadExt::read_exact` instead, or handle partial reads error: written amount is not handled - --> tests/ui/unused_io_amount.rs:147:11 + --> tests/ui/unused_io_amount.rs:148:11 | LL | match s.write(b"test") { | ^^^^^^^^^^^^^^^^ | = help: use `Write::write_all` instead, or handle partial writes note: the result is consumed here, but the amount of I/O bytes remains unhandled - --> tests/ui/unused_io_amount.rs:149:9 + --> tests/ui/unused_io_amount.rs:150:9 | LL | Ok(_) => todo!(), | ^^^^^ @@ -196,66 +196,66 @@ LL | Ok(_) => todo!(), | ^^^^^ error: read amount is not handled - --> tests/ui/unused_io_amount.rs:164:11 + --> tests/ui/unused_io_amount.rs:163:11 | LL | match s.read(&mut [0u8; 4]) { | ^^^^^^^^^^^^^^^^^^^^^ | = help: use `Read::read_exact` instead, or handle partial reads note: the result is consumed here, but the amount of I/O bytes remains unhandled - --> tests/ui/unused_io_amount.rs:166:9 + --> tests/ui/unused_io_amount.rs:165:9 | LL | Ok(_) => todo!(), | ^^^^^ error: written amount is not handled - --> tests/ui/unused_io_amount.rs:173:11 + --> tests/ui/unused_io_amount.rs:171:11 | LL | match s.write(b"test") { | ^^^^^^^^^^^^^^^^ | = help: use `Write::write_all` instead, or handle partial writes note: the result is consumed here, but the amount of I/O bytes remains unhandled - --> tests/ui/unused_io_amount.rs:175:9 + --> tests/ui/unused_io_amount.rs:173:9 | LL | Ok(_) => todo!(), | ^^^^^ error: read amount is not handled - --> tests/ui/unused_io_amount.rs:186:8 + --> tests/ui/unused_io_amount.rs:183:8 | LL | if let Ok(_) = s.read(&mut [0u8; 4]) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: use `Read::read_exact` instead, or handle partial reads note: the result is consumed here, but the amount of I/O bytes remains unhandled - --> tests/ui/unused_io_amount.rs:186:12 + --> tests/ui/unused_io_amount.rs:183:12 | LL | if let Ok(_) = s.read(&mut [0u8; 4]) { | ^^^^^ error: written amount is not handled - --> tests/ui/unused_io_amount.rs:193:8 + --> tests/ui/unused_io_amount.rs:190:8 | LL | if let Ok(_) = s.write(b"test") { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: use `Write::write_all` instead, or handle partial writes note: the result is consumed here, but the amount of I/O bytes remains unhandled - --> tests/ui/unused_io_amount.rs:193:12 + --> tests/ui/unused_io_amount.rs:190:12 | LL | if let Ok(_) = s.write(b"test") { | ^^^^^ error: written amount is not handled - --> tests/ui/unused_io_amount.rs:200:8 + --> tests/ui/unused_io_amount.rs:197:8 | LL | if let Ok(..) = s.write(b"test") { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: use `Write::write_all` instead, or handle partial writes note: the result is consumed here, but the amount of I/O bytes remains unhandled - --> tests/ui/unused_io_amount.rs:200:12 + --> tests/ui/unused_io_amount.rs:197:12 | LL | if let Ok(..) = s.write(b"test") { | ^^^^^^ diff --git a/tests/ui/unused_peekable.rs b/tests/ui/unused_peekable.rs index 5865bba43508..e7fe297764eb 100644 --- a/tests/ui/unused_peekable.rs +++ b/tests/ui/unused_peekable.rs @@ -11,17 +11,17 @@ fn main() { #[allow(clippy::unused_unit)] fn invalid() { let peekable = std::iter::empty::().peekable(); - //~^ ERROR: `peek` never called on `Peekable` iterator + //~^ unused_peekable // Only lint `new_local` let old_local = std::iter::empty::().peekable(); let new_local = old_local; - //~^ ERROR: `peek` never called on `Peekable` iterator + //~^ unused_peekable // Behind mut ref let mut by_mut_ref_test = std::iter::empty::().peekable(); let by_mut_ref = &mut by_mut_ref_test; - //~^ ERROR: `peek` never called on `Peekable` iterator + //~^ unused_peekable // Explicitly returns `Peekable` fn returns_peekable() -> Peekable> { @@ -29,26 +29,29 @@ fn invalid() { } let peekable_from_fn = returns_peekable(); - //~^ ERROR: `peek` never called on `Peekable` iterator + //~^ unused_peekable // Using a method not exclusive to `Peekable` let mut peekable_using_iterator_method = std::iter::empty::().peekable(); - //~^ ERROR: `peek` never called on `Peekable` iterator + //~^ unused_peekable + peekable_using_iterator_method.next(); // Passed by ref to another function fn takes_ref(_peek: &Peekable>) {} let passed_along_ref = std::iter::empty::().peekable(); - //~^ ERROR: `peek` never called on `Peekable` iterator + //~^ unused_peekable + takes_ref(&passed_along_ref); // `by_ref` without `peek` let mut by_ref_test = std::iter::empty::().peekable(); let _by_ref = by_ref_test.by_ref(); - //~^ ERROR: `peek` never called on `Peekable` iterator + //~^ unused_peekable let mut peekable_in_for_loop = std::iter::empty::().peekable(); - //~^ ERROR: `peek` never called on `Peekable` iterator + //~^ unused_peekable + for x in peekable_in_for_loop {} } diff --git a/tests/ui/unused_peekable.stderr b/tests/ui/unused_peekable.stderr index 00c6a52bab33..9330d8c58001 100644 --- a/tests/ui/unused_peekable.stderr +++ b/tests/ui/unused_peekable.stderr @@ -41,7 +41,7 @@ LL | let mut peekable_using_iterator_method = std::iter::empty::().peek = help: consider removing the call to `peekable` error: `peek` never called on `Peekable` iterator - --> tests/ui/unused_peekable.rs:41:9 + --> tests/ui/unused_peekable.rs:42:9 | LL | let passed_along_ref = std::iter::empty::().peekable(); | ^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | let passed_along_ref = std::iter::empty::().peekable(); = help: consider removing the call to `peekable` error: `peek` never called on `Peekable` iterator - --> tests/ui/unused_peekable.rs:47:9 + --> tests/ui/unused_peekable.rs:49:9 | LL | let _by_ref = by_ref_test.by_ref(); | ^^^^^^^ @@ -57,7 +57,7 @@ LL | let _by_ref = by_ref_test.by_ref(); = help: consider removing the call to `peekable` error: `peek` never called on `Peekable` iterator - --> tests/ui/unused_peekable.rs:50:13 + --> tests/ui/unused_peekable.rs:52:13 | LL | let mut peekable_in_for_loop = std::iter::empty::().peekable(); | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unused_result_ok.fixed b/tests/ui/unused_result_ok.fixed index e78fde5c9e3c..faedd96216c2 100644 --- a/tests/ui/unused_result_ok.fixed +++ b/tests/ui/unused_result_ok.fixed @@ -7,6 +7,7 @@ extern crate proc_macros; fn bad_style(x: &str) { let _ = x.parse::(); + //~^ unused_result_ok } fn good_style(x: &str) -> Option { @@ -16,6 +17,7 @@ fn good_style(x: &str) -> Option { #[rustfmt::skip] fn strange_parse(x: &str) { let _ = x . parse::(); + //~^ unused_result_ok } macro_rules! v { @@ -27,11 +29,13 @@ macro_rules! v { macro_rules! w { () => { let _ = Ok::<(), ()>(()); + //~^ unused_result_ok }; } fn main() { let _ = v!(); + //~^ unused_result_ok w!(); external! { diff --git a/tests/ui/unused_result_ok.rs b/tests/ui/unused_result_ok.rs index 117d64c4cec6..6ab974861b63 100644 --- a/tests/ui/unused_result_ok.rs +++ b/tests/ui/unused_result_ok.rs @@ -7,6 +7,7 @@ extern crate proc_macros; fn bad_style(x: &str) { x.parse::().ok(); + //~^ unused_result_ok } fn good_style(x: &str) -> Option { @@ -16,6 +17,7 @@ fn good_style(x: &str) -> Option { #[rustfmt::skip] fn strange_parse(x: &str) { x . parse::() . ok (); + //~^ unused_result_ok } macro_rules! v { @@ -27,11 +29,13 @@ macro_rules! v { macro_rules! w { () => { Ok::<(), ()>(()).ok(); + //~^ unused_result_ok }; } fn main() { v!().ok(); + //~^ unused_result_ok w!(); external! { diff --git a/tests/ui/unused_result_ok.stderr b/tests/ui/unused_result_ok.stderr index 024aafa6bbb8..0e134ba3ccba 100644 --- a/tests/ui/unused_result_ok.stderr +++ b/tests/ui/unused_result_ok.stderr @@ -13,7 +13,7 @@ LL + let _ = x.parse::(); | error: ignoring a result with `.ok()` is misleading - --> tests/ui/unused_result_ok.rs:18:5 + --> tests/ui/unused_result_ok.rs:19:5 | LL | x . parse::() . ok (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + let _ = x . parse::(); | error: ignoring a result with `.ok()` is misleading - --> tests/ui/unused_result_ok.rs:34:5 + --> tests/ui/unused_result_ok.rs:37:5 | LL | v!().ok(); | ^^^^^^^^^ @@ -37,7 +37,7 @@ LL + let _ = v!(); | error: ignoring a result with `.ok()` is misleading - --> tests/ui/unused_result_ok.rs:29:9 + --> tests/ui/unused_result_ok.rs:31:9 | LL | Ok::<(), ()>(()).ok(); | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unused_rounding.fixed b/tests/ui/unused_rounding.fixed index 7af2c8650a3d..461d97c55531 100644 --- a/tests/ui/unused_rounding.fixed +++ b/tests/ui/unused_rounding.fixed @@ -4,15 +4,20 @@ fn main() { let _ = 1f32; + //~^ unused_rounding let _ = 1.0f64; + //~^ unused_rounding let _ = 1.00f32; + //~^ unused_rounding let _ = 2e-54f64.floor(); // issue9866 let _ = 3.3_f32.round(); let _ = 3.3_f64.round(); let _ = 3.0_f32; + //~^ unused_rounding let _ = 3_3.0_0_f32; + //~^ unused_rounding let _ = 3_3.0_1_f64.round(); } diff --git a/tests/ui/unused_rounding.rs b/tests/ui/unused_rounding.rs index 1b0b22a9b685..0d5ebf941a5e 100644 --- a/tests/ui/unused_rounding.rs +++ b/tests/ui/unused_rounding.rs @@ -4,15 +4,20 @@ fn main() { let _ = 1f32.ceil(); + //~^ unused_rounding let _ = 1.0f64.floor(); + //~^ unused_rounding let _ = 1.00f32.round(); + //~^ unused_rounding let _ = 2e-54f64.floor(); // issue9866 let _ = 3.3_f32.round(); let _ = 3.3_f64.round(); let _ = 3.0_f32.round(); + //~^ unused_rounding let _ = 3_3.0_0_f32.round(); + //~^ unused_rounding let _ = 3_3.0_1_f64.round(); } diff --git a/tests/ui/unused_rounding.stderr b/tests/ui/unused_rounding.stderr index c5ae2da75f84..494b0cc7352d 100644 --- a/tests/ui/unused_rounding.stderr +++ b/tests/ui/unused_rounding.stderr @@ -8,25 +8,25 @@ LL | let _ = 1f32.ceil(); = help: to override `-D warnings` add `#[allow(clippy::unused_rounding)]` error: used the `floor` method with a whole number float - --> tests/ui/unused_rounding.rs:7:13 + --> tests/ui/unused_rounding.rs:8:13 | LL | let _ = 1.0f64.floor(); | ^^^^^^^^^^^^^^ help: remove the `floor` method call: `1.0f64` error: used the `round` method with a whole number float - --> tests/ui/unused_rounding.rs:8:13 + --> tests/ui/unused_rounding.rs:10:13 | LL | let _ = 1.00f32.round(); | ^^^^^^^^^^^^^^^ help: remove the `round` method call: `1.00f32` error: used the `round` method with a whole number float - --> tests/ui/unused_rounding.rs:14:13 + --> tests/ui/unused_rounding.rs:17:13 | LL | let _ = 3.0_f32.round(); | ^^^^^^^^^^^^^^^ help: remove the `round` method call: `3.0_f32` error: used the `round` method with a whole number float - --> tests/ui/unused_rounding.rs:16:13 + --> tests/ui/unused_rounding.rs:20:13 | LL | let _ = 3_3.0_0_f32.round(); | ^^^^^^^^^^^^^^^^^^^ help: remove the `round` method call: `3_3.0_0_f32` diff --git a/tests/ui/unused_self.rs b/tests/ui/unused_self.rs index d3d06037cb49..cb80d946aced 100644 --- a/tests/ui/unused_self.rs +++ b/tests/ui/unused_self.rs @@ -9,25 +9,34 @@ mod unused_self { impl A { fn unused_self_move(self) {} - //~^ ERROR: unused `self` argument + //~^ unused_self + fn unused_self_ref(&self) {} - //~^ ERROR: unused `self` argument + //~^ unused_self + fn unused_self_mut_ref(&mut self) {} - //~^ ERROR: unused `self` argument + //~^ unused_self + fn unused_self_pin_ref(self: Pin<&Self>) {} - //~^ ERROR: unused `self` argument + //~^ unused_self + fn unused_self_pin_mut_ref(self: Pin<&mut Self>) {} - //~^ ERROR: unused `self` argument + //~^ unused_self + fn unused_self_pin_nested(self: Pin>) {} - //~^ ERROR: unused `self` argument + //~^ unused_self + fn unused_self_box(self: Box) {} - //~^ ERROR: unused `self` argument + //~^ unused_self + fn unused_with_other_used_args(&self, x: u8, y: u8) -> u8 { - //~^ ERROR: unused `self` argument + //~^ unused_self + x + y } fn unused_self_class_method(&self) { - //~^ ERROR: unused `self` argument + //~^ unused_self + Self::static_method(); } diff --git a/tests/ui/unused_self.stderr b/tests/ui/unused_self.stderr index 5d5f1b643a4a..e29f5f96c886 100644 --- a/tests/ui/unused_self.stderr +++ b/tests/ui/unused_self.stderr @@ -9,7 +9,7 @@ LL | fn unused_self_move(self) {} = help: to override `-D warnings` add `#[allow(clippy::unused_self)]` error: unused `self` argument - --> tests/ui/unused_self.rs:13:28 + --> tests/ui/unused_self.rs:14:28 | LL | fn unused_self_ref(&self) {} | ^^^^^ @@ -17,7 +17,7 @@ LL | fn unused_self_ref(&self) {} = help: consider refactoring to an associated function error: unused `self` argument - --> tests/ui/unused_self.rs:15:32 + --> tests/ui/unused_self.rs:17:32 | LL | fn unused_self_mut_ref(&mut self) {} | ^^^^^^^^^ @@ -25,7 +25,7 @@ LL | fn unused_self_mut_ref(&mut self) {} = help: consider refactoring to an associated function error: unused `self` argument - --> tests/ui/unused_self.rs:17:32 + --> tests/ui/unused_self.rs:20:32 | LL | fn unused_self_pin_ref(self: Pin<&Self>) {} | ^^^^ @@ -33,7 +33,7 @@ LL | fn unused_self_pin_ref(self: Pin<&Self>) {} = help: consider refactoring to an associated function error: unused `self` argument - --> tests/ui/unused_self.rs:19:36 + --> tests/ui/unused_self.rs:23:36 | LL | fn unused_self_pin_mut_ref(self: Pin<&mut Self>) {} | ^^^^ @@ -41,7 +41,7 @@ LL | fn unused_self_pin_mut_ref(self: Pin<&mut Self>) {} = help: consider refactoring to an associated function error: unused `self` argument - --> tests/ui/unused_self.rs:21:35 + --> tests/ui/unused_self.rs:26:35 | LL | fn unused_self_pin_nested(self: Pin>) {} | ^^^^ @@ -49,7 +49,7 @@ LL | fn unused_self_pin_nested(self: Pin>) {} = help: consider refactoring to an associated function error: unused `self` argument - --> tests/ui/unused_self.rs:23:28 + --> tests/ui/unused_self.rs:29:28 | LL | fn unused_self_box(self: Box) {} | ^^^^ @@ -57,7 +57,7 @@ LL | fn unused_self_box(self: Box) {} = help: consider refactoring to an associated function error: unused `self` argument - --> tests/ui/unused_self.rs:25:40 + --> tests/ui/unused_self.rs:32:40 | LL | fn unused_with_other_used_args(&self, x: u8, y: u8) -> u8 { | ^^^^^ @@ -65,7 +65,7 @@ LL | fn unused_with_other_used_args(&self, x: u8, y: u8) -> u8 { = help: consider refactoring to an associated function error: unused `self` argument - --> tests/ui/unused_self.rs:29:37 + --> tests/ui/unused_self.rs:37:37 | LL | fn unused_self_class_method(&self) { | ^^^^^ diff --git a/tests/ui/unused_trait_names.fixed b/tests/ui/unused_trait_names.fixed index 7dfd0db65aa1..17e32ddfd9d9 100644 --- a/tests/ui/unused_trait_names.fixed +++ b/tests/ui/unused_trait_names.fixed @@ -10,6 +10,7 @@ fn main() {} fn bad() { use std::any::Any as _; + //~^ unused_trait_names println!("{:?}", "foo".type_id()); } @@ -29,6 +30,7 @@ fn used_good() { fn multi_bad() { use std::any::{self, Any as _, TypeId}; + //~^ unused_trait_names println!("{:?}", "foo".type_id()); } @@ -41,12 +43,14 @@ fn multi_good() { fn renamed_bad() { use std::any::Any as _; + //~^ unused_trait_names println!("{:?}", "foo".type_id()); } fn multi_renamed_bad() { use std::any::{Any as _, TypeId as MyTypeId}; + //~^ unused_trait_names println!("{:?}", "foo".type_id()); } @@ -70,6 +74,7 @@ mod used_mod_good { mod mod_import_bad { fn mod_import_bad() { use std::any::Any as _; + //~^ unused_trait_names println!("{:?}", "foo".type_id()); } @@ -111,6 +116,7 @@ mod nested_mod_used_good3 { mod nested_mod_used_bad { use std::any::Any as _; + //~^ unused_trait_names fn bar() { println!("{:?}", "foo".type_id()); @@ -130,6 +136,7 @@ mod nested_mod_used_bad { // the code would still compile. mod nested_mod_used_bad1 { use std::any::Any as _; + //~^ unused_trait_names use std::any::Any as MyAny; @@ -189,6 +196,7 @@ fn msrv_1_32() { #[clippy::msrv = "1.33"] fn msrv_1_33() { use simple_trait::{MyStruct, MyTrait as _}; + //~^ unused_trait_names MyStruct.do_things(); } @@ -196,6 +204,7 @@ mod lint_inside_macro_expansion_bad { macro_rules! foo { () => { use std::any::Any as _; + //~^ unused_trait_names fn bar() { "bar".type_id(); } @@ -243,6 +252,7 @@ proc_macros::with_span!( #[warn(unused)] mod unused_import { + //~^ ERROR: unused import } #[allow(clippy::unused_trait_names)] diff --git a/tests/ui/unused_trait_names.rs b/tests/ui/unused_trait_names.rs index ce44eedbc79c..3cf8597e5351 100644 --- a/tests/ui/unused_trait_names.rs +++ b/tests/ui/unused_trait_names.rs @@ -10,6 +10,7 @@ fn main() {} fn bad() { use std::any::Any; + //~^ unused_trait_names println!("{:?}", "foo".type_id()); } @@ -29,6 +30,7 @@ fn used_good() { fn multi_bad() { use std::any::{self, Any, TypeId}; + //~^ unused_trait_names println!("{:?}", "foo".type_id()); } @@ -41,12 +43,14 @@ fn multi_good() { fn renamed_bad() { use std::any::Any as MyAny; + //~^ unused_trait_names println!("{:?}", "foo".type_id()); } fn multi_renamed_bad() { use std::any::{Any as MyAny, TypeId as MyTypeId}; + //~^ unused_trait_names println!("{:?}", "foo".type_id()); } @@ -70,6 +74,7 @@ mod used_mod_good { mod mod_import_bad { fn mod_import_bad() { use std::any::Any; + //~^ unused_trait_names println!("{:?}", "foo".type_id()); } @@ -111,6 +116,7 @@ mod nested_mod_used_good3 { mod nested_mod_used_bad { use std::any::Any; + //~^ unused_trait_names fn bar() { println!("{:?}", "foo".type_id()); @@ -130,6 +136,7 @@ mod nested_mod_used_bad { // the code would still compile. mod nested_mod_used_bad1 { use std::any::Any; + //~^ unused_trait_names use std::any::Any as MyAny; @@ -189,6 +196,7 @@ fn msrv_1_32() { #[clippy::msrv = "1.33"] fn msrv_1_33() { use simple_trait::{MyStruct, MyTrait}; + //~^ unused_trait_names MyStruct.do_things(); } @@ -196,6 +204,7 @@ mod lint_inside_macro_expansion_bad { macro_rules! foo { () => { use std::any::Any; + //~^ unused_trait_names fn bar() { "bar".type_id(); } @@ -243,6 +252,7 @@ proc_macros::with_span!( #[warn(unused)] mod unused_import { use std::any::Any; + //~^ ERROR: unused import } #[allow(clippy::unused_trait_names)] diff --git a/tests/ui/unused_trait_names.stderr b/tests/ui/unused_trait_names.stderr index f59d8f58a170..3183289d8533 100644 --- a/tests/ui/unused_trait_names.stderr +++ b/tests/ui/unused_trait_names.stderr @@ -1,5 +1,5 @@ error: unused import: `std::any::Any` - --> tests/ui/unused_trait_names.rs:245:9 + --> tests/ui/unused_trait_names.rs:254:9 | LL | use std::any::Any; | ^^^^^^^^^^^^^ @@ -17,49 +17,49 @@ LL | use std::any::Any; = help: to override `-D warnings` add `#[allow(clippy::unused_trait_names)]` error: importing trait that is only used anonymously - --> tests/ui/unused_trait_names.rs:31:26 + --> tests/ui/unused_trait_names.rs:32:26 | LL | use std::any::{self, Any, TypeId}; | ^^^ help: use: `Any as _` error: importing trait that is only used anonymously - --> tests/ui/unused_trait_names.rs:43:19 + --> tests/ui/unused_trait_names.rs:45:19 | LL | use std::any::Any as MyAny; | ^^^^^^^^^^^^ help: use: `Any as _` error: importing trait that is only used anonymously - --> tests/ui/unused_trait_names.rs:49:20 + --> tests/ui/unused_trait_names.rs:52:20 | LL | use std::any::{Any as MyAny, TypeId as MyTypeId}; | ^^^^^^^^^^^^ help: use: `Any as _` error: importing trait that is only used anonymously - --> tests/ui/unused_trait_names.rs:72:23 + --> tests/ui/unused_trait_names.rs:76:23 | LL | use std::any::Any; | ^^^ help: use: `Any as _` error: importing trait that is only used anonymously - --> tests/ui/unused_trait_names.rs:113:19 + --> tests/ui/unused_trait_names.rs:118:19 | LL | use std::any::Any; | ^^^ help: use: `Any as _` error: importing trait that is only used anonymously - --> tests/ui/unused_trait_names.rs:132:19 + --> tests/ui/unused_trait_names.rs:138:19 | LL | use std::any::Any; | ^^^ help: use: `Any as _` error: importing trait that is only used anonymously - --> tests/ui/unused_trait_names.rs:191:34 + --> tests/ui/unused_trait_names.rs:198:34 | LL | use simple_trait::{MyStruct, MyTrait}; | ^^^^^^^ help: use: `MyTrait as _` error: importing trait that is only used anonymously - --> tests/ui/unused_trait_names.rs:198:27 + --> tests/ui/unused_trait_names.rs:206:27 | LL | use std::any::Any; | ^^^ help: use: `Any as _` diff --git a/tests/ui/unused_unit.fixed b/tests/ui/unused_unit.fixed index 04fe2d3b7af1..e3c02681c9fd 100644 --- a/tests/ui/unused_unit.fixed +++ b/tests/ui/unused_unit.fixed @@ -18,8 +18,12 @@ struct Unitter; impl Unitter { #[allow(clippy::no_effect)] pub fn get_unit(&self, f: F, _g: G) + //~^ unused_unit + //~| unused_unit where G: Fn() { + //~^ unused_unit let _y: &dyn Fn() = &f; + //~^ unused_unit (); // this should not lint, as it's not in return type position } } @@ -27,25 +31,35 @@ impl Unitter { impl Into<()> for Unitter { #[rustfmt::skip] fn into(self) { + //~^ unused_unit + //~^ unused_unit } } trait Trait { fn redundant(&self, _f: F, _g: G, _h: H) + //~^ unused_unit where G: FnMut(), + //~^ unused_unit H: Fn(); + //~^ unused_unit } impl Trait for Unitter { fn redundant(&self, _f: F, _g: G, _h: H) + //~^ unused_unit where G: FnMut(), + //~^ unused_unit H: Fn() {} + //~^ unused_unit } fn return_unit() { } +//~^ unused_unit +//~| unused_unit #[allow(clippy::needless_return)] #[allow(clippy::never_loop)] @@ -56,8 +70,10 @@ fn main() { return_unit(); loop { break; + //~^ unused_unit } return; + //~^ unused_unit } // https://github.com/rust-lang/rust-clippy/issues/4076 @@ -75,12 +91,15 @@ fn foo() { #[rustfmt::skip] fn test(){} +//~^ unused_unit #[rustfmt::skip] fn test2(){} +//~^ unused_unit #[rustfmt::skip] fn test3(){} +//~^ unused_unit fn macro_expr() { macro_rules! e { diff --git a/tests/ui/unused_unit.rs b/tests/ui/unused_unit.rs index 25c2ed59873a..4353026c594c 100644 --- a/tests/ui/unused_unit.rs +++ b/tests/ui/unused_unit.rs @@ -18,8 +18,12 @@ struct Unitter; impl Unitter { #[allow(clippy::no_effect)] pub fn get_unit (), G>(&self, f: F, _g: G) -> () + //~^ unused_unit + //~| unused_unit where G: Fn() -> () { + //~^ unused_unit let _y: &dyn Fn() -> () = &f; + //~^ unused_unit (); // this should not lint, as it's not in return type position } } @@ -27,25 +31,35 @@ impl Unitter { impl Into<()> for Unitter { #[rustfmt::skip] fn into(self) -> () { + //~^ unused_unit () + //~^ unused_unit } } trait Trait { fn redundant (), G, H>(&self, _f: F, _g: G, _h: H) + //~^ unused_unit where G: FnMut() -> (), + //~^ unused_unit H: Fn() -> (); + //~^ unused_unit } impl Trait for Unitter { fn redundant (), G, H>(&self, _f: F, _g: G, _h: H) + //~^ unused_unit where G: FnMut() -> (), + //~^ unused_unit H: Fn() -> () {} + //~^ unused_unit } fn return_unit() -> () { () } +//~^ unused_unit +//~| unused_unit #[allow(clippy::needless_return)] #[allow(clippy::never_loop)] @@ -56,8 +70,10 @@ fn main() { return_unit(); loop { break(); + //~^ unused_unit } return(); + //~^ unused_unit } // https://github.com/rust-lang/rust-clippy/issues/4076 @@ -75,12 +91,15 @@ fn foo() { #[rustfmt::skip] fn test()->(){} +//~^ unused_unit #[rustfmt::skip] fn test2() ->(){} +//~^ unused_unit #[rustfmt::skip] fn test3()-> (){} +//~^ unused_unit fn macro_expr() { macro_rules! e { diff --git a/tests/ui/unused_unit.stderr b/tests/ui/unused_unit.stderr index 104159ad5fc6..172fe0655028 100644 --- a/tests/ui/unused_unit.stderr +++ b/tests/ui/unused_unit.stderr @@ -17,49 +17,31 @@ LL | pub fn get_unit (), G>(&self, f: F, _g: G) -> () | ^^^^^^ help: remove the `-> ()` error: unneeded unit return type - --> tests/ui/unused_unit.rs:21:18 + --> tests/ui/unused_unit.rs:23:18 | LL | where G: Fn() -> () { | ^^^^^^ help: remove the `-> ()` error: unneeded unit return type - --> tests/ui/unused_unit.rs:22:26 + --> tests/ui/unused_unit.rs:25:26 | LL | let _y: &dyn Fn() -> () = &f; | ^^^^^^ help: remove the `-> ()` error: unneeded unit return type - --> tests/ui/unused_unit.rs:29:18 + --> tests/ui/unused_unit.rs:33:18 | LL | fn into(self) -> () { | ^^^^^^ help: remove the `-> ()` error: unneeded unit expression - --> tests/ui/unused_unit.rs:30:9 + --> tests/ui/unused_unit.rs:35:9 | LL | () | ^^ help: remove the final `()` error: unneeded unit return type - --> tests/ui/unused_unit.rs:35:29 - | -LL | fn redundant (), G, H>(&self, _f: F, _g: G, _h: H) - | ^^^^^^ help: remove the `-> ()` - -error: unneeded unit return type - --> tests/ui/unused_unit.rs:37:19 - | -LL | G: FnMut() -> (), - | ^^^^^^ help: remove the `-> ()` - -error: unneeded unit return type - --> tests/ui/unused_unit.rs:38:16 - | -LL | H: Fn() -> (); - | ^^^^^^ help: remove the `-> ()` - -error: unneeded unit return type - --> tests/ui/unused_unit.rs:42:29 + --> tests/ui/unused_unit.rs:41:29 | LL | fn redundant (), G, H>(&self, _f: F, _g: G, _h: H) | ^^^^^^ help: remove the `-> ()` @@ -71,49 +53,67 @@ LL | G: FnMut() -> (), | ^^^^^^ help: remove the `-> ()` error: unneeded unit return type - --> tests/ui/unused_unit.rs:45:16 + --> tests/ui/unused_unit.rs:46:16 + | +LL | H: Fn() -> (); + | ^^^^^^ help: remove the `-> ()` + +error: unneeded unit return type + --> tests/ui/unused_unit.rs:51:29 + | +LL | fn redundant (), G, H>(&self, _f: F, _g: G, _h: H) + | ^^^^^^ help: remove the `-> ()` + +error: unneeded unit return type + --> tests/ui/unused_unit.rs:54:19 + | +LL | G: FnMut() -> (), + | ^^^^^^ help: remove the `-> ()` + +error: unneeded unit return type + --> tests/ui/unused_unit.rs:56:16 | LL | H: Fn() -> () {} | ^^^^^^ help: remove the `-> ()` error: unneeded unit return type - --> tests/ui/unused_unit.rs:48:17 + --> tests/ui/unused_unit.rs:60:17 | LL | fn return_unit() -> () { () } | ^^^^^^ help: remove the `-> ()` error: unneeded unit expression - --> tests/ui/unused_unit.rs:48:26 + --> tests/ui/unused_unit.rs:60:26 | LL | fn return_unit() -> () { () } | ^^ help: remove the final `()` error: unneeded `()` - --> tests/ui/unused_unit.rs:58:14 + --> tests/ui/unused_unit.rs:72:14 | LL | break(); | ^^ help: remove the `()` error: unneeded `()` - --> tests/ui/unused_unit.rs:60:11 + --> tests/ui/unused_unit.rs:75:11 | LL | return(); | ^^ help: remove the `()` error: unneeded unit return type - --> tests/ui/unused_unit.rs:77:10 + --> tests/ui/unused_unit.rs:93:10 | LL | fn test()->(){} | ^^^^ help: remove the `-> ()` error: unneeded unit return type - --> tests/ui/unused_unit.rs:80:11 + --> tests/ui/unused_unit.rs:97:11 | LL | fn test2() ->(){} | ^^^^^ help: remove the `-> ()` error: unneeded unit return type - --> tests/ui/unused_unit.rs:83:11 + --> tests/ui/unused_unit.rs:101:11 | LL | fn test3()-> (){} | ^^^^^ help: remove the `-> ()` diff --git a/tests/ui/unwrap.rs b/tests/ui/unwrap.rs index 8ad7e98503bf..3191b396f99b 100644 --- a/tests/ui/unwrap.rs +++ b/tests/ui/unwrap.rs @@ -4,15 +4,16 @@ fn unwrap_option() { let opt = Some(0); let _ = opt.unwrap(); - //~^ ERROR: used `unwrap()` on an `Option` value + //~^ unwrap_used } fn unwrap_result() { let res: Result = Ok(0); let _ = res.unwrap(); - //~^ ERROR: used `unwrap()` on a `Result` value + //~^ unwrap_used + let _ = res.unwrap_err(); - //~^ ERROR: used `unwrap_err()` on a `Result` value + //~^ unwrap_used } fn main() { diff --git a/tests/ui/unwrap.stderr b/tests/ui/unwrap.stderr index 3c1b37bc3d9b..c242541a6bd7 100644 --- a/tests/ui/unwrap.stderr +++ b/tests/ui/unwrap.stderr @@ -19,7 +19,7 @@ LL | let _ = res.unwrap(); = help: consider using `expect()` to provide a better panic message error: used `unwrap_err()` on a `Result` value - --> tests/ui/unwrap.rs:14:13 + --> tests/ui/unwrap.rs:15:13 | LL | let _ = res.unwrap_err(); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unwrap_expect_used.rs b/tests/ui/unwrap_expect_used.rs index a56bd0a8d079..d0bb571273b5 100644 --- a/tests/ui/unwrap_expect_used.rs +++ b/tests/ui/unwrap_expect_used.rs @@ -25,9 +25,10 @@ impl OptionExt for Option { fn main() { Some(3).unwrap(); - //~^ ERROR: used `unwrap()` on an `Option` value + //~^ unwrap_used + Some(3).expect("Hello world!"); - //~^ ERROR: used `expect()` on an `Option` value + //~^ expect_used // Don't trigger on unwrap_err on an option Some(3).unwrap_err(); @@ -43,11 +44,25 @@ fn main() { let a: Result = Ok(3); a.unwrap(); - //~^ ERROR: used `unwrap()` on a `Result` value + //~^ unwrap_used + a.expect("Hello world!"); - //~^ ERROR: used `expect()` on a `Result` value + //~^ expect_used + a.unwrap_err(); - //~^ ERROR: used `unwrap_err()` on a `Result` value + //~^ unwrap_used + a.expect_err("Hello error!"); - //~^ ERROR: used `expect_err()` on a `Result` value + //~^ expect_used + + // Don't trigger in compile time contexts by default + const SOME: Option = Some(3); + const UNWRAPPED: i32 = SOME.unwrap(); + const EXPECTED: i32 = SOME.expect("Not three?"); + const { + SOME.unwrap(); + } + const { + SOME.expect("Still not three?"); + } } diff --git a/tests/ui/unwrap_expect_used.stderr b/tests/ui/unwrap_expect_used.stderr index 9069522a4df1..79eac3f58ccb 100644 --- a/tests/ui/unwrap_expect_used.stderr +++ b/tests/ui/unwrap_expect_used.stderr @@ -9,7 +9,7 @@ LL | Some(3).unwrap(); = help: to override `-D warnings` add `#[allow(clippy::unwrap_used)]` error: used `expect()` on an `Option` value - --> tests/ui/unwrap_expect_used.rs:29:5 + --> tests/ui/unwrap_expect_used.rs:30:5 | LL | Some(3).expect("Hello world!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | Some(3).expect("Hello world!"); = help: to override `-D warnings` add `#[allow(clippy::expect_used)]` error: used `unwrap()` on a `Result` value - --> tests/ui/unwrap_expect_used.rs:45:5 + --> tests/ui/unwrap_expect_used.rs:46:5 | LL | a.unwrap(); | ^^^^^^^^^^ @@ -27,7 +27,7 @@ LL | a.unwrap(); = note: if this value is an `Err`, it will panic error: used `expect()` on a `Result` value - --> tests/ui/unwrap_expect_used.rs:47:5 + --> tests/ui/unwrap_expect_used.rs:49:5 | LL | a.expect("Hello world!"); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | a.expect("Hello world!"); = note: if this value is an `Err`, it will panic error: used `unwrap_err()` on a `Result` value - --> tests/ui/unwrap_expect_used.rs:49:5 + --> tests/ui/unwrap_expect_used.rs:52:5 | LL | a.unwrap_err(); | ^^^^^^^^^^^^^^ @@ -43,7 +43,7 @@ LL | a.unwrap_err(); = note: if this value is an `Ok`, it will panic error: used `expect_err()` on a `Result` value - --> tests/ui/unwrap_expect_used.rs:51:5 + --> tests/ui/unwrap_expect_used.rs:55:5 | LL | a.expect_err("Hello error!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unwrap_in_result.rs b/tests/ui/unwrap_in_result.rs index 62c6d959c84b..4e872c67b423 100644 --- a/tests/ui/unwrap_in_result.rs +++ b/tests/ui/unwrap_in_result.rs @@ -20,7 +20,8 @@ impl A { // should be detected fn bad_divisible_by_3(i_str: String) -> Result { - //~^ ERROR: used unwrap or expect in a function that returns result or option + //~^ unwrap_in_result + // checks whether a string represents a number divisible by 3 let i = i_str.parse::().unwrap(); if i % 3 == 0 { @@ -31,7 +32,8 @@ impl A { } fn example_option_expect(i_str: String) -> Option { - //~^ ERROR: used unwrap or expect in a function that returns result or option + //~^ unwrap_in_result + let i = i_str.parse::().expect("not a number"); if i % 3 == 0 { return Some(true); @@ -40,6 +42,7 @@ impl A { } fn in_closure(a: Option) -> Option { + //~^ unwrap_in_result let c = || a.unwrap(); Some(c()) } diff --git a/tests/ui/unwrap_in_result.stderr b/tests/ui/unwrap_in_result.stderr index 201d4ae36ae3..5e3eab813e07 100644 --- a/tests/ui/unwrap_in_result.stderr +++ b/tests/ui/unwrap_in_result.stderr @@ -2,16 +2,13 @@ error: used unwrap or expect in a function that returns result or option --> tests/ui/unwrap_in_result.rs:22:5 | LL | / fn bad_divisible_by_3(i_str: String) -> Result { -LL | | -LL | | // checks whether a string represents a number divisible by 3 -LL | | let i = i_str.parse::().unwrap(); ... | LL | | } | |_____^ | = help: unwrap and expect should not be used in a function that returns result or option note: potential non-recoverable error(s) - --> tests/ui/unwrap_in_result.rs:25:17 + --> tests/ui/unwrap_in_result.rs:26:17 | LL | let i = i_str.parse::().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -19,12 +16,12 @@ LL | let i = i_str.parse::().unwrap(); = help: to override `-D warnings` add `#[allow(clippy::unwrap_in_result)]` error: used unwrap or expect in a function that returns result or option - --> tests/ui/unwrap_in_result.rs:33:5 + --> tests/ui/unwrap_in_result.rs:34:5 | LL | / fn example_option_expect(i_str: String) -> Option { LL | | +LL | | LL | | let i = i_str.parse::().expect("not a number"); -LL | | if i % 3 == 0 { ... | LL | | None LL | | } @@ -32,15 +29,16 @@ LL | | } | = help: unwrap and expect should not be used in a function that returns result or option note: potential non-recoverable error(s) - --> tests/ui/unwrap_in_result.rs:35:17 + --> tests/ui/unwrap_in_result.rs:37:17 | LL | let i = i_str.parse::().expect("not a number"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: used unwrap or expect in a function that returns result or option - --> tests/ui/unwrap_in_result.rs:42:5 + --> tests/ui/unwrap_in_result.rs:44:5 | LL | / fn in_closure(a: Option) -> Option { +LL | | LL | | let c = || a.unwrap(); LL | | Some(c()) LL | | } @@ -48,7 +46,7 @@ LL | | } | = help: unwrap and expect should not be used in a function that returns result or option note: potential non-recoverable error(s) - --> tests/ui/unwrap_in_result.rs:43:20 + --> tests/ui/unwrap_in_result.rs:46:20 | LL | let c = || a.unwrap(); | ^^^^^^^^^^ diff --git a/tests/ui/unwrap_or.fixed b/tests/ui/unwrap_or.fixed index 62bc1966da6f..c794ed577032 100644 --- a/tests/ui/unwrap_or.fixed +++ b/tests/ui/unwrap_or.fixed @@ -3,11 +3,10 @@ fn main() { let s = Some(String::from("test string")).unwrap_or_else(|| "Fail".to_string()).len(); - //~^ ERROR: function call inside of `unwrap_or` - //~| NOTE: `-D clippy::or-fun-call` implied by `-D warnings` + //~^ or_fun_call } fn new_lines() { let s = Some(String::from("test string")).unwrap_or_else(|| "Fail".to_string()).len(); - //~^ ERROR: function call inside of `unwrap_or` + //~^ or_fun_call } diff --git a/tests/ui/unwrap_or.rs b/tests/ui/unwrap_or.rs index e8e4b6b7168f..11a6883b7403 100644 --- a/tests/ui/unwrap_or.rs +++ b/tests/ui/unwrap_or.rs @@ -3,11 +3,10 @@ fn main() { let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); - //~^ ERROR: function call inside of `unwrap_or` - //~| NOTE: `-D clippy::or-fun-call` implied by `-D warnings` + //~^ or_fun_call } fn new_lines() { let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); - //~^ ERROR: function call inside of `unwrap_or` + //~^ or_fun_call } diff --git a/tests/ui/unwrap_or.stderr b/tests/ui/unwrap_or.stderr index b712f8cf693d..e95633680acc 100644 --- a/tests/ui/unwrap_or.stderr +++ b/tests/ui/unwrap_or.stderr @@ -8,7 +8,7 @@ LL | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()) = help: to override `-D warnings` add `#[allow(clippy::or_fun_call)]` error: function call inside of `unwrap_or` - --> tests/ui/unwrap_or.rs:11:47 + --> tests/ui/unwrap_or.rs:10:47 | LL | let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| "Fail".to_string())` diff --git a/tests/ui/unwrap_or_else_default.fixed b/tests/ui/unwrap_or_else_default.fixed index 8d5d34175c52..561cbce473de 100644 --- a/tests/ui/unwrap_or_else_default.fixed +++ b/tests/ui/unwrap_or_else_default.fixed @@ -44,6 +44,7 @@ fn unwrap_or_else_default() { let with_new = Some(vec![1]); with_new.unwrap_or_default(); + //~^ unwrap_or_default let with_err: Result<_, ()> = Ok(vec![1]); with_err.unwrap_or_else(make); @@ -58,43 +59,56 @@ fn unwrap_or_else_default() { let with_real_default = None::; with_real_default.unwrap_or_default(); + //~^ unwrap_or_default let with_default_trait = Some(1); with_default_trait.unwrap_or_default(); + //~^ unwrap_or_default let with_default_type = Some(1); with_default_type.unwrap_or_default(); + //~^ unwrap_or_default let with_default_type: Option> = None; with_default_type.unwrap_or_default(); + //~^ unwrap_or_default let empty_string = None::; empty_string.unwrap_or_default(); + //~^ unwrap_or_default } fn type_certainty(option: Option>) { option.unwrap_or_default().push(1); + //~^ unwrap_or_default let option: std::option::Option> = None; option.unwrap_or_default().push(1); + //~^ unwrap_or_default let option: Option> = None; option.unwrap_or_default().push(1); + //~^ unwrap_or_default let option = std::option::Option::>::None; option.unwrap_or_default().push(1); + //~^ unwrap_or_default let option = Option::>::None; option.unwrap_or_default().push(1); + //~^ unwrap_or_default let option = std::option::Option::None::>; option.unwrap_or_default().push(1); + //~^ unwrap_or_default let option = Option::None::>; option.unwrap_or_default().push(1); + //~^ unwrap_or_default let option = None::>; option.unwrap_or_default().push(1); + //~^ unwrap_or_default // should not be changed: type annotation with infer, unconcretized initializer let option: Option> = None; @@ -111,6 +125,7 @@ fn type_certainty(option: Option>) { type Alias = Option>; let option: Alias = Option::>::Some(Vec::new()); option.unwrap_or_default().push(1); + //~^ unwrap_or_default } fn method_call_with_deref() { @@ -128,6 +143,7 @@ fn method_call_with_deref() { let inner_map = outer_map.get_mut(&option.unwrap()).unwrap(); let _ = inner_map.entry(0).or_default(); + //~^ unwrap_or_default } fn missing_suggested_method() { diff --git a/tests/ui/unwrap_or_else_default.rs b/tests/ui/unwrap_or_else_default.rs index adbcb4b44659..8389be964fe6 100644 --- a/tests/ui/unwrap_or_else_default.rs +++ b/tests/ui/unwrap_or_else_default.rs @@ -44,6 +44,7 @@ fn unwrap_or_else_default() { let with_new = Some(vec![1]); with_new.unwrap_or_else(Vec::new); + //~^ unwrap_or_default let with_err: Result<_, ()> = Ok(vec![1]); with_err.unwrap_or_else(make); @@ -58,43 +59,56 @@ fn unwrap_or_else_default() { let with_real_default = None::; with_real_default.unwrap_or_else(::default); + //~^ unwrap_or_default let with_default_trait = Some(1); with_default_trait.unwrap_or_else(Default::default); + //~^ unwrap_or_default let with_default_type = Some(1); with_default_type.unwrap_or_else(u64::default); + //~^ unwrap_or_default let with_default_type: Option> = None; with_default_type.unwrap_or_else(Vec::new); + //~^ unwrap_or_default let empty_string = None::; empty_string.unwrap_or_else(|| "".to_string()); + //~^ unwrap_or_default } fn type_certainty(option: Option>) { option.unwrap_or_else(Vec::new).push(1); + //~^ unwrap_or_default let option: std::option::Option> = None; option.unwrap_or_else(Vec::new).push(1); + //~^ unwrap_or_default let option: Option> = None; option.unwrap_or_else(Vec::new).push(1); + //~^ unwrap_or_default let option = std::option::Option::>::None; option.unwrap_or_else(Vec::new).push(1); + //~^ unwrap_or_default let option = Option::>::None; option.unwrap_or_else(Vec::new).push(1); + //~^ unwrap_or_default let option = std::option::Option::None::>; option.unwrap_or_else(Vec::new).push(1); + //~^ unwrap_or_default let option = Option::None::>; option.unwrap_or_else(Vec::new).push(1); + //~^ unwrap_or_default let option = None::>; option.unwrap_or_else(Vec::new).push(1); + //~^ unwrap_or_default // should not be changed: type annotation with infer, unconcretized initializer let option: Option> = None; @@ -111,6 +125,7 @@ fn type_certainty(option: Option>) { type Alias = Option>; let option: Alias = Option::>::Some(Vec::new()); option.unwrap_or_else(Vec::new).push(1); + //~^ unwrap_or_default } fn method_call_with_deref() { @@ -128,6 +143,7 @@ fn method_call_with_deref() { let inner_map = outer_map.get_mut(&option.unwrap()).unwrap(); let _ = inner_map.entry(0).or_insert_with(Default::default); + //~^ unwrap_or_default } fn missing_suggested_method() { diff --git a/tests/ui/unwrap_or_else_default.stderr b/tests/ui/unwrap_or_else_default.stderr index e4b4a0a1f6aa..a001f7e46add 100644 --- a/tests/ui/unwrap_or_else_default.stderr +++ b/tests/ui/unwrap_or_else_default.stderr @@ -8,47 +8,35 @@ LL | with_new.unwrap_or_else(Vec::new); = help: to override `-D warnings` add `#[allow(clippy::unwrap_or_default)]` error: use of `unwrap_or_else` to construct default value - --> tests/ui/unwrap_or_else_default.rs:60:23 + --> tests/ui/unwrap_or_else_default.rs:61:23 | LL | with_real_default.unwrap_or_else(::default); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or_else` to construct default value - --> tests/ui/unwrap_or_else_default.rs:63:24 + --> tests/ui/unwrap_or_else_default.rs:65:24 | LL | with_default_trait.unwrap_or_else(Default::default); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or_else` to construct default value - --> tests/ui/unwrap_or_else_default.rs:66:23 + --> tests/ui/unwrap_or_else_default.rs:69:23 | LL | with_default_type.unwrap_or_else(u64::default); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or_else` to construct default value - --> tests/ui/unwrap_or_else_default.rs:69:23 + --> tests/ui/unwrap_or_else_default.rs:73:23 | LL | with_default_type.unwrap_or_else(Vec::new); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or_else` to construct default value - --> tests/ui/unwrap_or_else_default.rs:72:18 + --> tests/ui/unwrap_or_else_default.rs:77:18 | LL | empty_string.unwrap_or_else(|| "".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` -error: use of `unwrap_or_else` to construct default value - --> tests/ui/unwrap_or_else_default.rs:76:12 - | -LL | option.unwrap_or_else(Vec::new).push(1); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` - -error: use of `unwrap_or_else` to construct default value - --> tests/ui/unwrap_or_else_default.rs:79:12 - | -LL | option.unwrap_or_else(Vec::new).push(1); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` - error: use of `unwrap_or_else` to construct default value --> tests/ui/unwrap_or_else_default.rs:82:12 | @@ -56,19 +44,13 @@ LL | option.unwrap_or_else(Vec::new).push(1); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or_else` to construct default value - --> tests/ui/unwrap_or_else_default.rs:85:12 + --> tests/ui/unwrap_or_else_default.rs:86:12 | LL | option.unwrap_or_else(Vec::new).push(1); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or_else` to construct default value - --> tests/ui/unwrap_or_else_default.rs:88:12 - | -LL | option.unwrap_or_else(Vec::new).push(1); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` - -error: use of `unwrap_or_else` to construct default value - --> tests/ui/unwrap_or_else_default.rs:91:12 + --> tests/ui/unwrap_or_else_default.rs:90:12 | LL | option.unwrap_or_else(Vec::new).push(1); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` @@ -80,19 +62,37 @@ LL | option.unwrap_or_else(Vec::new).push(1); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or_else` to construct default value - --> tests/ui/unwrap_or_else_default.rs:97:12 + --> tests/ui/unwrap_or_else_default.rs:98:12 | LL | option.unwrap_or_else(Vec::new).push(1); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or_else` to construct default value - --> tests/ui/unwrap_or_else_default.rs:113:12 + --> tests/ui/unwrap_or_else_default.rs:102:12 + | +LL | option.unwrap_or_else(Vec::new).push(1); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` + +error: use of `unwrap_or_else` to construct default value + --> tests/ui/unwrap_or_else_default.rs:106:12 + | +LL | option.unwrap_or_else(Vec::new).push(1); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` + +error: use of `unwrap_or_else` to construct default value + --> tests/ui/unwrap_or_else_default.rs:110:12 + | +LL | option.unwrap_or_else(Vec::new).push(1); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` + +error: use of `unwrap_or_else` to construct default value + --> tests/ui/unwrap_or_else_default.rs:127:12 | LL | option.unwrap_or_else(Vec::new).push(1); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `or_insert_with` to construct default value - --> tests/ui/unwrap_or_else_default.rs:130:32 + --> tests/ui/unwrap_or_else_default.rs:145:32 | LL | let _ = inner_map.entry(0).or_insert_with(Default::default); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` diff --git a/tests/ui/upper_case_acronyms.fixed b/tests/ui/upper_case_acronyms.fixed index a8023ed00d21..da44c8e3026e 100644 --- a/tests/ui/upper_case_acronyms.fixed +++ b/tests/ui/upper_case_acronyms.fixed @@ -7,22 +7,21 @@ struct CString; // not linted enum Flags { NS, // not linted Cwr, - //~^ ERROR: name `CWR` contains a capitalized acronym - //~| NOTE: `-D clippy::upper-case-acronyms` implied by `-D warnings` + //~^ upper_case_acronyms Ece, - //~^ ERROR: name `ECE` contains a capitalized acronym + //~^ upper_case_acronyms Urg, - //~^ ERROR: name `URG` contains a capitalized acronym + //~^ upper_case_acronyms Ack, - //~^ ERROR: name `ACK` contains a capitalized acronym + //~^ upper_case_acronyms Psh, - //~^ ERROR: name `PSH` contains a capitalized acronym + //~^ upper_case_acronyms Rst, - //~^ ERROR: name `RST` contains a capitalized acronym + //~^ upper_case_acronyms Syn, - //~^ ERROR: name `SYN` contains a capitalized acronym + //~^ upper_case_acronyms Fin, - //~^ ERROR: name `FIN` contains a capitalized acronym + //~^ upper_case_acronyms } // linted with cfg option, beware that lint suggests `GccllvmSomething` instead of @@ -43,18 +42,18 @@ pub enum ParseError { // private, do lint here enum ParseErrorPrivate { Wasd(u8), - //~^ ERROR: name `WASD` contains a capitalized acronym + //~^ upper_case_acronyms Utf8(std::string::FromUtf8Error), Parse(T, String), } // do lint here struct Json; -//~^ ERROR: name `JSON` contains a capitalized acronym +//~^ upper_case_acronyms // do lint here enum Yaml { - //~^ ERROR: name `YAML` contains a capitalized acronym + //~^ upper_case_acronyms Num(u32), Str(String), } @@ -62,7 +61,7 @@ enum Yaml { // test for issue #7708 enum AllowOnField { Disallow, - //~^ ERROR: name `DISALLOW` contains a capitalized acronym + //~^ upper_case_acronyms #[allow(clippy::upper_case_acronyms)] ALLOW, } diff --git a/tests/ui/upper_case_acronyms.rs b/tests/ui/upper_case_acronyms.rs index c4711b87ec38..d223b02acda9 100644 --- a/tests/ui/upper_case_acronyms.rs +++ b/tests/ui/upper_case_acronyms.rs @@ -7,22 +7,21 @@ struct CString; // not linted enum Flags { NS, // not linted CWR, - //~^ ERROR: name `CWR` contains a capitalized acronym - //~| NOTE: `-D clippy::upper-case-acronyms` implied by `-D warnings` + //~^ upper_case_acronyms ECE, - //~^ ERROR: name `ECE` contains a capitalized acronym + //~^ upper_case_acronyms URG, - //~^ ERROR: name `URG` contains a capitalized acronym + //~^ upper_case_acronyms ACK, - //~^ ERROR: name `ACK` contains a capitalized acronym + //~^ upper_case_acronyms PSH, - //~^ ERROR: name `PSH` contains a capitalized acronym + //~^ upper_case_acronyms RST, - //~^ ERROR: name `RST` contains a capitalized acronym + //~^ upper_case_acronyms SYN, - //~^ ERROR: name `SYN` contains a capitalized acronym + //~^ upper_case_acronyms FIN, - //~^ ERROR: name `FIN` contains a capitalized acronym + //~^ upper_case_acronyms } // linted with cfg option, beware that lint suggests `GccllvmSomething` instead of @@ -43,18 +42,18 @@ pub enum ParseError { // private, do lint here enum ParseErrorPrivate { WASD(u8), - //~^ ERROR: name `WASD` contains a capitalized acronym + //~^ upper_case_acronyms Utf8(std::string::FromUtf8Error), Parse(T, String), } // do lint here struct JSON; -//~^ ERROR: name `JSON` contains a capitalized acronym +//~^ upper_case_acronyms // do lint here enum YAML { - //~^ ERROR: name `YAML` contains a capitalized acronym + //~^ upper_case_acronyms Num(u32), Str(String), } @@ -62,7 +61,7 @@ enum YAML { // test for issue #7708 enum AllowOnField { DISALLOW, - //~^ ERROR: name `DISALLOW` contains a capitalized acronym + //~^ upper_case_acronyms #[allow(clippy::upper_case_acronyms)] ALLOW, } diff --git a/tests/ui/upper_case_acronyms.stderr b/tests/ui/upper_case_acronyms.stderr index 1f8046c8e841..dd548fc143e2 100644 --- a/tests/ui/upper_case_acronyms.stderr +++ b/tests/ui/upper_case_acronyms.stderr @@ -8,67 +8,67 @@ LL | CWR, = help: to override `-D warnings` add `#[allow(clippy::upper_case_acronyms)]` error: name `ECE` contains a capitalized acronym - --> tests/ui/upper_case_acronyms.rs:12:5 + --> tests/ui/upper_case_acronyms.rs:11:5 | LL | ECE, | ^^^ help: consider making the acronym lowercase, except the initial letter: `Ece` error: name `URG` contains a capitalized acronym - --> tests/ui/upper_case_acronyms.rs:14:5 + --> tests/ui/upper_case_acronyms.rs:13:5 | LL | URG, | ^^^ help: consider making the acronym lowercase, except the initial letter: `Urg` error: name `ACK` contains a capitalized acronym - --> tests/ui/upper_case_acronyms.rs:16:5 + --> tests/ui/upper_case_acronyms.rs:15:5 | LL | ACK, | ^^^ help: consider making the acronym lowercase, except the initial letter (notice the capitalization): `Ack` error: name `PSH` contains a capitalized acronym - --> tests/ui/upper_case_acronyms.rs:18:5 + --> tests/ui/upper_case_acronyms.rs:17:5 | LL | PSH, | ^^^ help: consider making the acronym lowercase, except the initial letter: `Psh` error: name `RST` contains a capitalized acronym - --> tests/ui/upper_case_acronyms.rs:20:5 + --> tests/ui/upper_case_acronyms.rs:19:5 | LL | RST, | ^^^ help: consider making the acronym lowercase, except the initial letter: `Rst` error: name `SYN` contains a capitalized acronym - --> tests/ui/upper_case_acronyms.rs:22:5 + --> tests/ui/upper_case_acronyms.rs:21:5 | LL | SYN, | ^^^ help: consider making the acronym lowercase, except the initial letter: `Syn` error: name `FIN` contains a capitalized acronym - --> tests/ui/upper_case_acronyms.rs:24:5 + --> tests/ui/upper_case_acronyms.rs:23:5 | LL | FIN, | ^^^ help: consider making the acronym lowercase, except the initial letter: `Fin` error: name `WASD` contains a capitalized acronym - --> tests/ui/upper_case_acronyms.rs:45:5 + --> tests/ui/upper_case_acronyms.rs:44:5 | LL | WASD(u8), | ^^^^ help: consider making the acronym lowercase, except the initial letter: `Wasd` error: name `JSON` contains a capitalized acronym - --> tests/ui/upper_case_acronyms.rs:52:8 + --> tests/ui/upper_case_acronyms.rs:51:8 | LL | struct JSON; | ^^^^ help: consider making the acronym lowercase, except the initial letter: `Json` error: name `YAML` contains a capitalized acronym - --> tests/ui/upper_case_acronyms.rs:56:6 + --> tests/ui/upper_case_acronyms.rs:55:6 | LL | enum YAML { | ^^^^ help: consider making the acronym lowercase, except the initial letter: `Yaml` error: name `DISALLOW` contains a capitalized acronym - --> tests/ui/upper_case_acronyms.rs:64:5 + --> tests/ui/upper_case_acronyms.rs:63:5 | LL | DISALLOW, | ^^^^^^^^ help: consider making the acronym lowercase, except the initial letter: `Disallow` diff --git a/tests/ui/use_self.fixed b/tests/ui/use_self.fixed index ffc5b74d7bd6..f15e5e0a5bb4 100644 --- a/tests/ui/use_self.fixed +++ b/tests/ui/use_self.fixed @@ -21,16 +21,22 @@ mod use_self { impl Foo { fn new() -> Self { + //~^ use_self Self {} + //~^ use_self } fn test() -> Self { + //~^ use_self Self::new() + //~^ use_self } } impl Default for Foo { fn default() -> Self { + //~^ use_self Self::new() + //~^ use_self } } } @@ -72,6 +78,7 @@ mod lifetimes { } fn clone(&self) -> Self { + //~^ use_self Foo { foo_str: self.foo_str } } @@ -105,6 +112,8 @@ mod existential { impl Foo { fn bad(foos: &[Self]) -> impl Iterator { + //~^ use_self + //~| use_self foos.iter() } @@ -120,6 +129,7 @@ mod tuple_structs { impl TS { pub fn ts() -> Self { Self(0) + //~^ use_self } } } @@ -155,7 +165,9 @@ mod nesting { impl Bar { fn bar() -> Self { + //~^ use_self Self { foo: Foo {} } + //~^ use_self } } @@ -167,7 +179,9 @@ mod nesting { // Should lint here fn baz() -> Self { + //~^ use_self Self {} + //~^ use_self } } @@ -185,8 +199,11 @@ mod nesting { fn method2() { let _ = Self::B(42); + //~^ use_self let _ = Self::C { field: true }; + //~^ use_self let _ = Self::A; + //~^ use_self } } } @@ -229,9 +246,12 @@ mod rustfix { fn fun_2() { Self::fun_1(); + //~^ use_self Self::A; + //~^ use_self Self {}; + //~^ use_self } } } @@ -251,6 +271,7 @@ mod issue3567 { impl Test for TestStruct { fn test() -> TestStruct { Self::from_something() + //~^ use_self } } } @@ -265,11 +286,15 @@ mod paths_created_by_lowering { const B: usize = 1; async fn g() -> Self { + //~^ use_self Self {} + //~^ use_self } fn f<'a>(&self, p: &'a [u8]) -> &'a [u8] { &p[Self::A..Self::B] + //~^ use_self + //~| use_self } } @@ -293,7 +318,9 @@ mod generics { impl Foo { // `Self` is applicable here fn foo(value: T) -> Self { + //~^ use_self Self { value } + //~^ use_self } // `Cannot` use `Self` as a return type as the generic types are different @@ -466,6 +493,7 @@ mod nested_paths { impl A { fn test() -> Self { Self::new::(submod::B {}) + //~^ use_self } } } @@ -503,6 +531,7 @@ mod issue7206 { impl<'a> S2> { fn new_again() -> Self { Self::new() + //~^ use_self } } } @@ -540,13 +569,16 @@ mod use_self_in_pat { fn do_stuff(self) { match self { Self::Bar => unimplemented!(), + //~^ use_self Self::Baz => unimplemented!(), + //~^ use_self } match Some(1) { Some(_) => unimplemented!(), None => unimplemented!(), } if let Self::Bar = self { + //~^ use_self unimplemented!() } } @@ -571,16 +603,22 @@ mod issue8845 { fn get_value(&self) -> u8 { match self { Self::Num(n) => *n, + //~^ use_self Self::TupleNums(n, _m) => *n, + //~^ use_self Self::StructNums { one, two: _ } => *one, + //~^ use_self } } fn use_crate(&self) -> u8 { match self { Self::Num(n) => *n, + //~^ use_self Self::TupleNums(n, _m) => *n, + //~^ use_self Self::StructNums { one, two: _ } => *one, + //~^ use_self } } @@ -597,11 +635,13 @@ mod issue8845 { impl Foo { fn get_value(&self) -> u8 { let Self(x) = self; + //~^ use_self *x } fn use_crate(&self) -> u8 { let Self(x) = self; + //~^ use_self *x } } @@ -609,11 +649,13 @@ mod issue8845 { impl Bar { fn get_value(&self) -> u8 { let Self { x, .. } = self; + //~^ use_self *x } fn use_crate(&self) -> u8 { let Self { x, .. } = self; + //~^ use_self *x } } @@ -653,6 +695,7 @@ fn msrv_1_37() { fn foo(self) { match self { Self::A => {}, + //~^ use_self } } } @@ -667,3 +710,48 @@ mod issue_10371 { } } } + +mod issue_13092 { + use std::cell::RefCell; + macro_rules! macro_inner_item { + ($ty:ty) => { + fn foo(_: $ty) { + fn inner(_: $ty) {} + } + }; + } + + #[derive(Default)] + struct MyStruct; + + impl MyStruct { + macro_inner_item!(MyStruct); + } + + impl MyStruct { + thread_local! { + static SPECIAL: RefCell = RefCell::default(); + } + } +} + +mod crash_check_13128 { + struct A; + + impl A { + fn a() { + struct B; + + // pushes a NoCheck + impl Iterator for &B { + // Pops the NoCheck + type Item = A; + + // Lints A -> Self + fn next(&mut self) -> Option { + Some(A) + } + } + } + } +} diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index eb9d96168bcd..b6376938611e 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -21,16 +21,22 @@ mod use_self { impl Foo { fn new() -> Foo { + //~^ use_self Foo {} + //~^ use_self } fn test() -> Foo { + //~^ use_self Foo::new() + //~^ use_self } } impl Default for Foo { fn default() -> Foo { + //~^ use_self Foo::new() + //~^ use_self } } } @@ -72,6 +78,7 @@ mod lifetimes { } fn clone(&self) -> Foo<'a> { + //~^ use_self Foo { foo_str: self.foo_str } } @@ -105,6 +112,8 @@ mod existential { impl Foo { fn bad(foos: &[Foo]) -> impl Iterator { + //~^ use_self + //~| use_self foos.iter() } @@ -120,6 +129,7 @@ mod tuple_structs { impl TS { pub fn ts() -> Self { TS(0) + //~^ use_self } } } @@ -155,7 +165,9 @@ mod nesting { impl Bar { fn bar() -> Bar { + //~^ use_self Bar { foo: Foo {} } + //~^ use_self } } @@ -167,7 +179,9 @@ mod nesting { // Should lint here fn baz() -> Foo { + //~^ use_self Foo {} + //~^ use_self } } @@ -185,8 +199,11 @@ mod nesting { fn method2() { let _ = Enum::B(42); + //~^ use_self let _ = Enum::C { field: true }; + //~^ use_self let _ = Enum::A; + //~^ use_self } } } @@ -229,9 +246,12 @@ mod rustfix { fn fun_2() { nested::A::fun_1(); + //~^ use_self nested::A::A; + //~^ use_self nested::A {}; + //~^ use_self } } } @@ -251,6 +271,7 @@ mod issue3567 { impl Test for TestStruct { fn test() -> TestStruct { TestStruct::from_something() + //~^ use_self } } } @@ -265,11 +286,15 @@ mod paths_created_by_lowering { const B: usize = 1; async fn g() -> S { + //~^ use_self S {} + //~^ use_self } fn f<'a>(&self, p: &'a [u8]) -> &'a [u8] { &p[S::A..S::B] + //~^ use_self + //~| use_self } } @@ -293,7 +318,9 @@ mod generics { impl Foo { // `Self` is applicable here fn foo(value: T) -> Foo { + //~^ use_self Foo:: { value } + //~^ use_self } // `Cannot` use `Self` as a return type as the generic types are different @@ -466,6 +493,7 @@ mod nested_paths { impl A { fn test() -> Self { A::new::(submod::B {}) + //~^ use_self } } } @@ -503,6 +531,7 @@ mod issue7206 { impl<'a> S2> { fn new_again() -> Self { S2::new() + //~^ use_self } } } @@ -540,13 +569,16 @@ mod use_self_in_pat { fn do_stuff(self) { match self { Foo::Bar => unimplemented!(), + //~^ use_self Foo::Baz => unimplemented!(), + //~^ use_self } match Some(1) { Some(_) => unimplemented!(), None => unimplemented!(), } if let Foo::Bar = self { + //~^ use_self unimplemented!() } } @@ -571,16 +603,22 @@ mod issue8845 { fn get_value(&self) -> u8 { match self { Something::Num(n) => *n, + //~^ use_self Something::TupleNums(n, _m) => *n, + //~^ use_self Something::StructNums { one, two: _ } => *one, + //~^ use_self } } fn use_crate(&self) -> u8 { match self { crate::issue8845::Something::Num(n) => *n, + //~^ use_self crate::issue8845::Something::TupleNums(n, _m) => *n, + //~^ use_self crate::issue8845::Something::StructNums { one, two: _ } => *one, + //~^ use_self } } @@ -597,11 +635,13 @@ mod issue8845 { impl Foo { fn get_value(&self) -> u8 { let Foo(x) = self; + //~^ use_self *x } fn use_crate(&self) -> u8 { let crate::issue8845::Foo(x) = self; + //~^ use_self *x } } @@ -609,11 +649,13 @@ mod issue8845 { impl Bar { fn get_value(&self) -> u8 { let Bar { x, .. } = self; + //~^ use_self *x } fn use_crate(&self) -> u8 { let crate::issue8845::Bar { x, .. } = self; + //~^ use_self *x } } @@ -653,6 +695,7 @@ fn msrv_1_37() { fn foo(self) { match self { E::A => {}, + //~^ use_self } } } @@ -667,3 +710,48 @@ mod issue_10371 { } } } + +mod issue_13092 { + use std::cell::RefCell; + macro_rules! macro_inner_item { + ($ty:ty) => { + fn foo(_: $ty) { + fn inner(_: $ty) {} + } + }; + } + + #[derive(Default)] + struct MyStruct; + + impl MyStruct { + macro_inner_item!(MyStruct); + } + + impl MyStruct { + thread_local! { + static SPECIAL: RefCell = RefCell::default(); + } + } +} + +mod crash_check_13128 { + struct A; + + impl A { + fn a() { + struct B; + + // pushes a NoCheck + impl Iterator for &B { + // Pops the NoCheck + type Item = A; + + // Lints A -> Self + fn next(&mut self) -> Option { + Some(A) + } + } + } + } +} diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index bd5b685b45d5..781327696ac1 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -8,253 +8,253 @@ LL | fn new() -> Foo { = help: to override `-D warnings` add `#[allow(clippy::use_self)]` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:24:13 + --> tests/ui/use_self.rs:25:13 | LL | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:26:22 + --> tests/ui/use_self.rs:28:22 | LL | fn test() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:27:13 + --> tests/ui/use_self.rs:30:13 | LL | Foo::new() | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:32:25 + --> tests/ui/use_self.rs:36:25 | LL | fn default() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:33:13 + --> tests/ui/use_self.rs:38:13 | LL | Foo::new() | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:74:28 + --> tests/ui/use_self.rs:80:28 | LL | fn clone(&self) -> Foo<'a> { | ^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:107:24 + --> tests/ui/use_self.rs:114:24 | LL | fn bad(foos: &[Foo]) -> impl Iterator { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:107:55 + --> tests/ui/use_self.rs:114:55 | LL | fn bad(foos: &[Foo]) -> impl Iterator { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:122:13 + --> tests/ui/use_self.rs:131:13 | LL | TS(0) | ^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:157:29 + --> tests/ui/use_self.rs:167:29 | LL | fn bar() -> Bar { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:158:21 + --> tests/ui/use_self.rs:169:21 | LL | Bar { foo: Foo {} } | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:169:21 + --> tests/ui/use_self.rs:181:21 | LL | fn baz() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:170:13 + --> tests/ui/use_self.rs:183:13 | LL | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:187:21 + --> tests/ui/use_self.rs:201:21 | LL | let _ = Enum::B(42); | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:188:21 + --> tests/ui/use_self.rs:203:21 | LL | let _ = Enum::C { field: true }; | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:189:21 + --> tests/ui/use_self.rs:205:21 | LL | let _ = Enum::A; | ^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:231:13 + --> tests/ui/use_self.rs:248:13 | LL | nested::A::fun_1(); | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:232:13 + --> tests/ui/use_self.rs:250:13 | LL | nested::A::A; | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:234:13 + --> tests/ui/use_self.rs:253:13 | LL | nested::A {}; | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:253:13 + --> tests/ui/use_self.rs:273:13 | LL | TestStruct::from_something() | ^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:267:25 + --> tests/ui/use_self.rs:288:25 | LL | async fn g() -> S { | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:268:13 + --> tests/ui/use_self.rs:290:13 | LL | S {} | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:272:16 + --> tests/ui/use_self.rs:295:16 | LL | &p[S::A..S::B] | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:272:22 + --> tests/ui/use_self.rs:295:22 | LL | &p[S::A..S::B] | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:295:29 + --> tests/ui/use_self.rs:320:29 | LL | fn foo(value: T) -> Foo { | ^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:296:13 + --> tests/ui/use_self.rs:322:13 | LL | Foo:: { value } | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:468:13 + --> tests/ui/use_self.rs:495:13 | LL | A::new::(submod::B {}) | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:505:13 + --> tests/ui/use_self.rs:533:13 | LL | S2::new() | ^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:542:17 + --> tests/ui/use_self.rs:571:17 | LL | Foo::Bar => unimplemented!(), | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:543:17 + --> tests/ui/use_self.rs:573:17 | LL | Foo::Baz => unimplemented!(), | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:549:20 + --> tests/ui/use_self.rs:580:20 | LL | if let Foo::Bar = self { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:573:17 + --> tests/ui/use_self.rs:605:17 | LL | Something::Num(n) => *n, | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:574:17 + --> tests/ui/use_self.rs:607:17 | LL | Something::TupleNums(n, _m) => *n, | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:575:17 + --> tests/ui/use_self.rs:609:17 | LL | Something::StructNums { one, two: _ } => *one, | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:581:17 + --> tests/ui/use_self.rs:616:17 | LL | crate::issue8845::Something::Num(n) => *n, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:582:17 + --> tests/ui/use_self.rs:618:17 | LL | crate::issue8845::Something::TupleNums(n, _m) => *n, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:583:17 + --> tests/ui/use_self.rs:620:17 | LL | crate::issue8845::Something::StructNums { one, two: _ } => *one, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:599:17 + --> tests/ui/use_self.rs:637:17 | LL | let Foo(x) = self; | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:604:17 + --> tests/ui/use_self.rs:643:17 | LL | let crate::issue8845::Foo(x) = self; | ^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:611:17 + --> tests/ui/use_self.rs:651:17 | LL | let Bar { x, .. } = self; | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:616:17 + --> tests/ui/use_self.rs:657:17 | LL | let crate::issue8845::Bar { x, .. } = self; | ^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self.rs:655:17 + --> tests/ui/use_self.rs:697:17 | LL | E::A => {}, | ^ help: use the applicable keyword: `Self` diff --git a/tests/ui/use_self_trait.fixed b/tests/ui/use_self_trait.fixed index 2758ec7aca1f..c5d800dc94e1 100644 --- a/tests/ui/use_self_trait.fixed +++ b/tests/ui/use_self_trait.fixed @@ -17,28 +17,42 @@ struct Bad; impl SelfTrait for Bad { fn refs(p1: &Self) -> &Self { + //~^ use_self + //~| use_self p1 } fn ref_refs<'a>(p1: &'a &'a Self) -> &'a &'a Self { + //~^ use_self + //~| use_self p1 } fn mut_refs(p1: &mut Self) -> &mut Self { + //~^ use_self + //~| use_self p1 } fn nested(_p1: Box, _p2: (&u8, &Self)) {} + //~^ use_self + //~| use_self fn vals(_: Self) -> Self { + //~^ use_self + //~| use_self Self + //~^ use_self } } impl Mul for Bad { type Output = Self; + //~^ use_self fn mul(self, rhs: Self) -> Self { + //~^ use_self + //~| use_self rhs } } @@ -46,6 +60,7 @@ impl Mul for Bad { impl Clone for Bad { fn clone(&self) -> Self { Self + //~^ use_self } } @@ -143,6 +158,8 @@ mod full_path_replacement { impl Error for std::fmt::Error { fn custom(_msg: T) -> Self { Self // Should lint + // + //~^^ use_self } } } diff --git a/tests/ui/use_self_trait.rs b/tests/ui/use_self_trait.rs index 31031e8f50b2..dcf5820afc26 100644 --- a/tests/ui/use_self_trait.rs +++ b/tests/ui/use_self_trait.rs @@ -17,28 +17,42 @@ struct Bad; impl SelfTrait for Bad { fn refs(p1: &Bad) -> &Bad { + //~^ use_self + //~| use_self p1 } fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { + //~^ use_self + //~| use_self p1 } fn mut_refs(p1: &mut Bad) -> &mut Bad { + //~^ use_self + //~| use_self p1 } fn nested(_p1: Box, _p2: (&u8, &Bad)) {} + //~^ use_self + //~| use_self fn vals(_: Bad) -> Bad { + //~^ use_self + //~| use_self Bad + //~^ use_self } } impl Mul for Bad { type Output = Bad; + //~^ use_self fn mul(self, rhs: Bad) -> Bad { + //~^ use_self + //~| use_self rhs } } @@ -46,6 +60,7 @@ impl Mul for Bad { impl Clone for Bad { fn clone(&self) -> Self { Bad + //~^ use_self } } @@ -143,6 +158,8 @@ mod full_path_replacement { impl Error for std::fmt::Error { fn custom(_msg: T) -> Self { std::fmt::Error // Should lint + // + //~^^ use_self } } } diff --git a/tests/ui/use_self_trait.stderr b/tests/ui/use_self_trait.stderr index 9cbb728ebe66..1b664b3b7a28 100644 --- a/tests/ui/use_self_trait.stderr +++ b/tests/ui/use_self_trait.stderr @@ -14,85 +14,85 @@ LL | fn refs(p1: &Bad) -> &Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self_trait.rs:23:33 + --> tests/ui/use_self_trait.rs:25:33 | LL | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self_trait.rs:23:49 + --> tests/ui/use_self_trait.rs:25:49 | LL | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self_trait.rs:27:26 + --> tests/ui/use_self_trait.rs:31:26 | LL | fn mut_refs(p1: &mut Bad) -> &mut Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self_trait.rs:27:39 + --> tests/ui/use_self_trait.rs:31:39 | LL | fn mut_refs(p1: &mut Bad) -> &mut Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self_trait.rs:31:24 + --> tests/ui/use_self_trait.rs:37:24 | LL | fn nested(_p1: Box, _p2: (&u8, &Bad)) {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self_trait.rs:31:42 + --> tests/ui/use_self_trait.rs:37:42 | LL | fn nested(_p1: Box, _p2: (&u8, &Bad)) {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self_trait.rs:33:16 + --> tests/ui/use_self_trait.rs:41:16 | LL | fn vals(_: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self_trait.rs:33:24 + --> tests/ui/use_self_trait.rs:41:24 | LL | fn vals(_: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self_trait.rs:34:9 + --> tests/ui/use_self_trait.rs:44:9 | LL | Bad | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self_trait.rs:39:19 + --> tests/ui/use_self_trait.rs:50:19 | LL | type Output = Bad; | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self_trait.rs:41:23 + --> tests/ui/use_self_trait.rs:53:23 | LL | fn mul(self, rhs: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self_trait.rs:41:31 + --> tests/ui/use_self_trait.rs:53:31 | LL | fn mul(self, rhs: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self_trait.rs:48:9 + --> tests/ui/use_self_trait.rs:62:9 | LL | Bad | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> tests/ui/use_self_trait.rs:145:13 + --> tests/ui/use_self_trait.rs:160:13 | LL | std::fmt::Error // Should lint | ^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` diff --git a/tests/ui/used_underscore_binding.rs b/tests/ui/used_underscore_binding.rs index 84dccf28f3b2..3b063fd16be1 100644 --- a/tests/ui/used_underscore_binding.rs +++ b/tests/ui/used_underscore_binding.rs @@ -21,12 +21,16 @@ macro_rules! test_macro { /// Tests that we lint if we use a binding with a single leading underscore fn prefix_underscore(_foo: u32) -> u32 { _foo + 1 + //~^ used_underscore_binding } /// Tests that we lint if we use a `_`-variable defined outside within a macro expansion fn in_macro_or_desugar(_foo: u32) { println!("{}", _foo); + //~^ used_underscore_binding assert_eq!(_foo, _foo); + //~^ used_underscore_binding + //~| used_underscore_binding test_macro!() + 1; } @@ -40,6 +44,7 @@ struct StructFieldTest { fn in_struct_field() { let mut s = StructFieldTest { _underscore_field: 0 }; s._underscore_field += 1; + //~^ used_underscore_binding } /// Tests that we do not lint if the struct field is used in code created with derive. @@ -101,6 +106,7 @@ async fn await_desugaring() { ({ let _i = 5; uses_i(_i); + //~^ used_underscore_binding foo() }) .await diff --git a/tests/ui/used_underscore_binding.stderr b/tests/ui/used_underscore_binding.stderr index f9e8013d3ad5..7d94d79f9b3b 100644 --- a/tests/ui/used_underscore_binding.stderr +++ b/tests/ui/used_underscore_binding.stderr @@ -13,61 +13,61 @@ LL | fn prefix_underscore(_foo: u32) -> u32 { = help: to override `-D warnings` add `#[allow(clippy::used_underscore_binding)]` error: used underscore-prefixed binding - --> tests/ui/used_underscore_binding.rs:28:20 + --> tests/ui/used_underscore_binding.rs:29:20 | LL | println!("{}", _foo); | ^^^^ | note: binding is defined here - --> tests/ui/used_underscore_binding.rs:27:24 + --> tests/ui/used_underscore_binding.rs:28:24 | LL | fn in_macro_or_desugar(_foo: u32) { | ^^^^ error: used underscore-prefixed binding - --> tests/ui/used_underscore_binding.rs:29:16 + --> tests/ui/used_underscore_binding.rs:31:16 | LL | assert_eq!(_foo, _foo); | ^^^^ | note: binding is defined here - --> tests/ui/used_underscore_binding.rs:27:24 + --> tests/ui/used_underscore_binding.rs:28:24 | LL | fn in_macro_or_desugar(_foo: u32) { | ^^^^ error: used underscore-prefixed binding - --> tests/ui/used_underscore_binding.rs:29:22 + --> tests/ui/used_underscore_binding.rs:31:22 | LL | assert_eq!(_foo, _foo); | ^^^^ | note: binding is defined here - --> tests/ui/used_underscore_binding.rs:27:24 + --> tests/ui/used_underscore_binding.rs:28:24 | LL | fn in_macro_or_desugar(_foo: u32) { | ^^^^ error: used underscore-prefixed binding - --> tests/ui/used_underscore_binding.rs:42:5 + --> tests/ui/used_underscore_binding.rs:46:5 | LL | s._underscore_field += 1; | ^^^^^^^^^^^^^^^^^^^ | note: binding is defined here - --> tests/ui/used_underscore_binding.rs:36:5 + --> tests/ui/used_underscore_binding.rs:40:5 | LL | _underscore_field: u32, | ^^^^^^^^^^^^^^^^^^^^^^ error: used underscore-prefixed binding - --> tests/ui/used_underscore_binding.rs:103:16 + --> tests/ui/used_underscore_binding.rs:108:16 | LL | uses_i(_i); | ^^ | note: binding is defined here - --> tests/ui/used_underscore_binding.rs:102:13 + --> tests/ui/used_underscore_binding.rs:107:13 | LL | let _i = 5; | ^^ diff --git a/tests/ui/used_underscore_items.rs b/tests/ui/used_underscore_items.rs index 223016a5c966..3401df6ae743 100644 --- a/tests/ui/used_underscore_items.rs +++ b/tests/ui/used_underscore_items.rs @@ -41,16 +41,25 @@ mod a { fn main() { _foo1(); + //~^ used_underscore_items let _ = _foo2(); + //~^ used_underscore_items a::b::c::_foo3(); + //~^ used_underscore_items let _ = &_FooStruct {}; + //~^ used_underscore_items let _ = _FooStruct {}; + //~^ used_underscore_items let foo_struct = _FooStruct {}; + //~^ used_underscore_items foo_struct._method_call(); + //~^ used_underscore_items let foo_struct2 = a::b::c::_FooStruct2 {}; + //~^ used_underscore_items foo_struct2._method_call(); + //~^ used_underscore_items } // should not lint exteranl crate. @@ -61,3 +70,13 @@ fn external_item_call() { external_item::_exernal_foo(); } + +// should not lint foreign functions. +// issue #14156 +extern "C" { + pub fn _exit(code: i32) -> !; +} + +fn _f() { + unsafe { _exit(1) } +} diff --git a/tests/ui/used_underscore_items.stderr b/tests/ui/used_underscore_items.stderr index 93ac3a6fec6b..d6e23f1e726a 100644 --- a/tests/ui/used_underscore_items.stderr +++ b/tests/ui/used_underscore_items.stderr @@ -13,7 +13,7 @@ LL | fn _foo1() {} = help: to override `-D warnings` add `#[allow(clippy::used_underscore_items)]` error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:44:13 + --> tests/ui/used_underscore_items.rs:45:13 | LL | let _ = _foo2(); | ^^^^^^^ @@ -25,7 +25,7 @@ LL | fn _foo2() -> i32 { | ^^^^^^^^^^^^^^^^^ error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:45:5 + --> tests/ui/used_underscore_items.rs:47:5 | LL | a::b::c::_foo3(); | ^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL | pub fn _foo3() {} | ^^^^^^^^^^^^^^ error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:46:14 + --> tests/ui/used_underscore_items.rs:49:14 | LL | let _ = &_FooStruct {}; | ^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | struct _FooStruct {} | ^^^^^^^^^^^^^^^^^ error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:47:13 + --> tests/ui/used_underscore_items.rs:51:13 | LL | let _ = _FooStruct {}; | ^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL | struct _FooStruct {} | ^^^^^^^^^^^^^^^^^ error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:49:22 + --> tests/ui/used_underscore_items.rs:54:22 | LL | let foo_struct = _FooStruct {}; | ^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | struct _FooStruct {} | ^^^^^^^^^^^^^^^^^ error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:50:5 + --> tests/ui/used_underscore_items.rs:56:5 | LL | foo_struct._method_call(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL | fn _method_call(self) {} | ^^^^^^^^^^^^^^^^^^^^^ error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:52:23 + --> tests/ui/used_underscore_items.rs:59:23 | LL | let foo_struct2 = a::b::c::_FooStruct2 {}; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL | pub struct _FooStruct2 {} | ^^^^^^^^^^^^^^^^^^^^^^ error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:53:5 + --> tests/ui/used_underscore_items.rs:61:5 | LL | foo_struct2._method_call(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/useful_asref.rs b/tests/ui/useful_asref.rs index d17db9371ee8..a37c2785bde2 100644 --- a/tests/ui/useful_asref.rs +++ b/tests/ui/useful_asref.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![deny(clippy::useless_asref)] #![allow(clippy::needless_lifetimes)] diff --git a/tests/ui/useless_asref.fixed b/tests/ui/useless_asref.fixed index ddbb9255b466..8c1f948fb580 100644 --- a/tests/ui/useless_asref.fixed +++ b/tests/ui/useless_asref.fixed @@ -8,6 +8,7 @@ )] use std::fmt::Debug; +use std::ops::Deref; use std::rc::{Rc, Weak as RcWeak}; use std::sync::{Arc, Weak as ArcWeak}; @@ -48,14 +49,18 @@ fn not_ok() { { let rslice: &[i32] = &*mrslice; foo_rstr(rstr); + //~^ useless_asref foo_rstr(rstr); foo_rslice(rslice); + //~^ useless_asref foo_rslice(rslice); } { foo_mrslice(mrslice); + //~^ useless_asref foo_mrslice(mrslice); foo_rslice(mrslice); + //~^ useless_asref foo_rslice(mrslice); } @@ -63,19 +68,24 @@ fn not_ok() { let rrrrrstr = &&&&rstr; let rrrrrslice = &&&&&*mrslice; foo_rslice(rrrrrslice); + //~^ useless_asref foo_rslice(rrrrrslice); foo_rstr(rrrrrstr); + //~^ useless_asref foo_rstr(rrrrrstr); } { let mrrrrrslice = &mut &mut &mut &mut mrslice; foo_mrslice(mrrrrrslice); + //~^ useless_asref foo_mrslice(mrrrrrslice); foo_rslice(mrrrrrslice); + //~^ useless_asref foo_rslice(mrrrrrslice); } #[allow(unused_parens, clippy::double_parens, clippy::needless_borrow)] foo_rrrrmr((&&&&MoreRef)); + //~^ useless_asref generic_not_ok(mrslice); generic_ok(mrslice); @@ -126,8 +136,10 @@ fn foo_rt(t: &T) { fn generic_not_ok + AsRef + Debug + ?Sized>(mrt: &mut T) { foo_mrt(mrt); + //~^ useless_asref foo_mrt(mrt); foo_rt(mrt); + //~^ useless_asref foo_rt(mrt); } @@ -139,11 +151,13 @@ fn generic_ok + AsRef + ?Sized, T: Debug + ?Sized>(mru: &mut U) { fn foo() { let x = Some(String::new()); let z = x.clone(); - //~^ ERROR: this call to `as_ref.map(...)` does nothing + //~^ useless_asref + let z = x.clone(); - //~^ ERROR: this call to `as_ref.map(...)` does nothing + //~^ useless_asref + let z = x.clone(); - //~^ ERROR: this call to `as_ref.map(...)` does nothing + //~^ useless_asref } mod issue12135 { @@ -167,16 +181,18 @@ mod issue12135 { pub fn f(x: &Struct) -> Option { x.field.clone(); - //~^ ERROR: this call to `as_ref.map(...)` does nothing + //~^ useless_asref + x.field.clone(); - //~^ ERROR: this call to `as_ref.map(...)` does nothing + //~^ useless_asref + x.field.clone(); - //~^ ERROR: this call to `as_ref.map(...)` does nothing + //~^ useless_asref // https://github.com/rust-lang/rust-clippy/pull/12136#discussion_r1451565223 #[allow(clippy::clone_on_copy)] Some(1).clone(); - //~^ ERROR: this call to `as_ref.map(...)` does nothing + //~^ useless_asref x.field.as_ref().map(|v| v.method().clone()) } @@ -198,6 +214,40 @@ fn issue_12528() { let _ = opt.as_ref().map(RcWeak::clone); } +fn issue_14088() { + let s = Some("foo"); + let _: Option<&str> = s.as_ref().map(|x| x.as_ref()); +} + +pub struct Wrap { + inner: T, +} + +impl Deref for Wrap { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +struct NonCloneableError; + +pub struct Issue12357 { + current: Option>>, +} + +impl Issue12357 { + fn f(&self) -> Option> { + self.current.as_ref().map(|p| Arc::clone(p)) + } + + fn g(&self) { + let result: Result = Ok("Hello".to_string()); + let cloned = result.as_ref().map(|s| s.clone()); + } +} + fn main() { not_ok(); ok(); diff --git a/tests/ui/useless_asref.rs b/tests/ui/useless_asref.rs index b0405e930a25..d9db2d4f5596 100644 --- a/tests/ui/useless_asref.rs +++ b/tests/ui/useless_asref.rs @@ -8,6 +8,7 @@ )] use std::fmt::Debug; +use std::ops::Deref; use std::rc::{Rc, Weak as RcWeak}; use std::sync::{Arc, Weak as ArcWeak}; @@ -48,14 +49,18 @@ fn not_ok() { { let rslice: &[i32] = &*mrslice; foo_rstr(rstr.as_ref()); + //~^ useless_asref foo_rstr(rstr); foo_rslice(rslice.as_ref()); + //~^ useless_asref foo_rslice(rslice); } { foo_mrslice(mrslice.as_mut()); + //~^ useless_asref foo_mrslice(mrslice); foo_rslice(mrslice.as_ref()); + //~^ useless_asref foo_rslice(mrslice); } @@ -63,19 +68,24 @@ fn not_ok() { let rrrrrstr = &&&&rstr; let rrrrrslice = &&&&&*mrslice; foo_rslice(rrrrrslice.as_ref()); + //~^ useless_asref foo_rslice(rrrrrslice); foo_rstr(rrrrrstr.as_ref()); + //~^ useless_asref foo_rstr(rrrrrstr); } { let mrrrrrslice = &mut &mut &mut &mut mrslice; foo_mrslice(mrrrrrslice.as_mut()); + //~^ useless_asref foo_mrslice(mrrrrrslice); foo_rslice(mrrrrrslice.as_ref()); + //~^ useless_asref foo_rslice(mrrrrrslice); } #[allow(unused_parens, clippy::double_parens, clippy::needless_borrow)] foo_rrrrmr((&&&&MoreRef).as_ref()); + //~^ useless_asref generic_not_ok(mrslice); generic_ok(mrslice); @@ -126,8 +136,10 @@ fn foo_rt(t: &T) { fn generic_not_ok + AsRef + Debug + ?Sized>(mrt: &mut T) { foo_mrt(mrt.as_mut()); + //~^ useless_asref foo_mrt(mrt); foo_rt(mrt.as_ref()); + //~^ useless_asref foo_rt(mrt); } @@ -139,11 +151,13 @@ fn generic_ok + AsRef + ?Sized, T: Debug + ?Sized>(mru: &mut U) { fn foo() { let x = Some(String::new()); let z = x.as_ref().map(String::clone); - //~^ ERROR: this call to `as_ref.map(...)` does nothing + //~^ useless_asref + let z = x.as_ref().map(|z| z.clone()); - //~^ ERROR: this call to `as_ref.map(...)` does nothing + //~^ useless_asref + let z = x.as_ref().map(|z| String::clone(z)); - //~^ ERROR: this call to `as_ref.map(...)` does nothing + //~^ useless_asref } mod issue12135 { @@ -167,16 +181,18 @@ mod issue12135 { pub fn f(x: &Struct) -> Option { x.field.as_ref().map(|v| v.clone()); - //~^ ERROR: this call to `as_ref.map(...)` does nothing + //~^ useless_asref + x.field.as_ref().map(Clone::clone); - //~^ ERROR: this call to `as_ref.map(...)` does nothing + //~^ useless_asref + x.field.as_ref().map(|v| Clone::clone(v)); - //~^ ERROR: this call to `as_ref.map(...)` does nothing + //~^ useless_asref // https://github.com/rust-lang/rust-clippy/pull/12136#discussion_r1451565223 #[allow(clippy::clone_on_copy)] Some(1).as_ref().map(|&x| x.clone()); - //~^ ERROR: this call to `as_ref.map(...)` does nothing + //~^ useless_asref x.field.as_ref().map(|v| v.method().clone()) } @@ -198,6 +214,40 @@ fn issue_12528() { let _ = opt.as_ref().map(RcWeak::clone); } +fn issue_14088() { + let s = Some("foo"); + let _: Option<&str> = s.as_ref().map(|x| x.as_ref()); +} + +pub struct Wrap { + inner: T, +} + +impl Deref for Wrap { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +struct NonCloneableError; + +pub struct Issue12357 { + current: Option>>, +} + +impl Issue12357 { + fn f(&self) -> Option> { + self.current.as_ref().map(|p| Arc::clone(p)) + } + + fn g(&self) { + let result: Result = Ok("Hello".to_string()); + let cloned = result.as_ref().map(|s| s.clone()); + } +} + fn main() { not_ok(); ok(); diff --git a/tests/ui/useless_asref.stderr b/tests/ui/useless_asref.stderr index 5f495c396705..8255f5d9d2ab 100644 --- a/tests/ui/useless_asref.stderr +++ b/tests/ui/useless_asref.stderr @@ -1,5 +1,5 @@ error: this call to `as_ref` does nothing - --> tests/ui/useless_asref.rs:50:18 + --> tests/ui/useless_asref.rs:51:18 | LL | foo_rstr(rstr.as_ref()); | ^^^^^^^^^^^^^ help: try: `rstr` @@ -11,103 +11,103 @@ LL | #![deny(clippy::useless_asref)] | ^^^^^^^^^^^^^^^^^^^^^ error: this call to `as_ref` does nothing - --> tests/ui/useless_asref.rs:52:20 + --> tests/ui/useless_asref.rs:54:20 | LL | foo_rslice(rslice.as_ref()); | ^^^^^^^^^^^^^^^ help: try: `rslice` error: this call to `as_mut` does nothing - --> tests/ui/useless_asref.rs:56:21 + --> tests/ui/useless_asref.rs:59:21 | LL | foo_mrslice(mrslice.as_mut()); | ^^^^^^^^^^^^^^^^ help: try: `mrslice` error: this call to `as_ref` does nothing - --> tests/ui/useless_asref.rs:58:20 + --> tests/ui/useless_asref.rs:62:20 | LL | foo_rslice(mrslice.as_ref()); | ^^^^^^^^^^^^^^^^ help: try: `mrslice` error: this call to `as_ref` does nothing - --> tests/ui/useless_asref.rs:65:20 + --> tests/ui/useless_asref.rs:70:20 | LL | foo_rslice(rrrrrslice.as_ref()); | ^^^^^^^^^^^^^^^^^^^ help: try: `rrrrrslice` error: this call to `as_ref` does nothing - --> tests/ui/useless_asref.rs:67:18 + --> tests/ui/useless_asref.rs:73:18 | LL | foo_rstr(rrrrrstr.as_ref()); | ^^^^^^^^^^^^^^^^^ help: try: `rrrrrstr` error: this call to `as_mut` does nothing - --> tests/ui/useless_asref.rs:72:21 + --> tests/ui/useless_asref.rs:79:21 | LL | foo_mrslice(mrrrrrslice.as_mut()); | ^^^^^^^^^^^^^^^^^^^^ help: try: `mrrrrrslice` error: this call to `as_ref` does nothing - --> tests/ui/useless_asref.rs:74:20 + --> tests/ui/useless_asref.rs:82:20 | LL | foo_rslice(mrrrrrslice.as_ref()); | ^^^^^^^^^^^^^^^^^^^^ help: try: `mrrrrrslice` error: this call to `as_ref` does nothing - --> tests/ui/useless_asref.rs:78:16 + --> tests/ui/useless_asref.rs:87:16 | LL | foo_rrrrmr((&&&&MoreRef).as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `(&&&&MoreRef)` error: this call to `as_mut` does nothing - --> tests/ui/useless_asref.rs:128:13 + --> tests/ui/useless_asref.rs:138:13 | LL | foo_mrt(mrt.as_mut()); | ^^^^^^^^^^^^ help: try: `mrt` error: this call to `as_ref` does nothing - --> tests/ui/useless_asref.rs:130:12 + --> tests/ui/useless_asref.rs:141:12 | LL | foo_rt(mrt.as_ref()); | ^^^^^^^^^^^^ help: try: `mrt` error: this call to `as_ref.map(...)` does nothing - --> tests/ui/useless_asref.rs:141:13 + --> tests/ui/useless_asref.rs:153:13 | LL | let z = x.as_ref().map(String::clone); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.clone()` error: this call to `as_ref.map(...)` does nothing - --> tests/ui/useless_asref.rs:143:13 + --> tests/ui/useless_asref.rs:156:13 | LL | let z = x.as_ref().map(|z| z.clone()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.clone()` error: this call to `as_ref.map(...)` does nothing - --> tests/ui/useless_asref.rs:145:13 + --> tests/ui/useless_asref.rs:159:13 | LL | let z = x.as_ref().map(|z| String::clone(z)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.clone()` error: this call to `as_ref.map(...)` does nothing - --> tests/ui/useless_asref.rs:169:9 + --> tests/ui/useless_asref.rs:183:9 | LL | x.field.as_ref().map(|v| v.clone()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.field.clone()` error: this call to `as_ref.map(...)` does nothing - --> tests/ui/useless_asref.rs:171:9 + --> tests/ui/useless_asref.rs:186:9 | LL | x.field.as_ref().map(Clone::clone); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.field.clone()` error: this call to `as_ref.map(...)` does nothing - --> tests/ui/useless_asref.rs:173:9 + --> tests/ui/useless_asref.rs:189:9 | LL | x.field.as_ref().map(|v| Clone::clone(v)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.field.clone()` error: this call to `as_ref.map(...)` does nothing - --> tests/ui/useless_asref.rs:178:9 + --> tests/ui/useless_asref.rs:194:9 | LL | Some(1).as_ref().map(|&x| x.clone()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(1).clone()` diff --git a/tests/ui/useless_attribute.fixed b/tests/ui/useless_attribute.fixed index de1062f123b7..a96c8f46f551 100644 --- a/tests/ui/useless_attribute.fixed +++ b/tests/ui/useless_attribute.fixed @@ -6,7 +6,9 @@ #![feature(rustc_private)] #![allow(dead_code)] +//~^ useless_attribute #![cfg_attr(clippy, allow(dead_code))] +//~^ useless_attribute #[rustfmt::skip] #[allow(unused_imports)] #[allow(unused_extern_crates)] @@ -18,6 +20,7 @@ extern crate proc_macro_derive; fn test_indented_attr() { #![allow(clippy::almost_swapped)] + //~^ useless_attribute use std::collections::HashSet; let _ = HashSet::::default(); diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index 94657dd1ca37..b26410134bbb 100644 --- a/tests/ui/useless_attribute.rs +++ b/tests/ui/useless_attribute.rs @@ -6,7 +6,9 @@ #![feature(rustc_private)] #[allow(dead_code)] +//~^ useless_attribute #[cfg_attr(clippy, allow(dead_code))] +//~^ useless_attribute #[rustfmt::skip] #[allow(unused_imports)] #[allow(unused_extern_crates)] @@ -18,6 +20,7 @@ extern crate proc_macro_derive; fn test_indented_attr() { #[allow(clippy::almost_swapped)] + //~^ useless_attribute use std::collections::HashSet; let _ = HashSet::::default(); diff --git a/tests/ui/useless_attribute.stderr b/tests/ui/useless_attribute.stderr index 19f0e02de680..91383adf994b 100644 --- a/tests/ui/useless_attribute.stderr +++ b/tests/ui/useless_attribute.stderr @@ -8,13 +8,13 @@ LL | #[allow(dead_code)] = help: to override `-D warnings` add `#[allow(clippy::useless_attribute)]` error: useless lint attribute - --> tests/ui/useless_attribute.rs:9:1 + --> tests/ui/useless_attribute.rs:10:1 | LL | #[cfg_attr(clippy, allow(dead_code))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![cfg_attr(clippy, allow(dead_code)` error: useless lint attribute - --> tests/ui/useless_attribute.rs:20:5 + --> tests/ui/useless_attribute.rs:22:5 | LL | #[allow(clippy::almost_swapped)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![allow(clippy::almost_swapped)]` diff --git a/tests/ui/useless_conversion.fixed b/tests/ui/useless_conversion.fixed index 697d437b3885..489caacf2123 100644 --- a/tests/ui/useless_conversion.fixed +++ b/tests/ui/useless_conversion.fixed @@ -7,7 +7,9 @@ use std::ops::ControlFlow; fn test_generic(val: T) -> T { let _ = val; + //~^ useless_conversion val + //~^ useless_conversion } fn test_generic2 + Into, U: From>(val: T) { @@ -20,6 +22,7 @@ fn test_generic2 + Into, U: From>(val: T) { fn test_questionmark() -> Result<(), ()> { { let _: i32 = 0i32; + //~^ useless_conversion Ok(Ok(())) }??; Ok(()) @@ -50,28 +53,33 @@ fn lint_into_iter_on_mutable_local_implementing_iterator_in_expr() { let text = "foo\r\nbar\n\nbaz\n"; let mut lines = text.lines(); if Some("ok") == lines.next() {} + //~^ useless_conversion } fn lint_into_iter_on_expr_implementing_iterator() { let text = "foo\r\nbar\n\nbaz\n"; let mut lines = text.lines(); + //~^ useless_conversion if Some("ok") == lines.next() {} } fn lint_into_iter_on_expr_implementing_iterator_2() { let text = "foo\r\nbar\n\nbaz\n"; if Some("ok") == text.lines().next() {} + //~^ useless_conversion } #[allow(const_item_mutation)] fn lint_into_iter_on_const_implementing_iterator() { const NUMBERS: std::ops::Range = 0..10; let _ = NUMBERS.next(); + //~^ useless_conversion } fn lint_into_iter_on_const_implementing_iterator_2() { const NUMBERS: std::ops::Range = 0..10; let mut n = NUMBERS; + //~^ useless_conversion n.next(); } @@ -134,27 +142,38 @@ fn main() { } let _: String = "foo".to_string(); + //~^ useless_conversion let _: String = "foo".to_string(); + //~^ useless_conversion let _ = "foo".to_string(); + //~^ useless_conversion let _ = format!("A: {:04}", 123); + //~^ useless_conversion let _ = "".lines(); + //~^ useless_conversion let _ = vec![1, 2, 3].into_iter(); + //~^ useless_conversion let _: String = format!("Hello {}", "world"); + //~^ useless_conversion // keep parentheses around `a + b` for suggestion (see #4750) let a: i32 = 1; let b: i32 = 1; let _ = (a + b) * 3; + //~^ useless_conversion // see #7205 let s: Foo<'a'> = Foo; let _: Foo<'b'> = s.into(); let s2: Foo<'a'> = Foo; let _: Foo<'a'> = s2; + //~^ useless_conversion let s3: Foo<'a'> = Foo; let _ = s3; + //~^ useless_conversion let s4: Foo<'a'> = Foo; let _ = vec![s4, s4, s4].into_iter(); + //~^ useless_conversion issue11300::bar(); } @@ -187,12 +206,17 @@ fn explicit_into_iter_fn_arg() { a(vec![1, 2].into_iter()); b(vec![1, 2]); + //~^ useless_conversion c(vec![1, 2]); + //~^ useless_conversion d(vec![1, 2]); + //~^ useless_conversion b([&1, &2, &3].into_iter().cloned()); b(vec![1, 2]); + //~^ useless_conversion b(vec![1, 2]); + //~^ useless_conversion macro_rules! macro_generated { () => { @@ -239,6 +263,7 @@ mod issue11300 { // This should trigger the lint, receiver type [i32; 3] also implements `Helper` foo2::([1, 2, 3]); + //~^ useless_conversion // This again should *not* lint, since X = () and I = std::array::IntoIter, // and `[i32; 3]: Helper<()>` is not true (only `std::array::IntoIter: Helper<()>` is). @@ -247,6 +272,7 @@ mod issue11300 { // This should lint. Removing the `.into_iter()` means that `I` gets substituted with `[i32; 3]`, // and `i32: Helper2<[i32, 3]>` is true, so this call is indeed unnecessary. foo3([1, 2, 3]); + //~^ useless_conversion } fn ice() { @@ -256,6 +282,7 @@ mod issue11300 { } S1.foo([1, 2]); + //~^ useless_conversion // ICE that occurred in itertools trait Itertools { @@ -275,6 +302,7 @@ mod issue11300 { let v0: Vec = vec![0, 2, 4]; let v1: Vec = vec![1, 3, 5, 7]; v0.into_iter().interleave_shortest(v1); + //~^ useless_conversion trait TraitWithLifetime<'a> {} impl<'a> TraitWithLifetime<'a> for std::array::IntoIter<&'a i32, 2> {} @@ -303,16 +331,20 @@ impl From> for Foo<'b'> { fn direct_application() { let _: Result<(), std::io::Error> = test_issue_3913(); //~^ useless_conversion + let _: Result<(), std::io::Error> = test_issue_3913(); //~^ useless_conversion + let _: Result<(), std::io::Error> = test_issue_3913(); //~^ useless_conversion + let _: Result<(), std::io::Error> = test_issue_3913(); //~^ useless_conversion let c: ControlFlow<()> = ControlFlow::Continue(()); let _: ControlFlow<()> = c; //~^ useless_conversion + let c: ControlFlow<()> = ControlFlow::Continue(()); let _: ControlFlow<()> = c; //~^ useless_conversion diff --git a/tests/ui/useless_conversion.rs b/tests/ui/useless_conversion.rs index 4d8ad61a8c99..4f3a3b00ea20 100644 --- a/tests/ui/useless_conversion.rs +++ b/tests/ui/useless_conversion.rs @@ -7,7 +7,9 @@ use std::ops::ControlFlow; fn test_generic(val: T) -> T { let _ = T::from(val); + //~^ useless_conversion val.into() + //~^ useless_conversion } fn test_generic2 + Into, U: From>(val: T) { @@ -20,6 +22,7 @@ fn test_generic2 + Into, U: From>(val: T) { fn test_questionmark() -> Result<(), ()> { { let _: i32 = 0i32.into(); + //~^ useless_conversion Ok(Ok(())) }??; Ok(()) @@ -50,28 +53,33 @@ fn lint_into_iter_on_mutable_local_implementing_iterator_in_expr() { let text = "foo\r\nbar\n\nbaz\n"; let mut lines = text.lines(); if Some("ok") == lines.into_iter().next() {} + //~^ useless_conversion } fn lint_into_iter_on_expr_implementing_iterator() { let text = "foo\r\nbar\n\nbaz\n"; let mut lines = text.lines().into_iter(); + //~^ useless_conversion if Some("ok") == lines.next() {} } fn lint_into_iter_on_expr_implementing_iterator_2() { let text = "foo\r\nbar\n\nbaz\n"; if Some("ok") == text.lines().into_iter().next() {} + //~^ useless_conversion } #[allow(const_item_mutation)] fn lint_into_iter_on_const_implementing_iterator() { const NUMBERS: std::ops::Range = 0..10; let _ = NUMBERS.into_iter().next(); + //~^ useless_conversion } fn lint_into_iter_on_const_implementing_iterator_2() { const NUMBERS: std::ops::Range = 0..10; let mut n = NUMBERS.into_iter(); + //~^ useless_conversion n.next(); } @@ -134,27 +142,38 @@ fn main() { } let _: String = "foo".to_string().into(); + //~^ useless_conversion let _: String = From::from("foo".to_string()); + //~^ useless_conversion let _ = String::from("foo".to_string()); + //~^ useless_conversion let _ = String::from(format!("A: {:04}", 123)); + //~^ useless_conversion let _ = "".lines().into_iter(); + //~^ useless_conversion let _ = vec![1, 2, 3].into_iter().into_iter(); + //~^ useless_conversion let _: String = format!("Hello {}", "world").into(); + //~^ useless_conversion // keep parentheses around `a + b` for suggestion (see #4750) let a: i32 = 1; let b: i32 = 1; let _ = i32::from(a + b) * 3; + //~^ useless_conversion // see #7205 let s: Foo<'a'> = Foo; let _: Foo<'b'> = s.into(); let s2: Foo<'a'> = Foo; let _: Foo<'a'> = s2.into(); + //~^ useless_conversion let s3: Foo<'a'> = Foo; let _ = Foo::<'a'>::from(s3); + //~^ useless_conversion let s4: Foo<'a'> = Foo; let _ = vec![s4, s4, s4].into_iter().into_iter(); + //~^ useless_conversion issue11300::bar(); } @@ -187,12 +206,17 @@ fn explicit_into_iter_fn_arg() { a(vec![1, 2].into_iter()); b(vec![1, 2].into_iter()); + //~^ useless_conversion c(vec![1, 2].into_iter()); + //~^ useless_conversion d(vec![1, 2].into_iter()); + //~^ useless_conversion b([&1, &2, &3].into_iter().cloned()); b(vec![1, 2].into_iter().into_iter()); + //~^ useless_conversion b(vec![1, 2].into_iter().into_iter().into_iter()); + //~^ useless_conversion macro_rules! macro_generated { () => { @@ -239,6 +263,7 @@ mod issue11300 { // This should trigger the lint, receiver type [i32; 3] also implements `Helper` foo2::([1, 2, 3].into_iter()); + //~^ useless_conversion // This again should *not* lint, since X = () and I = std::array::IntoIter, // and `[i32; 3]: Helper<()>` is not true (only `std::array::IntoIter: Helper<()>` is). @@ -247,6 +272,7 @@ mod issue11300 { // This should lint. Removing the `.into_iter()` means that `I` gets substituted with `[i32; 3]`, // and `i32: Helper2<[i32, 3]>` is true, so this call is indeed unnecessary. foo3([1, 2, 3].into_iter()); + //~^ useless_conversion } fn ice() { @@ -256,6 +282,7 @@ mod issue11300 { } S1.foo([1, 2].into_iter()); + //~^ useless_conversion // ICE that occurred in itertools trait Itertools { @@ -275,6 +302,7 @@ mod issue11300 { let v0: Vec = vec![0, 2, 4]; let v1: Vec = vec![1, 3, 5, 7]; v0.into_iter().interleave_shortest(v1.into_iter()); + //~^ useless_conversion trait TraitWithLifetime<'a> {} impl<'a> TraitWithLifetime<'a> for std::array::IntoIter<&'a i32, 2> {} @@ -303,16 +331,20 @@ impl From> for Foo<'b'> { fn direct_application() { let _: Result<(), std::io::Error> = test_issue_3913().map(Into::into); //~^ useless_conversion + let _: Result<(), std::io::Error> = test_issue_3913().map_err(Into::into); //~^ useless_conversion + let _: Result<(), std::io::Error> = test_issue_3913().map(From::from); //~^ useless_conversion + let _: Result<(), std::io::Error> = test_issue_3913().map_err(From::from); //~^ useless_conversion let c: ControlFlow<()> = ControlFlow::Continue(()); let _: ControlFlow<()> = c.map_break(Into::into); //~^ useless_conversion + let c: ControlFlow<()> = ControlFlow::Continue(()); let _: ControlFlow<()> = c.map_continue(Into::into); //~^ useless_conversion diff --git a/tests/ui/useless_conversion.stderr b/tests/ui/useless_conversion.stderr index ed50f3071862..3cde2a786e46 100644 --- a/tests/ui/useless_conversion.stderr +++ b/tests/ui/useless_conversion.stderr @@ -11,115 +11,115 @@ LL | #![deny(clippy::useless_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: useless conversion to the same type: `T` - --> tests/ui/useless_conversion.rs:10:5 + --> tests/ui/useless_conversion.rs:11:5 | LL | val.into() | ^^^^^^^^^^ help: consider removing `.into()`: `val` error: useless conversion to the same type: `i32` - --> tests/ui/useless_conversion.rs:22:22 + --> tests/ui/useless_conversion.rs:24:22 | LL | let _: i32 = 0i32.into(); | ^^^^^^^^^^^ help: consider removing `.into()`: `0i32` error: useless conversion to the same type: `std::str::Lines<'_>` - --> tests/ui/useless_conversion.rs:52:22 + --> tests/ui/useless_conversion.rs:55:22 | LL | if Some("ok") == lines.into_iter().next() {} | ^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `lines` error: useless conversion to the same type: `std::str::Lines<'_>` - --> tests/ui/useless_conversion.rs:57:21 + --> tests/ui/useless_conversion.rs:61:21 | LL | let mut lines = text.lines().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()` error: useless conversion to the same type: `std::str::Lines<'_>` - --> tests/ui/useless_conversion.rs:63:22 + --> tests/ui/useless_conversion.rs:68:22 | LL | if Some("ok") == text.lines().into_iter().next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()` error: useless conversion to the same type: `std::ops::Range` - --> tests/ui/useless_conversion.rs:69:13 + --> tests/ui/useless_conversion.rs:75:13 | LL | let _ = NUMBERS.into_iter().next(); | ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS` error: useless conversion to the same type: `std::ops::Range` - --> tests/ui/useless_conversion.rs:74:17 + --> tests/ui/useless_conversion.rs:81:17 | LL | let mut n = NUMBERS.into_iter(); | ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion.rs:136:21 + --> tests/ui/useless_conversion.rs:144:21 | LL | let _: String = "foo".to_string().into(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion.rs:137:21 + --> tests/ui/useless_conversion.rs:146:21 | LL | let _: String = From::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion.rs:138:13 + --> tests/ui/useless_conversion.rs:148:13 | LL | let _ = String::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion.rs:139:13 + --> tests/ui/useless_conversion.rs:150:13 | LL | let _ = String::from(format!("A: {:04}", 123)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)` error: useless conversion to the same type: `std::str::Lines<'_>` - --> tests/ui/useless_conversion.rs:140:13 + --> tests/ui/useless_conversion.rs:152:13 | LL | let _ = "".lines().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()` error: useless conversion to the same type: `std::vec::IntoIter` - --> tests/ui/useless_conversion.rs:141:13 + --> tests/ui/useless_conversion.rs:154:13 | LL | let _ = vec![1, 2, 3].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion.rs:142:21 + --> tests/ui/useless_conversion.rs:156:21 | LL | let _: String = format!("Hello {}", "world").into(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")` error: useless conversion to the same type: `i32` - --> tests/ui/useless_conversion.rs:147:13 + --> tests/ui/useless_conversion.rs:162:13 | LL | let _ = i32::from(a + b) * 3; | ^^^^^^^^^^^^^^^^ help: consider removing `i32::from()`: `(a + b)` error: useless conversion to the same type: `Foo<'a'>` - --> tests/ui/useless_conversion.rs:153:23 + --> tests/ui/useless_conversion.rs:169:23 | LL | let _: Foo<'a'> = s2.into(); | ^^^^^^^^^ help: consider removing `.into()`: `s2` error: useless conversion to the same type: `Foo<'a'>` - --> tests/ui/useless_conversion.rs:155:13 + --> tests/ui/useless_conversion.rs:172:13 | LL | let _ = Foo::<'a'>::from(s3); | ^^^^^^^^^^^^^^^^^^^^ help: consider removing `Foo::<'a'>::from()`: `s3` error: useless conversion to the same type: `std::vec::IntoIter>` - --> tests/ui/useless_conversion.rs:157:13 + --> tests/ui/useless_conversion.rs:175:13 | LL | let _ = vec![s4, s4, s4].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![s4, s4, s4].into_iter()` error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:189:7 + --> tests/ui/useless_conversion.rs:208:7 | LL | b(vec![1, 2].into_iter()); | ^^^^^^^^^^------------ @@ -127,13 +127,13 @@ LL | b(vec![1, 2].into_iter()); | help: consider removing the `.into_iter()` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:179:13 + --> tests/ui/useless_conversion.rs:198:13 | LL | fn b>(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:190:7 + --> tests/ui/useless_conversion.rs:210:7 | LL | c(vec![1, 2].into_iter()); | ^^^^^^^^^^------------ @@ -141,13 +141,13 @@ LL | c(vec![1, 2].into_iter()); | help: consider removing the `.into_iter()` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:180:18 + --> tests/ui/useless_conversion.rs:199:18 | LL | fn c(_: impl IntoIterator) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:191:7 + --> tests/ui/useless_conversion.rs:212:7 | LL | d(vec![1, 2].into_iter()); | ^^^^^^^^^^------------ @@ -155,13 +155,13 @@ LL | d(vec![1, 2].into_iter()); | help: consider removing the `.into_iter()` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:183:12 + --> tests/ui/useless_conversion.rs:202:12 | LL | T: IntoIterator, | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:194:7 + --> tests/ui/useless_conversion.rs:216:7 | LL | b(vec![1, 2].into_iter().into_iter()); | ^^^^^^^^^^------------------------ @@ -169,13 +169,13 @@ LL | b(vec![1, 2].into_iter().into_iter()); | help: consider removing the `.into_iter()`s | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:179:13 + --> tests/ui/useless_conversion.rs:198:13 | LL | fn b>(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:195:7 + --> tests/ui/useless_conversion.rs:218:7 | LL | b(vec![1, 2].into_iter().into_iter().into_iter()); | ^^^^^^^^^^------------------------------------ @@ -183,13 +183,13 @@ LL | b(vec![1, 2].into_iter().into_iter().into_iter()); | help: consider removing the `.into_iter()`s | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:179:13 + --> tests/ui/useless_conversion.rs:198:13 | LL | fn b>(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:241:24 + --> tests/ui/useless_conversion.rs:265:24 | LL | foo2::([1, 2, 3].into_iter()); | ^^^^^^^^^------------ @@ -197,13 +197,13 @@ LL | foo2::([1, 2, 3].into_iter()); | help: consider removing the `.into_iter()` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:220:12 + --> tests/ui/useless_conversion.rs:244:12 | LL | I: IntoIterator + Helper, | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:249:14 + --> tests/ui/useless_conversion.rs:274:14 | LL | foo3([1, 2, 3].into_iter()); | ^^^^^^^^^------------ @@ -211,13 +211,13 @@ LL | foo3([1, 2, 3].into_iter()); | help: consider removing the `.into_iter()` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:229:12 + --> tests/ui/useless_conversion.rs:253:12 | LL | I: IntoIterator, | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:258:16 + --> tests/ui/useless_conversion.rs:284:16 | LL | S1.foo([1, 2].into_iter()); | ^^^^^^------------ @@ -225,13 +225,13 @@ LL | S1.foo([1, 2].into_iter()); | help: consider removing the `.into_iter()` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:255:27 + --> tests/ui/useless_conversion.rs:281:27 | LL | pub fn foo(&self, _: I) {} | ^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:277:44 + --> tests/ui/useless_conversion.rs:304:44 | LL | v0.into_iter().interleave_shortest(v1.into_iter()); | ^^------------ @@ -239,67 +239,67 @@ LL | v0.into_iter().interleave_shortest(v1.into_iter()); | help: consider removing the `.into_iter()` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:264:20 + --> tests/ui/useless_conversion.rs:291:20 | LL | J: IntoIterator, | ^^^^^^^^^^^^ error: useless conversion to the same type: `()` - --> tests/ui/useless_conversion.rs:304:58 + --> tests/ui/useless_conversion.rs:332:58 | LL | let _: Result<(), std::io::Error> = test_issue_3913().map(Into::into); | ^^^^^^^^^^^^^^^^ help: consider removing error: useless conversion to the same type: `std::io::Error` - --> tests/ui/useless_conversion.rs:306:58 + --> tests/ui/useless_conversion.rs:335:58 | LL | let _: Result<(), std::io::Error> = test_issue_3913().map_err(Into::into); | ^^^^^^^^^^^^^^^^^^^^ help: consider removing error: useless conversion to the same type: `()` - --> tests/ui/useless_conversion.rs:308:58 + --> tests/ui/useless_conversion.rs:338:58 | LL | let _: Result<(), std::io::Error> = test_issue_3913().map(From::from); | ^^^^^^^^^^^^^^^^ help: consider removing error: useless conversion to the same type: `std::io::Error` - --> tests/ui/useless_conversion.rs:310:58 + --> tests/ui/useless_conversion.rs:341:58 | LL | let _: Result<(), std::io::Error> = test_issue_3913().map_err(From::from); | ^^^^^^^^^^^^^^^^^^^^ help: consider removing error: useless conversion to the same type: `()` - --> tests/ui/useless_conversion.rs:314:31 + --> tests/ui/useless_conversion.rs:345:31 | LL | let _: ControlFlow<()> = c.map_break(Into::into); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing error: useless conversion to the same type: `()` - --> tests/ui/useless_conversion.rs:317:31 + --> tests/ui/useless_conversion.rs:349:31 | LL | let _: ControlFlow<()> = c.map_continue(Into::into); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing error: useless conversion to the same type: `u32` - --> tests/ui/useless_conversion.rs:331:41 + --> tests/ui/useless_conversion.rs:363:41 | LL | let _: Vec = [1u32].into_iter().map(Into::into).collect(); | ^^^^^^^^^^^^^^^^ help: consider removing error: useless conversion to the same type: `T` - --> tests/ui/useless_conversion.rs:342:18 + --> tests/ui/useless_conversion.rs:374:18 | LL | x.into_iter().map(Into::into).collect() | ^^^^^^^^^^^^^^^^ help: consider removing error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:358:29 + --> tests/ui/useless_conversion.rs:390:29 | LL | takes_into_iter(self.my_field.into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:347:32 + --> tests/ui/useless_conversion.rs:379:32 | LL | fn takes_into_iter(_: impl IntoIterator) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -310,13 +310,13 @@ LL + takes_into_iter(&self.my_field); | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:366:29 + --> tests/ui/useless_conversion.rs:398:29 | LL | takes_into_iter(self.my_field.into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:347:32 + --> tests/ui/useless_conversion.rs:379:32 | LL | fn takes_into_iter(_: impl IntoIterator) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -327,13 +327,13 @@ LL + takes_into_iter(&mut self.my_field); | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:375:29 + --> tests/ui/useless_conversion.rs:407:29 | LL | takes_into_iter(self.my_field.into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:347:32 + --> tests/ui/useless_conversion.rs:379:32 | LL | fn takes_into_iter(_: impl IntoIterator) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -344,13 +344,13 @@ LL + takes_into_iter(*self.my_field); | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:384:29 + --> tests/ui/useless_conversion.rs:416:29 | LL | takes_into_iter(self.my_field.into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:347:32 + --> tests/ui/useless_conversion.rs:379:32 | LL | fn takes_into_iter(_: impl IntoIterator) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -361,13 +361,13 @@ LL + takes_into_iter(&*self.my_field); | error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:393:29 + --> tests/ui/useless_conversion.rs:425:29 | LL | takes_into_iter(self.my_field.into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:347:32 + --> tests/ui/useless_conversion.rs:379:32 | LL | fn takes_into_iter(_: impl IntoIterator) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/useless_conversion_try.rs b/tests/ui/useless_conversion_try.rs index 23edeae12b83..d16506d94aa3 100644 --- a/tests/ui/useless_conversion_try.rs +++ b/tests/ui/useless_conversion_try.rs @@ -7,9 +7,10 @@ fn test_generic(val: T) -> T { let _ = T::try_from(val).unwrap(); - //~^ ERROR: useless conversion to the same type: `T` + //~^ useless_conversion + val.try_into().unwrap() - //~^ ERROR: useless conversion to the same type: `T` + //~^ useless_conversion } fn test_generic2 + Into, U: From>(val: T) { @@ -32,19 +33,25 @@ fn main() { let _: String = "foo".try_into().unwrap(); } let _: String = "foo".to_string().try_into().unwrap(); - //~^ ERROR: useless conversion to the same type: `std::string::String` + //~^ useless_conversion + let _: String = TryFrom::try_from("foo".to_string()).unwrap(); - //~^ ERROR: useless conversion to the same type: `std::string::String` + //~^ useless_conversion + let _ = String::try_from("foo".to_string()).unwrap(); - //~^ ERROR: useless conversion to the same type: `std::string::String` + //~^ useless_conversion + let _ = String::try_from(format!("A: {:04}", 123)).unwrap(); - //~^ ERROR: useless conversion to the same type: `std::string::String` + //~^ useless_conversion + let _: String = format!("Hello {}", "world").try_into().unwrap(); - //~^ ERROR: useless conversion to the same type: `std::string::String` + //~^ useless_conversion + let _: String = String::new().try_into().unwrap(); - //~^ ERROR: useless conversion to the same type: `std::string::String` + //~^ useless_conversion + let _: String = match String::from("_").try_into() { - //~^ ERROR: useless conversion to the same type: `std::string::String` + //~^ useless_conversion Ok(a) => a, Err(_) => String::new(), }; diff --git a/tests/ui/useless_conversion_try.stderr b/tests/ui/useless_conversion_try.stderr index 30a43629dbd6..1c62426c8952 100644 --- a/tests/ui/useless_conversion_try.stderr +++ b/tests/ui/useless_conversion_try.stderr @@ -12,7 +12,7 @@ LL | #![deny(clippy::useless_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: useless conversion to the same type: `T` - --> tests/ui/useless_conversion_try.rs:11:5 + --> tests/ui/useless_conversion_try.rs:12:5 | LL | val.try_into().unwrap() | ^^^^^^^^^^^^^^ @@ -20,7 +20,7 @@ LL | val.try_into().unwrap() = help: consider removing `.try_into()` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion_try.rs:34:21 + --> tests/ui/useless_conversion_try.rs:35:21 | LL | let _: String = "foo".to_string().try_into().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | let _: String = "foo".to_string().try_into().unwrap(); = help: consider removing `.try_into()` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion_try.rs:36:21 + --> tests/ui/useless_conversion_try.rs:38:21 | LL | let _: String = TryFrom::try_from("foo".to_string()).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +36,7 @@ LL | let _: String = TryFrom::try_from("foo".to_string()).unwrap(); = help: consider removing `TryFrom::try_from()` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion_try.rs:38:13 + --> tests/ui/useless_conversion_try.rs:41:13 | LL | let _ = String::try_from("foo".to_string()).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | let _ = String::try_from("foo".to_string()).unwrap(); = help: consider removing `String::try_from()` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion_try.rs:40:13 + --> tests/ui/useless_conversion_try.rs:44:13 | LL | let _ = String::try_from(format!("A: {:04}", 123)).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,7 +52,7 @@ LL | let _ = String::try_from(format!("A: {:04}", 123)).unwrap(); = help: consider removing `String::try_from()` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion_try.rs:42:21 + --> tests/ui/useless_conversion_try.rs:47:21 | LL | let _: String = format!("Hello {}", "world").try_into().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL | let _: String = format!("Hello {}", "world").try_into().unwrap(); = help: consider removing `.try_into()` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion_try.rs:44:21 + --> tests/ui/useless_conversion_try.rs:50:21 | LL | let _: String = String::new().try_into().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -68,7 +68,7 @@ LL | let _: String = String::new().try_into().unwrap(); = help: consider removing `.try_into()` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion_try.rs:46:27 + --> tests/ui/useless_conversion_try.rs:53:27 | LL | let _: String = match String::from("_").try_into() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/useless_nonzero_new_unchecked.fixed b/tests/ui/useless_nonzero_new_unchecked.fixed index 03b34afa54ec..f7f60bbe3f8d 100644 --- a/tests/ui/useless_nonzero_new_unchecked.fixed +++ b/tests/ui/useless_nonzero_new_unchecked.fixed @@ -5,7 +5,7 @@ use std::num::{NonZero, NonZeroUsize}; #[clippy::msrv = "1.83"] const fn func() -> NonZeroUsize { const { NonZeroUsize::new(3).unwrap() } - //~^ ERROR: `Option::unwrap()` can be safely used in a `const` context + //~^ useless_nonzero_new_unchecked } #[clippy::msrv = "1.82"] @@ -35,17 +35,17 @@ macro_rules! nzu { fn main() { const _A: NonZeroUsize = NonZeroUsize::new(3).unwrap(); - //~^ ERROR: `Option::unwrap()` can be safely used in a `const` context + //~^ useless_nonzero_new_unchecked static _B: NonZero = NonZero::::new(42).unwrap(); - //~^ ERROR: `Option::unwrap()` can be safely used in a `const` context + //~^ useless_nonzero_new_unchecked const _C: usize = unsafe { NonZeroUsize::new(3).unwrap().get() }; - //~^ ERROR: `Option::unwrap()` can be safely used in a `const` context + //~^ useless_nonzero_new_unchecked const AUX: usize = 3; const _D: NonZeroUsize = NonZeroUsize::new(AUX).unwrap(); - //~^ ERROR: `Option::unwrap()` can be safely used in a `const` context + //~^ useless_nonzero_new_unchecked const _X: NonZeroUsize = uns!(NonZeroUsize::new_unchecked(3)); const _Y: NonZeroUsize = unsafe { nzu!() }; diff --git a/tests/ui/useless_nonzero_new_unchecked.rs b/tests/ui/useless_nonzero_new_unchecked.rs index d450e3a03ec5..c90a63915efb 100644 --- a/tests/ui/useless_nonzero_new_unchecked.rs +++ b/tests/ui/useless_nonzero_new_unchecked.rs @@ -5,7 +5,7 @@ use std::num::{NonZero, NonZeroUsize}; #[clippy::msrv = "1.83"] const fn func() -> NonZeroUsize { const { unsafe { NonZeroUsize::new_unchecked(3) } } - //~^ ERROR: `Option::unwrap()` can be safely used in a `const` context + //~^ useless_nonzero_new_unchecked } #[clippy::msrv = "1.82"] @@ -35,17 +35,17 @@ macro_rules! nzu { fn main() { const _A: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(3) }; - //~^ ERROR: `Option::unwrap()` can be safely used in a `const` context + //~^ useless_nonzero_new_unchecked static _B: NonZero = unsafe { NonZero::::new_unchecked(42) }; - //~^ ERROR: `Option::unwrap()` can be safely used in a `const` context + //~^ useless_nonzero_new_unchecked const _C: usize = unsafe { NonZeroUsize::new_unchecked(3).get() }; - //~^ ERROR: `Option::unwrap()` can be safely used in a `const` context + //~^ useless_nonzero_new_unchecked const AUX: usize = 3; const _D: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(AUX) }; - //~^ ERROR: `Option::unwrap()` can be safely used in a `const` context + //~^ useless_nonzero_new_unchecked const _X: NonZeroUsize = uns!(NonZeroUsize::new_unchecked(3)); const _Y: NonZeroUsize = unsafe { nzu!() }; diff --git a/tests/ui/vec.fixed b/tests/ui/vec.fixed index 9e755a82af45..f360a8afadf6 100644 --- a/tests/ui/vec.fixed +++ b/tests/ui/vec.fixed @@ -28,24 +28,34 @@ impl Line { fn main() { on_slice(&[]); + //~^ useless_vec on_slice(&[]); on_mut_slice(&mut []); + //~^ useless_vec on_slice(&[1, 2]); + //~^ useless_vec on_slice(&[1, 2]); on_mut_slice(&mut [1, 2]); + //~^ useless_vec on_slice(&[1, 2]); + //~^ useless_vec on_slice(&[1, 2]); on_mut_slice(&mut [1, 2]); + //~^ useless_vec #[rustfmt::skip] on_slice(&[1, 2]); + //~^ useless_vec on_slice(&[1, 2]); on_mut_slice(&mut [1, 2]); + //~^ useless_vec on_slice(&[1; 2]); + //~^ useless_vec on_slice(&[1; 2]); on_mut_slice(&mut [1; 2]); + //~^ useless_vec on_vec(&vec![]); on_vec(&vec![1, 2]); @@ -72,17 +82,21 @@ fn main() { // https://github.com/rust-lang/rust-clippy/issues/2262#issuecomment-783979246 let _x: i32 = [1, 2, 3].iter().sum(); + //~^ useless_vec // Do lint let mut x = [1, 2, 3]; + //~^ useless_vec x.fill(123); dbg!(x[0]); dbg!(x.len()); dbg!(x.iter().sum::()); let _x: &[i32] = &[1, 2, 3]; + //~^ useless_vec for _ in [1, 2, 3] {} + //~^ useless_vec // Don't lint let x = vec![1, 2, 3]; @@ -122,6 +136,7 @@ fn issue11075() { } #[allow(clippy::never_loop)] for _string in [repro!(true), repro!(null)] { + //~^ useless_vec unimplemented!(); } @@ -139,6 +154,8 @@ fn issue11075() { } in_macro!(1, [1, 2], [1; 2]); + //~^ useless_vec + //~| useless_vec macro_rules! from_macro { () => { @@ -158,10 +175,12 @@ fn issue11075() { #[clippy::msrv = "1.53"] fn above() { for a in [1, 2, 3] { + //~^ useless_vec let _: usize = a; } for a in [String::new(), String::new()] { + //~^ useless_vec let _: String = a; } } @@ -193,7 +212,8 @@ fn issue11861() { // Do not lint the next line this_macro_needs_vec!(vec![1]); - this_macro_doesnt_need_vec!([1]); //~ ERROR: useless use of `vec!` + this_macro_doesnt_need_vec!([1]); + //~^ useless_vec macro_rules! m { ($x:expr) => { @@ -220,4 +240,5 @@ fn issue_11958() { fn issue_12101() { for a in &[1, 2] {} + //~^ useless_vec } diff --git a/tests/ui/vec.rs b/tests/ui/vec.rs index c483271438b1..a779d33557cb 100644 --- a/tests/ui/vec.rs +++ b/tests/ui/vec.rs @@ -28,24 +28,34 @@ impl Line { fn main() { on_slice(&vec![]); + //~^ useless_vec on_slice(&[]); on_mut_slice(&mut vec![]); + //~^ useless_vec on_slice(&vec![1, 2]); + //~^ useless_vec on_slice(&[1, 2]); on_mut_slice(&mut vec![1, 2]); + //~^ useless_vec on_slice(&vec![1, 2]); + //~^ useless_vec on_slice(&[1, 2]); on_mut_slice(&mut vec![1, 2]); + //~^ useless_vec #[rustfmt::skip] on_slice(&vec!(1, 2)); + //~^ useless_vec on_slice(&[1, 2]); on_mut_slice(&mut vec![1, 2]); + //~^ useless_vec on_slice(&vec![1; 2]); + //~^ useless_vec on_slice(&[1; 2]); on_mut_slice(&mut vec![1; 2]); + //~^ useless_vec on_vec(&vec![]); on_vec(&vec![1, 2]); @@ -72,17 +82,21 @@ fn main() { // https://github.com/rust-lang/rust-clippy/issues/2262#issuecomment-783979246 let _x: i32 = vec![1, 2, 3].iter().sum(); + //~^ useless_vec // Do lint let mut x = vec![1, 2, 3]; + //~^ useless_vec x.fill(123); dbg!(x[0]); dbg!(x.len()); dbg!(x.iter().sum::()); let _x: &[i32] = &vec![1, 2, 3]; + //~^ useless_vec for _ in vec![1, 2, 3] {} + //~^ useless_vec // Don't lint let x = vec![1, 2, 3]; @@ -122,6 +136,7 @@ fn issue11075() { } #[allow(clippy::never_loop)] for _string in vec![repro!(true), repro!(null)] { + //~^ useless_vec unimplemented!(); } @@ -139,6 +154,8 @@ fn issue11075() { } in_macro!(1, vec![1, 2], vec![1; 2]); + //~^ useless_vec + //~| useless_vec macro_rules! from_macro { () => { @@ -158,10 +175,12 @@ fn issue11075() { #[clippy::msrv = "1.53"] fn above() { for a in vec![1, 2, 3] { + //~^ useless_vec let _: usize = a; } for a in vec![String::new(), String::new()] { + //~^ useless_vec let _: String = a; } } @@ -193,7 +212,8 @@ fn issue11861() { // Do not lint the next line this_macro_needs_vec!(vec![1]); - this_macro_doesnt_need_vec!(vec![1]); //~ ERROR: useless use of `vec!` + this_macro_doesnt_need_vec!(vec![1]); + //~^ useless_vec macro_rules! m { ($x:expr) => { @@ -220,4 +240,5 @@ fn issue_11958() { fn issue_12101() { for a in &(vec![1, 2]) {} + //~^ useless_vec } diff --git a/tests/ui/vec.stderr b/tests/ui/vec.stderr index 3faea8033fe2..806d6617200f 100644 --- a/tests/ui/vec.stderr +++ b/tests/ui/vec.stderr @@ -8,31 +8,19 @@ LL | on_slice(&vec![]); = help: to override `-D warnings` add `#[allow(clippy::useless_vec)]` error: useless use of `vec!` - --> tests/ui/vec.rs:32:18 + --> tests/ui/vec.rs:33:18 | LL | on_mut_slice(&mut vec![]); | ^^^^^^^^^^^ help: you can use a slice directly: `&mut []` error: useless use of `vec!` - --> tests/ui/vec.rs:34:14 + --> tests/ui/vec.rs:36:14 | LL | on_slice(&vec![1, 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> tests/ui/vec.rs:36:18 - | -LL | on_mut_slice(&mut vec![1, 2]); - | ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]` - -error: useless use of `vec!` - --> tests/ui/vec.rs:38:14 - | -LL | on_slice(&vec![1, 2]); - | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` - -error: useless use of `vec!` - --> tests/ui/vec.rs:40:18 + --> tests/ui/vec.rs:39:18 | LL | on_mut_slice(&mut vec![1, 2]); | ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]` @@ -40,89 +28,101 @@ LL | on_mut_slice(&mut vec![1, 2]); error: useless use of `vec!` --> tests/ui/vec.rs:42:14 | -LL | on_slice(&vec!(1, 2)); +LL | on_slice(&vec![1, 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> tests/ui/vec.rs:44:18 + --> tests/ui/vec.rs:45:18 | LL | on_mut_slice(&mut vec![1, 2]); | ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]` error: useless use of `vec!` - --> tests/ui/vec.rs:46:14 + --> tests/ui/vec.rs:48:14 + | +LL | on_slice(&vec!(1, 2)); + | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` + +error: useless use of `vec!` + --> tests/ui/vec.rs:51:18 + | +LL | on_mut_slice(&mut vec![1, 2]); + | ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]` + +error: useless use of `vec!` + --> tests/ui/vec.rs:54:14 | LL | on_slice(&vec![1; 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1; 2]` error: useless use of `vec!` - --> tests/ui/vec.rs:48:18 + --> tests/ui/vec.rs:57:18 | LL | on_mut_slice(&mut vec![1; 2]); | ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1; 2]` error: useless use of `vec!` - --> tests/ui/vec.rs:74:19 + --> tests/ui/vec.rs:84:19 | LL | let _x: i32 = vec![1, 2, 3].iter().sum(); | ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]` error: useless use of `vec!` - --> tests/ui/vec.rs:77:17 + --> tests/ui/vec.rs:88:17 | LL | let mut x = vec![1, 2, 3]; | ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]` error: useless use of `vec!` - --> tests/ui/vec.rs:83:22 + --> tests/ui/vec.rs:95:22 | LL | let _x: &[i32] = &vec![1, 2, 3]; | ^^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]` error: useless use of `vec!` - --> tests/ui/vec.rs:85:14 + --> tests/ui/vec.rs:98:14 | LL | for _ in vec![1, 2, 3] {} | ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]` error: useless use of `vec!` - --> tests/ui/vec.rs:124:20 + --> tests/ui/vec.rs:138:20 | LL | for _string in vec![repro!(true), repro!(null)] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can use an array directly: `[repro!(true), repro!(null)]` error: useless use of `vec!` - --> tests/ui/vec.rs:141:18 + --> tests/ui/vec.rs:156:18 | LL | in_macro!(1, vec![1, 2], vec![1; 2]); | ^^^^^^^^^^ help: you can use an array directly: `[1, 2]` error: useless use of `vec!` - --> tests/ui/vec.rs:141:30 + --> tests/ui/vec.rs:156:30 | LL | in_macro!(1, vec![1, 2], vec![1; 2]); | ^^^^^^^^^^ help: you can use an array directly: `[1; 2]` error: useless use of `vec!` - --> tests/ui/vec.rs:160:14 + --> tests/ui/vec.rs:177:14 | LL | for a in vec![1, 2, 3] { | ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]` error: useless use of `vec!` - --> tests/ui/vec.rs:164:14 + --> tests/ui/vec.rs:182:14 | LL | for a in vec![String::new(), String::new()] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can use an array directly: `[String::new(), String::new()]` error: useless use of `vec!` - --> tests/ui/vec.rs:196:33 + --> tests/ui/vec.rs:215:33 | LL | this_macro_doesnt_need_vec!(vec![1]); | ^^^^^^^ help: you can use an array directly: `[1]` error: useless use of `vec!` - --> tests/ui/vec.rs:222:14 + --> tests/ui/vec.rs:242:14 | LL | for a in &(vec![1, 2]) {} | ^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` diff --git a/tests/ui/vec_box_sized.rs b/tests/ui/vec_box_sized.rs index 49eaf8e062af..897add423b6d 100644 --- a/tests/ui/vec_box_sized.rs +++ b/tests/ui/vec_box_sized.rs @@ -24,22 +24,30 @@ unsafe impl Allocator for DummyAllocator { mod should_trigger { use super::{DummyAllocator, SizedStruct}; const C: Vec> = Vec::new(); + //~^ vec_box static S: Vec> = Vec::new(); + //~^ vec_box struct StructWithVecBox { sized_type: Vec>, + //~^ vec_box } struct A(Vec>); + //~^ vec_box struct B(Vec>>); + //~^ vec_box fn allocator_global_defined_vec() -> Vec, std::alloc::Global> { + //~^ vec_box Vec::new() } fn allocator_global_defined_box() -> Vec> { + //~^ vec_box Vec::new() } fn allocator_match() -> Vec, DummyAllocator> { + //~^ vec_box Vec::new_in(DummyAllocator) } } @@ -77,6 +85,7 @@ mod inner_mod { use super::inner::S; pub fn f() -> Vec> { + //~^ vec_box vec![] } } diff --git a/tests/ui/vec_box_sized.stderr b/tests/ui/vec_box_sized.stderr index 0ffcc8314340..65db267977a6 100644 --- a/tests/ui/vec_box_sized.stderr +++ b/tests/ui/vec_box_sized.stderr @@ -8,49 +8,49 @@ LL | const C: Vec> = Vec::new(); = help: to override `-D warnings` add `#[allow(clippy::vec_box)]` error: `Vec` is already on the heap, the boxing is unnecessary - --> tests/ui/vec_box_sized.rs:27:15 + --> tests/ui/vec_box_sized.rs:28:15 | LL | static S: Vec> = Vec::new(); | ^^^^^^^^^^^^^ help: try: `Vec` error: `Vec` is already on the heap, the boxing is unnecessary - --> tests/ui/vec_box_sized.rs:30:21 + --> tests/ui/vec_box_sized.rs:32:21 | LL | sized_type: Vec>, | ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec` error: `Vec` is already on the heap, the boxing is unnecessary - --> tests/ui/vec_box_sized.rs:33:14 + --> tests/ui/vec_box_sized.rs:36:14 | LL | struct A(Vec>); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec` error: `Vec` is already on the heap, the boxing is unnecessary - --> tests/ui/vec_box_sized.rs:34:18 + --> tests/ui/vec_box_sized.rs:38:18 | LL | struct B(Vec>>); | ^^^^^^^^^^^^^^^ help: try: `Vec` error: `Vec` is already on the heap, the boxing is unnecessary - --> tests/ui/vec_box_sized.rs:36:42 + --> tests/ui/vec_box_sized.rs:41:42 | LL | fn allocator_global_defined_vec() -> Vec, std::alloc::Global> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec` error: `Vec` is already on the heap, the boxing is unnecessary - --> tests/ui/vec_box_sized.rs:39:42 + --> tests/ui/vec_box_sized.rs:45:42 | LL | fn allocator_global_defined_box() -> Vec> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec` error: `Vec` is already on the heap, the boxing is unnecessary - --> tests/ui/vec_box_sized.rs:42:29 + --> tests/ui/vec_box_sized.rs:49:29 | LL | fn allocator_match() -> Vec, DummyAllocator> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec` error: `Vec` is already on the heap, the boxing is unnecessary - --> tests/ui/vec_box_sized.rs:79:23 + --> tests/ui/vec_box_sized.rs:87:23 | LL | pub fn f() -> Vec> { | ^^^^^^^^^^^ help: try: `Vec` diff --git a/tests/ui/vec_init_then_push.rs b/tests/ui/vec_init_then_push.rs index 1c60a75c56ae..a32187edfea6 100644 --- a/tests/ui/vec_init_then_push.rs +++ b/tests/ui/vec_init_then_push.rs @@ -3,16 +3,18 @@ //@no-rustfix fn main() { let mut def_err: Vec = Default::default(); - //~^ ERROR: calls to `push` immediately after creation - //~| NOTE: `-D clippy::vec-init-then-push` implied by `-D warnings` + //~^ vec_init_then_push + def_err.push(0); let mut new_err = Vec::::new(); - //~^ ERROR: calls to `push` immediately after creation + //~^ vec_init_then_push + new_err.push(1); let mut cap_err = Vec::with_capacity(2); - //~^ ERROR: calls to `push` immediately after creation + //~^ vec_init_then_push + cap_err.push(0); cap_err.push(1); cap_err.push(2); @@ -25,7 +27,8 @@ fn main() { cap_ok.push(0); new_err = Vec::new(); - //~^ ERROR: calls to `push` immediately after creation + //~^ vec_init_then_push + new_err.push(0); let mut vec = Vec::new(); @@ -76,7 +79,8 @@ fn _cond_push(x: bool) -> Vec { fn _push_then_edit(x: u32) -> Vec { let mut v = Vec::new(); - //~^ ERROR: calls to `push` immediately after creation + //~^ vec_init_then_push + v.push(x); v.push(1); v[0] = v[1] + 5; @@ -85,7 +89,8 @@ fn _push_then_edit(x: u32) -> Vec { fn _cond_push_with_large_start(x: bool) -> Vec { let mut v = Vec::new(); - //~^ ERROR: calls to `push` immediately after creation + //~^ vec_init_then_push + v.push(0); v.push(1); v.push(0); @@ -99,7 +104,8 @@ fn _cond_push_with_large_start(x: bool) -> Vec { } let mut v2 = Vec::new(); - //~^ ERROR: calls to `push` immediately after creation + //~^ vec_init_then_push + v2.push(0); v2.push(1); v2.push(0); @@ -115,7 +121,8 @@ fn _cond_push_with_large_start(x: bool) -> Vec { fn f() { let mut v = Vec::new(); - //~^ ERROR: calls to `push` immediately after creation + //~^ vec_init_then_push + v.push((0i32, 0i32)); let y = v[0].0.abs(); } diff --git a/tests/ui/vec_init_then_push.stderr b/tests/ui/vec_init_then_push.stderr index f35625c9b085..1900ad7bd6a0 100644 --- a/tests/ui/vec_init_then_push.stderr +++ b/tests/ui/vec_init_then_push.stderr @@ -13,66 +13,68 @@ error: calls to `push` immediately after creation --> tests/ui/vec_init_then_push.rs:10:5 | LL | / let mut new_err = Vec::::new(); -LL | | +... | LL | | new_err.push(1); | |____________________^ help: consider using the `vec![]` macro: `let mut new_err = vec![..];` error: calls to `push` immediately after creation - --> tests/ui/vec_init_then_push.rs:14:5 + --> tests/ui/vec_init_then_push.rs:15:5 | LL | / let mut cap_err = Vec::with_capacity(2); LL | | +LL | | LL | | cap_err.push(0); LL | | cap_err.push(1); LL | | cap_err.push(2); | |____________________^ help: consider using the `vec![]` macro: `let mut cap_err = vec![..];` error: calls to `push` immediately after creation - --> tests/ui/vec_init_then_push.rs:27:5 + --> tests/ui/vec_init_then_push.rs:29:5 | LL | / new_err = Vec::new(); -LL | | +... | LL | | new_err.push(0); | |____________________^ help: consider using the `vec![]` macro: `new_err = vec![..];` error: calls to `push` immediately after creation - --> tests/ui/vec_init_then_push.rs:78:5 + --> tests/ui/vec_init_then_push.rs:81:5 | LL | / let mut v = Vec::new(); LL | | +LL | | LL | | v.push(x); LL | | v.push(1); | |______________^ help: consider using the `vec![]` macro: `let mut v = vec![..];` error: calls to `push` immediately after creation - --> tests/ui/vec_init_then_push.rs:87:5 + --> tests/ui/vec_init_then_push.rs:91:5 | LL | / let mut v = Vec::new(); LL | | +LL | | LL | | v.push(0); -LL | | v.push(1); ... | LL | | v.push(1); LL | | v.push(0); | |______________^ help: consider using the `vec![]` macro: `let mut v = vec![..];` error: calls to `push` immediately after creation - --> tests/ui/vec_init_then_push.rs:101:5 + --> tests/ui/vec_init_then_push.rs:106:5 | LL | / let mut v2 = Vec::new(); LL | | +LL | | LL | | v2.push(0); -LL | | v2.push(1); ... | LL | | v2.push(1); LL | | v2.push(0); | |_______________^ help: consider using the `vec![]` macro: `let mut v2 = vec![..];` error: calls to `push` immediately after creation - --> tests/ui/vec_init_then_push.rs:117:5 + --> tests/ui/vec_init_then_push.rs:123:5 | LL | / let mut v = Vec::new(); -LL | | +... | LL | | v.push((0i32, 0i32)); | |_________________________^ help: consider using the `vec![]` macro: `let v = vec![..];` diff --git a/tests/ui/vec_resize_to_zero.fixed b/tests/ui/vec_resize_to_zero.fixed index b4c2d8209e76..260943f655e3 100644 --- a/tests/ui/vec_resize_to_zero.fixed +++ b/tests/ui/vec_resize_to_zero.fixed @@ -5,7 +5,7 @@ fn main() { // applicable here v.clear(); - //~^ ERROR: emptying a vector with `resize` + //~^ vec_resize_to_zero // not applicable v.resize(2, 5); diff --git a/tests/ui/vec_resize_to_zero.rs b/tests/ui/vec_resize_to_zero.rs index 5b11c940f21a..d6054715143c 100644 --- a/tests/ui/vec_resize_to_zero.rs +++ b/tests/ui/vec_resize_to_zero.rs @@ -5,7 +5,7 @@ fn main() { // applicable here v.resize(0, 5); - //~^ ERROR: emptying a vector with `resize` + //~^ vec_resize_to_zero // not applicable v.resize(2, 5); diff --git a/tests/ui/verbose_file_reads.rs b/tests/ui/verbose_file_reads.rs index 9dd4f4e1d9be..374cd39df947 100644 --- a/tests/ui/verbose_file_reads.rs +++ b/tests/ui/verbose_file_reads.rs @@ -21,10 +21,12 @@ fn main() -> std::io::Result<()> { let mut f = File::open(path)?; let mut buffer = Vec::new(); f.read_to_end(&mut buffer)?; - //~^ ERROR: use of `File::read_to_end` + //~^ verbose_file_reads + // ...and this let mut string_buffer = String::new(); f.read_to_string(&mut string_buffer)?; - //~^ ERROR: use of `File::read_to_string` + //~^ verbose_file_reads + Ok(()) } diff --git a/tests/ui/verbose_file_reads.stderr b/tests/ui/verbose_file_reads.stderr index e85068fc7a9c..9e6f6788562f 100644 --- a/tests/ui/verbose_file_reads.stderr +++ b/tests/ui/verbose_file_reads.stderr @@ -9,7 +9,7 @@ LL | f.read_to_end(&mut buffer)?; = help: to override `-D warnings` add `#[allow(clippy::verbose_file_reads)]` error: use of `File::read_to_string` - --> tests/ui/verbose_file_reads.rs:27:5 + --> tests/ui/verbose_file_reads.rs:28:5 | LL | f.read_to_string(&mut string_buffer)?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/waker_clone_wake.fixed b/tests/ui/waker_clone_wake.fixed index 9c02b9a90fdd..d7b5000a5d50 100644 --- a/tests/ui/waker_clone_wake.fixed +++ b/tests/ui/waker_clone_wake.fixed @@ -13,8 +13,10 @@ macro_rules! mac { pub fn wake(cx: &mut std::task::Context) { cx.waker().wake_by_ref(); + //~^ waker_clone_wake mac!(cx).wake_by_ref(); + //~^ waker_clone_wake } pub fn no_lint(cx: &mut std::task::Context, c: &Custom) { diff --git a/tests/ui/waker_clone_wake.rs b/tests/ui/waker_clone_wake.rs index edc3bbd8fc08..27fa922d1112 100644 --- a/tests/ui/waker_clone_wake.rs +++ b/tests/ui/waker_clone_wake.rs @@ -13,8 +13,10 @@ macro_rules! mac { pub fn wake(cx: &mut std::task::Context) { cx.waker().clone().wake(); + //~^ waker_clone_wake mac!(cx).clone().wake(); + //~^ waker_clone_wake } pub fn no_lint(cx: &mut std::task::Context, c: &Custom) { diff --git a/tests/ui/waker_clone_wake.stderr b/tests/ui/waker_clone_wake.stderr index bf2c02a76c9b..9eb167d13107 100644 --- a/tests/ui/waker_clone_wake.stderr +++ b/tests/ui/waker_clone_wake.stderr @@ -8,7 +8,7 @@ LL | cx.waker().clone().wake(); = help: to override `-D warnings` add `#[allow(clippy::waker_clone_wake)]` error: cloning a `Waker` only to wake it - --> tests/ui/waker_clone_wake.rs:17:5 + --> tests/ui/waker_clone_wake.rs:18:5 | LL | mac!(cx).clone().wake(); | ^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `mac!(cx).wake_by_ref()` diff --git a/tests/ui/while_float.rs b/tests/ui/while_float.rs index a3b0618948e6..727b954ffcca 100644 --- a/tests/ui/while_float.rs +++ b/tests/ui/while_float.rs @@ -2,9 +2,11 @@ fn main() { let mut x = 0.0_f32; while x < 42.0_f32 { + //~^ while_float x += 0.5; } while x < 42.0 { + //~^ while_float x += 1.0; } let mut x = 0; diff --git a/tests/ui/while_float.stderr b/tests/ui/while_float.stderr index b8e934b97c6c..e83e1b925c16 100644 --- a/tests/ui/while_float.stderr +++ b/tests/ui/while_float.stderr @@ -11,7 +11,7 @@ LL | #[deny(clippy::while_float)] | ^^^^^^^^^^^^^^^^^^^ error: while condition comparing floats - --> tests/ui/while_float.rs:7:11 + --> tests/ui/while_float.rs:8:11 | LL | while x < 42.0 { | ^^^^^^^^ diff --git a/tests/ui/while_let_loop.rs b/tests/ui/while_let_loop.rs index fa5325bebffa..d591ab984cfa 100644 --- a/tests/ui/while_let_loop.rs +++ b/tests/ui/while_let_loop.rs @@ -4,8 +4,8 @@ fn main() { let y = Some(true); loop { - //~^ ERROR: this loop could be written as a `while let` loop - //~| NOTE: `-D clippy::while-let-loop` implied by `-D warnings` + //~^ while_let_loop + if let Some(_x) = y { let _v = 1; } else { @@ -23,7 +23,8 @@ fn main() { } loop { - //~^ ERROR: this loop could be written as a `while let` loop + //~^ while_let_loop + match y { Some(_x) => true, None => break, @@ -31,7 +32,8 @@ fn main() { } loop { - //~^ ERROR: this loop could be written as a `while let` loop + //~^ while_let_loop + let x = match y { Some(x) => x, None => break, @@ -41,7 +43,8 @@ fn main() { } loop { - //~^ ERROR: this loop could be written as a `while let` loop + //~^ while_let_loop + let x = match y { Some(x) => x, None => break, @@ -72,7 +75,8 @@ fn main() { // #675, this used to have a wrong suggestion loop { - //~^ ERROR: this loop could be written as a `while let` loop + //~^ while_let_loop + let (e, l) = match "".split_whitespace().next() { Some(word) => (word.is_empty(), word.len()), None => break, diff --git a/tests/ui/while_let_loop.stderr b/tests/ui/while_let_loop.stderr index 10c2311d82f7..bd482857e675 100644 --- a/tests/ui/while_let_loop.stderr +++ b/tests/ui/while_let_loop.stderr @@ -17,43 +17,43 @@ error: this loop could be written as a `while let` loop | LL | / loop { LL | | +LL | | LL | | match y { -LL | | Some(_x) => true, -LL | | None => break, +... | LL | | }; LL | | } | |_____^ help: try: `while let Some(_x) = y { .. }` error: this loop could be written as a `while let` loop - --> tests/ui/while_let_loop.rs:33:5 + --> tests/ui/while_let_loop.rs:34:5 | LL | / loop { LL | | +LL | | LL | | let x = match y { -LL | | Some(x) => x, ... | LL | | let _str = "foo"; LL | | } | |_____^ help: try: `while let Some(x) = y { .. }` error: this loop could be written as a `while let` loop - --> tests/ui/while_let_loop.rs:43:5 + --> tests/ui/while_let_loop.rs:45:5 | LL | / loop { LL | | +LL | | LL | | let x = match y { -LL | | Some(x) => x, ... | LL | | } | |_____^ help: try: `while let Some(x) = y { .. }` error: this loop could be written as a `while let` loop - --> tests/ui/while_let_loop.rs:74:5 + --> tests/ui/while_let_loop.rs:77:5 | LL | / loop { LL | | +LL | | LL | | let (e, l) = match "".split_whitespace().next() { -LL | | Some(word) => (word.is_empty(), word.len()), ... | LL | | let _ = (e, l); LL | | } diff --git a/tests/ui/while_let_on_iterator.fixed b/tests/ui/while_let_on_iterator.fixed index b8087c6e000f..f9ccefab5898 100644 --- a/tests/ui/while_let_on_iterator.fixed +++ b/tests/ui/while_let_on_iterator.fixed @@ -13,16 +13,19 @@ fn base() { let mut iter = 1..20; for x in iter { + //~^ while_let_on_iterator println!("{}", x); } let mut iter = 1..20; for x in iter { + //~^ while_let_on_iterator println!("{}", x); } let mut iter = 1..20; for _ in iter {} + //~^ while_let_on_iterator let mut iter = 1..20; while let None = iter.next() {} // this is fine (if nonsensical) @@ -99,6 +102,7 @@ fn refutable2() { let mut it = v.windows(2); for [..] in it {} + //~^ while_let_on_iterator let v = vec![[1], [2], [3]]; let mut it = v.iter(); @@ -106,6 +110,7 @@ fn refutable2() { let mut it = v.iter(); for [_x] in it {} + //~^ while_let_on_iterator } // binding @@ -119,6 +124,7 @@ fn refutable2() { let v = vec![[1], [2], [3]]; let mut it = v.iter(); for x @ [_] in it { + //~^ while_let_on_iterator println!("{:?}", x); } } @@ -139,6 +145,7 @@ fn nested_loops() { loop { let mut y = a.iter(); for _ in y { + //~^ while_let_on_iterator // use a for loop here } } @@ -196,6 +203,7 @@ fn issue6491() { let mut it = 1..40; while let Some(n) = it.next() { for m in it.by_ref() { + //~^ while_let_on_iterator if m % 10 == 0 { break; } @@ -207,8 +215,10 @@ fn issue6491() { // This is fine, inner loop uses a new iterator. let mut it = 1..40; for n in it { + //~^ while_let_on_iterator let mut it = 1..40; for m in it { + //~^ while_let_on_iterator if m % 10 == 0 { break; } @@ -218,6 +228,7 @@ fn issue6491() { // Weird binding shouldn't change anything. let (mut it, _) = (1..40, 0); for m in it { + //~^ while_let_on_iterator if m % 10 == 0 { break; } @@ -227,6 +238,7 @@ fn issue6491() { // Used after the loop, needs &mut. let mut it = 1..40; for m in it.by_ref() { + //~^ while_let_on_iterator if m % 10 == 0 { break; } @@ -244,6 +256,7 @@ fn issue6231() { let mut opt = Some(0); while let Some(n) = opt.take().or_else(|| it.next()) { for m in it.by_ref() { + //~^ while_let_on_iterator if n % 10 == 0 { break; } @@ -259,6 +272,7 @@ fn issue1924() { fn f(&mut self) -> Option { // Used as a field. for i in self.0.by_ref() { + //~^ while_let_on_iterator if !(3..8).contains(&i) { return Some(i); } @@ -291,6 +305,7 @@ fn issue1924() { } // This one is fine, a different field is borrowed for i in self.0.0.0.by_ref() { + //~^ while_let_on_iterator if i == 1 { return self.0.1.take(); } else { @@ -320,6 +335,7 @@ fn issue1924() { // Needs &mut, field of the iterator is accessed after the loop let mut it = S2(1..40, 0); for n in it.by_ref() { + //~^ while_let_on_iterator if n == 0 { break; } @@ -332,6 +348,7 @@ fn issue7249() { let mut x = || { // Needs &mut, the closure can be called multiple times for x in it.by_ref() { + //~^ while_let_on_iterator if x % 2 == 0 { break; } @@ -346,6 +363,7 @@ fn issue7510() { let it = &mut it; // Needs to reborrow `it` as the binding isn't mutable for x in it.by_ref() { + //~^ while_let_on_iterator if x % 2 == 0 { break; } @@ -357,6 +375,7 @@ fn issue7510() { let it = S(&mut it); // Needs to reborrow `it.0` as the binding isn't mutable for x in it.0.by_ref() { + //~^ while_let_on_iterator if x % 2 == 0 { break; } @@ -392,6 +411,7 @@ fn custom_deref() { let mut s = S2(S1 { x: 0..10 }); for x in s.x.by_ref() { + //~^ while_let_on_iterator println!("{}", x); } } @@ -399,6 +419,7 @@ fn custom_deref() { fn issue_8113() { let mut x = [0..10]; for x in x[0].by_ref() { + //~^ while_let_on_iterator println!("{}", x); } } @@ -407,6 +428,7 @@ fn fn_once_closure() { let mut it = 0..10; (|| { for x in it.by_ref() { + //~^ while_let_on_iterator if x % 2 == 0 { break; } @@ -417,6 +439,7 @@ fn fn_once_closure() { let mut it = 0..10; f(|| { for x in it { + //~^ while_let_on_iterator if x % 2 == 0 { break; } @@ -427,6 +450,7 @@ fn fn_once_closure() { let mut it = 0..10; f2(|| { for x in it.by_ref() { + //~^ while_let_on_iterator if x % 2 == 0 { break; } @@ -437,6 +461,7 @@ fn fn_once_closure() { f3(|| { let mut it = 0..10; for x in it { + //~^ while_let_on_iterator if x % 2 == 0 { break; } @@ -449,6 +474,7 @@ fn fn_once_closure() { let mut it = 0..10; f4(|| { for x in it { + //~^ while_let_on_iterator if x % 2 == 0 { break; } @@ -459,6 +485,7 @@ fn fn_once_closure() { fn issue13123() { let mut it = 0..20; 'label: for n in it { + //~^ while_let_on_iterator if n % 25 == 0 { break 'label; } @@ -468,6 +495,7 @@ fn issue13123() { fn main() { let mut it = 0..20; for _ in it { + //~^ while_let_on_iterator println!("test"); } } diff --git a/tests/ui/while_let_on_iterator.rs b/tests/ui/while_let_on_iterator.rs index 8e02f59b5126..f957f2e5a523 100644 --- a/tests/ui/while_let_on_iterator.rs +++ b/tests/ui/while_let_on_iterator.rs @@ -13,16 +13,19 @@ fn base() { let mut iter = 1..20; while let Option::Some(x) = iter.next() { + //~^ while_let_on_iterator println!("{}", x); } let mut iter = 1..20; while let Some(x) = iter.next() { + //~^ while_let_on_iterator println!("{}", x); } let mut iter = 1..20; while let Some(_) = iter.next() {} + //~^ while_let_on_iterator let mut iter = 1..20; while let None = iter.next() {} // this is fine (if nonsensical) @@ -99,6 +102,7 @@ fn refutable2() { let mut it = v.windows(2); while let Some([..]) = it.next() {} + //~^ while_let_on_iterator let v = vec![[1], [2], [3]]; let mut it = v.iter(); @@ -106,6 +110,7 @@ fn refutable2() { let mut it = v.iter(); while let Some([_x]) = it.next() {} + //~^ while_let_on_iterator } // binding @@ -119,6 +124,7 @@ fn refutable2() { let v = vec![[1], [2], [3]]; let mut it = v.iter(); while let Some(x @ [_]) = it.next() { + //~^ while_let_on_iterator println!("{:?}", x); } } @@ -139,6 +145,7 @@ fn nested_loops() { loop { let mut y = a.iter(); while let Some(_) = y.next() { + //~^ while_let_on_iterator // use a for loop here } } @@ -196,6 +203,7 @@ fn issue6491() { let mut it = 1..40; while let Some(n) = it.next() { while let Some(m) = it.next() { + //~^ while_let_on_iterator if m % 10 == 0 { break; } @@ -207,8 +215,10 @@ fn issue6491() { // This is fine, inner loop uses a new iterator. let mut it = 1..40; while let Some(n) = it.next() { + //~^ while_let_on_iterator let mut it = 1..40; while let Some(m) = it.next() { + //~^ while_let_on_iterator if m % 10 == 0 { break; } @@ -218,6 +228,7 @@ fn issue6491() { // Weird binding shouldn't change anything. let (mut it, _) = (1..40, 0); while let Some(m) = it.next() { + //~^ while_let_on_iterator if m % 10 == 0 { break; } @@ -227,6 +238,7 @@ fn issue6491() { // Used after the loop, needs &mut. let mut it = 1..40; while let Some(m) = it.next() { + //~^ while_let_on_iterator if m % 10 == 0 { break; } @@ -244,6 +256,7 @@ fn issue6231() { let mut opt = Some(0); while let Some(n) = opt.take().or_else(|| it.next()) { while let Some(m) = it.next() { + //~^ while_let_on_iterator if n % 10 == 0 { break; } @@ -259,6 +272,7 @@ fn issue1924() { fn f(&mut self) -> Option { // Used as a field. while let Some(i) = self.0.next() { + //~^ while_let_on_iterator if !(3..8).contains(&i) { return Some(i); } @@ -291,6 +305,7 @@ fn issue1924() { } // This one is fine, a different field is borrowed while let Some(i) = self.0.0.0.next() { + //~^ while_let_on_iterator if i == 1 { return self.0.1.take(); } else { @@ -320,6 +335,7 @@ fn issue1924() { // Needs &mut, field of the iterator is accessed after the loop let mut it = S2(1..40, 0); while let Some(n) = it.next() { + //~^ while_let_on_iterator if n == 0 { break; } @@ -332,6 +348,7 @@ fn issue7249() { let mut x = || { // Needs &mut, the closure can be called multiple times while let Some(x) = it.next() { + //~^ while_let_on_iterator if x % 2 == 0 { break; } @@ -346,6 +363,7 @@ fn issue7510() { let it = &mut it; // Needs to reborrow `it` as the binding isn't mutable while let Some(x) = it.next() { + //~^ while_let_on_iterator if x % 2 == 0 { break; } @@ -357,6 +375,7 @@ fn issue7510() { let it = S(&mut it); // Needs to reborrow `it.0` as the binding isn't mutable while let Some(x) = it.0.next() { + //~^ while_let_on_iterator if x % 2 == 0 { break; } @@ -392,6 +411,7 @@ fn custom_deref() { let mut s = S2(S1 { x: 0..10 }); while let Some(x) = s.x.next() { + //~^ while_let_on_iterator println!("{}", x); } } @@ -399,6 +419,7 @@ fn custom_deref() { fn issue_8113() { let mut x = [0..10]; while let Some(x) = x[0].next() { + //~^ while_let_on_iterator println!("{}", x); } } @@ -407,6 +428,7 @@ fn fn_once_closure() { let mut it = 0..10; (|| { while let Some(x) = it.next() { + //~^ while_let_on_iterator if x % 2 == 0 { break; } @@ -417,6 +439,7 @@ fn fn_once_closure() { let mut it = 0..10; f(|| { while let Some(x) = it.next() { + //~^ while_let_on_iterator if x % 2 == 0 { break; } @@ -427,6 +450,7 @@ fn fn_once_closure() { let mut it = 0..10; f2(|| { while let Some(x) = it.next() { + //~^ while_let_on_iterator if x % 2 == 0 { break; } @@ -437,6 +461,7 @@ fn fn_once_closure() { f3(|| { let mut it = 0..10; while let Some(x) = it.next() { + //~^ while_let_on_iterator if x % 2 == 0 { break; } @@ -449,6 +474,7 @@ fn fn_once_closure() { let mut it = 0..10; f4(|| { while let Some(x) = it.next() { + //~^ while_let_on_iterator if x % 2 == 0 { break; } @@ -459,6 +485,7 @@ fn fn_once_closure() { fn issue13123() { let mut it = 0..20; 'label: while let Some(n) = it.next() { + //~^ while_let_on_iterator if n % 25 == 0 { break 'label; } @@ -468,6 +495,7 @@ fn issue13123() { fn main() { let mut it = 0..20; while let Some(..) = it.next() { + //~^ while_let_on_iterator println!("test"); } } diff --git a/tests/ui/while_let_on_iterator.stderr b/tests/ui/while_let_on_iterator.stderr index d96b26acf345..50f20227b90f 100644 --- a/tests/ui/while_let_on_iterator.stderr +++ b/tests/ui/while_let_on_iterator.stderr @@ -8,59 +8,53 @@ LL | while let Option::Some(x) = iter.next() { = help: to override `-D warnings` add `#[allow(clippy::while_let_on_iterator)]` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:20:5 + --> tests/ui/while_let_on_iterator.rs:21:5 | LL | while let Some(x) = iter.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:25:5 + --> tests/ui/while_let_on_iterator.rs:27:5 | LL | while let Some(_) = iter.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in iter` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:101:9 + --> tests/ui/while_let_on_iterator.rs:104:9 | LL | while let Some([..]) = it.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [..] in it` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:108:9 + --> tests/ui/while_let_on_iterator.rs:112:9 | LL | while let Some([_x]) = it.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [_x] in it` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:121:9 + --> tests/ui/while_let_on_iterator.rs:126:9 | LL | while let Some(x @ [_]) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x @ [_] in it` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:141:9 + --> tests/ui/while_let_on_iterator.rs:147:9 | LL | while let Some(_) = y.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in y` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:198:9 + --> tests/ui/while_let_on_iterator.rs:205:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:209:5 + --> tests/ui/while_let_on_iterator.rs:217:5 | LL | while let Some(n) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in it` -error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:211:9 - | -LL | while let Some(m) = it.next() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it` - error: this loop could be written as a `for` loop --> tests/ui/while_let_on_iterator.rs:220:9 | @@ -68,103 +62,109 @@ LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:229:9 + --> tests/ui/while_let_on_iterator.rs:230:9 + | +LL | while let Some(m) = it.next() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it` + +error: this loop could be written as a `for` loop + --> tests/ui/while_let_on_iterator.rs:240:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:246:9 + --> tests/ui/while_let_on_iterator.rs:258:9 | LL | while let Some(m) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:261:13 + --> tests/ui/while_let_on_iterator.rs:274:13 | LL | while let Some(i) = self.0.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.by_ref()` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:293:13 + --> tests/ui/while_let_on_iterator.rs:307:13 | LL | while let Some(i) = self.0.0.0.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.0.0.by_ref()` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:322:5 + --> tests/ui/while_let_on_iterator.rs:337:5 | LL | while let Some(n) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in it.by_ref()` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:334:9 + --> tests/ui/while_let_on_iterator.rs:350:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:348:5 + --> tests/ui/while_let_on_iterator.rs:365:5 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:359:5 + --> tests/ui/while_let_on_iterator.rs:377:5 | LL | while let Some(x) = it.0.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.0.by_ref()` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:394:5 + --> tests/ui/while_let_on_iterator.rs:413:5 | LL | while let Some(x) = s.x.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in s.x.by_ref()` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:401:5 + --> tests/ui/while_let_on_iterator.rs:421:5 | LL | while let Some(x) = x[0].next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in x[0].by_ref()` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:409:9 + --> tests/ui/while_let_on_iterator.rs:430:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:419:9 + --> tests/ui/while_let_on_iterator.rs:441:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:429:9 + --> tests/ui/while_let_on_iterator.rs:452:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:439:9 + --> tests/ui/while_let_on_iterator.rs:463:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:451:9 + --> tests/ui/while_let_on_iterator.rs:476:9 | LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:461:5 + --> tests/ui/while_let_on_iterator.rs:487:5 | LL | 'label: while let Some(n) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'label: for n in it` error: this loop could be written as a `for` loop - --> tests/ui/while_let_on_iterator.rs:470:5 + --> tests/ui/while_let_on_iterator.rs:497:5 | LL | while let Some(..) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in it` diff --git a/tests/ui/wild_in_or_pats.rs b/tests/ui/wild_in_or_pats.rs index bc8a1dbee71d..ced13cc50c5d 100644 --- a/tests/ui/wild_in_or_pats.rs +++ b/tests/ui/wild_in_or_pats.rs @@ -6,7 +6,8 @@ fn main() { dbg!("matched a"); }, "bar" | _ => { - //~^ ERROR: wildcard pattern covers any other pattern as it will match anyway + //~^ wildcard_in_or_patterns + dbg!("matched (bar or) wild"); }, }; @@ -15,7 +16,8 @@ fn main() { dbg!("matched a"); }, "bar" | "bar2" | _ => { - //~^ ERROR: wildcard pattern covers any other pattern as it will match anyway + //~^ wildcard_in_or_patterns + dbg!("matched (bar or bar2 or) wild"); }, }; @@ -24,7 +26,8 @@ fn main() { dbg!("matched a"); }, _ | "bar" | _ => { - //~^ ERROR: wildcard pattern covers any other pattern as it will match anyway + //~^ wildcard_in_or_patterns + dbg!("matched (bar or) wild"); }, }; @@ -33,7 +36,8 @@ fn main() { dbg!("matched a"); }, _ | "bar" => { - //~^ ERROR: wildcard pattern covers any other pattern as it will match anyway + //~^ wildcard_in_or_patterns + dbg!("matched (bar or) wild"); }, }; @@ -67,6 +71,7 @@ fn main() { dbg!("Change the color"); }, ExhaustiveEnum::Quit | _ => { + //~^ wildcard_in_or_patterns dbg!("Quit or other"); }, }; @@ -102,6 +107,7 @@ fn main() { dbg!("On the y axis at {y}"); }, ExhaustiveStruct { x: 1, y: 1 } | _ => { + //~^ wildcard_in_or_patterns dbg!("On neither axis: ({x}, {y})"); }, } diff --git a/tests/ui/wild_in_or_pats.stderr b/tests/ui/wild_in_or_pats.stderr index 5e409d6dfa6d..09b2b533cd3e 100644 --- a/tests/ui/wild_in_or_pats.stderr +++ b/tests/ui/wild_in_or_pats.stderr @@ -9,7 +9,7 @@ LL | "bar" | _ => { = help: to override `-D warnings` add `#[allow(clippy::wildcard_in_or_patterns)]` error: wildcard pattern covers any other pattern as it will match anyway - --> tests/ui/wild_in_or_pats.rs:17:9 + --> tests/ui/wild_in_or_pats.rs:18:9 | LL | "bar" | "bar2" | _ => { | ^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | "bar" | "bar2" | _ => { = help: consider handling `_` separately error: wildcard pattern covers any other pattern as it will match anyway - --> tests/ui/wild_in_or_pats.rs:26:9 + --> tests/ui/wild_in_or_pats.rs:28:9 | LL | _ | "bar" | _ => { | ^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | _ | "bar" | _ => { = help: consider handling `_` separately error: wildcard pattern covers any other pattern as it will match anyway - --> tests/ui/wild_in_or_pats.rs:35:9 + --> tests/ui/wild_in_or_pats.rs:38:9 | LL | _ | "bar" => { | ^^^^^^^^^ @@ -33,7 +33,7 @@ LL | _ | "bar" => { = help: consider handling `_` separately error: wildcard pattern covers any other pattern as it will match anyway - --> tests/ui/wild_in_or_pats.rs:69:9 + --> tests/ui/wild_in_or_pats.rs:73:9 | LL | ExhaustiveEnum::Quit | _ => { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | ExhaustiveEnum::Quit | _ => { = help: consider handling `_` separately error: wildcard pattern covers any other pattern as it will match anyway - --> tests/ui/wild_in_or_pats.rs:104:9 + --> tests/ui/wild_in_or_pats.rs:109:9 | LL | ExhaustiveStruct { x: 1, y: 1 } | _ => { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/wildcard_enum_match_arm.fixed b/tests/ui/wildcard_enum_match_arm.fixed index 1089415733a9..141ff6eb2ac7 100644 --- a/tests/ui/wildcard_enum_match_arm.fixed +++ b/tests/ui/wildcard_enum_match_arm.fixed @@ -37,14 +37,17 @@ fn main() { match color { Color::Red => println!("Red"), Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan => eprintln!("Not red"), + //~^ wildcard_enum_match_arm }; match color { Color::Red => println!("Red"), _not_red @ Color::Green | _not_red @ Color::Blue | _not_red @ Color::Rgb(..) | _not_red @ Color::Cyan => eprintln!("Not red"), + //~^ wildcard_enum_match_arm }; let _str = match color { Color::Red => "Red".to_owned(), not_red @ Color::Green | not_red @ Color::Blue | not_red @ Color::Rgb(..) | not_red @ Color::Cyan => format!("{:?}", not_red), + //~^ wildcard_enum_match_arm }; match color { Color::Red => {}, @@ -61,6 +64,7 @@ fn main() { match color { Color::Rgb(r, _, _) if r > 0 => "Some red", Color::Red | Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan => "No red", + //~^ wildcard_enum_match_arm }; match color { Color::Red | Color::Green | Color::Blue | Color::Cyan => {}, @@ -78,6 +82,7 @@ fn main() { match error_kind { ErrorKind::NotFound => {}, ErrorKind::PermissionDenied | _ => {}, + //~^ wildcard_enum_match_arm } match error_kind { ErrorKind::NotFound => {}, @@ -96,6 +101,7 @@ fn main() { match Enum::A { Enum::A => (), Enum::B | Enum::__Private => (), + //~^ wildcard_enum_match_arm } } } diff --git a/tests/ui/wildcard_enum_match_arm.rs b/tests/ui/wildcard_enum_match_arm.rs index d9285c56f3ef..a13684e9100b 100644 --- a/tests/ui/wildcard_enum_match_arm.rs +++ b/tests/ui/wildcard_enum_match_arm.rs @@ -37,14 +37,17 @@ fn main() { match color { Color::Red => println!("Red"), _ => eprintln!("Not red"), + //~^ wildcard_enum_match_arm }; match color { Color::Red => println!("Red"), _not_red => eprintln!("Not red"), + //~^ wildcard_enum_match_arm }; let _str = match color { Color::Red => "Red".to_owned(), not_red => format!("{:?}", not_red), + //~^ wildcard_enum_match_arm }; match color { Color::Red => {}, @@ -61,6 +64,7 @@ fn main() { match color { Color::Rgb(r, _, _) if r > 0 => "Some red", _ => "No red", + //~^ wildcard_enum_match_arm }; match color { Color::Red | Color::Green | Color::Blue | Color::Cyan => {}, @@ -78,6 +82,7 @@ fn main() { match error_kind { ErrorKind::NotFound => {}, _ => {}, + //~^ wildcard_enum_match_arm } match error_kind { ErrorKind::NotFound => {}, @@ -96,6 +101,7 @@ fn main() { match Enum::A { Enum::A => (), _ => (), + //~^ wildcard_enum_match_arm } } } diff --git a/tests/ui/wildcard_enum_match_arm.stderr b/tests/ui/wildcard_enum_match_arm.stderr index 70ac768aaacd..088c6b7b2841 100644 --- a/tests/ui/wildcard_enum_match_arm.stderr +++ b/tests/ui/wildcard_enum_match_arm.stderr @@ -11,31 +11,31 @@ LL | #![deny(clippy::wildcard_enum_match_arm)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: wildcard match will also match any future added variants - --> tests/ui/wildcard_enum_match_arm.rs:43:9 + --> tests/ui/wildcard_enum_match_arm.rs:44:9 | LL | _not_red => eprintln!("Not red"), | ^^^^^^^^ help: try: `_not_red @ Color::Green | _not_red @ Color::Blue | _not_red @ Color::Rgb(..) | _not_red @ Color::Cyan` error: wildcard match will also match any future added variants - --> tests/ui/wildcard_enum_match_arm.rs:47:9 + --> tests/ui/wildcard_enum_match_arm.rs:49:9 | LL | not_red => format!("{:?}", not_red), | ^^^^^^^ help: try: `not_red @ Color::Green | not_red @ Color::Blue | not_red @ Color::Rgb(..) | not_red @ Color::Cyan` error: wildcard match will also match any future added variants - --> tests/ui/wildcard_enum_match_arm.rs:63:9 + --> tests/ui/wildcard_enum_match_arm.rs:66:9 | LL | _ => "No red", | ^ help: try: `Color::Red | Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan` error: wildcard matches known variants and will also match future added variants - --> tests/ui/wildcard_enum_match_arm.rs:80:9 + --> tests/ui/wildcard_enum_match_arm.rs:84:9 | LL | _ => {}, | ^ help: try: `ErrorKind::PermissionDenied | _` error: wildcard match will also match any future added variants - --> tests/ui/wildcard_enum_match_arm.rs:98:13 + --> tests/ui/wildcard_enum_match_arm.rs:103:13 | LL | _ => (), | ^ help: try: `Enum::B | Enum::__Private` diff --git a/tests/ui/wildcard_imports.fixed b/tests/ui/wildcard_imports.fixed index 46890ee9213f..a26b4a34190c 100644 --- a/tests/ui/wildcard_imports.fixed +++ b/tests/ui/wildcard_imports.fixed @@ -13,15 +13,21 @@ extern crate wildcard_imports_helper; use crate::fn_mod::foo; +//~^ wildcard_imports use crate::mod_mod::inner_mod; +//~^ wildcard_imports use crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}; +//~^ wildcard_imports #[macro_use] use crate::struct_mod::{A, inner_struct_mod}; +//~^ wildcard_imports #[allow(unused_imports)] use wildcard_imports_helper::inner::inner_for_self_import; use wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar; +//~^ wildcard_imports use wildcard_imports_helper::{ExternA, extern_foo}; +//~^ wildcard_imports use std::io::prelude::*; use wildcard_imports_helper::extern_prelude::v1::*; @@ -92,6 +98,7 @@ mod underscore_mod { fn does_lint() { use self::exports_underscore_ish::{_Deref, dummy}; + //~^ wildcard_imports let _ = (&0).deref(); dummy(); } @@ -123,13 +130,16 @@ mod in_fn_test { fn test_intern() { use crate::fn_mod::foo; + //~^ wildcard_imports foo(); } fn test_extern() { use wildcard_imports_helper::inner::inner_for_self_import::{self, inner_extern_foo}; + //~^ wildcard_imports use wildcard_imports_helper::{ExternA, extern_foo}; + //~^ wildcard_imports inner_for_self_import::inner_extern_foo(); inner_extern_foo(); @@ -142,6 +152,8 @@ mod in_fn_test { fn test_inner_nested() { #[rustfmt::skip] use self::{inner::inner_foo, inner2::inner_bar}; + //~^ wildcard_imports + //~| wildcard_imports inner_foo(); inner_bar(); @@ -149,6 +161,7 @@ mod in_fn_test { fn test_extern_reexported() { use wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}; + //~^ wildcard_imports extern_exported(); let _ = ExternExportedStruct; @@ -178,6 +191,7 @@ mod in_fn_test { fn test_reexported() { use crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}; + //~^ wildcard_imports exported(); let _ = ExportedStruct; @@ -187,6 +201,7 @@ fn test_reexported() { #[rustfmt::skip] fn test_weird_formatting() { use crate:: in_fn_test::exported; + //~^ wildcard_imports use crate:: fn_mod::foo; exported(); @@ -198,6 +213,7 @@ mod super_imports { mod should_be_replaced { use super::foofoo; + //~^ wildcard_imports fn with_super() { let _ = foofoo(); @@ -236,6 +252,7 @@ mod super_imports { fn insidefoo() {} mod inner { use super::insidefoo; + //~^ wildcard_imports fn with_super() { let _ = insidefoo(); } @@ -244,6 +261,7 @@ mod super_imports { mod use_explicit_should_be_replaced { use crate::super_imports::foofoo; + //~^ wildcard_imports fn with_explicit() { let _ = foofoo(); @@ -253,6 +271,7 @@ mod super_imports { mod use_double_super_should_be_replaced { mod inner { use super::super::foofoo; + //~^ wildcard_imports fn with_double_super() { let _ = foofoo(); @@ -262,6 +281,7 @@ mod super_imports { mod use_super_explicit_should_be_replaced { use super::super::super_imports::foofoo; + //~^ wildcard_imports fn with_super_explicit() { let _ = foofoo(); @@ -270,6 +290,7 @@ mod super_imports { mod attestation_should_be_replaced { use super::foofoo; + //~^ wildcard_imports fn with_explicit() { let _ = foofoo(); diff --git a/tests/ui/wildcard_imports.rs b/tests/ui/wildcard_imports.rs index 1a5586cbb88d..2168f0a8918d 100644 --- a/tests/ui/wildcard_imports.rs +++ b/tests/ui/wildcard_imports.rs @@ -13,15 +13,21 @@ extern crate wildcard_imports_helper; use crate::fn_mod::*; +//~^ wildcard_imports use crate::mod_mod::*; +//~^ wildcard_imports use crate::multi_fn_mod::*; +//~^ wildcard_imports #[macro_use] use crate::struct_mod::*; +//~^ wildcard_imports #[allow(unused_imports)] use wildcard_imports_helper::inner::inner_for_self_import; use wildcard_imports_helper::inner::inner_for_self_import::*; +//~^ wildcard_imports use wildcard_imports_helper::*; +//~^ wildcard_imports use std::io::prelude::*; use wildcard_imports_helper::extern_prelude::v1::*; @@ -92,6 +98,7 @@ mod underscore_mod { fn does_lint() { use self::exports_underscore_ish::*; + //~^ wildcard_imports let _ = (&0).deref(); dummy(); } @@ -123,13 +130,16 @@ mod in_fn_test { fn test_intern() { use crate::fn_mod::*; + //~^ wildcard_imports foo(); } fn test_extern() { use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; + //~^ wildcard_imports use wildcard_imports_helper::*; + //~^ wildcard_imports inner_for_self_import::inner_extern_foo(); inner_extern_foo(); @@ -142,6 +152,8 @@ mod in_fn_test { fn test_inner_nested() { #[rustfmt::skip] use self::{inner::*, inner2::*}; + //~^ wildcard_imports + //~| wildcard_imports inner_foo(); inner_bar(); @@ -149,6 +161,7 @@ mod in_fn_test { fn test_extern_reexported() { use wildcard_imports_helper::*; + //~^ wildcard_imports extern_exported(); let _ = ExternExportedStruct; @@ -178,6 +191,7 @@ mod in_fn_test { fn test_reexported() { use crate::in_fn_test::*; + //~^ wildcard_imports exported(); let _ = ExportedStruct; @@ -187,7 +201,9 @@ fn test_reexported() { #[rustfmt::skip] fn test_weird_formatting() { use crate:: in_fn_test:: * ; + //~^ wildcard_imports use crate:: fn_mod:: + //~^ wildcard_imports *; exported(); @@ -199,6 +215,7 @@ mod super_imports { mod should_be_replaced { use super::*; + //~^ wildcard_imports fn with_super() { let _ = foofoo(); @@ -237,6 +254,7 @@ mod super_imports { fn insidefoo() {} mod inner { use super::*; + //~^ wildcard_imports fn with_super() { let _ = insidefoo(); } @@ -245,6 +263,7 @@ mod super_imports { mod use_explicit_should_be_replaced { use crate::super_imports::*; + //~^ wildcard_imports fn with_explicit() { let _ = foofoo(); @@ -254,6 +273,7 @@ mod super_imports { mod use_double_super_should_be_replaced { mod inner { use super::super::*; + //~^ wildcard_imports fn with_double_super() { let _ = foofoo(); @@ -263,6 +283,7 @@ mod super_imports { mod use_super_explicit_should_be_replaced { use super::super::super_imports::*; + //~^ wildcard_imports fn with_super_explicit() { let _ = foofoo(); @@ -271,6 +292,7 @@ mod super_imports { mod attestation_should_be_replaced { use super::*; + //~^ wildcard_imports fn with_explicit() { let _ = foofoo(); diff --git a/tests/ui/wildcard_imports.stderr b/tests/ui/wildcard_imports.stderr index 8e88f216394d..f774126102bc 100644 --- a/tests/ui/wildcard_imports.stderr +++ b/tests/ui/wildcard_imports.stderr @@ -8,129 +8,130 @@ LL | use crate::fn_mod::*; = help: to override `-D warnings` add `#[allow(clippy::wildcard_imports)]` error: usage of wildcard import - --> tests/ui/wildcard_imports.rs:16:5 + --> tests/ui/wildcard_imports.rs:17:5 | LL | use crate::mod_mod::*; | ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod` error: usage of wildcard import - --> tests/ui/wildcard_imports.rs:17:5 + --> tests/ui/wildcard_imports.rs:19:5 | LL | use crate::multi_fn_mod::*; | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}` error: usage of wildcard import - --> tests/ui/wildcard_imports.rs:19:5 + --> tests/ui/wildcard_imports.rs:22:5 | LL | use crate::struct_mod::*; | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}` error: usage of wildcard import - --> tests/ui/wildcard_imports.rs:23:5 + --> tests/ui/wildcard_imports.rs:27:5 | LL | use wildcard_imports_helper::inner::inner_for_self_import::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar` error: usage of wildcard import - --> tests/ui/wildcard_imports.rs:24:5 + --> tests/ui/wildcard_imports.rs:29:5 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> tests/ui/wildcard_imports.rs:94:13 + --> tests/ui/wildcard_imports.rs:100:13 | LL | use self::exports_underscore_ish::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `self::exports_underscore_ish::{_Deref, dummy}` error: usage of wildcard import - --> tests/ui/wildcard_imports.rs:125:13 + --> tests/ui/wildcard_imports.rs:132:13 | LL | use crate::fn_mod::*; | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` error: usage of wildcard import - --> tests/ui/wildcard_imports.rs:131:75 + --> tests/ui/wildcard_imports.rs:139:75 | LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; | ^ help: try: `inner_extern_foo` error: usage of wildcard import - --> tests/ui/wildcard_imports.rs:132:13 + --> tests/ui/wildcard_imports.rs:141:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> tests/ui/wildcard_imports.rs:144:20 + --> tests/ui/wildcard_imports.rs:154:20 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^ help: try: `inner::inner_foo` error: usage of wildcard import - --> tests/ui/wildcard_imports.rs:144:30 + --> tests/ui/wildcard_imports.rs:154:30 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^^ help: try: `inner2::inner_bar` error: usage of wildcard import - --> tests/ui/wildcard_imports.rs:151:13 + --> tests/ui/wildcard_imports.rs:163:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` error: usage of wildcard import - --> tests/ui/wildcard_imports.rs:180:9 + --> tests/ui/wildcard_imports.rs:193:9 | LL | use crate::in_fn_test::*; | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` error: usage of wildcard import - --> tests/ui/wildcard_imports.rs:189:9 + --> tests/ui/wildcard_imports.rs:203:9 | LL | use crate:: in_fn_test:: * ; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` error: usage of wildcard import - --> tests/ui/wildcard_imports.rs:190:9 + --> tests/ui/wildcard_imports.rs:205:9 | LL | use crate:: fn_mod:: | _________^ +LL | | LL | | *; | |_________^ help: try: `crate:: fn_mod::foo` error: usage of wildcard import - --> tests/ui/wildcard_imports.rs:201:13 + --> tests/ui/wildcard_imports.rs:217:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` error: usage of wildcard import - --> tests/ui/wildcard_imports.rs:239:17 + --> tests/ui/wildcard_imports.rs:256:17 | LL | use super::*; | ^^^^^^^^ help: try: `super::insidefoo` error: usage of wildcard import - --> tests/ui/wildcard_imports.rs:247:13 + --> tests/ui/wildcard_imports.rs:265:13 | LL | use crate::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo` error: usage of wildcard import - --> tests/ui/wildcard_imports.rs:256:17 + --> tests/ui/wildcard_imports.rs:275:17 | LL | use super::super::*; | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` error: usage of wildcard import - --> tests/ui/wildcard_imports.rs:265:13 + --> tests/ui/wildcard_imports.rs:285:13 | LL | use super::super::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` error: usage of wildcard import - --> tests/ui/wildcard_imports.rs:273:13 + --> tests/ui/wildcard_imports.rs:294:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` diff --git a/tests/ui/wildcard_imports_2021.edition2018.fixed b/tests/ui/wildcard_imports_2021.edition2018.fixed index 197dd3b94df0..a3d1aebba8af 100644 --- a/tests/ui/wildcard_imports_2021.edition2018.fixed +++ b/tests/ui/wildcard_imports_2021.edition2018.fixed @@ -11,14 +11,20 @@ extern crate wildcard_imports_helper; use crate::fn_mod::foo; +//~^ wildcard_imports use crate::mod_mod::inner_mod; +//~^ wildcard_imports use crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}; +//~^ wildcard_imports use crate::struct_mod::{A, inner_struct_mod}; +//~^ wildcard_imports #[allow(unused_imports)] use wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar; +//~^ wildcard_imports use wildcard_imports_helper::prelude::v1::*; use wildcard_imports_helper::{ExternA, extern_foo}; +//~^ wildcard_imports use std::io::prelude::*; @@ -87,6 +93,7 @@ mod underscore_mod { fn does_lint() { use exports_underscore_ish::{_Deref, dummy}; + //~^ wildcard_imports let _ = (&0).deref(); dummy(); } @@ -117,13 +124,16 @@ mod in_fn_test { fn test_intern() { use crate::fn_mod::foo; + //~^ wildcard_imports foo(); } fn test_extern() { use wildcard_imports_helper::inner::inner_for_self_import::{self, inner_extern_foo}; + //~^ wildcard_imports use wildcard_imports_helper::{ExternA, extern_foo}; + //~^ wildcard_imports inner_for_self_import::inner_extern_foo(); inner_extern_foo(); @@ -136,6 +146,8 @@ mod in_fn_test { fn test_inner_nested() { #[rustfmt::skip] use self::{inner::inner_foo, inner2::inner_bar}; + //~^ wildcard_imports + //~| wildcard_imports inner_foo(); inner_bar(); @@ -143,6 +155,7 @@ mod in_fn_test { fn test_extern_reexported() { use wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}; + //~^ wildcard_imports extern_exported(); let _ = ExternExportedStruct; @@ -172,6 +185,7 @@ mod in_fn_test { fn test_reexported() { use crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}; + //~^ wildcard_imports exported(); let _ = ExportedStruct; @@ -181,6 +195,7 @@ fn test_reexported() { #[rustfmt::skip] fn test_weird_formatting() { use crate:: in_fn_test::exported; + //~^ wildcard_imports use crate:: fn_mod::foo; exported(); @@ -192,6 +207,7 @@ mod super_imports { mod should_be_replaced { use super::foofoo; + //~^ wildcard_imports fn with_super() { let _ = foofoo(); @@ -230,6 +246,7 @@ mod super_imports { fn insidefoo() {} mod inner { use super::insidefoo; + //~^ wildcard_imports fn with_super() { let _ = insidefoo(); } @@ -238,6 +255,7 @@ mod super_imports { mod use_explicit_should_be_replaced { use crate::super_imports::foofoo; + //~^ wildcard_imports fn with_explicit() { let _ = foofoo(); @@ -247,6 +265,7 @@ mod super_imports { mod use_double_super_should_be_replaced { mod inner { use super::super::foofoo; + //~^ wildcard_imports fn with_double_super() { let _ = foofoo(); @@ -256,6 +275,7 @@ mod super_imports { mod use_super_explicit_should_be_replaced { use super::super::super_imports::foofoo; + //~^ wildcard_imports fn with_super_explicit() { let _ = foofoo(); @@ -264,6 +284,7 @@ mod super_imports { mod attestation_should_be_replaced { use super::foofoo; + //~^ wildcard_imports fn with_explicit() { let _ = foofoo(); diff --git a/tests/ui/wildcard_imports_2021.edition2018.stderr b/tests/ui/wildcard_imports_2021.edition2018.stderr index 66adacd95dcc..a1b557f39f0d 100644 --- a/tests/ui/wildcard_imports_2021.edition2018.stderr +++ b/tests/ui/wildcard_imports_2021.edition2018.stderr @@ -8,129 +8,130 @@ LL | use crate::fn_mod::*; = help: to override `-D warnings` add `#[allow(clippy::wildcard_imports)]` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:14:5 + --> tests/ui/wildcard_imports_2021.rs:15:5 | LL | use crate::mod_mod::*; | ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:15:5 + --> tests/ui/wildcard_imports_2021.rs:17:5 | LL | use crate::multi_fn_mod::*; | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:16:5 + --> tests/ui/wildcard_imports_2021.rs:19:5 | LL | use crate::struct_mod::*; | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:19:5 + --> tests/ui/wildcard_imports_2021.rs:23:5 | LL | use wildcard_imports_helper::inner::inner_for_self_import::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:21:5 + --> tests/ui/wildcard_imports_2021.rs:26:5 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:89:13 + --> tests/ui/wildcard_imports_2021.rs:95:13 | LL | use exports_underscore_ish::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `exports_underscore_ish::{_Deref, dummy}` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:119:13 + --> tests/ui/wildcard_imports_2021.rs:126:13 | LL | use crate::fn_mod::*; | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:125:75 + --> tests/ui/wildcard_imports_2021.rs:133:75 | LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; | ^ help: try: `inner_extern_foo` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:126:13 + --> tests/ui/wildcard_imports_2021.rs:135:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:138:20 + --> tests/ui/wildcard_imports_2021.rs:148:20 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^ help: try: `inner::inner_foo` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:138:30 + --> tests/ui/wildcard_imports_2021.rs:148:30 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^^ help: try: `inner2::inner_bar` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:145:13 + --> tests/ui/wildcard_imports_2021.rs:157:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:174:9 + --> tests/ui/wildcard_imports_2021.rs:187:9 | LL | use crate::in_fn_test::*; | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:183:9 + --> tests/ui/wildcard_imports_2021.rs:197:9 | LL | use crate:: in_fn_test:: * ; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:184:9 + --> tests/ui/wildcard_imports_2021.rs:199:9 | LL | use crate:: fn_mod:: | _________^ +LL | | LL | | *; | |_________^ help: try: `crate:: fn_mod::foo` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:195:13 + --> tests/ui/wildcard_imports_2021.rs:211:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:233:17 + --> tests/ui/wildcard_imports_2021.rs:250:17 | LL | use super::*; | ^^^^^^^^ help: try: `super::insidefoo` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:241:13 + --> tests/ui/wildcard_imports_2021.rs:259:13 | LL | use crate::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:250:17 + --> tests/ui/wildcard_imports_2021.rs:269:17 | LL | use super::super::*; | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:259:13 + --> tests/ui/wildcard_imports_2021.rs:279:13 | LL | use super::super::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:267:13 + --> tests/ui/wildcard_imports_2021.rs:288:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` diff --git a/tests/ui/wildcard_imports_2021.edition2021.fixed b/tests/ui/wildcard_imports_2021.edition2021.fixed index 197dd3b94df0..a3d1aebba8af 100644 --- a/tests/ui/wildcard_imports_2021.edition2021.fixed +++ b/tests/ui/wildcard_imports_2021.edition2021.fixed @@ -11,14 +11,20 @@ extern crate wildcard_imports_helper; use crate::fn_mod::foo; +//~^ wildcard_imports use crate::mod_mod::inner_mod; +//~^ wildcard_imports use crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}; +//~^ wildcard_imports use crate::struct_mod::{A, inner_struct_mod}; +//~^ wildcard_imports #[allow(unused_imports)] use wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar; +//~^ wildcard_imports use wildcard_imports_helper::prelude::v1::*; use wildcard_imports_helper::{ExternA, extern_foo}; +//~^ wildcard_imports use std::io::prelude::*; @@ -87,6 +93,7 @@ mod underscore_mod { fn does_lint() { use exports_underscore_ish::{_Deref, dummy}; + //~^ wildcard_imports let _ = (&0).deref(); dummy(); } @@ -117,13 +124,16 @@ mod in_fn_test { fn test_intern() { use crate::fn_mod::foo; + //~^ wildcard_imports foo(); } fn test_extern() { use wildcard_imports_helper::inner::inner_for_self_import::{self, inner_extern_foo}; + //~^ wildcard_imports use wildcard_imports_helper::{ExternA, extern_foo}; + //~^ wildcard_imports inner_for_self_import::inner_extern_foo(); inner_extern_foo(); @@ -136,6 +146,8 @@ mod in_fn_test { fn test_inner_nested() { #[rustfmt::skip] use self::{inner::inner_foo, inner2::inner_bar}; + //~^ wildcard_imports + //~| wildcard_imports inner_foo(); inner_bar(); @@ -143,6 +155,7 @@ mod in_fn_test { fn test_extern_reexported() { use wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}; + //~^ wildcard_imports extern_exported(); let _ = ExternExportedStruct; @@ -172,6 +185,7 @@ mod in_fn_test { fn test_reexported() { use crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}; + //~^ wildcard_imports exported(); let _ = ExportedStruct; @@ -181,6 +195,7 @@ fn test_reexported() { #[rustfmt::skip] fn test_weird_formatting() { use crate:: in_fn_test::exported; + //~^ wildcard_imports use crate:: fn_mod::foo; exported(); @@ -192,6 +207,7 @@ mod super_imports { mod should_be_replaced { use super::foofoo; + //~^ wildcard_imports fn with_super() { let _ = foofoo(); @@ -230,6 +246,7 @@ mod super_imports { fn insidefoo() {} mod inner { use super::insidefoo; + //~^ wildcard_imports fn with_super() { let _ = insidefoo(); } @@ -238,6 +255,7 @@ mod super_imports { mod use_explicit_should_be_replaced { use crate::super_imports::foofoo; + //~^ wildcard_imports fn with_explicit() { let _ = foofoo(); @@ -247,6 +265,7 @@ mod super_imports { mod use_double_super_should_be_replaced { mod inner { use super::super::foofoo; + //~^ wildcard_imports fn with_double_super() { let _ = foofoo(); @@ -256,6 +275,7 @@ mod super_imports { mod use_super_explicit_should_be_replaced { use super::super::super_imports::foofoo; + //~^ wildcard_imports fn with_super_explicit() { let _ = foofoo(); @@ -264,6 +284,7 @@ mod super_imports { mod attestation_should_be_replaced { use super::foofoo; + //~^ wildcard_imports fn with_explicit() { let _ = foofoo(); diff --git a/tests/ui/wildcard_imports_2021.edition2021.stderr b/tests/ui/wildcard_imports_2021.edition2021.stderr index 66adacd95dcc..a1b557f39f0d 100644 --- a/tests/ui/wildcard_imports_2021.edition2021.stderr +++ b/tests/ui/wildcard_imports_2021.edition2021.stderr @@ -8,129 +8,130 @@ LL | use crate::fn_mod::*; = help: to override `-D warnings` add `#[allow(clippy::wildcard_imports)]` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:14:5 + --> tests/ui/wildcard_imports_2021.rs:15:5 | LL | use crate::mod_mod::*; | ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:15:5 + --> tests/ui/wildcard_imports_2021.rs:17:5 | LL | use crate::multi_fn_mod::*; | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:16:5 + --> tests/ui/wildcard_imports_2021.rs:19:5 | LL | use crate::struct_mod::*; | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:19:5 + --> tests/ui/wildcard_imports_2021.rs:23:5 | LL | use wildcard_imports_helper::inner::inner_for_self_import::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:21:5 + --> tests/ui/wildcard_imports_2021.rs:26:5 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:89:13 + --> tests/ui/wildcard_imports_2021.rs:95:13 | LL | use exports_underscore_ish::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `exports_underscore_ish::{_Deref, dummy}` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:119:13 + --> tests/ui/wildcard_imports_2021.rs:126:13 | LL | use crate::fn_mod::*; | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:125:75 + --> tests/ui/wildcard_imports_2021.rs:133:75 | LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; | ^ help: try: `inner_extern_foo` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:126:13 + --> tests/ui/wildcard_imports_2021.rs:135:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:138:20 + --> tests/ui/wildcard_imports_2021.rs:148:20 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^ help: try: `inner::inner_foo` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:138:30 + --> tests/ui/wildcard_imports_2021.rs:148:30 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^^ help: try: `inner2::inner_bar` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:145:13 + --> tests/ui/wildcard_imports_2021.rs:157:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:174:9 + --> tests/ui/wildcard_imports_2021.rs:187:9 | LL | use crate::in_fn_test::*; | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:183:9 + --> tests/ui/wildcard_imports_2021.rs:197:9 | LL | use crate:: in_fn_test:: * ; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:184:9 + --> tests/ui/wildcard_imports_2021.rs:199:9 | LL | use crate:: fn_mod:: | _________^ +LL | | LL | | *; | |_________^ help: try: `crate:: fn_mod::foo` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:195:13 + --> tests/ui/wildcard_imports_2021.rs:211:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:233:17 + --> tests/ui/wildcard_imports_2021.rs:250:17 | LL | use super::*; | ^^^^^^^^ help: try: `super::insidefoo` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:241:13 + --> tests/ui/wildcard_imports_2021.rs:259:13 | LL | use crate::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:250:17 + --> tests/ui/wildcard_imports_2021.rs:269:17 | LL | use super::super::*; | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:259:13 + --> tests/ui/wildcard_imports_2021.rs:279:13 | LL | use super::super::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` error: usage of wildcard import - --> tests/ui/wildcard_imports_2021.rs:267:13 + --> tests/ui/wildcard_imports_2021.rs:288:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` diff --git a/tests/ui/wildcard_imports_2021.rs b/tests/ui/wildcard_imports_2021.rs index 606ff080e774..8075c15bc14f 100644 --- a/tests/ui/wildcard_imports_2021.rs +++ b/tests/ui/wildcard_imports_2021.rs @@ -11,14 +11,20 @@ extern crate wildcard_imports_helper; use crate::fn_mod::*; +//~^ wildcard_imports use crate::mod_mod::*; +//~^ wildcard_imports use crate::multi_fn_mod::*; +//~^ wildcard_imports use crate::struct_mod::*; +//~^ wildcard_imports #[allow(unused_imports)] use wildcard_imports_helper::inner::inner_for_self_import::*; +//~^ wildcard_imports use wildcard_imports_helper::prelude::v1::*; use wildcard_imports_helper::*; +//~^ wildcard_imports use std::io::prelude::*; @@ -87,6 +93,7 @@ mod underscore_mod { fn does_lint() { use exports_underscore_ish::*; + //~^ wildcard_imports let _ = (&0).deref(); dummy(); } @@ -117,13 +124,16 @@ mod in_fn_test { fn test_intern() { use crate::fn_mod::*; + //~^ wildcard_imports foo(); } fn test_extern() { use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; + //~^ wildcard_imports use wildcard_imports_helper::*; + //~^ wildcard_imports inner_for_self_import::inner_extern_foo(); inner_extern_foo(); @@ -136,6 +146,8 @@ mod in_fn_test { fn test_inner_nested() { #[rustfmt::skip] use self::{inner::*, inner2::*}; + //~^ wildcard_imports + //~| wildcard_imports inner_foo(); inner_bar(); @@ -143,6 +155,7 @@ mod in_fn_test { fn test_extern_reexported() { use wildcard_imports_helper::*; + //~^ wildcard_imports extern_exported(); let _ = ExternExportedStruct; @@ -172,6 +185,7 @@ mod in_fn_test { fn test_reexported() { use crate::in_fn_test::*; + //~^ wildcard_imports exported(); let _ = ExportedStruct; @@ -181,7 +195,9 @@ fn test_reexported() { #[rustfmt::skip] fn test_weird_formatting() { use crate:: in_fn_test:: * ; + //~^ wildcard_imports use crate:: fn_mod:: + //~^ wildcard_imports *; exported(); @@ -193,6 +209,7 @@ mod super_imports { mod should_be_replaced { use super::*; + //~^ wildcard_imports fn with_super() { let _ = foofoo(); @@ -231,6 +248,7 @@ mod super_imports { fn insidefoo() {} mod inner { use super::*; + //~^ wildcard_imports fn with_super() { let _ = insidefoo(); } @@ -239,6 +257,7 @@ mod super_imports { mod use_explicit_should_be_replaced { use crate::super_imports::*; + //~^ wildcard_imports fn with_explicit() { let _ = foofoo(); @@ -248,6 +267,7 @@ mod super_imports { mod use_double_super_should_be_replaced { mod inner { use super::super::*; + //~^ wildcard_imports fn with_double_super() { let _ = foofoo(); @@ -257,6 +277,7 @@ mod super_imports { mod use_super_explicit_should_be_replaced { use super::super::super_imports::*; + //~^ wildcard_imports fn with_super_explicit() { let _ = foofoo(); @@ -265,6 +286,7 @@ mod super_imports { mod attestation_should_be_replaced { use super::*; + //~^ wildcard_imports fn with_explicit() { let _ = foofoo(); diff --git a/tests/ui/wildcard_imports_cfgtest.rs b/tests/ui/wildcard_imports_cfgtest.rs index 203c4e15b50c..c41458d5bb0a 100644 --- a/tests/ui/wildcard_imports_cfgtest.rs +++ b/tests/ui/wildcard_imports_cfgtest.rs @@ -1,3 +1,4 @@ +//@check-pass //@compile-flags: --test #![warn(clippy::wildcard_imports)] diff --git a/tests/ui/write_literal.fixed b/tests/ui/write_literal.fixed index f1def776e1bc..e84f768e33d0 100644 --- a/tests/ui/write_literal.fixed +++ b/tests/ui/write_literal.fixed @@ -29,46 +29,55 @@ fn main() { // these should throw warnings write!(v, "Hello world"); - //~^ ERROR: literal with an empty format string - //~| NOTE: `-D clippy::write-literal` implied by `-D warnings` + //~^ write_literal + writeln!(v, "Hello {} world", world); - //~^ ERROR: literal with an empty format string + //~^ write_literal + writeln!(v, "Hello world"); - //~^ ERROR: literal with an empty format string + //~^ write_literal + writeln!(v, "a literal {:.4}", 5); - //~^ ERROR: literal with an empty format string + //~^ write_literal // positional args don't change the fact // that we're using a literal -- this should // throw a warning writeln!(v, "hello world"); - //~^ ERROR: literal with an empty format string + //~^ write_literal + writeln!(v, "world hello"); - //~^ ERROR: literal with an empty format string + //~^ write_literal // named args shouldn't change anything either writeln!(v, "hello world"); - //~^ ERROR: literal with an empty format string + //~^ write_literal + writeln!(v, "world hello"); - //~^ ERROR: literal with an empty format string + //~^ write_literal // #10128 writeln!(v, "hello {0} world", 2); - //~^ ERROR: literal with an empty format string + //~^ write_literal + writeln!(v, "world {0} hello", 2); - //~^ ERROR: literal with an empty format string + //~^ write_literal + writeln!(v, "hello {0} {1}, {bar}", 2, 3, bar = 4); - //~^ ERROR: literal with an empty format string + //~^ write_literal + writeln!(v, "hello {0} {1}, world {2}", 2, 3, 4); - //~^ ERROR: literal with an empty format string + //~^ write_literal } fn issue_13959() { let mut v = Vec::new(); writeln!(v, "\""); + //~^ write_literal writeln!( v, " + //~^ write_literal foo \\ \\\\ diff --git a/tests/ui/write_literal.rs b/tests/ui/write_literal.rs index 1b7df91b47e1..fc29fcbede7e 100644 --- a/tests/ui/write_literal.rs +++ b/tests/ui/write_literal.rs @@ -29,47 +29,56 @@ fn main() { // these should throw warnings write!(v, "Hello {}", "world"); - //~^ ERROR: literal with an empty format string - //~| NOTE: `-D clippy::write-literal` implied by `-D warnings` + //~^ write_literal + writeln!(v, "Hello {} {}", world, "world"); - //~^ ERROR: literal with an empty format string + //~^ write_literal + writeln!(v, "Hello {}", "world"); - //~^ ERROR: literal with an empty format string + //~^ write_literal + writeln!(v, "{} {:.4}", "a literal", 5); - //~^ ERROR: literal with an empty format string + //~^ write_literal // positional args don't change the fact // that we're using a literal -- this should // throw a warning writeln!(v, "{0} {1}", "hello", "world"); - //~^ ERROR: literal with an empty format string + //~^ write_literal + writeln!(v, "{1} {0}", "hello", "world"); - //~^ ERROR: literal with an empty format string + //~^ write_literal // named args shouldn't change anything either writeln!(v, "{foo} {bar}", foo = "hello", bar = "world"); - //~^ ERROR: literal with an empty format string + //~^ write_literal + writeln!(v, "{bar} {foo}", foo = "hello", bar = "world"); - //~^ ERROR: literal with an empty format string + //~^ write_literal // #10128 writeln!(v, "{0} {1} {2}", "hello", 2, "world"); - //~^ ERROR: literal with an empty format string + //~^ write_literal + writeln!(v, "{2} {1} {0}", "hello", 2, "world"); - //~^ ERROR: literal with an empty format string + //~^ write_literal + writeln!(v, "{0} {1} {2}, {bar}", "hello", 2, 3, bar = 4); - //~^ ERROR: literal with an empty format string + //~^ write_literal + writeln!(v, "{0} {1} {2}, {3} {4}", "hello", 2, 3, "world", 4); - //~^ ERROR: literal with an empty format string + //~^ write_literal } fn issue_13959() { let mut v = Vec::new(); writeln!(v, "{}", r#"""#); + //~^ write_literal writeln!( v, "{}", r#" + //~^ write_literal foo \ \\ diff --git a/tests/ui/write_literal.stderr b/tests/ui/write_literal.stderr index 35c93d567cd3..d53c2a7de2e0 100644 --- a/tests/ui/write_literal.stderr +++ b/tests/ui/write_literal.stderr @@ -25,7 +25,7 @@ LL + writeln!(v, "Hello {} world", world); | error: literal with an empty format string - --> tests/ui/write_literal.rs:36:29 + --> tests/ui/write_literal.rs:37:29 | LL | writeln!(v, "Hello {}", "world"); | ^^^^^^^ @@ -37,7 +37,7 @@ LL + writeln!(v, "Hello world"); | error: literal with an empty format string - --> tests/ui/write_literal.rs:38:29 + --> tests/ui/write_literal.rs:40:29 | LL | writeln!(v, "{} {:.4}", "a literal", 5); | ^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + writeln!(v, "a literal {:.4}", 5); | error: literal with an empty format string - --> tests/ui/write_literal.rs:44:28 + --> tests/ui/write_literal.rs:46:28 | LL | writeln!(v, "{0} {1}", "hello", "world"); | ^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + writeln!(v, "hello world"); | error: literal with an empty format string - --> tests/ui/write_literal.rs:46:28 + --> tests/ui/write_literal.rs:49:28 | LL | writeln!(v, "{1} {0}", "hello", "world"); | ^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + writeln!(v, "world hello"); | error: literal with an empty format string - --> tests/ui/write_literal.rs:50:38 + --> tests/ui/write_literal.rs:53:38 | LL | writeln!(v, "{foo} {bar}", foo = "hello", bar = "world"); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + writeln!(v, "hello world"); | error: literal with an empty format string - --> tests/ui/write_literal.rs:52:38 + --> tests/ui/write_literal.rs:56:38 | LL | writeln!(v, "{bar} {foo}", foo = "hello", bar = "world"); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL + writeln!(v, "world hello"); | error: literal with an empty format string - --> tests/ui/write_literal.rs:56:32 + --> tests/ui/write_literal.rs:60:32 | LL | writeln!(v, "{0} {1} {2}", "hello", 2, "world"); | ^^^^^^^^^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL + writeln!(v, "hello {0} world", 2); | error: literal with an empty format string - --> tests/ui/write_literal.rs:58:32 + --> tests/ui/write_literal.rs:63:32 | LL | writeln!(v, "{2} {1} {0}", "hello", 2, "world"); | ^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL + writeln!(v, "world {0} hello", 2); | error: literal with an empty format string - --> tests/ui/write_literal.rs:60:39 + --> tests/ui/write_literal.rs:66:39 | LL | writeln!(v, "{0} {1} {2}, {bar}", "hello", 2, 3, bar = 4); | ^^^^^^^ @@ -133,7 +133,7 @@ LL + writeln!(v, "hello {0} {1}, {bar}", 2, 3, bar = 4); | error: literal with an empty format string - --> tests/ui/write_literal.rs:62:41 + --> tests/ui/write_literal.rs:69:41 | LL | writeln!(v, "{0} {1} {2}, {3} {4}", "hello", 2, 3, "world", 4); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -145,7 +145,7 @@ LL + writeln!(v, "hello {0} {1}, world {2}", 2, 3, 4); | error: literal with an empty format string - --> tests/ui/write_literal.rs:68:23 + --> tests/ui/write_literal.rs:75:23 | LL | writeln!(v, "{}", r#"""#); | ^^^^^^ @@ -157,12 +157,12 @@ LL + writeln!(v, "\""); | error: literal with an empty format string - --> tests/ui/write_literal.rs:72:9 + --> tests/ui/write_literal.rs:80:9 | LL | / r#" +LL | | LL | | foo LL | | \ -LL | | \\ ... | LL | | bar LL | | "# @@ -171,6 +171,7 @@ LL | | "# help: try | LL ~ " +LL + LL + foo LL + \\ LL + \\\\ diff --git a/tests/ui/write_literal_2.rs b/tests/ui/write_literal_2.rs index b2ed552d46bc..f896782aaf3b 100644 --- a/tests/ui/write_literal_2.rs +++ b/tests/ui/write_literal_2.rs @@ -8,44 +8,58 @@ fn main() { let mut v = Vec::new(); writeln!(v, "{}", "{hello}"); - //~^ ERROR: literal with an empty format string - //~| NOTE: `-D clippy::write-literal` implied by `-D warnings` + //~^ write_literal + writeln!(v, r"{}", r"{hello}"); - //~^ ERROR: literal with an empty format string + //~^ write_literal + writeln!(v, "{}", '\''); - //~^ ERROR: literal with an empty format string + //~^ write_literal + writeln!(v, "{}", '"'); - //~^ ERROR: literal with an empty format string + //~^ write_literal + writeln!(v, r"{}", '"'); - //~^ ERROR: literal with an empty format string + //~^ write_literal + writeln!(v, r"{}", '\''); - //~^ ERROR: literal with an empty format string + //~^ write_literal + writeln!( v, "some {}", "hello \ + //~^ write_literal world!", - //~^^ ERROR: literal with an empty format string ); writeln!( v, "some {}\ {} \\ {}", - "1", "2", "3", + "1", + "2", + "3", + //~^^^ write_literal ); writeln!(v, "{}", "\\"); - //~^ ERROR: literal with an empty format string + //~^ write_literal + writeln!(v, r"{}", "\\"); - //~^ ERROR: literal with an empty format string + //~^ write_literal + writeln!(v, r#"{}"#, "\\"); - //~^ ERROR: literal with an empty format string + //~^ write_literal + writeln!(v, "{}", r"\"); - //~^ ERROR: literal with an empty format string + //~^ write_literal + writeln!(v, "{}", "\r"); - //~^ ERROR: literal with an empty format string + //~^ write_literal + // hard mode writeln!(v, r#"{}{}"#, '#', '"'); - //~^ ERROR: literal with an empty format string + //~^ write_literal + // should not lint writeln!(v, r"{}", "\r"); } diff --git a/tests/ui/write_literal_2.stderr b/tests/ui/write_literal_2.stderr index 9fba3ce548a0..29803d6a8b18 100644 --- a/tests/ui/write_literal_2.stderr +++ b/tests/ui/write_literal_2.stderr @@ -25,7 +25,7 @@ LL + writeln!(v, r"{{hello}}"); | error: literal with an empty format string - --> tests/ui/write_literal_2.rs:15:23 + --> tests/ui/write_literal_2.rs:16:23 | LL | writeln!(v, "{}", '\''); | ^^^^ @@ -37,7 +37,7 @@ LL + writeln!(v, "'"); | error: literal with an empty format string - --> tests/ui/write_literal_2.rs:17:23 + --> tests/ui/write_literal_2.rs:19:23 | LL | writeln!(v, "{}", '"'); | ^^^ @@ -49,13 +49,13 @@ LL + writeln!(v, "\""); | error: literal with an empty format string - --> tests/ui/write_literal_2.rs:19:24 + --> tests/ui/write_literal_2.rs:22:24 | LL | writeln!(v, r"{}", '"'); | ^^^ error: literal with an empty format string - --> tests/ui/write_literal_2.rs:21:24 + --> tests/ui/write_literal_2.rs:25:24 | LL | writeln!(v, r"{}", '\''); | ^^^^ @@ -67,23 +67,27 @@ LL + writeln!(v, r"'"); | error: literal with an empty format string - --> tests/ui/write_literal_2.rs:26:9 + --> tests/ui/write_literal_2.rs:31:9 | LL | / "hello \ +LL | | LL | | world!", | |_______________^ | help: try | LL ~ "some hello \ +LL + LL ~ world!", | error: literal with an empty format string - --> tests/ui/write_literal_2.rs:34:9 + --> tests/ui/write_literal_2.rs:39:9 | -LL | "1", "2", "3", - | ^^^^^^^^^^^^^ +LL | / "1", +LL | | "2", +LL | | "3", + | |___________^ | help: try | @@ -92,7 +96,7 @@ LL ~ 2 \\ 3", | error: literal with an empty format string - --> tests/ui/write_literal_2.rs:36:23 + --> tests/ui/write_literal_2.rs:44:23 | LL | writeln!(v, "{}", "\\"); | ^^^^ @@ -104,7 +108,7 @@ LL + writeln!(v, "\\"); | error: literal with an empty format string - --> tests/ui/write_literal_2.rs:38:24 + --> tests/ui/write_literal_2.rs:47:24 | LL | writeln!(v, r"{}", "\\"); | ^^^^ @@ -116,7 +120,7 @@ LL + writeln!(v, r"\"); | error: literal with an empty format string - --> tests/ui/write_literal_2.rs:40:26 + --> tests/ui/write_literal_2.rs:50:26 | LL | writeln!(v, r#"{}"#, "\\"); | ^^^^ @@ -128,7 +132,7 @@ LL + writeln!(v, r#"\"#); | error: literal with an empty format string - --> tests/ui/write_literal_2.rs:42:23 + --> tests/ui/write_literal_2.rs:53:23 | LL | writeln!(v, "{}", r"\"); | ^^^^ @@ -140,7 +144,7 @@ LL + writeln!(v, "\\"); | error: literal with an empty format string - --> tests/ui/write_literal_2.rs:44:23 + --> tests/ui/write_literal_2.rs:56:23 | LL | writeln!(v, "{}", "\r"); | ^^^^ @@ -152,7 +156,7 @@ LL + writeln!(v, "\r"); | error: literal with an empty format string - --> tests/ui/write_literal_2.rs:47:28 + --> tests/ui/write_literal_2.rs:60:28 | LL | writeln!(v, r#"{}{}"#, '#', '"'); | ^^^^^^^^ diff --git a/tests/ui/write_with_newline.fixed b/tests/ui/write_with_newline.fixed index 82afff5c81f5..40742bbbb427 100644 --- a/tests/ui/write_with_newline.fixed +++ b/tests/ui/write_with_newline.fixed @@ -10,16 +10,19 @@ fn main() { // These should fail writeln!(v, "Hello"); - //~^ ERROR: using `write!()` with a format string that ends in a single newline - //~| NOTE: `-D clippy::write-with-newline` implied by `-D warnings` + //~^ write_with_newline + writeln!(v, "Hello {}", "world"); - //~^ ERROR: using `write!()` with a format string that ends in a single newline + //~^ write_with_newline + writeln!(v, "Hello {} {}", "world", "#2"); - //~^ ERROR: using `write!()` with a format string that ends in a single newline + //~^ write_with_newline + writeln!(v, "{}", 1265); - //~^ ERROR: using `write!()` with a format string that ends in a single newline + //~^ write_with_newline + writeln!(v); - //~^ ERROR: using `write!()` with a format string that ends in a single newline + //~^ write_with_newline // These should be fine write!(v, ""); @@ -42,7 +45,8 @@ fn main() { // #3514 write!(v, "\\n"); writeln!(v, "\\"); - //~^ ERROR: using `write!()` with a format string that ends in a single newline + //~^ write_with_newline + write!(v, "\\\\n"); // Raw strings @@ -51,11 +55,11 @@ fn main() { // Literal newlines should also fail writeln!( - //~^ ERROR: using `write!()` with a format string that ends in a single newline + //~^ write_with_newline v ); writeln!( - //~^ ERROR: using `write!()` with a format string that ends in a single newline + //~^ write_with_newline v ); @@ -63,7 +67,8 @@ fn main() { write!(v, "\r\n"); write!(v, "foo\r\n"); writeln!(v, "\\r"); - //~^ ERROR: using `write!()` with a format string that ends in a single newline + //~^ write_with_newline + write!(v, "foo\rbar\n"); // Ignore expanded format strings diff --git a/tests/ui/write_with_newline.rs b/tests/ui/write_with_newline.rs index 96e4bf0fbc4b..ad6af69e7813 100644 --- a/tests/ui/write_with_newline.rs +++ b/tests/ui/write_with_newline.rs @@ -10,16 +10,19 @@ fn main() { // These should fail write!(v, "Hello\n"); - //~^ ERROR: using `write!()` with a format string that ends in a single newline - //~| NOTE: `-D clippy::write-with-newline` implied by `-D warnings` + //~^ write_with_newline + write!(v, "Hello {}\n", "world"); - //~^ ERROR: using `write!()` with a format string that ends in a single newline + //~^ write_with_newline + write!(v, "Hello {} {}\n", "world", "#2"); - //~^ ERROR: using `write!()` with a format string that ends in a single newline + //~^ write_with_newline + write!(v, "{}\n", 1265); - //~^ ERROR: using `write!()` with a format string that ends in a single newline + //~^ write_with_newline + write!(v, "\n"); - //~^ ERROR: using `write!()` with a format string that ends in a single newline + //~^ write_with_newline // These should be fine write!(v, ""); @@ -42,7 +45,8 @@ fn main() { // #3514 write!(v, "\\n"); write!(v, "\\\n"); - //~^ ERROR: using `write!()` with a format string that ends in a single newline + //~^ write_with_newline + write!(v, "\\\\n"); // Raw strings @@ -51,13 +55,13 @@ fn main() { // Literal newlines should also fail write!( - //~^ ERROR: using `write!()` with a format string that ends in a single newline + //~^ write_with_newline v, " " ); write!( - //~^ ERROR: using `write!()` with a format string that ends in a single newline + //~^ write_with_newline v, r" " @@ -67,7 +71,8 @@ fn main() { write!(v, "\r\n"); write!(v, "foo\r\n"); write!(v, "\\r\n"); - //~^ ERROR: using `write!()` with a format string that ends in a single newline + //~^ write_with_newline + write!(v, "foo\rbar\n"); // Ignore expanded format strings diff --git a/tests/ui/write_with_newline.stderr b/tests/ui/write_with_newline.stderr index 7eb741107a7b..7243b7943df0 100644 --- a/tests/ui/write_with_newline.stderr +++ b/tests/ui/write_with_newline.stderr @@ -25,7 +25,7 @@ LL + writeln!(v, "Hello {}", "world"); | error: using `write!()` with a format string that ends in a single newline - --> tests/ui/write_with_newline.rs:17:5 + --> tests/ui/write_with_newline.rs:18:5 | LL | write!(v, "Hello {} {}\n", "world", "#2"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + writeln!(v, "Hello {} {}", "world", "#2"); | error: using `write!()` with a format string that ends in a single newline - --> tests/ui/write_with_newline.rs:19:5 + --> tests/ui/write_with_newline.rs:21:5 | LL | write!(v, "{}\n", 1265); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + writeln!(v, "{}", 1265); | error: using `write!()` with a format string that ends in a single newline - --> tests/ui/write_with_newline.rs:21:5 + --> tests/ui/write_with_newline.rs:24:5 | LL | write!(v, "\n"); | ^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + writeln!(v); | error: using `write!()` with a format string that ends in a single newline - --> tests/ui/write_with_newline.rs:44:5 + --> tests/ui/write_with_newline.rs:47:5 | LL | write!(v, "\\\n"); | ^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + writeln!(v, "\\"); | error: using `write!()` with a format string that ends in a single newline - --> tests/ui/write_with_newline.rs:53:5 + --> tests/ui/write_with_newline.rs:57:5 | LL | / write!( LL | | @@ -91,7 +91,7 @@ LL ~ v | error: using `write!()` with a format string that ends in a single newline - --> tests/ui/write_with_newline.rs:59:5 + --> tests/ui/write_with_newline.rs:63:5 | LL | / write!( LL | | @@ -109,7 +109,7 @@ LL ~ v | error: using `write!()` with a format string that ends in a single newline - --> tests/ui/write_with_newline.rs:69:5 + --> tests/ui/write_with_newline.rs:73:5 | LL | write!(v, "\\r\n"); | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/writeln_empty_string.fixed b/tests/ui/writeln_empty_string.fixed index f6a7481f6422..5cb702b10f2d 100644 --- a/tests/ui/writeln_empty_string.fixed +++ b/tests/ui/writeln_empty_string.fixed @@ -7,9 +7,11 @@ fn main() { // These should fail writeln!(v); + //~^ writeln_empty_string let mut suggestion = Vec::new(); writeln!(suggestion); + //~^ writeln_empty_string // These should be fine writeln!(v); diff --git a/tests/ui/writeln_empty_string.rs b/tests/ui/writeln_empty_string.rs index 0297dba8c45d..e6478264a578 100644 --- a/tests/ui/writeln_empty_string.rs +++ b/tests/ui/writeln_empty_string.rs @@ -7,9 +7,11 @@ fn main() { // These should fail writeln!(v, ""); + //~^ writeln_empty_string let mut suggestion = Vec::new(); writeln!(suggestion, ""); + //~^ writeln_empty_string // These should be fine writeln!(v); diff --git a/tests/ui/writeln_empty_string.stderr b/tests/ui/writeln_empty_string.stderr index 20ece6a41926..43e76309ba64 100644 --- a/tests/ui/writeln_empty_string.stderr +++ b/tests/ui/writeln_empty_string.stderr @@ -10,7 +10,7 @@ LL | writeln!(v, ""); = help: to override `-D warnings` add `#[allow(clippy::writeln_empty_string)]` error: empty string literal in `writeln!` - --> tests/ui/writeln_empty_string.rs:12:5 + --> tests/ui/writeln_empty_string.rs:13:5 | LL | writeln!(suggestion, ""); | ^^^^^^^^^^^^^^^^^^^----^ diff --git a/tests/ui/wrong_self_convention.rs b/tests/ui/wrong_self_convention.rs index d7ed883b767c..840dfe7c6524 100644 --- a/tests/ui/wrong_self_convention.rs +++ b/tests/ui/wrong_self_convention.rs @@ -14,14 +14,15 @@ impl Foo { fn is_u32(&self) {} fn to_i32(self) {} fn from_i32(self) {} - //~^ ERROR: methods called `from_*` usually take no `self` + //~^ wrong_self_convention pub fn as_i64(self) {} pub fn into_i64(self) {} pub fn is_i64(self) {} pub fn to_i64(self) {} pub fn from_i64(self) {} - //~^ ERROR: methods called `from_*` usually take no `self` + //~^ wrong_self_convention + // check whether the lint can be allowed at the function level #[allow(clippy::wrong_self_convention)] pub fn from_cake(self) {} @@ -34,30 +35,38 @@ struct Bar; impl Bar { fn as_i32(self) {} - //~^ ERROR: methods called `as_*` usually take `self` by reference or `self` by mutabl + //~^ wrong_self_convention + fn as_u32(&self) {} fn into_i32(&self) {} - //~^ ERROR: methods called `into_*` usually take `self` by value + //~^ wrong_self_convention + fn into_u32(self) {} fn is_i32(self) {} - //~^ ERROR: methods called `is_*` usually take `self` by mutable reference or `self` b + //~^ wrong_self_convention + fn is_u32(&self) {} fn to_i32(self) {} - //~^ ERROR: methods with the following characteristics: (`to_*` and `self` type is not + //~^ wrong_self_convention + fn to_u32(&self) {} fn from_i32(self) {} - //~^ ERROR: methods called `from_*` usually take no `self` + //~^ wrong_self_convention pub fn as_i64(self) {} - //~^ ERROR: methods called `as_*` usually take `self` by reference or `self` by mutabl + //~^ wrong_self_convention + pub fn into_i64(&self) {} - //~^ ERROR: methods called `into_*` usually take `self` by value + //~^ wrong_self_convention + pub fn is_i64(self) {} - //~^ ERROR: methods called `is_*` usually take `self` by mutable reference or `self` b + //~^ wrong_self_convention + pub fn to_i64(self) {} - //~^ ERROR: methods with the following characteristics: (`to_*` and `self` type is not + //~^ wrong_self_convention + pub fn from_i64(self) {} - //~^ ERROR: methods called `from_*` usually take no `self` + //~^ wrong_self_convention // test for false positives fn as_(self) {} @@ -103,19 +112,23 @@ mod issue4037 { mod issue6307 { trait T: Sized { fn as_i32(self) {} - //~^ ERROR: methods called `as_*` usually take `self` by reference or `self` by mu + //~^ wrong_self_convention + fn as_u32(&self) {} fn into_i32(self) {} fn into_i32_ref(&self) {} - //~^ ERROR: methods called `into_*` usually take `self` by value + //~^ wrong_self_convention + fn into_u32(self) {} fn is_i32(self) {} - //~^ ERROR: methods called `is_*` usually take `self` by mutable reference or `sel + //~^ wrong_self_convention + fn is_u32(&self) {} fn to_i32(self) {} fn to_u32(&self) {} fn from_i32(self) {} - //~^ ERROR: methods called `from_*` usually take no `self` + //~^ wrong_self_convention + // check whether the lint can be allowed at the function level #[allow(clippy::wrong_self_convention)] fn from_cake(self) {} @@ -131,19 +144,23 @@ mod issue6307 { trait U { fn as_i32(self); - //~^ ERROR: methods called `as_*` usually take `self` by reference or `self` by mu + //~^ wrong_self_convention + fn as_u32(&self); fn into_i32(self); fn into_i32_ref(&self); - //~^ ERROR: methods called `into_*` usually take `self` by value + //~^ wrong_self_convention + fn into_u32(self); fn is_i32(self); - //~^ ERROR: methods called `is_*` usually take `self` by mutable reference or `sel + //~^ wrong_self_convention + fn is_u32(&self); fn to_i32(self); fn to_u32(&self); fn from_i32(self); - //~^ ERROR: methods called `from_*` usually take no `self` + //~^ wrong_self_convention + // check whether the lint can be allowed at the function level #[allow(clippy::wrong_self_convention)] fn from_cake(self); @@ -162,14 +179,16 @@ mod issue6307 { fn as_u32(&self); fn into_i32(self); fn into_i32_ref(&self); - //~^ ERROR: methods called `into_*` usually take `self` by value + //~^ wrong_self_convention + fn into_u32(self); fn is_i32(self); fn is_u32(&self); fn to_i32(self); fn to_u32(&self); fn from_i32(self); - //~^ ERROR: methods called `from_*` usually take no `self` + //~^ wrong_self_convention + // check whether the lint can be allowed at the function level #[allow(clippy::wrong_self_convention)] fn from_cake(self); @@ -194,7 +213,8 @@ mod issue6727 { } // trigger lint fn to_u64_v2(&self) -> u64 { - //~^ ERROR: methods with the following characteristics: (`to_*` and `self` type is + //~^ wrong_self_convention + 1 } } @@ -204,7 +224,8 @@ mod issue6727 { impl FooNoCopy { // trigger lint fn to_u64(self) -> u64 { - //~^ ERROR: methods with the following characteristics: (`to_*` and `self` type is + //~^ wrong_self_convention + 2 } fn to_u64_v2(&self) -> u64 { diff --git a/tests/ui/wrong_self_convention.stderr b/tests/ui/wrong_self_convention.stderr index 5c286721c478..e720ddf3fae1 100644 --- a/tests/ui/wrong_self_convention.stderr +++ b/tests/ui/wrong_self_convention.stderr @@ -17,7 +17,7 @@ LL | pub fn from_i64(self) {} = help: consider choosing a less ambiguous name error: methods called `as_*` usually take `self` by reference or `self` by mutable reference - --> tests/ui/wrong_self_convention.rs:36:15 + --> tests/ui/wrong_self_convention.rs:37:15 | LL | fn as_i32(self) {} | ^^^^ @@ -25,7 +25,7 @@ LL | fn as_i32(self) {} = help: consider choosing a less ambiguous name error: methods called `into_*` usually take `self` by value - --> tests/ui/wrong_self_convention.rs:39:17 + --> tests/ui/wrong_self_convention.rs:41:17 | LL | fn into_i32(&self) {} | ^^^^^ @@ -33,7 +33,7 @@ LL | fn into_i32(&self) {} = help: consider choosing a less ambiguous name error: methods called `is_*` usually take `self` by mutable reference or `self` by reference or no `self` - --> tests/ui/wrong_self_convention.rs:42:15 + --> tests/ui/wrong_self_convention.rs:45:15 | LL | fn is_i32(self) {} | ^^^^ @@ -41,7 +41,7 @@ LL | fn is_i32(self) {} = help: consider choosing a less ambiguous name error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference - --> tests/ui/wrong_self_convention.rs:45:15 + --> tests/ui/wrong_self_convention.rs:49:15 | LL | fn to_i32(self) {} | ^^^^ @@ -49,7 +49,7 @@ LL | fn to_i32(self) {} = help: consider choosing a less ambiguous name error: methods called `from_*` usually take no `self` - --> tests/ui/wrong_self_convention.rs:48:17 + --> tests/ui/wrong_self_convention.rs:53:17 | LL | fn from_i32(self) {} | ^^^^ @@ -57,7 +57,7 @@ LL | fn from_i32(self) {} = help: consider choosing a less ambiguous name error: methods called `as_*` usually take `self` by reference or `self` by mutable reference - --> tests/ui/wrong_self_convention.rs:51:19 + --> tests/ui/wrong_self_convention.rs:56:19 | LL | pub fn as_i64(self) {} | ^^^^ @@ -65,7 +65,7 @@ LL | pub fn as_i64(self) {} = help: consider choosing a less ambiguous name error: methods called `into_*` usually take `self` by value - --> tests/ui/wrong_self_convention.rs:53:21 + --> tests/ui/wrong_self_convention.rs:59:21 | LL | pub fn into_i64(&self) {} | ^^^^^ @@ -73,7 +73,7 @@ LL | pub fn into_i64(&self) {} = help: consider choosing a less ambiguous name error: methods called `is_*` usually take `self` by mutable reference or `self` by reference or no `self` - --> tests/ui/wrong_self_convention.rs:55:19 + --> tests/ui/wrong_self_convention.rs:62:19 | LL | pub fn is_i64(self) {} | ^^^^ @@ -81,7 +81,7 @@ LL | pub fn is_i64(self) {} = help: consider choosing a less ambiguous name error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference - --> tests/ui/wrong_self_convention.rs:57:19 + --> tests/ui/wrong_self_convention.rs:65:19 | LL | pub fn to_i64(self) {} | ^^^^ @@ -89,7 +89,7 @@ LL | pub fn to_i64(self) {} = help: consider choosing a less ambiguous name error: methods called `from_*` usually take no `self` - --> tests/ui/wrong_self_convention.rs:59:21 + --> tests/ui/wrong_self_convention.rs:68:21 | LL | pub fn from_i64(self) {} | ^^^^ @@ -97,7 +97,7 @@ LL | pub fn from_i64(self) {} = help: consider choosing a less ambiguous name error: methods called `as_*` usually take `self` by reference or `self` by mutable reference - --> tests/ui/wrong_self_convention.rs:105:19 + --> tests/ui/wrong_self_convention.rs:114:19 | LL | fn as_i32(self) {} | ^^^^ @@ -105,7 +105,7 @@ LL | fn as_i32(self) {} = help: consider choosing a less ambiguous name error: methods called `into_*` usually take `self` by value - --> tests/ui/wrong_self_convention.rs:109:25 + --> tests/ui/wrong_self_convention.rs:119:25 | LL | fn into_i32_ref(&self) {} | ^^^^^ @@ -113,7 +113,7 @@ LL | fn into_i32_ref(&self) {} = help: consider choosing a less ambiguous name error: methods called `is_*` usually take `self` by mutable reference or `self` by reference or no `self` - --> tests/ui/wrong_self_convention.rs:112:19 + --> tests/ui/wrong_self_convention.rs:123:19 | LL | fn is_i32(self) {} | ^^^^ @@ -121,7 +121,7 @@ LL | fn is_i32(self) {} = help: consider choosing a less ambiguous name error: methods called `from_*` usually take no `self` - --> tests/ui/wrong_self_convention.rs:117:21 + --> tests/ui/wrong_self_convention.rs:129:21 | LL | fn from_i32(self) {} | ^^^^ @@ -129,7 +129,7 @@ LL | fn from_i32(self) {} = help: consider choosing a less ambiguous name error: methods called `as_*` usually take `self` by reference or `self` by mutable reference - --> tests/ui/wrong_self_convention.rs:133:19 + --> tests/ui/wrong_self_convention.rs:146:19 | LL | fn as_i32(self); | ^^^^ @@ -137,7 +137,7 @@ LL | fn as_i32(self); = help: consider choosing a less ambiguous name error: methods called `into_*` usually take `self` by value - --> tests/ui/wrong_self_convention.rs:137:25 + --> tests/ui/wrong_self_convention.rs:151:25 | LL | fn into_i32_ref(&self); | ^^^^^ @@ -145,7 +145,7 @@ LL | fn into_i32_ref(&self); = help: consider choosing a less ambiguous name error: methods called `is_*` usually take `self` by mutable reference or `self` by reference or no `self` - --> tests/ui/wrong_self_convention.rs:140:19 + --> tests/ui/wrong_self_convention.rs:155:19 | LL | fn is_i32(self); | ^^^^ @@ -153,7 +153,7 @@ LL | fn is_i32(self); = help: consider choosing a less ambiguous name error: methods called `from_*` usually take no `self` - --> tests/ui/wrong_self_convention.rs:145:21 + --> tests/ui/wrong_self_convention.rs:161:21 | LL | fn from_i32(self); | ^^^^ @@ -161,7 +161,7 @@ LL | fn from_i32(self); = help: consider choosing a less ambiguous name error: methods called `into_*` usually take `self` by value - --> tests/ui/wrong_self_convention.rs:164:25 + --> tests/ui/wrong_self_convention.rs:181:25 | LL | fn into_i32_ref(&self); | ^^^^^ @@ -169,7 +169,7 @@ LL | fn into_i32_ref(&self); = help: consider choosing a less ambiguous name error: methods called `from_*` usually take no `self` - --> tests/ui/wrong_self_convention.rs:171:21 + --> tests/ui/wrong_self_convention.rs:189:21 | LL | fn from_i32(self); | ^^^^ @@ -177,7 +177,7 @@ LL | fn from_i32(self); = help: consider choosing a less ambiguous name error: methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value - --> tests/ui/wrong_self_convention.rs:196:22 + --> tests/ui/wrong_self_convention.rs:215:22 | LL | fn to_u64_v2(&self) -> u64 { | ^^^^^ @@ -185,7 +185,7 @@ LL | fn to_u64_v2(&self) -> u64 { = help: consider choosing a less ambiguous name error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference - --> tests/ui/wrong_self_convention.rs:206:19 + --> tests/ui/wrong_self_convention.rs:226:19 | LL | fn to_u64(self) -> u64 { | ^^^^ diff --git a/tests/ui/wrong_self_convention2.rs b/tests/ui/wrong_self_convention2.rs index 44b70f877be4..0a3e4982a49a 100644 --- a/tests/ui/wrong_self_convention2.rs +++ b/tests/ui/wrong_self_convention2.rs @@ -52,7 +52,8 @@ mod issue7179 { // lint pub fn from_be_self(self) -> Self { - //~^ ERROR: methods called `from_*` usually take no `self` + //~^ wrong_self_convention + S(i32::from_be(self.0)) } } @@ -62,7 +63,7 @@ mod issue7179 { fn from_be(s: Self) -> Self; // lint fn from_be_self(self) -> Self; - //~^ ERROR: methods called `from_*` usually take no `self` + //~^ wrong_self_convention } trait Foo: Sized { diff --git a/tests/ui/wrong_self_convention2.stderr b/tests/ui/wrong_self_convention2.stderr index 7aabdcd408c6..2eafb95d9bbe 100644 --- a/tests/ui/wrong_self_convention2.stderr +++ b/tests/ui/wrong_self_convention2.stderr @@ -9,7 +9,7 @@ LL | pub fn from_be_self(self) -> Self { = help: to override `-D warnings` add `#[allow(clippy::wrong_self_convention)]` error: methods called `from_*` usually take no `self` - --> tests/ui/wrong_self_convention2.rs:64:25 + --> tests/ui/wrong_self_convention2.rs:65:25 | LL | fn from_be_self(self) -> Self; | ^^^^ diff --git a/tests/ui/wrong_self_conventions_mut.rs b/tests/ui/wrong_self_conventions_mut.rs index 9169fc6d71f6..eb6f08fff424 100644 --- a/tests/ui/wrong_self_conventions_mut.rs +++ b/tests/ui/wrong_self_conventions_mut.rs @@ -12,7 +12,8 @@ mod issue6758 { impl Test { // If a method starts with `to_` and not ends with `_mut` it should expect `&self` pub fn to_many(&mut self) -> Option<&mut [T]> { - //~^ ERROR: methods with the following characteristics: (`to_*` and `self` type is + //~^ wrong_self_convention + match self { Self::Many(data) => Some(data), _ => None, @@ -21,7 +22,8 @@ mod issue6758 { // If a method starts with `to_` and ends with `_mut` it should expect `&mut self` pub fn to_many_mut(&self) -> Option<&[T]> { - //~^ ERROR: methods with the following characteristics: (`to_*` and `*_mut`) usual + //~^ wrong_self_convention + match self { Self::Many(data) => Some(data), _ => None, diff --git a/tests/ui/wrong_self_conventions_mut.stderr b/tests/ui/wrong_self_conventions_mut.stderr index f52a36632101..5ea2e8192efe 100644 --- a/tests/ui/wrong_self_conventions_mut.stderr +++ b/tests/ui/wrong_self_conventions_mut.stderr @@ -9,7 +9,7 @@ LL | pub fn to_many(&mut self) -> Option<&mut [T]> { = help: to override `-D warnings` add `#[allow(clippy::wrong_self_convention)]` error: methods with the following characteristics: (`to_*` and `*_mut`) usually take `self` by mutable reference - --> tests/ui/wrong_self_conventions_mut.rs:23:28 + --> tests/ui/wrong_self_conventions_mut.rs:24:28 | LL | pub fn to_many_mut(&self) -> Option<&[T]> { | ^^^^^ diff --git a/tests/ui/zero_div_zero.rs b/tests/ui/zero_div_zero.rs index 340ed5ef1339..79a309f49933 100644 --- a/tests/ui/zero_div_zero.rs +++ b/tests/ui/zero_div_zero.rs @@ -2,13 +2,17 @@ #[warn(clippy::zero_divided_by_zero)] fn main() { let nan = 0.0 / 0.0; - //~^ ERROR: constant division of `0.0` with `0.0` will always result in NaN + //~^ zero_divided_by_zero + let f64_nan = 0.0 / 0.0f64; - //~^ ERROR: constant division of `0.0` with `0.0` will always result in NaN + //~^ zero_divided_by_zero + let other_f64_nan = 0.0f64 / 0.0; - //~^ ERROR: constant division of `0.0` with `0.0` will always result in NaN + //~^ zero_divided_by_zero + let one_more_f64_nan = 0.0f64 / 0.0f64; - //~^ ERROR: constant division of `0.0` with `0.0` will always result in NaN + //~^ zero_divided_by_zero + let zero = 0.0; let other_zero = 0.0; let other_nan = zero / other_zero; // fine - this lint doesn't propagate constants. diff --git a/tests/ui/zero_div_zero.stderr b/tests/ui/zero_div_zero.stderr index 5294ebdfa5da..bcf752d7c26c 100644 --- a/tests/ui/zero_div_zero.stderr +++ b/tests/ui/zero_div_zero.stderr @@ -9,7 +9,7 @@ LL | let nan = 0.0 / 0.0; = help: to override `-D warnings` add `#[allow(clippy::zero_divided_by_zero)]` error: constant division of `0.0` with `0.0` will always result in NaN - --> tests/ui/zero_div_zero.rs:6:19 + --> tests/ui/zero_div_zero.rs:7:19 | LL | let f64_nan = 0.0 / 0.0f64; | ^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | let f64_nan = 0.0 / 0.0f64; = help: consider using `f64::NAN` if you would like a constant representing NaN error: constant division of `0.0` with `0.0` will always result in NaN - --> tests/ui/zero_div_zero.rs:8:25 + --> tests/ui/zero_div_zero.rs:10:25 | LL | let other_f64_nan = 0.0f64 / 0.0; | ^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | let other_f64_nan = 0.0f64 / 0.0; = help: consider using `f64::NAN` if you would like a constant representing NaN error: constant division of `0.0` with `0.0` will always result in NaN - --> tests/ui/zero_div_zero.rs:10:28 + --> tests/ui/zero_div_zero.rs:13:28 | LL | let one_more_f64_nan = 0.0f64 / 0.0f64; | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/zero_offset.rs b/tests/ui/zero_offset.rs index c7a69dee4b2d..bedb09536c53 100644 --- a/tests/ui/zero_offset.rs +++ b/tests/ui/zero_offset.rs @@ -3,24 +3,29 @@ fn main() { unsafe { let m = &mut () as *mut (); m.offset(0); - //~^ ERROR: offset calculation on zero-sized value - //~| NOTE: `#[deny(clippy::zst_offset)]` on by default + //~^ zst_offset + m.wrapping_add(0); - //~^ ERROR: offset calculation on zero-sized value + //~^ zst_offset + m.sub(0); - //~^ ERROR: offset calculation on zero-sized value + //~^ zst_offset + m.wrapping_sub(0); - //~^ ERROR: offset calculation on zero-sized value + //~^ zst_offset let c = &() as *const (); c.offset(0); - //~^ ERROR: offset calculation on zero-sized value + //~^ zst_offset + c.wrapping_add(0); - //~^ ERROR: offset calculation on zero-sized value + //~^ zst_offset + c.sub(0); - //~^ ERROR: offset calculation on zero-sized value + //~^ zst_offset + c.wrapping_sub(0); - //~^ ERROR: offset calculation on zero-sized value + //~^ zst_offset let sized = &1 as *const i32; sized.offset(0); diff --git a/tests/ui/zero_offset.stderr b/tests/ui/zero_offset.stderr index a1efe3904c18..b69c7b92d56a 100644 --- a/tests/ui/zero_offset.stderr +++ b/tests/ui/zero_offset.stderr @@ -13,37 +13,37 @@ LL | m.wrapping_add(0); | ^^^^^^^^^^^^^^^^^ error: offset calculation on zero-sized value - --> tests/ui/zero_offset.rs:10:9 + --> tests/ui/zero_offset.rs:11:9 | LL | m.sub(0); | ^^^^^^^^ error: offset calculation on zero-sized value - --> tests/ui/zero_offset.rs:12:9 + --> tests/ui/zero_offset.rs:14:9 | LL | m.wrapping_sub(0); | ^^^^^^^^^^^^^^^^^ error: offset calculation on zero-sized value - --> tests/ui/zero_offset.rs:16:9 + --> tests/ui/zero_offset.rs:18:9 | LL | c.offset(0); | ^^^^^^^^^^^ error: offset calculation on zero-sized value - --> tests/ui/zero_offset.rs:18:9 + --> tests/ui/zero_offset.rs:21:9 | LL | c.wrapping_add(0); | ^^^^^^^^^^^^^^^^^ error: offset calculation on zero-sized value - --> tests/ui/zero_offset.rs:20:9 + --> tests/ui/zero_offset.rs:24:9 | LL | c.sub(0); | ^^^^^^^^ error: offset calculation on zero-sized value - --> tests/ui/zero_offset.rs:22:9 + --> tests/ui/zero_offset.rs:27:9 | LL | c.wrapping_sub(0); | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/zero_ptr.fixed b/tests/ui/zero_ptr.fixed index 5d99bc9b757d..f2375d57f3a2 100644 --- a/tests/ui/zero_ptr.fixed +++ b/tests/ui/zero_ptr.fixed @@ -2,11 +2,16 @@ pub fn foo(_const: *const f32, _mut: *mut i64) {} fn main() { let _ = std::ptr::null::(); + //~^ zero_ptr let _ = std::ptr::null_mut::(); + //~^ zero_ptr let _: *const u8 = std::ptr::null(); + //~^ zero_ptr foo(0 as _, 0 as _); foo(std::ptr::null(), std::ptr::null_mut()); + //~^ zero_ptr + //~| zero_ptr let z = 0; let _ = z as *const usize; // this is currently not caught diff --git a/tests/ui/zero_ptr.rs b/tests/ui/zero_ptr.rs index 09d321c7a18d..ee01e426a43b 100644 --- a/tests/ui/zero_ptr.rs +++ b/tests/ui/zero_ptr.rs @@ -2,11 +2,16 @@ pub fn foo(_const: *const f32, _mut: *mut i64) {} fn main() { let _ = 0 as *const usize; + //~^ zero_ptr let _ = 0 as *mut f64; + //~^ zero_ptr let _: *const u8 = 0 as *const _; + //~^ zero_ptr foo(0 as _, 0 as _); foo(0 as *const _, 0 as *mut _); + //~^ zero_ptr + //~| zero_ptr let z = 0; let _ = z as *const usize; // this is currently not caught diff --git a/tests/ui/zero_ptr.stderr b/tests/ui/zero_ptr.stderr index a580bebd5d3a..8dc781f36258 100644 --- a/tests/ui/zero_ptr.stderr +++ b/tests/ui/zero_ptr.stderr @@ -8,25 +8,25 @@ LL | let _ = 0 as *const usize; = help: to override `-D warnings` add `#[allow(clippy::zero_ptr)]` error: `0 as *mut _` detected - --> tests/ui/zero_ptr.rs:5:13 + --> tests/ui/zero_ptr.rs:6:13 | LL | let _ = 0 as *mut f64; | ^^^^^^^^^^^^^ help: try: `std::ptr::null_mut::()` error: `0 as *const _` detected - --> tests/ui/zero_ptr.rs:6:24 + --> tests/ui/zero_ptr.rs:8:24 | LL | let _: *const u8 = 0 as *const _; | ^^^^^^^^^^^^^ help: try: `std::ptr::null()` error: `0 as *const _` detected - --> tests/ui/zero_ptr.rs:9:9 + --> tests/ui/zero_ptr.rs:12:9 | LL | foo(0 as *const _, 0 as *mut _); | ^^^^^^^^^^^^^ help: try: `std::ptr::null()` error: `0 as *mut _` detected - --> tests/ui/zero_ptr.rs:9:24 + --> tests/ui/zero_ptr.rs:12:24 | LL | foo(0 as *const _, 0 as *mut _); | ^^^^^^^^^^^ help: try: `std::ptr::null_mut()` diff --git a/tests/ui/zero_ptr_no_std.fixed b/tests/ui/zero_ptr_no_std.fixed index 25143eee8cc3..bbb2464e41d2 100644 --- a/tests/ui/zero_ptr_no_std.fixed +++ b/tests/ui/zero_ptr_no_std.fixed @@ -4,7 +4,10 @@ pub fn main(_argc: isize, _argv: *const *const u8) -> isize { let _ = core::ptr::null::(); + //~^ zero_ptr let _ = core::ptr::null_mut::(); + //~^ zero_ptr let _: *const u8 = core::ptr::null(); + //~^ zero_ptr 0 } diff --git a/tests/ui/zero_ptr_no_std.rs b/tests/ui/zero_ptr_no_std.rs index 965733b45d92..22fe2d24e4b1 100644 --- a/tests/ui/zero_ptr_no_std.rs +++ b/tests/ui/zero_ptr_no_std.rs @@ -4,7 +4,10 @@ pub fn main(_argc: isize, _argv: *const *const u8) -> isize { let _ = 0 as *const usize; + //~^ zero_ptr let _ = 0 as *mut f64; + //~^ zero_ptr let _: *const u8 = 0 as *const _; + //~^ zero_ptr 0 } diff --git a/tests/ui/zero_ptr_no_std.stderr b/tests/ui/zero_ptr_no_std.stderr index 014bf312bf32..77978d0a38b2 100644 --- a/tests/ui/zero_ptr_no_std.stderr +++ b/tests/ui/zero_ptr_no_std.stderr @@ -11,13 +11,13 @@ LL | #![deny(clippy::zero_ptr)] | ^^^^^^^^^^^^^^^^ error: `0 as *mut _` detected - --> tests/ui/zero_ptr_no_std.rs:7:13 + --> tests/ui/zero_ptr_no_std.rs:8:13 | LL | let _ = 0 as *mut f64; | ^^^^^^^^^^^^^ help: try: `core::ptr::null_mut::()` error: `0 as *const _` detected - --> tests/ui/zero_ptr_no_std.rs:8:24 + --> tests/ui/zero_ptr_no_std.rs:10:24 | LL | let _: *const u8 = 0 as *const _; | ^^^^^^^^^^^^^ help: try: `core::ptr::null()` diff --git a/tests/ui/zero_repeat_side_effects.fixed b/tests/ui/zero_repeat_side_effects.fixed index 989e8ae70e58..fb9d7880a4a7 100644 --- a/tests/ui/zero_repeat_side_effects.fixed +++ b/tests/ui/zero_repeat_side_effects.fixed @@ -16,27 +16,36 @@ fn main() { // on arrays f(); let a: [i32; 0] = []; + //~^ zero_repeat_side_effects let mut b; f(); b = [] as [i32; 0]; + //~^ zero_repeat_side_effects // on vecs // vecs dont support inferring value of consts f(); let c: std::vec::Vec = vec![]; + //~^ zero_repeat_side_effects let d; f(); d = vec![] as std::vec::Vec; + //~^ zero_repeat_side_effects // for macros println!("side effect"); let e: [(); 0] = []; + //~^ zero_repeat_side_effects // for nested calls { f() }; let g: [i32; 0] = []; + //~^ zero_repeat_side_effects // as function param drop({ f(); vec![] as std::vec::Vec }); + //~^ zero_repeat_side_effects // when singled out/not part of assignment/local { f(); vec![] as std::vec::Vec }; + //~^ zero_repeat_side_effects { f(); [] as [i32; 0] }; + //~^ zero_repeat_side_effects // should not trigger let a = [f(); N]; diff --git a/tests/ui/zero_repeat_side_effects.rs b/tests/ui/zero_repeat_side_effects.rs index 68511f41a95e..8b22ff840244 100644 --- a/tests/ui/zero_repeat_side_effects.rs +++ b/tests/ui/zero_repeat_side_effects.rs @@ -16,27 +16,36 @@ fn main() { // on arrays let a = [f(); 0]; + //~^ zero_repeat_side_effects let mut b; b = [f(); 0]; + //~^ zero_repeat_side_effects // on vecs // vecs dont support inferring value of consts let c = vec![f(); 0]; + //~^ zero_repeat_side_effects let d; d = vec![f(); 0]; + //~^ zero_repeat_side_effects // for macros let e = [println!("side effect"); 0]; + //~^ zero_repeat_side_effects // for nested calls let g = [{ f() }; 0]; + //~^ zero_repeat_side_effects // as function param drop(vec![f(); 0]); + //~^ zero_repeat_side_effects // when singled out/not part of assignment/local vec![f(); 0]; + //~^ zero_repeat_side_effects [f(); 0]; + //~^ zero_repeat_side_effects // should not trigger let a = [f(); N]; diff --git a/tests/ui/zero_repeat_side_effects.stderr b/tests/ui/zero_repeat_side_effects.stderr index d578e22b9716..2dba52e2112e 100644 --- a/tests/ui/zero_repeat_side_effects.stderr +++ b/tests/ui/zero_repeat_side_effects.stderr @@ -8,49 +8,49 @@ LL | let a = [f(); 0]; = help: to override `-D warnings` add `#[allow(clippy::zero_repeat_side_effects)]` error: function or method calls as the initial value in zero-sized array initializers may cause side effects - --> tests/ui/zero_repeat_side_effects.rs:20:5 + --> tests/ui/zero_repeat_side_effects.rs:21:5 | LL | b = [f(); 0]; | ^^^^^^^^^^^^ help: consider using: `f(); b = [] as [i32; 0]` error: function or method calls as the initial value in zero-sized array initializers may cause side effects - --> tests/ui/zero_repeat_side_effects.rs:24:5 + --> tests/ui/zero_repeat_side_effects.rs:26:5 | LL | let c = vec![f(); 0]; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f(); let c: std::vec::Vec = vec![];` error: function or method calls as the initial value in zero-sized array initializers may cause side effects - --> tests/ui/zero_repeat_side_effects.rs:26:5 + --> tests/ui/zero_repeat_side_effects.rs:29:5 | LL | d = vec![f(); 0]; | ^^^^^^^^^^^^^^^^ help: consider using: `f(); d = vec![] as std::vec::Vec` error: function or method calls as the initial value in zero-sized array initializers may cause side effects - --> tests/ui/zero_repeat_side_effects.rs:29:5 + --> tests/ui/zero_repeat_side_effects.rs:33:5 | LL | let e = [println!("side effect"); 0]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `println!("side effect"); let e: [(); 0] = [];` error: function or method calls as the initial value in zero-sized array initializers may cause side effects - --> tests/ui/zero_repeat_side_effects.rs:32:5 + --> tests/ui/zero_repeat_side_effects.rs:37:5 | LL | let g = [{ f() }; 0]; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `{ f() }; let g: [i32; 0] = [];` error: function or method calls as the initial value in zero-sized array initializers may cause side effects - --> tests/ui/zero_repeat_side_effects.rs:35:10 + --> tests/ui/zero_repeat_side_effects.rs:41:10 | LL | drop(vec![f(); 0]); | ^^^^^^^^^^^^ help: consider using: `{ f(); vec![] as std::vec::Vec }` error: function or method calls as the initial value in zero-sized array initializers may cause side effects - --> tests/ui/zero_repeat_side_effects.rs:38:5 + --> tests/ui/zero_repeat_side_effects.rs:45:5 | LL | vec![f(); 0]; | ^^^^^^^^^^^^ help: consider using: `{ f(); vec![] as std::vec::Vec }` error: function or method calls as the initial value in zero-sized array initializers may cause side effects - --> tests/ui/zero_repeat_side_effects.rs:39:5 + --> tests/ui/zero_repeat_side_effects.rs:47:5 | LL | [f(); 0]; | ^^^^^^^^ help: consider using: `{ f(); [] as [i32; 0] }` diff --git a/tests/ui/zero_sized_btreemap_values.rs b/tests/ui/zero_sized_btreemap_values.rs index 565f639201ff..cdeea15f28bc 100644 --- a/tests/ui/zero_sized_btreemap_values.rs +++ b/tests/ui/zero_sized_btreemap_values.rs @@ -3,28 +3,28 @@ use std::collections::BTreeMap; const CONST_OK: Option> = None; const CONST_NOT_OK: Option> = None; -//~^ ERROR: map with zero-sized value type +//~^ zero_sized_map_values static STATIC_OK: Option> = None; static STATIC_NOT_OK: Option> = None; -//~^ ERROR: map with zero-sized value type +//~^ zero_sized_map_values type OkMap = BTreeMap; type NotOkMap = BTreeMap; -//~^ ERROR: map with zero-sized value type +//~^ zero_sized_map_values enum TestEnum { Ok(BTreeMap), NotOk(BTreeMap), - //~^ ERROR: map with zero-sized value type + //~^ zero_sized_map_values } struct Test { ok: BTreeMap, not_ok: BTreeMap, - //~^ ERROR: map with zero-sized value type + //~^ zero_sized_map_values also_not_ok: Vec>, - //~^ ERROR: map with zero-sized value type + //~^ zero_sized_map_values } trait TestTrait { @@ -33,7 +33,7 @@ trait TestTrait { fn produce_output() -> Self::Output; fn weird_map(&self, map: BTreeMap); - //~^ ERROR: map with zero-sized value type + //~^ zero_sized_map_values } impl Test { @@ -42,7 +42,8 @@ impl Test { } fn not_ok(&self) -> BTreeMap { - //~^ ERROR: map with zero-sized value type + //~^ zero_sized_map_values + todo!() } } @@ -60,8 +61,9 @@ impl TestTrait for Test { } fn test(map: BTreeMap, key: &str) -> BTreeMap { - //~^ ERROR: map with zero-sized value type - //~| ERROR: map with zero-sized value type + //~^ zero_sized_map_values + //~| zero_sized_map_values + todo!(); } @@ -71,10 +73,11 @@ fn test2(map: BTreeMap, key: &str) -> BTreeMap { fn main() { let _: BTreeMap = BTreeMap::new(); - //~^ ERROR: map with zero-sized value type - //~| ERROR: map with zero-sized value type + //~^ zero_sized_map_values + //~| zero_sized_map_values + let _: BTreeMap = BTreeMap::new(); let _: BTreeMap<_, _> = std::iter::empty::<(String, ())>().collect(); - //~^ ERROR: map with zero-sized value type + //~^ zero_sized_map_values } diff --git a/tests/ui/zero_sized_btreemap_values.stderr b/tests/ui/zero_sized_btreemap_values.stderr index 65fc81e10e6c..40acb0b211f7 100644 --- a/tests/ui/zero_sized_btreemap_values.stderr +++ b/tests/ui/zero_sized_btreemap_values.stderr @@ -65,7 +65,7 @@ LL | fn not_ok(&self) -> BTreeMap { = help: consider using a set instead error: map with zero-sized value type - --> tests/ui/zero_sized_btreemap_values.rs:62:14 + --> tests/ui/zero_sized_btreemap_values.rs:63:14 | LL | fn test(map: BTreeMap, key: &str) -> BTreeMap { | ^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | fn test(map: BTreeMap, key: &str) -> BTreeMap { = help: consider using a set instead error: map with zero-sized value type - --> tests/ui/zero_sized_btreemap_values.rs:62:50 + --> tests/ui/zero_sized_btreemap_values.rs:63:50 | LL | fn test(map: BTreeMap, key: &str) -> BTreeMap { | ^^^^^^^^^^^^^^^^^^^^ @@ -81,7 +81,7 @@ LL | fn test(map: BTreeMap, key: &str) -> BTreeMap { = help: consider using a set instead error: map with zero-sized value type - --> tests/ui/zero_sized_btreemap_values.rs:73:35 + --> tests/ui/zero_sized_btreemap_values.rs:75:35 | LL | let _: BTreeMap = BTreeMap::new(); | ^^^^^^^^ @@ -89,7 +89,7 @@ LL | let _: BTreeMap = BTreeMap::new(); = help: consider using a set instead error: map with zero-sized value type - --> tests/ui/zero_sized_btreemap_values.rs:73:12 + --> tests/ui/zero_sized_btreemap_values.rs:75:12 | LL | let _: BTreeMap = BTreeMap::new(); | ^^^^^^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL | let _: BTreeMap = BTreeMap::new(); = help: consider using a set instead error: map with zero-sized value type - --> tests/ui/zero_sized_btreemap_values.rs:78:12 + --> tests/ui/zero_sized_btreemap_values.rs:81:12 | LL | let _: BTreeMap<_, _> = std::iter::empty::<(String, ())>().collect(); | ^^^^^^^^^^^^^^ diff --git a/tests/ui/zero_sized_hashmap_values.rs b/tests/ui/zero_sized_hashmap_values.rs index 5498261ee95a..4beeef421f30 100644 --- a/tests/ui/zero_sized_hashmap_values.rs +++ b/tests/ui/zero_sized_hashmap_values.rs @@ -3,28 +3,28 @@ use std::collections::HashMap; const CONST_OK: Option> = None; const CONST_NOT_OK: Option> = None; -//~^ ERROR: map with zero-sized value type +//~^ zero_sized_map_values static STATIC_OK: Option> = None; static STATIC_NOT_OK: Option> = None; -//~^ ERROR: map with zero-sized value type +//~^ zero_sized_map_values type OkMap = HashMap; type NotOkMap = HashMap; -//~^ ERROR: map with zero-sized value type +//~^ zero_sized_map_values enum TestEnum { Ok(HashMap), NotOk(HashMap), - //~^ ERROR: map with zero-sized value type + //~^ zero_sized_map_values } struct Test { ok: HashMap, not_ok: HashMap, - //~^ ERROR: map with zero-sized value type + //~^ zero_sized_map_values also_not_ok: Vec>, - //~^ ERROR: map with zero-sized value type + //~^ zero_sized_map_values } trait TestTrait { @@ -33,7 +33,7 @@ trait TestTrait { fn produce_output() -> Self::Output; fn weird_map(&self, map: HashMap); - //~^ ERROR: map with zero-sized value type + //~^ zero_sized_map_values } impl Test { @@ -42,7 +42,8 @@ impl Test { } fn not_ok(&self) -> HashMap { - //~^ ERROR: map with zero-sized value type + //~^ zero_sized_map_values + todo!() } } @@ -60,8 +61,9 @@ impl TestTrait for Test { } fn test(map: HashMap, key: &str) -> HashMap { - //~^ ERROR: map with zero-sized value type - //~| ERROR: map with zero-sized value type + //~^ zero_sized_map_values + //~| zero_sized_map_values + todo!(); } @@ -71,10 +73,11 @@ fn test2(map: HashMap, key: &str) -> HashMap { fn main() { let _: HashMap = HashMap::new(); - //~^ ERROR: map with zero-sized value type - //~| ERROR: map with zero-sized value type + //~^ zero_sized_map_values + //~| zero_sized_map_values + let _: HashMap = HashMap::new(); let _: HashMap<_, _> = std::iter::empty::<(String, ())>().collect(); - //~^ ERROR: map with zero-sized value type + //~^ zero_sized_map_values } diff --git a/tests/ui/zero_sized_hashmap_values.stderr b/tests/ui/zero_sized_hashmap_values.stderr index 08afef58a2aa..ed8536acfe8f 100644 --- a/tests/ui/zero_sized_hashmap_values.stderr +++ b/tests/ui/zero_sized_hashmap_values.stderr @@ -65,7 +65,7 @@ LL | fn not_ok(&self) -> HashMap { = help: consider using a set instead error: map with zero-sized value type - --> tests/ui/zero_sized_hashmap_values.rs:62:14 + --> tests/ui/zero_sized_hashmap_values.rs:63:14 | LL | fn test(map: HashMap, key: &str) -> HashMap { | ^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | fn test(map: HashMap, key: &str) -> HashMap { = help: consider using a set instead error: map with zero-sized value type - --> tests/ui/zero_sized_hashmap_values.rs:62:49 + --> tests/ui/zero_sized_hashmap_values.rs:63:49 | LL | fn test(map: HashMap, key: &str) -> HashMap { | ^^^^^^^^^^^^^^^^^^^ @@ -81,7 +81,7 @@ LL | fn test(map: HashMap, key: &str) -> HashMap { = help: consider using a set instead error: map with zero-sized value type - --> tests/ui/zero_sized_hashmap_values.rs:73:34 + --> tests/ui/zero_sized_hashmap_values.rs:75:34 | LL | let _: HashMap = HashMap::new(); | ^^^^^^^ @@ -89,7 +89,7 @@ LL | let _: HashMap = HashMap::new(); = help: consider using a set instead error: map with zero-sized value type - --> tests/ui/zero_sized_hashmap_values.rs:73:12 + --> tests/ui/zero_sized_hashmap_values.rs:75:12 | LL | let _: HashMap = HashMap::new(); | ^^^^^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL | let _: HashMap = HashMap::new(); = help: consider using a set instead error: map with zero-sized value type - --> tests/ui/zero_sized_hashmap_values.rs:78:12 + --> tests/ui/zero_sized_hashmap_values.rs:81:12 | LL | let _: HashMap<_, _> = std::iter::empty::<(String, ())>().collect(); | ^^^^^^^^^^^^^ diff --git a/tests/ui/zombie_processes.rs b/tests/ui/zombie_processes.rs index 6f0d2760a860..25bbc02ffb76 100644 --- a/tests/ui/zombie_processes.rs +++ b/tests/ui/zombie_processes.rs @@ -13,6 +13,7 @@ fn main() { { let mut x = Command::new("").spawn().unwrap(); //~^ zombie_processes + x.kill(); x.id(); } @@ -40,6 +41,7 @@ fn main() { { let mut x = Command::new("").spawn().unwrap(); //~^ zombie_processes + let v = &x; // (allow shared refs is fine because one cannot call `.wait()` through that) } @@ -65,6 +67,7 @@ fn main() { { let mut x = Command::new("").spawn().unwrap(); //~^ zombie_processes + if true { std::process::exit(0); } @@ -72,6 +75,7 @@ fn main() { { let mut x = Command::new("").spawn().unwrap(); //~^ zombie_processes + if true { while false {} // Calling `exit()` after leaving a while loop should still be linted. @@ -98,6 +102,7 @@ fn main() { { let mut x = Command::new("").spawn().unwrap(); //~^ zombie_processes + if true { return; } @@ -107,6 +112,7 @@ fn main() { { let mut x = Command::new("").spawn().unwrap(); //~^ zombie_processes + if true { x.wait().unwrap(); } @@ -115,6 +121,7 @@ fn main() { { let mut x = Command::new("").spawn().unwrap(); //~^ zombie_processes + if true { x.wait().unwrap(); } else { @@ -125,6 +132,7 @@ fn main() { { let mut x = Command::new("").spawn().unwrap(); //~^ zombie_processes + if true { // this else block exists to test the other help message } else { diff --git a/tests/ui/zombie_processes.stderr b/tests/ui/zombie_processes.stderr index afc518c60db2..0374d097b1b5 100644 --- a/tests/ui/zombie_processes.stderr +++ b/tests/ui/zombie_processes.stderr @@ -11,7 +11,7 @@ LL | let mut x = Command::new("").spawn().unwrap(); = help: to override `-D warnings` add `#[allow(clippy::zombie_processes)]` error: spawned process is never `wait()`ed on - --> tests/ui/zombie_processes.rs:41:21 + --> tests/ui/zombie_processes.rs:42:21 | LL | let mut x = Command::new("").spawn().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -21,7 +21,7 @@ LL | let mut x = Command::new("").spawn().unwrap(); = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning error: spawned process is never `wait()`ed on - --> tests/ui/zombie_processes.rs:66:21 + --> tests/ui/zombie_processes.rs:68:21 | LL | let mut x = Command::new("").spawn().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -31,7 +31,7 @@ LL | let mut x = Command::new("").spawn().unwrap(); = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning error: spawned process is never `wait()`ed on - --> tests/ui/zombie_processes.rs:73:21 + --> tests/ui/zombie_processes.rs:76:21 | LL | let mut x = Command::new("").spawn().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -41,18 +41,18 @@ LL | let mut x = Command::new("").spawn().unwrap(); = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning error: spawned process is not `wait()`ed on in all code paths - --> tests/ui/zombie_processes.rs:99:21 + --> tests/ui/zombie_processes.rs:103:21 | LL | let mut x = Command::new("").spawn().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: no `wait()` call exists on the code path to this early return - --> tests/ui/zombie_processes.rs:102:13 + --> tests/ui/zombie_processes.rs:107:13 | LL | return; | ^^^^^^ note: `wait()` call exists, but it is unreachable due to the early return - --> tests/ui/zombie_processes.rs:104:9 + --> tests/ui/zombie_processes.rs:109:9 | LL | x.wait().unwrap(); | ^ @@ -61,20 +61,20 @@ LL | x.wait().unwrap(); = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning error: spawned process is not `wait()`ed on in all code paths - --> tests/ui/zombie_processes.rs:108:21 + --> tests/ui/zombie_processes.rs:113:21 | LL | let mut x = Command::new("").spawn().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this if expression has a `wait()` call, but it is missing an else block - --> tests/ui/zombie_processes.rs:110:9 + --> tests/ui/zombie_processes.rs:116:9 | LL | / if true { LL | | x.wait().unwrap(); LL | | } | |_________^ note: `wait()` called here - --> tests/ui/zombie_processes.rs:111:13 + --> tests/ui/zombie_processes.rs:117:13 | LL | x.wait().unwrap(); | ^ @@ -83,13 +83,13 @@ LL | x.wait().unwrap(); = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning error: spawned process is not `wait()`ed on in all code paths - --> tests/ui/zombie_processes.rs:116:21 + --> tests/ui/zombie_processes.rs:122:21 | LL | let mut x = Command::new("").spawn().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `wait()` is not called in this if branch - --> tests/ui/zombie_processes.rs:120:10 + --> tests/ui/zombie_processes.rs:127:10 | LL | } else { | __________^ @@ -97,7 +97,7 @@ LL | | // this else block exists to test the other help message LL | | } | |_________^ note: `wait()` is called in the other branch - --> tests/ui/zombie_processes.rs:119:13 + --> tests/ui/zombie_processes.rs:126:13 | LL | x.wait().unwrap(); | ^ @@ -106,20 +106,20 @@ LL | x.wait().unwrap(); = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning error: spawned process is not `wait()`ed on in all code paths - --> tests/ui/zombie_processes.rs:126:21 + --> tests/ui/zombie_processes.rs:133:21 | LL | let mut x = Command::new("").spawn().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `wait()` is not called in this if branch - --> tests/ui/zombie_processes.rs:128:9 + --> tests/ui/zombie_processes.rs:136:9 | LL | / if true { LL | | // this else block exists to test the other help message LL | | } else { | |_________^ note: `wait()` is called in the other branch - --> tests/ui/zombie_processes.rs:131:13 + --> tests/ui/zombie_processes.rs:139:13 | LL | x.wait().unwrap(); | ^ diff --git a/tests/ui/zombie_processes_fixable.fixed b/tests/ui/zombie_processes_fixable.fixed index 6045262f519a..220abbfcfd7b 100644 --- a/tests/ui/zombie_processes_fixable.fixed +++ b/tests/ui/zombie_processes_fixable.fixed @@ -5,16 +5,20 @@ use std::process::{Child, Command}; fn main() { let _ = Command::new("").spawn().unwrap().wait(); - //~^ ERROR: spawned process is never `wait()`ed on + //~^ zombie_processes + Command::new("").spawn().unwrap().wait(); - //~^ ERROR: spawned process is never `wait()`ed on + //~^ zombie_processes + spawn_proc().wait(); - //~^ ERROR: spawned process is never `wait()`ed on + //~^ zombie_processes + spawn_proc().wait().unwrap(); // OK } fn not_main() { Command::new("").spawn().unwrap().wait(); + //~^ zombie_processes } fn spawn_proc() -> Child { diff --git a/tests/ui/zombie_processes_fixable.rs b/tests/ui/zombie_processes_fixable.rs index e1ecb771641e..820a839cd461 100644 --- a/tests/ui/zombie_processes_fixable.rs +++ b/tests/ui/zombie_processes_fixable.rs @@ -5,16 +5,20 @@ use std::process::{Child, Command}; fn main() { let _ = Command::new("").spawn().unwrap(); - //~^ ERROR: spawned process is never `wait()`ed on + //~^ zombie_processes + Command::new("").spawn().unwrap(); - //~^ ERROR: spawned process is never `wait()`ed on + //~^ zombie_processes + spawn_proc(); - //~^ ERROR: spawned process is never `wait()`ed on + //~^ zombie_processes + spawn_proc().wait().unwrap(); // OK } fn not_main() { Command::new("").spawn().unwrap(); + //~^ zombie_processes } fn spawn_proc() -> Child { diff --git a/tests/ui/zombie_processes_fixable.stderr b/tests/ui/zombie_processes_fixable.stderr index e1c40472c325..abc593fe4396 100644 --- a/tests/ui/zombie_processes_fixable.stderr +++ b/tests/ui/zombie_processes_fixable.stderr @@ -10,7 +10,7 @@ LL | let _ = Command::new("").spawn().unwrap(); = help: to override `-D warnings` add `#[allow(clippy::zombie_processes)]` error: spawned process is never `wait()`ed on - --> tests/ui/zombie_processes_fixable.rs:9:5 + --> tests/ui/zombie_processes_fixable.rs:10:5 | LL | Command::new("").spawn().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try: `.wait()` @@ -19,7 +19,7 @@ LL | Command::new("").spawn().unwrap(); = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning error: spawned process is never `wait()`ed on - --> tests/ui/zombie_processes_fixable.rs:11:5 + --> tests/ui/zombie_processes_fixable.rs:13:5 | LL | spawn_proc(); | ^^^^^^^^^^^^- help: try: `.wait()` @@ -28,7 +28,7 @@ LL | spawn_proc(); = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning error: spawned process is never `wait()`ed on - --> tests/ui/zombie_processes_fixable.rs:17:5 + --> tests/ui/zombie_processes_fixable.rs:20:5 | LL | Command::new("").spawn().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try: `.wait()` diff --git a/tests/ui/{literal_string_with_formatting_args}.rs b/tests/ui/{literal_string_with_formatting_args}.rs new file mode 100644 index 000000000000..3096558a516a --- /dev/null +++ b/tests/ui/{literal_string_with_formatting_args}.rs @@ -0,0 +1,48 @@ +//@check-pass + +// Regression test for . +// The `dbg` macro generates a literal with the name of the current file, so +// we need to ensure the lint is not emitted in this case. + +// Clippy sets `-Zflatten_format_args=no`, which changes the default behavior of how format args +// are lowered and only that one has this non-macro span. Adding the flag makes it repro on +// godbolt and shows a root context span for the file name string. +// +// So instead of having: +// +// ``` +// Lit( +// Spanned { +// node: Str( +// "[/app/example.rs:2:5] \"something\" = ", +// Cooked, +// ), +// span: /rustc/eb54a50837ad4bcc9842924f27e7287ca66e294c/library/std/src/macros.rs:365:35: 365:58 (#4), +// }, +// ), +// ``` +// +// We get: +// +// ``` +// Lit( +// Spanned { +// node: Str( +// "/app/example.rs", +// Cooked, +// ), +// span: /app/example.rs:2:5: 2:22 (#0), +// }, +// ) +// ``` + +#![crate_name = "foo"] +#![allow(unused)] +#![warn(clippy::literal_string_with_formatting_args)] + +fn another_bad() { + let literal_string_with_formatting_args = 0; + dbg!("something"); +} + +fn main() {} diff --git a/tests/versioncheck.rs b/tests/versioncheck.rs index ed357137095b..ea540d48a2b9 100644 --- a/tests/versioncheck.rs +++ b/tests/versioncheck.rs @@ -90,3 +90,9 @@ fn check_that_clippy_has_the_same_major_version_as_rustc() { }, } } + +#[test] +fn check_host_compiler() { + let version = rustc_tools_util::get_version_info!(); + assert_eq!(version.host_compiler, Some("nightly".to_string())); +} From a6a78e13e2b79d9f93e7a2d1a914ff9a6c0cb3ba Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 20 Feb 2025 21:23:38 +0100 Subject: [PATCH 060/745] Clippy: skip check_host_compiler check in rustc testsuite This test only makes sense to run in the Clippy repo In the Rust repo the name of the host_compiler is dev, not nightly --- tests/versioncheck.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/versioncheck.rs b/tests/versioncheck.rs index ea540d48a2b9..f6fc2354ca08 100644 --- a/tests/versioncheck.rs +++ b/tests/versioncheck.rs @@ -93,6 +93,11 @@ fn check_that_clippy_has_the_same_major_version_as_rustc() { #[test] fn check_host_compiler() { + // do not run this test inside the upstream rustc repo: + if option_env!("RUSTC_TEST_SUITE").is_some() { + return; + } + let version = rustc_tools_util::get_version_info!(); assert_eq!(version.host_compiler, Some("nightly".to_string())); } From 870f3952ac57f97cbb5f6d8cbd2d01e6ae3db7c5 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Fri, 21 Feb 2025 17:42:48 +0100 Subject: [PATCH 061/745] Fix link to ty::Ty in clippy_utils --- clippy_utils/src/ty/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index 2611fb8a78d8..6fdf4c244f8d 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -37,7 +37,7 @@ use crate::{def_path_def_ids, match_def_path, path_res}; mod type_certainty; pub use type_certainty::expr_type_is_certain; -/// Lower a [`hir::Ty`] to a [`rustc_middle::Ty`]. +/// Lower a [`hir::Ty`] to a [`rustc_middle::ty::Ty`]. pub fn ty_from_hir_ty<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { cx.maybe_typeck_results() .and_then(|results| { From 60e1d7ec2d6e7ae22c4f8f137a89024e34c6dd17 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 27 Feb 2025 12:52:08 +0100 Subject: [PATCH 062/745] Extend `{implicit,inverted}_saturating_sub` to expressions Side-effect free expressions are eligible to these lints, whereas previously only local variables were checked. --- clippy_lints/src/implicit_saturating_sub.rs | 65 +++++++++------------ tests/ui/implicit_saturating_sub.fixed | 24 ++++++++ tests/ui/implicit_saturating_sub.rs | 24 ++++++++ tests/ui/implicit_saturating_sub.stderr | 20 ++++++- tests/ui/manual_arithmetic_check-2.rs | 9 +++ tests/ui/manual_arithmetic_check-2.stderr | 38 +++++++++++- 6 files changed, 139 insertions(+), 41 deletions(-) diff --git a/clippy_lints/src/implicit_saturating_sub.rs b/clippy_lints/src/implicit_saturating_sub.rs index f2d16ff2e564..cbc3e2ccd5b8 100644 --- a/clippy_lints/src/implicit_saturating_sub.rs +++ b/clippy_lints/src/implicit_saturating_sub.rs @@ -1,14 +1,14 @@ use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::msrvs::{self, Msrv}; -use clippy_utils::source::snippet_opt; +use clippy_utils::sugg::{Sugg, make_binop}; use clippy_utils::{ - SpanlessEq, higher, is_in_const_context, is_integer_literal, path_to_local, peel_blocks, peel_blocks_with_stmt, + SpanlessEq, eq_expr_value, higher, is_in_const_context, is_integer_literal, peel_blocks, peel_blocks_with_stmt, }; use rustc_ast::ast::LitKind; use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; -use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, HirId, QPath}; +use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::Span; @@ -170,22 +170,20 @@ fn check_gt( cx: &LateContext<'_>, condition_span: Span, expr_span: Span, - big_var: &Expr<'_>, - little_var: &Expr<'_>, + big_expr: &Expr<'_>, + little_expr: &Expr<'_>, if_block: &Expr<'_>, else_block: &Expr<'_>, msrv: Msrv, is_composited: bool, ) { - if let Some(big_var) = Var::new(big_var) - && let Some(little_var) = Var::new(little_var) - { + if is_side_effect_free(cx, big_expr) && is_side_effect_free(cx, little_expr) { check_subtraction( cx, condition_span, expr_span, - big_var, - little_var, + big_expr, + little_expr, if_block, else_block, msrv, @@ -194,18 +192,8 @@ fn check_gt( } } -struct Var { - span: Span, - hir_id: HirId, -} - -impl Var { - fn new(expr: &Expr<'_>) -> Option { - path_to_local(expr).map(|hir_id| Self { - span: expr.span, - hir_id, - }) - } +fn is_side_effect_free(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + eq_expr_value(cx, expr, expr) } #[allow(clippy::too_many_arguments)] @@ -213,8 +201,8 @@ fn check_subtraction( cx: &LateContext<'_>, condition_span: Span, expr_span: Span, - big_var: Var, - little_var: Var, + big_expr: &Expr<'_>, + little_expr: &Expr<'_>, if_block: &Expr<'_>, else_block: &Expr<'_>, msrv: Msrv, @@ -234,8 +222,8 @@ fn check_subtraction( cx, condition_span, expr_span, - little_var, - big_var, + little_expr, + big_expr, else_block, if_block, msrv, @@ -247,17 +235,15 @@ fn check_subtraction( && let ExprKind::Binary(op, left, right) = if_block.kind && let BinOpKind::Sub = op.node { - let local_left = path_to_local(left); - let local_right = path_to_local(right); - if Some(big_var.hir_id) == local_left && Some(little_var.hir_id) == local_right { + if eq_expr_value(cx, left, big_expr) && eq_expr_value(cx, right, little_expr) { // This part of the condition is voluntarily split from the one before to ensure that // if `snippet_opt` fails, it won't try the next conditions. - if let Some(big_var_snippet) = snippet_opt(cx, big_var.span) - && let Some(little_var_snippet) = snippet_opt(cx, little_var.span) - && (!is_in_const_context(cx) || msrv.meets(cx, msrvs::SATURATING_SUB_CONST)) + if (!is_in_const_context(cx) || msrv.meets(cx, msrvs::SATURATING_SUB_CONST)) + && let Some(big_expr_sugg) = Sugg::hir_opt(cx, big_expr).map(Sugg::maybe_par) + && let Some(little_expr_sugg) = Sugg::hir_opt(cx, little_expr) { let sugg = format!( - "{}{big_var_snippet}.saturating_sub({little_var_snippet}){}", + "{}{big_expr_sugg}.saturating_sub({little_expr_sugg}){}", if is_composited { "{ " } else { "" }, if is_composited { " }" } else { "" } ); @@ -271,11 +257,12 @@ fn check_subtraction( Applicability::MachineApplicable, ); } - } else if Some(little_var.hir_id) == local_left - && Some(big_var.hir_id) == local_right - && let Some(big_var_snippet) = snippet_opt(cx, big_var.span) - && let Some(little_var_snippet) = snippet_opt(cx, little_var.span) + } else if eq_expr_value(cx, left, little_expr) + && eq_expr_value(cx, right, big_expr) + && let Some(big_expr_sugg) = Sugg::hir_opt(cx, big_expr) + && let Some(little_expr_sugg) = Sugg::hir_opt(cx, little_expr) { + let sugg = make_binop(BinOpKind::Sub, &big_expr_sugg, &little_expr_sugg); span_lint_and_then( cx, INVERTED_SATURATING_SUB, @@ -284,12 +271,12 @@ fn check_subtraction( |diag| { diag.span_note( if_block.span, - format!("this subtraction underflows when `{little_var_snippet} < {big_var_snippet}`"), + format!("this subtraction underflows when `{little_expr_sugg} < {big_expr_sugg}`"), ); diag.span_suggestion( if_block.span, "try replacing it with", - format!("{big_var_snippet} - {little_var_snippet}"), + format!("{sugg}"), Applicability::MaybeIncorrect, ); }, diff --git a/tests/ui/implicit_saturating_sub.fixed b/tests/ui/implicit_saturating_sub.fixed index 136238f9ecac..1aab6c54407e 100644 --- a/tests/ui/implicit_saturating_sub.fixed +++ b/tests/ui/implicit_saturating_sub.fixed @@ -228,3 +228,27 @@ fn regression_13524(a: usize, b: usize, c: bool) -> usize { 123 } else { b.saturating_sub(a) } } + +fn with_side_effect(a: u64) -> u64 { + println!("a = {a}"); + a +} + +fn arbitrary_expression() { + let (a, b) = (15u64, 20u64); + + let _ = (a * 2).saturating_sub(b); + //~^ implicit_saturating_sub + + let _ = a.saturating_sub(b * 2); + //~^ implicit_saturating_sub + + let _ = a.saturating_sub(b * 2); + //~^ implicit_saturating_sub + + let _ = if with_side_effect(a) > a { + with_side_effect(a) - a + } else { + 0 + }; +} diff --git a/tests/ui/implicit_saturating_sub.rs b/tests/ui/implicit_saturating_sub.rs index 140cf0338602..7ca57a2902db 100644 --- a/tests/ui/implicit_saturating_sub.rs +++ b/tests/ui/implicit_saturating_sub.rs @@ -302,3 +302,27 @@ fn regression_13524(a: usize, b: usize, c: bool) -> usize { b - a } } + +fn with_side_effect(a: u64) -> u64 { + println!("a = {a}"); + a +} + +fn arbitrary_expression() { + let (a, b) = (15u64, 20u64); + + let _ = if a * 2 > b { a * 2 - b } else { 0 }; + //~^ implicit_saturating_sub + + let _ = if a > b * 2 { a - b * 2 } else { 0 }; + //~^ implicit_saturating_sub + + let _ = if a < b * 2 { 0 } else { a - b * 2 }; + //~^ implicit_saturating_sub + + let _ = if with_side_effect(a) > a { + with_side_effect(a) - a + } else { + 0 + }; +} diff --git a/tests/ui/implicit_saturating_sub.stderr b/tests/ui/implicit_saturating_sub.stderr index f9c94d3ad841..0c225856fd07 100644 --- a/tests/ui/implicit_saturating_sub.stderr +++ b/tests/ui/implicit_saturating_sub.stderr @@ -220,5 +220,23 @@ LL | | b - a LL | | } | |_____^ help: replace it with: `{ b.saturating_sub(a) }` -error: aborting due to 24 previous errors +error: manual arithmetic check found + --> tests/ui/implicit_saturating_sub.rs:314:13 + | +LL | let _ = if a * 2 > b { a * 2 - b } else { 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `(a * 2).saturating_sub(b)` + +error: manual arithmetic check found + --> tests/ui/implicit_saturating_sub.rs:317:13 + | +LL | let _ = if a > b * 2 { a - b * 2 } else { 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b * 2)` + +error: manual arithmetic check found + --> tests/ui/implicit_saturating_sub.rs:320:13 + | +LL | let _ = if a < b * 2 { 0 } else { a - b * 2 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b * 2)` + +error: aborting due to 27 previous errors diff --git a/tests/ui/manual_arithmetic_check-2.rs b/tests/ui/manual_arithmetic_check-2.rs index 749d15f1cbd8..b094b2021b32 100644 --- a/tests/ui/manual_arithmetic_check-2.rs +++ b/tests/ui/manual_arithmetic_check-2.rs @@ -24,6 +24,15 @@ fn main() { let result = if b <= a { 0 } else { a - b }; //~^ inverted_saturating_sub + let result = if b * 2 <= a { 0 } else { a - b * 2 }; + //~^ inverted_saturating_sub + + let result = if b <= a * 2 { 0 } else { a * 2 - b }; + //~^ inverted_saturating_sub + + let result = if b + 3 <= a + 2 { 0 } else { (a + 2) - (b + 3) }; + //~^ inverted_saturating_sub + let af = 12f32; let bf = 13f32; // Should not lint! diff --git a/tests/ui/manual_arithmetic_check-2.stderr b/tests/ui/manual_arithmetic_check-2.stderr index 8841210befda..fb0f0da772c9 100644 --- a/tests/ui/manual_arithmetic_check-2.stderr +++ b/tests/ui/manual_arithmetic_check-2.stderr @@ -71,5 +71,41 @@ note: this subtraction underflows when `a < b` LL | let result = if b <= a { 0 } else { a - b }; | ^^^^^ -error: aborting due to 6 previous errors +error: inverted arithmetic check before subtraction + --> tests/ui/manual_arithmetic_check-2.rs:27:27 + | +LL | let result = if b * 2 <= a { 0 } else { a - b * 2 }; + | ^^ --------- help: try replacing it with: `b * 2 - a` + | +note: this subtraction underflows when `a < b * 2` + --> tests/ui/manual_arithmetic_check-2.rs:27:45 + | +LL | let result = if b * 2 <= a { 0 } else { a - b * 2 }; + | ^^^^^^^^^ + +error: inverted arithmetic check before subtraction + --> tests/ui/manual_arithmetic_check-2.rs:30:23 + | +LL | let result = if b <= a * 2 { 0 } else { a * 2 - b }; + | ^^ --------- help: try replacing it with: `b - a * 2` + | +note: this subtraction underflows when `a * 2 < b` + --> tests/ui/manual_arithmetic_check-2.rs:30:45 + | +LL | let result = if b <= a * 2 { 0 } else { a * 2 - b }; + | ^^^^^^^^^ + +error: inverted arithmetic check before subtraction + --> tests/ui/manual_arithmetic_check-2.rs:33:27 + | +LL | let result = if b + 3 <= a + 2 { 0 } else { (a + 2) - (b + 3) }; + | ^^ ----------------- help: try replacing it with: `b + 3 - (a + 2)` + | +note: this subtraction underflows when `a + 2 < b + 3` + --> tests/ui/manual_arithmetic_check-2.rs:33:49 + | +LL | let result = if b + 3 <= a + 2 { 0 } else { (a + 2) - (b + 3) }; + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors From 029a6db879382ab14614f744878c6d774e7bd33a Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 27 Feb 2025 13:19:06 +0100 Subject: [PATCH 063/745] Apply `implicit_saturating_sub` to Clippy sources --- clippy_lints/src/doc/mod.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index 0296ff13112f..c742d6abb5c2 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -1010,11 +1010,7 @@ fn check_doc<'a, Events: Iterator, Range range.start { - start - range.start - } else { - 0 - } + start.saturating_sub(range.start) } } else { 0 From c4d642616d8fb74d9884bdc0b8df270d13739de3 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 1 Mar 2025 04:47:36 +0100 Subject: [PATCH 064/745] Set target_vendor = "openwrt" On mips64-openwrt-linux-musl target. --- .../rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs | 1 + tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr | 2 +- tests/ui/check-cfg/exhaustive-names-values.feature.stderr | 2 +- tests/ui/check-cfg/exhaustive-names-values.full.stderr | 2 +- tests/ui/check-cfg/well-known-values.stderr | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs index 1300280e35b0..71b3fbe00b2f 100644 --- a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs @@ -23,6 +23,7 @@ pub(crate) fn target() -> Target { data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(), arch: "mips64".into(), options: TargetOptions { + vendor: "openwrt".into(), abi: "abi64".into(), endian: Endian::Big, mcount: "_mcount".into(), diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr index e7b8f3550576..b07d630e5f5d 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr @@ -14,7 +14,7 @@ warning: unexpected `cfg` condition value: `value` LL | #[cfg(target_vendor = "value")] | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` + = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `feature` diff --git a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr index 95af0a909299..80f8f36c23f7 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr @@ -15,7 +15,7 @@ warning: unexpected `cfg` condition value: `value` LL | #[cfg(target_vendor = "value")] | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` + = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `unk` diff --git a/tests/ui/check-cfg/exhaustive-names-values.full.stderr b/tests/ui/check-cfg/exhaustive-names-values.full.stderr index 95af0a909299..80f8f36c23f7 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.full.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.full.stderr @@ -15,7 +15,7 @@ warning: unexpected `cfg` condition value: `value` LL | #[cfg(target_vendor = "value")] | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` + = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `unk` diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index ba1900fcddb2..4636b6945d06 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -230,7 +230,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_vendor = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` + = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` From e15b9a09e8b4472e6b5ed768ae59cd387dbfddde Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 1 Mar 2025 09:01:21 +0100 Subject: [PATCH 065/745] Suggest using `#[expect]` to check lint positioning Using `#[allow]` will also apply to child HIR nodes, while `#[expect]` will ensure that the proper HIR node has been used for positioning the lint. --- clippy_utils/src/diagnostics.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_utils/src/diagnostics.rs b/clippy_utils/src/diagnostics.rs index ddb7a6635e06..292792408c64 100644 --- a/clippy_utils/src/diagnostics.rs +++ b/clippy_utils/src/diagnostics.rs @@ -85,7 +85,7 @@ fn validate_diag(diag: &Diag<'_, impl EmissionGuarantee>) { /// This is needed for `#[allow]` and `#[expect]` attributes to work on the node /// highlighted in the displayed warning. /// -/// If you're unsure which function you should use, you can test if the `#[allow]` attribute works +/// If you're unsure which function you should use, you can test if the `#[expect]` attribute works /// where you would expect it to. /// If it doesn't, you likely need to use [`span_lint_hir`] instead. /// @@ -128,7 +128,7 @@ pub fn span_lint(cx: &T, lint: &'static Lint, sp: impl Into( /// This is needed for `#[allow]` and `#[expect]` attributes to work on the node /// highlighted in the displayed warning. /// -/// If you're unsure which function you should use, you can test if the `#[allow]` attribute works +/// If you're unsure which function you should use, you can test if the `#[expect]` attribute works /// where you would expect it to. /// If it doesn't, you likely need to use [`span_lint_hir_and_then`] instead. /// @@ -241,7 +241,7 @@ pub fn span_lint_and_note( /// This is needed for `#[allow]` and `#[expect]` attributes to work on the node /// highlighted in the displayed warning. /// -/// If you're unsure which function you should use, you can test if the `#[allow]` attribute works +/// If you're unsure which function you should use, you can test if the `#[expect]` attribute works /// where you would expect it to. /// If it doesn't, you likely need to use [`span_lint_hir_and_then`] instead. pub fn span_lint_and_then(cx: &C, lint: &'static Lint, sp: S, msg: M, f: F) @@ -358,7 +358,7 @@ pub fn span_lint_hir_and_then( /// This is needed for `#[allow]` and `#[expect]` attributes to work on the node /// highlighted in the displayed warning. /// -/// If you're unsure which function you should use, you can test if the `#[allow]` attribute works +/// If you're unsure which function you should use, you can test if the `#[expect]` attribute works /// where you would expect it to. /// If it doesn't, you likely need to use [`span_lint_hir_and_then`] instead. /// From f94f64f5e84e5b55c39be795e4e2a8515bbca517 Mon Sep 17 00:00:00 2001 From: Jacher Date: Sat, 1 Jun 2024 15:44:27 +0000 Subject: [PATCH 066/745] new lint: `doc_comment_double_space_linebreak` fix typo change replacement character in example, remove extraneous space from suggested change add additional testcases; check doc comment not from expansion do not lint on macros, add more testcases fix wording, remove commented out code, add additonal testcase uibless fix doc comments, use optional snippets Remove unneeded additional space --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + .../doc/doc_comment_double_space_linebreak.rs | 41 ++++++++ clippy_lints/src/doc/mod.rs | 49 ++++++++++ .../doc_comment_double_space_linebreak.fixed | 94 +++++++++++++++++++ .../doc/doc_comment_double_space_linebreak.rs | 94 +++++++++++++++++++ .../doc_comment_double_space_linebreak.stderr | 76 +++++++++++++++ 7 files changed, 356 insertions(+) create mode 100644 clippy_lints/src/doc/doc_comment_double_space_linebreak.rs create mode 100644 tests/ui/doc/doc_comment_double_space_linebreak.fixed create mode 100644 tests/ui/doc/doc_comment_double_space_linebreak.rs create mode 100644 tests/ui/doc/doc_comment_double_space_linebreak.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 51441ab9fc0d..91608fb8d1e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5571,6 +5571,7 @@ Released 2018-09-13 [`disallowed_types`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types [`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression [`doc_include_without_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_include_without_cfg +[`doc_comment_double_space_linebreak`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_comment_double_space_linebreak [`doc_lazy_continuation`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_lazy_continuation [`doc_link_code`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_code [`doc_link_with_quotes`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_with_quotes diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 0834618499c7..586ee22d9ef7 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -138,6 +138,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS_INFO, crate::disallowed_types::DISALLOWED_TYPES_INFO, crate::doc::DOC_INCLUDE_WITHOUT_CFG_INFO, + crate::doc::DOC_COMMENT_DOUBLE_SPACE_LINEBREAK_INFO, crate::doc::DOC_LAZY_CONTINUATION_INFO, crate::doc::DOC_LINK_CODE_INFO, crate::doc::DOC_LINK_WITH_QUOTES_INFO, diff --git a/clippy_lints/src/doc/doc_comment_double_space_linebreak.rs b/clippy_lints/src/doc/doc_comment_double_space_linebreak.rs new file mode 100644 index 000000000000..4c2475ad8d85 --- /dev/null +++ b/clippy_lints/src/doc/doc_comment_double_space_linebreak.rs @@ -0,0 +1,41 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet_opt; +use rustc_errors::Applicability; +use rustc_lint::LateContext; +use rustc_span::Span; + +use super::DOC_COMMENT_DOUBLE_SPACE_LINEBREAK; + +pub fn check(cx: &LateContext<'_>, collected_breaks: &[Span]) { + let replacements: Vec<_> = collect_doc_replacements(cx, collected_breaks); + + if let Some((&(lo_span, _), &(hi_span, _))) = replacements.first().zip(replacements.last()) { + span_lint_and_then( + cx, + DOC_COMMENT_DOUBLE_SPACE_LINEBREAK, + lo_span.to(hi_span), + "doc comment uses two spaces for a hard line break", + |diag| { + diag.multipart_suggestion( + "replace this double space with a backslash", + replacements, + Applicability::MachineApplicable, + ); + }, + ); + } +} + +fn collect_doc_replacements(cx: &LateContext<'_>, spans: &[Span]) -> Vec<(Span, String)> { + spans + .iter() + .map(|span| { + // we already made sure the snippet exists when collecting spans + let s = snippet_opt(cx, *span).expect("snippet was already validated to exist"); + let after_newline = s.trim_start_matches(' '); + + let new_comment = format!("\\{after_newline}"); + (*span, new_comment) + }) + .collect() +} diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index c742d6abb5c2..d36ef10f4b94 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -7,6 +7,7 @@ use clippy_config::Conf; use clippy_utils::attrs::is_doc_hidden; use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_then}; use clippy_utils::macros::{is_panic, root_macro_call_first_node}; +use clippy_utils::source::snippet_opt; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::visitors::Visitable; use clippy_utils::{is_entrypoint_fn, is_trait_impl_item, method_chain_args}; @@ -33,6 +34,7 @@ use rustc_span::{Span, sym}; use std::ops::Range; use url::Url; +mod doc_comment_double_space_linebreak; mod include_in_doc_without_cfg; mod link_with_quotes; mod markdown; @@ -567,6 +569,38 @@ declare_clippy_lint! { "link reference defined in list item or quote" } +declare_clippy_lint! { + /// Detects doc comment linebreaks that use double spaces to separate lines, instead of back-slash (`\`). + /// + /// ### Why is this bad? + /// Double spaces, when used as doc comment linebreaks, can be difficult to see, and may + /// accidentally be removed during automatic formatting or manual refactoring. The use of a back-slash (`\`) + /// is clearer in this regard. + /// + /// ### Example + /// The two replacement dots in this example represent a double space. + /// ```no_run + /// /// This command takes two numbers as inputs and·· + /// /// adds them together, and then returns the result. + /// fn add(l: i32, r: i32) -> i32 { + /// l + r + /// } + /// ``` + /// + /// Use instead: + /// ```no_run + /// /// This command takes two numbers as inputs and\ + /// /// adds them together, and then returns the result. + /// fn add(l: i32, r: i32) -> i32 { + /// l + r + /// } + /// ``` + #[clippy::version = "1.80.0"] + pub DOC_COMMENT_DOUBLE_SPACE_LINEBREAK, + pedantic, + "double-space used for doc comment linebreak instead of `\\`" +} + pub struct Documentation { valid_idents: FxHashSet, check_private_items: bool, @@ -598,6 +632,7 @@ impl_lint_pass!(Documentation => [ DOC_OVERINDENTED_LIST_ITEMS, TOO_LONG_FIRST_DOC_PARAGRAPH, DOC_INCLUDE_WITHOUT_CFG, + DOC_COMMENT_DOUBLE_SPACE_LINEBREAK ]); impl EarlyLintPass for Documentation { @@ -737,6 +772,8 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet, attrs: &[ return None; } + suspicious_doc_comments::check(cx, attrs); + let (fragments, _) = attrs_to_doc_fragments( attrs.iter().filter_map(|attr| { if attr.doc_str_and_comment_kind().is_none() || attr.span().in_external_macro(cx.sess().source_map()) { @@ -894,6 +931,7 @@ fn check_doc<'a, Events: Iterator, Range = Vec::new(); let mut is_first_paragraph = true; let mut containers = Vec::new(); @@ -1069,6 +1107,14 @@ fn check_doc<'a, Events: Iterator, Range { paragraph_range.end = range.end; @@ -1119,6 +1165,9 @@ fn check_doc<'a, Events: Iterator, Range {} } } + + doc_comment_double_space_linebreak::check(cx, &collected_breaks); + headers } diff --git a/tests/ui/doc/doc_comment_double_space_linebreak.fixed b/tests/ui/doc/doc_comment_double_space_linebreak.fixed new file mode 100644 index 000000000000..efcd56809b7e --- /dev/null +++ b/tests/ui/doc/doc_comment_double_space_linebreak.fixed @@ -0,0 +1,94 @@ +#![feature(custom_inner_attributes)] +#![rustfmt::skip] + +#![warn(clippy::doc_comment_double_space_linebreak)] +#![allow(unused, clippy::empty_docs)] + +//! Should warn on double space linebreaks\ +//! in file/module doc comment + +/// Should not warn on single-line doc comments +fn single_line() {} + +/// Should not warn on single-line doc comments +/// split across multiple lines +fn single_line_split() {} + +// Should not warn on normal comments + +// note: cargo fmt can remove double spaces from normal and block comments +// Should not warn on normal comments +// with double spaces at the end of a line + +#[doc = "This is a doc attribute, which should not be linted"] +fn normal_comment() { + /* + Should not warn on block comments + */ + + /* + Should not warn on block comments + with double space at the end of a line + */ +} + +/// Should warn when doc comment uses double space\ +/// as a line-break, even when there are multiple\ +/// in a row +fn double_space_doc_comment() {} + +/// Should not warn when back-slash is used \ +/// as a line-break +fn back_slash_doc_comment() {} + +/// 🌹 are 🟥\ +/// 🌷 are 🟦\ +/// 📎 is 😎\ +/// and so are 🫵\ +/// (hopefully no formatting weirdness linting this) +fn multi_byte_chars_tada() {} + +macro_rules! macro_that_makes_function { + () => { + /// Shouldn't lint on this! + /// (hopefully) + fn my_macro_created_function() {} + } +} + +macro_that_makes_function!(); + +// dont lint when its alone on a line +/// +fn alone() {} + +/// | First column | Second column | +/// | ------------ | ------------- | +/// | Not a line | break when | +/// | after a line | in a table | +fn table() {} + +/// ```text +/// It's also not a hard line break if +/// there's two spaces at the end of a +/// line in a block code. +/// ``` +fn codeblock() {} + +/// It's also not a hard line break `if +/// there's` two spaces in the middle of inline code. +fn inline() {} + +/// It's also not a hard line break [when]( +/// https://example.com) in a URL. +fn url() {} + +/// here we mix\ +/// double spaces\ +/// and also\ +/// adding backslash\ +/// to some of them\ +/// to see how that looks +fn mixed() {} + +fn main() {} diff --git a/tests/ui/doc/doc_comment_double_space_linebreak.rs b/tests/ui/doc/doc_comment_double_space_linebreak.rs new file mode 100644 index 000000000000..c64eedc24289 --- /dev/null +++ b/tests/ui/doc/doc_comment_double_space_linebreak.rs @@ -0,0 +1,94 @@ +#![feature(custom_inner_attributes)] +#![rustfmt::skip] + +#![warn(clippy::doc_comment_double_space_linebreak)] +#![allow(unused, clippy::empty_docs)] + +//! Should warn on double space linebreaks +//! in file/module doc comment + +/// Should not warn on single-line doc comments +fn single_line() {} + +/// Should not warn on single-line doc comments +/// split across multiple lines +fn single_line_split() {} + +// Should not warn on normal comments + +// note: cargo fmt can remove double spaces from normal and block comments +// Should not warn on normal comments +// with double spaces at the end of a line + +#[doc = "This is a doc attribute, which should not be linted"] +fn normal_comment() { + /* + Should not warn on block comments + */ + + /* + Should not warn on block comments + with double space at the end of a line + */ +} + +/// Should warn when doc comment uses double space +/// as a line-break, even when there are multiple +/// in a row +fn double_space_doc_comment() {} + +/// Should not warn when back-slash is used \ +/// as a line-break +fn back_slash_doc_comment() {} + +/// 🌹 are 🟥 +/// 🌷 are 🟦 +/// 📎 is 😎 +/// and so are 🫵 +/// (hopefully no formatting weirdness linting this) +fn multi_byte_chars_tada() {} + +macro_rules! macro_that_makes_function { + () => { + /// Shouldn't lint on this! + /// (hopefully) + fn my_macro_created_function() {} + } +} + +macro_that_makes_function!(); + +// dont lint when its alone on a line +/// +fn alone() {} + +/// | First column | Second column | +/// | ------------ | ------------- | +/// | Not a line | break when | +/// | after a line | in a table | +fn table() {} + +/// ```text +/// It's also not a hard line break if +/// there's two spaces at the end of a +/// line in a block code. +/// ``` +fn codeblock() {} + +/// It's also not a hard line break `if +/// there's` two spaces in the middle of inline code. +fn inline() {} + +/// It's also not a hard line break [when]( +/// https://example.com) in a URL. +fn url() {} + +/// here we mix +/// double spaces\ +/// and also +/// adding backslash\ +/// to some of them +/// to see how that looks +fn mixed() {} + +fn main() {} diff --git a/tests/ui/doc/doc_comment_double_space_linebreak.stderr b/tests/ui/doc/doc_comment_double_space_linebreak.stderr new file mode 100644 index 000000000000..4c77f8e15034 --- /dev/null +++ b/tests/ui/doc/doc_comment_double_space_linebreak.stderr @@ -0,0 +1,76 @@ +error: doc comment uses two spaces for a hard line break + --> tests/ui/doc/doc_comment_double_space_linebreak.rs:7:43 + | +LL | //! Should warn on double space linebreaks + | ___________________________________________^ +LL | | //! in file/module doc comment + | |____^ + | + = note: `-D clippy::doc-comment-double-space-linebreak` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::doc_comment_double_space_linebreak)]` +help: replace this double space with a backslash + | +LL ~ //! Should warn on double space linebreaks\ +LL ~ //! in file/module doc comment + | + +error: doc comment uses two spaces for a hard line break + --> tests/ui/doc/doc_comment_double_space_linebreak.rs:35:51 + | +LL | /// Should warn when doc comment uses double space + | ___________________________________________________^ +LL | | /// as a line-break, even when there are multiple +LL | | /// in a row + | |____^ + | +help: replace this double space with a backslash + | +LL ~ /// Should warn when doc comment uses double space\ +LL ~ /// as a line-break, even when there are multiple\ +LL ~ /// in a row + | + +error: doc comment uses two spaces for a hard line break + --> tests/ui/doc/doc_comment_double_space_linebreak.rs:44:12 + | +LL | /// 🌹 are 🟥 + | ______________^ +LL | | /// 🌷 are 🟦 +LL | | /// 📎 is 😎 +LL | | /// and so are 🫵 +LL | | /// (hopefully no formatting weirdness linting this) + | |____^ + | +help: replace this double space with a backslash + | +LL ~ /// 🌹 are 🟥\ +LL ~ /// 🌷 are 🟦\ +LL ~ /// 📎 is 😎\ +LL ~ /// and so are 🫵\ +LL ~ /// (hopefully no formatting weirdness linting this) + | + +error: doc comment uses two spaces for a hard line break + --> tests/ui/doc/doc_comment_double_space_linebreak.rs:86:16 + | +LL | /// here we mix + | ________________^ +LL | | /// double spaces\ +LL | | /// and also +LL | | /// adding backslash\ +LL | | /// to some of them +LL | | /// to see how that looks + | |____^ + | +help: replace this double space with a backslash + | +LL ~ /// here we mix\ +LL ~ /// double spaces\ +LL ~ /// and also\ +LL ~ /// adding backslash\ +LL ~ /// to some of them\ +LL ~ /// to see how that looks + | + +error: aborting due to 4 previous errors + From 2fd51b8d3472cbb3384b68f52cc07a573085ffe4 Mon Sep 17 00:00:00 2001 From: Jacherr Date: Thu, 13 Feb 2025 16:45:43 +0000 Subject: [PATCH 067/745] `doc_comment_double_space_linebreaks`: lint per line instead of by block remove additional lint call fix fix lint defs --- CHANGELOG.md | 2 +- clippy_lints/src/declared_lints.rs | 2 +- .../doc/doc_comment_double_space_linebreak.rs | 37 ++------ clippy_lints/src/doc/mod.rs | 2 - .../doc_comment_double_space_linebreak.stderr | 93 ++++++++----------- 5 files changed, 51 insertions(+), 85 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91608fb8d1e1..94550f531ac4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5570,8 +5570,8 @@ Released 2018-09-13 [`disallowed_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_type [`disallowed_types`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types [`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression -[`doc_include_without_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_include_without_cfg [`doc_comment_double_space_linebreak`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_comment_double_space_linebreak +[`doc_include_without_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_include_without_cfg [`doc_lazy_continuation`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_lazy_continuation [`doc_link_code`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_code [`doc_link_with_quotes`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_with_quotes diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 586ee22d9ef7..a99c9ce46354 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -137,8 +137,8 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::disallowed_names::DISALLOWED_NAMES_INFO, crate::disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS_INFO, crate::disallowed_types::DISALLOWED_TYPES_INFO, - crate::doc::DOC_INCLUDE_WITHOUT_CFG_INFO, crate::doc::DOC_COMMENT_DOUBLE_SPACE_LINEBREAK_INFO, + crate::doc::DOC_INCLUDE_WITHOUT_CFG_INFO, crate::doc::DOC_LAZY_CONTINUATION_INFO, crate::doc::DOC_LINK_CODE_INFO, crate::doc::DOC_LINK_WITH_QUOTES_INFO, diff --git a/clippy_lints/src/doc/doc_comment_double_space_linebreak.rs b/clippy_lints/src/doc/doc_comment_double_space_linebreak.rs index 4c2475ad8d85..c50a987101a0 100644 --- a/clippy_lints/src/doc/doc_comment_double_space_linebreak.rs +++ b/clippy_lints/src/doc/doc_comment_double_space_linebreak.rs @@ -1,41 +1,20 @@ -use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::diagnostics::span_lint_and_sugg; use rustc_errors::Applicability; use rustc_lint::LateContext; -use rustc_span::Span; +use rustc_span::{BytePos, Span}; use super::DOC_COMMENT_DOUBLE_SPACE_LINEBREAK; pub fn check(cx: &LateContext<'_>, collected_breaks: &[Span]) { - let replacements: Vec<_> = collect_doc_replacements(cx, collected_breaks); - - if let Some((&(lo_span, _), &(hi_span, _))) = replacements.first().zip(replacements.last()) { - span_lint_and_then( + for r_span in collected_breaks { + span_lint_and_sugg( cx, DOC_COMMENT_DOUBLE_SPACE_LINEBREAK, - lo_span.to(hi_span), + r_span.with_hi(r_span.lo() + BytePos(2)), "doc comment uses two spaces for a hard line break", - |diag| { - diag.multipart_suggestion( - "replace this double space with a backslash", - replacements, - Applicability::MachineApplicable, - ); - }, + "replace this double space with a backslash", + "\\".to_owned(), + Applicability::MachineApplicable, ); } } - -fn collect_doc_replacements(cx: &LateContext<'_>, spans: &[Span]) -> Vec<(Span, String)> { - spans - .iter() - .map(|span| { - // we already made sure the snippet exists when collecting spans - let s = snippet_opt(cx, *span).expect("snippet was already validated to exist"); - let after_newline = s.trim_start_matches(' '); - - let new_comment = format!("\\{after_newline}"); - (*span, new_comment) - }) - .collect() -} diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index d36ef10f4b94..1317bbb47273 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -772,8 +772,6 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet, attrs: &[ return None; } - suspicious_doc_comments::check(cx, attrs); - let (fragments, _) = attrs_to_doc_fragments( attrs.iter().filter_map(|attr| { if attr.doc_str_and_comment_kind().is_none() || attr.span().in_external_macro(cx.sess().source_map()) { diff --git a/tests/ui/doc/doc_comment_double_space_linebreak.stderr b/tests/ui/doc/doc_comment_double_space_linebreak.stderr index 4c77f8e15034..dccec5b8c85e 100644 --- a/tests/ui/doc/doc_comment_double_space_linebreak.stderr +++ b/tests/ui/doc/doc_comment_double_space_linebreak.stderr @@ -1,76 +1,65 @@ error: doc comment uses two spaces for a hard line break --> tests/ui/doc/doc_comment_double_space_linebreak.rs:7:43 | -LL | //! Should warn on double space linebreaks - | ___________________________________________^ -LL | | //! in file/module doc comment - | |____^ +LL | //! Should warn on double space linebreaks + | ^^ help: replace this double space with a backslash: `\` | = note: `-D clippy::doc-comment-double-space-linebreak` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::doc_comment_double_space_linebreak)]` -help: replace this double space with a backslash - | -LL ~ //! Should warn on double space linebreaks\ -LL ~ //! in file/module doc comment - | error: doc comment uses two spaces for a hard line break --> tests/ui/doc/doc_comment_double_space_linebreak.rs:35:51 | -LL | /// Should warn when doc comment uses double space - | ___________________________________________________^ -LL | | /// as a line-break, even when there are multiple -LL | | /// in a row - | |____^ - | -help: replace this double space with a backslash - | -LL ~ /// Should warn when doc comment uses double space\ -LL ~ /// as a line-break, even when there are multiple\ -LL ~ /// in a row +LL | /// Should warn when doc comment uses double space + | ^^ help: replace this double space with a backslash: `\` + +error: doc comment uses two spaces for a hard line break + --> tests/ui/doc/doc_comment_double_space_linebreak.rs:36:50 | +LL | /// as a line-break, even when there are multiple + | ^^ help: replace this double space with a backslash: `\` error: doc comment uses two spaces for a hard line break --> tests/ui/doc/doc_comment_double_space_linebreak.rs:44:12 | -LL | /// 🌹 are 🟥 - | ______________^ -LL | | /// 🌷 are 🟦 -LL | | /// 📎 is 😎 -LL | | /// and so are 🫵 -LL | | /// (hopefully no formatting weirdness linting this) - | |____^ +LL | /// 🌹 are 🟥 + | ^^ help: replace this double space with a backslash: `\` + +error: doc comment uses two spaces for a hard line break + --> tests/ui/doc/doc_comment_double_space_linebreak.rs:45:12 | -help: replace this double space with a backslash +LL | /// 🌷 are 🟦 + | ^^ help: replace this double space with a backslash: `\` + +error: doc comment uses two spaces for a hard line break + --> tests/ui/doc/doc_comment_double_space_linebreak.rs:46:11 | -LL ~ /// 🌹 are 🟥\ -LL ~ /// 🌷 are 🟦\ -LL ~ /// 📎 is 😎\ -LL ~ /// and so are 🫵\ -LL ~ /// (hopefully no formatting weirdness linting this) +LL | /// 📎 is 😎 + | ^^ help: replace this double space with a backslash: `\` + +error: doc comment uses two spaces for a hard line break + --> tests/ui/doc/doc_comment_double_space_linebreak.rs:47:17 | +LL | /// and so are 🫵 + | ^^ help: replace this double space with a backslash: `\` error: doc comment uses two spaces for a hard line break --> tests/ui/doc/doc_comment_double_space_linebreak.rs:86:16 | -LL | /// here we mix - | ________________^ -LL | | /// double spaces\ -LL | | /// and also -LL | | /// adding backslash\ -LL | | /// to some of them -LL | | /// to see how that looks - | |____^ - | -help: replace this double space with a backslash - | -LL ~ /// here we mix\ -LL ~ /// double spaces\ -LL ~ /// and also\ -LL ~ /// adding backslash\ -LL ~ /// to some of them\ -LL ~ /// to see how that looks - | +LL | /// here we mix + | ^^ help: replace this double space with a backslash: `\` -error: aborting due to 4 previous errors +error: doc comment uses two spaces for a hard line break + --> tests/ui/doc/doc_comment_double_space_linebreak.rs:88:13 + | +LL | /// and also + | ^^ help: replace this double space with a backslash: `\` + +error: doc comment uses two spaces for a hard line break + --> tests/ui/doc/doc_comment_double_space_linebreak.rs:90:20 + | +LL | /// to some of them + | ^^ help: replace this double space with a backslash: `\` + +error: aborting due to 10 previous errors From 60191cfd5ba18ef83800e4599a9a7e073e12d1c9 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Sat, 1 Mar 2025 11:43:30 +0100 Subject: [PATCH 068/745] `doc_comment_double_space_linebreak`: Use multi spans and suggestions --- .../doc/doc_comment_double_space_linebreak.rs | 35 ++++++++---- .../doc_comment_double_space_linebreak.stderr | 55 +++++++------------ 2 files changed, 44 insertions(+), 46 deletions(-) diff --git a/clippy_lints/src/doc/doc_comment_double_space_linebreak.rs b/clippy_lints/src/doc/doc_comment_double_space_linebreak.rs index c50a987101a0..c9aee09f72e4 100644 --- a/clippy_lints/src/doc/doc_comment_double_space_linebreak.rs +++ b/clippy_lints/src/doc/doc_comment_double_space_linebreak.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::diagnostics::span_lint_and_then; use rustc_errors::Applicability; use rustc_lint::LateContext; use rustc_span::{BytePos, Span}; @@ -6,15 +6,28 @@ use rustc_span::{BytePos, Span}; use super::DOC_COMMENT_DOUBLE_SPACE_LINEBREAK; pub fn check(cx: &LateContext<'_>, collected_breaks: &[Span]) { - for r_span in collected_breaks { - span_lint_and_sugg( - cx, - DOC_COMMENT_DOUBLE_SPACE_LINEBREAK, - r_span.with_hi(r_span.lo() + BytePos(2)), - "doc comment uses two spaces for a hard line break", - "replace this double space with a backslash", - "\\".to_owned(), - Applicability::MachineApplicable, - ); + if collected_breaks.is_empty() { + return; } + + let breaks: Vec<_> = collected_breaks + .iter() + .map(|span| span.with_hi(span.lo() + BytePos(2))) + .collect(); + + span_lint_and_then( + cx, + DOC_COMMENT_DOUBLE_SPACE_LINEBREAK, + breaks.clone(), + "doc comment uses two spaces for a hard line break", + |diag| { + let suggs: Vec<_> = breaks.iter().map(|span| (*span, "\\".to_string())).collect(); + diag.tool_only_multipart_suggestion( + "replace this double space with a backslash:", + suggs, + Applicability::MachineApplicable, + ); + diag.help("replace this double space with a backslash: `\\`"); + }, + ); } diff --git a/tests/ui/doc/doc_comment_double_space_linebreak.stderr b/tests/ui/doc/doc_comment_double_space_linebreak.stderr index dccec5b8c85e..5a6171c837bd 100644 --- a/tests/ui/doc/doc_comment_double_space_linebreak.stderr +++ b/tests/ui/doc/doc_comment_double_space_linebreak.stderr @@ -2,8 +2,9 @@ error: doc comment uses two spaces for a hard line break --> tests/ui/doc/doc_comment_double_space_linebreak.rs:7:43 | LL | //! Should warn on double space linebreaks - | ^^ help: replace this double space with a backslash: `\` + | ^^ | + = help: replace this double space with a backslash: `\` = note: `-D clippy::doc-comment-double-space-linebreak` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::doc_comment_double_space_linebreak)]` @@ -11,55 +12,39 @@ error: doc comment uses two spaces for a hard line break --> tests/ui/doc/doc_comment_double_space_linebreak.rs:35:51 | LL | /// Should warn when doc comment uses double space - | ^^ help: replace this double space with a backslash: `\` - -error: doc comment uses two spaces for a hard line break - --> tests/ui/doc/doc_comment_double_space_linebreak.rs:36:50 - | + | ^^ LL | /// as a line-break, even when there are multiple - | ^^ help: replace this double space with a backslash: `\` + | ^^ + | + = help: replace this double space with a backslash: `\` error: doc comment uses two spaces for a hard line break --> tests/ui/doc/doc_comment_double_space_linebreak.rs:44:12 | LL | /// 🌹 are 🟥 - | ^^ help: replace this double space with a backslash: `\` - -error: doc comment uses two spaces for a hard line break - --> tests/ui/doc/doc_comment_double_space_linebreak.rs:45:12 - | + | ^^ LL | /// 🌷 are 🟦 - | ^^ help: replace this double space with a backslash: `\` - -error: doc comment uses two spaces for a hard line break - --> tests/ui/doc/doc_comment_double_space_linebreak.rs:46:11 - | + | ^^ LL | /// 📎 is 😎 - | ^^ help: replace this double space with a backslash: `\` - -error: doc comment uses two spaces for a hard line break - --> tests/ui/doc/doc_comment_double_space_linebreak.rs:47:17 - | + | ^^ LL | /// and so are 🫵 - | ^^ help: replace this double space with a backslash: `\` + | ^^ + | + = help: replace this double space with a backslash: `\` error: doc comment uses two spaces for a hard line break --> tests/ui/doc/doc_comment_double_space_linebreak.rs:86:16 | LL | /// here we mix - | ^^ help: replace this double space with a backslash: `\` - -error: doc comment uses two spaces for a hard line break - --> tests/ui/doc/doc_comment_double_space_linebreak.rs:88:13 - | + | ^^ +LL | /// double spaces\ LL | /// and also - | ^^ help: replace this double space with a backslash: `\` - -error: doc comment uses two spaces for a hard line break - --> tests/ui/doc/doc_comment_double_space_linebreak.rs:90:20 - | + | ^^ +LL | /// adding backslash\ LL | /// to some of them - | ^^ help: replace this double space with a backslash: `\` + | ^^ + | + = help: replace this double space with a backslash: `\` -error: aborting due to 10 previous errors +error: aborting due to 4 previous errors From 7fe160a60d58456dff82fec397d330f22cb00242 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Sat, 1 Mar 2025 11:50:26 +0100 Subject: [PATCH 069/745] Rename `doc_comment_double_space_linebreak` -> `doc_comment_double_space_linebreaks` --- CHANGELOG.md | 2 +- clippy_lints/src/declared_lints.rs | 2 +- ....rs => doc_comment_double_space_linebreaks.rs} | 4 ++-- clippy_lints/src/doc/mod.rs | 15 +++++++-------- ... => doc_comment_double_space_linebreaks.fixed} | 0 ....rs => doc_comment_double_space_linebreaks.rs} | 0 ...=> doc_comment_double_space_linebreaks.stderr} | 10 +++++----- 7 files changed, 16 insertions(+), 17 deletions(-) rename clippy_lints/src/doc/{doc_comment_double_space_linebreak.rs => doc_comment_double_space_linebreaks.rs} (90%) rename tests/ui/doc/{doc_comment_double_space_linebreak.fixed => doc_comment_double_space_linebreaks.fixed} (100%) rename tests/ui/doc/{doc_comment_double_space_linebreak.rs => doc_comment_double_space_linebreaks.rs} (100%) rename tests/ui/doc/{doc_comment_double_space_linebreak.stderr => doc_comment_double_space_linebreaks.stderr} (83%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94550f531ac4..0d42eaf53d44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5570,7 +5570,7 @@ Released 2018-09-13 [`disallowed_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_type [`disallowed_types`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types [`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression -[`doc_comment_double_space_linebreak`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_comment_double_space_linebreak +[`doc_comment_double_space_linebreaks`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_comment_double_space_linebreaks [`doc_include_without_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_include_without_cfg [`doc_lazy_continuation`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_lazy_continuation [`doc_link_code`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_code diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index a99c9ce46354..7092a282c882 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -137,7 +137,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::disallowed_names::DISALLOWED_NAMES_INFO, crate::disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS_INFO, crate::disallowed_types::DISALLOWED_TYPES_INFO, - crate::doc::DOC_COMMENT_DOUBLE_SPACE_LINEBREAK_INFO, + crate::doc::DOC_COMMENT_DOUBLE_SPACE_LINEBREAKS_INFO, crate::doc::DOC_INCLUDE_WITHOUT_CFG_INFO, crate::doc::DOC_LAZY_CONTINUATION_INFO, crate::doc::DOC_LINK_CODE_INFO, diff --git a/clippy_lints/src/doc/doc_comment_double_space_linebreak.rs b/clippy_lints/src/doc/doc_comment_double_space_linebreaks.rs similarity index 90% rename from clippy_lints/src/doc/doc_comment_double_space_linebreak.rs rename to clippy_lints/src/doc/doc_comment_double_space_linebreaks.rs index c9aee09f72e4..4cc027022333 100644 --- a/clippy_lints/src/doc/doc_comment_double_space_linebreak.rs +++ b/clippy_lints/src/doc/doc_comment_double_space_linebreaks.rs @@ -3,7 +3,7 @@ use rustc_errors::Applicability; use rustc_lint::LateContext; use rustc_span::{BytePos, Span}; -use super::DOC_COMMENT_DOUBLE_SPACE_LINEBREAK; +use super::DOC_COMMENT_DOUBLE_SPACE_LINEBREAKS; pub fn check(cx: &LateContext<'_>, collected_breaks: &[Span]) { if collected_breaks.is_empty() { @@ -17,7 +17,7 @@ pub fn check(cx: &LateContext<'_>, collected_breaks: &[Span]) { span_lint_and_then( cx, - DOC_COMMENT_DOUBLE_SPACE_LINEBREAK, + DOC_COMMENT_DOUBLE_SPACE_LINEBREAKS, breaks.clone(), "doc comment uses two spaces for a hard line break", |diag| { diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index 1317bbb47273..8e5682494e9e 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -1,8 +1,5 @@ #![allow(clippy::lint_without_lint_pass)] -mod lazy_continuation; -mod too_long_first_doc_paragraph; - use clippy_config::Conf; use clippy_utils::attrs::is_doc_hidden; use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_then}; @@ -34,13 +31,15 @@ use rustc_span::{Span, sym}; use std::ops::Range; use url::Url; -mod doc_comment_double_space_linebreak; +mod doc_comment_double_space_linebreaks; mod include_in_doc_without_cfg; +mod lazy_continuation; mod link_with_quotes; mod markdown; mod missing_headers; mod needless_doctest_main; mod suspicious_doc_comments; +mod too_long_first_doc_paragraph; declare_clippy_lint! { /// ### What it does @@ -595,8 +594,8 @@ declare_clippy_lint! { /// l + r /// } /// ``` - #[clippy::version = "1.80.0"] - pub DOC_COMMENT_DOUBLE_SPACE_LINEBREAK, + #[clippy::version = "1.87.0"] + pub DOC_COMMENT_DOUBLE_SPACE_LINEBREAKS, pedantic, "double-space used for doc comment linebreak instead of `\\`" } @@ -632,7 +631,7 @@ impl_lint_pass!(Documentation => [ DOC_OVERINDENTED_LIST_ITEMS, TOO_LONG_FIRST_DOC_PARAGRAPH, DOC_INCLUDE_WITHOUT_CFG, - DOC_COMMENT_DOUBLE_SPACE_LINEBREAK + DOC_COMMENT_DOUBLE_SPACE_LINEBREAKS ]); impl EarlyLintPass for Documentation { @@ -1164,7 +1163,7 @@ fn check_doc<'a, Events: Iterator, Range tests/ui/doc/doc_comment_double_space_linebreak.rs:7:43 + --> tests/ui/doc/doc_comment_double_space_linebreaks.rs:7:43 | LL | //! Should warn on double space linebreaks | ^^ | = help: replace this double space with a backslash: `\` = note: `-D clippy::doc-comment-double-space-linebreak` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::doc_comment_double_space_linebreak)]` + = help: to override `-D warnings` add `#[allow(clippy::doc_comment_double_space_linebreaks)]` error: doc comment uses two spaces for a hard line break - --> tests/ui/doc/doc_comment_double_space_linebreak.rs:35:51 + --> tests/ui/doc/doc_comment_double_space_linebreaks.rs:35:51 | LL | /// Should warn when doc comment uses double space | ^^ @@ -19,7 +19,7 @@ LL | /// as a line-break, even when there are multiple = help: replace this double space with a backslash: `\` error: doc comment uses two spaces for a hard line break - --> tests/ui/doc/doc_comment_double_space_linebreak.rs:44:12 + --> tests/ui/doc/doc_comment_double_space_linebreaks.rs:44:12 | LL | /// 🌹 are 🟥 | ^^ @@ -33,7 +33,7 @@ LL | /// and so are 🫵 = help: replace this double space with a backslash: `\` error: doc comment uses two spaces for a hard line break - --> tests/ui/doc/doc_comment_double_space_linebreak.rs:86:16 + --> tests/ui/doc/doc_comment_double_space_linebreaks.rs:86:16 | LL | /// here we mix | ^^ From 45e44878a7d57a8d64802341103a34cfac8f2704 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Sat, 1 Mar 2025 12:13:46 +0100 Subject: [PATCH 070/745] `doc_comment_double_space_linebreaks`: Fix tests --- clippy_lints/src/doc/mod.rs | 1 + .../doc_comment_double_space_linebreaks.fixed | 22 +++++++++++-------- .../doc_comment_double_space_linebreaks.rs | 22 +++++++++++-------- ...doc_comment_double_space_linebreaks.stderr | 10 ++++----- 4 files changed, 32 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index 8e5682494e9e..36fd396cc1df 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -569,6 +569,7 @@ declare_clippy_lint! { } declare_clippy_lint! { + /// ### What it does /// Detects doc comment linebreaks that use double spaces to separate lines, instead of back-slash (`\`). /// /// ### Why is this bad? diff --git a/tests/ui/doc/doc_comment_double_space_linebreaks.fixed b/tests/ui/doc/doc_comment_double_space_linebreaks.fixed index efcd56809b7e..6a616b2c7e18 100644 --- a/tests/ui/doc/doc_comment_double_space_linebreaks.fixed +++ b/tests/ui/doc/doc_comment_double_space_linebreaks.fixed @@ -1,9 +1,10 @@ #![feature(custom_inner_attributes)] #![rustfmt::skip] -#![warn(clippy::doc_comment_double_space_linebreak)] +#![warn(clippy::doc_comment_double_space_linebreaks)] #![allow(unused, clippy::empty_docs)] +//~v doc_comment_double_space_linebreaks //! Should warn on double space linebreaks\ //! in file/module doc comment @@ -22,16 +23,17 @@ fn single_line_split() {} #[doc = "This is a doc attribute, which should not be linted"] fn normal_comment() { - /* - Should not warn on block comments - */ - - /* - Should not warn on block comments - with double space at the end of a line - */ + /* + Should not warn on block comments + */ + + /* + Should not warn on block comments + with double space at the end of a line + */ } +//~v doc_comment_double_space_linebreaks /// Should warn when doc comment uses double space\ /// as a line-break, even when there are multiple\ /// in a row @@ -41,6 +43,7 @@ fn double_space_doc_comment() {} /// as a line-break fn back_slash_doc_comment() {} +//~v doc_comment_double_space_linebreaks /// 🌹 are 🟥\ /// 🌷 are 🟦\ /// 📎 is 😎\ @@ -83,6 +86,7 @@ fn inline() {} /// https://example.com) in a URL. fn url() {} +//~v doc_comment_double_space_linebreaks /// here we mix\ /// double spaces\ /// and also\ diff --git a/tests/ui/doc/doc_comment_double_space_linebreaks.rs b/tests/ui/doc/doc_comment_double_space_linebreaks.rs index c64eedc24289..e36cf7dea236 100644 --- a/tests/ui/doc/doc_comment_double_space_linebreaks.rs +++ b/tests/ui/doc/doc_comment_double_space_linebreaks.rs @@ -1,9 +1,10 @@ #![feature(custom_inner_attributes)] #![rustfmt::skip] -#![warn(clippy::doc_comment_double_space_linebreak)] +#![warn(clippy::doc_comment_double_space_linebreaks)] #![allow(unused, clippy::empty_docs)] +//~v doc_comment_double_space_linebreaks //! Should warn on double space linebreaks //! in file/module doc comment @@ -22,16 +23,17 @@ fn single_line_split() {} #[doc = "This is a doc attribute, which should not be linted"] fn normal_comment() { - /* - Should not warn on block comments - */ - - /* - Should not warn on block comments - with double space at the end of a line - */ + /* + Should not warn on block comments + */ + + /* + Should not warn on block comments + with double space at the end of a line + */ } +//~v doc_comment_double_space_linebreaks /// Should warn when doc comment uses double space /// as a line-break, even when there are multiple /// in a row @@ -41,6 +43,7 @@ fn double_space_doc_comment() {} /// as a line-break fn back_slash_doc_comment() {} +//~v doc_comment_double_space_linebreaks /// 🌹 are 🟥 /// 🌷 are 🟦 /// 📎 is 😎 @@ -83,6 +86,7 @@ fn inline() {} /// https://example.com) in a URL. fn url() {} +//~v doc_comment_double_space_linebreaks /// here we mix /// double spaces\ /// and also diff --git a/tests/ui/doc/doc_comment_double_space_linebreaks.stderr b/tests/ui/doc/doc_comment_double_space_linebreaks.stderr index 41b0790e5d3f..08c6956c3d00 100644 --- a/tests/ui/doc/doc_comment_double_space_linebreaks.stderr +++ b/tests/ui/doc/doc_comment_double_space_linebreaks.stderr @@ -1,15 +1,15 @@ error: doc comment uses two spaces for a hard line break - --> tests/ui/doc/doc_comment_double_space_linebreaks.rs:7:43 + --> tests/ui/doc/doc_comment_double_space_linebreaks.rs:8:43 | LL | //! Should warn on double space linebreaks | ^^ | = help: replace this double space with a backslash: `\` - = note: `-D clippy::doc-comment-double-space-linebreak` implied by `-D warnings` + = note: `-D clippy::doc-comment-double-space-linebreaks` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::doc_comment_double_space_linebreaks)]` error: doc comment uses two spaces for a hard line break - --> tests/ui/doc/doc_comment_double_space_linebreaks.rs:35:51 + --> tests/ui/doc/doc_comment_double_space_linebreaks.rs:37:51 | LL | /// Should warn when doc comment uses double space | ^^ @@ -19,7 +19,7 @@ LL | /// as a line-break, even when there are multiple = help: replace this double space with a backslash: `\` error: doc comment uses two spaces for a hard line break - --> tests/ui/doc/doc_comment_double_space_linebreaks.rs:44:12 + --> tests/ui/doc/doc_comment_double_space_linebreaks.rs:47:12 | LL | /// 🌹 are 🟥 | ^^ @@ -33,7 +33,7 @@ LL | /// and so are 🫵 = help: replace this double space with a backslash: `\` error: doc comment uses two spaces for a hard line break - --> tests/ui/doc/doc_comment_double_space_linebreaks.rs:86:16 + --> tests/ui/doc/doc_comment_double_space_linebreaks.rs:90:16 | LL | /// here we mix | ^^ From d395646a60f91ff40baebc9f0cd032cb182ea916 Mon Sep 17 00:00:00 2001 From: J-ZhengLi Date: Wed, 10 Jul 2024 11:34:24 +0800 Subject: [PATCH 071/745] fix [`undocumented_unsafe_blocks`] FP with trait/impl items --- .../src/undocumented_unsafe_blocks.rs | 82 +++++++++++-------- .../undocumented_unsafe_blocks.default.stderr | 42 +++++++++- ...undocumented_unsafe_blocks.disabled.stderr | 42 +++++++++- .../undocumented_unsafe_blocks.rs | 41 ++++++++++ 4 files changed, 171 insertions(+), 36 deletions(-) diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index 746bf018bcc3..917e7919c124 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -350,12 +350,13 @@ fn block_parents_have_safety_comment( let (span, hir_id) = match cx.tcx.parent_hir_node(id) { Node::Expr(expr) => match cx.tcx.parent_hir_node(expr.hir_id) { Node::LetStmt(hir::LetStmt { span, hir_id, .. }) => (*span, *hir_id), - Node::Item(hir::Item { - kind: ItemKind::Const(..) | ItemKind::Static(..), - span, - owner_id, - .. - }) => (*span, cx.tcx.local_def_id_to_hir_id(owner_id.def_id)), + + node if let Some((span, hir_id)) = span_and_hid_of_item_alike_node(&node) + && is_const_or_static(&node) => + { + (span, hir_id) + }, + _ => { if is_branchy(expr) { return false; @@ -371,12 +372,13 @@ fn block_parents_have_safety_comment( .. }) | Node::LetStmt(hir::LetStmt { span, hir_id, .. }) => (*span, *hir_id), - Node::Item(hir::Item { - kind: ItemKind::Const(..) | ItemKind::Static(..), - span, - owner_id, - .. - }) => (*span, cx.tcx.local_def_id_to_hir_id(owner_id.def_id)), + + node if let Some((span, hir_id)) = span_and_hid_of_item_alike_node(&node) + && is_const_or_static(&node) => + { + (span, hir_id) + }, + _ => return false, }; // if unsafe block is part of a let/const/static statement, @@ -604,31 +606,18 @@ fn span_from_macro_expansion_has_safety_comment(cx: &LateContext<'_>, span: Span fn get_body_search_span(cx: &LateContext<'_>) -> Option { let body = cx.enclosing_body?; - let mut span = cx.tcx.hir_body(body).value.span; - let mut maybe_global_var = false; - for (_, node) in cx.tcx.hir_parent_iter(body.hir_id) { - match node { - Node::Expr(e) => span = e.span, - Node::Block(_) | Node::Arm(_) | Node::Stmt(_) | Node::LetStmt(_) => (), - Node::Item(hir::Item { - kind: ItemKind::Const(..) | ItemKind::Static(..), - .. - }) => maybe_global_var = true, - Node::Item(hir::Item { - kind: ItemKind::Mod(_), - span: item_span, - .. - }) => { - span = *item_span; - break; + for (_, parent_node) in cx.tcx.hir_parent_iter(body.hir_id) { + match parent_node { + Node::Crate(mod_) => return Some(mod_.spans.inner_span), + node if let Some((span, _)) = span_and_hid_of_item_alike_node(&node) + && !is_const_or_static(&node) => + { + return Some(span); }, - Node::Crate(mod_) if maybe_global_var => { - span = mod_.spans.inner_span; - }, - _ => break, + _ => {}, } } - Some(span) + None } fn span_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool { @@ -717,3 +706,28 @@ fn text_has_safety_comment(src: &str, line_starts: &[RelativeBytePos], start_pos } } } + +fn span_and_hid_of_item_alike_node(node: &Node<'_>) -> Option<(Span, HirId)> { + match node { + Node::Item(item) => Some((item.span, item.owner_id.into())), + Node::TraitItem(ti) => Some((ti.span, ti.owner_id.into())), + Node::ImplItem(ii) => Some((ii.span, ii.owner_id.into())), + _ => None, + } +} + +fn is_const_or_static(node: &Node<'_>) -> bool { + matches!( + node, + Node::Item(hir::Item { + kind: ItemKind::Const(..) | ItemKind::Static(..), + .. + }) | Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::Const(..), + .. + }) | Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Const(..), + .. + }) + ) +} diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr index 32ed78151d23..d3585322bb92 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr @@ -310,5 +310,45 @@ LL | let bar = unsafe {}; | = help: consider adding a safety comment on the preceding line -error: aborting due to 35 previous errors +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:592:52 + | +LL | const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 0 }; + | ^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:601:41 + | +LL | const NO_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; + | ^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:611:42 + | +LL | const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 3 }; + | ^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:616:40 + | +LL | const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; + | ^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:627:9 + | +LL | unsafe { here_is_another_variable_with_long_name }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: aborting due to 40 previous errors diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr index 83a6986addf2..9ded7fb407a2 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr @@ -390,5 +390,45 @@ LL | unsafe {} | = help: consider adding a safety comment on the preceding line -error: aborting due to 45 previous errors +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:592:52 + | +LL | const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 0 }; + | ^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:601:41 + | +LL | const NO_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; + | ^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:611:42 + | +LL | const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 3 }; + | ^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:616:40 + | +LL | const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; + | ^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:627:9 + | +LL | unsafe { here_is_another_variable_with_long_name }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: aborting due to 50 previous errors diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs index 6a3fda3df5c3..582f31f3bba2 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs @@ -632,4 +632,45 @@ mod issue_11246 { // Safety: Another safety comment const FOO: () = unsafe {}; +// trait items and impl items +mod issue_11709 { + trait MyTrait { + const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 0 }; + //~^ ERROR: unsafe block missing a safety comment + + // SAFETY: safe + const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; + + // SAFETY: unrelated + unsafe fn unsafe_fn() {} + + const NO_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; + //~^ ERROR: unsafe block missing a safety comment + } + + struct UnsafeStruct; + + impl MyTrait for UnsafeStruct { + // SAFETY: safe in this impl + const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 2 }; + + const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 3 }; + //~^ ERROR: unsafe block missing a safety comment + } + + impl UnsafeStruct { + const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; + //~^ ERROR: unsafe block missing a safety comment + } +} + +fn issue_13024() { + let mut just_a_simple_variable_with_a_very_long_name_that_has_seventy_eight_characters = 0; + let here_is_another_variable_with_long_name = 100; + + // SAFETY: good + just_a_simple_variable_with_a_very_long_name_that_has_seventy_eight_characters = + unsafe { here_is_another_variable_with_long_name }; +} + fn main() {} From 91d20cbb82f041a31f747788567f884023cc322b Mon Sep 17 00:00:00 2001 From: yanglsh Date: Sat, 28 Dec 2024 00:19:20 -0700 Subject: [PATCH 072/745] Use inner span in `undocumented_unsafe_blocks` --- .../src/undocumented_unsafe_blocks.rs | 19 ++++++++++++++++++- .../undocumented_unsafe_blocks.default.stderr | 10 +++++----- ...undocumented_unsafe_blocks.disabled.stderr | 10 +++++----- .../undocumented_unsafe_blocks.rs | 1 + 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index 917e7919c124..cfb7246f2d24 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -606,15 +606,32 @@ fn span_from_macro_expansion_has_safety_comment(cx: &LateContext<'_>, span: Span fn get_body_search_span(cx: &LateContext<'_>) -> Option { let body = cx.enclosing_body?; + let mut maybe_mod_item = None; + for (_, parent_node) in cx.tcx.hir_parent_iter(body.hir_id) { match parent_node { Node::Crate(mod_) => return Some(mod_.spans.inner_span), + Node::Item(hir::Item { + kind: ItemKind::Mod(mod_), + span, + .. + }) => { + return maybe_mod_item + .and_then(|item| comment_start_before_item_in_mod(cx, mod_, *span, &item)) + .map(|comment_start| mod_.spans.inner_span.with_lo(comment_start)) + .or(Some(*span)); + }, node if let Some((span, _)) = span_and_hid_of_item_alike_node(&node) && !is_const_or_static(&node) => { return Some(span); }, - _ => {}, + Node::Item(item) => { + maybe_mod_item = Some(*item); + }, + _ => { + maybe_mod_item = None; + }, } } None diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr index d3585322bb92..1773babbfcfc 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr @@ -311,7 +311,7 @@ LL | let bar = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:592:52 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:638:52 | LL | const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 0 }; | ^^^^^^^^^^^^ @@ -319,7 +319,7 @@ LL | const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 0 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:601:41 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:647:41 | LL | const NO_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; | ^^^^^^^^^^^^ @@ -327,7 +327,7 @@ LL | const NO_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:611:42 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:657:42 | LL | const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 3 }; | ^^^^^^^^^^^^ @@ -335,7 +335,7 @@ LL | const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 3 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:616:40 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:662:40 | LL | const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; | ^^^^^^^^^^^^ @@ -343,7 +343,7 @@ LL | const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:627:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:673:9 | LL | unsafe { here_is_another_variable_with_long_name }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr index 9ded7fb407a2..494da37a5fb3 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr @@ -391,7 +391,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:592:52 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:638:52 | LL | const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 0 }; | ^^^^^^^^^^^^ @@ -399,7 +399,7 @@ LL | const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 0 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:601:41 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:647:41 | LL | const NO_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; | ^^^^^^^^^^^^ @@ -407,7 +407,7 @@ LL | const NO_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:611:42 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:657:42 | LL | const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 3 }; | ^^^^^^^^^^^^ @@ -415,7 +415,7 @@ LL | const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 3 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:616:40 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:662:40 | LL | const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; | ^^^^^^^^^^^^ @@ -423,7 +423,7 @@ LL | const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:627:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:673:9 | LL | unsafe { here_is_another_variable_with_long_name }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs index 582f31f3bba2..e6002c2d22ef 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs @@ -671,6 +671,7 @@ fn issue_13024() { // SAFETY: good just_a_simple_variable_with_a_very_long_name_that_has_seventy_eight_characters = unsafe { here_is_another_variable_with_long_name }; + //~^ undocumented_unsafe_blocks } fn main() {} From 3899488e5363f438c5373656ba70cbbe77b438a5 Mon Sep 17 00:00:00 2001 From: yanglsh Date: Tue, 18 Feb 2025 00:08:33 +0800 Subject: [PATCH 073/745] fix `undocumented_unsafe_blocks` FP in long assignment --- clippy_lints/src/undocumented_unsafe_blocks.rs | 8 ++++++-- .../undocumented_unsafe_blocks.default.stderr | 10 +--------- .../undocumented_unsafe_blocks.rs | 4 ++-- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index cfb7246f2d24..fcb3e4e6ab9e 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -349,8 +349,12 @@ fn block_parents_have_safety_comment( ) -> bool { let (span, hir_id) = match cx.tcx.parent_hir_node(id) { Node::Expr(expr) => match cx.tcx.parent_hir_node(expr.hir_id) { - Node::LetStmt(hir::LetStmt { span, hir_id, .. }) => (*span, *hir_id), - + Node::LetStmt(hir::LetStmt { span, hir_id, .. }) + | Node::Expr(hir::Expr { + hir_id, + kind: hir::ExprKind::Assign(_, _, span), + .. + }) => (*span, *hir_id), node if let Some((span, hir_id)) = span_and_hid_of_item_alike_node(&node) && is_const_or_static(&node) => { diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr index 1773babbfcfc..4357c455e50e 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr @@ -342,13 +342,5 @@ LL | const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; | = help: consider adding a safety comment on the preceding line -error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:673:9 - | -LL | unsafe { here_is_another_variable_with_long_name }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider adding a safety comment on the preceding line - -error: aborting due to 40 previous errors +error: aborting due to 39 previous errors diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs index e6002c2d22ef..f3546101c96b 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs @@ -668,10 +668,10 @@ fn issue_13024() { let mut just_a_simple_variable_with_a_very_long_name_that_has_seventy_eight_characters = 0; let here_is_another_variable_with_long_name = 100; - // SAFETY: good + // SAFETY: fail ONLY if `accept-comment-above-statement = false` just_a_simple_variable_with_a_very_long_name_that_has_seventy_eight_characters = unsafe { here_is_another_variable_with_long_name }; - //~^ undocumented_unsafe_blocks + //~[disabled]^ undocumented_unsafe_blocks } fn main() {} From d027ca95de8ebe3795d3a94304f654635a893c54 Mon Sep 17 00:00:00 2001 From: yanglsh Date: Tue, 18 Feb 2025 03:23:42 +0800 Subject: [PATCH 074/745] Add regression test for #11709 --- .../src/undocumented_unsafe_blocks.rs | 60 +++++++++++-------- ...undocumented_unsafe_blocks.disabled.stderr | 10 +++- .../undocumented_unsafe_blocks.rs | 29 +++++++++ 3 files changed, 72 insertions(+), 27 deletions(-) diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index fcb3e4e6ab9e..b824eb88abf9 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -339,6 +339,33 @@ fn is_unsafe_from_proc_macro(cx: &LateContext<'_>, span: Span) -> bool { .is_none_or(|src| !src.starts_with("unsafe")) } +fn find_unsafe_block_parent_in_expr<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx hir::Expr<'tcx>, +) -> Option<(Span, HirId)> { + match cx.tcx.parent_hir_node(expr.hir_id) { + Node::LetStmt(hir::LetStmt { span, hir_id, .. }) + | Node::Expr(hir::Expr { + hir_id, + kind: hir::ExprKind::Assign(_, _, span), + .. + }) => Some((*span, *hir_id)), + Node::Expr(expr) => find_unsafe_block_parent_in_expr(cx, expr), + node if let Some((span, hir_id)) = span_and_hid_of_item_alike_node(&node) + && is_const_or_static(&node) => + { + Some((span, hir_id)) + }, + + _ => { + if is_branchy(expr) { + return None; + } + Some((expr.span, expr.hir_id)) + }, + } +} + // Checks if any parent {expression, statement, block, local, const, static} // has a safety comment fn block_parents_have_safety_comment( @@ -348,26 +375,7 @@ fn block_parents_have_safety_comment( id: HirId, ) -> bool { let (span, hir_id) = match cx.tcx.parent_hir_node(id) { - Node::Expr(expr) => match cx.tcx.parent_hir_node(expr.hir_id) { - Node::LetStmt(hir::LetStmt { span, hir_id, .. }) - | Node::Expr(hir::Expr { - hir_id, - kind: hir::ExprKind::Assign(_, _, span), - .. - }) => (*span, *hir_id), - node if let Some((span, hir_id)) = span_and_hid_of_item_alike_node(&node) - && is_const_or_static(&node) => - { - (span, hir_id) - }, - - _ => { - if is_branchy(expr) { - return false; - } - (expr.span, expr.hir_id) - }, - }, + Node::Expr(expr) if let Some(inner) = find_unsafe_block_parent_in_expr(cx, expr) => inner, Node::Stmt(hir::Stmt { kind: hir::StmtKind::Let(hir::LetStmt { span, hir_id, .. }) @@ -433,12 +441,12 @@ fn block_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool { } fn include_attrs_in_span(cx: &LateContext<'_>, hir_id: HirId, span: Span) -> Span { - span.to(cx - .tcx - .hir() - .attrs(hir_id) - .iter() - .fold(span, |acc, attr| acc.to(attr.span()))) + span.to(cx.tcx.hir().attrs(hir_id).iter().fold(span, |acc, attr| { + if attr.is_doc_comment() { + return acc; + } + acc.to(attr.span()) + })) } enum HasSafetyComment { diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr index 494da37a5fb3..eb61e1e6da08 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr @@ -430,5 +430,13 @@ LL | unsafe { here_is_another_variable_with_long_name }; | = help: consider adding a safety comment on the preceding line -error: aborting due to 50 previous errors +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:702:9 + | +LL | unsafe { Date::__from_ordinal_date_unchecked(1970, 1) }.into_julian_day_just_make_this_line_longer(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: aborting due to 51 previous errors diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs index f3546101c96b..2492a3c2f562 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs @@ -674,4 +674,33 @@ fn issue_13024() { //~[disabled]^ undocumented_unsafe_blocks } +// https://docs.rs/time/0.3.36/src/time/offset_date_time.rs.html#35 +mod issue_11709_regression { + use std::num::NonZeroI32; + + struct Date { + value: NonZeroI32, + } + + impl Date { + const unsafe fn __from_ordinal_date_unchecked(year: i32, ordinal: u16) -> Self { + Self { + // Safety: The caller must guarantee that `ordinal` is not zero. + value: unsafe { NonZeroI32::new_unchecked((year << 9) | ordinal as i32) }, + } + } + + const fn into_julian_day_just_make_this_line_longer(self) -> i32 { + 42 + } + } + + /// The Julian day of the Unix epoch. + // SAFETY: fail ONLY if `accept-comment-above-attribute = false` + #[allow(unsafe_code)] + const UNIX_EPOCH_JULIAN_DAY: i32 = + unsafe { Date::__from_ordinal_date_unchecked(1970, 1) }.into_julian_day_just_make_this_line_longer(); + //~[disabled]^ undocumented_unsafe_blocks +} + fn main() {} From 6537f93b8b9c89d82e7339eed3821119e878c6c7 Mon Sep 17 00:00:00 2001 From: lapla-cogito Date: Sat, 1 Mar 2025 22:30:11 +0900 Subject: [PATCH 075/745] rename the MSRV alias `MANUAL_DIV_CEIL` to `DIV_CEIL` --- clippy_lints/src/manual_div_ceil.rs | 2 +- clippy_utils/src/msrvs.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/manual_div_ceil.rs b/clippy_lints/src/manual_div_ceil.rs index 9c1419175d55..9944c4f88048 100644 --- a/clippy_lints/src/manual_div_ceil.rs +++ b/clippy_lints/src/manual_div_ceil.rs @@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualDivCeil { && check_int_ty_and_feature(cx, div_lhs) && check_int_ty_and_feature(cx, div_rhs) && let ExprKind::Binary(inner_op, inner_lhs, inner_rhs) = div_lhs.kind - && self.msrv.meets(cx, msrvs::MANUAL_DIV_CEIL) + && self.msrv.meets(cx, msrvs::DIV_CEIL) { // (x + (y - 1)) / y if let ExprKind::Binary(sub_op, sub_lhs, sub_rhs) = inner_rhs.kind diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 5bb2b12988a6..523e7e5aaa69 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -33,7 +33,7 @@ msrv_aliases! { 1,76,0 { PTR_FROM_REF, OPTION_RESULT_INSPECT } 1,75,0 { OPTION_AS_SLICE } 1,74,0 { REPR_RUST, IO_ERROR_OTHER } - 1,73,0 { MANUAL_DIV_CEIL } + 1,73,0 { DIV_CEIL } 1,71,0 { TUPLE_ARRAY_CONVERSIONS, BUILD_HASHER_HASH_ONE } 1,70,0 { OPTION_RESULT_IS_VARIANT_AND, BINARY_HEAP_RETAIN } 1,68,0 { PATH_MAIN_SEPARATOR_STR } From cac9e0ab60c9c3498426a2a988d23ade483139bb Mon Sep 17 00:00:00 2001 From: Frank King Date: Wed, 5 Feb 2025 18:58:29 +0800 Subject: [PATCH 076/745] Implment `#[cfg]` and `#[cfg_attr]` in `where` clauses --- clippy_utils/src/ast_utils/mod.rs | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/clippy_utils/src/ast_utils/mod.rs b/clippy_utils/src/ast_utils/mod.rs index ab5f97199ce3..4f024ecaf29e 100644 --- a/clippy_utils/src/ast_utils/mod.rs +++ b/clippy_utils/src/ast_utils/mod.rs @@ -682,19 +682,20 @@ pub fn eq_generics(l: &Generics, r: &Generics) -> bool { pub fn eq_where_predicate(l: &WherePredicate, r: &WherePredicate) -> bool { use WherePredicateKind::*; - match (&l.kind, &r.kind) { - (BoundPredicate(l), BoundPredicate(r)) => { - over(&l.bound_generic_params, &r.bound_generic_params, |l, r| { - eq_generic_param(l, r) - }) && eq_ty(&l.bounded_ty, &r.bounded_ty) - && over(&l.bounds, &r.bounds, eq_generic_bound) - }, - (RegionPredicate(l), RegionPredicate(r)) => { - eq_id(l.lifetime.ident, r.lifetime.ident) && over(&l.bounds, &r.bounds, eq_generic_bound) - }, - (EqPredicate(l), EqPredicate(r)) => eq_ty(&l.lhs_ty, &r.lhs_ty) && eq_ty(&l.rhs_ty, &r.rhs_ty), - _ => false, - } + over(&l.attrs, &r.attrs, eq_attr) + && match (&l.kind, &r.kind) { + (BoundPredicate(l), BoundPredicate(r)) => { + over(&l.bound_generic_params, &r.bound_generic_params, |l, r| { + eq_generic_param(l, r) + }) && eq_ty(&l.bounded_ty, &r.bounded_ty) + && over(&l.bounds, &r.bounds, eq_generic_bound) + }, + (RegionPredicate(l), RegionPredicate(r)) => { + eq_id(l.lifetime.ident, r.lifetime.ident) && over(&l.bounds, &r.bounds, eq_generic_bound) + }, + (EqPredicate(l), EqPredicate(r)) => eq_ty(&l.lhs_ty, &r.lhs_ty) && eq_ty(&l.rhs_ty, &r.rhs_ty), + _ => false, + } } pub fn eq_use_tree(l: &UseTree, r: &UseTree) -> bool { From 5328983b077f98a41d6dc3c3af303ae4f3ecccf2 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 25 Feb 2025 19:08:03 +0000 Subject: [PATCH 077/745] Update `compiler-builtins` to 0.1.150 Includes a change to make a subset of math symbols available on all platforms [1], and disables `f16` on aarch64 without neon [2]. [1]: https://github.com/rust-lang/compiler-builtins/pull/763 [2]: https://github.com/rust-lang/compiler-builtins/pull/775 --- ...029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index bedc6ca11b3f..d8db7d63f2dd 100644 --- a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -16,8 +16,8 @@ index 7165c3e48af..968552ad435 100644 [dependencies] core = { path = "../core", public = true } --compiler_builtins = { version = "=0.1.148", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "=0.1.148", features = ['rustc-dep-of-std', 'no-f16-f128'] } +-compiler_builtins = { version = "=0.1.150", features = ['rustc-dep-of-std'] } ++compiler_builtins = { version = "=0.1.150", features = ['rustc-dep-of-std', 'no-f16-f128'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } From 33b78f2be1b71b282c952775e98265d177406701 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sun, 2 Mar 2025 05:03:55 +0000 Subject: [PATCH 078/745] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 9ab3d5a6e7f5..92f8fa089b0d 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -cb06d12710575a0d7ff71d6fe108f3bcff4f9195 +1c3b035542775e9a5decc93167d351b062942d32 From c40d30eb6ee63b32927cbed250c076e5e53db1b5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 2 Mar 2025 10:01:38 +0100 Subject: [PATCH 079/745] clippy --- src/tools/miri/cargo-miri/src/phases.rs | 2 +- src/tools/miri/src/eval.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs index d7b4421061c6..71ea07f34636 100644 --- a/src/tools/miri/cargo-miri/src/phases.rs +++ b/src/tools/miri/cargo-miri/src/phases.rs @@ -467,7 +467,7 @@ pub fn phase_rustc(mut args: impl Iterator, phase: RustcPhase) { if let Some(i) = val.iter().position(|&s| s == "link") { emit_link_hack = true; val.remove(i); - if !val.iter().any(|&s| s == "metadata") { + if !val.contains(&"metadata") { val.push("metadata"); } } diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index 36b15dbf623d..ed13f670a90e 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -434,7 +434,6 @@ pub fn create_ecx<'tcx>( /// Evaluates the entry function specified by `entry_id`. /// Returns `Some(return_code)` if program execution completed. /// Returns `None` if an evaluation error occurred. -#[expect(clippy::needless_lifetimes)] pub fn eval_entry<'tcx>( tcx: TyCtxt<'tcx>, entry_id: DefId, From d7d0abd2adfa15a0e8981408f91500b0509e982b Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 2 Mar 2025 15:02:14 +0100 Subject: [PATCH 080/745] Lint more cases of `ptr::eq()` Also, do not strip conversions of a function pointer to a `*const`, as no implicit conversion will take place. --- clippy_lints/src/operators/ptr_eq.rs | 33 ++++++++++++++++-------- tests/ui/ptr_eq.fixed | 20 ++++++++++++--- tests/ui/ptr_eq.rs | 12 +++++++++ tests/ui/ptr_eq.stderr | 38 +++++++++++++++++++++++++++- tests/ui/ptr_eq_no_std.fixed | 12 ++++++--- tests/ui/ptr_eq_no_std.rs | 4 +++ tests/ui/ptr_eq_no_std.stderr | 26 ++++++++++++++++++- 7 files changed, 124 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/operators/ptr_eq.rs b/clippy_lints/src/operators/ptr_eq.rs index 8118ad59bb71..79893c21a433 100644 --- a/clippy_lints/src/operators/ptr_eq.rs +++ b/clippy_lints/src/operators/ptr_eq.rs @@ -4,6 +4,7 @@ use clippy_utils::std_or_core; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::LateContext; +use rustc_middle::ty::{self, Ty}; use super::PTR_EQ; @@ -15,14 +16,21 @@ pub(super) fn check<'tcx>( right: &'tcx Expr<'_>, ) { if BinOpKind::Eq == op { + // Remove one level of usize conversion if any let (left, right) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) { (Some(lhs), Some(rhs)) => (lhs, rhs), _ => (left, right), }; - if let Some(left_var) = expr_as_cast_to_raw_pointer(cx, left) - && let Some(right_var) = expr_as_cast_to_raw_pointer(cx, right) - && let Some(left_snip) = left_var.span.get_source_text(cx) + // This lint concerns raw pointers + let (left_ty, right_ty) = (cx.typeck_results().expr_ty(left), cx.typeck_results().expr_ty(right)); + if !left_ty.is_raw_ptr() || !right_ty.is_raw_ptr() { + return; + } + + let (left_var, right_var) = (peel_raw_casts(cx, left, left_ty), peel_raw_casts(cx, right, right_ty)); + + if let Some(left_snip) = left_var.span.get_source_text(cx) && let Some(right_snip) = right_var.span.get_source_text(cx) { let Some(top_crate) = std_or_core(cx) else { return }; @@ -50,13 +58,16 @@ fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_> None } -// If the given expression is a cast to a `*const` pointer, return the lhs of the cast -// E.g., `foo as *const _` returns `foo`. -fn expr_as_cast_to_raw_pointer<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { - if cx.typeck_results().expr_ty(cast_expr).is_raw_ptr() { - if let ExprKind::Cast(expr, _) = cast_expr.kind { - return Some(expr); - } +// Peel raw casts if the remaining expression can be coerced to it +fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty: Ty<'tcx>) -> &'tcx Expr<'tcx> { + if let ExprKind::Cast(inner, _) = expr.kind + && let ty::RawPtr(target_ty, _) = expr_ty.kind() + && let inner_ty = cx.typeck_results().expr_ty(inner) + && let ty::RawPtr(inner_target_ty, _) | ty::Ref(_, inner_target_ty, _) = inner_ty.kind() + && target_ty == inner_target_ty + { + peel_raw_casts(cx, inner, inner_ty) + } else { + expr } - None } diff --git a/tests/ui/ptr_eq.fixed b/tests/ui/ptr_eq.fixed index 1ccd2c2237de..2111067d49fb 100644 --- a/tests/ui/ptr_eq.fixed +++ b/tests/ui/ptr_eq.fixed @@ -20,8 +20,10 @@ fn main() { //~^ ptr_eq let _ = std::ptr::eq(a, b); //~^ ptr_eq - let _ = a.as_ptr() == b as *const _; - let _ = a.as_ptr() == b.as_ptr(); + let _ = std::ptr::eq(a.as_ptr(), b as *const _); + //~^ ptr_eq + let _ = std::ptr::eq(a.as_ptr(), b.as_ptr()); + //~^ ptr_eq // Do not lint @@ -31,9 +33,19 @@ fn main() { let a = &mut [1, 2, 3]; let b = &mut [1, 2, 3]; - let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _; - let _ = a.as_mut_ptr() == b.as_mut_ptr(); + let _ = std::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _); + //~^ ptr_eq + let _ = std::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr()); + //~^ ptr_eq let _ = a == b; let _ = core::ptr::eq(a, b); + + let (x, y) = (&0u32, &mut 1u32); + let _ = std::ptr::eq(x, y); + //~^ ptr_eq + + #[allow(clippy::eq_op)] + let _issue14337 = std::ptr::eq(main as *const (), main as *const ()); + //~^ ptr_eq } diff --git a/tests/ui/ptr_eq.rs b/tests/ui/ptr_eq.rs index 0bc58a57fa53..f0ddaaa0f6d4 100644 --- a/tests/ui/ptr_eq.rs +++ b/tests/ui/ptr_eq.rs @@ -21,7 +21,9 @@ fn main() { let _ = a as *const _ == b as *const _; //~^ ptr_eq let _ = a.as_ptr() == b as *const _; + //~^ ptr_eq let _ = a.as_ptr() == b.as_ptr(); + //~^ ptr_eq // Do not lint @@ -32,8 +34,18 @@ fn main() { let b = &mut [1, 2, 3]; let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _; + //~^ ptr_eq let _ = a.as_mut_ptr() == b.as_mut_ptr(); + //~^ ptr_eq let _ = a == b; let _ = core::ptr::eq(a, b); + + let (x, y) = (&0u32, &mut 1u32); + let _ = x as *const u32 == y as *mut u32 as *const u32; + //~^ ptr_eq + + #[allow(clippy::eq_op)] + let _issue14337 = main as *const () == main as *const (); + //~^ ptr_eq } diff --git a/tests/ui/ptr_eq.stderr b/tests/ui/ptr_eq.stderr index 8e8b34f26ff7..8db602d30236 100644 --- a/tests/ui/ptr_eq.stderr +++ b/tests/ui/ptr_eq.stderr @@ -13,5 +13,41 @@ error: use `std::ptr::eq` when comparing raw pointers LL | let _ = a as *const _ == b as *const _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a, b)` -error: aborting due to 2 previous errors +error: use `std::ptr::eq` when comparing raw pointers + --> tests/ui/ptr_eq.rs:23:13 + | +LL | let _ = a.as_ptr() == b as *const _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_ptr(), b as *const _)` + +error: use `std::ptr::eq` when comparing raw pointers + --> tests/ui/ptr_eq.rs:25:13 + | +LL | let _ = a.as_ptr() == b.as_ptr(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_ptr(), b.as_ptr())` + +error: use `std::ptr::eq` when comparing raw pointers + --> tests/ui/ptr_eq.rs:36:13 + | +LL | let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _)` + +error: use `std::ptr::eq` when comparing raw pointers + --> tests/ui/ptr_eq.rs:38:13 + | +LL | let _ = a.as_mut_ptr() == b.as_mut_ptr(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr())` + +error: use `std::ptr::eq` when comparing raw pointers + --> tests/ui/ptr_eq.rs:45:13 + | +LL | let _ = x as *const u32 == y as *mut u32 as *const u32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(x, y)` + +error: use `std::ptr::eq` when comparing raw pointers + --> tests/ui/ptr_eq.rs:49:23 + | +LL | let _issue14337 = main as *const () == main as *const (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(main as *const (), main as *const ())` + +error: aborting due to 8 previous errors diff --git a/tests/ui/ptr_eq_no_std.fixed b/tests/ui/ptr_eq_no_std.fixed index b3e82fae38f3..d8ee4ea88f84 100644 --- a/tests/ui/ptr_eq_no_std.fixed +++ b/tests/ui/ptr_eq_no_std.fixed @@ -32,8 +32,10 @@ fn main() { //~^ ptr_eq let _ = core::ptr::eq(a, b); //~^ ptr_eq - let _ = a.as_ptr() == b as *const _; - let _ = a.as_ptr() == b.as_ptr(); + let _ = core::ptr::eq(a.as_ptr(), b as *const _); + //~^ ptr_eq + let _ = core::ptr::eq(a.as_ptr(), b.as_ptr()); + //~^ ptr_eq // Do not lint @@ -43,8 +45,10 @@ fn main() { let a = &mut [1, 2, 3]; let b = &mut [1, 2, 3]; - let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _; - let _ = a.as_mut_ptr() == b.as_mut_ptr(); + let _ = core::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _); + //~^ ptr_eq + let _ = core::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr()); + //~^ ptr_eq let _ = a == b; let _ = core::ptr::eq(a, b); diff --git a/tests/ui/ptr_eq_no_std.rs b/tests/ui/ptr_eq_no_std.rs index ba78f5ee5f84..a236314c29b7 100644 --- a/tests/ui/ptr_eq_no_std.rs +++ b/tests/ui/ptr_eq_no_std.rs @@ -33,7 +33,9 @@ fn main() { let _ = a as *const _ == b as *const _; //~^ ptr_eq let _ = a.as_ptr() == b as *const _; + //~^ ptr_eq let _ = a.as_ptr() == b.as_ptr(); + //~^ ptr_eq // Do not lint @@ -44,7 +46,9 @@ fn main() { let b = &mut [1, 2, 3]; let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _; + //~^ ptr_eq let _ = a.as_mut_ptr() == b.as_mut_ptr(); + //~^ ptr_eq let _ = a == b; let _ = core::ptr::eq(a, b); diff --git a/tests/ui/ptr_eq_no_std.stderr b/tests/ui/ptr_eq_no_std.stderr index 8c7b1ff76661..5b8135dc8e8b 100644 --- a/tests/ui/ptr_eq_no_std.stderr +++ b/tests/ui/ptr_eq_no_std.stderr @@ -13,5 +13,29 @@ error: use `core::ptr::eq` when comparing raw pointers LL | let _ = a as *const _ == b as *const _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a, b)` -error: aborting due to 2 previous errors +error: use `core::ptr::eq` when comparing raw pointers + --> tests/ui/ptr_eq_no_std.rs:35:13 + | +LL | let _ = a.as_ptr() == b as *const _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_ptr(), b as *const _)` + +error: use `core::ptr::eq` when comparing raw pointers + --> tests/ui/ptr_eq_no_std.rs:37:13 + | +LL | let _ = a.as_ptr() == b.as_ptr(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_ptr(), b.as_ptr())` + +error: use `core::ptr::eq` when comparing raw pointers + --> tests/ui/ptr_eq_no_std.rs:48:13 + | +LL | let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _)` + +error: use `core::ptr::eq` when comparing raw pointers + --> tests/ui/ptr_eq_no_std.rs:50:13 + | +LL | let _ = a.as_mut_ptr() == b.as_mut_ptr(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr())` + +error: aborting due to 6 previous errors From 336d34481e9fce4df59096ede51832416c2e34ed Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 2 Mar 2025 15:57:30 +0100 Subject: [PATCH 081/745] Apply `ptr_eq` lint only if `cmp_null` is not applicable The `cmp_null` lint is more specialized than `ptr_eq`. The former should take precedence, unless the user allows it. --- clippy_lints/src/declared_lints.rs | 2 +- clippy_lints/src/operators/mod.rs | 32 -------- clippy_lints/src/operators/ptr_eq.rs | 73 ------------------ clippy_lints/src/ptr.rs | 111 +++++++++++++++++++++++++-- tests/ui/ptr_eq.fixed | 3 + tests/ui/ptr_eq.rs | 3 + tests/ui/ptr_eq.stderr | 10 ++- 7 files changed, 121 insertions(+), 113 deletions(-) delete mode 100644 clippy_lints/src/operators/ptr_eq.rs diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 0834618499c7..ae779af2a894 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -614,7 +614,6 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::operators::MODULO_ONE_INFO, crate::operators::NEEDLESS_BITWISE_BOOL_INFO, crate::operators::OP_REF_INFO, - crate::operators::PTR_EQ_INFO, crate::operators::REDUNDANT_COMPARISONS_INFO, crate::operators::SELF_ASSIGNMENT_INFO, crate::operators::VERBOSE_BIT_MASK_INFO, @@ -641,6 +640,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::ptr::INVALID_NULL_PTR_USAGE_INFO, crate::ptr::MUT_FROM_REF_INFO, crate::ptr::PTR_ARG_INFO, + crate::ptr::PTR_EQ_INFO, crate::ptr_offset_with_cast::PTR_OFFSET_WITH_CAST_INFO, crate::pub_underscore_fields::PUB_UNDERSCORE_FIELDS_INFO, crate::pub_use::PUB_USE_INFO, diff --git a/clippy_lints/src/operators/mod.rs b/clippy_lints/src/operators/mod.rs index 80459945094e..f758d08d3663 100644 --- a/clippy_lints/src/operators/mod.rs +++ b/clippy_lints/src/operators/mod.rs @@ -18,7 +18,6 @@ mod modulo_one; mod needless_bitwise_bool; mod numeric_arithmetic; mod op_ref; -mod ptr_eq; mod self_assignment; mod verbose_bit_mask; @@ -768,35 +767,6 @@ declare_clippy_lint! { "Boolean expressions that use bitwise rather than lazy operators" } -declare_clippy_lint! { - /// ### What it does - /// Use `std::ptr::eq` when applicable - /// - /// ### Why is this bad? - /// `ptr::eq` can be used to compare `&T` references - /// (which coerce to `*const T` implicitly) by their address rather than - /// comparing the values they point to. - /// - /// ### Example - /// ```no_run - /// let a = &[1, 2, 3]; - /// let b = &[1, 2, 3]; - /// - /// assert!(a as *const _ as usize == b as *const _ as usize); - /// ``` - /// Use instead: - /// ```no_run - /// let a = &[1, 2, 3]; - /// let b = &[1, 2, 3]; - /// - /// assert!(std::ptr::eq(a, b)); - /// ``` - #[clippy::version = "1.49.0"] - pub PTR_EQ, - style, - "use `std::ptr::eq` when comparing raw pointers" -} - declare_clippy_lint! { /// ### What it does /// Checks for explicit self-assignments. @@ -902,7 +872,6 @@ impl_lint_pass!(Operators => [ MODULO_ONE, MODULO_ARITHMETIC, NEEDLESS_BITWISE_BOOL, - PTR_EQ, SELF_ASSIGNMENT, MANUAL_MIDPOINT, ]); @@ -921,7 +890,6 @@ impl<'tcx> LateLintPass<'tcx> for Operators { erasing_op::check(cx, e, op.node, lhs, rhs); identity_op::check(cx, e, op.node, lhs, rhs); needless_bitwise_bool::check(cx, e, op.node, lhs, rhs); - ptr_eq::check(cx, e, op.node, lhs, rhs); manual_midpoint::check(cx, e, op.node, lhs, rhs, self.msrv); } self.arithmetic_context.check_binary(cx, e, op.node, lhs, rhs); diff --git a/clippy_lints/src/operators/ptr_eq.rs b/clippy_lints/src/operators/ptr_eq.rs deleted file mode 100644 index 79893c21a433..000000000000 --- a/clippy_lints/src/operators/ptr_eq.rs +++ /dev/null @@ -1,73 +0,0 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::SpanRangeExt; -use clippy_utils::std_or_core; -use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Expr, ExprKind}; -use rustc_lint::LateContext; -use rustc_middle::ty::{self, Ty}; - -use super::PTR_EQ; - -pub(super) fn check<'tcx>( - cx: &LateContext<'tcx>, - expr: &'tcx Expr<'_>, - op: BinOpKind, - left: &'tcx Expr<'_>, - right: &'tcx Expr<'_>, -) { - if BinOpKind::Eq == op { - // Remove one level of usize conversion if any - let (left, right) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) { - (Some(lhs), Some(rhs)) => (lhs, rhs), - _ => (left, right), - }; - - // This lint concerns raw pointers - let (left_ty, right_ty) = (cx.typeck_results().expr_ty(left), cx.typeck_results().expr_ty(right)); - if !left_ty.is_raw_ptr() || !right_ty.is_raw_ptr() { - return; - } - - let (left_var, right_var) = (peel_raw_casts(cx, left, left_ty), peel_raw_casts(cx, right, right_ty)); - - if let Some(left_snip) = left_var.span.get_source_text(cx) - && let Some(right_snip) = right_var.span.get_source_text(cx) - { - let Some(top_crate) = std_or_core(cx) else { return }; - span_lint_and_sugg( - cx, - PTR_EQ, - expr.span, - format!("use `{top_crate}::ptr::eq` when comparing raw pointers"), - "try", - format!("{top_crate}::ptr::eq({left_snip}, {right_snip})"), - Applicability::MachineApplicable, - ); - } - } -} - -// If the given expression is a cast to a usize, return the lhs of the cast -// E.g., `foo as *const _ as usize` returns `foo as *const _`. -fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { - if cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize { - if let ExprKind::Cast(expr, _) = cast_expr.kind { - return Some(expr); - } - } - None -} - -// Peel raw casts if the remaining expression can be coerced to it -fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty: Ty<'tcx>) -> &'tcx Expr<'tcx> { - if let ExprKind::Cast(inner, _) = expr.kind - && let ty::RawPtr(target_ty, _) = expr_ty.kind() - && let inner_ty = cx.typeck_results().expr_ty(inner) - && let ty::RawPtr(inner_target_ty, _) | ty::Ref(_, inner_target_ty, _) = inner_ty.kind() - && target_ty == inner_target_ty - { - peel_raw_casts(cx, inner, inner_ty) - } else { - expr - } -} diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index dae0709a5404..55f1ece05593 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -148,7 +148,36 @@ declare_clippy_lint! { "invalid usage of a null pointer, suggesting `NonNull::dangling()` instead" } -declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF, INVALID_NULL_PTR_USAGE]); +declare_clippy_lint! { + /// ### What it does + /// Use `std::ptr::eq` when applicable + /// + /// ### Why is this bad? + /// `ptr::eq` can be used to compare `&T` references + /// (which coerce to `*const T` implicitly) by their address rather than + /// comparing the values they point to. + /// + /// ### Example + /// ```no_run + /// let a = &[1, 2, 3]; + /// let b = &[1, 2, 3]; + /// + /// assert!(a as *const _ as usize == b as *const _ as usize); + /// ``` + /// Use instead: + /// ```no_run + /// let a = &[1, 2, 3]; + /// let b = &[1, 2, 3]; + /// + /// assert!(std::ptr::eq(a, b)); + /// ``` + #[clippy::version = "1.49.0"] + pub PTR_EQ, + style, + "use `std::ptr::eq` when comparing raw pointers" +} + +declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF, INVALID_NULL_PTR_USAGE, PTR_EQ]); impl<'tcx> LateLintPass<'tcx> for Ptr { fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { @@ -253,10 +282,14 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { if let ExprKind::Binary(op, l, r) = expr.kind && (op.node == BinOpKind::Eq || op.node == BinOpKind::Ne) { - let non_null_path_snippet = match (is_null_path(cx, l), is_null_path(cx, r)) { - (true, false) if let Some(sugg) = Sugg::hir_opt(cx, r) => sugg.maybe_par(), - (false, true) if let Some(sugg) = Sugg::hir_opt(cx, l) => sugg.maybe_par(), - _ => return, + let non_null_path_snippet = match ( + is_lint_allowed(cx, CMP_NULL, expr.hir_id), + is_null_path(cx, l), + is_null_path(cx, r), + ) { + (false, true, false) if let Some(sugg) = Sugg::hir_opt(cx, r) => sugg.maybe_par(), + (false, false, true) if let Some(sugg) = Sugg::hir_opt(cx, l) => sugg.maybe_par(), + _ => return check_ptr_eq(cx, expr, op.node, l, r), }; span_lint_and_sugg( @@ -740,3 +773,71 @@ fn is_null_path(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { false } } + +fn check_ptr_eq<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'_>, + op: BinOpKind, + left: &'tcx Expr<'_>, + right: &'tcx Expr<'_>, +) { + if expr.span.from_expansion() { + return; + } + + // Remove one level of usize conversion if any + let (left, right) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) { + (Some(lhs), Some(rhs)) => (lhs, rhs), + _ => (left, right), + }; + + // This lint concerns raw pointers + let (left_ty, right_ty) = (cx.typeck_results().expr_ty(left), cx.typeck_results().expr_ty(right)); + if !left_ty.is_raw_ptr() || !right_ty.is_raw_ptr() { + return; + } + + let (left_var, right_var) = (peel_raw_casts(cx, left, left_ty), peel_raw_casts(cx, right, right_ty)); + + if let Some(left_snip) = left_var.span.get_source_text(cx) + && let Some(right_snip) = right_var.span.get_source_text(cx) + { + let Some(top_crate) = std_or_core(cx) else { return }; + let invert = if op == BinOpKind::Eq { "" } else { "!" }; + span_lint_and_sugg( + cx, + PTR_EQ, + expr.span, + format!("use `{top_crate}::ptr::eq` when comparing raw pointers"), + "try", + format!("{invert}{top_crate}::ptr::eq({left_snip}, {right_snip})"), + Applicability::MachineApplicable, + ); + } +} + +// If the given expression is a cast to a usize, return the lhs of the cast +// E.g., `foo as *const _ as usize` returns `foo as *const _`. +fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { + if cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize + && let ExprKind::Cast(expr, _) = cast_expr.kind + { + Some(expr) + } else { + None + } +} + +// Peel raw casts if the remaining expression can be coerced to it +fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty: Ty<'tcx>) -> &'tcx Expr<'tcx> { + if let ExprKind::Cast(inner, _) = expr.kind + && let ty::RawPtr(target_ty, _) = expr_ty.kind() + && let inner_ty = cx.typeck_results().expr_ty(inner) + && let ty::RawPtr(inner_target_ty, _) | ty::Ref(_, inner_target_ty, _) = inner_ty.kind() + && target_ty == inner_target_ty + { + peel_raw_casts(cx, inner, inner_ty) + } else { + expr + } +} diff --git a/tests/ui/ptr_eq.fixed b/tests/ui/ptr_eq.fixed index 2111067d49fb..df6305ed497e 100644 --- a/tests/ui/ptr_eq.fixed +++ b/tests/ui/ptr_eq.fixed @@ -45,6 +45,9 @@ fn main() { let _ = std::ptr::eq(x, y); //~^ ptr_eq + let _ = !std::ptr::eq(x, y); + //~^ ptr_eq + #[allow(clippy::eq_op)] let _issue14337 = std::ptr::eq(main as *const (), main as *const ()); //~^ ptr_eq diff --git a/tests/ui/ptr_eq.rs b/tests/ui/ptr_eq.rs index f0ddaaa0f6d4..0ed0ff0d1371 100644 --- a/tests/ui/ptr_eq.rs +++ b/tests/ui/ptr_eq.rs @@ -45,6 +45,9 @@ fn main() { let _ = x as *const u32 == y as *mut u32 as *const u32; //~^ ptr_eq + let _ = x as *const u32 != y as *mut u32 as *const u32; + //~^ ptr_eq + #[allow(clippy::eq_op)] let _issue14337 = main as *const () == main as *const (); //~^ ptr_eq diff --git a/tests/ui/ptr_eq.stderr b/tests/ui/ptr_eq.stderr index 8db602d30236..33190df284a3 100644 --- a/tests/ui/ptr_eq.stderr +++ b/tests/ui/ptr_eq.stderr @@ -44,10 +44,16 @@ LL | let _ = x as *const u32 == y as *mut u32 as *const u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(x, y)` error: use `std::ptr::eq` when comparing raw pointers - --> tests/ui/ptr_eq.rs:49:23 + --> tests/ui/ptr_eq.rs:48:13 + | +LL | let _ = x as *const u32 != y as *mut u32 as *const u32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!std::ptr::eq(x, y)` + +error: use `std::ptr::eq` when comparing raw pointers + --> tests/ui/ptr_eq.rs:52:23 | LL | let _issue14337 = main as *const () == main as *const (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(main as *const (), main as *const ())` -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors From 4508f5f8628c2869f153b59aba6d90411d831e33 Mon Sep 17 00:00:00 2001 From: Mu001999 Date: Sun, 2 Mar 2025 23:21:43 +0800 Subject: [PATCH 082/745] update outdated doc with new example --- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index d72cf00293f0..e81d753f3e7d 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -218,10 +218,10 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGua /// definition itself. For example, this definition would be illegal: /// /// ```rust -/// struct Ref<'a, T> { x: &'a T } +/// struct StaticRef { x: &'static T } /// ``` /// -/// because the type did not declare that `T:'a`. +/// because the type did not declare that `T: 'static`. /// /// We do this check as a pre-pass before checking fn bodies because if these constraints are /// not included it frequently leads to confusing errors in fn bodies. So it's better to check From 68679f295f50093501c9781f67f07f3feb7bf02c Mon Sep 17 00:00:00 2001 From: yanglsh Date: Wed, 12 Feb 2025 06:06:09 -0700 Subject: [PATCH 083/745] fix: `manual_let_else` missing binding mode --- clippy_lints/src/manual_let_else.rs | 37 ++++++++++++------------- tests/ui/manual_let_else.rs | 34 +++++++++++++++++++++++ tests/ui/manual_let_else.stderr | 42 ++++++++++++++++++++++++++++- 3 files changed, 94 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs index 47939767212e..d6ac6e106b4b 100644 --- a/clippy_lints/src/manual_let_else.rs +++ b/clippy_lints/src/manual_let_else.rs @@ -5,7 +5,8 @@ use clippy_utils::higher::IfLetOrMatch; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{is_lint_allowed, is_never_expr, msrvs, pat_and_expr_can_be_question_mark, peel_blocks}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_ast::BindingMode; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatExpr, PatExprKind, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LintContext}; @@ -113,7 +114,7 @@ fn emit_manual_let_else( cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, - ident_map: &FxHashMap>, + ident_map: &FxHashMap, BindingMode)>, pat: &Pat<'_>, else_body: &Expr<'_>, ) { @@ -167,7 +168,7 @@ fn emit_manual_let_else( fn replace_in_pattern( cx: &LateContext<'_>, span: Span, - ident_map: &FxHashMap>, + ident_map: &FxHashMap, BindingMode)>, pat: &Pat<'_>, app: &mut Applicability, top_level: bool, @@ -185,15 +186,16 @@ fn replace_in_pattern( match pat.kind { PatKind::Binding(_ann, _id, binding_name, opt_subpt) => { - let Some(pat_to_put) = ident_map.get(&binding_name.name) else { + let Some((pat_to_put, binding_mode)) = ident_map.get(&binding_name.name) else { break 'a; }; + let sn_pfx = binding_mode.prefix_str(); let (sn_ptp, _) = snippet_with_context(cx, pat_to_put.span, span.ctxt(), "", app); if let Some(subpt) = opt_subpt { let subpt = replace_in_pattern(cx, span, ident_map, subpt, app, false); - return format!("{sn_ptp} @ {subpt}"); + return format!("{sn_pfx}{sn_ptp} @ {subpt}"); } - return sn_ptp.to_string(); + return format!("{sn_pfx}{sn_ptp}"); }, PatKind::Or(pats) => { let patterns = pats @@ -211,17 +213,18 @@ fn replace_in_pattern( .iter() .map(|fld| { if let PatKind::Binding(_, _, name, None) = fld.pat.kind - && let Some(pat_to_put) = ident_map.get(&name.name) + && let Some((pat_to_put, binding_mode)) = ident_map.get(&name.name) { + let sn_pfx = binding_mode.prefix_str(); let (sn_fld_name, _) = snippet_with_context(cx, fld.ident.span, span.ctxt(), "", app); let (sn_ptp, _) = snippet_with_context(cx, pat_to_put.span, span.ctxt(), "", app); // TODO: this is a bit of a hack, but it does its job. Ideally, we'd check if pat_to_put is // a PatKind::Binding but that is also hard to get right. if sn_fld_name == sn_ptp { // Field init shorthand - return format!("{sn_fld_name}"); + return format!("{sn_pfx}{sn_fld_name}"); } - return format!("{sn_fld_name}: {sn_ptp}"); + return format!("{sn_fld_name}: {sn_pfx}{sn_ptp}"); } let (sn_fld, _) = snippet_with_context(cx, fld.span, span.ctxt(), "", app); sn_fld.into_owned() @@ -334,7 +337,7 @@ fn expr_simple_identity_map<'a, 'hir>( local_pat: &'a Pat<'hir>, let_pat: &'_ Pat<'hir>, expr: &'_ Expr<'hir>, -) -> Option>> { +) -> Option, BindingMode)>> { let peeled = peel_blocks(expr); let (sub_pats, paths) = match (local_pat.kind, peeled.kind) { (PatKind::Tuple(pats, _), ExprKind::Tup(exprs)) | (PatKind::Slice(pats, ..), ExprKind::Array(exprs)) => { @@ -351,9 +354,9 @@ fn expr_simple_identity_map<'a, 'hir>( return None; } - let mut pat_bindings = FxHashSet::default(); - let_pat.each_binding_or_first(&mut |_ann, _hir_id, _sp, ident| { - pat_bindings.insert(ident); + let mut pat_bindings = FxHashMap::default(); + let_pat.each_binding_or_first(&mut |binding_mode, _hir_id, _sp, ident| { + pat_bindings.insert(ident, binding_mode); }); if pat_bindings.len() < paths.len() { // This rebinds some bindings from the outer scope, or it repeats some copy-able bindings multiple @@ -366,12 +369,10 @@ fn expr_simple_identity_map<'a, 'hir>( for (sub_pat, path) in sub_pats.iter().zip(paths.iter()) { if let ExprKind::Path(QPath::Resolved(_ty, path)) = path.kind && let [path_seg] = path.segments + && let ident = path_seg.ident + && let Some(let_binding_mode) = pat_bindings.remove(&ident) { - let ident = path_seg.ident; - if !pat_bindings.remove(&ident) { - return None; - } - ident_map.insert(ident.name, sub_pat); + ident_map.insert(ident.name, (sub_pat, let_binding_mode)); } else { return None; } diff --git a/tests/ui/manual_let_else.rs b/tests/ui/manual_let_else.rs index d2350d97ed00..a753566b34cb 100644 --- a/tests/ui/manual_let_else.rs +++ b/tests/ui/manual_let_else.rs @@ -480,3 +480,37 @@ fn issue12337() { //~^ manual_let_else }; } + +mod issue13768 { + enum Foo { + Str(String), + None, + } + + fn foo(value: Foo) { + let signature = match value { + //~^ manual_let_else + Foo::Str(ref val) => val, + _ => { + println!("No signature found"); + return; + }, + }; + } + + enum Bar { + Str { inner: String }, + None, + } + + fn bar(mut value: Bar) { + let signature = match value { + //~^ manual_let_else + Bar::Str { ref mut inner } => inner, + _ => { + println!("No signature found"); + return; + }, + }; + } +} diff --git a/tests/ui/manual_let_else.stderr b/tests/ui/manual_let_else.stderr index 8f5cba64d545..ef0421921141 100644 --- a/tests/ui/manual_let_else.stderr +++ b/tests/ui/manual_let_else.stderr @@ -489,5 +489,45 @@ error: this could be rewritten as `let...else` LL | let v = if let Some(v_some) = g() { v_some } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };` -error: aborting due to 31 previous errors +error: this could be rewritten as `let...else` + --> tests/ui/manual_let_else.rs:491:9 + | +LL | / let signature = match value { +LL | | +LL | | Foo::Str(ref val) => val, +LL | | _ => { +... | +LL | | }, +LL | | }; + | |__________^ + | +help: consider writing + | +LL ~ let Foo::Str(ref signature) = value else { +LL + println!("No signature found"); +LL + return; +LL + }; + | + +error: this could be rewritten as `let...else` + --> tests/ui/manual_let_else.rs:507:9 + | +LL | / let signature = match value { +LL | | +LL | | Bar::Str { ref mut inner } => inner, +LL | | _ => { +... | +LL | | }, +LL | | }; + | |__________^ + | +help: consider writing + | +LL ~ let Bar::Str { inner: ref mut signature } = value else { +LL + println!("No signature found"); +LL + return; +LL + }; + | + +error: aborting due to 33 previous errors From ddc9f45b8924d7b38ec0dbc7ecf3c1058988cd93 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 3 Mar 2025 20:17:26 +1100 Subject: [PATCH 084/745] Remove some unnecessary aliases from `rustc_data_structures::sync` With the removal of `cfg(parallel_compiler)`, these are always shared references and `std::sync::OnceLock`. --- clippy_utils/src/macros.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs index 3ce2cdfebe96..1a457bc7f214 100644 --- a/clippy_utils/src/macros.rs +++ b/clippy_utils/src/macros.rs @@ -1,6 +1,6 @@ #![allow(clippy::similar_names)] // `expr` and `expn` -use std::sync::Arc; +use std::sync::{Arc, OnceLock}; use crate::get_unique_attr; use crate::visitors::{Descend, for_each_expr_without_closures}; @@ -8,7 +8,6 @@ use crate::visitors::{Descend, for_each_expr_without_closures}; use arrayvec::ArrayVec; use rustc_ast::{FormatArgs, FormatArgument, FormatPlaceholder}; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::OnceLock; use rustc_hir::{self as hir, Expr, ExprKind, HirId, Node, QPath}; use rustc_lint::{LateContext, LintContext}; use rustc_span::def_id::DefId; From e31bb45e47d78798f6b6d31316f525316bfcaecf Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 3 Mar 2025 10:53:58 +0100 Subject: [PATCH 085/745] stabilize const_cell --- library/core/src/cell.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index cbf00106c517..79051588f443 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -495,7 +495,7 @@ impl Cell { /// ``` #[inline] #[stable(feature = "move_cell", since = "1.17.0")] - #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")] #[rustc_confusables("swap")] pub const fn replace(&self, val: T) -> T { // SAFETY: This can cause data races if called from a separate thread, @@ -537,7 +537,7 @@ impl Cell { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")] pub const fn get(&self) -> T { // SAFETY: This can cause data races if called from a separate thread, // but `Cell` is `!Sync` so this won't happen. @@ -617,7 +617,7 @@ impl Cell { /// ``` #[inline] #[stable(feature = "cell_get_mut", since = "1.11.0")] - #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")] pub const fn get_mut(&mut self) -> &mut T { self.value.get_mut() } @@ -637,7 +637,7 @@ impl Cell { /// ``` #[inline] #[stable(feature = "as_cell", since = "1.37.0")] - #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")] pub const fn from_mut(t: &mut T) -> &Cell { // SAFETY: `&mut` ensures unique access. unsafe { &*(t as *mut T as *const Cell) } @@ -695,7 +695,7 @@ impl Cell<[T]> { /// assert_eq!(slice_cell.len(), 3); /// ``` #[stable(feature = "as_cell", since = "1.37.0")] - #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")] pub const fn as_slice_of_cells(&self) -> &[Cell] { // SAFETY: `Cell` has the same memory layout as `T`. unsafe { &*(self as *const Cell<[T]> as *const [Cell]) } From 57767d6d998c9998049df14e9c4ccc903396f013 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 3 Mar 2025 12:35:10 +0000 Subject: [PATCH 086/745] Rustup to rustc 1.87.0-nightly (f4a216d28 2025-03-02) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 86052b4df764..d9b4f2fc6743 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-02-26" +channel = "nightly-2025-03-03" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From 0f9c09fb3a64ff11ea81446a96907cd5e86490c2 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 3 Mar 2025 12:43:05 +0000 Subject: [PATCH 087/745] Remoe has_ptr_meta in favor of tcx.type_has_metadata() --- src/base.rs | 6 ++++-- src/common.rs | 18 ++---------------- src/debuginfo/types.rs | 4 ++-- src/num.rs | 8 ++++++-- src/value_and_place.rs | 6 +++--- 5 files changed, 17 insertions(+), 25 deletions(-) diff --git a/src/base.rs b/src/base.rs index 125a9201831c..adaa754491e5 100644 --- a/src/base.rs +++ b/src/base.rs @@ -729,8 +729,10 @@ fn codegen_stmt<'tcx>( let to_ty = fx.monomorphize(to_ty); fn is_wide_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool { - ty.builtin_deref(true) - .is_some_and(|pointee_ty| has_ptr_meta(fx.tcx, pointee_ty)) + ty.builtin_deref(true).is_some_and(|pointee_ty| { + fx.tcx + .type_has_metadata(pointee_ty, ty::TypingEnv::fully_monomorphized()) + }) } if is_wide_ptr(fx, from_ty) { diff --git a/src/common.rs b/src/common.rs index 766278d87183..abe2972ba0cb 100644 --- a/src/common.rs +++ b/src/common.rs @@ -71,7 +71,7 @@ fn clif_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option pointer_ty(tcx), ty::RawPtr(pointee_ty, _) | ty::Ref(_, pointee_ty, _) => { - if has_ptr_meta(tcx, *pointee_ty) { + if tcx.type_has_metadata(*pointee_ty, ty::TypingEnv::fully_monomorphized()) { return None; } else { pointer_ty(tcx) @@ -91,7 +91,7 @@ fn clif_pair_type_from_ty<'tcx>( (clif_type_from_ty(tcx, types[0])?, clif_type_from_ty(tcx, types[1])?) } ty::RawPtr(pointee_ty, _) | ty::Ref(_, pointee_ty, _) => { - if has_ptr_meta(tcx, *pointee_ty) { + if tcx.type_has_metadata(*pointee_ty, ty::TypingEnv::fully_monomorphized()) { (pointer_ty(tcx), pointer_ty(tcx)) } else { return None; @@ -101,20 +101,6 @@ fn clif_pair_type_from_ty<'tcx>( }) } -/// Is a pointer to this type a wide ptr? -pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { - if ty.is_sized(tcx, ty::TypingEnv::fully_monomorphized()) { - return false; - } - - let tail = tcx.struct_tail_for_codegen(ty, ty::TypingEnv::fully_monomorphized()); - match tail.kind() { - ty::Foreign(..) => false, - ty::Str | ty::Slice(..) | ty::Dynamic(..) => true, - _ => bug!("unexpected unsized tail: {:?}", tail), - } -} - pub(crate) fn codegen_icmp_imm( fx: &mut FunctionCx<'_, '_, '_>, intcc: IntCC, diff --git a/src/debuginfo/types.rs b/src/debuginfo/types.rs index 017d7784dc03..25b922c8be4c 100644 --- a/src/debuginfo/types.rs +++ b/src/debuginfo/types.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty, TyCtxt}; -use crate::{DebugContext, FullyMonomorphizedLayoutCx, has_ptr_meta}; +use crate::{DebugContext, FullyMonomorphizedLayoutCx}; #[derive(Default)] pub(crate) struct TypeDebugContext<'tcx> { @@ -129,7 +129,7 @@ impl DebugContext { let name = type_names::compute_debuginfo_type_name(tcx, ptr_type, true); - if !has_ptr_meta(tcx, ptr_type) { + if !tcx.type_has_metadata(ptr_type, ty::TypingEnv::fully_monomorphized()) { let pointer_type_id = self.dwarf.unit.add(self.dwarf.unit.root(), gimli::DW_TAG_pointer_type); let pointer_entry = self.dwarf.unit.get_mut(pointer_type_id); diff --git a/src/num.rs b/src/num.rs index f44e2459a784..2a4d1e3ae571 100644 --- a/src/num.rs +++ b/src/num.rs @@ -395,8 +395,12 @@ pub(crate) fn codegen_ptr_binop<'tcx>( in_lhs: CValue<'tcx>, in_rhs: CValue<'tcx>, ) -> CValue<'tcx> { - let is_thin_ptr = - in_lhs.layout().ty.builtin_deref(true).map(|ty| !has_ptr_meta(fx.tcx, ty)).unwrap_or(true); + let is_thin_ptr = in_lhs + .layout() + .ty + .builtin_deref(true) + .map(|ty| !fx.tcx.type_has_metadata(ty, ty::TypingEnv::fully_monomorphized())) + .unwrap_or(true); if is_thin_ptr { match bin_op { diff --git a/src/value_and_place.rs b/src/value_and_place.rs index cc739fefcd06..f8a19589fdd7 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -746,7 +746,7 @@ impl<'tcx> CPlace<'tcx> { }; let (field_ptr, field_layout) = codegen_field(fx, base, extra, layout, field); - if has_ptr_meta(fx.tcx, field_layout.ty) { + if fx.tcx.type_has_metadata(field_layout.ty, ty::TypingEnv::fully_monomorphized()) { CPlace::for_ptr_with_extra(field_ptr, extra.unwrap(), field_layout) } else { CPlace::for_ptr(field_ptr, field_layout) @@ -832,7 +832,7 @@ impl<'tcx> CPlace<'tcx> { pub(crate) fn place_deref(self, fx: &mut FunctionCx<'_, '_, 'tcx>) -> CPlace<'tcx> { let inner_layout = fx.layout_of(self.layout().ty.builtin_deref(true).unwrap()); - if has_ptr_meta(fx.tcx, inner_layout.ty) { + if fx.tcx.type_has_metadata(inner_layout.ty, ty::TypingEnv::fully_monomorphized()) { let (addr, extra) = self.to_cvalue(fx).load_scalar_pair(fx); CPlace::for_ptr_with_extra(Pointer::new(addr), extra, inner_layout) } else { @@ -845,7 +845,7 @@ impl<'tcx> CPlace<'tcx> { fx: &mut FunctionCx<'_, '_, 'tcx>, layout: TyAndLayout<'tcx>, ) -> CValue<'tcx> { - if has_ptr_meta(fx.tcx, self.layout().ty) { + if fx.tcx.type_has_metadata(self.layout().ty, ty::TypingEnv::fully_monomorphized()) { let (ptr, extra) = self.to_ptr_unsized(); CValue::by_val_pair(ptr.get_addr(fx), extra, layout) } else { From d63d56aeb0649df09eafe192dedbf834c3ca0964 Mon Sep 17 00:00:00 2001 From: lapla-cogito Date: Mon, 3 Mar 2025 22:28:57 +0900 Subject: [PATCH 088/745] add `macos-latest` as a CI target --- .github/workflows/clippy_mq.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/clippy_mq.yml b/.github/workflows/clippy_mq.yml index c337a96bdac5..741e74573317 100644 --- a/.github/workflows/clippy_mq.yml +++ b/.github/workflows/clippy_mq.yml @@ -27,6 +27,8 @@ jobs: host: x86_64-pc-windows-msvc - os: macos-13 host: x86_64-apple-darwin + - os: macos-latest + host: aarch64-apple-darwin runs-on: ${{ matrix.os }} From f6fc17a4c8ccc88096785dfb50e553003e99f147 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Mon, 3 Mar 2025 13:16:14 -0500 Subject: [PATCH 089/745] Add an anchor to directly link to the -Zmiri-tree-borrows docs --- src/tools/miri/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index 4ae901be9b43..d64de4b1976d 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -432,7 +432,8 @@ to Miri failing to detect cases of undefined behavior in a program. * `-Zmiri-track-weak-memory-loads` shows a backtrace when weak memory emulation returns an outdated value from a load. This can help diagnose problems that disappear under `-Zmiri-disable-weak-memory-emulation`. -* `-Zmiri-tree-borrows` replaces [Stacked Borrows] with the [Tree Borrows] rules. +* + `-Zmiri-tree-borrows` replaces [Stacked Borrows] with the [Tree Borrows] rules. Tree Borrows is even more experimental than Stacked Borrows. While Tree Borrows is still sound in the sense of catching all aliasing violations that current versions of the compiler might exploit, it is likely that the eventual final aliasing model From 7b5e847ae5b8d2da27455ffd3fe55cc2e2dccf6d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 30 Jan 2025 22:15:26 +0100 Subject: [PATCH 090/745] exit: document interaction with C --- library/std/src/env.rs | 2 +- library/std/src/process.rs | 34 +++++++++++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 4a071b4e1fae..c0415eafb051 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -330,7 +330,7 @@ impl Error for VarError { /// /// Discussion of this unsafety on Unix may be found in: /// -/// - [Austin Group Bugzilla](https://austingroupbugs.net/view.php?id=188) +/// - [Austin Group Bugzilla (for POSIX)](https://austingroupbugs.net/view.php?id=188) /// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2) /// /// To pass an environment variable to a child process, you can instead use [`Command::env`]. diff --git a/library/std/src/process.rs b/library/std/src/process.rs index bdd4844b6511..2ae93d84ba4b 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -2003,9 +2003,9 @@ impl ExitCode { /// /// Note that this has the same caveats as [`process::exit()`][exit], namely that this function /// terminates the process immediately, so no destructors on the current stack or any other - /// thread's stack will be run. If a clean shutdown is needed, it is recommended to simply - /// return this ExitCode from the `main` function, as demonstrated in the [type - /// documentation](#examples). + /// thread's stack will be run. Also see those docs for some important notes on interop with C + /// code. If a clean shutdown is needed, it is recommended to simply return this ExitCode from + /// the `main` function, as demonstrated in the [type documentation](#examples). /// /// # Differences from `process::exit()` /// @@ -2297,6 +2297,34 @@ impl Child { /// considered undesirable. Note that returning from `main` also calls `exit`, so making `exit` an /// unsafe operation is not an option.) /// +/// ## Safe interop with C code +/// +/// This function is safe to call as long as `exit` is only ever invoked from Rust. However, on some +/// platforms this function is implemented by calling the C function [`exit`][C-exit]. As of C23, +/// the C standard does not permit multiple threads to call `exit` concurrently. Rust mitigates this +/// with a lock, but if C code calls `exit`, that can still cause undefined behavior. Note that +/// returning from `main` is equivalent to calling `exit`. +/// +/// Therefore, it is undefined behavior to have two concurrent threads perform the following +/// without synchronization: +/// - One thread calls Rust's `exit` function or returns from Rust's `main` function +/// - Another thread calls the C function `exit` or `quick_exit`, or returns from C's `main` function +/// +/// Note that if a binary contains multiple copies of the Rust runtime (e.g., when combining +/// multiple `cdylib` or `staticlib`), they each have their own separate lock, so from the +/// perspective of code running in one of the Rust runtimes, the "outside" Rust code is basically C +/// code, and concurrent `exit` again causes undefined behavior. +/// +/// Individual C implementations might provide more guarantees than the standard and permit concurrent +/// calls to `exit`; consult the documentation of your C implementation for details. +/// +/// For some of the on-going discussion to make `exit` thread-safe in C, see: +/// - [Rust issue #126600](https://github.com/rust-lang/rust/issues/126600) +/// - [Austin Group Bugzilla (for POSIX)](https://austingroupbugs.net/view.php?id=1845) +/// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=31997) +/// +/// [C-exit]: https://en.cppreference.com/w/c/program/exit +/// /// ## Platform-specific behavior /// /// **Unix**: On Unix-like platforms, it is unlikely that all 32 bits of `exit` From 414136239bde39b9420e0f654a2fc8dc83fbbeb3 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Tue, 4 Mar 2025 08:28:42 +0100 Subject: [PATCH 091/745] Use the latest nightly rust to run linkcheck --- .github/workflows/remark.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/remark.yml b/.github/workflows/remark.yml index 13902f78b541..7e7e26818c09 100644 --- a/.github/workflows/remark.yml +++ b/.github/workflows/remark.yml @@ -37,6 +37,7 @@ jobs: - name: Linkcheck book run: | rustup toolchain install nightly --component rust-docs + rustup override set nightly curl https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/linkchecker/linkcheck.sh -o linkcheck.sh sh linkcheck.sh clippy --path ./book From e587a5d0f08ca138e42bff6f3308bc7950dc6b82 Mon Sep 17 00:00:00 2001 From: lapla-cogito Date: Mon, 17 Feb 2025 05:36:40 +0900 Subject: [PATCH 092/745] better help for `mixed_case_hex_literals` --- .../src/misc_early/mixed_case_hex_literals.rs | 33 +++++++++++--- tests/ui/literals.rs | 4 ++ tests/ui/literals.stderr | 45 +++++++++++++------ 3 files changed, 62 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/misc_early/mixed_case_hex_literals.rs b/clippy_lints/src/misc_early/mixed_case_hex_literals.rs index 9151cc633200..4fbd3c9874db 100644 --- a/clippy_lints/src/misc_early/mixed_case_hex_literals.rs +++ b/clippy_lints/src/misc_early/mixed_case_hex_literals.rs @@ -1,32 +1,51 @@ -use clippy_utils::diagnostics::span_lint; +use clippy_utils::diagnostics::span_lint_and_help; use rustc_lint::EarlyContext; use rustc_span::Span; use super::MIXED_CASE_HEX_LITERALS; pub(super) fn check(cx: &EarlyContext<'_>, lit_span: Span, suffix: &str, lit_snip: &str) { - let Some(maybe_last_sep_idx) = lit_snip.len().checked_sub(suffix.len() + 1) else { - return; // It's useless so shouldn't lint. + let num_end_idx = match lit_snip.strip_suffix(suffix) { + Some(p) if p.ends_with('_') => lit_snip.len() - (suffix.len() + 1), + Some(_) => lit_snip.len() - suffix.len(), + None => lit_snip.len(), }; - if maybe_last_sep_idx <= 2 { + + if num_end_idx <= 2 { // It's meaningless or causes range error. return; } + let mut seen = (false, false); - for ch in &lit_snip.as_bytes()[2..=maybe_last_sep_idx] { + for ch in &lit_snip.as_bytes()[2..num_end_idx] { match ch { b'a'..=b'f' => seen.0 = true, b'A'..=b'F' => seen.1 = true, _ => {}, } if seen.0 && seen.1 { - span_lint( + let raw_digits = &lit_snip[2..num_end_idx]; + let (sugg_lower, sugg_upper) = if suffix.is_empty() { + ( + format!("0x{}", raw_digits.to_lowercase()), + format!("0x{}", raw_digits.to_uppercase()), + ) + } else { + ( + format!("0x{}_{}", raw_digits.to_lowercase(), suffix), + format!("0x{}_{}", raw_digits.to_uppercase(), suffix), + ) + }; + + span_lint_and_help( cx, MIXED_CASE_HEX_LITERALS, lit_span, "inconsistent casing in hexadecimal literal", + None, + format!("consider using `{sugg_lower}` or `{sugg_upper}`"), ); - break; + return; } } } diff --git a/tests/ui/literals.rs b/tests/ui/literals.rs index d21d49310a07..ba343a8f62f8 100644 --- a/tests/ui/literals.rs +++ b/tests/ui/literals.rs @@ -30,6 +30,10 @@ fn main() { //~^ separated_literal_suffix //~| mixed_case_hex_literals + let fail2 = 0xab_CD_isize; + //~^ separated_literal_suffix + //~| mixed_case_hex_literals + let fail_multi_zero = 000_123usize; //~^ unseparated_literal_suffix //~| zero_prefixed_literal diff --git a/tests/ui/literals.stderr b/tests/ui/literals.stderr index d65cd3c89ebb..6bfeb91625b3 100644 --- a/tests/ui/literals.stderr +++ b/tests/ui/literals.stderr @@ -25,6 +25,7 @@ error: inconsistent casing in hexadecimal literal LL | let fail1 = 0xabCD; | ^^^^^^ | + = help: consider using `0xabcd` or `0xABCD` = note: `-D clippy::mixed-case-hex-literals` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::mixed_case_hex_literals)]` @@ -39,6 +40,8 @@ error: inconsistent casing in hexadecimal literal | LL | let fail2 = 0xabCD_u32; | ^^^^^^^^^^ + | + = help: consider using `0xabcd_u32` or `0xABCD_u32` error: integer type suffix should not be separated by an underscore --> tests/ui/literals.rs:29:17 @@ -51,9 +54,25 @@ error: inconsistent casing in hexadecimal literal | LL | let fail2 = 0xabCD_isize; | ^^^^^^^^^^^^ + | + = help: consider using `0xabcd_isize` or `0xABCD_isize` + +error: integer type suffix should not be separated by an underscore + --> tests/ui/literals.rs:33:17 + | +LL | let fail2 = 0xab_CD_isize; + | ^^^^^^^^^^^^^ help: remove the underscore: `0xab_CDisize` + +error: inconsistent casing in hexadecimal literal + --> tests/ui/literals.rs:33:17 + | +LL | let fail2 = 0xab_CD_isize; + | ^^^^^^^^^^^^^ + | + = help: consider using `0xab_cd_isize` or `0xAB_CD_isize` error: integer type suffix should be separated by an underscore - --> tests/ui/literals.rs:33:27 + --> tests/ui/literals.rs:37:27 | LL | let fail_multi_zero = 000_123usize; | ^^^^^^^^^^^^ help: add an underscore: `000_123_usize` @@ -62,7 +81,7 @@ LL | let fail_multi_zero = 000_123usize; = help: to override `-D warnings` add `#[allow(clippy::unseparated_literal_suffix)]` error: this is a decimal constant - --> tests/ui/literals.rs:33:27 + --> tests/ui/literals.rs:37:27 | LL | let fail_multi_zero = 000_123usize; | ^^^^^^^^^^^^ @@ -81,13 +100,13 @@ LL + let fail_multi_zero = 0o123usize; | error: integer type suffix should not be separated by an underscore - --> tests/ui/literals.rs:38:16 + --> tests/ui/literals.rs:42:16 | LL | let ok10 = 0_i64; | ^^^^^ help: remove the underscore: `0i64` error: this is a decimal constant - --> tests/ui/literals.rs:41:17 + --> tests/ui/literals.rs:45:17 | LL | let fail8 = 0123; | ^^^^ @@ -103,13 +122,13 @@ LL | let fail8 = 0o123; | + error: integer type suffix should not be separated by an underscore - --> tests/ui/literals.rs:51:16 + --> tests/ui/literals.rs:55:16 | LL | let ok17 = 0x123_4567_8901_usize; | ^^^^^^^^^^^^^^^^^^^^^ help: remove the underscore: `0x123_4567_8901usize` error: digits grouped inconsistently by underscores - --> tests/ui/literals.rs:56:18 + --> tests/ui/literals.rs:60:18 | LL | let fail19 = 12_3456_21; | ^^^^^^^^^^ help: consider: `12_345_621` @@ -118,19 +137,19 @@ LL | let fail19 = 12_3456_21; = help: to override `-D warnings` add `#[allow(clippy::inconsistent_digit_grouping)]` error: digits grouped inconsistently by underscores - --> tests/ui/literals.rs:59:18 + --> tests/ui/literals.rs:63:18 | LL | let fail22 = 3__4___23; | ^^^^^^^^^ help: consider: `3_423` error: digits grouped inconsistently by underscores - --> tests/ui/literals.rs:62:18 + --> tests/ui/literals.rs:66:18 | LL | let fail23 = 3__16___23; | ^^^^^^^^^^ help: consider: `31_623` error: digits of hex, binary or octal literal not in groups of equal size - --> tests/ui/literals.rs:65:18 + --> tests/ui/literals.rs:69:18 | LL | let fail24 = 0xAB_ABC_AB; | ^^^^^^^^^^^ help: consider: `0x0ABA_BCAB` @@ -139,7 +158,7 @@ LL | let fail24 = 0xAB_ABC_AB; = help: to override `-D warnings` add `#[allow(clippy::unusual_byte_groupings)]` error: this is a decimal constant - --> tests/ui/literals.rs:75:13 + --> tests/ui/literals.rs:79:13 | LL | let _ = 08; | ^^ @@ -151,7 +170,7 @@ LL + let _ = 8; | error: this is a decimal constant - --> tests/ui/literals.rs:78:13 + --> tests/ui/literals.rs:82:13 | LL | let _ = 09; | ^^ @@ -163,7 +182,7 @@ LL + let _ = 9; | error: this is a decimal constant - --> tests/ui/literals.rs:81:13 + --> tests/ui/literals.rs:85:13 | LL | let _ = 089; | ^^^ @@ -174,5 +193,5 @@ LL - let _ = 089; LL + let _ = 89; | -error: aborting due to 20 previous errors +error: aborting due to 22 previous errors From e6a4cf63adfaed64b74ed04441e902ce64a47116 Mon Sep 17 00:00:00 2001 From: lapla-cogito Date: Tue, 4 Mar 2025 10:50:40 +0900 Subject: [PATCH 093/745] don't trigger `unnecessary_debug_formatting` in tests --- clippy_lints/src/format_args.rs | 5 +++-- tests/ui/unnecessary_path_debug_formatting.rs | 6 ++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs index fc5f76179f90..3862ff7921db 100644 --- a/clippy_lints/src/format_args.rs +++ b/clippy_lints/src/format_args.rs @@ -9,7 +9,7 @@ use clippy_utils::macros::{ use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{SpanRangeExt, snippet}; use clippy_utils::ty::{implements_trait, is_type_lang_item}; -use clippy_utils::{is_diag_trait_item, is_from_proc_macro}; +use clippy_utils::{is_diag_trait_item, is_from_proc_macro, is_in_test}; use itertools::Itertools; use rustc_ast::{ FormatArgPosition, FormatArgPositionKind, FormatArgsPiece, FormatArgumentKind, FormatCount, FormatOptions, @@ -484,7 +484,8 @@ impl<'tcx> FormatArgsExpr<'_, 'tcx> { fn check_unnecessary_debug_formatting(&self, name: Symbol, value: &Expr<'tcx>) { let cx = self.cx; - if !value.span.from_expansion() + if !is_in_test(cx.tcx, value.hir_id) + && !value.span.from_expansion() && !is_from_proc_macro(cx, value) && let ty = cx.typeck_results().expr_ty(value) && self.can_display_format(ty) diff --git a/tests/ui/unnecessary_path_debug_formatting.rs b/tests/ui/unnecessary_path_debug_formatting.rs index 02adeece2809..f14f6085c9a1 100644 --- a/tests/ui/unnecessary_path_debug_formatting.rs +++ b/tests/ui/unnecessary_path_debug_formatting.rs @@ -41,3 +41,9 @@ fn main() { let deref_path = DerefPath { path }; println!("{:?}", &*deref_path); //~ unnecessary_debug_formatting } + +#[test] +fn issue_14345() { + let input = std::path::Path::new("/foo/bar"); + assert!(input.ends_with("baz"), "{input:?}"); +} From 9f0d819ced0be88286711817d4111ab45ce45afc Mon Sep 17 00:00:00 2001 From: decryphe <12104091+decryphe@users.noreply.github.com> Date: Mon, 3 Mar 2025 14:32:23 +0100 Subject: [PATCH 094/745] Create helper function to suggest a candidate in case of a typo --- clippy_config/src/conf.rs | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index a61acbaa96bc..5cde7c8ac35c 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -950,17 +950,10 @@ impl serde::de::Error for FieldError { } } - let suggestion = expected - .iter() - .filter_map(|expected| { - let dist = edit_distance(field, expected, 4)?; - Some((dist, expected)) - }) - .min_by_key(|&(dist, _)| dist) - .map(|(_, suggestion)| Suggestion { - message: "perhaps you meant", - suggestion, - }); + let suggestion = suggest_candidate(field, expected).map(|suggestion| Suggestion { + message: "perhaps you meant", + suggestion, + }); Self { error: msg, suggestion } } @@ -998,6 +991,22 @@ fn calculate_dimensions(fields: &[&str]) -> (usize, Vec) { (rows, column_widths) } +/// Given a user-provided value that couldn't be matched to a known option, finds the most likely +/// candidate among candidates that the user might have meant. +fn suggest_candidate<'a, I>(value: &str, candidates: I) -> Option<&'a str> +where + I: IntoIterator, +{ + candidates + .into_iter() + .filter_map(|expected| { + let dist = edit_distance(value, expected, 4)?; + Some((dist, expected)) + }) + .min_by_key(|&(dist, _)| dist) + .map(|(_, suggestion)| suggestion) +} + #[cfg(test)] mod tests { use serde::de::IgnoredAny; From 5df68878bf741c2a126b3032c2c3a5f60ac7e1e0 Mon Sep 17 00:00:00 2001 From: decryphe <12104091+decryphe@users.noreply.github.com> Date: Thu, 21 Nov 2024 18:43:52 +0100 Subject: [PATCH 095/745] Make alphabetic ordering in module item groups configurable (new default: off) From feedback to this lint after its inclusion in clippy 1.82, this has turned out to be the most requested improvement. With this improvement, it is possible to make the lint check certain top-level structural checks on modules (e.g. use statements and module inclusions at the top), but still leaving everything else up to the developer. --- CHANGELOG.md | 1 + book/src/lint_configuration.md | 13 + clippy_config/src/conf.rs | 47 +++- clippy_config/src/types.rs | 108 +++++++- .../src/arbitrary_source_item_ordering.rs | 62 +++-- .../bad_conf_4/clippy.toml | 1 + .../bad_conf_5/clippy.toml | 1 + .../bad_conf_6/clippy.toml | 1 + .../default_exp/clippy.toml | 2 +- .../ord_in_2/clippy.toml | 1 + .../ord_in_3/clippy.toml | 2 + .../ord_within/clippy.toml | 1 + .../ordering_good.bad_conf_4.stderr | 8 + .../ordering_good.bad_conf_5.stderr | 4 + .../ordering_good.bad_conf_6.stderr | 4 + .../ordering_good.rs | 8 +- .../ordering_mixed.default.stderr | 125 +++------- .../ordering_mixed.default_exp.stderr | 160 ++++++++++++ .../ordering_mixed.ord_within.stderr | 235 ++++++++++++++++++ .../ordering_mixed.rs | 14 +- .../selective_ordering.default.stderr | 19 ++ .../selective_ordering.ord_in_2.stderr | 36 +++ .../selective_ordering.ord_in_3.stderr | 19 ++ .../selective_ordering.ord_within.stderr | 48 ++++ .../selective_ordering.rs | 46 ++++ .../toml_unknown_key/conf_unknown_key.stderr | 3 + 26 files changed, 851 insertions(+), 118 deletions(-) create mode 100644 tests/ui-toml/arbitrary_source_item_ordering/bad_conf_4/clippy.toml create mode 100644 tests/ui-toml/arbitrary_source_item_ordering/bad_conf_5/clippy.toml create mode 100644 tests/ui-toml/arbitrary_source_item_ordering/bad_conf_6/clippy.toml create mode 100644 tests/ui-toml/arbitrary_source_item_ordering/ord_in_2/clippy.toml create mode 100644 tests/ui-toml/arbitrary_source_item_ordering/ord_in_3/clippy.toml create mode 100644 tests/ui-toml/arbitrary_source_item_ordering/ord_within/clippy.toml create mode 100644 tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_4.stderr create mode 100644 tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_5.stderr create mode 100644 tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_6.stderr create mode 100644 tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default_exp.stderr create mode 100644 tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.ord_within.stderr create mode 100644 tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.default.stderr create mode 100644 tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_2.stderr create mode 100644 tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_3.stderr create mode 100644 tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_within.stderr create mode 100644 tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 51441ab9fc0d..00323da7745a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6372,6 +6372,7 @@ Released 2018-09-13 [`min-ident-chars-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#min-ident-chars-threshold [`missing-docs-in-crate-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#missing-docs-in-crate-items [`module-item-order-groupings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#module-item-order-groupings +[`module-items-ordered-within-groupings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#module-items-ordered-within-groupings [`msrv`]: https://doc.rust-lang.org/clippy/lint_configuration.html#msrv [`pass-by-value-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pass-by-value-size-limit [`pub-underscore-fields-behavior`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pub-underscore-fields-behavior diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 28b613ea3295..3cd70ed18b59 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -744,6 +744,19 @@ The named groupings of different source item kinds within modules. * [`arbitrary_source_item_ordering`](https://rust-lang.github.io/rust-clippy/master/index.html#arbitrary_source_item_ordering) +## `module-items-ordered-within-groupings` +Whether the items within module groups should be ordered alphabetically or not. + +This option can be configured to "all", "none", or a list of specific grouping names that should be checked +(e.g. only "enums"). + +**Default Value:** `"none"` + +--- +**Affected lints:** +* [`arbitrary_source_item_ordering`](https://rust-lang.github.io/rust-clippy/master/index.html#arbitrary_source_item_ordering) + + ## `msrv` The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml` diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 5cde7c8ac35c..75f68d0dc5f9 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -3,14 +3,17 @@ use crate::types::{ DisallowedPath, DisallowedPathWithoutReplacement, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename, SourceItemOrdering, SourceItemOrderingCategory, SourceItemOrderingModuleItemGroupings, SourceItemOrderingModuleItemKind, SourceItemOrderingTraitAssocItemKind, SourceItemOrderingTraitAssocItemKinds, + SourceItemOrderingWithinModuleItemGroupings, }; use clippy_utils::msrvs::Msrv; +use itertools::Itertools; use rustc_errors::Applicability; use rustc_session::Session; use rustc_span::edit_distance::edit_distance; use rustc_span::{BytePos, Pos, SourceFile, Span, SyntaxContext}; use serde::de::{IgnoredAny, IntoDeserializer, MapAccess, Visitor}; use serde::{Deserialize, Deserializer, Serialize}; +use std::collections::HashMap; use std::fmt::{Debug, Display, Formatter}; use std::ops::Range; use std::path::PathBuf; @@ -79,6 +82,7 @@ const DEFAULT_SOURCE_ITEM_ORDERING: &[SourceItemOrderingCategory] = { #[derive(Default)] struct TryConf { conf: Conf, + value_spans: HashMap>, errors: Vec, warnings: Vec, } @@ -87,6 +91,7 @@ impl TryConf { fn from_toml_error(file: &SourceFile, error: &toml::de::Error) -> Self { Self { conf: Conf::default(), + value_spans: HashMap::default(), errors: vec![ConfError::from_toml(file, error)], warnings: vec![], } @@ -210,6 +215,7 @@ macro_rules! define_Conf { } fn visit_map(self, mut map: V) -> Result where V: MapAccess<'de> { + let mut value_spans = HashMap::new(); let mut errors = Vec::new(); let mut warnings = Vec::new(); $(let mut $name = None;)* @@ -232,6 +238,7 @@ macro_rules! define_Conf { } None => { $name = Some(value); + value_spans.insert(name.get_ref().as_str().to_string(), value_span); // $new_conf is the same as one of the defined `$name`s, so // this variable is defined in line 2 of this function. $(match $new_conf { @@ -250,7 +257,7 @@ macro_rules! define_Conf { } } let conf = Conf { $($name: $name.unwrap_or_else(defaults::$name),)* }; - Ok(TryConf { conf, errors, warnings }) + Ok(TryConf { conf, value_spans, errors, warnings }) } } @@ -596,6 +603,13 @@ define_Conf! { /// The named groupings of different source item kinds within modules. #[lints(arbitrary_source_item_ordering)] module_item_order_groupings: SourceItemOrderingModuleItemGroupings = DEFAULT_MODULE_ITEM_ORDERING_GROUPS.into(), + /// Whether the items within module groups should be ordered alphabetically or not. + /// + /// This option can be configured to "all", "none", or a list of specific grouping names that should be checked + /// (e.g. only "enums"). + #[lints(arbitrary_source_item_ordering)] + module_items_ordered_within_groupings: SourceItemOrderingWithinModuleItemGroupings = + SourceItemOrderingWithinModuleItemGroupings::None, /// The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml` #[default_text = "current version"] #[lints( @@ -815,6 +829,36 @@ fn deserialize(file: &SourceFile) -> TryConf { &mut conf.conf.allow_renamed_params_for, DEFAULT_ALLOWED_TRAITS_WITH_RENAMED_PARAMS, ); + + // Confirms that the user has not accidentally configured ordering requirements for groups that + // aren't configured. + if let SourceItemOrderingWithinModuleItemGroupings::Custom(groupings) = + &conf.conf.module_items_ordered_within_groupings + { + for grouping in groupings { + if !conf.conf.module_item_order_groupings.is_grouping(grouping) { + // Since this isn't fixable by rustfix, don't emit a `Suggestion`. This just adds some useful + // info for the user instead. + + let names = conf.conf.module_item_order_groupings.grouping_names(); + let suggestion = suggest_candidate(grouping, names.iter().map(String::as_str)) + .map(|s| format!(" perhaps you meant `{s}`?")) + .unwrap_or_default(); + let names = names.iter().map(|s| format!("`{s}`")).join(", "); + let message = format!( + "unknown ordering group: `{grouping}` was not specified in `module-items-ordered-within-groupings`,{suggestion} expected one of: {names}" + ); + + let span = conf + .value_spans + .get("module_item_order_groupings") + .cloned() + .unwrap_or_default(); + conf.errors.push(ConfError::spanned(file, message, None, span)); + } + } + } + // TODO: THIS SHOULD BE TESTED, this comment will be gone soon if conf.conf.allowed_idents_below_min_chars.iter().any(|e| e == "..") { conf.conf @@ -860,6 +904,7 @@ impl Conf { let TryConf { mut conf, + value_spans: _, errors, warnings, } = match path { diff --git a/clippy_config/src/types.rs b/clippy_config/src/types.rs index c72291e9799f..8faac9ecffea 100644 --- a/clippy_config/src/types.rs +++ b/clippy_config/src/types.rs @@ -305,6 +305,7 @@ impl SourceItemOrderingModuleItemKind { pub struct SourceItemOrderingModuleItemGroupings { groups: Vec<(String, Vec)>, lut: HashMap, + back_lut: HashMap, } impl SourceItemOrderingModuleItemGroupings { @@ -320,6 +321,30 @@ impl SourceItemOrderingModuleItemGroupings { lut } + fn build_back_lut( + groups: &[(String, Vec)], + ) -> HashMap { + let mut lut = HashMap::new(); + for (group_name, items) in groups { + for item in items { + lut.insert(item.clone(), group_name.clone()); + } + } + lut + } + + pub fn grouping_name_of(&self, item: &SourceItemOrderingModuleItemKind) -> Option<&String> { + self.back_lut.get(item) + } + + pub fn grouping_names(&self) -> Vec { + self.groups.iter().map(|(name, _)| name.clone()).collect() + } + + pub fn is_grouping(&self, grouping: &str) -> bool { + self.groups.iter().any(|(g, _)| g == grouping) + } + pub fn module_level_order_of(&self, item: &SourceItemOrderingModuleItemKind) -> Option { self.lut.get(item).copied() } @@ -330,7 +355,8 @@ impl From<&[(&str, &[SourceItemOrderingModuleItemKind])]> for SourceItemOrdering let groups: Vec<(String, Vec)> = value.iter().map(|item| (item.0.to_string(), item.1.to_vec())).collect(); let lut = Self::build_lut(&groups); - Self { groups, lut } + let back_lut = Self::build_back_lut(&groups); + Self { groups, lut, back_lut } } } @@ -348,6 +374,7 @@ impl<'de> Deserialize<'de> for SourceItemOrderingModuleItemGroupings { let groups = Vec::<(String, Vec)>::deserialize(deserializer)?; let items_total: usize = groups.iter().map(|(_, v)| v.len()).sum(); let lut = Self::build_lut(&groups); + let back_lut = Self::build_back_lut(&groups); let mut expected_items = SourceItemOrderingModuleItemKind::all_variants(); for item in lut.keys() { @@ -370,7 +397,7 @@ impl<'de> Deserialize<'de> for SourceItemOrderingModuleItemGroupings { )); } - Ok(Self { groups, lut }) + Ok(Self { groups, lut, back_lut }) } else if items_total != all_items.len() { Err(de::Error::custom(format!( "Some module item kinds were configured more than once, or were missing, in the source ordering configuration. \ @@ -482,6 +509,83 @@ impl Serialize for SourceItemOrderingTraitAssocItemKinds { } } +/// Describes which specific groupings should have their items ordered +/// alphabetically. +/// +/// This is separate from defining and enforcing groupings. For example, +/// defining enums are grouped before structs still allows for an enum B to be +/// placed before an enum A. Only when enforcing ordering within the grouping, +/// will it be checked if A is placed before B. +#[derive(Clone, Debug)] +pub enum SourceItemOrderingWithinModuleItemGroupings { + /// All groupings should have their items ordered. + All, + + /// None of the groupings should have their order checked. + None, + + /// Only the specified groupings should have their order checked. + Custom(Vec), +} + +impl SourceItemOrderingWithinModuleItemGroupings { + pub fn ordered_within(&self, grouping_name: &String) -> bool { + match self { + SourceItemOrderingWithinModuleItemGroupings::All => true, + SourceItemOrderingWithinModuleItemGroupings::None => false, + SourceItemOrderingWithinModuleItemGroupings::Custom(groups) => groups.contains(grouping_name), + } + } +} + +/// Helper struct for deserializing the [`SourceItemOrderingWithinModuleItemGroupings`]. +#[derive(Deserialize)] +#[serde(untagged)] +enum StringOrVecOfString { + String(String), + Vec(Vec), +} + +impl<'de> Deserialize<'de> for SourceItemOrderingWithinModuleItemGroupings { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let description = "The available options for configuring an ordering within module item groups are: \ + \"all\", \"none\", or a list of module item group names \ + (as configured with the `module-item-order-groupings` configuration option)."; + + match StringOrVecOfString::deserialize(deserializer) { + Ok(StringOrVecOfString::String(preset)) if preset == "all" => { + Ok(SourceItemOrderingWithinModuleItemGroupings::All) + }, + Ok(StringOrVecOfString::String(preset)) if preset == "none" => { + Ok(SourceItemOrderingWithinModuleItemGroupings::None) + }, + Ok(StringOrVecOfString::String(preset)) => Err(de::Error::custom(format!( + "Unknown configuration option: {preset}.\n{description}" + ))), + Ok(StringOrVecOfString::Vec(groupings)) => { + Ok(SourceItemOrderingWithinModuleItemGroupings::Custom(groupings)) + }, + Err(e) => Err(de::Error::custom(format!("{e}\n{description}"))), + } + } +} + +impl Serialize for SourceItemOrderingWithinModuleItemGroupings { + fn serialize(&self, serializer: S) -> Result + where + S: ser::Serializer, + { + match self { + SourceItemOrderingWithinModuleItemGroupings::All => serializer.serialize_str("all"), + SourceItemOrderingWithinModuleItemGroupings::None => serializer.serialize_str("none"), + SourceItemOrderingWithinModuleItemGroupings::Custom(vec) => vec.serialize(serializer), + } + } +} + // these impls are never actually called but are used by the various config options that default to // empty lists macro_rules! unimplemented_serialize { diff --git a/clippy_lints/src/arbitrary_source_item_ordering.rs b/clippy_lints/src/arbitrary_source_item_ordering.rs index c0ae4960e10d..cf4fe45936c9 100644 --- a/clippy_lints/src/arbitrary_source_item_ordering.rs +++ b/clippy_lints/src/arbitrary_source_item_ordering.rs @@ -2,6 +2,7 @@ use clippy_config::Conf; use clippy_config::types::{ SourceItemOrderingCategory, SourceItemOrderingModuleItemGroupings, SourceItemOrderingModuleItemKind, SourceItemOrderingTraitAssocItemKind, SourceItemOrderingTraitAssocItemKinds, + SourceItemOrderingWithinModuleItemGroupings, }; use clippy_utils::diagnostics::span_lint_and_note; use rustc_hir::{ @@ -36,7 +37,7 @@ declare_clippy_lint! { /// 2. Individual ordering rules per item kind. /// /// The item kinds that can be linted are: - /// - Module (with customized groupings, alphabetical within) + /// - Module (with customized groupings, alphabetical within - configurable) /// - Trait (with customized order of associated items, alphabetical within) /// - Enum, Impl, Struct (purely alphabetical) /// @@ -57,8 +58,31 @@ declare_clippy_lint! { /// | `PascalCase` | "ty_alias", "opaque_ty", "enum", "struct", "union", "trait", "trait_alias", "impl" | /// | `lower_snake_case` | "fn" | /// + /// The groups' names are arbitrary and can be changed to suit the + /// conventions that should be enforced for a specific project. + /// /// All item kinds must be accounted for to create an enforceable linting - /// rule set. + /// rule set. Following are some example configurations that may be useful. + /// + /// Example: *module inclusions and use statements to be at the top* + /// + /// ```toml + /// module-item-order-groupings = [ + /// [ "modules", [ "extern_crate", "mod", "foreign_mod" ], ], + /// [ "use", [ "use", ], ], + /// [ "everything_else", [ "macro", "global_asm", "static", "const", "ty_alias", "enum", "struct", "union", "trait", "trait_alias", "impl", "fn", ], ], + /// ] + /// ``` + /// + /// Example: *only consts and statics should be alphabetically ordered* + /// + /// It is also possible to configure a selection of module item groups that + /// should be ordered alphabetically. This may be useful if for example + /// statics and consts should be ordered, but the rest should be left open. + /// + /// ```toml + /// module-items-ordered-within-groupings = ["UPPER_SNAKE_CASE"] + /// ``` /// /// ### Known Problems /// @@ -143,6 +167,7 @@ pub struct ArbitrarySourceItemOrdering { enable_ordering_for_struct: bool, enable_ordering_for_trait: bool, module_item_order_groupings: SourceItemOrderingModuleItemGroupings, + module_items_ordered_within_groupings: SourceItemOrderingWithinModuleItemGroupings, } impl ArbitrarySourceItemOrdering { @@ -157,6 +182,7 @@ impl ArbitrarySourceItemOrdering { enable_ordering_for_struct: conf.source_item_ordering.contains(&Struct), enable_ordering_for_trait: conf.source_item_ordering.contains(&Trait), module_item_order_groupings: conf.module_item_order_groupings.clone(), + module_items_ordered_within_groupings: conf.module_items_ordered_within_groupings.clone(), } } @@ -191,7 +217,7 @@ impl ArbitrarySourceItemOrdering { ); } - fn lint_member_item(cx: &T, item: &Item<'_>, before_item: &Item<'_>) { + fn lint_member_item(cx: &T, item: &Item<'_>, before_item: &Item<'_>, msg: &'static str) { let span = if item.ident.as_str().is_empty() { &item.span } else { @@ -215,14 +241,7 @@ impl ArbitrarySourceItemOrdering { return; } - span_lint_and_note( - cx, - ARBITRARY_SOURCE_ITEM_ORDERING, - *span, - "incorrect ordering of items (must be alphabetically ordered)", - Some(*before_span), - note, - ); + span_lint_and_note(cx, ARBITRARY_SOURCE_ITEM_ORDERING, *span, msg, Some(*before_span), note); } /// Produces a linting warning for incorrectly ordered trait items. @@ -402,6 +421,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { } let item_kind = convert_module_item_kind(&item.kind); + let grouping_name = self.module_item_order_groupings.grouping_name_of(&item_kind); let module_level_order = self .module_item_order_groupings .module_level_order_of(&item_kind) @@ -411,13 +431,27 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { use std::cmp::Ordering; // Better legibility. match module_level_order.cmp(&cur_t.order) { Ordering::Less => { - Self::lint_member_item(cx, item, cur_t.item); + Self::lint_member_item( + cx, + item, + cur_t.item, + "incorrect ordering of items (module item groupings specify another order)", + ); }, Ordering::Equal if item_kind == SourceItemOrderingModuleItemKind::Use => { // Skip ordering use statements, as these should be ordered by rustfmt. }, - Ordering::Equal if cur_t.name > get_item_name(item) => { - Self::lint_member_item(cx, item, cur_t.item); + Ordering::Equal + if (grouping_name.is_some_and(|grouping_name| { + self.module_items_ordered_within_groupings.ordered_within(grouping_name) + }) && cur_t.name > get_item_name(item)) => + { + Self::lint_member_item( + cx, + item, + cur_t.item, + "incorrect ordering of items (must be alphabetically ordered)", + ); }, Ordering::Equal | Ordering::Greater => { // Nothing to do in this case, they're already in the right order. diff --git a/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_4/clippy.toml b/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_4/clippy.toml new file mode 100644 index 000000000000..baf7041138f9 --- /dev/null +++ b/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_4/clippy.toml @@ -0,0 +1 @@ +module-items-ordered-within-groupings = true diff --git a/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_5/clippy.toml b/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_5/clippy.toml new file mode 100644 index 000000000000..1fa80c730126 --- /dev/null +++ b/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_5/clippy.toml @@ -0,0 +1 @@ +module-items-ordered-within-groupings = ["madules"] diff --git a/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_6/clippy.toml b/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_6/clippy.toml new file mode 100644 index 000000000000..cee857a155b9 --- /dev/null +++ b/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_6/clippy.toml @@ -0,0 +1 @@ +module-items-ordered-within-groupings = ["entirely garbled"] diff --git a/tests/ui-toml/arbitrary_source_item_ordering/default_exp/clippy.toml b/tests/ui-toml/arbitrary_source_item_ordering/default_exp/clippy.toml index ddca5cfa5779..af3aa1cc62a4 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/default_exp/clippy.toml +++ b/tests/ui-toml/arbitrary_source_item_ordering/default_exp/clippy.toml @@ -9,4 +9,4 @@ module-item-order-groupings = [ ["PascalCase", ["ty_alias", "enum", "struct", "union", "trait", "trait_alias", "impl"]], ["lower_snake_case", ["fn"]] ] - +module-items-ordered-within-groupings = "none" diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ord_in_2/clippy.toml b/tests/ui-toml/arbitrary_source_item_ordering/ord_in_2/clippy.toml new file mode 100644 index 000000000000..fd961c82d6f2 --- /dev/null +++ b/tests/ui-toml/arbitrary_source_item_ordering/ord_in_2/clippy.toml @@ -0,0 +1 @@ +module-items-ordered-within-groupings = ["PascalCase"] diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ord_in_3/clippy.toml b/tests/ui-toml/arbitrary_source_item_ordering/ord_in_3/clippy.toml new file mode 100644 index 000000000000..de2a7307eca6 --- /dev/null +++ b/tests/ui-toml/arbitrary_source_item_ordering/ord_in_3/clippy.toml @@ -0,0 +1,2 @@ +source-item-ordering = ["module"] +module-items-ordered-within-groupings = ["PascalCase"] diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ord_within/clippy.toml b/tests/ui-toml/arbitrary_source_item_ordering/ord_within/clippy.toml new file mode 100644 index 000000000000..e7640efde10c --- /dev/null +++ b/tests/ui-toml/arbitrary_source_item_ordering/ord_within/clippy.toml @@ -0,0 +1 @@ +module-items-ordered-within-groupings = "all" diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_4.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_4.stderr new file mode 100644 index 000000000000..c38c54ffeb0d --- /dev/null +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_4.stderr @@ -0,0 +1,8 @@ +error: error reading Clippy's configuration file: data did not match any variant of untagged enum StringOrVecOfString The available options for configuring an ordering within module item groups are: "all", "none", or a list of module item group names (as configured with the `module-item-order-groupings` configuration option). + --> $DIR/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_4/clippy.toml:1:41 + | +LL | module-items-ordered-within-groupings = true + | ^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_5.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_5.stderr new file mode 100644 index 000000000000..7b1dafb6d0d5 --- /dev/null +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_5.stderr @@ -0,0 +1,4 @@ +error: error reading Clippy's configuration file: unknown ordering group: `madules` was not specified in `module-items-ordered-within-groupings`, perhaps you meant `modules`? expected one of: `modules`, `use`, `macros`, `global_asm`, `UPPER_SNAKE_CASE`, `PascalCase`, `lower_snake_case` + +error: aborting due to 1 previous error + diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_6.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_6.stderr new file mode 100644 index 000000000000..996cabeeed4a --- /dev/null +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_6.stderr @@ -0,0 +1,4 @@ +error: error reading Clippy's configuration file: unknown ordering group: `entirely garbled` was not specified in `module-items-ordered-within-groupings`, expected one of: `modules`, `use`, `macros`, `global_asm`, `UPPER_SNAKE_CASE`, `PascalCase`, `lower_snake_case` + +error: aborting due to 1 previous error + diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs index 05eb40506db4..b43791521cb5 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs @@ -1,15 +1,21 @@ //@aux-build:../../ui/auxiliary/proc_macros.rs -//@revisions: default default_exp bad_conf_1 bad_conf_2 bad_conf_3 +//@revisions: default default_exp bad_conf_1 bad_conf_2 bad_conf_3 bad_conf_4 bad_conf_5 bad_conf_6 //@[default] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/default //@[default_exp] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/default_exp //@[bad_conf_1] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_1 //@[bad_conf_2] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_2 //@[bad_conf_3] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_3 +//@[bad_conf_4] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_4 +//@[bad_conf_5] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_5 +//@[bad_conf_6] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_6 //@[default] check-pass //@[default_exp] check-pass //@[bad_conf_1] error-in-other-file: //@[bad_conf_2] error-in-other-file: //@[bad_conf_3] error-in-other-file: +//@[bad_conf_4] error-in-other-file: +//@[bad_conf_5] error-in-other-file: +//@[bad_conf_6] error-in-other-file: #![allow(dead_code)] #![warn(clippy::arbitrary_source_item_ordering)] diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr index 3605952bddc9..50567e32b1bb 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr @@ -1,223 +1,160 @@ -error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:22:14 +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:26:14 | LL | use std::rc::Weak; | ^^^^ | note: should be placed before `SNAKE_CASE` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:20:7 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:23:7 | LL | const SNAKE_CASE: &str = "zzzzzzzz"; | ^^^^^^^^^^ = note: `-D clippy::arbitrary-source-item-ordering` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]` -error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:67:1 - | -LL | / impl CloneSelf for StructOrdered { -LL | | -LL | | fn clone_self(&self) -> Self { -LL | | Self { -... | -LL | | } - | |_^ - | -note: should be placed before the following item - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:57:1 - | -LL | / impl Default for StructOrdered { -LL | | fn default() -> Self { -LL | | Self { -LL | | a: true, -... | -LL | | } - | |_^ - -error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:145:7 +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:149:7 | LL | const ZIS_SHOULD_BE_REALLY_EARLY: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before `TraitUnorderedItemKinds` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:132:7 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:136:7 | LL | trait TraitUnorderedItemKinds { | ^^^^^^^^^^^^^^^^^^^^^^^ -error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:163:1 - | -LL | impl BasicEmptyTrait for StructOrdered {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: should be placed before the following item - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:148:1 - | -LL | / impl TraitUnordered for StructUnordered { -LL | | const A: bool = false; -LL | | const C: bool = false; -LL | | const B: bool = false; -... | -LL | | } - | |_^ - -error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:184:5 +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:188:5 | LL | mod this_is_in_the_wrong_position { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before `main` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:179:4 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:183:4 | LL | fn main() { | ^^^^ -error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:194:7 +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:198:7 | LL | const ZIS_SHOULD_BE_EVEN_EARLIER: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before `ZisShouldBeBeforeZeMainFn` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:192:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:196:8 | LL | struct ZisShouldBeBeforeZeMainFn; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:12:11 - | -LL | const AFTER: i8 = 0; - | ^^^^^ - | -note: should be placed before `BEFORE` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:10:11 - | -LL | const BEFORE: i8 = 0; - | ^^^^^^ - -error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:40:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:44:5 | LL | B, | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:39:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:43:5 | LL | C, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:92:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:96:5 | LL | b: bool, | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:91:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:95:5 | LL | c: bool, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:101:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:105:5 | LL | b: bool, | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:100:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:104:5 | LL | c: bool, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:121:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:125:11 | LL | const B: bool; | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:120:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:124:11 | LL | const C: bool; | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:128:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:132:8 | LL | fn b(); | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:127:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:131:8 | LL | fn c(); | ^ error: incorrect ordering of trait items (defined order: [Const, Type, Fn]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:135:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:139:5 | LL | const A: bool; | ^^^^^^^^^^^^^^ | note: should be placed before `SomeType` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:133:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:137:5 | LL | type SomeType; | ^^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:151:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:155:11 | LL | const B: bool = false; | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:150:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:154:11 | LL | const C: bool = false; | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:158:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:162:8 | LL | fn b() {} | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:157:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:161:8 | LL | fn c() {} | ^ error: incorrect ordering of impl items (defined order: [Const, Type, Fn]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:169:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:173:5 | LL | const A: bool = false; | ^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before `SomeType` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:167:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:171:5 | LL | type SomeType = (); | ^^^^^^^^^^^^^^^^^^^ -error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:187:11 - | -LL | const A: i8 = 1; - | ^ - | -note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:186:11 - | -LL | const C: i8 = 0; - | ^ - -error: aborting due to 17 previous errors +error: aborting due to 13 previous errors diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default_exp.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default_exp.stderr new file mode 100644 index 000000000000..50567e32b1bb --- /dev/null +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default_exp.stderr @@ -0,0 +1,160 @@ +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:26:14 + | +LL | use std::rc::Weak; + | ^^^^ + | +note: should be placed before `SNAKE_CASE` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:23:7 + | +LL | const SNAKE_CASE: &str = "zzzzzzzz"; + | ^^^^^^^^^^ + = note: `-D clippy::arbitrary-source-item-ordering` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]` + +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:149:7 + | +LL | const ZIS_SHOULD_BE_REALLY_EARLY: () = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `TraitUnorderedItemKinds` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:136:7 + | +LL | trait TraitUnorderedItemKinds { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:188:5 + | +LL | mod this_is_in_the_wrong_position { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `main` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:183:4 + | +LL | fn main() { + | ^^^^ + +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:198:7 + | +LL | const ZIS_SHOULD_BE_EVEN_EARLIER: () = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `ZisShouldBeBeforeZeMainFn` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:196:8 + | +LL | struct ZisShouldBeBeforeZeMainFn; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:44:5 + | +LL | B, + | ^ + | +note: should be placed before `C` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:43:5 + | +LL | C, + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:96:5 + | +LL | b: bool, + | ^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:95:5 + | +LL | c: bool, + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:105:5 + | +LL | b: bool, + | ^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:104:5 + | +LL | c: bool, + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:125:11 + | +LL | const B: bool; + | ^ + | +note: should be placed before `C` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:124:11 + | +LL | const C: bool; + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:132:8 + | +LL | fn b(); + | ^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:131:8 + | +LL | fn c(); + | ^ + +error: incorrect ordering of trait items (defined order: [Const, Type, Fn]) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:139:5 + | +LL | const A: bool; + | ^^^^^^^^^^^^^^ + | +note: should be placed before `SomeType` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:137:5 + | +LL | type SomeType; + | ^^^^^^^^^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:155:11 + | +LL | const B: bool = false; + | ^ + | +note: should be placed before `C` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:154:11 + | +LL | const C: bool = false; + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:162:8 + | +LL | fn b() {} + | ^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:161:8 + | +LL | fn c() {} + | ^ + +error: incorrect ordering of impl items (defined order: [Const, Type, Fn]) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:173:5 + | +LL | const A: bool = false; + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `SomeType` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:171:5 + | +LL | type SomeType = (); + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 13 previous errors + diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.ord_within.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.ord_within.stderr new file mode 100644 index 000000000000..ae5261dcc6df --- /dev/null +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.ord_within.stderr @@ -0,0 +1,235 @@ +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:23:7 + | +LL | const SNAKE_CASE: &str = "zzzzzzzz"; + | ^^^^^^^^^^ + | +note: should be placed before `ZNAKE_CASE` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:22:7 + | +LL | const ZNAKE_CASE: &str = "123"; + | ^^^^^^^^^^ + = note: `-D clippy::arbitrary-source-item-ordering` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]` + +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:26:14 + | +LL | use std::rc::Weak; + | ^^^^ + | +note: should be placed before `SNAKE_CASE` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:23:7 + | +LL | const SNAKE_CASE: &str = "zzzzzzzz"; + | ^^^^^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:71:1 + | +LL | / impl CloneSelf for StructOrdered { +LL | | +LL | | fn clone_self(&self) -> Self { +LL | | Self { +... | +LL | | } + | |_^ + | +note: should be placed before the following item + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:61:1 + | +LL | / impl Default for StructOrdered { +LL | | fn default() -> Self { +LL | | Self { +LL | | a: true, +... | +LL | | } + | |_^ + +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:149:7 + | +LL | const ZIS_SHOULD_BE_REALLY_EARLY: () = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `TraitUnorderedItemKinds` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:136:7 + | +LL | trait TraitUnorderedItemKinds { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:167:1 + | +LL | impl BasicEmptyTrait for StructOrdered {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before the following item + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:152:1 + | +LL | / impl TraitUnordered for StructUnordered { +LL | | const A: bool = false; +LL | | const C: bool = false; +LL | | const B: bool = false; +... | +LL | | } + | |_^ + +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:188:5 + | +LL | mod this_is_in_the_wrong_position { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `main` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:183:4 + | +LL | fn main() { + | ^^^^ + +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:198:7 + | +LL | const ZIS_SHOULD_BE_EVEN_EARLIER: () = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `ZisShouldBeBeforeZeMainFn` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:196:8 + | +LL | struct ZisShouldBeBeforeZeMainFn; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:14:11 + | +LL | const AFTER: i8 = 0; + | ^^^^^ + | +note: should be placed before `BEFORE` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:12:11 + | +LL | const BEFORE: i8 = 0; + | ^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:44:5 + | +LL | B, + | ^ + | +note: should be placed before `C` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:43:5 + | +LL | C, + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:96:5 + | +LL | b: bool, + | ^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:95:5 + | +LL | c: bool, + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:105:5 + | +LL | b: bool, + | ^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:104:5 + | +LL | c: bool, + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:125:11 + | +LL | const B: bool; + | ^ + | +note: should be placed before `C` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:124:11 + | +LL | const C: bool; + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:132:8 + | +LL | fn b(); + | ^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:131:8 + | +LL | fn c(); + | ^ + +error: incorrect ordering of trait items (defined order: [Const, Type, Fn]) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:139:5 + | +LL | const A: bool; + | ^^^^^^^^^^^^^^ + | +note: should be placed before `SomeType` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:137:5 + | +LL | type SomeType; + | ^^^^^^^^^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:155:11 + | +LL | const B: bool = false; + | ^ + | +note: should be placed before `C` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:154:11 + | +LL | const C: bool = false; + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:162:8 + | +LL | fn b() {} + | ^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:161:8 + | +LL | fn c() {} + | ^ + +error: incorrect ordering of impl items (defined order: [Const, Type, Fn]) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:173:5 + | +LL | const A: bool = false; + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `SomeType` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:171:5 + | +LL | type SomeType = (); + | ^^^^^^^^^^^^^^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:191:11 + | +LL | const A: i8 = 1; + | ^ + | +note: should be placed before `C` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:190:11 + | +LL | const C: i8 = 0; + | ^ + +error: aborting due to 18 previous errors + diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs index 9e65a9cca0da..90399470d4c0 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs @@ -1,6 +1,8 @@ //@aux-build:../../ui/auxiliary/proc_macros.rs -//@revisions: default +//@revisions: default default_exp ord_within //@[default] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/default +//@[default_exp] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/default_exp +//@[ord_within] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/ord_within #![allow(dead_code)] #![warn(clippy::arbitrary_source_item_ordering)] @@ -10,14 +12,16 @@ mod i_am_just_right { const BEFORE: i8 = 0; const AFTER: i8 = 0; - //~^ arbitrary_source_item_ordering + //~[ord_within]^ arbitrary_source_item_ordering } // Use statements should not be linted internally - this is normally auto-sorted using rustfmt. use std::rc::Rc; use std::sync::{Arc, Barrier, RwLock}; +const ZNAKE_CASE: &str = "123"; const SNAKE_CASE: &str = "zzzzzzzz"; +//~[ord_within]^ arbitrary_source_item_ordering use std::rc::Weak; //~^ arbitrary_source_item_ordering @@ -65,7 +69,7 @@ impl Default for StructOrdered { } impl CloneSelf for StructOrdered { - //~^ arbitrary_source_item_ordering + //~[ord_within]^ arbitrary_source_item_ordering fn clone_self(&self) -> Self { Self { a: true, @@ -161,7 +165,7 @@ impl TraitUnordered for StructUnordered { // Trait impls should be located just after the type they implement it for. impl BasicEmptyTrait for StructOrdered {} -//~^ arbitrary_source_item_ordering +//~[ord_within]^ arbitrary_source_item_ordering impl TraitUnorderedItemKinds for StructUnordered { type SomeType = (); @@ -185,7 +189,7 @@ mod this_is_in_the_wrong_position { //~^ arbitrary_source_item_ordering const C: i8 = 0; const A: i8 = 1; - //~^ arbitrary_source_item_ordering + //~[ord_within]^ arbitrary_source_item_ordering } #[derive(Default, std::clone::Clone)] diff --git a/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.default.stderr b/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.default.stderr new file mode 100644 index 000000000000..7fc216b30d50 --- /dev/null +++ b/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.default.stderr @@ -0,0 +1,19 @@ +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:35:5 + | +LL | a: bool, + | ^ + | +note: should be placed before `b` + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:34:5 + | +LL | b: bool, + | ^ +note: the lint level is defined here + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:32:8 + | +LL | #[deny(clippy::arbitrary_source_item_ordering)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_2.stderr b/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_2.stderr new file mode 100644 index 000000000000..1f75f5099ecc --- /dev/null +++ b/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_2.stderr @@ -0,0 +1,36 @@ +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:24:8 + | +LL | struct OrderedChecked { + | ^^^^^^^^^^^^^^ + | +note: should be placed before `Unordered` + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:18:8 + | +LL | struct Unordered { + | ^^^^^^^^^ +note: the lint level is defined here + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:9:9 + | +LL | #![deny(clippy::arbitrary_source_item_ordering)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:35:5 + | +LL | a: bool, + | ^ + | +note: should be placed before `b` + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:34:5 + | +LL | b: bool, + | ^ +note: the lint level is defined here + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:32:8 + | +LL | #[deny(clippy::arbitrary_source_item_ordering)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_3.stderr b/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_3.stderr new file mode 100644 index 000000000000..8027f55add67 --- /dev/null +++ b/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_3.stderr @@ -0,0 +1,19 @@ +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:24:8 + | +LL | struct OrderedChecked { + | ^^^^^^^^^^^^^^ + | +note: should be placed before `Unordered` + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:18:8 + | +LL | struct Unordered { + | ^^^^^^^^^ +note: the lint level is defined here + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:9:9 + | +LL | #![deny(clippy::arbitrary_source_item_ordering)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_within.stderr b/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_within.stderr new file mode 100644 index 000000000000..333a601f6a95 --- /dev/null +++ b/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_within.stderr @@ -0,0 +1,48 @@ +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:24:8 + | +LL | struct OrderedChecked { + | ^^^^^^^^^^^^^^ + | +note: should be placed before `Unordered` + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:18:8 + | +LL | struct Unordered { + | ^^^^^^^^^ +note: the lint level is defined here + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:9:9 + | +LL | #![deny(clippy::arbitrary_source_item_ordering)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:45:4 + | +LL | fn before_main() {} + | ^^^^^^^^^^^ + | +note: should be placed before `main` + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:41:4 + | +LL | fn main() { + | ^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:35:5 + | +LL | a: bool, + | ^ + | +note: should be placed before `b` + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:34:5 + | +LL | b: bool, + | ^ +note: the lint level is defined here + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:32:8 + | +LL | #[deny(clippy::arbitrary_source_item_ordering)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs b/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs new file mode 100644 index 000000000000..e32b921dd965 --- /dev/null +++ b/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs @@ -0,0 +1,46 @@ +//@aux-build:../../ui/auxiliary/proc_macros.rs +//@revisions: default ord_within ord_in_2 ord_in_3 +//@[default] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/default +//@[ord_within] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/ord_within +//@[ord_in_2] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/ord_in_2 +//@[ord_in_3] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/ord_in_3 + +#![allow(dead_code)] +#![deny(clippy::arbitrary_source_item_ordering)] + +#[allow(clippy::arbitrary_source_item_ordering)] +struct Ordered { + a: bool, + b: bool, +} + +#[allow(clippy::arbitrary_source_item_ordering)] +struct Unordered { + b: bool, + a: bool, +} + +#[deny(clippy::arbitrary_source_item_ordering)] +struct OrderedChecked { + //~[ord_within]^ arbitrary_source_item_ordering + //~[ord_in_2]| arbitrary_source_item_ordering + //~[ord_in_3]| arbitrary_source_item_ordering + a: bool, + b: bool, +} + +#[deny(clippy::arbitrary_source_item_ordering)] +struct UnorderedChecked { + b: bool, + a: bool, + //~[ord_within]^ arbitrary_source_item_ordering + //~[default]| arbitrary_source_item_ordering + //~[ord_in_2]| arbitrary_source_item_ordering +} + +fn main() { + // test code goes here +} + +fn before_main() {} +//~[ord_within]^ arbitrary_source_item_ordering diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index acfe739277cc..fee5b01b6898 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -60,6 +60,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect min-ident-chars-threshold missing-docs-in-crate-items module-item-order-groupings + module-items-ordered-within-groupings msrv pass-by-value-size-limit pub-underscore-fields-behavior @@ -152,6 +153,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect min-ident-chars-threshold missing-docs-in-crate-items module-item-order-groupings + module-items-ordered-within-groupings msrv pass-by-value-size-limit pub-underscore-fields-behavior @@ -244,6 +246,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni min-ident-chars-threshold missing-docs-in-crate-items module-item-order-groupings + module-items-ordered-within-groupings msrv pass-by-value-size-limit pub-underscore-fields-behavior From 9275ae994bb37415b490634a3b9bf7a5090b7afc Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Tue, 4 Mar 2025 11:57:23 +0100 Subject: [PATCH 096/745] Walk back to the root context to compute the span Since the error kind (`io::ErrorKind::other`) is in the root context, the error message must be found in the root context as well to compute the correct span to remove. --- clippy_lints/src/methods/io_other_error.rs | 2 +- tests/ui/io_other_error.fixed | 5 +++++ tests/ui/io_other_error.rs | 5 +++++ tests/ui/io_other_error.stderr | 14 +++++++++++++- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/methods/io_other_error.rs b/clippy_lints/src/methods/io_other_error.rs index 4659e9e163fe..bdc834bd47a5 100644 --- a/clippy_lints/src/methods/io_other_error.rs +++ b/clippy_lints/src/methods/io_other_error.rs @@ -27,7 +27,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, path: &Expr<'_>, args "use `std::io::Error::other`", vec![ (new_segment.ident.span, "other".to_owned()), - (error_kind.span.until(error.span), String::new()), + (error_kind.span.until(error.span.source_callsite()), String::new()), ], Applicability::MachineApplicable, ); diff --git a/tests/ui/io_other_error.fixed b/tests/ui/io_other_error.fixed index 0054c56fb628..ce7e8ef281f7 100644 --- a/tests/ui/io_other_error.fixed +++ b/tests/ui/io_other_error.fixed @@ -53,3 +53,8 @@ mod paths { fn under_msrv() { let _err = std::io::Error::new(std::io::ErrorKind::Other, E); } + +pub fn issue14346(x: i32) -> std::io::Error { + std::io::Error::other(format!("{x}")) + //~^ ERROR: this can be `std::io::Error::other(_)` +} diff --git a/tests/ui/io_other_error.rs b/tests/ui/io_other_error.rs index 8529fb9a77f9..b66e7f88ab14 100644 --- a/tests/ui/io_other_error.rs +++ b/tests/ui/io_other_error.rs @@ -53,3 +53,8 @@ mod paths { fn under_msrv() { let _err = std::io::Error::new(std::io::ErrorKind::Other, E); } + +pub fn issue14346(x: i32) -> std::io::Error { + std::io::Error::new(std::io::ErrorKind::Other, format!("{x}")) + //~^ ERROR: this can be `std::io::Error::other(_)` +} diff --git a/tests/ui/io_other_error.stderr b/tests/ui/io_other_error.stderr index e79e05ecd406..b37e3d15064f 100644 --- a/tests/ui/io_other_error.stderr +++ b/tests/ui/io_other_error.stderr @@ -48,5 +48,17 @@ LL - let _err = io::Error::new(io::ErrorKind::Other, super::E); LL + let _err = io::Error::other(super::E); | -error: aborting due to 4 previous errors +error: this can be `std::io::Error::other(_)` + --> tests/ui/io_other_error.rs:58:5 + | +LL | std::io::Error::new(std::io::ErrorKind::Other, format!("{x}")) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `std::io::Error::other` + | +LL - std::io::Error::new(std::io::ErrorKind::Other, format!("{x}")) +LL + std::io::Error::other(format!("{x}")) + | + +error: aborting due to 5 previous errors From 206737569741970865cdc6d5347994b971aa2af8 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Fri, 24 Jan 2025 22:00:17 -0800 Subject: [PATCH 097/745] Make `struct_field_names` lint on private fields of public structs. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, If a struct is `pub` and its field is private, and `avoid-breaking-exported-api = true` (default), then `struct_field_names` will not lint the field, even though changing the field’s name is not a breaking change. This is because the breaking-exported-api condition was checking the visibility of the struct, not its fields (perhaps because the same code was used for enums). With this change, Clippy will check the field’s effective visibility only. Note: This change is large because some functions were moved into an `impl` to be able to access more configuration. Consider viewing the diff with whitespace ignored. --- clippy_lints/src/item_name_repetitions.rs | 172 +++++++++++++--------- tests/ui/struct_fields.rs | 27 ++++ tests/ui/struct_fields.stderr | 21 ++- 3 files changed, 146 insertions(+), 74 deletions(-) diff --git a/clippy_lints/src/item_name_repetitions.rs b/clippy_lints/src/item_name_repetitions.rs index 6363f717a5c2..fbde2ff799e8 100644 --- a/clippy_lints/src/item_name_repetitions.rs +++ b/clippy_lints/src/item_name_repetitions.rs @@ -196,80 +196,100 @@ fn have_no_extra_prefix(prefixes: &[&str]) -> bool { prefixes.iter().all(|p| p == &"" || p == &"_") } -fn check_fields(cx: &LateContext<'_>, threshold: u64, item: &Item<'_>, fields: &[FieldDef<'_>]) { - if (fields.len() as u64) < threshold { - return; - } - - check_struct_name_repetition(cx, item, fields); - - // if the SyntaxContext of the identifiers of the fields and struct differ dont lint them. - // this prevents linting in macros in which the location of the field identifier names differ - if !fields.iter().all(|field| item.ident.span.eq_ctxt(field.ident.span)) { - return; - } - - let mut pre: Vec<&str> = match fields.first() { - Some(first_field) => first_field.ident.name.as_str().split('_').collect(), - None => return, - }; - let mut post = pre.clone(); - post.reverse(); - for field in fields { - let field_split: Vec<&str> = field.ident.name.as_str().split('_').collect(); - if field_split.len() == 1 { +impl ItemNameRepetitions { + /// Lint the names of struct fields against the name of the struct. + fn check_fields(&self, cx: &LateContext<'_>, item: &Item<'_>, fields: &[FieldDef<'_>]) { + if (fields.len() as u64) < self.struct_threshold { return; } - pre = pre - .into_iter() - .zip(field_split.iter()) - .take_while(|(a, b)| &a == b) - .map(|e| e.0) - .collect(); - post = post - .into_iter() - .zip(field_split.iter().rev()) - .take_while(|(a, b)| &a == b) - .map(|e| e.0) - .collect(); + self.check_struct_name_repetition(cx, item, fields); + self.check_common_affix(cx, item, fields); } - let prefix = pre.join("_"); - post.reverse(); - let postfix = match post.last() { - Some(&"") => post.join("_") + "_", - Some(_) | None => post.join("_"), - }; - if fields.len() > 1 { - let (what, value) = match ( - prefix.is_empty() || prefix.chars().all(|c| c == '_'), - postfix.is_empty(), - ) { - (true, true) => return, - (false, _) => ("pre", prefix), - (true, false) => ("post", postfix), + + fn check_common_affix(&self, cx: &LateContext<'_>, item: &Item<'_>, fields: &[FieldDef<'_>]) { + // if the SyntaxContext of the identifiers of the fields and struct differ dont lint them. + // this prevents linting in macros in which the location of the field identifier names differ + if !fields.iter().all(|field| item.ident.span.eq_ctxt(field.ident.span)) { + return; + } + + if self.avoid_breaking_exported_api + && fields + .iter() + .any(|field| cx.effective_visibilities.is_exported(field.def_id)) + { + return; + } + + let mut pre: Vec<&str> = match fields.first() { + Some(first_field) => first_field.ident.name.as_str().split('_').collect(), + None => return, }; - if fields.iter().all(|field| is_bool(field.ty)) { - // If all fields are booleans, we don't want to emit this lint. - return; - } - span_lint_and_help( - cx, - STRUCT_FIELD_NAMES, - item.span, - format!("all fields have the same {what}fix: `{value}`"), - None, - format!("remove the {what}fixes"), - ); - } -} + let mut post = pre.clone(); + post.reverse(); + for field in fields { + let field_split: Vec<&str> = field.ident.name.as_str().split('_').collect(); + if field_split.len() == 1 { + return; + } + + pre = pre + .into_iter() + .zip(field_split.iter()) + .take_while(|(a, b)| &a == b) + .map(|e| e.0) + .collect(); + post = post + .into_iter() + .zip(field_split.iter().rev()) + .take_while(|(a, b)| &a == b) + .map(|e| e.0) + .collect(); + } + let prefix = pre.join("_"); + post.reverse(); + let postfix = match post.last() { + Some(&"") => post.join("_") + "_", + Some(_) | None => post.join("_"), + }; + if fields.len() > 1 { + let (what, value) = match ( + prefix.is_empty() || prefix.chars().all(|c| c == '_'), + postfix.is_empty(), + ) { + (true, true) => return, + (false, _) => ("pre", prefix), + (true, false) => ("post", postfix), + }; + if fields.iter().all(|field| is_bool(field.ty)) { + // If all fields are booleans, we don't want to emit this lint. + return; + } + span_lint_and_help( + cx, + STRUCT_FIELD_NAMES, + item.span, + format!("all fields have the same {what}fix: `{value}`"), + None, + format!("remove the {what}fixes"), + ); + } + } + + fn check_struct_name_repetition(&self, cx: &LateContext<'_>, item: &Item<'_>, fields: &[FieldDef<'_>]) { + let snake_name = to_snake_case(item.ident.name.as_str()); + let item_name_words: Vec<&str> = snake_name.split('_').collect(); + for field in fields { + if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(field.def_id) { + continue; + } + + if !field.ident.span.eq_ctxt(item.ident.span) { + // consider linting only if the field identifier has the same SyntaxContext as the item(struct) + continue; + } -fn check_struct_name_repetition(cx: &LateContext<'_>, item: &Item<'_>, fields: &[FieldDef<'_>]) { - let snake_name = to_snake_case(item.ident.name.as_str()); - let item_name_words: Vec<&str> = snake_name.split('_').collect(); - for field in fields { - if field.ident.span.eq_ctxt(item.ident.span) { - //consider linting only if the field identifier has the same SyntaxContext as the item(struct) let field_words: Vec<&str> = field.ident.name.as_str().split('_').collect(); if field_words.len() >= item_name_words.len() { // if the field name is shorter than the struct name it cannot contain it @@ -458,17 +478,23 @@ impl LateLintPass<'_> for ItemNameRepetitions { } } } - if !(self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(item.owner_id.def_id)) - && span_is_local(item.span) - { + + if span_is_local(item.span) { match item.kind { - ItemKind::Enum(def, _) => check_variant(cx, self.enum_threshold, &def, item_name, item.span), + ItemKind::Enum(def, _) => { + if !(self.avoid_breaking_exported_api + && cx.effective_visibilities.is_exported(item.owner_id.def_id)) + { + check_variant(cx, self.enum_threshold, &def, item_name, item.span); + } + }, ItemKind::Struct(VariantData::Struct { fields, .. }, _) => { - check_fields(cx, self.struct_threshold, item, fields); + self.check_fields(cx, item, fields); }, _ => (), } } + self.modules.push((item.ident.name, item_camel, item.owner_id)); } } diff --git a/tests/ui/struct_fields.rs b/tests/ui/struct_fields.rs index 3dce530efffa..e7ff2e6573b2 100644 --- a/tests/ui/struct_fields.rs +++ b/tests/ui/struct_fields.rs @@ -344,4 +344,31 @@ struct Use { //~^ struct_field_names } +// should lint on private fields of public structs (renaming them is not breaking-exported-api) +pub struct PubStructFieldNamedAfterStruct { + pub_struct_field_named_after_struct: bool, + //~^ ERROR: field name starts with the struct's name + other1: bool, + other2: bool, +} +pub struct PubStructFieldPrefix { + //~^ ERROR: all fields have the same prefix: `field` + field_foo: u8, + field_bar: u8, + field_baz: u8, +} +// ...but should not lint on structs with public fields. +pub struct PubStructPubAndPrivateFields { + /// One could argue that this field should be linted, but currently, any public field stops all + /// checking. + pub_struct_pub_and_private_fields_1: bool, + pub pub_struct_pub_and_private_fields_2: bool, +} +// nor on common prefixes if one of the involved fields is public +pub struct PubStructPubAndPrivateFieldPrefix { + pub field_foo: u8, + field_bar: u8, + field_baz: u8, +} + fn main() {} diff --git a/tests/ui/struct_fields.stderr b/tests/ui/struct_fields.stderr index 79186cc1cfd8..a5ff1b125907 100644 --- a/tests/ui/struct_fields.stderr +++ b/tests/ui/struct_fields.stderr @@ -281,5 +281,24 @@ error: field name starts with the struct's name LL | use_baz: bool, | ^^^^^^^^^^^^^ -error: aborting due to 24 previous errors +error: field name starts with the struct's name + --> tests/ui/struct_fields.rs:349:5 + | +LL | pub_struct_field_named_after_struct: bool, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: all fields have the same prefix: `field` + --> tests/ui/struct_fields.rs:354:1 + | +LL | / pub struct PubStructFieldPrefix { +LL | | +LL | | field_foo: u8, +LL | | field_bar: u8, +LL | | field_baz: u8, +LL | | } + | |_^ + | + = help: remove the prefixes + +error: aborting due to 26 previous errors From 8c73b76fb2f32674f76254e07474a596afee8120 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Sun, 16 Feb 2025 13:26:27 -0800 Subject: [PATCH 098/745] Move `check_variant()` code into a method of `ItemNameRepetitions` too. --- clippy_lints/src/item_name_repetitions.rs | 139 +++++++++++----------- 1 file changed, 72 insertions(+), 67 deletions(-) diff --git a/clippy_lints/src/item_name_repetitions.rs b/clippy_lints/src/item_name_repetitions.rs index fbde2ff799e8..1107946f538b 100644 --- a/clippy_lints/src/item_name_repetitions.rs +++ b/clippy_lints/src/item_name_repetitions.rs @@ -8,7 +8,6 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir::{EnumDef, FieldDef, Item, ItemKind, OwnerId, Variant, VariantData}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; -use rustc_span::Span; use rustc_span::symbol::Symbol; declare_clippy_lint! { @@ -197,6 +196,25 @@ fn have_no_extra_prefix(prefixes: &[&str]) -> bool { } impl ItemNameRepetitions { + /// Lint the names of enum variants against the name of the enum. + fn check_variants(&self, cx: &LateContext<'_>, item: &Item<'_>, def: &EnumDef<'_>) { + if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(item.owner_id.def_id) { + return; + } + + if (def.variants.len() as u64) < self.enum_threshold { + return; + } + + let item_name = item.ident.name.as_str(); + for var in def.variants { + check_enum_start(cx, item_name, var); + check_enum_end(cx, item_name, var); + } + + Self::check_enum_common_affix(cx, item, def); + } + /// Lint the names of struct fields against the name of the struct. fn check_fields(&self, cx: &LateContext<'_>, item: &Item<'_>, fields: &[FieldDef<'_>]) { if (fields.len() as u64) < self.struct_threshold { @@ -204,10 +222,60 @@ impl ItemNameRepetitions { } self.check_struct_name_repetition(cx, item, fields); - self.check_common_affix(cx, item, fields); + self.check_struct_common_affix(cx, item, fields); } - fn check_common_affix(&self, cx: &LateContext<'_>, item: &Item<'_>, fields: &[FieldDef<'_>]) { + fn check_enum_common_affix(cx: &LateContext<'_>, item: &Item<'_>, def: &EnumDef<'_>) { + let first = match def.variants.first() { + Some(variant) => variant.ident.name.as_str(), + None => return, + }; + let mut pre = camel_case_split(first); + let mut post = pre.clone(); + post.reverse(); + for var in def.variants { + let name = var.ident.name.as_str(); + + let variant_split = camel_case_split(name); + if variant_split.len() == 1 { + return; + } + + pre = pre + .iter() + .zip(variant_split.iter()) + .take_while(|(a, b)| a == b) + .map(|e| *e.0) + .collect(); + post = post + .iter() + .zip(variant_split.iter().rev()) + .take_while(|(a, b)| a == b) + .map(|e| *e.0) + .collect(); + } + let (what, value) = match (have_no_extra_prefix(&pre), post.is_empty()) { + (true, true) => return, + (false, _) => ("pre", pre.join("")), + (true, false) => { + post.reverse(); + ("post", post.join("")) + }, + }; + span_lint_and_help( + cx, + ENUM_VARIANT_NAMES, + item.span, + format!("all variants have the same {what}fix: `{value}`"), + None, + format!( + "remove the {what}fixes and use full paths to \ + the variants instead of glob imports" + ), + ); + } + + fn check_struct_common_affix(&self, cx: &LateContext<'_>, item: &Item<'_>, fields: &[FieldDef<'_>]) { // if the SyntaxContext of the identifiers of the fields and struct differ dont lint them. // this prevents linting in macros in which the location of the field identifier names differ if !fields.iter().all(|field| item.ident.span.eq_ctxt(field.ident.span)) { @@ -357,65 +425,6 @@ fn check_enum_end(cx: &LateContext<'_>, item_name: &str, variant: &Variant<'_>) } } -fn check_variant(cx: &LateContext<'_>, threshold: u64, def: &EnumDef<'_>, item_name: &str, span: Span) { - if (def.variants.len() as u64) < threshold { - return; - } - - for var in def.variants { - check_enum_start(cx, item_name, var); - check_enum_end(cx, item_name, var); - } - - let first = match def.variants.first() { - Some(variant) => variant.ident.name.as_str(), - None => return, - }; - let mut pre = camel_case_split(first); - let mut post = pre.clone(); - post.reverse(); - for var in def.variants { - let name = var.ident.name.as_str(); - - let variant_split = camel_case_split(name); - if variant_split.len() == 1 { - return; - } - - pre = pre - .iter() - .zip(variant_split.iter()) - .take_while(|(a, b)| a == b) - .map(|e| *e.0) - .collect(); - post = post - .iter() - .zip(variant_split.iter().rev()) - .take_while(|(a, b)| a == b) - .map(|e| *e.0) - .collect(); - } - let (what, value) = match (have_no_extra_prefix(&pre), post.is_empty()) { - (true, true) => return, - (false, _) => ("pre", pre.join("")), - (true, false) => { - post.reverse(); - ("post", post.join("")) - }, - }; - span_lint_and_help( - cx, - ENUM_VARIANT_NAMES, - span, - format!("all variants have the same {what}fix: `{value}`"), - None, - format!( - "remove the {what}fixes and use full paths to \ - the variants instead of glob imports" - ), - ); -} - impl LateLintPass<'_> for ItemNameRepetitions { fn check_item_post(&mut self, _cx: &LateContext<'_>, _item: &Item<'_>) { let last = self.modules.pop(); @@ -482,11 +491,7 @@ impl LateLintPass<'_> for ItemNameRepetitions { if span_is_local(item.span) { match item.kind { ItemKind::Enum(def, _) => { - if !(self.avoid_breaking_exported_api - && cx.effective_visibilities.is_exported(item.owner_id.def_id)) - { - check_variant(cx, self.enum_threshold, &def, item_name, item.span); - } + self.check_variants(cx, item, &def); }, ItemKind::Struct(VariantData::Struct { fields, .. }, _) => { self.check_fields(cx, item, fields); From 157137a64aeba7fb6e6571bcc046c97d63d368a7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Feb 2025 15:25:54 +1100 Subject: [PATCH 099/745] Change signature of `target_features_cfg`. Currently it is called twice, once with `allow_unstable` set to true and once with it set to false. This results in some duplicated work. Most notably, for the LLVM backend, `LLVMRustHasFeature` is called twice for every feature, and it's moderately slow. For very short running compilations on platforms with many features (e.g. a `check` build of hello-world on x86) this is a significant fraction of runtime. This commit changes `target_features_cfg` so it is only called once, and it now returns a pair of feature sets. This halves the number of `LLVMRustHasFeature` calls. --- src/lib.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a3f437448757..06939beb3742 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -176,13 +176,9 @@ impl CodegenBackend for CraneliftCodegenBackend { } } - fn target_features_cfg( - &self, - sess: &Session, - _allow_unstable: bool, - ) -> Vec { + fn target_features_cfg(&self, sess: &Session) -> (Vec, Vec) { // FIXME return the actually used target features. this is necessary for #[cfg(target_feature)] - if sess.target.arch == "x86_64" && sess.target.os != "none" { + let target_features = if sess.target.arch == "x86_64" && sess.target.os != "none" { // x86_64 mandates SSE2 support and rustc requires the x87 feature to be enabled vec![sym::fsxr, sym::sse, sym::sse2, Symbol::intern("x87")] } else if sess.target.arch == "aarch64" { @@ -196,7 +192,10 @@ impl CodegenBackend for CraneliftCodegenBackend { } } else { vec![] - } + }; + // FIXME do `unstable_target_features` properly + let unstable_target_features = target_features.clone(); + (target_features, unstable_target_features) } fn print_version(&self) { From 0ec1d460bb898a22de37bcc040f86449371bdbdb Mon Sep 17 00:00:00 2001 From: sayantn Date: Tue, 4 Mar 2025 20:07:25 +0530 Subject: [PATCH 100/745] Add the new `amx` target features --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 6 ++++++ compiler/rustc_target/src/target_features.rs | 5 +++++ tests/ui/check-cfg/target_feature.stderr | 5 +++++ 3 files changed, 16 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 5cc4f4ab9e67..e3e2e8f2c0be 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -298,6 +298,12 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option Some(LLVMFeature::new("v9")), ("sparc", "v8plus") if get_version().0 < 19 => None, ("powerpc", "power8-crypto") => Some(LLVMFeature::new("crypto")), + // These new `amx` variants and `movrs` were introduced in LLVM20 + ("x86", "amx-avx512" | "amx-fp8" | "amx-movrs" | "amx-tf32" | "amx-transpose") + if get_version().0 < 20 => + { + None + } (_, s) => Some(LLVMFeature::new(s)), } } diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index d05466bb4843..1a4903cdbfa3 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -380,11 +380,16 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("adx", Stable, &[]), ("aes", Stable, &["sse2"]), + ("amx-avx512", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), ("amx-bf16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), ("amx-complex", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), ("amx-fp16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), + ("amx-fp8", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), ("amx-int8", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), + ("amx-movrs", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), + ("amx-tf32", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), ("amx-tile", Unstable(sym::x86_amx_intrinsics), &[]), + ("amx-transpose", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), ("avx", Stable, &["sse4.2"]), ("avx2", Stable, &["avx"]), ("avx512bf16", Unstable(sym::avx512_target_feature), &["avx512bw"]), diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr index 5b82d3f539fe..2060dcc61600 100644 --- a/tests/ui/check-cfg/target_feature.stderr +++ b/tests/ui/check-cfg/target_feature.stderr @@ -17,11 +17,16 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `aes` `altivec` `alu32` +`amx-avx512` `amx-bf16` `amx-complex` `amx-fp16` +`amx-fp8` `amx-int8` +`amx-movrs` +`amx-tf32` `amx-tile` +`amx-transpose` `atomics` `avx` `avx2` From 7c2434c52caf1fc4269dd2e376fb332d0dd78143 Mon Sep 17 00:00:00 2001 From: sayantn Date: Tue, 4 Mar 2025 20:08:28 +0530 Subject: [PATCH 101/745] Add the `movrs` target feature and `movrs_target_feature` feature gate --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 1 + compiler/rustc_feature/src/unstable.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_target/src/target_features.rs | 1 + tests/ui/check-cfg/target_feature.stderr | 1 + .../feature-gate-movrs_target_feature.rs | 6 ++++++ .../feature-gate-movrs_target_feature.stderr | 13 +++++++++++++ 7 files changed, 24 insertions(+) create mode 100644 tests/ui/feature-gates/feature-gate-movrs_target_feature.rs create mode 100644 tests/ui/feature-gates/feature-gate-movrs_target_feature.stderr diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index e3e2e8f2c0be..7e244e0b2680 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -304,6 +304,7 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option None, (_, s) => Some(LLVMFeature::new(s)), } } diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 841d30841856..4248cac5812b 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -323,6 +323,7 @@ declare_features! ( (unstable, loongarch_target_feature, "1.73.0", Some(44839)), (unstable, m68k_target_feature, "1.85.0", Some(134328)), (unstable, mips_target_feature, "1.27.0", Some(44839)), + (unstable, movrs_target_feature, "CURRENT_RUSTC_VERSION", Some(137976)), (unstable, powerpc_target_feature, "1.27.0", Some(44839)), (unstable, prfchw_target_feature, "1.78.0", Some(44839)), (unstable, riscv_target_feature, "1.45.0", Some(44839)), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 1dc84150cbe5..b932b525aea5 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1348,6 +1348,7 @@ symbols! { movbe_target_feature, move_ref_pattern, move_size_limit, + movrs_target_feature, mul, mul_assign, mul_with_overflow, diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 1a4903cdbfa3..e46da2359b97 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -423,6 +423,7 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]), ("lzcnt", Stable, &[]), ("movbe", Stable, &[]), + ("movrs", Unstable(sym::movrs_target_feature), &[]), ("pclmulqdq", Stable, &["sse2"]), ("popcnt", Stable, &[]), ("prfchw", Unstable(sym::prfchw_target_feature), &[]), diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr index 2060dcc61600..e3133b0af3c5 100644 --- a/tests/ui/check-cfg/target_feature.stderr +++ b/tests/ui/check-cfg/target_feature.stderr @@ -153,6 +153,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `mclass` `mops` `movbe` +`movrs` `mp` `mp1e2` `msa` diff --git a/tests/ui/feature-gates/feature-gate-movrs_target_feature.rs b/tests/ui/feature-gates/feature-gate-movrs_target_feature.rs new file mode 100644 index 000000000000..738cab5a06d6 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-movrs_target_feature.rs @@ -0,0 +1,6 @@ +//@ only-x86_64 +#[target_feature(enable = "movrs")] +//~^ ERROR: currently unstable +unsafe fn foo() {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-movrs_target_feature.stderr b/tests/ui/feature-gates/feature-gate-movrs_target_feature.stderr new file mode 100644 index 000000000000..16fe7aaead5c --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-movrs_target_feature.stderr @@ -0,0 +1,13 @@ +error[E0658]: the target feature `movrs` is currently unstable + --> $DIR/feature-gate-movrs_target_feature.rs:2:18 + | +LL | #[target_feature(enable = "movrs")] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #137976 for more information + = help: add `#![feature(movrs_target_feature)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. From 75485a2c093304e93831e6789b38d7aa0024ff3b Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 5 Mar 2025 01:35:02 -0500 Subject: [PATCH 102/745] Update `compiler-builtins` to 0.1.151 This enables `f16` builtins for loongarch [1] and adds support for Cygwin [2]. [1]: https://github.com/rust-lang/compiler-builtins/pull/770 [2]: https://github.com/rust-lang/compiler-builtins/pull/774 --- ...029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index d8db7d63f2dd..c2027863b00b 100644 --- a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -16,8 +16,8 @@ index 7165c3e48af..968552ad435 100644 [dependencies] core = { path = "../core", public = true } --compiler_builtins = { version = "=0.1.150", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "=0.1.150", features = ['rustc-dep-of-std', 'no-f16-f128'] } +-compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std'] } ++compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std', 'no-f16-f128'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } From 2ff10504401ba4619e2416c4afa0a6789c3aaff3 Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Tue, 4 Mar 2025 20:28:38 -0800 Subject: [PATCH 103/745] Use size_of from the prelude instead of imported It was added to all preludes in Rust 1.80. --- src/tools/miri/bench-cargo-miri/mse/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/bench-cargo-miri/mse/src/main.rs b/src/tools/miri/bench-cargo-miri/mse/src/main.rs index e16ccd2c0d73..06d5487d1d4e 100644 --- a/src/tools/miri/bench-cargo-miri/mse/src/main.rs +++ b/src/tools/miri/bench-cargo-miri/mse/src/main.rs @@ -10,7 +10,7 @@ fn main() { } fn read_i16(buffer: &[u8], index: usize) -> i16 { - const SIZE: usize = std::mem::size_of::(); + const SIZE: usize = size_of::(); let mut bytes: [u8; SIZE] = [0u8; SIZE]; bytes.copy_from_slice(&buffer[(index * SIZE)..(index * SIZE + SIZE)]); unsafe { std::mem::transmute(bytes) } From e8cd3d4752bdb2d623bcec892c7055fbceabd24c Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Tue, 4 Mar 2025 20:28:38 -0800 Subject: [PATCH 104/745] Use size_of from the prelude instead of imported Use `std::mem::{size_of, size_of_val, align_of, align_of_val}` from the prelude instead of importing or qualifying them. These functions were added to all preludes in Rust 1.80. --- clippy_lints/src/manual_bits.rs | 6 +- .../src/manual_slice_size_calculation.rs | 4 +- clippy_lints/src/size_of_in_element_count.rs | 1 - clippy_lints/src/size_of_ref.rs | 12 ++-- tests/ui/manual_bits.stderr | 58 +++++++++---------- tests/ui/size_of_ref.stderr | 12 ++-- 6 files changed, 46 insertions(+), 47 deletions(-) diff --git a/clippy_lints/src/manual_bits.rs b/clippy_lints/src/manual_bits.rs index 39c4857b3e87..40fe88532729 100644 --- a/clippy_lints/src/manual_bits.rs +++ b/clippy_lints/src/manual_bits.rs @@ -14,7 +14,7 @@ use rustc_span::{Span, sym}; declare_clippy_lint! { /// ### What it does - /// Checks for usage of `std::mem::size_of::() * 8` when + /// Checks for usage of `size_of::() * 8` when /// `T::BITS` is available. /// /// ### Why is this bad? @@ -22,7 +22,7 @@ declare_clippy_lint! { /// /// ### Example /// ```no_run - /// std::mem::size_of::() * 8; + /// size_of::() * 8; /// ``` /// Use instead: /// ```no_run @@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualBits { cx, MANUAL_BITS, expr.span, - "usage of `mem::size_of::()` to obtain the size of `T` in bits", + "usage of `size_of::()` to obtain the size of `T` in bits", "consider using", sugg, app, diff --git a/clippy_lints/src/manual_slice_size_calculation.rs b/clippy_lints/src/manual_slice_size_calculation.rs index 18901f7399d9..2dad0fa4925e 100644 --- a/clippy_lints/src/manual_slice_size_calculation.rs +++ b/clippy_lints/src/manual_slice_size_calculation.rs @@ -24,12 +24,12 @@ declare_clippy_lint! { /// ### Example /// ```no_run /// # let data : &[i32] = &[1, 2, 3]; - /// let newlen = data.len() * std::mem::size_of::(); + /// let newlen = data.len() * size_of::(); /// ``` /// Use instead: /// ```no_run /// # let data : &[i32] = &[1, 2, 3]; - /// let newlen = std::mem::size_of_val(data); + /// let newlen = size_of_val(data); /// ``` #[clippy::version = "1.70.0"] pub MANUAL_SLICE_SIZE_CALCULATION, diff --git a/clippy_lints/src/size_of_in_element_count.rs b/clippy_lints/src/size_of_in_element_count.rs index dc19236011bd..835ec1e4ca1c 100644 --- a/clippy_lints/src/size_of_in_element_count.rs +++ b/clippy_lints/src/size_of_in_element_count.rs @@ -18,7 +18,6 @@ declare_clippy_lint! { /// ### Example /// ```rust,no_run /// # use std::ptr::copy_nonoverlapping; - /// # use std::mem::size_of; /// const SIZE: usize = 128; /// let x = [2u8; SIZE]; /// let mut y = [2u8; SIZE]; diff --git a/clippy_lints/src/size_of_ref.rs b/clippy_lints/src/size_of_ref.rs index b3d32a6d7d84..60d923bcd77e 100644 --- a/clippy_lints/src/size_of_ref.rs +++ b/clippy_lints/src/size_of_ref.rs @@ -8,7 +8,7 @@ use rustc_span::sym; declare_clippy_lint! { /// ### What it does /// - /// Checks for calls to `std::mem::size_of_val()` where the argument is + /// Checks for calls to `size_of_val()` where the argument is /// a reference to a reference. /// /// ### Why is this bad? @@ -29,7 +29,7 @@ declare_clippy_lint! { /// // is already a reference, `&self` is a double-reference. /// // The return value of `size_of_val()` therefore is the /// // size of the reference-type, not the size of `self`. - /// std::mem::size_of_val(&self) + /// size_of_val(&self) /// } /// } /// ``` @@ -42,14 +42,14 @@ declare_clippy_lint! { /// impl Foo { /// fn size(&self) -> usize { /// // Correct - /// std::mem::size_of_val(self) + /// size_of_val(self) /// } /// } /// ``` #[clippy::version = "1.68.0"] pub SIZE_OF_REF, suspicious, - "Argument to `std::mem::size_of_val()` is a double-reference, which is almost certainly unintended" + "Argument to `size_of_val()` is a double-reference, which is almost certainly unintended" } declare_lint_pass!(SizeOfRef => [SIZE_OF_REF]); @@ -65,9 +65,9 @@ impl LateLintPass<'_> for SizeOfRef { cx, SIZE_OF_REF, expr.span, - "argument to `std::mem::size_of_val()` is a reference to a reference", + "argument to `size_of_val()` is a reference to a reference", None, - "dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the size of the reference-type", + "dereference the argument to `size_of_val()` to get the size of the value instead of the size of the reference-type", ); } } diff --git a/tests/ui/manual_bits.stderr b/tests/ui/manual_bits.stderr index a50975ed474e..44c4cf9239c8 100644 --- a/tests/ui/manual_bits.stderr +++ b/tests/ui/manual_bits.stderr @@ -1,4 +1,4 @@ -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:14:5 | LL | size_of::() * 8; @@ -7,169 +7,169 @@ LL | size_of::() * 8; = note: `-D clippy::manual-bits` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::manual_bits)]` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:16:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i16::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:18:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i32::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:20:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i64::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:22:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `i128::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:24:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `isize::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:27:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^ help: consider using: `u8::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:29:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u16::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:31:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u32::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:33:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u64::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:35:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `u128::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:37:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `usize::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:40:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `i8::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:42:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i16::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:44:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i32::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:46:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i64::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:48:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `i128::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:50:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `isize::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:53:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `u8::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:55:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u16::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:57:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u32::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:59:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u64::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:61:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `u128::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:63:5 | LL | 8 * size_of::(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `usize::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:74:5 | LL | size_of::() * 8; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `Word::BITS as usize` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:79:18 | LL | let _: u32 = (size_of::() * 8) as u32; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `u128::BITS` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:81:18 | LL | let _: u32 = (size_of::() * 8).try_into().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `u128::BITS` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:83:13 | LL | let _ = (size_of::() * 8).pow(5); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(u128::BITS as usize)` -error: usage of `mem::size_of::()` to obtain the size of `T` in bits +error: usage of `size_of::()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:85:14 | LL | let _ = &(size_of::() * 8); diff --git a/tests/ui/size_of_ref.stderr b/tests/ui/size_of_ref.stderr index 6ac0b0dd2f06..46af9f55deaf 100644 --- a/tests/ui/size_of_ref.stderr +++ b/tests/ui/size_of_ref.stderr @@ -1,28 +1,28 @@ -error: argument to `std::mem::size_of_val()` is a reference to a reference +error: argument to `size_of_val()` is a reference to a reference --> tests/ui/size_of_ref.rs:13:5 | LL | size_of_val(&&x); | ^^^^^^^^^^^^^^^^ | - = help: dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the size of the reference-type + = help: dereference the argument to `size_of_val()` to get the size of the value instead of the size of the reference-type = note: `-D clippy::size-of-ref` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::size_of_ref)]` -error: argument to `std::mem::size_of_val()` is a reference to a reference +error: argument to `size_of_val()` is a reference to a reference --> tests/ui/size_of_ref.rs:16:5 | LL | size_of_val(&y); | ^^^^^^^^^^^^^^^ | - = help: dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the size of the reference-type + = help: dereference the argument to `size_of_val()` to get the size of the value instead of the size of the reference-type -error: argument to `std::mem::size_of_val()` is a reference to a reference +error: argument to `size_of_val()` is a reference to a reference --> tests/ui/size_of_ref.rs:28:9 | LL | std::mem::size_of_val(&self) + (std::mem::size_of::() * self.data.capacity()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the size of the reference-type + = help: dereference the argument to `size_of_val()` to get the size of the value instead of the size of the reference-type error: aborting due to 3 previous errors From 0fcd068bec1aab1a596f23328769a26f253dfee2 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 5 Mar 2025 15:12:57 +0000 Subject: [PATCH 105/745] Refactor the cli of cg_clif --- docs/usage.md | 4 ++-- scripts/cargo-clif.rs | 5 +++-- scripts/filter_profile.rs | 2 +- src/config.rs | 41 +++++++++++++-------------------------- src/driver/jit.rs | 19 ++++++++---------- src/lib.rs | 15 +++++++------- 6 files changed, 34 insertions(+), 52 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index 135a51ce392b..785adbbdf9a8 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -38,7 +38,7 @@ $ $cg_clif_dir/dist/cargo-clif jit or ```bash -$ $cg_clif_dir/dist/rustc-clif -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs +$ $cg_clif_dir/dist/rustc-clif -Cllvm-args=jit-mode -Cprefer-dynamic my_crate.rs ``` There is also an experimental lazy jit mode. In this mode functions are only compiled once they are @@ -54,7 +54,7 @@ These are a few functions that allow you to easily run rust code from the shell ```bash function jit_naked() { - echo "$@" | $cg_clif_dir/dist/rustc-clif - -Zunstable-options -Cllvm-args=mode=jit-lazy -Cprefer-dynamic + echo "$@" | $cg_clif_dir/dist/rustc-clif - -Zunstable-options -Cllvm-args=jit-mode -Cllvm-args=jit-lazy -Cprefer-dynamic } function jit() { diff --git a/scripts/cargo-clif.rs b/scripts/cargo-clif.rs index ebbb68796105..1ca02bc6a2ce 100644 --- a/scripts/cargo-clif.rs +++ b/scripts/cargo-clif.rs @@ -50,7 +50,7 @@ fn main() { .chain([ "--".to_string(), "-Zunstable-options".to_string(), - "-Cllvm-args=mode=jit".to_string(), + "-Cllvm-args=jit-mode".to_string(), ]) .collect() } @@ -62,7 +62,8 @@ fn main() { .chain([ "--".to_string(), "-Zunstable-options".to_string(), - "-Cllvm-args=mode=jit-lazy".to_string(), + "-Cllvm-args=jit-mode".to_string(), + "-Cllvm-args=jit-lazy".to_string(), ]) .collect() } diff --git a/scripts/filter_profile.rs b/scripts/filter_profile.rs index 0252d5b33403..4595063c032d 100755 --- a/scripts/filter_profile.rs +++ b/scripts/filter_profile.rs @@ -4,7 +4,7 @@ pushd $(dirname "$0")/../ RUSTC="$(pwd)/dist/rustc-clif" popd -PROFILE=$1 OUTPUT=$2 exec $RUSTC -Zunstable-options -Cllvm-args=mode=jit -Cprefer-dynamic $0 +PROFILE=$1 OUTPUT=$2 exec $RUSTC -Zunstable-options -Cllvm-args=jit-mode -Cprefer-dynamic $0 #*/ //! This program filters away uninteresting samples and trims uninteresting frames for stackcollapse diff --git a/src/config.rs b/src/config.rs index d784f6e9d9eb..30b48786cdc4 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,21 +1,15 @@ -/// The mode to use for compilation. -#[derive(Copy, Clone, Debug)] -pub enum CodegenMode { - /// AOT compile the crate. This is the default. - Aot, - /// JIT compile and execute the crate. - Jit, - /// JIT compile and execute the crate, but only compile functions the first time they are used. - JitLazy, -} - /// Configuration of cg_clif as passed in through `-Cllvm-args` and various env vars. #[derive(Clone, Debug)] pub struct BackendConfig { /// Should the crate be AOT compiled or JIT executed. /// - /// Defaults to AOT compilation. Can be set using `-Cllvm-args=mode=...`. - pub codegen_mode: CodegenMode, + /// Defaults to AOT compilation. Can be set using `-Cllvm-args=jit-mode`. + pub jit_mode: bool, + + /// When JIT executing should the lazy JIT mode be used. + /// + /// Defaults to false. Can be set using `-Cllvm-args=jit-lazy`. + pub lazy_jit: bool, /// When JIT mode is enable pass these arguments to the program. /// @@ -27,7 +21,8 @@ impl BackendConfig { /// Parse the configuration passed in using `-Cllvm-args`. pub fn from_opts(opts: &[String]) -> Result { let mut config = BackendConfig { - codegen_mode: CodegenMode::Aot, + jit_mode: false, + lazy_jit: false, jit_args: match std::env::var("CG_CLIF_JIT_ARGS") { Ok(args) => args.split(' ').map(|arg| arg.to_string()).collect(), Err(std::env::VarError::NotPresent) => vec![], @@ -43,20 +38,10 @@ impl BackendConfig { // testing cg_clif. continue; } - if let Some((name, value)) = opt.split_once('=') { - match name { - "mode" => { - config.codegen_mode = match value { - "aot" => CodegenMode::Aot, - "jit" => CodegenMode::Jit, - "jit-lazy" => CodegenMode::JitLazy, - _ => return Err(format!("Unknown codegen mode `{}`", value)), - }; - } - _ => return Err(format!("Unknown option `{}`", name)), - } - } else { - return Err(format!("Invalid option `{}`", opt)); + match &**opt { + "jit-mode" => config.jit_mode = true, + "jit-lazy" => config.lazy_jit = true, + _ => return Err(format!("Unknown option `{}`", opt)), } } diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 57c88f4b0f9f..17d55a82e8b5 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -13,10 +13,10 @@ use rustc_middle::mir::mono::MonoItem; use rustc_session::Session; use rustc_span::sym; +use crate::CodegenCx; use crate::debuginfo::TypeDebugContext; use crate::prelude::*; use crate::unwind_module::UnwindModule; -use crate::{CodegenCx, CodegenMode}; struct JitState { jit_module: UnwindModule, @@ -79,7 +79,7 @@ fn create_jit_module(tcx: TyCtxt<'_>, hotswap: bool) -> (UnwindModule (jit_module, cx) } -pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec) -> ! { +pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_lazy: bool, jit_args: Vec) -> ! { if !tcx.sess.opts.output_types.should_codegen() { tcx.dcx().fatal("JIT mode doesn't work with `cargo check`"); } @@ -88,8 +88,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec< tcx.dcx().fatal("can't jit non-executable crate"); } - let (mut jit_module, mut cx) = - create_jit_module(tcx, matches!(codegen_mode, CodegenMode::JitLazy)); + let (mut jit_module, mut cx) = create_jit_module(tcx, jit_lazy); let mut cached_context = Context::new(); let cgus = tcx.collect_and_partition_mono_items(()).codegen_units; @@ -105,9 +104,10 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec< super::predefine_mono_items(tcx, &mut jit_module, &mono_items); for (mono_item, _) in mono_items { match mono_item { - MonoItem::Fn(inst) => match codegen_mode { - CodegenMode::Aot => unreachable!(), - CodegenMode::Jit => { + MonoItem::Fn(inst) => { + if jit_lazy { + codegen_shim(tcx, &mut cached_context, &mut jit_module, inst) + } else { codegen_and_compile_fn( tcx, &mut cx, @@ -116,10 +116,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec< inst, ); } - CodegenMode::JitLazy => { - codegen_shim(tcx, &mut cached_context, &mut jit_module, inst) - } - }, + } MonoItem::Static(def_id) => { crate::constant::codegen_static(tcx, &mut jit_module, def_id); } diff --git a/src/lib.rs b/src/lib.rs index 2c019e754460..c5ca6565a86b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -213,15 +213,14 @@ impl CodegenBackend for CraneliftCodegenBackend { BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args) .unwrap_or_else(|err| tcx.sess.dcx().fatal(err)) }); - match config.codegen_mode { - CodegenMode::Aot => driver::aot::run_aot(tcx, metadata, need_metadata_module), - CodegenMode::Jit | CodegenMode::JitLazy => { - #[cfg(feature = "jit")] - driver::jit::run_jit(tcx, config.codegen_mode, config.jit_args); + if config.jit_mode { + #[cfg(feature = "jit")] + driver::jit::run_jit(tcx, config.lazy_jit, config.jit_args); - #[cfg(not(feature = "jit"))] - tcx.dcx().fatal("jit support was disabled when compiling rustc_codegen_cranelift"); - } + #[cfg(not(feature = "jit"))] + tcx.dcx().fatal("jit support was disabled when compiling rustc_codegen_cranelift"); + } else { + driver::aot::run_aot(tcx, metadata, need_metadata_module) } } From 5d03df9431833ad992c1507fedc7daee3e232443 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 5 Mar 2025 15:35:51 +0000 Subject: [PATCH 106/745] Remove support for the lazy jit mode I might re-implement it in the future, but would probably do so by replacing cranelift-jit. cranelift-jit's api doesn't quite work well for lazy jitting. And even so it adds complexity to cranelift-jit and breaks cranelift-jit outside of x86_64. --- build_system/tests.rs | 14 --- docs/usage.md | 9 +- scripts/cargo-clif.rs | 13 --- src/config.rs | 7 -- src/driver/jit.rs | 214 ++++-------------------------------------- src/lib.rs | 2 +- 6 files changed, 18 insertions(+), 241 deletions(-) diff --git a/build_system/tests.rs b/build_system/tests.rs index ea7e94c345ad..1b1f0f483a33 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -384,20 +384,6 @@ impl<'a> TestRunner<'a> { jit_cmd.env("CG_CLIF_JIT_ARGS", args); } spawn_and_wait(jit_cmd); - - eprintln!("[JIT-lazy] {testname}"); - let mut jit_cmd = self.rustc_command([ - "-Zunstable-options", - "-Cllvm-args=mode=jit-lazy", - "-Cprefer-dynamic", - source, - "--cfg", - "jit", - ]); - if !args.is_empty() { - jit_cmd.env("CG_CLIF_JIT_ARGS", args); - } - spawn_and_wait(jit_cmd); } } } diff --git a/docs/usage.md b/docs/usage.md index 785adbbdf9a8..dbe36109f83e 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -41,20 +41,13 @@ or $ $cg_clif_dir/dist/rustc-clif -Cllvm-args=jit-mode -Cprefer-dynamic my_crate.rs ``` -There is also an experimental lazy jit mode. In this mode functions are only compiled once they are -first called. - -```bash -$ $cg_clif_dir/dist/cargo-clif lazy-jit -``` - ## Shell These are a few functions that allow you to easily run rust code from the shell using cg_clif as jit. ```bash function jit_naked() { - echo "$@" | $cg_clif_dir/dist/rustc-clif - -Zunstable-options -Cllvm-args=jit-mode -Cllvm-args=jit-lazy -Cprefer-dynamic + echo "$@" | $cg_clif_dir/dist/rustc-clif - -Zunstable-options -Cllvm-args=jit-mode-Cprefer-dynamic } function jit() { diff --git a/scripts/cargo-clif.rs b/scripts/cargo-clif.rs index 1ca02bc6a2ce..e6c63bf5e650 100644 --- a/scripts/cargo-clif.rs +++ b/scripts/cargo-clif.rs @@ -54,19 +54,6 @@ fn main() { ]) .collect() } - Some("lazy-jit") => { - rustflags.push("-Cprefer-dynamic".to_owned()); - args.remove(0); - IntoIterator::into_iter(["rustc".to_string()]) - .chain(args) - .chain([ - "--".to_string(), - "-Zunstable-options".to_string(), - "-Cllvm-args=jit-mode".to_string(), - "-Cllvm-args=jit-lazy".to_string(), - ]) - .collect() - } _ => args, }; diff --git a/src/config.rs b/src/config.rs index 30b48786cdc4..d328b33a704f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -6,11 +6,6 @@ pub struct BackendConfig { /// Defaults to AOT compilation. Can be set using `-Cllvm-args=jit-mode`. pub jit_mode: bool, - /// When JIT executing should the lazy JIT mode be used. - /// - /// Defaults to false. Can be set using `-Cllvm-args=jit-lazy`. - pub lazy_jit: bool, - /// When JIT mode is enable pass these arguments to the program. /// /// Defaults to the value of `CG_CLIF_JIT_ARGS`. @@ -22,7 +17,6 @@ impl BackendConfig { pub fn from_opts(opts: &[String]) -> Result { let mut config = BackendConfig { jit_mode: false, - lazy_jit: false, jit_args: match std::env::var("CG_CLIF_JIT_ARGS") { Ok(args) => args.split(' ').map(|arg| arg.to_string()).collect(), Err(std::env::VarError::NotPresent) => vec![], @@ -40,7 +34,6 @@ impl BackendConfig { } match &**opt { "jit-mode" => config.jit_mode = true, - "jit-lazy" => config.lazy_jit = true, _ => return Err(format!("Unknown option `{}`", opt)), } } diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 17d55a82e8b5..4a08937f4aa9 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -1,12 +1,9 @@ //! The JIT driver uses [`cranelift_jit`] to JIT execute programs without writing any object //! files. -use std::cell::RefCell; use std::ffi::CString; use std::os::raw::{c_char, c_int}; -use std::sync::{Mutex, OnceLock, mpsc}; -use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext}; use cranelift_jit::{JITBuilder, JITModule}; use rustc_codegen_ssa::CrateInfo; use rustc_middle::mir::mono::MonoItem; @@ -18,58 +15,13 @@ use crate::debuginfo::TypeDebugContext; use crate::prelude::*; use crate::unwind_module::UnwindModule; -struct JitState { - jit_module: UnwindModule, -} - -thread_local! { - static LAZY_JIT_STATE: RefCell> = const { RefCell::new(None) }; -} - -/// The Sender owned by the rustc thread -static GLOBAL_MESSAGE_SENDER: OnceLock>> = OnceLock::new(); - -/// A message that is sent from the jitted runtime to the rustc thread. -/// Senders are responsible for upholding `Send` semantics. -enum UnsafeMessage { - /// Request that the specified `Instance` be lazily jitted. - /// - /// Nothing accessible through `instance_ptr` may be moved or mutated by the sender after - /// this message is sent. - JitFn { - instance_ptr: *const Instance<'static>, - trampoline_ptr: *const u8, - tx: mpsc::Sender<*const u8>, - }, -} -unsafe impl Send for UnsafeMessage {} - -impl UnsafeMessage { - /// Send the message. - fn send(self) { - thread_local! { - /// The Sender owned by the local thread - static LOCAL_MESSAGE_SENDER: mpsc::Sender = - GLOBAL_MESSAGE_SENDER - .get().unwrap() - .lock().unwrap() - .clone(); - } - LOCAL_MESSAGE_SENDER.with(|sender| { - sender.send(self).expect("rustc thread hung up before lazy JIT request was sent") - }) - } -} - -fn create_jit_module(tcx: TyCtxt<'_>, hotswap: bool) -> (UnwindModule, CodegenCx) { +fn create_jit_module(tcx: TyCtxt<'_>) -> (UnwindModule, CodegenCx) { let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string()); let isa = crate::build_isa(tcx.sess); let mut jit_builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names()); - jit_builder.hotswap(hotswap); crate::compiler_builtins::register_functions_for_jit(&mut jit_builder); jit_builder.symbol_lookup_fn(dep_symbol_lookup_fn(tcx.sess, crate_info)); - jit_builder.symbol("__clif_jit_fn", clif_jit_fn as *const u8); let mut jit_module = UnwindModule::new(JITModule::new(jit_builder), false); let cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name); @@ -79,7 +31,7 @@ fn create_jit_module(tcx: TyCtxt<'_>, hotswap: bool) -> (UnwindModule (jit_module, cx) } -pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_lazy: bool, jit_args: Vec) -> ! { +pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_args: Vec) -> ! { if !tcx.sess.opts.output_types.should_codegen() { tcx.dcx().fatal("JIT mode doesn't work with `cargo check`"); } @@ -88,7 +40,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_lazy: bool, jit_args: Vec) -> tcx.dcx().fatal("can't jit non-executable crate"); } - let (mut jit_module, mut cx) = create_jit_module(tcx, jit_lazy); + let (mut jit_module, mut cx) = create_jit_module(tcx); let mut cached_context = Context::new(); let cgus = tcx.collect_and_partition_mono_items(()).codegen_units; @@ -105,17 +57,13 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_lazy: bool, jit_args: Vec) -> for (mono_item, _) in mono_items { match mono_item { MonoItem::Fn(inst) => { - if jit_lazy { - codegen_shim(tcx, &mut cached_context, &mut jit_module, inst) - } else { - codegen_and_compile_fn( - tcx, - &mut cx, - &mut cached_context, - &mut jit_module, - inst, - ); - } + codegen_and_compile_fn( + tcx, + &mut cx, + &mut cached_context, + &mut jit_module, + inst, + ); } MonoItem::Static(def_id) => { crate::constant::codegen_static(tcx, &mut jit_module, def_id); @@ -158,41 +106,17 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_lazy: bool, jit_args: Vec) -> let start_func_id = jit_module.declare_function("main", Linkage::Import, &start_sig).unwrap(); let finalized_start: *const u8 = jit_module.module.get_finalized_function(start_func_id); - LAZY_JIT_STATE.with(|lazy_jit_state| { - let mut lazy_jit_state = lazy_jit_state.borrow_mut(); - assert!(lazy_jit_state.is_none()); - *lazy_jit_state = Some(JitState { jit_module }); - }); - let f: extern "C" fn(c_int, *const *const c_char) -> c_int = unsafe { ::std::mem::transmute(finalized_start) }; - let (tx, rx) = mpsc::channel(); - GLOBAL_MESSAGE_SENDER.set(Mutex::new(tx)).unwrap(); + let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::>(); - // Spawn the jitted runtime in a new thread so that this rustc thread can handle messages - // (eg to lazily JIT further functions as required) - std::thread::spawn(move || { - let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::>(); + // Push a null pointer as a terminating argument. This is required by POSIX and + // useful as some dynamic linkers use it as a marker to jump over. + argv.push(std::ptr::null()); - // Push a null pointer as a terminating argument. This is required by POSIX and - // useful as some dynamic linkers use it as a marker to jump over. - argv.push(std::ptr::null()); - - let ret = f(args.len() as c_int, argv.as_ptr()); - std::process::exit(ret); - }); - - // Handle messages - loop { - match rx.recv().unwrap() { - // lazy JIT compilation request - compile requested instance and return pointer to result - UnsafeMessage::JitFn { instance_ptr, trampoline_ptr, tx } => { - tx.send(jit_fn(instance_ptr, trampoline_ptr)) - .expect("jitted runtime hung up before response to lazy JIT request was sent"); - } - } - } + let ret = f(args.len() as c_int, argv.as_ptr()); + std::process::exit(ret); } pub(crate) fn codegen_and_compile_fn<'tcx>( @@ -224,58 +148,6 @@ pub(crate) fn codegen_and_compile_fn<'tcx>( }); } -extern "C" fn clif_jit_fn( - instance_ptr: *const Instance<'static>, - trampoline_ptr: *const u8, -) -> *const u8 { - // send the JIT request to the rustc thread, with a channel for the response - let (tx, rx) = mpsc::channel(); - UnsafeMessage::JitFn { instance_ptr, trampoline_ptr, tx }.send(); - - // block on JIT compilation result - rx.recv().expect("rustc thread hung up before responding to sent lazy JIT request") -} - -fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> *const u8 { - rustc_middle::ty::tls::with(|tcx| { - // lift is used to ensure the correct lifetime for instance. - let instance = tcx.lift(unsafe { *instance_ptr }).unwrap(); - - LAZY_JIT_STATE.with(|lazy_jit_state| { - let mut lazy_jit_state = lazy_jit_state.borrow_mut(); - let lazy_jit_state = lazy_jit_state.as_mut().unwrap(); - let jit_module = &mut lazy_jit_state.jit_module; - - let name = tcx.symbol_name(instance).name; - let sig = crate::abi::get_function_sig( - tcx, - jit_module.target_config().default_call_conv, - instance, - ); - let func_id = jit_module.declare_function(name, Linkage::Export, &sig).unwrap(); - - let current_ptr = jit_module.module.read_got_entry(func_id); - - // If the function's GOT entry has already been updated to point at something other - // than the shim trampoline, don't re-jit but just return the new pointer instead. - // This does not need synchronization as this code is executed only by a sole rustc - // thread. - if current_ptr != trampoline_ptr { - return current_ptr; - } - - jit_module.module.prepare_for_function_redefine(func_id).unwrap(); - - let mut cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name); - codegen_and_compile_fn(tcx, &mut cx, &mut Context::new(), jit_module, instance); - - assert!(cx.global_asm.is_empty()); - jit_module.finalize_definitions(); - jit_module.module.get_finalized_function(func_id) - }) - }) -} - fn dep_symbol_lookup_fn( sess: &Session, crate_info: CrateInfo, @@ -323,57 +195,3 @@ fn dep_symbol_lookup_fn( None }) } - -fn codegen_shim<'tcx>( - tcx: TyCtxt<'tcx>, - cached_context: &mut Context, - module: &mut UnwindModule, - inst: Instance<'tcx>, -) { - let pointer_type = module.target_config().pointer_type(); - - let name = tcx.symbol_name(inst).name; - let sig = crate::abi::get_function_sig(tcx, module.target_config().default_call_conv, inst); - let func_id = module.declare_function(name, Linkage::Export, &sig).unwrap(); - - let instance_ptr = Box::into_raw(Box::new(inst)); - - let jit_fn = module - .declare_function( - "__clif_jit_fn", - Linkage::Import, - &Signature { - call_conv: module.target_config().default_call_conv, - params: vec![AbiParam::new(pointer_type), AbiParam::new(pointer_type)], - returns: vec![AbiParam::new(pointer_type)], - }, - ) - .unwrap(); - - let context = cached_context; - context.clear(); - let trampoline = &mut context.func; - trampoline.signature = sig.clone(); - - let mut builder_ctx = FunctionBuilderContext::new(); - let mut trampoline_builder = FunctionBuilder::new(trampoline, &mut builder_ctx); - - let trampoline_fn = module.declare_func_in_func(func_id, trampoline_builder.func); - let jit_fn = module.declare_func_in_func(jit_fn, trampoline_builder.func); - let sig_ref = trampoline_builder.func.import_signature(sig); - - let entry_block = trampoline_builder.create_block(); - trampoline_builder.append_block_params_for_function_params(entry_block); - let fn_args = trampoline_builder.func.dfg.block_params(entry_block).to_vec(); - - trampoline_builder.switch_to_block(entry_block); - let instance_ptr = trampoline_builder.ins().iconst(pointer_type, instance_ptr as u64 as i64); - let trampoline_ptr = trampoline_builder.ins().func_addr(pointer_type, trampoline_fn); - let jitted_fn = trampoline_builder.ins().call(jit_fn, &[instance_ptr, trampoline_ptr]); - let jitted_fn = trampoline_builder.func.dfg.inst_results(jitted_fn)[0]; - let call_inst = trampoline_builder.ins().call_indirect(sig_ref, jitted_fn, &fn_args); - let ret_vals = trampoline_builder.func.dfg.inst_results(call_inst).to_vec(); - trampoline_builder.ins().return_(&ret_vals); - - module.define_function(func_id, context).unwrap(); -} diff --git a/src/lib.rs b/src/lib.rs index c5ca6565a86b..4d97c3ae6048 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -215,7 +215,7 @@ impl CodegenBackend for CraneliftCodegenBackend { }); if config.jit_mode { #[cfg(feature = "jit")] - driver::jit::run_jit(tcx, config.lazy_jit, config.jit_args); + driver::jit::run_jit(tcx, config.jit_args); #[cfg(not(feature = "jit"))] tcx.dcx().fatal("jit support was disabled when compiling rustc_codegen_cranelift"); From 5cdb8663563fa1fc47a869d790e5cd06eaf1de3e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 5 Mar 2025 15:51:35 +0000 Subject: [PATCH 107/745] Update rust-analyzer config mod_bench no longer exists and there is no benefit to not having a sysroot available for mini_core and mini_core_hello_world. --- .vscode/settings.json | 33 ++++++++++++++++----------------- .zed/settings.json | 25 ++++++++++--------------- 2 files changed, 26 insertions(+), 32 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 491646ce59bb..68bd93aea890 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,41 +1,40 @@ { "editor.formatOnSave": true, - // in case rustc.source is disabled for performance reasons; disable the errors about this - "rust-analyzer.diagnostics.disabled": ["unresolved-extern-crate", "unresolved-macro-call"], + "rust-analyzer.diagnostics.disabled": [ + "unresolved-extern-crate", + "unresolved-macro-call" + ], "rust-analyzer.rustc.source": "discover", "rust-analyzer.imports.granularity.enforce": true, "rust-analyzer.imports.granularity.group": "module", "rust-analyzer.imports.prefix": "crate", - "rust-analyzer.cargo.features": ["unstable-features"], + "rust-analyzer.cargo.features": [ + "unstable-features" + ], "rust-analyzer.linkedProjects": [ "./Cargo.toml", "./build_system/Cargo.toml", { + "sysroot_src": "./build/stdlib/library", "crates": [ { "root_module": "./example/mini_core.rs", - "edition": "2018", + "edition": "2015", "deps": [], "cfg": [], }, { "root_module": "./example/mini_core_hello_world.rs", - "edition": "2018", - "deps": [{ "crate": 0, "name": "mini_core" }], + "edition": "2015", + "deps": [ + { + "crate": 0, + "name": "mini_core" + } + ], "cfg": [], }, - { - "root_module": "./example/mod_bench.rs", - "edition": "2018", - "deps": [], - "cfg": [], - }, - ] - }, - { - "sysroot_src": "./build/stdlib/library", - "crates": [ { "root_module": "./example/std_example.rs", "edition": "2015", diff --git a/.zed/settings.json b/.zed/settings.json index e93bed369492..4338a3473311 100644 --- a/.zed/settings.json +++ b/.zed/settings.json @@ -5,7 +5,10 @@ "initialization_options": { "diagnostics": { // in case rustc.source is disabled for performance reasons; disable the errors about this - "disabled": ["unresolved-extern-crate", "unresolved-macro-call"] + "disabled": [ + "unresolved-extern-crate", + "unresolved-macro-call" + ] }, "rustc": { "source": "discover" @@ -18,22 +21,25 @@ "prefix": "crate" }, "cargo": { - "features": ["unstable-features"] + "features": [ + "unstable-features" + ] }, "linkedProjects": [ "./Cargo.toml", "./build_system/Cargo.toml", { + "sysroot_src": "./build/stdlib/library", "crates": [ { "root_module": "./example/mini_core.rs", - "edition": "2018", + "edition": "2015", "deps": [], "cfg": [] }, { "root_module": "./example/mini_core_hello_world.rs", - "edition": "2018", + "edition": "2015", "deps": [ { "crate": 0, @@ -42,17 +48,6 @@ ], "cfg": [] }, - { - "root_module": "./example/mod_bench.rs", - "edition": "2018", - "deps": [], - "cfg": [] - } - ] - }, - { - "sysroot_src": "./build/stdlib/library", - "crates": [ { "root_module": "./example/std_example.rs", "edition": "2015", From 7eb0a99fc9ff5ee3870a07926d5137d434ee22ab Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 5 Mar 2025 15:55:41 +0000 Subject: [PATCH 108/745] Fix jit mode testing --- build_system/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_system/tests.rs b/build_system/tests.rs index 1b1f0f483a33..9ec0d3850f11 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -374,7 +374,7 @@ impl<'a> TestRunner<'a> { TestCaseCmd::JitBin { source, args } => { let mut jit_cmd = self.rustc_command([ "-Zunstable-options", - "-Cllvm-args=mode=jit", + "-Cllvm-args=jit-mode", "-Cprefer-dynamic", source, "--cfg", From 1cd7022fb433e74c0e5e037a6af32b0c2153c51b Mon Sep 17 00:00:00 2001 From: lapla-cogito Date: Wed, 29 Jan 2025 13:32:58 +0900 Subject: [PATCH 109/745] fix incorrect suggestions related to parentheses in `needless_return` --- clippy_utils/src/lib.rs | 2 +- tests/ui/needless_return.fixed | 12 +++- tests/ui/needless_return.rs | 12 +++- tests/ui/needless_return.stderr | 122 ++++++++++++++++++-------------- 4 files changed, 90 insertions(+), 58 deletions(-) diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 0d9502c50db6..60866d9065d5 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -3552,7 +3552,7 @@ pub fn is_block_like(expr: &Expr<'_>) -> bool { pub fn binary_expr_needs_parentheses(expr: &Expr<'_>) -> bool { fn contains_block(expr: &Expr<'_>, is_operand: bool) -> bool { match expr.kind { - ExprKind::Binary(_, lhs, _) => contains_block(lhs, true), + ExprKind::Binary(_, lhs, _) | ExprKind::Cast(lhs, _) => contains_block(lhs, true), _ if is_block_like(expr) => is_operand, _ => false, } diff --git a/tests/ui/needless_return.fixed b/tests/ui/needless_return.fixed index efc073ebe874..ad625ad6d507 100644 --- a/tests/ui/needless_return.fixed +++ b/tests/ui/needless_return.fixed @@ -6,7 +6,8 @@ clippy::single_match, clippy::needless_bool, clippy::equatable_if_let, - clippy::needless_else + clippy::needless_else, + clippy::missing_safety_doc )] #![warn(clippy::needless_return)] @@ -442,3 +443,12 @@ fn b(x: Option) -> Option { }, } } + +unsafe fn todo() -> *const u8 { + todo!() +} + +pub unsafe fn issue_12157() -> *const i32 { + (unsafe { todo() } as *const i32) + //~^ needless_return +} diff --git a/tests/ui/needless_return.rs b/tests/ui/needless_return.rs index 283d86f25fe5..41d7e5bdd506 100644 --- a/tests/ui/needless_return.rs +++ b/tests/ui/needless_return.rs @@ -6,7 +6,8 @@ clippy::single_match, clippy::needless_bool, clippy::equatable_if_let, - clippy::needless_else + clippy::needless_else, + clippy::missing_safety_doc )] #![warn(clippy::needless_return)] @@ -451,3 +452,12 @@ fn b(x: Option) -> Option { }, } } + +unsafe fn todo() -> *const u8 { + todo!() +} + +pub unsafe fn issue_12157() -> *const i32 { + return unsafe { todo() } as *const i32; + //~^ needless_return +} diff --git a/tests/ui/needless_return.stderr b/tests/ui/needless_return.stderr index 3865a7fea6bf..18553780ad0c 100644 --- a/tests/ui/needless_return.stderr +++ b/tests/ui/needless_return.stderr @@ -1,5 +1,5 @@ error: unneeded `return` statement - --> tests/ui/needless_return.rs:29:5 + --> tests/ui/needless_return.rs:30:5 | LL | return true; | ^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:34:5 + --> tests/ui/needless_return.rs:35:5 | LL | return true; | ^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:40:5 + --> tests/ui/needless_return.rs:41:5 | LL | return true;;; | ^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:46:5 + --> tests/ui/needless_return.rs:47:5 | LL | return true;; ; ; | ^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:52:9 + --> tests/ui/needless_return.rs:53:9 | LL | return true; | ^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:55:9 + --> tests/ui/needless_return.rs:56:9 | LL | return false; | ^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + false | error: unneeded `return` statement - --> tests/ui/needless_return.rs:62:17 + --> tests/ui/needless_return.rs:63:17 | LL | true => return false, | ^^^^^^^^^^^^ @@ -84,7 +84,7 @@ LL | true => false, | ~~~~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:65:13 + --> tests/ui/needless_return.rs:66:13 | LL | return true; | ^^^^^^^^^^^ @@ -96,7 +96,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:73:9 + --> tests/ui/needless_return.rs:74:9 | LL | return true; | ^^^^^^^^^^^ @@ -108,7 +108,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:76:16 + --> tests/ui/needless_return.rs:77:16 | LL | let _ = || return true; | ^^^^^^^^^^^ @@ -119,7 +119,7 @@ LL | let _ = || true; | ~~~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:81:5 + --> tests/ui/needless_return.rs:82:5 | LL | return the_answer!(); | ^^^^^^^^^^^^^^^^^^^^ @@ -131,7 +131,7 @@ LL + the_answer!() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:85:21 + --> tests/ui/needless_return.rs:86:21 | LL | fn test_void_fun() { | _____________________^ @@ -146,7 +146,7 @@ LL + fn test_void_fun() { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:91:11 + --> tests/ui/needless_return.rs:92:11 | LL | if b { | ___________^ @@ -161,7 +161,7 @@ LL + if b { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:94:13 + --> tests/ui/needless_return.rs:95:13 | LL | } else { | _____________^ @@ -176,7 +176,7 @@ LL + } else { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:103:14 + --> tests/ui/needless_return.rs:104:14 | LL | _ => return, | ^^^^^^ @@ -187,7 +187,7 @@ LL | _ => (), | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:112:24 + --> tests/ui/needless_return.rs:113:24 | LL | let _ = 42; | ________________________^ @@ -202,7 +202,7 @@ LL + let _ = 42; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:116:14 + --> tests/ui/needless_return.rs:117:14 | LL | _ => return, | ^^^^^^ @@ -213,7 +213,7 @@ LL | _ => (), | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:130:9 + --> tests/ui/needless_return.rs:131:9 | LL | return String::from("test"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -225,7 +225,7 @@ LL + String::from("test") | error: unneeded `return` statement - --> tests/ui/needless_return.rs:133:9 + --> tests/ui/needless_return.rs:134:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^ @@ -237,7 +237,7 @@ LL + String::new() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:156:32 + --> tests/ui/needless_return.rs:157:32 | LL | bar.unwrap_or_else(|_| return) | ^^^^^^ @@ -248,7 +248,7 @@ LL | bar.unwrap_or_else(|_| {}) | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:161:21 + --> tests/ui/needless_return.rs:162:21 | LL | let _ = || { | _____________________^ @@ -263,7 +263,7 @@ LL + let _ = || { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:165:20 + --> tests/ui/needless_return.rs:166:20 | LL | let _ = || return; | ^^^^^^ @@ -274,7 +274,7 @@ LL | let _ = || {}; | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:172:32 + --> tests/ui/needless_return.rs:173:32 | LL | res.unwrap_or_else(|_| return Foo) | ^^^^^^^^^^ @@ -285,7 +285,7 @@ LL | res.unwrap_or_else(|_| Foo) | ~~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:182:5 + --> tests/ui/needless_return.rs:183:5 | LL | return true; | ^^^^^^^^^^^ @@ -297,7 +297,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:187:5 + --> tests/ui/needless_return.rs:188:5 | LL | return true; | ^^^^^^^^^^^ @@ -309,7 +309,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:193:9 + --> tests/ui/needless_return.rs:194:9 | LL | return true; | ^^^^^^^^^^^ @@ -321,7 +321,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:196:9 + --> tests/ui/needless_return.rs:197:9 | LL | return false; | ^^^^^^^^^^^^ @@ -333,7 +333,7 @@ LL + false | error: unneeded `return` statement - --> tests/ui/needless_return.rs:203:17 + --> tests/ui/needless_return.rs:204:17 | LL | true => return false, | ^^^^^^^^^^^^ @@ -344,7 +344,7 @@ LL | true => false, | ~~~~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:206:13 + --> tests/ui/needless_return.rs:207:13 | LL | return true; | ^^^^^^^^^^^ @@ -356,7 +356,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:214:9 + --> tests/ui/needless_return.rs:215:9 | LL | return true; | ^^^^^^^^^^^ @@ -368,7 +368,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:217:16 + --> tests/ui/needless_return.rs:218:16 | LL | let _ = || return true; | ^^^^^^^^^^^ @@ -379,7 +379,7 @@ LL | let _ = || true; | ~~~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:222:5 + --> tests/ui/needless_return.rs:223:5 | LL | return the_answer!(); | ^^^^^^^^^^^^^^^^^^^^ @@ -391,7 +391,7 @@ LL + the_answer!() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:226:33 + --> tests/ui/needless_return.rs:227:33 | LL | async fn async_test_void_fun() { | _________________________________^ @@ -406,7 +406,7 @@ LL + async fn async_test_void_fun() { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:232:11 + --> tests/ui/needless_return.rs:233:11 | LL | if b { | ___________^ @@ -421,7 +421,7 @@ LL + if b { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:235:13 + --> tests/ui/needless_return.rs:236:13 | LL | } else { | _____________^ @@ -436,7 +436,7 @@ LL + } else { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:244:14 + --> tests/ui/needless_return.rs:245:14 | LL | _ => return, | ^^^^^^ @@ -447,7 +447,7 @@ LL | _ => (), | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:258:9 + --> tests/ui/needless_return.rs:259:9 | LL | return String::from("test"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -459,7 +459,7 @@ LL + String::from("test") | error: unneeded `return` statement - --> tests/ui/needless_return.rs:261:9 + --> tests/ui/needless_return.rs:262:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^ @@ -471,7 +471,7 @@ LL + String::new() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:278:5 + --> tests/ui/needless_return.rs:279:5 | LL | return format!("Hello {}", "world!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -483,7 +483,7 @@ LL + format!("Hello {}", "world!") | error: unneeded `return` statement - --> tests/ui/needless_return.rs:320:9 + --> tests/ui/needless_return.rs:321:9 | LL | return true; | ^^^^^^^^^^^ @@ -498,7 +498,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:323:9 + --> tests/ui/needless_return.rs:324:9 | LL | return false; | ^^^^^^^^^^^^ @@ -511,7 +511,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:331:13 + --> tests/ui/needless_return.rs:332:13 | LL | return 10; | ^^^^^^^^^ @@ -526,7 +526,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:335:13 + --> tests/ui/needless_return.rs:336:13 | LL | return 100; | ^^^^^^^^^^ @@ -540,7 +540,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:344:9 + --> tests/ui/needless_return.rs:345:9 | LL | return 0; | ^^^^^^^^ @@ -553,7 +553,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:352:13 + --> tests/ui/needless_return.rs:353:13 | LL | return *(x as *const isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -569,7 +569,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:355:13 + --> tests/ui/needless_return.rs:356:13 | LL | return !*(x as *const isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -583,7 +583,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:363:20 + --> tests/ui/needless_return.rs:364:20 | LL | let _ = 42; | ____________________^ @@ -598,7 +598,7 @@ LL + let _ = 42; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:370:20 + --> tests/ui/needless_return.rs:371:20 | LL | let _ = 42; return; | ^^^^^^^ @@ -610,7 +610,7 @@ LL + let _ = 42; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:383:9 + --> tests/ui/needless_return.rs:384:9 | LL | return Ok(format!("ok!")); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -622,7 +622,7 @@ LL + Ok(format!("ok!")) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:386:9 + --> tests/ui/needless_return.rs:387:9 | LL | return Err(format!("err!")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -634,7 +634,7 @@ LL + Err(format!("err!")) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:393:9 + --> tests/ui/needless_return.rs:394:9 | LL | return if true { 1 } else { 2 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -646,7 +646,7 @@ LL + if true { 1 } else { 2 } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:398:9 + --> tests/ui/needless_return.rs:399:9 | LL | return if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -658,7 +658,7 @@ LL + (if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else | error: unneeded `return` statement - --> tests/ui/needless_return.rs:420:5 + --> tests/ui/needless_return.rs:421:5 | LL | return { "a".to_string() } + "b" + { "c" }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -670,7 +670,7 @@ LL + ({ "a".to_string() } + "b" + { "c" }) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:425:5 + --> tests/ui/needless_return.rs:426:5 | LL | return "".split("").next().unwrap().to_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -681,5 +681,17 @@ LL - return "".split("").next().unwrap().to_string(); LL + "".split("").next().unwrap().to_string() | -error: aborting due to 54 previous errors +error: unneeded `return` statement + --> tests/ui/needless_return.rs:461:5 + | +LL | return unsafe { todo() } as *const i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove `return` and wrap the sequence with parentheses + | +LL - return unsafe { todo() } as *const i32; +LL + (unsafe { todo() } as *const i32) + | + +error: aborting due to 55 previous errors From 2fda4f6bb85ae334ae36cc4b3d88a609b3132bd0 Mon Sep 17 00:00:00 2001 From: lapla-cogito Date: Tue, 25 Feb 2025 08:32:37 +0900 Subject: [PATCH 110/745] add `is_expr_temporary_value` helper function --- clippy_utils/src/lib.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 62f70a5d957f..82433405cde9 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -2331,6 +2331,18 @@ pub fn is_expr_final_block_expr(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { matches!(tcx.parent_hir_node(expr.hir_id), Node::Block(..)) } +/// Checks if the expression is a temporary value. +// This logic is the same as the one used in rustc's `check_named_place_expr function`. +// https://github.com/rust-lang/rust/blob/3ed2a10d173d6c2e0232776af338ca7d080b1cd4/compiler/rustc_hir_typeck/src/expr.rs#L482-L499 +pub fn is_expr_temporary_value(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + !expr.is_place_expr(|base| { + cx.typeck_results() + .adjustments() + .get(base.hir_id) + .is_some_and(|x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_)))) + }) +} + pub fn std_or_core(cx: &LateContext<'_>) -> Option<&'static str> { if !is_no_std_crate(cx) { Some("std") From 27e69a80f5bf6660fdadaa52c364a16994116688 Mon Sep 17 00:00:00 2001 From: lapla-cogito Date: Tue, 25 Feb 2025 08:34:13 +0900 Subject: [PATCH 111/745] apply `is_expr_temporary_value` to Clippy source --- clippy_lints/src/casts/borrow_as_ptr.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/casts/borrow_as_ptr.rs b/clippy_lints/src/casts/borrow_as_ptr.rs index 6057144bc6a4..c1d775831c0f 100644 --- a/clippy_lints/src/casts/borrow_as_ptr.rs +++ b/clippy_lints/src/casts/borrow_as_ptr.rs @@ -2,11 +2,10 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::msrvs::Msrv; use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::has_enclosing_paren; -use clippy_utils::{is_lint_allowed, msrvs, std_or_core}; +use clippy_utils::{is_expr_temporary_value, is_lint_allowed, msrvs, std_or_core}; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Ty, TyKind}; use rustc_lint::LateContext; -use rustc_middle::ty::adjustment::Adjust; use rustc_span::BytePos; use super::BORROW_AS_PTR; @@ -25,12 +24,7 @@ pub(super) fn check<'tcx>( let mut app = Applicability::MachineApplicable; let snip = snippet_with_context(cx, e.span, cast_expr.span.ctxt(), "..", &mut app).0; // Fix #9884 - if !e.is_place_expr(|base| { - cx.typeck_results() - .adjustments() - .get(base.hir_id) - .is_some_and(|x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_)))) - }) { + if is_expr_temporary_value(cx, e) { return false; } From 06f797d3f7663f0854387d4f09865ba7b208f260 Mon Sep 17 00:00:00 2001 From: lapla-cogito Date: Tue, 18 Feb 2025 03:25:10 +0900 Subject: [PATCH 112/745] don't call `iter()` on a temporary object in `unnecessary_to_owned` --- .../src/methods/unnecessary_to_owned.rs | 5 +- tests/ui/unnecessary_to_owned.fixed | 36 ++++---- tests/ui/unnecessary_to_owned.rs | 36 ++++---- tests/ui/unnecessary_to_owned.stderr | 86 ++++++------------- 4 files changed, 59 insertions(+), 104 deletions(-) diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index e80d99dca56d..f2d040003393 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -6,7 +6,8 @@ use clippy_utils::source::{SpanRangeExt, snippet}; 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, peel_middle_ty_refs, return_ty, + fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, is_expr_temporary_value, peel_middle_ty_refs, + return_ty, }; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; @@ -219,6 +220,8 @@ fn check_into_iter_call_arg( && let Some(receiver_snippet) = receiver.span.get_source_text(cx) // If the receiver is a `Cow`, we can't remove the `into_owned` generally, see https://github.com/rust-lang/rust-clippy/issues/13624. && !is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(receiver), sym::Cow) + // Calling `iter()` on a temporary object can lead to false positives. #14242 + && !is_expr_temporary_value(cx, receiver) { if unnecessary_iter_cloned::check_for_loop_iter(cx, parent, method_name, receiver, true) { return true; diff --git a/tests/ui/unnecessary_to_owned.fixed b/tests/ui/unnecessary_to_owned.fixed index bf271aef763b..5410033dbd8f 100644 --- a/tests/ui/unnecessary_to_owned.fixed +++ b/tests/ui/unnecessary_to_owned.fixed @@ -195,19 +195,11 @@ fn main() { //~^ unnecessary_to_owned let _ = slice.iter().copied(); //~^ unnecessary_to_owned - let _ = [std::path::PathBuf::new()][..].iter().cloned(); - //~^ unnecessary_to_owned - let _ = [std::path::PathBuf::new()][..].iter().cloned(); - //~^ unnecessary_to_owned let _ = slice.iter().copied(); //~^ unnecessary_to_owned let _ = slice.iter().copied(); //~^ unnecessary_to_owned - let _ = [std::path::PathBuf::new()][..].iter().cloned(); - //~^ unnecessary_to_owned - let _ = [std::path::PathBuf::new()][..].iter().cloned(); - //~^ unnecessary_to_owned let _ = check_files(&[FileType::Account]); @@ -317,19 +309,6 @@ fn get_file_path(_file_type: &FileType) -> Result impl IntoIterator { cow.into_owned().into_iter() } + +mod issue_14242 { + use std::rc::Rc; + + #[derive(Copy, Clone)] + struct Foo; + + fn rc_slice_provider() -> Rc<[Foo]> { + Rc::from([Foo]) + } + + fn iterator_provider() -> impl Iterator { + rc_slice_provider().to_vec().into_iter() + } +} diff --git a/tests/ui/unnecessary_to_owned.rs b/tests/ui/unnecessary_to_owned.rs index 95b95ab6bd22..0619dd4ddec0 100644 --- a/tests/ui/unnecessary_to_owned.rs +++ b/tests/ui/unnecessary_to_owned.rs @@ -195,19 +195,11 @@ fn main() { //~^ unnecessary_to_owned let _ = slice.to_owned().into_iter(); //~^ unnecessary_to_owned - let _ = [std::path::PathBuf::new()][..].to_vec().into_iter(); - //~^ unnecessary_to_owned - let _ = [std::path::PathBuf::new()][..].to_owned().into_iter(); - //~^ unnecessary_to_owned let _ = IntoIterator::into_iter(slice.to_vec()); //~^ unnecessary_to_owned let _ = IntoIterator::into_iter(slice.to_owned()); //~^ unnecessary_to_owned - let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_vec()); - //~^ unnecessary_to_owned - let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_owned()); - //~^ unnecessary_to_owned let _ = check_files(&[FileType::Account]); @@ -317,19 +309,6 @@ fn get_file_path(_file_type: &FileType) -> Result impl IntoIterator { cow.into_owned().into_iter() } + +mod issue_14242 { + use std::rc::Rc; + + #[derive(Copy, Clone)] + struct Foo; + + fn rc_slice_provider() -> Rc<[Foo]> { + Rc::from([Foo]) + } + + fn iterator_provider() -> impl Iterator { + rc_slice_provider().to_vec().into_iter() + } +} diff --git a/tests/ui/unnecessary_to_owned.stderr b/tests/ui/unnecessary_to_owned.stderr index 4daa3876e60e..8926db34da8c 100644 --- a/tests/ui/unnecessary_to_owned.stderr +++ b/tests/ui/unnecessary_to_owned.stderr @@ -1,11 +1,11 @@ error: redundant clone - --> tests/ui/unnecessary_to_owned.rs:225:64 + --> tests/ui/unnecessary_to_owned.rs:217:64 | LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned()); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/unnecessary_to_owned.rs:225:20 + --> tests/ui/unnecessary_to_owned.rs:217:20 | LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,49 +13,49 @@ LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned()) = help: to override `-D warnings` add `#[allow(clippy::redundant_clone)]` error: redundant clone - --> tests/ui/unnecessary_to_owned.rs:227:40 + --> tests/ui/unnecessary_to_owned.rs:219:40 | LL | require_os_str(&OsString::from("x").to_os_string()); | ^^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/unnecessary_to_owned.rs:227:21 + --> tests/ui/unnecessary_to_owned.rs:219:21 | LL | require_os_str(&OsString::from("x").to_os_string()); | ^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> tests/ui/unnecessary_to_owned.rs:229:48 + --> tests/ui/unnecessary_to_owned.rs:221:48 | LL | require_path(&std::path::PathBuf::from("x").to_path_buf()); | ^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/unnecessary_to_owned.rs:229:19 + --> tests/ui/unnecessary_to_owned.rs:221:19 | LL | require_path(&std::path::PathBuf::from("x").to_path_buf()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> tests/ui/unnecessary_to_owned.rs:231:35 + --> tests/ui/unnecessary_to_owned.rs:223:35 | LL | require_str(&String::from("x").to_string()); | ^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/unnecessary_to_owned.rs:231:18 + --> tests/ui/unnecessary_to_owned.rs:223:18 | LL | require_str(&String::from("x").to_string()); | ^^^^^^^^^^^^^^^^^ error: redundant clone - --> tests/ui/unnecessary_to_owned.rs:233:39 + --> tests/ui/unnecessary_to_owned.rs:225:39 | LL | require_slice(&[String::from("x")].to_owned()); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/unnecessary_to_owned.rs:233:20 + --> tests/ui/unnecessary_to_owned.rs:225:20 | LL | require_slice(&[String::from("x")].to_owned()); | ^^^^^^^^^^^^^^^^^^^ @@ -442,43 +442,19 @@ LL | let _ = slice.to_owned().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:198:13 - | -LL | let _ = [std::path::PathBuf::new()][..].to_vec().into_iter(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` - -error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:200:13 - | -LL | let _ = [std::path::PathBuf::new()][..].to_owned().into_iter(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` - -error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:203:13 + --> tests/ui/unnecessary_to_owned.rs:199:13 | LL | let _ = IntoIterator::into_iter(slice.to_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:205:13 + --> tests/ui/unnecessary_to_owned.rs:201:13 | LL | let _ = IntoIterator::into_iter(slice.to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` -error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:207:13 - | -LL | let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_vec()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` - -error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:209:13 - | -LL | let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_owned()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` - error: allocating a new `String` only to create a temporary `&str` from it - --> tests/ui/unnecessary_to_owned.rs:237:26 + --> tests/ui/unnecessary_to_owned.rs:229:26 | LL | let _ref_str: &str = &String::from_utf8(slice.to_vec()).expect("not UTF-8"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -490,7 +466,7 @@ LL + let _ref_str: &str = core::str::from_utf8(&slice).expect("not UTF-8"); | error: allocating a new `String` only to create a temporary `&str` from it - --> tests/ui/unnecessary_to_owned.rs:239:26 + --> tests/ui/unnecessary_to_owned.rs:231:26 | LL | let _ref_str: &str = &String::from_utf8(b"foo".to_vec()).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -502,7 +478,7 @@ LL + let _ref_str: &str = core::str::from_utf8(b"foo").unwrap(); | error: allocating a new `String` only to create a temporary `&str` from it - --> tests/ui/unnecessary_to_owned.rs:241:26 + --> tests/ui/unnecessary_to_owned.rs:233:26 | LL | let _ref_str: &str = &String::from_utf8(b"foo".as_slice().to_owned()).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -514,7 +490,7 @@ LL + let _ref_str: &str = core::str::from_utf8(b"foo".as_slice()).unwrap(); | error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:299:14 + --> tests/ui/unnecessary_to_owned.rs:291:14 | LL | for t in file_types.to_vec() { | ^^^^^^^^^^^^^^^^^^^ @@ -526,65 +502,53 @@ LL | LL ~ let path = match get_file_path(t) { | -error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:323:14 - | -LL | let _ = &["x"][..].to_vec().into_iter(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `["x"][..].iter().cloned()` - -error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:329:14 - | -LL | let _ = &["x"][..].to_vec().into_iter(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `["x"][..].iter().copied()` - error: unnecessary use of `to_string` - --> tests/ui/unnecessary_to_owned.rs:378:24 + --> tests/ui/unnecessary_to_owned.rs:357:24 | LL | Box::new(build(y.to_string())) | ^^^^^^^^^^^^^ help: use: `y` error: unnecessary use of `to_string` - --> tests/ui/unnecessary_to_owned.rs:488:12 + --> tests/ui/unnecessary_to_owned.rs:467:12 | LL | id("abc".to_string()) | ^^^^^^^^^^^^^^^^^ help: use: `"abc"` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:632:37 + --> tests/ui/unnecessary_to_owned.rs:611:37 | LL | IntoFuture::into_future(foo([].to_vec(), &0)); | ^^^^^^^^^^^ help: use: `[]` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:643:18 + --> tests/ui/unnecessary_to_owned.rs:622:18 | LL | s.remove(&a.to_vec()); | ^^^^^^^^^^^ help: replace it with: `a` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:648:14 + --> tests/ui/unnecessary_to_owned.rs:627:14 | LL | s.remove(&"b".to_owned()); | ^^^^^^^^^^^^^^^ help: replace it with: `"b"` error: unnecessary use of `to_string` - --> tests/ui/unnecessary_to_owned.rs:650:14 + --> tests/ui/unnecessary_to_owned.rs:629:14 | LL | s.remove(&"b".to_string()); | ^^^^^^^^^^^^^^^^ help: replace it with: `"b"` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:656:14 + --> tests/ui/unnecessary_to_owned.rs:635:14 | LL | s.remove(&["b"].to_vec()); | ^^^^^^^^^^^^^^^ help: replace it with: `["b"].as_slice()` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:658:14 + --> tests/ui/unnecessary_to_owned.rs:637:14 | LL | s.remove(&(&["b"]).to_vec()); | ^^^^^^^^^^^^^^^^^^ help: replace it with: `(&["b"]).as_slice()` -error: aborting due to 88 previous errors +error: aborting due to 82 previous errors From 1be80d48fa0f3fdea8dec7f05426dd619dfdf411 Mon Sep 17 00:00:00 2001 From: moxian Date: Wed, 5 Mar 2025 17:43:24 -0800 Subject: [PATCH 113/745] Leave a breadcrumb towards bootstrap config documentation --- src/bootstrap/src/core/build_steps/setup.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index f25dfaab0f11..ae6544227a62 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -216,8 +216,9 @@ fn setup_config_toml(path: &Path, profile: Profile, config: &Config) { let latest_change_id = CONFIG_CHANGE_HISTORY.last().unwrap().change_id; let settings = format!( - "# Includes one of the default files in {PROFILE_DIR}\n\ - profile = \"{profile}\"\n\ + "# See bootstrap.example.toml for documentation of available options\n\ + #\n\ + profile = \"{profile}\" # Includes one of the default files in {PROFILE_DIR}\n\ change-id = {latest_change_id}\n" ); From 95a65704d9ed8fb175eeb1143c675e4f96e2bd40 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Thu, 6 Mar 2025 05:05:15 +0000 Subject: [PATCH 114/745] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 92f8fa089b0d..f6fd106fa523 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -1c3b035542775e9a5decc93167d351b062942d32 +30f168ef811aec63124eac677e14699baa9395bd From a028651184f66700f3c48755f4d8ff52666df1c6 Mon Sep 17 00:00:00 2001 From: yanglsh Date: Tue, 25 Feb 2025 22:47:42 +0800 Subject: [PATCH 115/745] fix: `missing_const_for_fn` FP on unstable const traits --- clippy_utils/src/qualify_min_const_fn.rs | 40 +++++---- .../ui/missing_const_for_fn/cant_be_const.rs | 88 +++++++++++++++++++ 2 files changed, 112 insertions(+), 16 deletions(-) diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index 8e6f4d4a317e..5d0401010db6 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -395,24 +395,32 @@ fn check_terminator<'tcx>( fn is_stable_const_fn(cx: &LateContext<'_>, def_id: DefId, msrv: Msrv) -> bool { cx.tcx.is_const_fn(def_id) - && cx.tcx.lookup_const_stability(def_id).is_none_or(|const_stab| { - if let rustc_attr_parsing::StabilityLevel::Stable { since, .. } = const_stab.level { - // Checking MSRV is manually necessary because `rustc` has no such concept. This entire - // function could be removed if `rustc` provided a MSRV-aware version of `is_stable_const_fn`. - // as a part of an unimplemented MSRV check https://github.com/rust-lang/rust/issues/65262. + && cx + .tcx + .lookup_const_stability(def_id) + .or_else(|| { + cx.tcx + .trait_of_item(def_id) + .and_then(|trait_def_id| cx.tcx.lookup_const_stability(trait_def_id)) + }) + .is_none_or(|const_stab| { + if let rustc_attr_parsing::StabilityLevel::Stable { since, .. } = const_stab.level { + // Checking MSRV is manually necessary because `rustc` has no such concept. This entire + // function could be removed if `rustc` provided a MSRV-aware version of `is_stable_const_fn`. + // as a part of an unimplemented MSRV check https://github.com/rust-lang/rust/issues/65262. - let const_stab_rust_version = match since { - StableSince::Version(version) => version, - StableSince::Current => RustcVersion::CURRENT, - StableSince::Err => return false, - }; + let const_stab_rust_version = match since { + StableSince::Version(version) => version, + StableSince::Current => RustcVersion::CURRENT, + StableSince::Err => return false, + }; - msrv.meets(cx, const_stab_rust_version) - } else { - // Unstable const fn, check if the feature is enabled. - cx.tcx.features().enabled(const_stab.feature) && msrv.current(cx).is_none() - } - }) + msrv.meets(cx, const_stab_rust_version) + } else { + // Unstable const fn, check if the feature is enabled. + cx.tcx.features().enabled(const_stab.feature) && msrv.current(cx).is_none() + } + }) } fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>) -> bool { diff --git a/tests/ui/missing_const_for_fn/cant_be_const.rs b/tests/ui/missing_const_for_fn/cant_be_const.rs index aef5eb5b890a..d8e1c468db0d 100644 --- a/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -217,3 +217,91 @@ mod with_ty_alias { fn mut_add(x: &mut i32) { *x += 1; } + +#[clippy::msrv = "1.87"] +mod issue14020 { + use std::ops::Add; + + fn f(a: T, b: T) -> ::Output { + a + b + } +} + +#[clippy::msrv = "1.87"] +mod issue14290 { + use std::ops::{Deref, DerefMut}; + + struct Wrapper { + t: T, + } + + impl Deref for Wrapper { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.t + } + } + impl DerefMut for Wrapper { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.t + } + } + + struct Example(bool); + + fn do_something(mut a: Wrapper) { + a.0 = !a.0; + } + + pub struct Stream(Vec); + + impl Stream { + pub fn bytes(&self) -> &[u8] { + &self.0 + } + } +} + +#[clippy::msrv = "1.87"] +mod issue14091 { + use std::mem::ManuallyDrop; + + struct BucketSlotGuard<'a> { + id: u32, + free_list: &'a mut Vec, + } + + impl BucketSlotGuard<'_> { + fn into_inner(self) -> u32 { + let this = ManuallyDrop::new(self); + this.id + } + } + + use std::ops::{Deref, DerefMut}; + + struct Wrap(T); + + impl Deref for Wrap { + type Target = T; + fn deref(&self) -> &T { + &self.0 + } + } + + impl DerefMut for Wrap { + fn deref_mut(&mut self) -> &mut T { + &mut self.0 + } + } + + fn smart_two_field(v: &mut Wrap<(i32, i32)>) { + let _a = &mut v.0; + let _b = &mut v.1; + } + + fn smart_destructure(v: &mut Wrap<(i32, i32)>) { + let (ref mut _head, ref mut _tail) = **v; + } +} From e5c1d1cb7ee727246a6d453f52b5707e264387d5 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 5 Feb 2025 15:22:10 +0000 Subject: [PATCH 116/745] Remove the `Option` part of range ends in the HIR --- clippy_utils/src/hir_utils.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index 4bd86a253351..c47c08285c2e 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -1108,14 +1108,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { pub fn hash_ty_pat(&mut self, pat: &TyPat<'_>) { std::mem::discriminant(&pat.kind).hash(&mut self.s); match pat.kind { - TyPatKind::Range(s, e, i) => { - if let Some(s) = s { - self.hash_const_arg(s); - } - if let Some(e) = e { - self.hash_const_arg(e); - } - std::mem::discriminant(&i).hash(&mut self.s); + TyPatKind::Range(s, e) => { + self.hash_const_arg(s); + self.hash_const_arg(e); }, TyPatKind::Err(_) => {}, } From f048c4501839701e27443abe68407f2824197137 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 6 Mar 2025 12:40:11 +0000 Subject: [PATCH 117/745] Rustup to rustc 1.87.0-nightly (30f168ef8 2025-03-05) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index d9b4f2fc6743..4a566552322a 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-03-03" +channel = "nightly-2025-03-06" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From 75109ec1ba2fe1b5182f2accab3e31a1b6e810f7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 6 Mar 2025 12:46:54 +0000 Subject: [PATCH 118/745] FIx rustc test suite --- scripts/test_rustc_tests.sh | 40 +++++++------------------------------ 1 file changed, 7 insertions(+), 33 deletions(-) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index 599ce63bab56..63f3c8b05036 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -152,46 +152,20 @@ rm tests/ui/process/process-panic-after-fork.rs # same cp ../dist/bin/rustdoc-clif ../dist/bin/rustdoc # some tests expect bin/rustdoc to exist cp $(../dist/rustc-clif --print target-libdir)/libstd-*.so ../dist/lib/ -# prevent $(RUSTDOC) from picking up the sysroot built by x.py. It conflicts with the one used by -# rustdoc-clif cat < Self { - #[track_caller] - pub fn new() -> Self { - let mut cmd = setup_common(); -- cmd.arg("-L").arg(env_var_os("TARGET_RPATH_DIR")); - Self { cmd } - } - diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs index e7ae773ffa1d3..04bc2d7787da7 100644 --- a/src/tools/compiletest/src/runtest/run_make.rs +++ b/src/tools/compiletest/src/runtest/run_make.rs -@@ -329,7 +329,6 @@ impl TestCx<'_> { +@@ -117,7 +117,6 @@ impl TestCx<'_> { .arg(format!("run_make_support={}", &support_lib_path.to_string_lossy())) .arg("--edition=2021") - .arg(&self.testpaths.file.join("rmake.rs")) -- .arg("-Cprefer-dynamic") - // Provide necessary library search paths for rustc. - .env(dylib_env_var(), &env::join_paths(host_dylib_search_paths).unwrap()); +- .arg(&self.testpaths.file.join("rmake.rs")) +- .arg("-Cprefer-dynamic"); ++ .arg(&self.testpaths.file.join("rmake.rs")); + // In test code we want to be very pedantic about values being silently discarded that are + // annotated with \`#[must_use]\`. diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs index 30387af428c..f7895b12961 100644 --- a/tests/run-make/linker-warning/rmake.rs @@ -205,7 +179,7 @@ index 30387af428c..f7895b12961 100644 regex::escape(run_make_support::build_root().to_str().unwrap()), "/build-root", ) - .run(); + .normalize(r#""[^"]*\/symbols.o""#, "\\"/symbols.o\\"") EOF echo "[TEST] rustc test suite" From aa31d42b39cf9a7c216736392aa522a94794c071 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 6 Mar 2025 12:51:22 +0000 Subject: [PATCH 119/745] Remove no longer necessary disabling of dylib usage for run-make tests Run-make tests are now fully compiled using the bootstrap compiler. --- scripts/test_rustc_tests.sh | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index 63f3c8b05036..005e87c2b2ad 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -150,22 +150,8 @@ rm tests/ui/intrinsics/panic-uninitialized-zeroed.rs # same rm tests/ui/process/process-panic-after-fork.rs # same cp ../dist/bin/rustdoc-clif ../dist/bin/rustdoc # some tests expect bin/rustdoc to exist -cp $(../dist/rustc-clif --print target-libdir)/libstd-*.so ../dist/lib/ cat < { - .arg(format!("run_make_support={}", &support_lib_path.to_string_lossy())) - .arg("--edition=2021") -- .arg(&self.testpaths.file.join("rmake.rs")) -- .arg("-Cprefer-dynamic"); -+ .arg(&self.testpaths.file.join("rmake.rs")); - - // In test code we want to be very pedantic about values being silently discarded that are - // annotated with \`#[must_use]\`. diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs index 30387af428c..f7895b12961 100644 --- a/tests/run-make/linker-warning/rmake.rs From 58c10c66c1d5ec2e47e35a4ff31f3758448f20f4 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Fri, 6 Dec 2024 23:16:06 +0100 Subject: [PATCH 120/745] Lower BinOp::Cmp to llvm.{s,u}cmp.* intrinsics Lowers `mir::BinOp::Cmp` (`three_way_compare` intrinsic) to the corresponding LLVM `llvm.{s,u}cmp.i8.*` intrinsics, added in LLVM 19. --- compiler/rustc_codegen_llvm/src/builder.rs | 30 ++++++++++++ compiler/rustc_codegen_llvm/src/context.rs | 12 +++++ compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 3 ++ .../rustc_codegen_ssa/src/traits/builder.rs | 12 +++++ tests/assembly/x86_64-cmp.rs | 46 ++++++++++++------- tests/codegen/comparison-operators-2-tuple.rs | 1 - tests/codegen/integer-cmp.rs | 35 ++++++++++++-- tests/codegen/intrinsics/three_way_compare.rs | 27 ++--------- 8 files changed, 124 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 3f20350d0efd..04b9ed02aab2 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -14,6 +14,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::*; use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; +use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::ty::layout::{ FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTypingEnv, LayoutError, LayoutOfHelpers, @@ -1119,6 +1120,35 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { unsafe { llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, UNNAMED) } } + fn three_way_compare( + &mut self, + ty: Ty<'tcx>, + lhs: Self::Value, + rhs: Self::Value, + ) -> Option { + // FIXME: See comment on the definition of `three_way_compare`. + if crate::llvm_util::get_version() < (20, 0, 0) { + return None; + } + + let name = match (ty.is_signed(), ty.primitive_size(self.tcx).bits()) { + (true, 8) => "llvm.scmp.i8.i8", + (true, 16) => "llvm.scmp.i8.i16", + (true, 32) => "llvm.scmp.i8.i32", + (true, 64) => "llvm.scmp.i8.i64", + (true, 128) => "llvm.scmp.i8.i128", + + (false, 8) => "llvm.ucmp.i8.i8", + (false, 16) => "llvm.ucmp.i8.i16", + (false, 32) => "llvm.ucmp.i8.i32", + (false, 64) => "llvm.ucmp.i8.i64", + (false, 128) => "llvm.ucmp.i8.i128", + + _ => bug!("three-way compare unsupported for type {ty:?}"), + }; + Some(self.call_intrinsic(name, &[lhs, rhs])) + } + /* Miscellaneous instructions */ fn memcpy( &mut self, diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index ed8426ae1974..e367cf90eee6 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -1108,6 +1108,18 @@ impl<'ll> CodegenCx<'ll, '_> { ifn!("llvm.usub.sat.i64", fn(t_i64, t_i64) -> t_i64); ifn!("llvm.usub.sat.i128", fn(t_i128, t_i128) -> t_i128); + ifn!("llvm.scmp.i8.i8", fn(t_i8, t_i8) -> t_i8); + ifn!("llvm.scmp.i8.i16", fn(t_i16, t_i16) -> t_i8); + ifn!("llvm.scmp.i8.i32", fn(t_i32, t_i32) -> t_i8); + ifn!("llvm.scmp.i8.i64", fn(t_i64, t_i64) -> t_i8); + ifn!("llvm.scmp.i8.i128", fn(t_i128, t_i128) -> t_i8); + + ifn!("llvm.ucmp.i8.i8", fn(t_i8, t_i8) -> t_i8); + ifn!("llvm.ucmp.i8.i16", fn(t_i16, t_i16) -> t_i8); + ifn!("llvm.ucmp.i8.i32", fn(t_i32, t_i32) -> t_i8); + ifn!("llvm.ucmp.i8.i64", fn(t_i64, t_i64) -> t_i8); + ifn!("llvm.ucmp.i8.i128", fn(t_i128, t_i128) -> t_i8); + ifn!("llvm.lifetime.start.p0i8", fn(t_i64, ptr) -> void); ifn!("llvm.lifetime.end.p0i8", fn(t_i64, ptr) -> void); diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index d24e48b37a46..992a23442e2f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -1005,6 +1005,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::BinOp::Cmp => { use std::cmp::Ordering; assert!(!is_float); + if let Some(value) = bx.three_way_compare(lhs_ty, lhs, rhs) { + return value; + } let pred = |op| base::bin_op_to_icmp_predicate(op, is_signed); if bx.cx().tcx().sess.opts.optimize == OptLevel::No { // FIXME: This actually generates tighter assembly, and is a classic trick diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 99fd6b6510ff..070b680e540a 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -397,6 +397,18 @@ pub trait BuilderMethods<'a, 'tcx>: fn icmp(&mut self, op: IntPredicate, lhs: Self::Value, rhs: Self::Value) -> Self::Value; fn fcmp(&mut self, op: RealPredicate, lhs: Self::Value, rhs: Self::Value) -> Self::Value; + /// Returns `-1` if `lhs < rhs`, `0` if `lhs == rhs`, and `1` if `lhs > rhs`. + // FIXME: Move the default implementation from `codegen_scalar_binop` into this method and + // remove the `Option` return once LLVM 20 is the minimum version. + fn three_way_compare( + &mut self, + _ty: Ty<'tcx>, + _lhs: Self::Value, + _rhs: Self::Value, + ) -> Option { + None + } + fn memcpy( &mut self, dst: Self::Value, diff --git a/tests/assembly/x86_64-cmp.rs b/tests/assembly/x86_64-cmp.rs index 8cccab7d40da..26c9013d96fc 100644 --- a/tests/assembly/x86_64-cmp.rs +++ b/tests/assembly/x86_64-cmp.rs @@ -1,5 +1,8 @@ -//@ revisions: DEBUG LLVM-PRE-20-OPTIM LLVM-20-OPTIM -//@ [DEBUG] compile-flags: -C opt-level=0 +//@ revisions: LLVM-PRE-20-DEBUG LLVM-20-DEBUG LLVM-PRE-20-OPTIM LLVM-20-OPTIM +//@ [LLVM-PRE-20-DEBUG] compile-flags: -C opt-level=0 +//@ [LLVM-PRE-20-DEBUG] max-llvm-major-version: 19 +//@ [LLVM-20-DEBUG] compile-flags: -C opt-level=0 +//@ [LLVM-20-DEBUG] min-llvm-version: 20 //@ [LLVM-PRE-20-OPTIM] compile-flags: -C opt-level=3 //@ [LLVM-PRE-20-OPTIM] max-llvm-major-version: 19 //@ [LLVM-20-OPTIM] compile-flags: -C opt-level=3 @@ -16,13 +19,19 @@ use std::intrinsics::three_way_compare; #[no_mangle] // CHECK-LABEL: signed_cmp: pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering { - // DEBUG: cmp - // DEBUG: setg - // DEBUG: and - // DEBUG: cmp - // DEBUG: setl - // DEBUG: and - // DEBUG: sub + // LLVM-PRE-20-DEBUG: cmp + // LLVM-PRE-20-DEBUG: setg + // LLVM-PRE-20-DEBUG: and + // LLVM-PRE-20-DEBUG: cmp + // LLVM-PRE-20-DEBUG: setl + // LLVM-PRE-20-DEBUG: and + // LLVM-PRE-20-DEBUG: sub + // + // LLVM-20-DEBUG: sub + // LLVM-20-DEBUG: setl + // LLVM-20-DEBUG: setg + // LLVM-20-DEBUG: sub + // LLVM-20-DEBUG: ret // LLVM-PRE-20-OPTIM: xor // LLVM-PRE-20-OPTIM: cmp @@ -42,13 +51,18 @@ pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering { #[no_mangle] // CHECK-LABEL: unsigned_cmp: pub fn unsigned_cmp(a: u16, b: u16) -> std::cmp::Ordering { - // DEBUG: cmp - // DEBUG: seta - // DEBUG: and - // DEBUG: cmp - // DEBUG: setb - // DEBUG: and - // DEBUG: sub + // LLVM-PRE-20-DEBUG: cmp + // LLVM-PRE-20-DEBUG: seta + // LLVM-PRE-20-DEBUG: and + // LLVM-PRE-20-DEBUG: cmp + // LLVM-PRE-20-DEBUG: setb + // LLVM-PRE-20-DEBUG: and + // LLVM-PRE-20-DEBUG: sub + // + // LLVM-20-DEBUG: sub + // LLVM-20-DEBUG: seta + // LLVM-20-DEBUG: sbb + // LLVM-20-DEBUG: ret // LLVM-PRE-20-OPTIM: xor // LLVM-PRE-20-OPTIM: cmp diff --git a/tests/codegen/comparison-operators-2-tuple.rs b/tests/codegen/comparison-operators-2-tuple.rs index 91a99f9b91f9..6a7e489c82dd 100644 --- a/tests/codegen/comparison-operators-2-tuple.rs +++ b/tests/codegen/comparison-operators-2-tuple.rs @@ -1,5 +1,4 @@ //@ compile-flags: -C opt-level=1 -Z merge-functions=disabled -//@ only-x86_64 //@ min-llvm-version: 20 #![crate_type = "lib"] diff --git a/tests/codegen/integer-cmp.rs b/tests/codegen/integer-cmp.rs index 9bbf243946d1..812fa8e4a424 100644 --- a/tests/codegen/integer-cmp.rs +++ b/tests/codegen/integer-cmp.rs @@ -4,7 +4,7 @@ //@ revisions: llvm-pre-20 llvm-20 //@ [llvm-20] min-llvm-version: 20 //@ [llvm-pre-20] max-llvm-major-version: 19 -//@ compile-flags: -C opt-level=3 +//@ compile-flags: -C opt-level=3 -Zmerge-functions=disabled #![crate_type = "lib"] @@ -13,7 +13,7 @@ use std::cmp::Ordering; // CHECK-LABEL: @cmp_signed #[no_mangle] pub fn cmp_signed(a: i64, b: i64) -> Ordering { - // llvm-20: @llvm.scmp.i8.i64 + // llvm-20: call{{.*}} i8 @llvm.scmp.i8.i64 // llvm-pre-20: icmp slt // llvm-pre-20: icmp ne // llvm-pre-20: zext i1 @@ -24,10 +24,39 @@ pub fn cmp_signed(a: i64, b: i64) -> Ordering { // CHECK-LABEL: @cmp_unsigned #[no_mangle] pub fn cmp_unsigned(a: u32, b: u32) -> Ordering { - // llvm-20: @llvm.ucmp.i8.i32 + // llvm-20: call{{.*}} i8 @llvm.ucmp.i8.i32 // llvm-pre-20: icmp ult // llvm-pre-20: icmp ne // llvm-pre-20: zext i1 // llvm-pre-20: select i1 a.cmp(&b) } + +// CHECK-LABEL: @cmp_char +#[no_mangle] +pub fn cmp_char(a: char, b: char) -> Ordering { + // llvm-20: call{{.*}} i8 @llvm.ucmp.i8.i32 + // llvm-pre-20: icmp ult + // llvm-pre-20: icmp ne + // llvm-pre-20: zext i1 + // llvm-pre-20: select i1 + a.cmp(&b) +} + +// CHECK-LABEL: @cmp_tuple +#[no_mangle] +pub fn cmp_tuple(a: (i16, u16), b: (i16, u16)) -> Ordering { + // llvm-20-DAG: call{{.*}} i8 @llvm.ucmp.i8.i16 + // llvm-20-DAG: call{{.*}} i8 @llvm.scmp.i8.i16 + // llvm-20: ret i8 + // llvm-pre-20: icmp slt + // llvm-pre-20: icmp ne + // llvm-pre-20: zext i1 + // llvm-pre-20: select i1 + // llvm-pre-20: icmp ult + // llvm-pre-20: icmp ne + // llvm-pre-20: zext i1 + // llvm-pre-20: select i1 + // llvm-pre-20: select i1 + a.cmp(&b) +} diff --git a/tests/codegen/intrinsics/three_way_compare.rs b/tests/codegen/intrinsics/three_way_compare.rs index 9a476abe8914..95fcb636f7ca 100644 --- a/tests/codegen/intrinsics/three_way_compare.rs +++ b/tests/codegen/intrinsics/three_way_compare.rs @@ -2,6 +2,7 @@ //@ [DEBUG] compile-flags: -C opt-level=0 //@ [OPTIM] compile-flags: -C opt-level=3 //@ compile-flags: -C no-prepopulate-passes +//@ min-llvm-version: 20 #![crate_type = "lib"] #![feature(core_intrinsics)] @@ -12,17 +13,8 @@ use std::intrinsics::three_way_compare; // CHECK-LABEL: @signed_cmp // CHECK-SAME: (i16{{.*}} %a, i16{{.*}} %b) pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering { - // DEBUG: %[[GT:.+]] = icmp sgt i16 %a, %b - // DEBUG: %[[ZGT:.+]] = zext i1 %[[GT]] to i8 - // DEBUG: %[[LT:.+]] = icmp slt i16 %a, %b - // DEBUG: %[[ZLT:.+]] = zext i1 %[[LT]] to i8 - // DEBUG: %[[R:.+]] = sub nsw i8 %[[ZGT]], %[[ZLT]] - - // OPTIM: %[[LT:.+]] = icmp slt i16 %a, %b - // OPTIM: %[[NE:.+]] = icmp ne i16 %a, %b - // OPTIM: %[[CGE:.+]] = select i1 %[[NE]], i8 1, i8 0 - // OPTIM: %[[CGEL:.+]] = select i1 %[[LT]], i8 -1, i8 %[[CGE]] - // OPTIM: ret i8 %[[CGEL]] + // CHECK: %[[CMP:.+]] = call i8 @llvm.scmp.i8.i16(i16 %a, i16 %b) + // CHECK-NEXT: ret i8 %[[CMP]] three_way_compare(a, b) } @@ -30,16 +22,7 @@ pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering { // CHECK-LABEL: @unsigned_cmp // CHECK-SAME: (i16{{.*}} %a, i16{{.*}} %b) pub fn unsigned_cmp(a: u16, b: u16) -> std::cmp::Ordering { - // DEBUG: %[[GT:.+]] = icmp ugt i16 %a, %b - // DEBUG: %[[ZGT:.+]] = zext i1 %[[GT]] to i8 - // DEBUG: %[[LT:.+]] = icmp ult i16 %a, %b - // DEBUG: %[[ZLT:.+]] = zext i1 %[[LT]] to i8 - // DEBUG: %[[R:.+]] = sub nsw i8 %[[ZGT]], %[[ZLT]] - - // OPTIM: %[[LT:.+]] = icmp ult i16 %a, %b - // OPTIM: %[[NE:.+]] = icmp ne i16 %a, %b - // OPTIM: %[[CGE:.+]] = select i1 %[[NE]], i8 1, i8 0 - // OPTIM: %[[CGEL:.+]] = select i1 %[[LT]], i8 -1, i8 %[[CGE]] - // OPTIM: ret i8 %[[CGEL]] + // CHECK: %[[CMP:.+]] = call i8 @llvm.ucmp.i8.i16(i16 %a, i16 %b) + // CHECK-NEXT: ret i8 %[[CMP]] three_way_compare(a, b) } From 4b7bcdbf9fcfa4972a97e7cc47b105d7b3711b19 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 6 Mar 2025 14:16:09 +0000 Subject: [PATCH 121/745] Use the github cli to publish dev releases This removes a whole bunch of complicated javascript with two lines of bash. Fixes rust-lang/rustc_codegen_cranelift#1562 --- .github/actions/github-release/README.md | 18 - .github/actions/github-release/action.yml | 13 - .github/actions/github-release/main.js | 162 ----- .../actions/github-release/package-lock.json | 571 ------------------ .github/actions/github-release/package.json | 11 - .github/workflows/main.yml | 15 +- 6 files changed, 6 insertions(+), 784 deletions(-) delete mode 100644 .github/actions/github-release/README.md delete mode 100644 .github/actions/github-release/action.yml delete mode 100644 .github/actions/github-release/main.js delete mode 100644 .github/actions/github-release/package-lock.json delete mode 100644 .github/actions/github-release/package.json diff --git a/.github/actions/github-release/README.md b/.github/actions/github-release/README.md deleted file mode 100644 index c70ba8f49538..000000000000 --- a/.github/actions/github-release/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# github-release - -An action used to publish GitHub releases for `wasmtime`. - -As of the time of this writing there's a few actions floating around which -perform github releases but they all tend to have their set of drawbacks. -Additionally nothing handles deleting releases which we need for our rolling -`dev` release. - -To handle all this this action rolls-its-own implementation using the -actions/toolkit repository and packages published there. These run in a Docker -container and take various inputs to orchestrate the release from the build. - -More comments can be found in `main.js`. - -Testing this is really hard. If you want to try though run `npm install` and -then `node main.js`. You'll have to configure a bunch of env vars though to get -anything reasonably working. diff --git a/.github/actions/github-release/action.yml b/.github/actions/github-release/action.yml deleted file mode 100644 index 36e5209f50c3..000000000000 --- a/.github/actions/github-release/action.yml +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -name: 'rustc_codegen_cranelift github releases' -description: 'rustc_codegen_cranelift github releases' -inputs: - token: - description: '' - required: true - files: - description: '' - required: true -runs: - using: 'node16' - main: 'main.js' diff --git a/.github/actions/github-release/main.js b/.github/actions/github-release/main.js deleted file mode 100644 index 1eb2b7f23b26..000000000000 --- a/.github/actions/github-release/main.js +++ /dev/null @@ -1,162 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -const core = require('@actions/core'); -const path = require("path"); -const fs = require("fs"); -const github = require('@actions/github'); -const glob = require('glob'); - -function sleep(milliseconds) { - return new Promise(resolve => setTimeout(resolve, milliseconds)) -} - -async function runOnce() { - // Load all our inputs and env vars. Note that `getInput` reads from `INPUT_*` - const files = core.getInput('files'); - const token = core.getInput('token'); - const slug = process.env.GITHUB_REPOSITORY; - const owner = slug.split('/')[0]; - const repo = slug.split('/')[1]; - const sha = process.env.GITHUB_SHA; - let name = 'dev'; - if (process.env.GITHUB_REF.startsWith('refs/tags/v')) { - name = process.env.GITHUB_REF.substring(10); - } - - core.info(`files: ${files}`); - core.info(`name: ${name}`); - core.info(`token: ${token}`); - - const octokit = github.getOctokit(token); - - // For the `dev` release we may need to update the tag to point to the new - // commit on this branch. All other names should already have tags associated - // with them. - if (name == 'dev') { - let tag = null; - try { - tag = await octokit.request("GET /repos/:owner/:repo/git/refs/tags/:name", { owner, repo, name }); - core.info(`found existing tag`); - console.log("tag: ", JSON.stringify(tag.data, null, 2)); - } catch (e) { - // ignore if this tag doesn't exist - core.info(`no existing tag found`); - } - - if (tag === null || tag.data.object.sha !== sha) { - core.info(`updating existing tag or creating new one`); - - try { - core.info(`updating dev tag`); - await octokit.rest.git.updateRef({ - owner, - repo, - ref: 'tags/dev', - sha, - force: true, - }); - } catch (e) { - console.log("ERROR: ", JSON.stringify(e.response, null, 2)); - core.info(`creating dev tag`); - try { - await octokit.rest.git.createRef({ - owner, - repo, - ref: 'refs/tags/dev', - sha, - }); - } catch (e) { - // we might race with others, so assume someone else has created the - // tag by this point. - console.log("failed to create tag: ", JSON.stringify(e.response, null, 2)); - } - } - - console.log("double-checking tag is correct"); - tag = await octokit.request("GET /repos/:owner/:repo/git/refs/tags/:name", { owner, repo, name }); - if (tag.data.object.sha !== sha) { - console.log("tag: ", JSON.stringify(tag.data, null, 2)); - throw new Error("tag didn't work"); - } - } else { - core.info(`existing tag works`); - } - } - - // Delete a previous release - try { - core.info(`fetching release`); - let release = await octokit.rest.repos.getReleaseByTag({ owner, repo, tag: name }); - console.log("found release: ", JSON.stringify(release.data, null, 2)); - await octokit.rest.repos.deleteRelease({ - owner, - repo, - release_id: release.data.id, - }); - console.log("deleted release"); - } catch (e) { - console.log("ERROR: ", JSON.stringify(e, null, 2)); - } - - console.log("creating a release"); - let release = await octokit.rest.repos.createRelease({ - owner, - repo, - tag_name: name, - prerelease: name === 'dev', - }); - - // Delete all assets from a previous run - for (const asset of release.data.assets) { - console.log(`deleting prior asset ${asset.id}`); - await octokit.rest.repos.deleteReleaseAsset({ - owner, - repo, - asset_id: asset.id, - }); - } - - // Upload all the relevant assets for this release as just general blobs. - for (const file of glob.sync(files)) { - const size = fs.statSync(file).size; - const name = path.basename(file); - core.info(`upload ${file}`); - await octokit.rest.repos.uploadReleaseAsset({ - data: fs.createReadStream(file), - headers: { 'content-length': size, 'content-type': 'application/octet-stream' }, - name, - url: release.data.upload_url, - }); - } -} - -async function run() { - const retries = 10; - for (let i = 0; i < retries; i++) { - try { - await runOnce(); - break; - } catch (e) { - if (i === retries - 1) - throw e; - logError(e); - console.log("RETRYING after 10s"); - await sleep(10000) - } - } -} - -function logError(e) { - console.log("ERROR: ", e.message); - try { - console.log(JSON.stringify(e, null, 2)); - } catch (e) { - // ignore json errors for now - } - console.log(e.stack); -} - -run().catch(err => { - logError(err); - core.setFailed(err.message); -}); diff --git a/.github/actions/github-release/package-lock.json b/.github/actions/github-release/package-lock.json deleted file mode 100644 index dd3b2a048f09..000000000000 --- a/.github/actions/github-release/package-lock.json +++ /dev/null @@ -1,571 +0,0 @@ -{ - "name": "rustc_codegen_cranelift-github-release", - "version": "0.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "rustc_codegen_cranelift-github-release", - "version": "0.0.0", - "dependencies": { - "@actions/core": "^1.9.1", - "@actions/github": "^5.1.0", - "glob": "^7.1.5" - } - }, - "node_modules/@actions/core": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", - "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", - "dependencies": { - "@actions/http-client": "^2.0.1", - "uuid": "^8.3.2" - } - }, - "node_modules/@actions/github": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.0.tgz", - "integrity": "sha512-tuI80F7JQIhg77ZTTgUAPpVD7ZnP9oHSPN8xw7LOwtA4vEMbAjWJNbmLBfV7xua7r016GyjzWLuec5cs8f/a8A==", - "dependencies": { - "@actions/http-client": "^2.0.1", - "@octokit/core": "^3.6.0", - "@octokit/plugin-paginate-rest": "^2.17.0", - "@octokit/plugin-rest-endpoint-methods": "^5.13.0" - } - }, - "node_modules/@actions/http-client": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz", - "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==", - "dependencies": { - "tunnel": "^0.0.6" - } - }, - "node_modules/@octokit/auth-token": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", - "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", - "dependencies": { - "@octokit/types": "^6.0.3" - } - }, - "node_modules/@octokit/core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", - "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", - "dependencies": { - "@octokit/auth-token": "^2.4.4", - "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.6.3", - "@octokit/request-error": "^2.0.5", - "@octokit/types": "^6.0.3", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/@octokit/endpoint": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", - "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", - "dependencies": { - "@octokit/types": "^6.0.3", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/@octokit/graphql": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", - "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", - "dependencies": { - "@octokit/request": "^5.6.0", - "@octokit/types": "^6.0.3", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "node_modules/@octokit/plugin-paginate-rest": { - "version": "2.21.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", - "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", - "dependencies": { - "@octokit/types": "^6.40.0" - }, - "peerDependencies": { - "@octokit/core": ">=2" - } - }, - "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "5.16.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", - "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", - "dependencies": { - "@octokit/types": "^6.39.0", - "deprecation": "^2.3.1" - }, - "peerDependencies": { - "@octokit/core": ">=3" - } - }, - "node_modules/@octokit/request": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", - "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", - "dependencies": { - "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.16.1", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", - "dependencies": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "node_modules/@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dependencies": { - "@octokit/openapi-types": "^12.11.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" - } - }, - "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - } - }, - "dependencies": { - "@actions/core": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", - "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", - "requires": { - "@actions/http-client": "^2.0.1", - "uuid": "^8.3.2" - } - }, - "@actions/github": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.0.tgz", - "integrity": "sha512-tuI80F7JQIhg77ZTTgUAPpVD7ZnP9oHSPN8xw7LOwtA4vEMbAjWJNbmLBfV7xua7r016GyjzWLuec5cs8f/a8A==", - "requires": { - "@actions/http-client": "^2.0.1", - "@octokit/core": "^3.6.0", - "@octokit/plugin-paginate-rest": "^2.17.0", - "@octokit/plugin-rest-endpoint-methods": "^5.13.0" - } - }, - "@actions/http-client": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz", - "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==", - "requires": { - "tunnel": "^0.0.6" - } - }, - "@octokit/auth-token": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", - "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", - "requires": { - "@octokit/types": "^6.0.3" - } - }, - "@octokit/core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", - "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", - "requires": { - "@octokit/auth-token": "^2.4.4", - "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.6.3", - "@octokit/request-error": "^2.0.5", - "@octokit/types": "^6.0.3", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/endpoint": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", - "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", - "requires": { - "@octokit/types": "^6.0.3", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/graphql": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", - "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", - "requires": { - "@octokit/request": "^5.6.0", - "@octokit/types": "^6.0.3", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "@octokit/plugin-paginate-rest": { - "version": "2.21.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", - "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", - "requires": { - "@octokit/types": "^6.40.0" - } - }, - "@octokit/plugin-rest-endpoint-methods": { - "version": "5.16.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", - "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", - "requires": { - "@octokit/types": "^6.39.0", - "deprecation": "^2.3.1" - } - }, - "@octokit/request": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", - "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", - "requires": { - "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.16.1", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", - "requires": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "requires": { - "@octokit/openapi-types": "^12.11.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "requires": { - "wrappy": "1" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==" - }, - "universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - } - } -} diff --git a/.github/actions/github-release/package.json b/.github/actions/github-release/package.json deleted file mode 100644 index d9c23f8873ec..000000000000 --- a/.github/actions/github-release/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "rustc_codegen_cranelift-github-release", - "version": "0.0.0", - "license": "Apache-2.0 WITH LLVM-exception", - "main": "main.js", - "dependencies": { - "@actions/core": "^1.9.1", - "@actions/github": "^5.1.0", - "glob": "^7.1.5" - } -} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7d941887100d..6fd288d195c0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -261,12 +261,9 @@ jobs: rmdir artifacts/ # verify all artifacts are represented in release/ ls -R release/ - - run: npm install --production - working-directory: .github/actions/github-release - - - name: Publish Release - uses: ./.github/actions/github-release - with: - files: "release/*" - token: ${{ github.token }} - continue-on-error: true + - name: Publish release + env: + GH_TOKEN: ${{ github.token }} + run: | + gh release delete --cleanup-tag -y dev || true + gh release create --target $GITHUB_SHA --prerelease dev release/* From cc6127bce89c249dec752ea93fb2d31bdfa8ebc3 Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 4 Mar 2025 14:33:57 +0000 Subject: [PATCH 122/745] docs: update rationale for excessive-bools Adds the reasoning to the docs for this rule on why enums are generally better for representing state machines than structs with many bool fields. --- clippy_lints/src/excessive_bools.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/excessive_bools.rs b/clippy_lints/src/excessive_bools.rs index 54a1ac21c85c..3b71d2127fac 100644 --- a/clippy_lints/src/excessive_bools.rs +++ b/clippy_lints/src/excessive_bools.rs @@ -15,12 +15,17 @@ declare_clippy_lint! { /// use of bools in structs. /// /// ### Why is this bad? - /// Excessive bools in a struct - /// is often a sign that it's used as a state machine, - /// which is much better implemented as an enum. - /// If it's not the case, excessive bools usually benefit - /// from refactoring into two-variant enums for better - /// readability and API. + /// Excessive bools in a struct is often a sign that + /// the type is being used to represent a state + /// machine, which is much better implemented as an + /// enum. + /// + /// The reason an enum is better for state machines + /// over structs is that enums more easily forbid + /// invalid states. + /// + /// Structs with too many booleans may benefit from refactoring + /// into multi variant enums for better readability and API. /// /// ### Example /// ```no_run From d52ac1b6d8cd56f72c9466e18c745c21b5424085 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 26 Dec 2024 18:15:50 -0300 Subject: [PATCH 123/745] Fix clippy --- clippy_lints/src/escape.rs | 2 ++ clippy_lints/src/loops/mut_range_bound.rs | 2 ++ clippy_lints/src/loops/never_loop.rs | 1 + clippy_lints/src/matches/manual_utils.rs | 2 +- clippy_lints/src/methods/iter_overeager_cloned.rs | 2 ++ clippy_lints/src/needless_pass_by_ref_mut.rs | 2 ++ clippy_lints/src/needless_pass_by_value.rs | 2 ++ clippy_lints/src/operators/assign_op_pattern.rs | 2 ++ clippy_lints/src/option_if_let_else.rs | 2 +- clippy_lints/src/unwrap.rs | 2 ++ clippy_lints/src/utils/author.rs | 6 ++++++ clippy_utils/src/eager_or_lazy.rs | 1 + clippy_utils/src/hir_utils.rs | 5 +++++ clippy_utils/src/lib.rs | 9 ++++++--- clippy_utils/src/sugg.rs | 4 ++++ clippy_utils/src/usage.rs | 2 ++ clippy_utils/src/visitors.rs | 3 +++ 17 files changed, 44 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 8d1e893cb1af..33ba401d60c2 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -150,6 +150,8 @@ impl<'tcx> Delegate<'tcx> for EscapeDelegate<'_, 'tcx> { } } + fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {} + fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) { if cmt.place.projections.is_empty() { if let PlaceBase::Local(lid) = cmt.place.base { diff --git a/clippy_lints/src/loops/mut_range_bound.rs b/clippy_lints/src/loops/mut_range_bound.rs index 39e5e140b7a4..fb5d49a10047 100644 --- a/clippy_lints/src/loops/mut_range_bound.rs +++ b/clippy_lints/src/loops/mut_range_bound.rs @@ -79,6 +79,8 @@ struct MutatePairDelegate<'a, 'tcx> { impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> { fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {} + fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {} + fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, diag_expr_id: HirId, bk: ty::BorrowKind) { if bk == ty::BorrowKind::Mutable { if let PlaceBase::Local(id) = cmt.place.base { diff --git a/clippy_lints/src/loops/never_loop.rs b/clippy_lints/src/loops/never_loop.rs index b679fdfadc3a..dd7a6f77acff 100644 --- a/clippy_lints/src/loops/never_loop.rs +++ b/clippy_lints/src/loops/never_loop.rs @@ -160,6 +160,7 @@ fn never_loop_expr<'tcx>( | ExprKind::UnsafeBinderCast(_, e, _) => never_loop_expr(cx, e, local_labels, main_loop_id), ExprKind::Let(let_expr) => never_loop_expr(cx, let_expr.init, local_labels, main_loop_id), ExprKind::Array(es) | ExprKind::Tup(es) => never_loop_expr_all(cx, es.iter(), local_labels, main_loop_id), + ExprKind::Use(expr, _) => never_loop_expr(cx, expr, local_labels, main_loop_id), ExprKind::MethodCall(_, receiver, es, _) => { never_loop_expr_all(cx, once(receiver).chain(es.iter()), local_labels, main_loop_id) }, diff --git a/clippy_lints/src/matches/manual_utils.rs b/clippy_lints/src/matches/manual_utils.rs index 09440c396ee1..d0905733ab50 100644 --- a/clippy_lints/src/matches/manual_utils.rs +++ b/clippy_lints/src/matches/manual_utils.rs @@ -99,7 +99,7 @@ where }); if let ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(l), .. })) = e.kind { match captures.get(l) { - Some(CaptureKind::Value | CaptureKind::Ref(Mutability::Mut)) => return None, + Some(CaptureKind::Value | CaptureKind::Use | CaptureKind::Ref(Mutability::Mut)) => return None, Some(CaptureKind::Ref(Mutability::Not)) if binding_ref_mutability == Mutability::Mut => { return None; }, diff --git a/clippy_lints/src/methods/iter_overeager_cloned.rs b/clippy_lints/src/methods/iter_overeager_cloned.rs index a80977459f21..f51bdc78f8a5 100644 --- a/clippy_lints/src/methods/iter_overeager_cloned.rs +++ b/clippy_lints/src/methods/iter_overeager_cloned.rs @@ -147,6 +147,8 @@ impl<'tcx> Delegate<'tcx> for MoveDelegate { } } + fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {} + fn borrow(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId, _: BorrowKind) {} fn mutate(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {} diff --git a/clippy_lints/src/needless_pass_by_ref_mut.rs b/clippy_lints/src/needless_pass_by_ref_mut.rs index d5c5679c990d..dc10de24bc8c 100644 --- a/clippy_lints/src/needless_pass_by_ref_mut.rs +++ b/clippy_lints/src/needless_pass_by_ref_mut.rs @@ -396,6 +396,8 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> { } } + fn use_cloned(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId) {} + #[allow(clippy::if_same_then_else)] fn borrow(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, id: HirId, borrow: ty::BorrowKind) { self.prev_bind = None; diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 380cc380ad0f..dc85176ebb9e 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -326,6 +326,8 @@ impl<'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt { self.move_common(cmt); } + fn use_cloned(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId) {} + fn borrow(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {} fn mutate(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId) {} diff --git a/clippy_lints/src/operators/assign_op_pattern.rs b/clippy_lints/src/operators/assign_op_pattern.rs index 5737a91031db..03b907ebdf4d 100644 --- a/clippy_lints/src/operators/assign_op_pattern.rs +++ b/clippy_lints/src/operators/assign_op_pattern.rs @@ -112,6 +112,7 @@ fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> HirIdSet { } fn consume(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {} + fn use_cloned(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {} fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {} fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: HirId) {} fn copy(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {} @@ -137,6 +138,7 @@ fn mut_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> HirIdSet { } fn consume(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {} + fn use_cloned(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {} fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {} fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: HirId) {} fn copy(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {} diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index de9f055863cb..75b18bc651e2 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -177,7 +177,7 @@ fn try_get_option_occurrence<'tcx>( .then_some(()) .and_then(|()| none_captures.get(local_id)) }) { - Some(CaptureKind::Value | CaptureKind::Ref(Mutability::Mut)) => return None, + Some(CaptureKind::Value | CaptureKind::Use | CaptureKind::Ref(Mutability::Mut)) => return None, Some(CaptureKind::Ref(Mutability::Not)) if as_mut => return None, Some(CaptureKind::Ref(Mutability::Not)) | None => (), } diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 76b9bbbd32fd..6f6683eb9712 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -230,6 +230,8 @@ impl<'tcx> Delegate<'tcx> for MutationVisitor<'tcx> { fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {} + fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {} + fn fake_read(&mut self, _: &PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {} } diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 5fc166438e84..9d8c161873c0 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -426,6 +426,11 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { kind!("Tup({elements})"); self.slice(elements, |e| self.expr(e)); }, + ExprKind::Use(expr, _) => { + bind!(self, expr); + kind!("Use({expr})"); + self.expr(expr); + }, ExprKind::Binary(op, left, right) => { bind!(self, op, left, right); kind!("Binary({op}, {left}, {right})"); @@ -488,6 +493,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { }) => { let capture_clause = match capture_clause { CaptureBy::Value { .. } => "Value { .. }", + CaptureBy::Use { .. } => "Use { .. }", CaptureBy::Ref => "Ref", }; diff --git a/clippy_utils/src/eager_or_lazy.rs b/clippy_utils/src/eager_or_lazy.rs index aaea8d71efbe..4543a20cc2cd 100644 --- a/clippy_utils/src/eager_or_lazy.rs +++ b/clippy_utils/src/eager_or_lazy.rs @@ -291,6 +291,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS ExprKind::ConstBlock(_) | ExprKind::Array(_) | ExprKind::Tup(_) + | ExprKind::Use(..) | ExprKind::Lit(_) | ExprKind::Cast(..) | ExprKind::Type(..) diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index 4bd86a253351..dd0ac224e456 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -393,6 +393,7 @@ impl HirEqInterExpr<'_, '_, '_> { && over(lf, rf, |l, r| self.eq_expr_field(l, r)) }, (&ExprKind::Tup(l_tup), &ExprKind::Tup(r_tup)) => self.eq_exprs(l_tup, r_tup), + (&ExprKind::Use(l_expr, _), &ExprKind::Use(r_expr, _)) => self.eq_expr(l_expr, r_expr), (&ExprKind::Type(le, lt), &ExprKind::Type(re, rt)) => self.eq_expr(le, re) && self.eq_ty(lt, rt), (&ExprKind::Unary(l_op, le), &ExprKind::Unary(r_op, re)) => l_op == r_op && self.eq_expr(le, re), (&ExprKind::Yield(le, _), &ExprKind::Yield(re, _)) => return self.eq_expr(le, re), @@ -425,6 +426,7 @@ impl HirEqInterExpr<'_, '_, '_> { | &ExprKind::Ret(..) | &ExprKind::Struct(..) | &ExprKind::Tup(..) + | &ExprKind::Use(..) | &ExprKind::Type(..) | &ExprKind::Unary(..) | &ExprKind::Yield(..) @@ -1053,6 +1055,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { ExprKind::Tup(tup) => { self.hash_exprs(tup); }, + ExprKind::Use(expr, _) => { + self.hash_expr(expr); + }, ExprKind::Unary(lop, le) => { std::mem::discriminant(&lop).hash(&mut self.s); self.hash_expr(le); diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index d850cc410008..723ae9b01a80 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -1129,6 +1129,7 @@ pub fn can_move_expr_to_closure_no_visit<'tcx>( #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum CaptureKind { Value, + Use, Ref(Mutability), } impl CaptureKind { @@ -1141,6 +1142,7 @@ impl std::ops::BitOr for CaptureKind { fn bitor(self, rhs: Self) -> Self::Output { match (self, rhs) { (CaptureKind::Value, _) | (_, CaptureKind::Value) => CaptureKind::Value, + (CaptureKind::Use, _) | (_, CaptureKind::Use) => CaptureKind::Use, (CaptureKind::Ref(Mutability::Mut), CaptureKind::Ref(_)) | (CaptureKind::Ref(_), CaptureKind::Ref(Mutability::Mut)) => CaptureKind::Ref(Mutability::Mut), (CaptureKind::Ref(Mutability::Not), CaptureKind::Ref(Mutability::Not)) => CaptureKind::Ref(Mutability::Not), @@ -1220,7 +1222,7 @@ pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind { }, ExprKind::Let(let_expr) => { let mutability = match pat_capture_kind(cx, let_expr.pat) { - CaptureKind::Value => Mutability::Not, + CaptureKind::Value | CaptureKind::Use => Mutability::Not, CaptureKind::Ref(m) => m, }; return CaptureKind::Ref(mutability); @@ -1229,7 +1231,7 @@ pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind { let mut mutability = Mutability::Not; for capture in arms.iter().map(|arm| pat_capture_kind(cx, arm.pat)) { match capture { - CaptureKind::Value => break, + CaptureKind::Value | CaptureKind::Use => break, CaptureKind::Ref(Mutability::Mut) => mutability = Mutability::Mut, CaptureKind::Ref(Mutability::Not) => (), } @@ -1239,7 +1241,7 @@ pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind { _ => break, }, Node::LetStmt(l) => match pat_capture_kind(cx, l.pat) { - CaptureKind::Value => break, + CaptureKind::Value | CaptureKind::Use => break, capture @ CaptureKind::Ref(_) => return capture, }, _ => break, @@ -1294,6 +1296,7 @@ pub fn can_move_expr_to_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<' if !self.locals.contains(&local_id) { let capture = match capture.info.capture_kind { UpvarCapture::ByValue => CaptureKind::Value, + UpvarCapture::ByUse => CaptureKind::Use, UpvarCapture::ByRef(kind) => match kind { BorrowKind::Immutable => CaptureKind::Ref(Mutability::Not), BorrowKind::UniqueImmutable | BorrowKind::Mutable => { diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index 4a9ab17d4a60..24b4f0d9e6d8 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -147,6 +147,7 @@ impl<'a> Sugg<'a> { | ExprKind::Become(..) | ExprKind::Struct(..) | ExprKind::Tup(..) + | ExprKind::Use(..) | ExprKind::Err(_) | ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(get_snippet(expr.span)), ExprKind::DropTemps(inner) => Self::hir_from_snippet(inner, get_snippet), @@ -217,6 +218,7 @@ impl<'a> Sugg<'a> { | ast::ExprKind::Try(..) | ast::ExprKind::TryBlock(..) | ast::ExprKind::Tup(..) + | ast::ExprKind::Use(..) | ast::ExprKind::Array(..) | ast::ExprKind::While(..) | ast::ExprKind::Await(..) @@ -835,6 +837,8 @@ impl<'tcx> DerefDelegate<'_, 'tcx> { impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> { fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {} + fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {} + fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) { if let PlaceBase::Local(id) = cmt.place.base { let map = self.cx.tcx.hir(); diff --git a/clippy_utils/src/usage.rs b/clippy_utils/src/usage.rs index 3bf518f7fe70..a079fd940c00 100644 --- a/clippy_utils/src/usage.rs +++ b/clippy_utils/src/usage.rs @@ -66,6 +66,8 @@ impl MutVarsDelegate { impl<'tcx> Delegate<'tcx> for MutVarsDelegate { fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {} + fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {} + fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, bk: ty::BorrowKind) { if bk == ty::BorrowKind::Mutable { self.update(cmt); diff --git a/clippy_utils/src/visitors.rs b/clippy_utils/src/visitors.rs index 2ac0efd7e392..63dd00f2de0f 100644 --- a/clippy_utils/src/visitors.rs +++ b/clippy_utils/src/visitors.rs @@ -648,6 +648,9 @@ pub fn for_each_unconsumed_temporary<'tcx, B>( helper(typeck, true, arg, f)?; } }, + ExprKind::Use(expr, _) => { + helper(typeck, true, expr, f)?; + }, ExprKind::Index(borrowed, consumed, _) | ExprKind::Assign(borrowed, consumed, _) | ExprKind::AssignOp(_, borrowed, consumed) => { From fd3fb2cf46a155682eee50ef8d6f84cac4ef154d Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Wed, 5 Mar 2025 18:14:07 -0800 Subject: [PATCH 124/745] Remove #[cfg(not(test))] gates in core These gates are unnecessary now that unit tests for `core` are in a separate package, `coretests`, instead of in the same files as the source code. They previously prevented the two `core` versions from conflicting with each other. --- ...0027-stdlib-128bit-atomic-operations.patch | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/patches/0027-stdlib-128bit-atomic-operations.patch b/patches/0027-stdlib-128bit-atomic-operations.patch index 3c81b04c0ead..d7e3b11127c4 100644 --- a/patches/0027-stdlib-128bit-atomic-operations.patch +++ b/patches/0027-stdlib-128bit-atomic-operations.patch @@ -1,4 +1,4 @@ -From ad7ffe71baba46865f2e65266ab025920dfdc20b Mon Sep 17 00:00:00 2001 +From 5d7c709608b01301d4628d2159265936d4440b67 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 18 Feb 2021 18:45:28 +0100 Subject: [PATCH] Disable 128bit atomic operations @@ -7,11 +7,10 @@ Cranelift doesn't support them yet --- library/core/src/panic/unwind_safe.rs | 6 ----- library/core/src/sync/atomic.rs | 38 --------------------------- - library/core/tests/atomic.rs | 4 --- - 4 files changed, 4 insertions(+), 50 deletions(-) + 2 files changed, 44 deletions(-) diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs -index 092b7cf..158cf71 100644 +index a60f0799c0e..af056fbf41f 100644 --- a/library/core/src/panic/unwind_safe.rs +++ b/library/core/src/panic/unwind_safe.rs @@ -216,9 +216,6 @@ impl RefUnwindSafe for crate::sync::atomic::AtomicI32 {} @@ -21,7 +20,7 @@ index 092b7cf..158cf71 100644 -#[cfg(target_has_atomic_load_store = "128")] -#[unstable(feature = "integer_atomics", issue = "99069")] -impl RefUnwindSafe for crate::sync::atomic::AtomicI128 {} - + #[cfg(target_has_atomic_load_store = "ptr")] #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] @@ -235,9 +232,6 @@ impl RefUnwindSafe for crate::sync::atomic::AtomicU32 {} @@ -31,14 +30,14 @@ index 092b7cf..158cf71 100644 -#[cfg(target_has_atomic_load_store = "128")] -#[unstable(feature = "integer_atomics", issue = "99069")] -impl RefUnwindSafe for crate::sync::atomic::AtomicU128 {} - + #[cfg(target_has_atomic_load_store = "8")] #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs -index d9de37e..8293fce 100644 +index bf2b6d59f88..d5ccce03bbf 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs -@@ -2996,44 +2996,6 @@ atomic_int! { +@@ -3585,44 +3585,6 @@ pub const fn as_ptr(&self) -> *mut $int_type { 8, u64 AtomicU64 } @@ -54,7 +53,7 @@ index d9de37e..8293fce 100644 - unstable(feature = "integer_atomics", issue = "99069"), - rustc_const_unstable(feature = "integer_atomics", issue = "99069"), - rustc_const_unstable(feature = "integer_atomics", issue = "99069"), -- cfg_attr(not(test), rustc_diagnostic_item = "AtomicI128"), +- rustc_diagnostic_item = "AtomicI128", - "i128", - "#![feature(integer_atomics)]\n\n", - atomic_min, atomic_max, @@ -73,7 +72,7 @@ index d9de37e..8293fce 100644 - unstable(feature = "integer_atomics", issue = "99069"), - rustc_const_unstable(feature = "integer_atomics", issue = "99069"), - rustc_const_unstable(feature = "integer_atomics", issue = "99069"), -- cfg_attr(not(test), rustc_diagnostic_item = "AtomicU128"), +- rustc_diagnostic_item = "AtomicU128", - "u128", - "#![feature(integer_atomics)]\n\n", - atomic_umin, atomic_umax, @@ -83,7 +82,6 @@ index d9de37e..8293fce 100644 #[cfg(target_has_atomic_load_store = "ptr")] macro_rules! atomic_int_ptr_sized { - ( $($target_pointer_width:literal $align:literal)* ) => { $( --- -2.26.2.7.g19db9cfb68 +-- +2.48.1 From 726c8d4c57f31a4ff6e37d73224fc37bdd2830b9 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Tue, 4 Mar 2025 20:21:37 -0500 Subject: [PATCH 125/745] Fix tier 2 sysroots job --- src/tools/miri/.github/workflows/sysroots.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/miri/.github/workflows/sysroots.yml b/src/tools/miri/.github/workflows/sysroots.yml index 6a4f44ddd507..11bcaec9255b 100644 --- a/src/tools/miri/.github/workflows/sysroots.yml +++ b/src/tools/miri/.github/workflows/sysroots.yml @@ -16,6 +16,7 @@ jobs: - uses: actions/checkout@v4 - name: Build the sysroots run: | + rustup toolchain install nightly cargo install -f rustup-toolchain-install-master ./miri toolchain -c rust-docs # Docs are the only place targets are separated by tier ./miri install From b709bdeb94c9fcc9a68123a83a46d16907b2a5c0 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Thu, 6 Mar 2025 19:34:57 -0500 Subject: [PATCH 126/745] Update documentation about nextest --- src/tools/miri/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index d64de4b1976d..201aa1f53869 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -237,8 +237,7 @@ inherent interpreter slowdown and a loss of parallelism. You can get your test suite's parallelism back by running `cargo miri nextest run -jN` (note that you will need [`cargo-nextest`](https://nexte.st) installed). This works because `cargo-nextest` collects a list of all tests then launches a -separate `cargo miri run` for each test. You will need to specify a `-j` or `--test-threads`; -by default `cargo miri nextest run` runs one test at a time. For more details, see the +separate `cargo miri run` for each test. For more information about nextest, see the [`cargo-nextest` Miri documentation](https://nexte.st/book/miri.html). Note: This one-test-per-process model means that `cargo miri test` is able to detect data From c86f0a134cf975f354e0fe14f868ccb58276bdbf Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Tue, 4 Mar 2025 20:28:38 -0800 Subject: [PATCH 127/745] Use size_of from the prelude instead of imported Use `std::mem::{size_of, size_of_val, align_of, align_of_val}` from the prelude instead of importing or qualifying them. These functions were added to all preludes in Rust 1.80. --- beginners-guide.md | 4 ++-- crates/core_simd/src/masks/full_masks.rs | 2 +- crates/core_simd/src/simd/num/float.rs | 4 ++-- crates/core_simd/src/simd/ptr/const_ptr.rs | 2 +- crates/core_simd/src/simd/ptr/mut_ptr.rs | 2 +- crates/core_simd/src/vector.rs | 2 +- crates/core_simd/tests/layout.rs | 4 ++-- crates/core_simd/tests/round.rs | 2 +- crates/test_helpers/src/subnormals.rs | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/beginners-guide.md b/beginners-guide.md index 17ade06ae80f..dc08d847ced5 100644 --- a/beginners-guide.md +++ b/beginners-guide.md @@ -80,12 +80,12 @@ Most of the portable SIMD API is designed to allow the user to gloss over the de Fortunately, most SIMD types have a fairly predictable size. `i32x4` is bit-equivalent to `[i32; 4]` and so can be bitcast to it, e.g. using [`mem::transmute`], though the API usually offers a safe cast you can use instead. -However, this is not the same as alignment. Computer architectures generally prefer aligned accesses, especially when moving data between memory and vector registers, and while some support specialized operations that can bend the rules to help with this, unaligned access is still typically slow, or even undefined behavior. In addition, different architectures can require different alignments when interacting with their native SIMD types. For this reason, any `#[repr(simd)]` type has a non-portable alignment. If it is necessary to directly interact with the alignment of these types, it should be via [`mem::align_of`]. +However, this is not the same as alignment. Computer architectures generally prefer aligned accesses, especially when moving data between memory and vector registers, and while some support specialized operations that can bend the rules to help with this, unaligned access is still typically slow, or even undefined behavior. In addition, different architectures can require different alignments when interacting with their native SIMD types. For this reason, any `#[repr(simd)]` type has a non-portable alignment. If it is necessary to directly interact with the alignment of these types, it should be via [`align_of`]. When working with slices, data correctly aligned for SIMD can be acquired using the [`as_simd`] and [`as_simd_mut`] methods of the slice primitive. [`mem::transmute`]: https://doc.rust-lang.org/core/mem/fn.transmute.html -[`mem::align_of`]: https://doc.rust-lang.org/core/mem/fn.align_of.html +[`align_of`]: https://doc.rust-lang.org/core/mem/fn.align_of.html [`as_simd`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.as_simd [`as_simd_mut`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.as_simd_mut diff --git a/crates/core_simd/src/masks/full_masks.rs b/crates/core_simd/src/masks/full_masks.rs index 2d01946b5747..ae55cf1f8fa8 100644 --- a/crates/core_simd/src/masks/full_masks.rs +++ b/crates/core_simd/src/masks/full_masks.rs @@ -81,7 +81,7 @@ macro_rules! impl_reverse_bits { #[inline(always)] fn reverse_bits(self, n: usize) -> Self { let rev = <$int>::reverse_bits(self); - let bitsize = core::mem::size_of::<$int>() * 8; + let bitsize = size_of::<$int>() * 8; if n < bitsize { // Shift things back to the right rev >> (bitsize - n) diff --git a/crates/core_simd/src/simd/num/float.rs b/crates/core_simd/src/simd/num/float.rs index 46b94ad9f1ca..6d36b9ac68cc 100644 --- a/crates/core_simd/src/simd/num/float.rs +++ b/crates/core_simd/src/simd/num/float.rs @@ -302,14 +302,14 @@ macro_rules! impl_trait { #[inline] fn to_bits(self) -> Simd<$bits_ty, N> { - assert_eq!(core::mem::size_of::(), core::mem::size_of::()); + assert_eq!(size_of::(), size_of::()); // Safety: transmuting between vector types is safe unsafe { core::mem::transmute_copy(&self) } } #[inline] fn from_bits(bits: Simd<$bits_ty, N>) -> Self { - assert_eq!(core::mem::size_of::(), core::mem::size_of::()); + assert_eq!(size_of::(), size_of::()); // Safety: transmuting between vector types is safe unsafe { core::mem::transmute_copy(&bits) } } diff --git a/crates/core_simd/src/simd/ptr/const_ptr.rs b/crates/core_simd/src/simd/ptr/const_ptr.rs index 34d46216710c..36452e7ae920 100644 --- a/crates/core_simd/src/simd/ptr/const_ptr.rs +++ b/crates/core_simd/src/simd/ptr/const_ptr.rs @@ -109,7 +109,7 @@ where fn cast(self) -> Self::CastPtr { // SimdElement currently requires zero-sized metadata, so this should never fail. // If this ever changes, `simd_cast_ptr` should produce a post-mono error. - use core::{mem::size_of, ptr::Pointee}; + use core::ptr::Pointee; assert_eq!(size_of::<::Metadata>(), 0); assert_eq!(size_of::<::Metadata>(), 0); diff --git a/crates/core_simd/src/simd/ptr/mut_ptr.rs b/crates/core_simd/src/simd/ptr/mut_ptr.rs index bf5d160c09ea..c644f390c20a 100644 --- a/crates/core_simd/src/simd/ptr/mut_ptr.rs +++ b/crates/core_simd/src/simd/ptr/mut_ptr.rs @@ -106,7 +106,7 @@ where fn cast(self) -> Self::CastPtr { // SimdElement currently requires zero-sized metadata, so this should never fail. // If this ever changes, `simd_cast_ptr` should produce a post-mono error. - use core::{mem::size_of, ptr::Pointee}; + use core::ptr::Pointee; assert_eq!(size_of::<::Metadata>(), 0); assert_eq!(size_of::<::Metadata>(), 0); diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs index 498715887e1d..d76a6cd52bfc 100644 --- a/crates/core_simd/src/vector.rs +++ b/crates/core_simd/src/vector.rs @@ -83,7 +83,7 @@ use crate::simd::{ /// converting `[T]` to `[Simd]`, and allows soundly operating on an aligned SIMD body, /// but it may cost more time when handling the scalar head and tail. /// If these are not enough, it is most ideal to design data structures to be already aligned -/// to `mem::align_of::>()` before using `unsafe` Rust to read or write. +/// to `align_of::>()` before using `unsafe` Rust to read or write. /// Other ways to compensate for these facts, like materializing `Simd` to or from an array first, /// are handled by safe methods like [`Simd::from_array`] and [`Simd::from_slice`]. /// diff --git a/crates/core_simd/tests/layout.rs b/crates/core_simd/tests/layout.rs index 24114c2d261e..3b4666249b0d 100644 --- a/crates/core_simd/tests/layout.rs +++ b/crates/core_simd/tests/layout.rs @@ -7,8 +7,8 @@ macro_rules! layout_tests { test_helpers::test_lanes! { fn no_padding() { assert_eq!( - core::mem::size_of::>(), - core::mem::size_of::<[$ty; LANES]>(), + size_of::>(), + size_of::<[$ty; LANES]>(), ); } } diff --git a/crates/core_simd/tests/round.rs b/crates/core_simd/tests/round.rs index 847766ec41ed..4c1ac3c36f89 100644 --- a/crates/core_simd/tests/round.rs +++ b/crates/core_simd/tests/round.rs @@ -58,7 +58,7 @@ macro_rules! float_rounding_test { // all of the mantissa digits set to 1, pushed up to the MSB. const ALL_MANTISSA_BITS: IntScalar = ((1 << ::MANTISSA_DIGITS) - 1); const MAX_REPRESENTABLE_VALUE: Scalar = - (ALL_MANTISSA_BITS << (core::mem::size_of::() * 8 - ::MANTISSA_DIGITS as usize - 1)) as Scalar; + (ALL_MANTISSA_BITS << (size_of::() * 8 - ::MANTISSA_DIGITS as usize - 1)) as Scalar; let mut runner = test_helpers::make_runner(); runner.run( diff --git a/crates/test_helpers/src/subnormals.rs b/crates/test_helpers/src/subnormals.rs index ec0f1fb24b93..b5f19ba47b81 100644 --- a/crates/test_helpers/src/subnormals.rs +++ b/crates/test_helpers/src/subnormals.rs @@ -12,7 +12,7 @@ macro_rules! impl_float { $( impl FlushSubnormals for $ty { fn flush(self) -> Self { - let is_f32 = core::mem::size_of::() == 4; + let is_f32 = size_of::() == 4; let ppc_flush = is_f32 && cfg!(all( any(target_arch = "powerpc", all(target_arch = "powerpc64", target_endian = "big")), target_feature = "altivec", From 7e3daf4edae9d4586478d0dda1930698aaec86e3 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Fri, 7 Mar 2025 05:16:53 +0000 Subject: [PATCH 128/745] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index f6fd106fa523..f403fba2f9da 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -30f168ef811aec63124eac677e14699baa9395bd +98a48781feb1220c0cf2feea23f9ef92cdfa7437 From 5cf0c95552a8400046cfe00afd0d6e8c3970fa10 Mon Sep 17 00:00:00 2001 From: Stypox Date: Fri, 7 Mar 2025 10:20:13 +0100 Subject: [PATCH 129/745] Show interpreter backtrace error on Ctrl+C See https://github.com/rust-lang/rust/pull/111769 --- src/tools/miri/src/concurrency/thread.rs | 2 +- src/tools/miri/src/diagnostics.rs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index a8a2491304dd..94629964ea60 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -1150,7 +1150,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { loop { if CTRL_C_RECEIVED.load(Relaxed) { this.machine.handle_abnormal_termination(); - std::process::exit(1); + throw_machine_stop!(TerminationInfo::Interrupted); } match this.machine.threads.schedule(&this.machine.clock)? { SchedulingAction::ExecuteStep => { diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index 1a12d4139c71..014b1299f2dd 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -16,6 +16,8 @@ pub enum TerminationInfo { leak_check: bool, }, Abort(String), + /// Miri was interrupted by a Ctrl+C from the user + Interrupted, UnsupportedInIsolation(String), StackedBorrowsUb { msg: String, @@ -63,6 +65,7 @@ impl fmt::Display for TerminationInfo { match self { Exit { code, .. } => write!(f, "the evaluated program completed with exit code {code}"), Abort(msg) => write!(f, "{msg}"), + Interrupted => write!(f, "interpretation was interrupted"), UnsupportedInIsolation(msg) => write!(f, "{msg}"), Int2PtrWithStrictProvenance => write!( @@ -226,6 +229,7 @@ pub fn report_error<'tcx>( let title = match info { &Exit { code, leak_check } => return Some((code, leak_check)), Abort(_) => Some("abnormal termination"), + Interrupted => None, UnsupportedInIsolation(_) | Int2PtrWithStrictProvenance | UnsupportedForeignItem(_) => Some("unsupported operation"), StackedBorrowsUb { .. } | TreeBorrowsUb { .. } | DataRace { .. } => From cf0752527f1e1b91cff5683b59e49153187d9efe Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 4 Mar 2025 14:34:18 +1100 Subject: [PATCH 130/745] Make synthetic RPITIT assoc ty name handling more rigorous. Currently it relies on special treatment of `kw::Empty`, which is really easy to get wrong. This commit makes the special case clearer in the type system by using `Option`. It's a bit clumsy, but the synthetic name handling itself is a bit clumsy; better to make it explicit than sneak it in. Fixes #133426. --- clippy_utils/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index d850cc410008..ef706cd076f0 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -3489,7 +3489,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St // a::b::c ::d::sym refers to // e::f::sym:: :: // result should be super::super::super::super::e::f - if let DefPathData::TypeNs(s) = l { + if let DefPathData::TypeNs(Some(s)) = l { path.push(s.to_string()); } if let DefPathData::TypeNs(_) = r { @@ -3500,7 +3500,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St // a::b::sym:: :: refers to // c::d::e ::f::sym // when looking at `f` - Left(DefPathData::TypeNs(sym)) => path.push(sym.to_string()), + Left(DefPathData::TypeNs(Some(sym))) => path.push(sym.to_string()), // consider: // a::b::c ::d::sym refers to // e::f::sym:: :: @@ -3514,7 +3514,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St // `super` chain would be too long, just use the absolute path instead once(String::from("crate")) .chain(to.data.iter().filter_map(|el| { - if let DefPathData::TypeNs(sym) = el.data { + if let DefPathData::TypeNs(Some(sym)) = el.data { Some(sym.to_string()) } else { None From 61f70003c2122313faf77185b6e5ec4bc2ba3bb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Mon, 3 Mar 2025 12:54:26 +0100 Subject: [PATCH 131/745] Add helper methods checking for "#[non_exhaustive] that's active" A check for `#[non_exhaustive]` is often done in combination with checking whether the type is local to the crate, in a variety of ways. Create a helper method and standardize on it as the way to check for this. --- compiler/rustc_hir_typeck/src/cast.rs | 3 +-- compiler/rustc_hir_typeck/src/expr.rs | 2 +- compiler/rustc_hir_typeck/src/expr_use_visitor.rs | 11 ++--------- compiler/rustc_hir_typeck/src/pat.rs | 2 +- compiler/rustc_lint/src/types.rs | 12 ++++-------- compiler/rustc_lint/src/types/improper_ctypes.rs | 14 +++----------- compiler/rustc_middle/src/ty/adt.rs | 11 +++++++++++ compiler/rustc_middle/src/ty/inhabitedness/mod.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 13 ++++++++++++- .../src/builder/matches/match_pair.rs | 3 +-- compiler/rustc_mir_build/src/errors.rs | 6 +++--- compiler/rustc_pattern_analysis/src/rustc.rs | 4 +--- src/tools/clippy/clippy_lints/src/default.rs | 2 +- .../clippy/clippy_lints/src/needless_update.rs | 5 +++-- .../clippy_lints/src/unneeded_struct_pattern.rs | 2 +- 15 files changed, 46 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 70b49fea34f1..e2e366c82c0a 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -42,7 +42,6 @@ use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{self, Ty, TyCtxt, TypeAndMut, TypeVisitableExt, VariantDef}; use rustc_middle::{bug, span_bug}; use rustc_session::lint; -use rustc_span::def_id::LOCAL_CRATE; use rustc_span::{DUMMY_SP, Span, sym}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_type_ir::elaborate; @@ -789,7 +788,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { _ => return Err(CastError::NonScalar), }; if let ty::Adt(adt_def, _) = *self.expr_ty.kind() - && adt_def.did().krate != LOCAL_CRATE + && !adt_def.did().is_local() && adt_def.variants().iter().any(VariantDef::is_field_list_non_exhaustive) { return Err(CastError::ForeignNonExhaustiveAdt); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 2a89a03e0aa4..f771c938f5dd 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1966,7 +1966,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Prohibit struct expressions when non-exhaustive flag is set. let adt = adt_ty.ty_adt_def().expect("`check_struct_path` returned non-ADT type"); - if !adt.did().is_local() && variant.is_field_list_non_exhaustive() { + if variant.field_list_has_applicable_non_exhaustive() { self.dcx() .emit_err(StructExprNonExhaustive { span: expr.span, what: adt.variant_descr() }); } diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index c0617119d67c..f16d258e982f 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -20,7 +20,7 @@ use rustc_middle::hir::place::ProjectionKind; pub use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection}; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::{ - self, AdtKind, BorrowKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _, adjustment, + self, BorrowKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _, adjustment, }; use rustc_middle::{bug, span_bug}; use rustc_span::{ErrorGuaranteed, Span}; @@ -1834,14 +1834,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx // to assume that more cases will be added to the variant in the future. This mean // that we should handle non-exhaustive SingleVariant the same way we would handle // a MultiVariant. - // If the variant is not local it must be defined in another crate. - let is_non_exhaustive = match def.adt_kind() { - AdtKind::Struct | AdtKind::Union => { - def.non_enum_variant().is_field_list_non_exhaustive() - } - AdtKind::Enum => def.is_variant_list_non_exhaustive(), - }; - def.variants().len() > 1 || (!def.did().is_local() && is_non_exhaustive) + def.variants().len() > 1 || def.variant_list_has_applicable_non_exhaustive() } else { false } diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 19ae3e3899c9..f493ae6a8f82 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1722,7 +1722,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // Require `..` if struct has non_exhaustive attribute. - let non_exhaustive = variant.is_field_list_non_exhaustive() && !adt.did().is_local(); + let non_exhaustive = variant.field_list_has_applicable_non_exhaustive(); if non_exhaustive && !has_rest_pat { self.error_foreign_non_exhaustive_spat(pat, adt.variant_descr(), fields.is_empty()); } diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index fcadbfc3c4a7..31098bf443ac 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1193,9 +1193,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { }; } - let is_non_exhaustive = - def.non_enum_variant().is_field_list_non_exhaustive(); - if is_non_exhaustive && !def.did().is_local() { + if def.non_enum_variant().field_list_has_applicable_non_exhaustive() { return FfiUnsafe { ty, reason: if def.is_struct() { @@ -1248,14 +1246,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { }; } - use improper_ctypes::{ - check_non_exhaustive_variant, non_local_and_non_exhaustive, - }; + use improper_ctypes::check_non_exhaustive_variant; - let non_local_def = non_local_and_non_exhaustive(def); + let non_exhaustive = def.variant_list_has_applicable_non_exhaustive(); // Check the contained variants. let ret = def.variants().iter().try_for_each(|variant| { - check_non_exhaustive_variant(non_local_def, variant) + check_non_exhaustive_variant(non_exhaustive, variant) .map_break(|reason| FfiUnsafe { ty, reason, help: None })?; match self.check_variant_for_ffi(acc, ty, def, variant, args) { diff --git a/compiler/rustc_lint/src/types/improper_ctypes.rs b/compiler/rustc_lint/src/types/improper_ctypes.rs index 1030101c545d..13afa540afcf 100644 --- a/compiler/rustc_lint/src/types/improper_ctypes.rs +++ b/compiler/rustc_lint/src/types/improper_ctypes.rs @@ -15,13 +15,13 @@ use crate::fluent_generated as fluent; /// so we don't need the lint to account for it. /// e.g. going from enum Foo { A, B, C } to enum Foo { A, B, C, D(u32) }. pub(crate) fn check_non_exhaustive_variant( - non_local_def: bool, + non_exhaustive_variant_list: bool, variant: &ty::VariantDef, ) -> ControlFlow { // non_exhaustive suggests it is possible that someone might break ABI // see: https://github.com/rust-lang/rust/issues/44109#issuecomment-537583344 // so warn on complex enums being used outside their crate - if non_local_def { + if non_exhaustive_variant_list { // which is why we only warn about really_tagged_union reprs from https://rust.tf/rfc2195 // with an enum like `#[repr(u8)] enum Enum { A(DataA), B(DataB), }` // but exempt enums with unit ctors like C's (e.g. from rust-bindgen) @@ -30,8 +30,7 @@ pub(crate) fn check_non_exhaustive_variant( } } - let non_exhaustive_variant_fields = variant.is_field_list_non_exhaustive(); - if non_exhaustive_variant_fields && !variant.def_id.is_local() { + if variant.field_list_has_applicable_non_exhaustive() { return ControlFlow::Break(fluent::lint_improper_ctypes_non_exhaustive_variant); } @@ -42,10 +41,3 @@ fn variant_has_complex_ctor(variant: &ty::VariantDef) -> bool { // CtorKind::Const means a "unit" ctor !matches!(variant.ctor_kind(), Some(CtorKind::Const)) } - -// non_exhaustive suggests it is possible that someone might break ABI -// see: https://github.com/rust-lang/rust/issues/44109#issuecomment-537583344 -// so warn on complex enums being used outside their crate -pub(crate) fn non_local_and_non_exhaustive(def: ty::AdtDef<'_>) -> bool { - def.is_variant_list_non_exhaustive() && !def.did().is_local() -} diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 3585f28b4a55..fc48f6880498 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -329,11 +329,22 @@ impl<'tcx> AdtDef<'tcx> { } /// Returns `true` if the variant list of this ADT is `#[non_exhaustive]`. + /// + /// Note that this function will return `true` even if the ADT has been + /// defined in the crate currently being compiled. If that's not what you + /// want, see [`Self::variant_list_has_applicable_non_exhaustive`]. #[inline] pub fn is_variant_list_non_exhaustive(self) -> bool { self.flags().contains(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE) } + /// Returns `true` if the variant list of this ADT is `#[non_exhaustive]` + /// and has been defined in another crate. + #[inline] + pub fn variant_list_has_applicable_non_exhaustive(self) -> bool { + self.is_variant_list_non_exhaustive() && !self.did().is_local() + } + /// Returns the kind of the ADT. #[inline] pub fn adt_kind(self) -> AdtKind { diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index 4a5f6d80f24c..855e5043e84a 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -107,7 +107,7 @@ impl<'tcx> Ty<'tcx> { // For now, unions are always considered inhabited Adt(adt, _) if adt.is_union() => InhabitedPredicate::True, // Non-exhaustive ADTs from other crates are always considered inhabited - Adt(adt, _) if adt.is_variant_list_non_exhaustive() && !adt.did().is_local() => { + Adt(adt, _) if adt.variant_list_has_applicable_non_exhaustive() => { InhabitedPredicate::True } Never => InhabitedPredicate::False, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 527509af05fc..7b8f74e8a397 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1206,12 +1206,23 @@ impl VariantDef { } } - /// Is this field list non-exhaustive? + /// Returns `true` if the field list of this variant is `#[non_exhaustive]`. + /// + /// Note that this function will return `true` even if the type has been + /// defined in the crate currently being compiled. If that's not what you + /// want, see [`Self::field_list_has_applicable_non_exhaustive`]. #[inline] pub fn is_field_list_non_exhaustive(&self) -> bool { self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE) } + /// Returns `true` if the field list of this variant is `#[non_exhaustive]` + /// and the type has been defined in another crate. + #[inline] + pub fn field_list_has_applicable_non_exhaustive(&self) -> bool { + self.is_field_list_non_exhaustive() && !self.def_id.is_local() + } + /// Computes the `Ident` of this variant by looking up the `Span` pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap()) diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index c6f3e22e95f6..c41538a2817d 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -277,8 +277,7 @@ impl<'tcx> MatchPairTree<'tcx> { .inhabited_predicate(cx.tcx, adt_def) .instantiate(cx.tcx, args) .apply_ignore_module(cx.tcx, cx.infcx.typing_env(cx.param_env)) - }) && (adt_def.did().is_local() - || !adt_def.is_variant_list_non_exhaustive()); + }) && !adt_def.variant_list_has_applicable_non_exhaustive(); if irrefutable { None } else { Some(TestCase::Variant { adt_def, variant_index }) } } diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 17b22f25dbb0..0e16f871b16f 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -613,9 +613,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNo diag.span_note(span, fluent::mir_build_def_note); } - let is_variant_list_non_exhaustive = matches!(self.ty.kind(), - ty::Adt(def, _) if def.is_variant_list_non_exhaustive() && !def.did().is_local()); - if is_variant_list_non_exhaustive { + let is_non_exhaustive = matches!(self.ty.kind(), + ty::Adt(def, _) if def.variant_list_has_applicable_non_exhaustive()); + if is_non_exhaustive { diag.note(fluent::mir_build_non_exhaustive_type_note); } else { diag.note(fluent::mir_build_type_note); diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 88194c737a6c..fec525c9e8cd 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -150,9 +150,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { /// Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`. pub fn is_foreign_non_exhaustive_enum(&self, ty: RevealedTy<'tcx>) -> bool { match ty.kind() { - ty::Adt(def, ..) => { - def.is_enum() && def.is_variant_list_non_exhaustive() && !def.did().is_local() - } + ty::Adt(def, ..) => def.variant_list_has_applicable_non_exhaustive(), _ => false, } } diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs index ffdd946aadb8..886c325b355f 100644 --- a/src/tools/clippy/clippy_lints/src/default.rs +++ b/src/tools/clippy/clippy_lints/src/default.rs @@ -134,7 +134,7 @@ impl<'tcx> LateLintPass<'tcx> for Default { && let ty::Adt(adt, args) = *binding_type.kind() && adt.is_struct() && let variant = adt.non_enum_variant() - && (adt.did().is_local() || !variant.is_field_list_non_exhaustive()) + && !variant.field_list_has_applicable_non_exhaustive() && let module_did = cx.tcx.parent_module(stmt.hir_id) && variant .fields diff --git a/src/tools/clippy/clippy_lints/src/needless_update.rs b/src/tools/clippy/clippy_lints/src/needless_update.rs index 0cba72bd2c6a..cce0617ba392 100644 --- a/src/tools/clippy/clippy_lints/src/needless_update.rs +++ b/src/tools/clippy/clippy_lints/src/needless_update.rs @@ -54,8 +54,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessUpdate { if let ExprKind::Struct(_, fields, StructTailExpr::Base(base)) = expr.kind { let ty = cx.typeck_results().expr_ty(expr); if let ty::Adt(def, _) = ty.kind() { - if fields.len() == def.non_enum_variant().fields.len() - && !def.variant(0_usize.into()).is_field_list_non_exhaustive() + let variant = def.non_enum_variant(); + if fields.len() == variant.fields.len() + && !variant.is_field_list_non_exhaustive() { span_lint( cx, diff --git a/src/tools/clippy/clippy_lints/src/unneeded_struct_pattern.rs b/src/tools/clippy/clippy_lints/src/unneeded_struct_pattern.rs index a74eab8b6ae5..3326dea8c5df 100644 --- a/src/tools/clippy/clippy_lints/src/unneeded_struct_pattern.rs +++ b/src/tools/clippy/clippy_lints/src/unneeded_struct_pattern.rs @@ -51,7 +51,7 @@ impl LateLintPass<'_> for UnneededStructPattern { let variant = cx.tcx.adt_def(enum_did).variant_with_id(did); let has_only_fields_brackets = variant.ctor.is_some() && variant.fields.is_empty(); - let non_exhaustive_activated = !variant.def_id.is_local() && variant.is_field_list_non_exhaustive(); + let non_exhaustive_activated = variant.field_list_has_applicable_non_exhaustive(); if !has_only_fields_brackets || non_exhaustive_activated { return; } From 044deec6824a834ac870e6d081807d432a999807 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Tue, 4 Mar 2025 15:18:01 +0100 Subject: [PATCH 132/745] mir_build: consider privacy when checking for irrefutable patterns --- .../src/builder/matches/match_pair.rs | 9 ++-- .../privately-uninhabited-issue-137999.rs | 44 +++++++++++++++++++ .../privately-uninhabited-issue-137999.stderr | 26 +++++++++++ 3 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 tests/ui/match/privately-uninhabited-issue-137999.rs create mode 100644 tests/ui/match/privately-uninhabited-issue-137999.stderr diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index c41538a2817d..f2ce0c46dd33 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -273,10 +273,11 @@ impl<'tcx> MatchPairTree<'tcx> { let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| { i == variant_index - || !v - .inhabited_predicate(cx.tcx, adt_def) - .instantiate(cx.tcx, args) - .apply_ignore_module(cx.tcx, cx.infcx.typing_env(cx.param_env)) + || !v.inhabited_predicate(cx.tcx, adt_def).instantiate(cx.tcx, args).apply( + cx.tcx, + cx.infcx.typing_env(cx.param_env), + cx.def_id.into(), + ) }) && !adt_def.variant_list_has_applicable_non_exhaustive(); if irrefutable { None } else { Some(TestCase::Variant { adt_def, variant_index }) } } diff --git a/tests/ui/match/privately-uninhabited-issue-137999.rs b/tests/ui/match/privately-uninhabited-issue-137999.rs new file mode 100644 index 000000000000..918393a0c6ac --- /dev/null +++ b/tests/ui/match/privately-uninhabited-issue-137999.rs @@ -0,0 +1,44 @@ +//@ edition:2024 +//@ check-fail + +mod m { + enum Void {} + + pub struct Internal { + _v: Void, + } + + pub enum Test { + A(u32, u32), + B(Internal), + } +} + +use m::Test; + +pub fn f1(x: &mut Test) { + let r1: &mut u32 = match x { + Test::A(a, _) => a, + _ => todo!(), + }; + + let r2: &mut u32 = match x { //~ ERROR cannot use `*x` because it was mutably borrowed + Test::A(_, b) => b, + _ => todo!(), + }; + + let _ = *r1; + let _ = *r2; +} + +pub fn f2(x: &mut Test) { + let r = &mut *x; + match x { //~ ERROR cannot use `*x` because it was mutably borrowed + Test::A(_, _) => {} + _ => {} + } + + let _ = r; +} + +fn main() {} diff --git a/tests/ui/match/privately-uninhabited-issue-137999.stderr b/tests/ui/match/privately-uninhabited-issue-137999.stderr new file mode 100644 index 000000000000..6f74a75375e3 --- /dev/null +++ b/tests/ui/match/privately-uninhabited-issue-137999.stderr @@ -0,0 +1,26 @@ +error[E0503]: cannot use `*x` because it was mutably borrowed + --> $DIR/privately-uninhabited-issue-137999.rs:25:30 + | +LL | Test::A(a, _) => a, + | - `x.0` is borrowed here +... +LL | let r2: &mut u32 = match x { + | ^ use of borrowed `x.0` +... +LL | let _ = *r1; + | --- borrow later used here + +error[E0503]: cannot use `*x` because it was mutably borrowed + --> $DIR/privately-uninhabited-issue-137999.rs:36:11 + | +LL | let r = &mut *x; + | ------- `*x` is borrowed here +LL | match x { + | ^ use of borrowed `*x` +... +LL | let _ = r; + | - borrow later used here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0503`. From 540565e5b97b4669cd84ecd57f3d7affd00e83a1 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 6 Feb 2025 12:46:33 +0000 Subject: [PATCH 133/745] Fully test the alloc crate through alloctests For the tests that make use of internal implementation details, we include the module to test using #[path] in alloctests now. --- ...9-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index c2027863b00b..754025ff49db 100644 --- a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -12,15 +12,15 @@ index 7165c3e48af..968552ad435 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -11,7 +11,7 @@ test = { path = "../test" } - edition = "2021" + bench = false [dependencies] core = { path = "../core", public = true } -compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std', 'no-f16-f128'] } - [dev-dependencies] - rand = { version = "0.8.5", default-features = false, features = ["alloc"] } + [features] + compiler-builtins-mem = ['compiler_builtins/mem'] -- 2.34.1 From f86a71dfbf35b36b1ce439f65dfe51f591688393 Mon Sep 17 00:00:00 2001 From: Amy Kwan Date: Sat, 8 Mar 2025 00:23:46 -0500 Subject: [PATCH 134/745] [AIX] Ignore linting on repr(C) structs with repr(packed) or repr(align(n)) This PR updates the lint added in 9b40bd7 to ignore repr(C) structs that also have repr(packed) or repr(align(n)). As these representations can be modifiers on repr(C), it is assumed that users that add these should know what they are doing, and thus the the lint should not warn on the respective structs. For example, for the time being, using repr(packed) and manually padding a repr(C) struct can be done to correctly align struct members on AIX. --- compiler/rustc_lint/src/types.rs | 6 ++++++ tests/ui/layout/reprc-power-alignment.rs | 26 +++++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index fcadbfc3c4a7..71116d0bfe42 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1638,6 +1638,9 @@ impl ImproperCTypesDefinitions { return true; } else if let Adt(adt_def, _) = ty.kind() && adt_def.is_struct() + && adt_def.repr().c() + && !adt_def.repr().packed() + && adt_def.repr().align.is_none() { let struct_variant = adt_def.variant(VariantIdx::ZERO); // Within a nested struct, all fields are examined to correctly @@ -1659,8 +1662,11 @@ impl ImproperCTypesDefinitions { item: &'tcx hir::Item<'tcx>, ) { let adt_def = cx.tcx.adt_def(item.owner_id.to_def_id()); + // repr(C) structs also with packed or aligned representation + // should be ignored. if adt_def.repr().c() && !adt_def.repr().packed() + && adt_def.repr().align.is_none() && cx.tcx.sess.target.os == "aix" && !adt_def.all_fields().next().is_none() { diff --git a/tests/ui/layout/reprc-power-alignment.rs b/tests/ui/layout/reprc-power-alignment.rs index f6c1df55988b..f144094d43fb 100644 --- a/tests/ui/layout/reprc-power-alignment.rs +++ b/tests/ui/layout/reprc-power-alignment.rs @@ -148,5 +148,29 @@ pub struct I { d: f32, e: f64, } - +#[repr(C)] +pub struct J { + a: u8, + b: I, +} +// The lint also ignores diagnosing #[repr(align(n))]. +#[repr(C, align(8))] +pub struct K { + a: u8, + b: u8, + c: f64, + d: f32, + e: f64, +} +#[repr(C)] +pub struct L { + a: u8, + b: K, +} +#[repr(C, align(8))] +pub struct M { + a: u8, + b: K, + c: L, +} fn main() { } From 243e0ee2741d78e1fc73a045c8cc0319fa98b259 Mon Sep 17 00:00:00 2001 From: lapla-cogito Date: Sun, 2 Mar 2025 22:24:43 +0900 Subject: [PATCH 135/745] don't trigger `blocks_in_conditions` when the condition contains a `return` --- clippy_lints/src/blocks_in_conditions.rs | 9 ++++++++- tests/ui/blocks_in_conditions.fixed | 7 +++++++ tests/ui/blocks_in_conditions.rs | 7 +++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/blocks_in_conditions.rs b/clippy_lints/src/blocks_in_conditions.rs index aab0af0d743b..011962846cb3 100644 --- a/clippy_lints/src/blocks_in_conditions.rs +++ b/clippy_lints/src/blocks_in_conditions.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_block_with_applicability; -use clippy_utils::{higher, is_from_proc_macro}; +use clippy_utils::{contains_return, higher, is_from_proc_macro}; use rustc_errors::Applicability; use rustc_hir::{BlockCheckMode, Expr, ExprKind, MatchSource}; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -86,6 +86,13 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInConditions { if expr.span.from_expansion() || ex.span.from_expansion() { return; } + + // Linting should not be triggered to cases where `return` is included in the condition. + // #9911 + if contains_return(block.expr) { + return; + } + let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, diff --git a/tests/ui/blocks_in_conditions.fixed b/tests/ui/blocks_in_conditions.fixed index df375e370573..cd307e803d0c 100644 --- a/tests/ui/blocks_in_conditions.fixed +++ b/tests/ui/blocks_in_conditions.fixed @@ -118,6 +118,13 @@ mod issue_12016 { } } +fn issue_9911() { + if { return } {} + + let a = 1; + if { if a == 1 { return } else { true } } {} +} + fn in_closure() { let v = vec![1, 2, 3]; if v.into_iter() diff --git a/tests/ui/blocks_in_conditions.rs b/tests/ui/blocks_in_conditions.rs index 1d9c9dd42460..6a211c8edfd4 100644 --- a/tests/ui/blocks_in_conditions.rs +++ b/tests/ui/blocks_in_conditions.rs @@ -118,6 +118,13 @@ mod issue_12016 { } } +fn issue_9911() { + if { return } {} + + let a = 1; + if { if a == 1 { return } else { true } } {} +} + fn in_closure() { let v = vec![1, 2, 3]; if v.into_iter() From 79013f813dde402c9d032dbf189f33221ed33c64 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 26 Dec 2024 12:00:57 +0100 Subject: [PATCH 136/745] Improve `needless_pass_by_value` suggestion --- clippy_lints/src/needless_pass_by_value.rs | 10 +++++++++- tests/ui/needless_pass_by_value.rs | 7 +++++++ tests/ui/needless_pass_by_value.stderr | 10 ++++++++-- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 380cc380ad0f..f5652e7b832d 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -279,10 +279,18 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { } } + let suggestion = if is_type_diagnostic_item(cx, ty, sym::Option) + && let snip = snippet(cx, input.span, "_") + && let Some((first, rest)) = snip.split_once('<') + { + format!("{first}<&{rest}") + } else { + format!("&{}", snippet(cx, input.span, "_")) + }; diag.span_suggestion( input.span, "consider taking a reference instead", - format!("&{}", snippet(cx, input.span, "_")), + suggestion, Applicability::MaybeIncorrect, ); }; diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index 885fb409417b..adea373fd55a 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -189,6 +189,13 @@ struct Obj(String); fn prefix_test(_unused_with_prefix: Obj) {} +// Regression test for . +// It's more idiomatic to write `Option<&T>` rather than `&Option`. +fn option_inner_ref(x: Option) { + //~^ ERROR: this argument is passed by value, but not consumed in the function body + assert!(x.is_some()); +} + fn main() { // This should not cause an ICE either // https://github.com/rust-lang/rust-clippy/issues/3144 diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index 4ac4fdce972d..7aea725d50ba 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -29,7 +29,7 @@ error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:58:18 | LL | fn test_match(x: Option>, y: Option>) { - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&Option>` + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `Option<&Option>` error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:73:24 @@ -179,5 +179,11 @@ error: this argument is passed by value, but not consumed in the function body LL | fn more_fun(items: impl Club<'static, i32>) {} | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&impl Club<'static, i32>` -error: aborting due to 22 previous errors +error: this argument is passed by value, but not consumed in the function body + --> tests/ui/needless_pass_by_value.rs:187:24 + | +LL | fn option_inner_ref(x: Option) { + | ^^^^^^^^^^^^^^ help: consider taking a reference instead: `Option<&String>` + +error: aborting due to 23 previous errors From c8e47f9a72b0c3009e17b4fb66667931ac335026 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 8 Mar 2025 21:14:11 +0100 Subject: [PATCH 137/745] Update `needless_pass_by_value` stderr --- tests/ui/needless_pass_by_value.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index 7aea725d50ba..987bfc4affc5 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -180,7 +180,7 @@ LL | fn more_fun(items: impl Club<'static, i32>) {} | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&impl Club<'static, i32>` error: this argument is passed by value, but not consumed in the function body - --> tests/ui/needless_pass_by_value.rs:187:24 + --> tests/ui/needless_pass_by_value.rs:194:24 | LL | fn option_inner_ref(x: Option) { | ^^^^^^^^^^^^^^ help: consider taking a reference instead: `Option<&String>` From 8269132210360e201ff9969b956c660602104cf8 Mon Sep 17 00:00:00 2001 From: ltdk Date: Sun, 18 Aug 2024 19:50:41 -0400 Subject: [PATCH 138/745] Add inherent versions of MaybeUninit::fill methods for slices --- library/core/src/mem/maybe_uninit.rs | 320 +++++++++++++++------------ library/coretests/tests/mem.rs | 54 ++--- library/std/src/io/util.rs | 3 +- 3 files changed, 209 insertions(+), 168 deletions(-) diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index ce84f105e5c5..d0be82adb6b1 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -1065,161 +1065,46 @@ impl MaybeUninit { this.write_clone_of_slice(src) } - /// Fills a slice with elements by cloning `value`, returning a mutable reference to the now - /// initialized contents of the slice. - /// Any previously initialized elements will not be dropped. - /// - /// This is similar to [`slice::fill`]. - /// - /// # Panics - /// - /// This function will panic if any call to `Clone` panics. - /// - /// If such a panic occurs, any elements previously initialized during this operation will be - /// dropped. - /// - /// # Examples - /// - /// ``` - /// #![feature(maybe_uninit_fill)] - /// use std::mem::MaybeUninit; - /// - /// let mut buf = [const { MaybeUninit::uninit() }; 10]; - /// let initialized = MaybeUninit::fill(&mut buf, 1); - /// assert_eq!(initialized, &mut [1; 10]); - /// ``` - #[doc(alias = "memset")] + /// Deprecated version of [`slice::write_filled`]. #[unstable(feature = "maybe_uninit_fill", issue = "117428")] - pub fn fill(this: &mut [MaybeUninit], value: T) -> &mut [T] + #[deprecated( + note = "replaced by inherent write_filled method; will eventually be removed", + since = "1.83.0" + )] + pub fn fill<'a>(this: &'a mut [MaybeUninit], value: T) -> &'a mut [T] where T: Clone, { - SpecFill::spec_fill(this, value); - // SAFETY: Valid elements have just been filled into `this` so it is initialized - unsafe { this.assume_init_mut() } + this.write_filled(value) } - /// Fills a slice with elements returned by calling a closure repeatedly. - /// - /// This method uses a closure to create new values. If you'd rather `Clone` a given value, use - /// [`MaybeUninit::fill`]. If you want to use the `Default` trait to generate values, you can - /// pass [`Default::default`] as the argument. - /// - /// # Panics - /// - /// This function will panic if any call to the provided closure panics. - /// - /// If such a panic occurs, any elements previously initialized during this operation will be - /// dropped. - /// - /// # Examples - /// - /// ``` - /// #![feature(maybe_uninit_fill)] - /// use std::mem::MaybeUninit; - /// - /// let mut buf = [const { MaybeUninit::::uninit() }; 10]; - /// let initialized = MaybeUninit::fill_with(&mut buf, Default::default); - /// assert_eq!(initialized, &mut [0; 10]); - /// ``` + /// Deprecated version of [`slice::write_with`]. #[unstable(feature = "maybe_uninit_fill", issue = "117428")] - pub fn fill_with(this: &mut [MaybeUninit], mut f: F) -> &mut [T] + #[deprecated( + note = "replaced by inherent write_with method; will eventually be removed", + since = "1.83.0" + )] + pub fn fill_with<'a, F>(this: &'a mut [MaybeUninit], mut f: F) -> &'a mut [T] where F: FnMut() -> T, { - let mut guard = Guard { slice: this, initialized: 0 }; - - for element in guard.slice.iter_mut() { - element.write(f()); - guard.initialized += 1; - } - - super::forget(guard); - - // SAFETY: Valid elements have just been written into `this` so it is initialized - unsafe { this.assume_init_mut() } + this.write_with(|_| f()) } - /// Fills a slice with elements yielded by an iterator until either all elements have been - /// initialized or the iterator is empty. - /// - /// Returns two slices. The first slice contains the initialized portion of the original slice. - /// The second slice is the still-uninitialized remainder of the original slice. - /// - /// # Panics - /// - /// This function panics if the iterator's `next` function panics. - /// - /// If such a panic occurs, any elements previously initialized during this operation will be - /// dropped. - /// - /// # Examples - /// - /// Completely filling the slice: - /// - /// ``` - /// #![feature(maybe_uninit_fill)] - /// use std::mem::MaybeUninit; - /// - /// let mut buf = [const { MaybeUninit::uninit() }; 5]; - /// - /// let iter = [1, 2, 3].into_iter().cycle(); - /// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter); - /// - /// assert_eq!(initialized, &mut [1, 2, 3, 1, 2]); - /// assert_eq!(remainder.len(), 0); - /// ``` - /// - /// Partially filling the slice: - /// - /// ``` - /// #![feature(maybe_uninit_fill)] - /// use std::mem::MaybeUninit; - /// - /// let mut buf = [const { MaybeUninit::uninit() }; 5]; - /// let iter = [1, 2]; - /// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter); - /// - /// assert_eq!(initialized, &mut [1, 2]); - /// assert_eq!(remainder.len(), 3); - /// ``` - /// - /// Checking an iterator after filling a slice: - /// - /// ``` - /// #![feature(maybe_uninit_fill)] - /// use std::mem::MaybeUninit; - /// - /// let mut buf = [const { MaybeUninit::uninit() }; 3]; - /// let mut iter = [1, 2, 3, 4, 5].into_iter(); - /// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter.by_ref()); - /// - /// assert_eq!(initialized, &mut [1, 2, 3]); - /// assert_eq!(remainder.len(), 0); - /// assert_eq!(iter.as_slice(), &[4, 5]); - /// ``` + /// Deprecated version of [`slice::write_iter`]. #[unstable(feature = "maybe_uninit_fill", issue = "117428")] - pub fn fill_from(this: &mut [MaybeUninit], it: I) -> (&mut [T], &mut [MaybeUninit]) + #[deprecated( + note = "replaced by inherent write_iter method; will eventually be removed", + since = "1.83.0" + )] + pub fn fill_from<'a, I>( + this: &'a mut [MaybeUninit], + it: I, + ) -> (&'a mut [T], &'a mut [MaybeUninit]) where I: IntoIterator, { - let iter = it.into_iter(); - let mut guard = Guard { slice: this, initialized: 0 }; - - for (element, val) in guard.slice.iter_mut().zip(iter) { - element.write(val); - guard.initialized += 1; - } - - let initialized_len = guard.initialized; - super::forget(guard); - - // SAFETY: guard.initialized <= this.len() - let (initted, remainder) = unsafe { this.split_at_mut_unchecked(initialized_len) }; - - // SAFETY: Valid elements have just been written into `init`, so that portion - // of `this` is initialized. - (unsafe { initted.assume_init_mut() }, remainder) + this.write_iter(it) } /// Deprecated version of [`slice::as_bytes`]. @@ -1380,6 +1265,163 @@ impl [MaybeUninit] { unsafe { self.assume_init_mut() } } + /// Fills a slice with elements by cloning `value`, returning a mutable reference to the now + /// initialized contents of the slice. + /// Any previously initialized elements will not be dropped. + /// + /// This is similar to [`slice::fill`]. + /// + /// # Panics + /// + /// This function will panic if any call to `Clone` panics. + /// + /// If such a panic occurs, any elements previously initialized during this operation will be + /// dropped. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = [const { MaybeUninit::uninit() }; 10]; + /// let initialized = buf.write_filled(1); + /// assert_eq!(initialized, &mut [1; 10]); + /// ``` + #[doc(alias = "memset")] + #[unstable(feature = "maybe_uninit_fill", issue = "117428")] + pub fn write_filled(&mut self, value: T) -> &mut [T] + where + T: Clone, + { + SpecFill::spec_fill(self, value); + // SAFETY: Valid elements have just been filled into `self` so it is initialized + unsafe { self.assume_init_mut() } + } + + /// Fills a slice with elements returned by calling a closure for each index. + /// + /// This method uses a closure to create new values. If you'd rather `Clone` a given value, use + /// [`MaybeUninit::fill`]. If you want to use the `Default` trait to generate values, you can + /// pass [`|_| Default::default()`][Default::default] as the argument. + /// + /// # Panics + /// + /// This function will panic if any call to the provided closure panics. + /// + /// If such a panic occurs, any elements previously initialized during this operation will be + /// dropped. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = [const { MaybeUninit::::uninit() }; 5]; + /// let initialized = buf.write_with(|idx| idx + 1); + /// assert_eq!(initialized, &mut [1, 2, 3, 4, 5]); + /// ``` + #[unstable(feature = "maybe_uninit_fill", issue = "117428")] + pub fn write_with(&mut self, mut f: F) -> &mut [T] + where + F: FnMut(usize) -> T, + { + let mut guard = Guard { slice: self, initialized: 0 }; + + for (idx, element) in guard.slice.iter_mut().enumerate() { + element.write(f(idx)); + guard.initialized += 1; + } + + super::forget(guard); + + // SAFETY: Valid elements have just been written into `this` so it is initialized + unsafe { self.assume_init_mut() } + } + + /// Fills a slice with elements yielded by an iterator until either all elements have been + /// initialized or the iterator is empty. + /// + /// Returns two slices. The first slice contains the initialized portion of the original slice. + /// The second slice is the still-uninitialized remainder of the original slice. + /// + /// # Panics + /// + /// This function panics if the iterator's `next` function panics. + /// + /// If such a panic occurs, any elements previously initialized during this operation will be + /// dropped. + /// + /// # Examples + /// + /// Completely filling the slice: + /// + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = [const { MaybeUninit::uninit() }; 5]; + /// + /// let iter = [1, 2, 3].into_iter().cycle(); + /// let (initialized, remainder) = buf.write_iter(iter); + /// + /// assert_eq!(initialized, &mut [1, 2, 3, 1, 2]); + /// assert_eq!(remainder.len(), 0); + /// ``` + /// + /// Partially filling the slice: + /// + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = [const { MaybeUninit::uninit() }; 5]; + /// let iter = [1, 2]; + /// let (initialized, remainder) = buf.write_iter(iter); + /// + /// assert_eq!(initialized, &mut [1, 2]); + /// assert_eq!(remainder.len(), 3); + /// ``` + /// + /// Checking an iterator after filling a slice: + /// + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = [const { MaybeUninit::uninit() }; 3]; + /// let mut iter = [1, 2, 3, 4, 5].into_iter(); + /// let (initialized, remainder) = buf.write_iter(iter.by_ref()); + /// + /// assert_eq!(initialized, &mut [1, 2, 3]); + /// assert_eq!(remainder.len(), 0); + /// assert_eq!(iter.as_slice(), &[4, 5]); + /// ``` + #[unstable(feature = "maybe_uninit_fill", issue = "117428")] + pub fn write_iter(&mut self, it: I) -> (&mut [T], &mut [MaybeUninit]) + where + I: IntoIterator, + { + let iter = it.into_iter(); + let mut guard = Guard { slice: self, initialized: 0 }; + + for (element, val) in guard.slice.iter_mut().zip(iter) { + element.write(val); + guard.initialized += 1; + } + + let initialized_len = guard.initialized; + super::forget(guard); + + // SAFETY: guard.initialized <= self.len() + let (initted, remainder) = unsafe { self.split_at_mut_unchecked(initialized_len) }; + + // SAFETY: Valid elements have just been written into `init`, so that portion + // of `this` is initialized. + (unsafe { initted.assume_init_mut() }, remainder) + } + /// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes. /// /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still diff --git a/library/coretests/tests/mem.rs b/library/coretests/tests/mem.rs index 9cb94ca3b0ff..9c15be4a8c4b 100644 --- a/library/coretests/tests/mem.rs +++ b/library/coretests/tests/mem.rs @@ -1,5 +1,5 @@ use core::mem::*; -use core::ptr; +use core::{array, ptr}; #[cfg(panic = "unwind")] use std::rc::Rc; @@ -327,11 +327,11 @@ fn uninit_write_clone_of_slice_no_drop() { } #[test] -fn uninit_fill() { +fn uninit_write_filled() { let mut dst = [MaybeUninit::new(255); 64]; let expect = [0; 64]; - assert_eq!(MaybeUninit::fill(&mut dst, 0), &expect); + assert_eq!(dst.write_filled(0), &expect); } #[cfg(panic = "unwind")] @@ -352,7 +352,7 @@ impl Clone for CloneUntilPanic { #[test] #[cfg(panic = "unwind")] -fn uninit_fill_clone_panic_drop() { +fn uninit_write_filled_panic_drop() { use std::panic; let rc = Rc::new(()); @@ -361,7 +361,7 @@ fn uninit_fill_clone_panic_drop() { let src = CloneUntilPanic { limit: 3, rc: rc.clone() }; let err = panic::catch_unwind(panic::AssertUnwindSafe(|| { - MaybeUninit::fill(&mut dst, src); + dst.write_filled(src); })); match err { @@ -378,23 +378,23 @@ fn uninit_fill_clone_panic_drop() { #[test] #[cfg(panic = "unwind")] -fn uninit_fill_clone_no_drop_clones() { +fn uninit_write_filled_no_drop_clones() { let mut dst = [MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit()]; - MaybeUninit::fill(&mut dst, Bomb); + dst.write_filled(Bomb); } #[test] -fn uninit_fill_with() { - let mut dst = [MaybeUninit::new(255); 64]; - let expect = [0; 64]; +fn uninit_write_with() { + let mut dst = [MaybeUninit::new(255usize); 64]; + let expect = array::from_fn::(|idx| idx); - assert_eq!(MaybeUninit::fill_with(&mut dst, || 0), &expect); + assert_eq!(dst.write_with(|idx| idx), &expect); } #[test] #[cfg(panic = "unwind")] -fn uninit_fill_with_mid_panic() { +fn uninit_write_with_mid_panic() { use std::panic; let rc = Rc::new(()); @@ -403,7 +403,7 @@ fn uninit_fill_with_mid_panic() { let src = CloneUntilPanic { limit: 3, rc: rc.clone() }; let err = panic::catch_unwind(panic::AssertUnwindSafe(|| { - MaybeUninit::fill_with(&mut dst, || src.clone()); + dst.write_with(|_| src.clone()); })); drop(src); @@ -423,58 +423,58 @@ fn uninit_fill_with_mid_panic() { #[test] #[cfg(panic = "unwind")] -fn uninit_fill_with_no_drop() { +fn uninit_write_with_no_drop() { let mut dst = [MaybeUninit::uninit()]; let src = Bomb; - MaybeUninit::fill_with(&mut dst, || src.clone()); + dst.write_with(|_| src.clone()); forget(src); } #[test] -fn uninit_fill_from() { +fn uninit_write_iter() { let mut dst = [MaybeUninit::new(255); 64]; let src = [0; 64]; - let (initted, remainder) = MaybeUninit::fill_from(&mut dst, src.into_iter()); + let (initted, remainder) = dst.write_iter(src.into_iter()); assert_eq!(initted, &src); assert_eq!(remainder.len(), 0); } #[test] -fn uninit_fill_from_partial() { +fn uninit_write_iter_partial() { let mut dst = [MaybeUninit::new(255); 64]; let src = [0; 48]; - let (initted, remainder) = MaybeUninit::fill_from(&mut dst, src.into_iter()); + let (initted, remainder) = dst.write_iter(src.into_iter()); assert_eq!(initted, &src); assert_eq!(remainder.len(), 16); } #[test] -fn uninit_over_fill() { +fn uninit_write_iter_overfill() { let mut dst = [MaybeUninit::new(255); 64]; let src = [0; 72]; - let (initted, remainder) = MaybeUninit::fill_from(&mut dst, src.into_iter()); + let (initted, remainder) = dst.write_iter(src.into_iter()); assert_eq!(initted, &src[0..64]); assert_eq!(remainder.len(), 0); } #[test] -fn uninit_empty_fill() { +fn uninit_write_iter_empty() { let mut dst = [MaybeUninit::new(255); 64]; let src = [0; 0]; - let (initted, remainder) = MaybeUninit::fill_from(&mut dst, src.into_iter()); + let (initted, remainder) = dst.write_iter(src.into_iter()); assert_eq!(initted, &src[0..0]); assert_eq!(remainder.len(), 64); } #[test] #[cfg(panic = "unwind")] -fn uninit_fill_from_mid_panic() { +fn uninit_write_iter_mid_panic() { use std::panic; struct IterUntilPanic { @@ -504,7 +504,7 @@ fn uninit_fill_from_mid_panic() { let src = IterUntilPanic { limit: 3, rc: rc.clone() }; let err = panic::catch_unwind(panic::AssertUnwindSafe(|| { - MaybeUninit::fill_from(&mut dst, src); + dst.write_iter(src); })); match err { @@ -522,11 +522,11 @@ fn uninit_fill_from_mid_panic() { #[test] #[cfg(panic = "unwind")] -fn uninit_fill_from_no_drop() { +fn uninit_write_iter_no_drop() { let mut dst = [MaybeUninit::uninit()]; let src = [Bomb]; - MaybeUninit::fill_from(&mut dst, src.iter()); + dst.write_iter(src.iter()); forget(src); } diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index cb3f864fd4e1..3b66dbf40b6b 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -7,7 +7,6 @@ use crate::fmt; use crate::io::{ self, BorrowedCursor, BufRead, IoSlice, IoSliceMut, Read, Seek, SeekFrom, SizeHint, Write, }; -use crate::mem::MaybeUninit; /// `Empty` ignores any data written via [`Write`], and will always be empty /// (returning zero bytes) when read via [`Read`]. @@ -196,7 +195,7 @@ impl Read for Repeat { #[inline] fn read_buf(&mut self, mut buf: BorrowedCursor<'_>) -> io::Result<()> { // SAFETY: No uninit bytes are being written. - MaybeUninit::fill(unsafe { buf.as_mut() }, self.byte); + unsafe { buf.as_mut() }.write_filled(self.byte); // SAFETY: the entire unfilled portion of buf has been initialized. unsafe { buf.advance_unchecked(buf.capacity()) }; Ok(()) From ab21f716fc966d16d43cf8979fbdc58b5f0d2d5c Mon Sep 17 00:00:00 2001 From: lapla-cogito Date: Sun, 9 Mar 2025 11:04:21 +0900 Subject: [PATCH 139/745] fix broken CSS links --- util/gh-pages/index_template.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/util/gh-pages/index_template.html b/util/gh-pages/index_template.html index a9b646280030..19dc1ec0b0cc 100644 --- a/util/gh-pages/index_template.html +++ b/util/gh-pages/index_template.html @@ -19,10 +19,10 @@ Otherwise, have a great day =^.^= {# #} - {# #} - {# #} - {# #} - {# #} + {# #} + {# #} + {# #} + {# #} {# #} {# #} {# #} From 8dd65e4098faf3fc7d97f297577b033d3c24d66b Mon Sep 17 00:00:00 2001 From: Turtel216 Date: Sun, 9 Mar 2025 16:03:12 +0200 Subject: [PATCH 140/745] Add documentation to json.rs module --- lintcheck/src/json.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lintcheck/src/json.rs b/lintcheck/src/json.rs index 3a68f2c92435..58830f8a8b3c 100644 --- a/lintcheck/src/json.rs +++ b/lintcheck/src/json.rs @@ -1,3 +1,9 @@ +//! JSON output and comparison functionality for Clippy warnings. +//! +//! This module handles serialization of Clippy warnings to JSON format, +//! loading warnings from JSON files, and generating human-readable diffs +//! between different linting runs. + use std::fs; use std::path::Path; @@ -8,8 +14,10 @@ use crate::ClippyWarning; /// This is the total number. 300 warnings results in 100 messages per section. const DEFAULT_LIMIT_PER_LINT: usize = 300; +/// Target for total warnings to display across all lints when truncating output. const TRUNCATION_TOTAL_TARGET: usize = 1000; +/// Representation of a single Clippy warning for JSON serialization. #[derive(Debug, Deserialize, Serialize)] struct LintJson { /// The lint name e.g. `clippy::bytes_nth` @@ -21,10 +29,12 @@ struct LintJson { } impl LintJson { + /// Returns a tuple of name and file_line for sorting and comparison. fn key(&self) -> impl Ord + '_ { (self.name.as_str(), self.file_line.as_str()) } + /// Formats the warning information with an action verb for display. fn info_text(&self, action: &str) -> String { format!("{action} `{}` at [`{}`]({})", self.name, self.file_line, self.file_url) } @@ -53,12 +63,17 @@ pub(crate) fn output(clippy_warnings: Vec) -> String { serde_json::to_string(&lints).unwrap() } +/// Loads lint warnings from a JSON file at the given path. fn load_warnings(path: &Path) -> Vec { let file = fs::read(path).unwrap_or_else(|e| panic!("failed to read {}: {e}", path.display())); serde_json::from_slice(&file).unwrap_or_else(|e| panic!("failed to deserialize {}: {e}", path.display())) } +/// Generates and prints a diff between two sets of lint warnings. +/// +/// Compares warnings from `old_path` and `new_path`, then displays a summary table +/// and detailed information about added, removed, and changed warnings. pub(crate) fn diff(old_path: &Path, new_path: &Path, truncate: bool) { let old_warnings = load_warnings(old_path); let new_warnings = load_warnings(new_path); @@ -116,6 +131,7 @@ pub(crate) fn diff(old_path: &Path, new_path: &Path, truncate: bool) { } } +/// Container for grouped lint warnings organized by status (added/removed/changed). #[derive(Debug)] struct LintWarnings { name: String, @@ -124,6 +140,7 @@ struct LintWarnings { changed: Vec<(LintJson, LintJson)>, } +/// Prints a formatted report for a single lint type with its warnings. fn print_lint_warnings(lint: &LintWarnings, truncate_after: usize) { let name = &lint.name; let html_id = to_html_id(name); @@ -145,6 +162,7 @@ fn print_lint_warnings(lint: &LintWarnings, truncate_after: usize) { print_changed_diff(&lint.changed, truncate_after / 3); } +/// Prints a summary table of all lints with counts of added, removed, and changed warnings. fn print_summary_table(lints: &[LintWarnings]) { println!("| Lint | Added | Removed | Changed |"); println!("| ------------------------------------------ | ------: | ------: | ------: |"); @@ -160,6 +178,7 @@ fn print_summary_table(lints: &[LintWarnings]) { } } +/// Prints a section of warnings with a header and formatted code blocks. fn print_warnings(title: &str, warnings: &[LintJson], truncate_after: usize) { if warnings.is_empty() { return; @@ -180,6 +199,7 @@ fn print_warnings(title: &str, warnings: &[LintJson], truncate_after: usize) { } } +/// Prints a section of changed warnings with unified diff format. fn print_changed_diff(changed: &[(LintJson, LintJson)], truncate_after: usize) { if changed.is_empty() { return; @@ -213,6 +233,7 @@ fn print_changed_diff(changed: &[(LintJson, LintJson)], truncate_after: usize) { } } +/// Truncates a list to a maximum number of items and prints a message about truncation. fn truncate(list: &[T], truncate_after: usize) -> &[T] { if list.len() > truncate_after { println!( @@ -227,6 +248,7 @@ fn truncate(list: &[T], truncate_after: usize) -> &[T] { } } +/// Prints a level 3 heading with an appropriate HTML ID for linking. fn print_h3(lint: &str, title: &str) { let html_id = to_html_id(lint); // We have to use HTML here to be able to manually add an id. From 184feee826bb534a568bcea2cf35c93fa1a40549 Mon Sep 17 00:00:00 2001 From: Turtel216 Date: Sun, 9 Mar 2025 16:29:07 +0200 Subject: [PATCH 141/745] Fix key function description --- lintcheck/src/json.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lintcheck/src/json.rs b/lintcheck/src/json.rs index 58830f8a8b3c..8ea0a41ed368 100644 --- a/lintcheck/src/json.rs +++ b/lintcheck/src/json.rs @@ -29,7 +29,7 @@ struct LintJson { } impl LintJson { - /// Returns a tuple of name and file_line for sorting and comparison. + /// Returns a tuple of name and `file_line` for sorting and comparison. fn key(&self) -> impl Ord + '_ { (self.name.as_str(), self.file_line.as_str()) } From 97275d523ce22491fa5843596593414e58be4411 Mon Sep 17 00:00:00 2001 From: yanglsh Date: Fri, 7 Mar 2025 19:06:38 +0800 Subject: [PATCH 142/745] fix: `unnecessary_safety_comment` FP on desugared assign --- .../src/undocumented_unsafe_blocks.rs | 19 ++++++++++++++++++ .../undocumented_unsafe_blocks.default.stderr | 14 ++++++++++++- ...undocumented_unsafe_blocks.disabled.stderr | 14 ++++++++++++- .../undocumented_unsafe_blocks.rs | 20 +++++++++++++++++++ 4 files changed, 65 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index b824eb88abf9..816e400ed840 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -312,6 +312,25 @@ fn expr_has_unnecessary_safety_comment<'tcx>( }, _, ) => ControlFlow::Break(()), + // `_ = foo()` is desugared to `{ let _ = foo(); }` + hir::ExprKind::Block( + Block { + rules: BlockCheckMode::DefaultBlock, + stmts: + [ + hir::Stmt { + kind: + hir::StmtKind::Let(hir::LetStmt { + source: hir::LocalSource::AssignDesugar(_), + .. + }), + .. + }, + ], + .. + }, + _, + ) => ControlFlow::Continue(Descend::Yes), // statements will be handled by check_stmt itself again hir::ExprKind::Block(..) => ControlFlow::Continue(Descend::No), _ => ControlFlow::Continue(Descend::Yes), diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr index 4357c455e50e..8a2f201009a9 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr @@ -342,5 +342,17 @@ LL | const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; | = help: consider adding a safety comment on the preceding line -error: aborting due to 39 previous errors +error: statement has unnecessary safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:719:5 + | +LL | _ = bar(); + | ^^^^^^^^^^ + | +help: consider removing the safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:718:5 + | +LL | // SAFETY: unnecessary_safety_comment triggers here + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 40 previous errors diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr index eb61e1e6da08..e9c5e5f9f114 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr @@ -438,5 +438,17 @@ LL | unsafe { Date::__from_ordinal_date_unchecked(1970, 1) }.into_julian | = help: consider adding a safety comment on the preceding line -error: aborting due to 51 previous errors +error: statement has unnecessary safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:719:5 + | +LL | _ = bar(); + | ^^^^^^^^^^ + | +help: consider removing the safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:718:5 + | +LL | // SAFETY: unnecessary_safety_comment triggers here + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 52 previous errors diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs index 2492a3c2f562..91a02bc3d7c6 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs @@ -703,4 +703,24 @@ mod issue_11709_regression { //~[disabled]^ undocumented_unsafe_blocks } +fn issue_13039() { + unsafe fn foo() -> usize { + 1234 + } + + fn bar() -> usize { + 1234 + } + + // SAFETY: unnecessary_safety_comment should not trigger here + _ = unsafe { foo() }; + + // SAFETY: unnecessary_safety_comment triggers here + _ = bar(); + //~^ unnecessary_safety_comment + + // SAFETY: unnecessary_safety_comment should not trigger here + _ = unsafe { foo() } +} + fn main() {} From 90dbc5bf94de29304c18d840c8c90f09f2d32cf6 Mon Sep 17 00:00:00 2001 From: lapla-cogito Date: Wed, 12 Feb 2025 22:25:58 +0900 Subject: [PATCH 143/745] make `never_loop` applicability more flexible --- clippy_lints/src/loops/never_loop.rs | 25 ++++++++-- tests/ui/never_loop.rs | 28 +++++++++++ tests/ui/never_loop.stderr | 70 +++++++++++++++++++++++++++- tests/ui/never_loop_fixable.fixed | 20 ++++++++ tests/ui/never_loop_fixable.rs | 20 ++++++++ tests/ui/never_loop_fixable.stderr | 35 ++++++++++++++ 6 files changed, 193 insertions(+), 5 deletions(-) create mode 100644 tests/ui/never_loop_fixable.fixed create mode 100644 tests/ui/never_loop_fixable.rs create mode 100644 tests/ui/never_loop_fixable.stderr diff --git a/clippy_lints/src/loops/never_loop.rs b/clippy_lints/src/loops/never_loop.rs index b679fdfadc3a..3f8de774eef7 100644 --- a/clippy_lints/src/loops/never_loop.rs +++ b/clippy_lints/src/loops/never_loop.rs @@ -4,11 +4,13 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::ForLoop; use clippy_utils::macros::root_macro_call_first_node; use clippy_utils::source::snippet; +use clippy_utils::visitors::{Descend, for_each_expr_without_closures}; use rustc_errors::Applicability; use rustc_hir::{Block, Destination, Expr, ExprKind, HirId, InlineAsmOperand, Pat, Stmt, StmtKind, StructTailExpr}; use rustc_lint::LateContext; use rustc_span::{Span, sym}; use std::iter::once; +use std::ops::ControlFlow; pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, @@ -24,17 +26,23 @@ pub(super) fn check<'tcx>( arg: iterator, pat, span: for_span, + label, .. }) = for_loop { - // Suggests using an `if let` instead. This is `Unspecified` because the - // loop may (probably) contain `break` statements which would be invalid - // in an `if let`. + // If the block contains a break or continue, or if the loop has a label, `MachineApplicable` is not + // appropriate. + let app = if !contains_any_break_or_continue(block) && label.is_none() { + Applicability::MachineApplicable + } else { + Applicability::Unspecified + }; + diag.span_suggestion_verbose( for_span.with_hi(iterator.span.hi()), "if you need the first element of the iterator, try writing", for_to_if_let_sugg(cx, iterator, pat), - Applicability::Unspecified, + app, ); } }); @@ -43,6 +51,15 @@ pub(super) fn check<'tcx>( } } +fn contains_any_break_or_continue(block: &Block<'_>) -> bool { + for_each_expr_without_closures(block, |e| match e.kind { + ExprKind::Break(..) | ExprKind::Continue(..) => ControlFlow::Break(()), + ExprKind::Loop(..) => ControlFlow::Continue(Descend::No), + _ => ControlFlow::Continue(Descend::Yes), + }) + .is_some() +} + /// The `never_loop` analysis keeps track of three things: /// /// * Has any (reachable) code path hit a `continue` of the main loop? diff --git a/tests/ui/never_loop.rs b/tests/ui/never_loop.rs index 2d8e04c192e4..e0f54ef899b0 100644 --- a/tests/ui/never_loop.rs +++ b/tests/ui/never_loop.rs @@ -422,6 +422,34 @@ pub fn issue12205() -> Option<()> { } } +fn stmt_after_return() { + for v in 0..10 { + //~^ never_loop + break; + println!("{v}"); + } +} + +fn loop_label() { + 'outer: for v in 0..10 { + //~^ never_loop + loop { + //~^ never_loop + break 'outer; + } + return; + } + + for v in 0..10 { + //~^ never_loop + 'inner: loop { + //~^ never_loop + break 'inner; + } + return; + } +} + fn main() { test1(); test2(); diff --git a/tests/ui/never_loop.stderr b/tests/ui/never_loop.stderr index f6d6d109542b..bc9a7ec48b48 100644 --- a/tests/ui/never_loop.stderr +++ b/tests/ui/never_loop.stderr @@ -164,5 +164,73 @@ LL | | unimplemented!("not yet"); LL | | } | |_____^ -error: aborting due to 16 previous errors +error: this loop never actually loops + --> tests/ui/never_loop.rs:426:5 + | +LL | / for v in 0..10 { +LL | | +LL | | break; +LL | | println!("{v}"); +LL | | } + | |_____^ + | +help: if you need the first element of the iterator, try writing + | +LL - for v in 0..10 { +LL + if let Some(v) = (0..10).next() { + | + +error: this loop never actually loops + --> tests/ui/never_loop.rs:434:5 + | +LL | / 'outer: for v in 0..10 { +LL | | +LL | | loop { +... | +LL | | return; +LL | | } + | |_____^ + | +help: if you need the first element of the iterator, try writing + | +LL - 'outer: for v in 0..10 { +LL + if let Some(v) = (0..10).next() { + | + +error: this loop never actually loops + --> tests/ui/never_loop.rs:436:9 + | +LL | / loop { +LL | | +LL | | break 'outer; +LL | | } + | |_________^ + +error: this loop never actually loops + --> tests/ui/never_loop.rs:443:5 + | +LL | / for v in 0..10 { +LL | | +LL | | 'inner: loop { +... | +LL | | return; +LL | | } + | |_____^ + | +help: if you need the first element of the iterator, try writing + | +LL - for v in 0..10 { +LL + if let Some(v) = (0..10).next() { + | + +error: this loop never actually loops + --> tests/ui/never_loop.rs:445:9 + | +LL | / 'inner: loop { +LL | | +LL | | break 'inner; +LL | | } + | |_________^ + +error: aborting due to 21 previous errors diff --git a/tests/ui/never_loop_fixable.fixed b/tests/ui/never_loop_fixable.fixed new file mode 100644 index 000000000000..5bc9ff1bb4df --- /dev/null +++ b/tests/ui/never_loop_fixable.fixed @@ -0,0 +1,20 @@ +#![allow(clippy::iter_next_slice, clippy::needless_return)] + +fn no_break_or_continue_loop() { + if let Some(i) = [1, 2, 3].iter().next() { + //~^ never_loop + return; + } +} + +fn no_break_or_continue_loop_outer() { + if let Some(i) = [1, 2, 3].iter().next() { + //~^ never_loop + return; + loop { + if true { + continue; + } + } + } +} diff --git a/tests/ui/never_loop_fixable.rs b/tests/ui/never_loop_fixable.rs new file mode 100644 index 000000000000..9782bc107e9a --- /dev/null +++ b/tests/ui/never_loop_fixable.rs @@ -0,0 +1,20 @@ +#![allow(clippy::iter_next_slice, clippy::needless_return)] + +fn no_break_or_continue_loop() { + for i in [1, 2, 3].iter() { + //~^ never_loop + return; + } +} + +fn no_break_or_continue_loop_outer() { + for i in [1, 2, 3].iter() { + //~^ never_loop + return; + loop { + if true { + continue; + } + } + } +} diff --git a/tests/ui/never_loop_fixable.stderr b/tests/ui/never_loop_fixable.stderr new file mode 100644 index 000000000000..ee02d9a42976 --- /dev/null +++ b/tests/ui/never_loop_fixable.stderr @@ -0,0 +1,35 @@ +error: this loop never actually loops + --> tests/ui/never_loop_fixable.rs:4:5 + | +LL | / for i in [1, 2, 3].iter() { +LL | | +LL | | return; +LL | | } + | |_____^ + | + = note: `#[deny(clippy::never_loop)]` on by default +help: if you need the first element of the iterator, try writing + | +LL - for i in [1, 2, 3].iter() { +LL + if let Some(i) = [1, 2, 3].iter().next() { + | + +error: this loop never actually loops + --> tests/ui/never_loop_fixable.rs:11:5 + | +LL | / for i in [1, 2, 3].iter() { +LL | | +LL | | return; +LL | | loop { +... | +LL | | } + | |_____^ + | +help: if you need the first element of the iterator, try writing + | +LL - for i in [1, 2, 3].iter() { +LL + if let Some(i) = [1, 2, 3].iter().next() { + | + +error: aborting due to 2 previous errors + From 523b9d942890f331fcee5d2d26e7cecfb59c6ec8 Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Fri, 14 Feb 2025 13:40:24 -0800 Subject: [PATCH 144/745] Implement default methods for io::Empty and io::Sink Eliminate any redundant, unobservable logic from the their default method implementations. The observable changes are that `Write::write_fmt` for both types now ignores the formatting arguments, so a user fmt impl which has side effects is not invoked, and `Write::write_all_vectored` for both types does not advance the borrowed buffers. Neither behavior is guaranteed by the docs and the latter is documented as unspecified. `Empty` is not marked as vectored, so that `Chain` and `Chain<_, Empty>` are not forced to be vectored. --- library/std/src/io/util.rs | 116 +++++++++++++++++++++++++++++++ library/std/src/io/util/tests.rs | 111 ++++++++++++++++++++++++++--- tests/ui/write-fmt-errors.rs | 4 +- 3 files changed, 218 insertions(+), 13 deletions(-) diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index cb3f864fd4e1..17178b4a6414 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -68,6 +68,38 @@ impl Read for Empty { fn read_buf(&mut self, _cursor: BorrowedCursor<'_>) -> io::Result<()> { Ok(()) } + + #[inline] + fn read_vectored(&mut self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result { + Ok(0) + } + + #[inline] + fn is_read_vectored(&self) -> bool { + // Do not force `Chain` or `Chain` to use vectored + // reads, unless the other reader is vectored. + false + } + + #[inline] + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { + if !buf.is_empty() { Err(io::Error::READ_EXACT_EOF) } else { Ok(()) } + } + + #[inline] + fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { + if cursor.capacity() != 0 { Err(io::Error::READ_EXACT_EOF) } else { Ok(()) } + } + + #[inline] + fn read_to_end(&mut self, _buf: &mut Vec) -> io::Result { + Ok(0) + } + + #[inline] + fn read_to_string(&mut self, _buf: &mut String) -> io::Result { + Ok(0) + } } #[stable(feature = "rust1", since = "1.0.0")] impl BufRead for Empty { @@ -75,20 +107,44 @@ impl BufRead for Empty { fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) } + #[inline] fn consume(&mut self, _n: usize) {} + + #[inline] + fn has_data_left(&mut self) -> io::Result { + Ok(false) + } + + #[inline] + fn read_until(&mut self, _byte: u8, _buf: &mut Vec) -> io::Result { + Ok(0) + } + + #[inline] + fn skip_until(&mut self, _byte: u8) -> io::Result { + Ok(0) + } + + #[inline] + fn read_line(&mut self, _buf: &mut String) -> io::Result { + Ok(0) + } } #[stable(feature = "empty_seek", since = "1.51.0")] impl Seek for Empty { + #[inline] fn seek(&mut self, _pos: SeekFrom) -> io::Result { Ok(0) } + #[inline] fn stream_len(&mut self) -> io::Result { Ok(0) } + #[inline] fn stream_position(&mut self) -> io::Result { Ok(0) } @@ -119,6 +175,21 @@ impl Write for Empty { true } + #[inline] + fn write_all(&mut self, _buf: &[u8]) -> io::Result<()> { + Ok(()) + } + + #[inline] + fn write_all_vectored(&mut self, _bufs: &mut [IoSlice<'_>]) -> io::Result<()> { + Ok(()) + } + + #[inline] + fn write_fmt(&mut self, _args: fmt::Arguments<'_>) -> io::Result<()> { + Ok(()) + } + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) @@ -143,6 +214,21 @@ impl Write for &Empty { true } + #[inline] + fn write_all(&mut self, _buf: &[u8]) -> io::Result<()> { + Ok(()) + } + + #[inline] + fn write_all_vectored(&mut self, _bufs: &mut [IoSlice<'_>]) -> io::Result<()> { + Ok(()) + } + + #[inline] + fn write_fmt(&mut self, _args: fmt::Arguments<'_>) -> io::Result<()> { + Ok(()) + } + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) @@ -302,6 +388,21 @@ impl Write for Sink { true } + #[inline] + fn write_all(&mut self, _buf: &[u8]) -> io::Result<()> { + Ok(()) + } + + #[inline] + fn write_all_vectored(&mut self, _bufs: &mut [IoSlice<'_>]) -> io::Result<()> { + Ok(()) + } + + #[inline] + fn write_fmt(&mut self, _args: fmt::Arguments<'_>) -> io::Result<()> { + Ok(()) + } + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) @@ -326,6 +427,21 @@ impl Write for &Sink { true } + #[inline] + fn write_all(&mut self, _buf: &[u8]) -> io::Result<()> { + Ok(()) + } + + #[inline] + fn write_all_vectored(&mut self, _bufs: &mut [IoSlice<'_>]) -> io::Result<()> { + Ok(()) + } + + #[inline] + fn write_fmt(&mut self, _args: fmt::Arguments<'_>) -> io::Result<()> { + Ok(()) + } + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) diff --git a/library/std/src/io/util/tests.rs b/library/std/src/io/util/tests.rs index 0599a881af17..d0f106d7af41 100644 --- a/library/std/src/io/util/tests.rs +++ b/library/std/src/io/util/tests.rs @@ -1,14 +1,51 @@ +use crate::fmt; use crate::io::prelude::*; -use crate::io::{BorrowedBuf, Empty, Repeat, SeekFrom, Sink, empty, repeat, sink}; +use crate::io::{ + BorrowedBuf, Empty, ErrorKind, IoSlice, IoSliceMut, Repeat, SeekFrom, Sink, empty, repeat, sink, +}; use crate::mem::MaybeUninit; +struct ErrorDisplay; + +impl fmt::Display for ErrorDisplay { + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + Err(fmt::Error) + } +} + +struct PanicDisplay; + +impl fmt::Display for PanicDisplay { + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + panic!() + } +} + +#[track_caller] +fn test_sinking(mut w: W) { + assert_eq!(w.write(&[]).unwrap(), 0); + assert_eq!(w.write(&[0]).unwrap(), 1); + assert_eq!(w.write(&[0; 1024]).unwrap(), 1024); + w.write_all(&[]).unwrap(); + w.write_all(&[0]).unwrap(); + w.write_all(&[0; 1024]).unwrap(); + let mut bufs = + [IoSlice::new(&[]), IoSlice::new(&[0]), IoSlice::new(&[0; 1024]), IoSlice::new(&[])]; + assert!(w.is_write_vectored()); + assert_eq!(w.write_vectored(&[]).unwrap(), 0); + assert_eq!(w.write_vectored(&bufs).unwrap(), 1025); + w.write_all_vectored(&mut []).unwrap(); + w.write_all_vectored(&mut bufs).unwrap(); + assert!(w.flush().is_ok()); + assert_eq!(w.by_ref().write(&[0; 1024]).unwrap(), 1024); + // Ignores fmt arguments + w.write_fmt(format_args!("{}", ErrorDisplay)).unwrap(); + w.write_fmt(format_args!("{}", PanicDisplay)).unwrap(); +} + #[test] fn sink_sinks() { - let mut s = sink(); - assert_eq!(s.write(&[]).unwrap(), 0); - assert_eq!(s.write(&[0]).unwrap(), 1); - assert_eq!(s.write(&[0; 1024]).unwrap(), 1024); - assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024); + test_sinking(sink()); } #[test] @@ -19,6 +56,21 @@ fn empty_reads() { assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0); assert_eq!(Read::by_ref(&mut e).read(&mut [0; 1024]).unwrap(), 0); + e.read_exact(&mut []).unwrap(); + assert_eq!(e.read_exact(&mut [0]).unwrap_err().kind(), ErrorKind::UnexpectedEof); + assert_eq!(e.read_exact(&mut [0; 1024]).unwrap_err().kind(), ErrorKind::UnexpectedEof); + + assert!(!e.is_read_vectored()); + assert_eq!(e.read_vectored(&mut []).unwrap(), 0); + let (mut buf1, mut buf1024) = ([0], [0; 1024]); + let bufs = &mut [ + IoSliceMut::new(&mut []), + IoSliceMut::new(&mut buf1), + IoSliceMut::new(&mut buf1024), + IoSliceMut::new(&mut []), + ]; + assert_eq!(e.read_vectored(bufs).unwrap(), 0); + let buf: &mut [MaybeUninit<_>] = &mut []; let mut buf: BorrowedBuf<'_> = buf.into(); e.read_buf(buf.unfilled()).unwrap(); @@ -42,6 +94,47 @@ fn empty_reads() { Read::by_ref(&mut e).read_buf(buf.unfilled()).unwrap(); assert_eq!(buf.len(), 0); assert_eq!(buf.init_len(), 0); + + let buf: &mut [MaybeUninit<_>] = &mut []; + let mut buf: BorrowedBuf<'_> = buf.into(); + e.read_buf_exact(buf.unfilled()).unwrap(); + assert_eq!(buf.len(), 0); + assert_eq!(buf.init_len(), 0); + + let buf: &mut [_] = &mut [MaybeUninit::uninit()]; + let mut buf: BorrowedBuf<'_> = buf.into(); + assert_eq!(e.read_buf_exact(buf.unfilled()).unwrap_err().kind(), ErrorKind::UnexpectedEof); + assert_eq!(buf.len(), 0); + assert_eq!(buf.init_len(), 0); + + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 1024]; + let mut buf: BorrowedBuf<'_> = buf.into(); + assert_eq!(e.read_buf_exact(buf.unfilled()).unwrap_err().kind(), ErrorKind::UnexpectedEof); + assert_eq!(buf.len(), 0); + assert_eq!(buf.init_len(), 0); + + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 1024]; + let mut buf: BorrowedBuf<'_> = buf.into(); + assert_eq!( + Read::by_ref(&mut e).read_buf_exact(buf.unfilled()).unwrap_err().kind(), + ErrorKind::UnexpectedEof, + ); + assert_eq!(buf.len(), 0); + assert_eq!(buf.init_len(), 0); + + let mut buf = Vec::new(); + assert_eq!(e.read_to_end(&mut buf).unwrap(), 0); + assert_eq!(buf, vec![]); + let mut buf = vec![1, 2, 3]; + assert_eq!(e.read_to_end(&mut buf).unwrap(), 0); + assert_eq!(buf, vec![1, 2, 3]); + + let mut buf = String::new(); + assert_eq!(e.read_to_string(&mut buf).unwrap(), 0); + assert_eq!(buf, ""); + let mut buf = "hello".to_owned(); + assert_eq!(e.read_to_string(&mut buf).unwrap(), 0); + assert_eq!(buf, "hello"); } #[test] @@ -66,11 +159,7 @@ fn empty_seeks() { #[test] fn empty_sinks() { - let mut e = empty(); - assert_eq!(e.write(&[]).unwrap(), 0); - assert_eq!(e.write(&[0]).unwrap(), 1); - assert_eq!(e.write(&[0; 1024]).unwrap(), 1024); - assert_eq!(Write::by_ref(&mut e).write(&[0; 1024]).unwrap(), 1024); + test_sinking(empty()); } #[test] diff --git a/tests/ui/write-fmt-errors.rs b/tests/ui/write-fmt-errors.rs index 1dafb9a784b3..b48fa3f11ccb 100644 --- a/tests/ui/write-fmt-errors.rs +++ b/tests/ui/write-fmt-errors.rs @@ -4,7 +4,7 @@ #![feature(io_error_uncategorized)] use std::fmt; -use std::io::{self, Error, Write, sink}; +use std::io::{self, Error, Write}; use std::panic::catch_unwind; struct ErrorDisplay; @@ -33,7 +33,7 @@ fn main() { assert!(res.is_err(), "writer error did not propagate"); // Test that the error from the formatter is detected. - let res = catch_unwind(|| write!(sink(), "{} {} {}", 1, ErrorDisplay, "bar")); + let res = catch_unwind(|| write!(vec![], "{} {} {}", 1, ErrorDisplay, "bar")); let err = res.expect_err("formatter error did not lead to panic").downcast::<&str>().unwrap(); assert!( err.contains("formatting trait implementation returned an error"), From 28bd22c3d9a477ff9b7b85782fb517c29b58ed88 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sun, 9 Mar 2025 23:42:48 +0000 Subject: [PATCH 145/745] rustdoc: Gate unstable `doc(cfg())` predicates --- src/librustdoc/clean/cfg.rs | 14 ++++---------- src/librustdoc/clean/types.rs | 7 +++++++ src/librustdoc/doctest/rust.rs | 2 +- tests/rustdoc-ui/doc-cfg-unstable.rs | 10 ++++++++++ tests/rustdoc-ui/doc-cfg-unstable.stderr | 23 +++++++++++++++++++++++ 5 files changed, 45 insertions(+), 11 deletions(-) create mode 100644 tests/rustdoc-ui/doc-cfg-unstable.rs create mode 100644 tests/rustdoc-ui/doc-cfg-unstable.stderr diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index ab169f3c2a4d..1541e7201cef 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -8,7 +8,6 @@ use std::{mem, ops}; use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit}; use rustc_data_structures::fx::FxHashSet; -use rustc_feature::Features; use rustc_session::parse::ParseSess; use rustc_span::Span; use rustc_span::symbol::{Symbol, sym}; @@ -132,18 +131,13 @@ impl Cfg { /// Checks whether the given configuration can be matched in the current session. /// /// Equivalent to `attr::cfg_matches`. - // FIXME: Actually make use of `features`. - pub(crate) fn matches(&self, psess: &ParseSess, features: Option<&Features>) -> bool { + pub(crate) fn matches(&self, psess: &ParseSess) -> bool { match *self { Cfg::False => false, Cfg::True => true, - Cfg::Not(ref child) => !child.matches(psess, features), - Cfg::All(ref sub_cfgs) => { - sub_cfgs.iter().all(|sub_cfg| sub_cfg.matches(psess, features)) - } - Cfg::Any(ref sub_cfgs) => { - sub_cfgs.iter().any(|sub_cfg| sub_cfg.matches(psess, features)) - } + Cfg::Not(ref child) => !child.matches(psess), + Cfg::All(ref sub_cfgs) => sub_cfgs.iter().all(|sub_cfg| sub_cfg.matches(psess)), + Cfg::Any(ref sub_cfgs) => sub_cfgs.iter().any(|sub_cfg| sub_cfg.matches(psess)), Cfg::Cfg(name, value) => psess.config.contains(&(name, value)), } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 9e9cd5288349..e70511a798a3 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1056,6 +1056,13 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator .meta_item() .and_then(|item| rustc_expand::config::parse_cfg(item, sess)) { + // The result is unused here but we can gate unstable predicates + rustc_attr_parsing::cfg_matches( + cfg_mi, + tcx.sess, + rustc_ast::CRATE_NODE_ID, + Some(tcx.features()), + ); match Cfg::parse(cfg_mi) { Ok(new_cfg) => cfg &= new_cfg, Err(e) => { diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs index 907e2a3eb2fc..b12c516a827d 100644 --- a/src/librustdoc/doctest/rust.rs +++ b/src/librustdoc/doctest/rust.rs @@ -98,7 +98,7 @@ impl HirCollector<'_> { let ast_attrs = self.tcx.hir().attrs(self.tcx.local_def_id_to_hir_id(def_id)); if let Some(ref cfg) = extract_cfg_from_attrs(ast_attrs.iter(), self.tcx, &FxHashSet::default()) - && !cfg.matches(&self.tcx.sess.psess, Some(self.tcx.features())) + && !cfg.matches(&self.tcx.sess.psess) { return; } diff --git a/tests/rustdoc-ui/doc-cfg-unstable.rs b/tests/rustdoc-ui/doc-cfg-unstable.rs new file mode 100644 index 000000000000..14c2e83ec854 --- /dev/null +++ b/tests/rustdoc-ui/doc-cfg-unstable.rs @@ -0,0 +1,10 @@ +// #138113: rustdoc didn't gate unstable predicates inside `doc(cfg(..))` +#![feature(doc_cfg)] + +// `cfg_boolean_literals` +#[doc(cfg(false))] //~ ERROR `cfg(false)` is experimental and subject to change +pub fn cfg_boolean_literals() {} + +// `cfg_version` +#[doc(cfg(sanitize = "thread"))] //~ ERROR `cfg(sanitize)` is experimental and subject to change +pub fn cfg_sanitize() {} diff --git a/tests/rustdoc-ui/doc-cfg-unstable.stderr b/tests/rustdoc-ui/doc-cfg-unstable.stderr new file mode 100644 index 000000000000..54de3b178edb --- /dev/null +++ b/tests/rustdoc-ui/doc-cfg-unstable.stderr @@ -0,0 +1,23 @@ +error[E0658]: `cfg(false)` is experimental and subject to change + --> $DIR/doc-cfg-unstable.rs:5:11 + | +LL | #[doc(cfg(false))] + | ^^^^^ + | + = note: see issue #131204 for more information + = help: add `#![feature(cfg_boolean_literals)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `cfg(sanitize)` is experimental and subject to change + --> $DIR/doc-cfg-unstable.rs:9:11 + | +LL | #[doc(cfg(sanitize = "thread"))] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #39699 for more information + = help: add `#![feature(cfg_sanitize)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. From 9e5c942286f8d2367987daac856300447ee43776 Mon Sep 17 00:00:00 2001 From: Paul Menage Date: Mon, 10 Mar 2025 08:31:06 -0700 Subject: [PATCH 146/745] Mark some std tests as requiring `panic = "unwind"` This allows these test modules to pass on builds/targets without unwinding support, where `panic = "abort"` - the ignored tests are for functionality that's not supported on those targets. --- library/std/src/thread/tests.rs | 5 +++++ library/std/tests/sync/mutex.rs | 10 ++++++++++ library/std/tests/sync/once.rs | 4 ++++ library/std/tests/sync/once_lock.rs | 6 ++++-- library/std/tests/sync/rwlock.rs | 16 ++++++++++++++++ 5 files changed, 39 insertions(+), 2 deletions(-) diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs index 06c347af1819..59ec48a57d1c 100644 --- a/library/std/src/thread/tests.rs +++ b/library/std/src/thread/tests.rs @@ -108,6 +108,7 @@ fn test_is_finished() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_join_panic() { match thread::spawn(move || panic!()).join() { result::Result::Err(_) => (), @@ -210,6 +211,7 @@ fn test_simple_newsched_spawn() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_try_panic_message_string_literal() { match thread::spawn(move || { panic!("static string"); @@ -226,6 +228,7 @@ fn test_try_panic_message_string_literal() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_try_panic_any_message_owned_str() { match thread::spawn(move || { panic_any("owned string".to_string()); @@ -242,6 +245,7 @@ fn test_try_panic_any_message_owned_str() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_try_panic_any_message_any() { match thread::spawn(move || { panic_any(Box::new(413u16) as Box); @@ -260,6 +264,7 @@ fn test_try_panic_any_message_any() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_try_panic_any_message_unit_struct() { struct Juju; diff --git a/library/std/tests/sync/mutex.rs b/library/std/tests/sync/mutex.rs index 74c627201073..88fb448d1ebf 100644 --- a/library/std/tests/sync/mutex.rs +++ b/library/std/tests/sync/mutex.rs @@ -118,6 +118,7 @@ fn test_into_inner_drop() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_into_inner_poison() { let m = new_poisoned_mutex(NonCopy(10)); @@ -135,6 +136,7 @@ fn test_get_cloned() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_get_cloned_poison() { let m = new_poisoned_mutex(Cloneable(10)); @@ -152,6 +154,7 @@ fn test_get_mut() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_get_mut_poison() { let mut m = new_poisoned_mutex(NonCopy(10)); @@ -179,6 +182,7 @@ fn test_set() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_set_poison() { fn inner(mut init: impl FnMut() -> T, mut value: impl FnMut() -> T) where @@ -217,6 +221,7 @@ fn test_replace() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_replace_poison() { fn inner(mut init: impl FnMut() -> T, mut value: impl FnMut() -> T) where @@ -261,6 +266,7 @@ fn test_mutex_arc_condvar() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_arc_condvar_poison() { let packet = Packet(Arc::new((Mutex::new(1), Condvar::new()))); let packet2 = Packet(packet.0.clone()); @@ -290,6 +296,7 @@ fn test_arc_condvar_poison() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_mutex_arc_poison() { let arc = Arc::new(Mutex::new(1)); assert!(!arc.is_poisoned()); @@ -304,6 +311,7 @@ fn test_mutex_arc_poison() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_mutex_arc_poison_mapped() { let arc = Arc::new(Mutex::new(1)); assert!(!arc.is_poisoned()); @@ -335,6 +343,7 @@ fn test_mutex_arc_nested() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_mutex_arc_access_in_unwind() { let arc = Arc::new(Mutex::new(1)); let arc2 = arc.clone(); @@ -381,6 +390,7 @@ fn test_mapping_mapped_guard() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn panic_while_mapping_unlocked_poison() { let lock = Mutex::new(()); diff --git a/library/std/tests/sync/once.rs b/library/std/tests/sync/once.rs index a3ffc73fe06b..1b43831df3a4 100644 --- a/library/std/tests/sync/once.rs +++ b/library/std/tests/sync/once.rs @@ -52,6 +52,7 @@ fn stampede_once() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn poison_bad() { static O: Once = Once::new(); @@ -80,6 +81,7 @@ fn poison_bad() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn wait_for_force_to_finish() { static O: Once = Once::new(); @@ -137,6 +139,7 @@ fn wait() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn wait_on_poisoned() { let once = Once::new(); @@ -145,6 +148,7 @@ fn wait_on_poisoned() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn wait_force_on_poisoned() { let once = Once::new(); diff --git a/library/std/tests/sync/once_lock.rs b/library/std/tests/sync/once_lock.rs index ac9aaa8892ef..922fd7da3d44 100644 --- a/library/std/tests/sync/once_lock.rs +++ b/library/std/tests/sync/once_lock.rs @@ -77,8 +77,10 @@ fn get_or_try_init() { let cell: OnceLock = OnceLock::new(); assert!(cell.get().is_none()); - let res = panic::catch_unwind(|| cell.get_or_try_init(|| -> Result<_, ()> { panic!() })); - assert!(res.is_err()); + if cfg!(panic = "unwind") { + let res = panic::catch_unwind(|| cell.get_or_try_init(|| -> Result<_, ()> { panic!() })); + assert!(res.is_err()); + } assert!(cell.get().is_none()); assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); diff --git a/library/std/tests/sync/rwlock.rs b/library/std/tests/sync/rwlock.rs index 49f260648c6a..d2c784aefcf6 100644 --- a/library/std/tests/sync/rwlock.rs +++ b/library/std/tests/sync/rwlock.rs @@ -73,6 +73,7 @@ fn frob() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_rw_arc_poison_wr() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); @@ -85,6 +86,7 @@ fn test_rw_arc_poison_wr() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_rw_arc_poison_mapped_w_r() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); @@ -98,6 +100,7 @@ fn test_rw_arc_poison_mapped_w_r() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_rw_arc_poison_ww() { let arc = Arc::new(RwLock::new(1)); assert!(!arc.is_poisoned()); @@ -112,6 +115,7 @@ fn test_rw_arc_poison_ww() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_rw_arc_poison_mapped_w_w() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); @@ -126,6 +130,7 @@ fn test_rw_arc_poison_mapped_w_w() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_rw_arc_no_poison_rr() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); @@ -139,6 +144,7 @@ fn test_rw_arc_no_poison_rr() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_rw_arc_no_poison_mapped_r_r() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); @@ -153,6 +159,7 @@ fn test_rw_arc_no_poison_mapped_r_r() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_rw_arc_no_poison_rw() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); @@ -166,6 +173,7 @@ fn test_rw_arc_no_poison_rw() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_rw_arc_no_poison_mapped_r_w() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); @@ -218,6 +226,7 @@ fn test_rw_arc() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_rw_arc_access_in_unwind() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); @@ -316,6 +325,7 @@ fn test_into_inner_drop() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_into_inner_poison() { let m = new_poisoned_rwlock(NonCopy(10)); @@ -333,6 +343,7 @@ fn test_get_cloned() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_get_cloned_poison() { let m = new_poisoned_rwlock(Cloneable(10)); @@ -350,6 +361,7 @@ fn test_get_mut() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_get_mut_poison() { let mut m = new_poisoned_rwlock(NonCopy(10)); @@ -377,6 +389,7 @@ fn test_set() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_set_poison() { fn inner(mut init: impl FnMut() -> T, mut value: impl FnMut() -> T) where @@ -415,6 +428,7 @@ fn test_replace() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_replace_poison() { fn inner(mut init: impl FnMut() -> T, mut value: impl FnMut() -> T) where @@ -482,6 +496,7 @@ fn test_mapping_mapped_guard() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn panic_while_mapping_read_unlocked_no_poison() { let lock = RwLock::new(()); @@ -551,6 +566,7 @@ fn panic_while_mapping_read_unlocked_no_poison() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn panic_while_mapping_write_unlocked_poison() { let lock = RwLock::new(()); From 5889b95f4e04716058da56a5162b4f62338cd922 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Tue, 11 Mar 2025 05:14:57 +0000 Subject: [PATCH 147/745] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index f403fba2f9da..8b14b51496a8 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -98a48781feb1220c0cf2feea23f9ef92cdfa7437 +90384941aae4ea38de00e4702b50757e9b882a19 From d9de94001a25d33d4ba77cfa686c65f49264264c Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 26 Jul 2024 10:04:02 +0000 Subject: [PATCH 148/745] Implement `#[define_opaque]` attribute for functions. --- example/issue-72793.rs | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/example/issue-72793.rs b/example/issue-72793.rs index 2e08fbca8ef2..95d58b90e798 100644 --- a/example/issue-72793.rs +++ b/example/issue-72793.rs @@ -2,23 +2,21 @@ #![feature(type_alias_impl_trait)] -mod helper { - pub trait T { - type Item; - } - - pub type Alias<'a> = impl T; - - struct S; - impl<'a> T for &'a S { - type Item = &'a (); - } - - pub fn filter_positive<'a>() -> Alias<'a> { - &S - } +pub trait T { + type Item; +} + +pub type Alias<'a> = impl T; + +struct S; +impl<'a> T for &'a S { + type Item = &'a (); +} + +#[define_opaque(Alias)] +pub fn filter_positive<'a>() -> Alias<'a> { + &S } -use helper::*; fn with_positive(fun: impl Fn(Alias<'_>)) { fun(filter_positive()); From cb044d4d7b6d4b9f944a648b38c790e6fadae9b8 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 26 Jul 2024 10:04:02 +0000 Subject: [PATCH 149/745] Implement `#[define_opaque]` attribute for functions. --- clippy_utils/src/ast_utils/mod.rs | 6 ++++++ tests/ui/crashes/ice-10972-tait.rs | 10 ---------- tests/ui/implied_bounds_in_impls.fixed | 1 + tests/ui/implied_bounds_in_impls.rs | 1 + tests/ui/missing_const_for_fn/cant_be_const.rs | 1 + tests/ui/new_ret_no_self_overflow.rs | 1 + tests/ui/new_ret_no_self_overflow.stderr | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) delete mode 100644 tests/ui/crashes/ice-10972-tait.rs diff --git a/clippy_utils/src/ast_utils/mod.rs b/clippy_utils/src/ast_utils/mod.rs index 4f024ecaf29e..707312a97f3b 100644 --- a/clippy_utils/src/ast_utils/mod.rs +++ b/clippy_utils/src/ast_utils/mod.rs @@ -364,6 +364,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { generics: lg, contract: lc, body: lb, + define_opaque: _, }), Fn(box ast::Fn { defaultness: rd, @@ -371,6 +372,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { generics: rg, contract: rc, body: rb, + define_opaque: _, }), ) => { eq_defaultness(*ld, *rd) @@ -502,6 +504,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { generics: lg, contract: lc, body: lb, + define_opaque: _, }), Fn(box ast::Fn { defaultness: rd, @@ -509,6 +512,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { generics: rg, contract: rc, body: rb, + define_opaque: _, }), ) => { eq_defaultness(*ld, *rd) @@ -567,6 +571,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { generics: lg, contract: lc, body: lb, + define_opaque: _, }), Fn(box ast::Fn { defaultness: rd, @@ -574,6 +579,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { generics: rg, contract: rc, body: rb, + define_opaque: _, }), ) => { eq_defaultness(*ld, *rd) diff --git a/tests/ui/crashes/ice-10972-tait.rs b/tests/ui/crashes/ice-10972-tait.rs deleted file mode 100644 index 11ddbfc3a04b..000000000000 --- a/tests/ui/crashes/ice-10972-tait.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ check-pass -// ICE: #10972 -// asked to assemble constituent types of unexpected type: Binder(Foo, []) -#![feature(type_alias_impl_trait)] - -use std::fmt::Debug; -type Foo = impl Debug; -const FOO2: Foo = 22_u32; - -pub fn main() {} diff --git a/tests/ui/implied_bounds_in_impls.fixed b/tests/ui/implied_bounds_in_impls.fixed index bac7af59491f..4fe3fa4eab51 100644 --- a/tests/ui/implied_bounds_in_impls.fixed +++ b/tests/ui/implied_bounds_in_impls.fixed @@ -192,6 +192,7 @@ impl Atpit for () { type Tait = impl DerefMut; //~^ implied_bounds_in_impls +#[define_opaque(Tait)] fn define() -> Tait { &mut [] as &mut [()] } diff --git a/tests/ui/implied_bounds_in_impls.rs b/tests/ui/implied_bounds_in_impls.rs index 2014cd46ada7..6cc824db1107 100644 --- a/tests/ui/implied_bounds_in_impls.rs +++ b/tests/ui/implied_bounds_in_impls.rs @@ -192,6 +192,7 @@ impl Atpit for () { type Tait = impl Deref + DerefMut; //~^ implied_bounds_in_impls +#[define_opaque(Tait)] fn define() -> Tait { &mut [] as &mut [()] } diff --git a/tests/ui/missing_const_for_fn/cant_be_const.rs b/tests/ui/missing_const_for_fn/cant_be_const.rs index aef5eb5b890a..bd6339b78700 100644 --- a/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -207,6 +207,7 @@ mod msrv { mod with_ty_alias { type Foo = impl std::fmt::Debug; + #[define_opaque(Foo)] fn foo(_: Foo) { let _: Foo = 1; } diff --git a/tests/ui/new_ret_no_self_overflow.rs b/tests/ui/new_ret_no_self_overflow.rs index 8a85c5662276..f317674bc1ae 100644 --- a/tests/ui/new_ret_no_self_overflow.rs +++ b/tests/ui/new_ret_no_self_overflow.rs @@ -17,6 +17,7 @@ mod issue10041 { struct Bomb2; impl Bomb2 { + #[define_opaque(X)] pub fn new() -> X { //~^ ERROR: overflow evaluating the requirement 0i32 diff --git a/tests/ui/new_ret_no_self_overflow.stderr b/tests/ui/new_ret_no_self_overflow.stderr index 77c1b64ebc8e..8ecd0437e7db 100644 --- a/tests/ui/new_ret_no_self_overflow.stderr +++ b/tests/ui/new_ret_no_self_overflow.stderr @@ -1,5 +1,5 @@ error[E0275]: overflow evaluating the requirement `::Output == issue10041::X` - --> tests/ui/new_ret_no_self_overflow.rs:20:25 + --> tests/ui/new_ret_no_self_overflow.rs:21:25 | LL | pub fn new() -> X { | ^ From cb9682b628d81459ba825cef82ed3ee870f683b7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 11 Mar 2025 16:34:26 +0100 Subject: [PATCH 150/745] Add missing tests annotations for `ui-internal` --- .../check_clippy_version_attribute.rs | 4 +++ .../check_clippy_version_attribute.stderr | 19 +++++++------ tests/ui-internal/check_formulation.rs | 2 ++ tests/ui-internal/check_formulation.stderr | 2 +- .../collapsible_span_lint_calls.rs | 5 ++++ .../collapsible_span_lint_calls.stderr | 13 ++++++--- tests/ui-internal/default_lint.rs | 1 + tests/ui-internal/default_lint.stderr | 1 + tests/ui-internal/disallow_span_lint.rs | 2 ++ tests/ui-internal/disallow_span_lint.stderr | 2 +- .../interning_defined_symbol.fixed | 4 +++ tests/ui-internal/interning_defined_symbol.rs | 4 +++ .../interning_defined_symbol.stderr | 6 ++-- .../ui-internal/invalid_msrv_attr_impl.fixed | 1 + tests/ui-internal/invalid_msrv_attr_impl.rs | 1 + tests/ui-internal/invalid_paths.rs | 3 ++ tests/ui-internal/invalid_paths.stderr | 4 +-- tests/ui-internal/lint_without_lint_pass.rs | 1 + .../ui-internal/lint_without_lint_pass.stderr | 1 + tests/ui-internal/outer_expn_data.fixed | 1 + tests/ui-internal/outer_expn_data.rs | 1 + tests/ui-internal/unnecessary_def_path.fixed | 15 ++++++++++ tests/ui-internal/unnecessary_def_path.rs | 15 ++++++++++ tests/ui-internal/unnecessary_def_path.stderr | 28 +++++++++---------- .../unnecessary_def_path_hardcoded_path.rs | 3 ++ ...unnecessary_def_path_hardcoded_path.stderr | 4 +-- .../ui-internal/unnecessary_symbol_str.fixed | 5 ++++ tests/ui-internal/unnecessary_symbol_str.rs | 5 ++++ .../ui-internal/unnecessary_symbol_str.stderr | 8 +++--- 29 files changed, 121 insertions(+), 40 deletions(-) diff --git a/tests/ui-internal/check_clippy_version_attribute.rs b/tests/ui-internal/check_clippy_version_attribute.rs index 31acac89cc63..e5f6001b74d0 100644 --- a/tests/ui-internal/check_clippy_version_attribute.rs +++ b/tests/ui-internal/check_clippy_version_attribute.rs @@ -38,6 +38,7 @@ declare_tool_lint! { // Invalid attributes /////////////////////// declare_tool_lint! { +//~^ invalid_clippy_version_attribute #[clippy::version = "1.2.3.4.5.6"] pub clippy::INVALID_ONE, Warn, @@ -46,6 +47,7 @@ declare_tool_lint! { } declare_tool_lint! { +//~^ invalid_clippy_version_attribute #[clippy::version = "I'm a string"] pub clippy::INVALID_TWO, Warn, @@ -57,6 +59,7 @@ declare_tool_lint! { // Missing attribute test /////////////////////// declare_tool_lint! { +//~^ missing_clippy_version_attribute #[clippy::version] pub clippy::MISSING_ATTRIBUTE_ONE, Warn, @@ -65,6 +68,7 @@ declare_tool_lint! { } declare_tool_lint! { +//~^ missing_clippy_version_attribute pub clippy::MISSING_ATTRIBUTE_TWO, Warn, "Two", diff --git a/tests/ui-internal/check_clippy_version_attribute.stderr b/tests/ui-internal/check_clippy_version_attribute.stderr index 631c292f5249..1129c35d1d01 100644 --- a/tests/ui-internal/check_clippy_version_attribute.stderr +++ b/tests/ui-internal/check_clippy_version_attribute.stderr @@ -2,10 +2,10 @@ error: this item has an invalid `clippy::version` attribute --> tests/ui-internal/check_clippy_version_attribute.rs:40:1 | LL | / declare_tool_lint! { +LL | | LL | | #[clippy::version = "1.2.3.4.5.6"] LL | | pub clippy::INVALID_ONE, -LL | | Warn, -LL | | "One", +... | LL | | report_in_external_macro: true LL | | } | |_^ @@ -20,13 +20,13 @@ LL | #![deny(clippy::internal)] = note: this error originates in the macro `$crate::declare_tool_lint` which comes from the expansion of the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info) error: this item has an invalid `clippy::version` attribute - --> tests/ui-internal/check_clippy_version_attribute.rs:48:1 + --> tests/ui-internal/check_clippy_version_attribute.rs:49:1 | LL | / declare_tool_lint! { +LL | | LL | | #[clippy::version = "I'm a string"] LL | | pub clippy::INVALID_TWO, -LL | | Warn, -LL | | "Two", +... | LL | | report_in_external_macro: true LL | | } | |_^ @@ -35,13 +35,13 @@ LL | | } = note: this error originates in the macro `$crate::declare_tool_lint` which comes from the expansion of the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info) error: this lint is missing the `clippy::version` attribute or version value - --> tests/ui-internal/check_clippy_version_attribute.rs:59:1 + --> tests/ui-internal/check_clippy_version_attribute.rs:61:1 | LL | / declare_tool_lint! { +LL | | LL | | #[clippy::version] LL | | pub clippy::MISSING_ATTRIBUTE_ONE, -LL | | Warn, -LL | | "Two", +... | LL | | report_in_external_macro: true LL | | } | |_^ @@ -51,9 +51,10 @@ LL | | } = note: this error originates in the macro `$crate::declare_tool_lint` which comes from the expansion of the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info) error: this lint is missing the `clippy::version` attribute or version value - --> tests/ui-internal/check_clippy_version_attribute.rs:67:1 + --> tests/ui-internal/check_clippy_version_attribute.rs:70:1 | LL | / declare_tool_lint! { +LL | | LL | | pub clippy::MISSING_ATTRIBUTE_TWO, LL | | Warn, LL | | "Two", diff --git a/tests/ui-internal/check_formulation.rs b/tests/ui-internal/check_formulation.rs index 43fc996033ea..8265a78769d1 100644 --- a/tests/ui-internal/check_formulation.rs +++ b/tests/ui-internal/check_formulation.rs @@ -21,6 +21,7 @@ declare_tool_lint! { declare_tool_lint! { /// # What it does /// Check for lint formulations that are correct + //~^ almost_standard_lint_formulation #[clippy::version = "pre 1.29.0"] pub clippy::INVALID1, Warn, @@ -31,6 +32,7 @@ declare_tool_lint! { declare_tool_lint! { /// # What it does /// Detects uses of incorrect formulations + //~^ almost_standard_lint_formulation #[clippy::version = "pre 1.29.0"] pub clippy::INVALID2, Warn, diff --git a/tests/ui-internal/check_formulation.stderr b/tests/ui-internal/check_formulation.stderr index 12514370e6de..b16e1bf86873 100644 --- a/tests/ui-internal/check_formulation.stderr +++ b/tests/ui-internal/check_formulation.stderr @@ -9,7 +9,7 @@ LL | /// Check for lint formulations that are correct = help: to override `-D warnings` add `#[allow(clippy::almost_standard_lint_formulation)]` error: non-standard lint formulation - --> tests/ui-internal/check_formulation.rs:33:5 + --> tests/ui-internal/check_formulation.rs:34:5 | LL | /// Detects uses of incorrect formulations | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-internal/collapsible_span_lint_calls.rs b/tests/ui-internal/collapsible_span_lint_calls.rs index 1baf6142b349..2f289ae2b481 100644 --- a/tests/ui-internal/collapsible_span_lint_calls.rs +++ b/tests/ui-internal/collapsible_span_lint_calls.rs @@ -33,18 +33,23 @@ impl EarlyLintPass for Pass { let predicate = true; span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls db.span_suggestion(expr.span, help_msg, sugg.to_string(), Applicability::MachineApplicable); }); span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls db.span_help(expr.span, help_msg); }); span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls db.help(help_msg); }); span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls db.span_note(expr.span, note_msg); }); span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls db.note(note_msg); }); diff --git a/tests/ui-internal/collapsible_span_lint_calls.stderr b/tests/ui-internal/collapsible_span_lint_calls.stderr index 104995918de2..a2be1f1cd367 100644 --- a/tests/ui-internal/collapsible_span_lint_calls.stderr +++ b/tests/ui-internal/collapsible_span_lint_calls.stderr @@ -2,6 +2,7 @@ error: this call is collapsible --> tests/ui-internal/collapsible_span_lint_calls.rs:35:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | LL | | db.span_suggestion(expr.span, help_msg, sugg.to_string(), Applicability::MachineApplicable); LL | | }); | |__________^ help: collapse into: `span_lint_and_sugg(cx, TEST_LINT, expr.span, lint_msg, help_msg, sugg.to_string(), Applicability::MachineApplicable)` @@ -14,33 +15,37 @@ LL | #![deny(clippy::internal)] = note: `#[deny(clippy::collapsible_span_lint_calls)]` implied by `#[deny(clippy::internal)]` error: this call is collapsible - --> tests/ui-internal/collapsible_span_lint_calls.rs:38:9 + --> tests/ui-internal/collapsible_span_lint_calls.rs:39:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | LL | | db.span_help(expr.span, help_msg); LL | | }); | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), help_msg)` error: this call is collapsible - --> tests/ui-internal/collapsible_span_lint_calls.rs:41:9 + --> tests/ui-internal/collapsible_span_lint_calls.rs:43:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | LL | | db.help(help_msg); LL | | }); | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, help_msg)` error: this call is collapsible - --> tests/ui-internal/collapsible_span_lint_calls.rs:44:9 + --> tests/ui-internal/collapsible_span_lint_calls.rs:47:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | LL | | db.span_note(expr.span, note_msg); LL | | }); | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), note_msg)` error: this call is collapsible - --> tests/ui-internal/collapsible_span_lint_calls.rs:47:9 + --> tests/ui-internal/collapsible_span_lint_calls.rs:51:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | LL | | db.note(note_msg); LL | | }); | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, note_msg)` diff --git a/tests/ui-internal/default_lint.rs b/tests/ui-internal/default_lint.rs index da29aedb2a3a..959bfd27e389 100644 --- a/tests/ui-internal/default_lint.rs +++ b/tests/ui-internal/default_lint.rs @@ -16,6 +16,7 @@ declare_tool_lint! { } declare_tool_lint! { +//~^ default_lint pub clippy::TEST_LINT_DEFAULT, Warn, "default lint description", diff --git a/tests/ui-internal/default_lint.stderr b/tests/ui-internal/default_lint.stderr index c939125e875c..9d4c2e15349f 100644 --- a/tests/ui-internal/default_lint.stderr +++ b/tests/ui-internal/default_lint.stderr @@ -2,6 +2,7 @@ error: the lint `TEST_LINT_DEFAULT` has the default lint description --> tests/ui-internal/default_lint.rs:18:1 | LL | / declare_tool_lint! { +LL | | LL | | pub clippy::TEST_LINT_DEFAULT, LL | | Warn, LL | | "default lint description", diff --git a/tests/ui-internal/disallow_span_lint.rs b/tests/ui-internal/disallow_span_lint.rs index ca71dddcc24f..3fed38cab64d 100644 --- a/tests/ui-internal/disallow_span_lint.rs +++ b/tests/ui-internal/disallow_span_lint.rs @@ -12,12 +12,14 @@ use rustc_middle::ty::TyCtxt; pub fn a(cx: impl LintContext, lint: &'static Lint, span: impl Into, msg: impl Into) { cx.span_lint(lint, span, |lint| { + //~^ disallowed_methods lint.primary_message(msg); }); } pub fn b(tcx: TyCtxt<'_>, lint: &'static Lint, hir_id: HirId, span: impl Into, msg: impl Into) { tcx.node_span_lint(lint, hir_id, span, |lint| { + //~^ disallowed_methods lint.primary_message(msg); }); } diff --git a/tests/ui-internal/disallow_span_lint.stderr b/tests/ui-internal/disallow_span_lint.stderr index 16e1487f2bbc..9a7a7ecbbff9 100644 --- a/tests/ui-internal/disallow_span_lint.stderr +++ b/tests/ui-internal/disallow_span_lint.stderr @@ -9,7 +9,7 @@ LL | cx.span_lint(lint, span, |lint| { = help: to override `-D warnings` add `#[allow(clippy::disallowed_methods)]` error: use of a disallowed method `rustc_middle::ty::context::TyCtxt::node_span_lint` - --> tests/ui-internal/disallow_span_lint.rs:20:9 + --> tests/ui-internal/disallow_span_lint.rs:21:9 | LL | tcx.node_span_lint(lint, hir_id, span, |lint| { | ^^^^^^^^^^^^^^ diff --git a/tests/ui-internal/interning_defined_symbol.fixed b/tests/ui-internal/interning_defined_symbol.fixed index 3bcabb4ab2d3..92d3b1537e0c 100644 --- a/tests/ui-internal/interning_defined_symbol.fixed +++ b/tests/ui-internal/interning_defined_symbol.fixed @@ -15,15 +15,19 @@ macro_rules! sym { fn main() { // Direct use of Symbol::intern let _ = rustc_span::sym::f32; + //~^ interning_defined_symbol // Using a sym macro let _ = rustc_span::sym::f32; + //~^ interning_defined_symbol // Correct suggestion when symbol isn't stringified constant name let _ = rustc_span::sym::proc_dash_macro; + //~^ interning_defined_symbol // interning a keyword let _ = rustc_span::kw::SelfLower; + //~^ interning_defined_symbol // Interning a symbol that is not defined let _ = Symbol::intern("xyz123"); diff --git a/tests/ui-internal/interning_defined_symbol.rs b/tests/ui-internal/interning_defined_symbol.rs index 92e92d4fbc16..d1e6f9cb1c41 100644 --- a/tests/ui-internal/interning_defined_symbol.rs +++ b/tests/ui-internal/interning_defined_symbol.rs @@ -15,15 +15,19 @@ macro_rules! sym { fn main() { // Direct use of Symbol::intern let _ = Symbol::intern("f32"); + //~^ interning_defined_symbol // Using a sym macro let _ = sym!(f32); + //~^ interning_defined_symbol // Correct suggestion when symbol isn't stringified constant name let _ = Symbol::intern("proc-macro"); + //~^ interning_defined_symbol // interning a keyword let _ = Symbol::intern("self"); + //~^ interning_defined_symbol // Interning a symbol that is not defined let _ = Symbol::intern("xyz123"); diff --git a/tests/ui-internal/interning_defined_symbol.stderr b/tests/ui-internal/interning_defined_symbol.stderr index c4d0308979f6..c84a566436a8 100644 --- a/tests/ui-internal/interning_defined_symbol.stderr +++ b/tests/ui-internal/interning_defined_symbol.stderr @@ -12,19 +12,19 @@ LL | #![deny(clippy::internal)] = note: `#[deny(clippy::interning_defined_symbol)]` implied by `#[deny(clippy::internal)]` error: interning a defined symbol - --> tests/ui-internal/interning_defined_symbol.rs:20:13 + --> tests/ui-internal/interning_defined_symbol.rs:21:13 | LL | let _ = sym!(f32); | ^^^^^^^^^ help: try: `rustc_span::sym::f32` error: interning a defined symbol - --> tests/ui-internal/interning_defined_symbol.rs:23:13 + --> tests/ui-internal/interning_defined_symbol.rs:25:13 | LL | let _ = Symbol::intern("proc-macro"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `rustc_span::sym::proc_dash_macro` error: interning a defined symbol - --> tests/ui-internal/interning_defined_symbol.rs:26:13 + --> tests/ui-internal/interning_defined_symbol.rs:29:13 | LL | let _ = Symbol::intern("self"); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `rustc_span::kw::SelfLower` diff --git a/tests/ui-internal/invalid_msrv_attr_impl.fixed b/tests/ui-internal/invalid_msrv_attr_impl.fixed index 7011ef518f20..6804e2bbae83 100644 --- a/tests/ui-internal/invalid_msrv_attr_impl.fixed +++ b/tests/ui-internal/invalid_msrv_attr_impl.fixed @@ -27,6 +27,7 @@ impl_lint_pass!(Pass => [TEST_LINT]); impl EarlyLintPass for Pass { extract_msrv_attr!(); + //~^ missing_msrv_attr_impl fn check_expr(&mut self, _: &EarlyContext<'_>, _: &rustc_ast::Expr) {} } diff --git a/tests/ui-internal/invalid_msrv_attr_impl.rs b/tests/ui-internal/invalid_msrv_attr_impl.rs index 323061decd23..c625a5d9a459 100644 --- a/tests/ui-internal/invalid_msrv_attr_impl.rs +++ b/tests/ui-internal/invalid_msrv_attr_impl.rs @@ -26,6 +26,7 @@ struct Pass { impl_lint_pass!(Pass => [TEST_LINT]); impl EarlyLintPass for Pass { + //~^ missing_msrv_attr_impl fn check_expr(&mut self, _: &EarlyContext<'_>, _: &rustc_ast::Expr) {} } diff --git a/tests/ui-internal/invalid_paths.rs b/tests/ui-internal/invalid_paths.rs index 9a9790a4bae5..abfb111f938e 100644 --- a/tests/ui-internal/invalid_paths.rs +++ b/tests/ui-internal/invalid_paths.rs @@ -13,12 +13,15 @@ mod paths { // Path with empty segment pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"]; + //~^ invalid_paths // Path with bad crate pub const BAD_CRATE_PATH: [&str; 2] = ["bad", "path"]; + //~^ invalid_paths // Path with bad module pub const BAD_MOD_PATH: [&str; 2] = ["std", "xxx"]; + //~^ invalid_paths // Path to method on an enum inherent impl pub const OPTION_IS_SOME: [&str; 4] = ["core", "option", "Option", "is_some"]; diff --git a/tests/ui-internal/invalid_paths.stderr b/tests/ui-internal/invalid_paths.stderr index fc530a2efa37..7bde37667be4 100644 --- a/tests/ui-internal/invalid_paths.stderr +++ b/tests/ui-internal/invalid_paths.stderr @@ -8,13 +8,13 @@ LL | pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute" = help: to override `-D warnings` add `#[allow(clippy::invalid_paths)]` error: invalid path - --> tests/ui-internal/invalid_paths.rs:18:5 + --> tests/ui-internal/invalid_paths.rs:19:5 | LL | pub const BAD_CRATE_PATH: [&str; 2] = ["bad", "path"]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: invalid path - --> tests/ui-internal/invalid_paths.rs:21:5 + --> tests/ui-internal/invalid_paths.rs:23:5 | LL | pub const BAD_MOD_PATH: [&str; 2] = ["std", "xxx"]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-internal/lint_without_lint_pass.rs b/tests/ui-internal/lint_without_lint_pass.rs index d59e9cbbb617..69591523432c 100644 --- a/tests/ui-internal/lint_without_lint_pass.rs +++ b/tests/ui-internal/lint_without_lint_pass.rs @@ -10,6 +10,7 @@ extern crate rustc_lint; use rustc_lint::{LintPass, LintVec}; declare_tool_lint! { +//~^ lint_without_lint_pass pub clippy::TEST_LINT, Warn, "", diff --git a/tests/ui-internal/lint_without_lint_pass.stderr b/tests/ui-internal/lint_without_lint_pass.stderr index 187bba97fd41..9cca96ca1602 100644 --- a/tests/ui-internal/lint_without_lint_pass.stderr +++ b/tests/ui-internal/lint_without_lint_pass.stderr @@ -2,6 +2,7 @@ error: the lint `TEST_LINT` is not added to any `LintPass` --> tests/ui-internal/lint_without_lint_pass.rs:12:1 | LL | / declare_tool_lint! { +LL | | LL | | pub clippy::TEST_LINT, LL | | Warn, LL | | "", diff --git a/tests/ui-internal/outer_expn_data.fixed b/tests/ui-internal/outer_expn_data.fixed index cef16cf6ca5b..cb7680b8bb14 100644 --- a/tests/ui-internal/outer_expn_data.fixed +++ b/tests/ui-internal/outer_expn_data.fixed @@ -21,6 +21,7 @@ declare_lint_pass!(Pass => [TEST_LINT]); impl<'tcx> LateLintPass<'tcx> for Pass { fn check_expr(&mut self, _cx: &LateContext<'tcx>, expr: &'tcx Expr) { let _ = expr.span.ctxt().outer_expn_data(); + //~^ outer_expn_expn_data } } diff --git a/tests/ui-internal/outer_expn_data.rs b/tests/ui-internal/outer_expn_data.rs index fb453be661c8..41d735110b5a 100644 --- a/tests/ui-internal/outer_expn_data.rs +++ b/tests/ui-internal/outer_expn_data.rs @@ -21,6 +21,7 @@ declare_lint_pass!(Pass => [TEST_LINT]); impl<'tcx> LateLintPass<'tcx> for Pass { fn check_expr(&mut self, _cx: &LateContext<'tcx>, expr: &'tcx Expr) { let _ = expr.span.ctxt().outer_expn().expn_data(); + //~^ outer_expn_expn_data } } diff --git a/tests/ui-internal/unnecessary_def_path.fixed b/tests/ui-internal/unnecessary_def_path.fixed index d3fab60f9e3e..577fad9341b6 100644 --- a/tests/ui-internal/unnecessary_def_path.fixed +++ b/tests/ui-internal/unnecessary_def_path.fixed @@ -35,28 +35,43 @@ const RESULT: &[&str] = &["core", "result", "Result"]; fn _f<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, did: DefId, expr: &Expr<'_>) { let _ = is_type_diagnostic_item(cx, ty, sym::Option); + //~^ unnecessary_def_path let _ = is_type_diagnostic_item(cx, ty, sym::Result); + //~^ unnecessary_def_path let _ = is_type_diagnostic_item(cx, ty, sym::Result); + //~^ unnecessary_def_path #[allow(unused, clippy::unnecessary_def_path)] let rc_path = &["alloc", "rc", "Rc"]; let _ = is_type_diagnostic_item(cx, ty, sym::Rc); + //~^ unnecessary_def_path let _ = is_type_diagnostic_item(cx, ty, sym::Option); + //~^ unnecessary_def_path let _ = is_type_diagnostic_item(cx, ty, sym::Result); + //~^ unnecessary_def_path let _ = is_type_lang_item(cx, ty, LangItem::OwnedBox); + //~^ unnecessary_def_path let _ = is_type_diagnostic_item(cx, ty, sym::maybe_uninit_uninit); + //~^ unnecessary_def_path let _ = cx.tcx.lang_items().get(LangItem::OwnedBox) == Some(did); + //~^ unnecessary_def_path let _ = cx.tcx.is_diagnostic_item(sym::Option, did); + //~^ unnecessary_def_path let _ = cx.tcx.lang_items().get(LangItem::OptionSome) == Some(did); + //~^ unnecessary_def_path let _ = is_trait_method(cx, expr, sym::AsRef); + //~^ unnecessary_def_path let _ = is_path_diagnostic_item(cx, expr, sym::Option); + //~^ unnecessary_def_path let _ = path_res(cx, expr).opt_def_id().map_or(false, |id| cx.tcx.lang_items().get(LangItem::IteratorNext) == Some(id)); + //~^ unnecessary_def_path let _ = is_res_lang_ctor(cx, path_res(cx, expr), LangItem::OptionSome); + //~^ unnecessary_def_path } fn main() {} diff --git a/tests/ui-internal/unnecessary_def_path.rs b/tests/ui-internal/unnecessary_def_path.rs index 1b36f6b09e9c..d4deb3626d0b 100644 --- a/tests/ui-internal/unnecessary_def_path.rs +++ b/tests/ui-internal/unnecessary_def_path.rs @@ -35,28 +35,43 @@ const RESULT: &[&str] = &["core", "result", "Result"]; fn _f<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, did: DefId, expr: &Expr<'_>) { let _ = match_type(cx, ty, &OPTION); + //~^ unnecessary_def_path let _ = match_type(cx, ty, RESULT); + //~^ unnecessary_def_path let _ = match_type(cx, ty, &["core", "result", "Result"]); + //~^ unnecessary_def_path #[allow(unused, clippy::unnecessary_def_path)] let rc_path = &["alloc", "rc", "Rc"]; let _ = clippy_utils::ty::match_type(cx, ty, rc_path); + //~^ unnecessary_def_path let _ = match_type(cx, ty, &paths::OPTION); + //~^ unnecessary_def_path let _ = match_type(cx, ty, paths::RESULT); + //~^ unnecessary_def_path let _ = match_type(cx, ty, &["alloc", "boxed", "Box"]); + //~^ unnecessary_def_path let _ = match_type(cx, ty, &["core", "mem", "maybe_uninit", "MaybeUninit", "uninit"]); + //~^ unnecessary_def_path let _ = match_def_path(cx, did, &["alloc", "boxed", "Box"]); + //~^ unnecessary_def_path let _ = match_def_path(cx, did, &["core", "option", "Option"]); + //~^ unnecessary_def_path let _ = match_def_path(cx, did, &["core", "option", "Option", "Some"]); + //~^ unnecessary_def_path let _ = match_trait_method(cx, expr, &["core", "convert", "AsRef"]); + //~^ unnecessary_def_path let _ = is_expr_path_def_path(cx, expr, &["core", "option", "Option"]); + //~^ unnecessary_def_path let _ = is_expr_path_def_path(cx, expr, &["core", "iter", "traits", "Iterator", "next"]); + //~^ unnecessary_def_path let _ = is_expr_path_def_path(cx, expr, &["core", "option", "Option", "Some"]); + //~^ unnecessary_def_path } fn main() {} diff --git a/tests/ui-internal/unnecessary_def_path.stderr b/tests/ui-internal/unnecessary_def_path.stderr index 79521c5037a8..0053ba321bbe 100644 --- a/tests/ui-internal/unnecessary_def_path.stderr +++ b/tests/ui-internal/unnecessary_def_path.stderr @@ -12,61 +12,61 @@ LL | #![deny(clippy::internal)] = note: `#[deny(clippy::unnecessary_def_path)]` implied by `#[deny(clippy::internal)]` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:38:13 + --> tests/ui-internal/unnecessary_def_path.rs:39:13 | LL | let _ = match_type(cx, ty, RESULT); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Result)` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:39:13 + --> tests/ui-internal/unnecessary_def_path.rs:41:13 | LL | let _ = match_type(cx, ty, &["core", "result", "Result"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Result)` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:43:13 + --> tests/ui-internal/unnecessary_def_path.rs:46:13 | LL | let _ = clippy_utils::ty::match_type(cx, ty, rc_path); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Rc)` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:45:13 + --> tests/ui-internal/unnecessary_def_path.rs:49:13 | LL | let _ = match_type(cx, ty, &paths::OPTION); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Option)` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:46:13 + --> tests/ui-internal/unnecessary_def_path.rs:51:13 | LL | let _ = match_type(cx, ty, paths::RESULT); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Result)` error: use of a def path to a `LangItem` - --> tests/ui-internal/unnecessary_def_path.rs:48:13 + --> tests/ui-internal/unnecessary_def_path.rs:54:13 | LL | let _ = match_type(cx, ty, &["alloc", "boxed", "Box"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_lang_item(cx, ty, LangItem::OwnedBox)` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:49:13 + --> tests/ui-internal/unnecessary_def_path.rs:56:13 | LL | let _ = match_type(cx, ty, &["core", "mem", "maybe_uninit", "MaybeUninit", "uninit"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::maybe_uninit_uninit)` error: use of a def path to a `LangItem` - --> tests/ui-internal/unnecessary_def_path.rs:51:13 + --> tests/ui-internal/unnecessary_def_path.rs:59:13 | LL | let _ = match_def_path(cx, did, &["alloc", "boxed", "Box"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.lang_items().get(LangItem::OwnedBox) == Some(did)` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:52:13 + --> tests/ui-internal/unnecessary_def_path.rs:61:13 | LL | let _ = match_def_path(cx, did, &["core", "option", "Option"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.is_diagnostic_item(sym::Option, did)` error: use of a def path to a `LangItem` - --> tests/ui-internal/unnecessary_def_path.rs:53:13 + --> tests/ui-internal/unnecessary_def_path.rs:63:13 | LL | let _ = match_def_path(cx, did, &["core", "option", "Option", "Some"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.lang_items().get(LangItem::OptionSome) == Some(did)` @@ -74,25 +74,25 @@ LL | let _ = match_def_path(cx, did, &["core", "option", "Option", "Some"]); = help: if this `DefId` came from a constructor expression or pattern then the parent `DefId` should be used instead error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:55:13 + --> tests/ui-internal/unnecessary_def_path.rs:66:13 | LL | let _ = match_trait_method(cx, expr, &["core", "convert", "AsRef"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_trait_method(cx, expr, sym::AsRef)` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:57:13 + --> tests/ui-internal/unnecessary_def_path.rs:69:13 | LL | let _ = is_expr_path_def_path(cx, expr, &["core", "option", "Option"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_path_diagnostic_item(cx, expr, sym::Option)` error: use of a def path to a `LangItem` - --> tests/ui-internal/unnecessary_def_path.rs:58:13 + --> tests/ui-internal/unnecessary_def_path.rs:71:13 | LL | let _ = is_expr_path_def_path(cx, expr, &["core", "iter", "traits", "Iterator", "next"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `path_res(cx, expr).opt_def_id().map_or(false, |id| cx.tcx.lang_items().get(LangItem::IteratorNext) == Some(id))` error: use of a def path to a `LangItem` - --> tests/ui-internal/unnecessary_def_path.rs:59:13 + --> tests/ui-internal/unnecessary_def_path.rs:73:13 | LL | let _ = is_expr_path_def_path(cx, expr, &["core", "option", "Option", "Some"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_res_lang_ctor(cx, path_res(cx, expr), LangItem::OptionSome)` diff --git a/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs b/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs index f6abb3cc3d71..4801d76bd268 100644 --- a/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs +++ b/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs @@ -8,8 +8,11 @@ use rustc_hir::LangItem; fn main() { const DEREF_TRAIT: [&str; 4] = ["core", "ops", "deref", "Deref"]; + //~^ unnecessary_def_path const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"]; + //~^ unnecessary_def_path const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"]; + //~^ unnecessary_def_path // Don't lint, not a diagnostic or language item const OPS_MOD: [&str; 2] = ["core", "ops"]; diff --git a/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr b/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr index e4575d99d03a..ff4726de69af 100644 --- a/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr +++ b/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr @@ -9,7 +9,7 @@ LL | const DEREF_TRAIT: [&str; 4] = ["core", "ops", "deref", "Deref"]; = help: to override `-D warnings` add `#[allow(clippy::unnecessary_def_path)]` error: hardcoded path to a language item - --> tests/ui-internal/unnecessary_def_path_hardcoded_path.rs:11:40 + --> tests/ui-internal/unnecessary_def_path_hardcoded_path.rs:12:40 | LL | const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"] = help: convert all references to use `LangItem::DerefMut` error: hardcoded path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path_hardcoded_path.rs:12:43 + --> tests/ui-internal/unnecessary_def_path_hardcoded_path.rs:14:43 | LL | const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-internal/unnecessary_symbol_str.fixed b/tests/ui-internal/unnecessary_symbol_str.fixed index 3d9deb705ace..dc564daef829 100644 --- a/tests/ui-internal/unnecessary_symbol_str.fixed +++ b/tests/ui-internal/unnecessary_symbol_str.fixed @@ -14,8 +14,13 @@ use rustc_span::symbol::{Ident, Symbol}; fn main() { Symbol::intern("foo") == rustc_span::sym::clippy; + //~^ unnecessary_symbol_str Symbol::intern("foo") == rustc_span::kw::SelfLower; + //~^ unnecessary_symbol_str Symbol::intern("foo") != rustc_span::kw::SelfUpper; + //~^ unnecessary_symbol_str Ident::empty().name == rustc_span::sym::clippy; + //~^ unnecessary_symbol_str rustc_span::sym::clippy == Ident::empty().name; + //~^ unnecessary_symbol_str } diff --git a/tests/ui-internal/unnecessary_symbol_str.rs b/tests/ui-internal/unnecessary_symbol_str.rs index 9aeeb9aaf3aa..d74262d1294b 100644 --- a/tests/ui-internal/unnecessary_symbol_str.rs +++ b/tests/ui-internal/unnecessary_symbol_str.rs @@ -14,8 +14,13 @@ use rustc_span::symbol::{Ident, Symbol}; fn main() { Symbol::intern("foo").as_str() == "clippy"; + //~^ unnecessary_symbol_str Symbol::intern("foo").to_string() == "self"; + //~^ unnecessary_symbol_str Symbol::intern("foo").to_ident_string() != "Self"; + //~^ unnecessary_symbol_str &*Ident::empty().as_str() == "clippy"; + //~^ unnecessary_symbol_str "clippy" == Ident::empty().to_string(); + //~^ unnecessary_symbol_str } diff --git a/tests/ui-internal/unnecessary_symbol_str.stderr b/tests/ui-internal/unnecessary_symbol_str.stderr index 1742603eff6d..517a395e93f2 100644 --- a/tests/ui-internal/unnecessary_symbol_str.stderr +++ b/tests/ui-internal/unnecessary_symbol_str.stderr @@ -12,25 +12,25 @@ LL | #![deny(clippy::internal)] = note: `#[deny(clippy::unnecessary_symbol_str)]` implied by `#[deny(clippy::internal)]` error: unnecessary `Symbol` to string conversion - --> tests/ui-internal/unnecessary_symbol_str.rs:17:5 + --> tests/ui-internal/unnecessary_symbol_str.rs:18:5 | LL | Symbol::intern("foo").to_string() == "self"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Symbol::intern("foo") == rustc_span::kw::SelfLower` error: unnecessary `Symbol` to string conversion - --> tests/ui-internal/unnecessary_symbol_str.rs:18:5 + --> tests/ui-internal/unnecessary_symbol_str.rs:20:5 | LL | Symbol::intern("foo").to_ident_string() != "Self"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Symbol::intern("foo") != rustc_span::kw::SelfUpper` error: unnecessary `Symbol` to string conversion - --> tests/ui-internal/unnecessary_symbol_str.rs:19:5 + --> tests/ui-internal/unnecessary_symbol_str.rs:22:5 | LL | &*Ident::empty().as_str() == "clippy"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Ident::empty().name == rustc_span::sym::clippy` error: unnecessary `Symbol` to string conversion - --> tests/ui-internal/unnecessary_symbol_str.rs:20:5 + --> tests/ui-internal/unnecessary_symbol_str.rs:24:5 | LL | "clippy" == Ident::empty().to_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `rustc_span::sym::clippy == Ident::empty().name` From 85b1116a18595794da07c53642eefd81ff775faf Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 10 Mar 2025 15:58:41 +0000 Subject: [PATCH 151/745] rustdoc: Add FIXME test for `doc_cfg` interaction with `check_cfg` --- tests/rustdoc-ui/doc-cfg-check-cfg.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 tests/rustdoc-ui/doc-cfg-check-cfg.rs diff --git a/tests/rustdoc-ui/doc-cfg-check-cfg.rs b/tests/rustdoc-ui/doc-cfg-check-cfg.rs new file mode 100644 index 000000000000..e3420dc07897 --- /dev/null +++ b/tests/rustdoc-ui/doc-cfg-check-cfg.rs @@ -0,0 +1,16 @@ +// Ensure that `doc(cfg())` respects `check-cfg` +// Currently not properly working +#![feature(doc_cfg)] +#![deny(unexpected_cfgs)] + +//@revisions: no_check cfg_empty cfg_foo +//@[cfg_empty] compile-flags: --check-cfg cfg() +//@[cfg_foo] compile-flags: --check-cfg cfg(foo) + +//@[no_check] check-pass +//@[cfg_empty] check-pass +//@[cfg_empty] known-bug: #138358 +//@[cfg_foo] check-pass + +#[doc(cfg(foo))] +pub fn foo() {} From 60805dc7e48171164af2e311a160bbbfa3baf6cb Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Sat, 8 Feb 2025 17:45:05 -0800 Subject: [PATCH 152/745] Deduplicate platform stdio types --- library/std/src/sys/stdio/solid.rs | 59 ++++-------------------- library/std/src/sys/stdio/teeos.rs | 55 ++++++---------------- library/std/src/sys/stdio/unsupported.rs | 18 +------- library/std/src/sys/stdio/xous.rs | 27 ++++------- 4 files changed, 32 insertions(+), 127 deletions(-) diff --git a/library/std/src/sys/stdio/solid.rs b/library/std/src/sys/stdio/solid.rs index a2ff4bb212ff..55daf0b54b92 100644 --- a/library/std/src/sys/stdio/solid.rs +++ b/library/std/src/sys/stdio/solid.rs @@ -1,22 +1,13 @@ +#[expect(dead_code)] +#[path = "unsupported.rs"] +mod unsupported_stdio; + use crate::io; use crate::sys::pal::abi; -pub struct Stdin; +pub type Stdin = unsupported_stdio::Stdin; pub struct Stdout; -pub struct Stderr; -struct PanicOutput; - -impl Stdin { - pub const fn new() -> Stdin { - Stdin - } -} - -impl io::Read for Stdin { - fn read(&mut self, _buf: &mut [u8]) -> io::Result { - Ok(0) - } -} +pub type Stderr = Stdout; impl Stdout { pub const fn new() -> Stdout { @@ -35,46 +26,12 @@ impl io::Write for Stdout { } } -impl Stderr { - pub const fn new() -> Stderr { - Stderr - } -} - -impl io::Write for Stderr { - fn write(&mut self, buf: &[u8]) -> io::Result { - unsafe { abi::SOLID_LOG_write(buf.as_ptr(), buf.len()) }; - Ok(buf.len()) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -impl PanicOutput { - pub const fn new() -> PanicOutput { - PanicOutput - } -} - -impl io::Write for PanicOutput { - fn write(&mut self, buf: &[u8]) -> io::Result { - unsafe { abi::SOLID_LOG_write(buf.as_ptr(), buf.len()) }; - Ok(buf.len()) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -pub const STDIN_BUF_SIZE: usize = 0; +pub const STDIN_BUF_SIZE: usize = unsupported_stdio::STDIN_BUF_SIZE; pub fn is_ebadf(_err: &io::Error) -> bool { true } pub fn panic_output() -> Option { - Some(PanicOutput::new()) + Some(Stderr::new()) } diff --git a/library/std/src/sys/stdio/teeos.rs b/library/std/src/sys/stdio/teeos.rs index 67e251812da7..27b3292bf8f0 100644 --- a/library/std/src/sys/stdio/teeos.rs +++ b/library/std/src/sys/stdio/teeos.rs @@ -1,12 +1,16 @@ #![deny(unsafe_op_in_unsafe_fn)] +#[expect(dead_code)] +#[path = "unsupported.rs"] +mod unsupported_stdio; + use core::arch::asm; use crate::io; -pub struct Stdin; +pub type Stdin = unsupported_stdio::Stdin; pub struct Stdout; -pub struct Stderr; +pub type Stderr = Stdout; const KCALL_DEBUG_CMD_PUT_BYTES: i64 = 2; @@ -25,27 +29,6 @@ unsafe fn debug_call(cap_ref: u64, call_no: i64, arg1: u64, arg2: u64) -> i32 { ret as i32 } -fn print_buf(s: &[u8]) -> io::Result { - // Corresponds to `HM_DEBUG_PUT_BYTES_LIMIT`. - const MAX_LEN: usize = 512; - let len = if s.len() > MAX_LEN { MAX_LEN } else { s.len() }; - let result = unsafe { debug_call(0, KCALL_DEBUG_CMD_PUT_BYTES, s.as_ptr() as u64, len as u64) }; - - if result == 0 { Ok(len) } else { Err(io::Error::from(io::ErrorKind::InvalidInput)) } -} - -impl Stdin { - pub const fn new() -> Stdin { - Stdin - } -} - -impl io::Read for Stdin { - fn read(&mut self, _buf: &mut [u8]) -> io::Result { - Ok(0) - } -} - impl Stdout { pub const fn new() -> Stdout { Stdout @@ -54,7 +37,13 @@ impl Stdout { impl io::Write for Stdout { fn write(&mut self, buf: &[u8]) -> io::Result { - print_buf(buf) + // Corresponds to `HM_DEBUG_PUT_BYTES_LIMIT`. + const MAX_LEN: usize = 512; + let len = buf.len().min(MAX_LEN); + let result = + unsafe { debug_call(0, KCALL_DEBUG_CMD_PUT_BYTES, buf.as_ptr() as u64, len as u64) }; + + if result == 0 { Ok(len) } else { Err(io::Error::from(io::ErrorKind::InvalidInput)) } } fn flush(&mut self) -> io::Result<()> { @@ -62,23 +51,7 @@ impl io::Write for Stdout { } } -impl Stderr { - pub const fn new() -> Stderr { - Stderr - } -} - -impl io::Write for Stderr { - fn write(&mut self, buf: &[u8]) -> io::Result { - print_buf(buf) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -pub const STDIN_BUF_SIZE: usize = 0; +pub const STDIN_BUF_SIZE: usize = unsupported_stdio::STDIN_BUF_SIZE; pub fn is_ebadf(err: &io::Error) -> bool { err.raw_os_error() == Some(libc::EBADF as i32) diff --git a/library/std/src/sys/stdio/unsupported.rs b/library/std/src/sys/stdio/unsupported.rs index b5e3f5be9885..67f7c1b7efb9 100644 --- a/library/std/src/sys/stdio/unsupported.rs +++ b/library/std/src/sys/stdio/unsupported.rs @@ -2,7 +2,7 @@ use crate::io; pub struct Stdin; pub struct Stdout; -pub struct Stderr; +pub type Stderr = Stdout; impl Stdin { pub const fn new() -> Stdin { @@ -32,22 +32,6 @@ impl io::Write for Stdout { } } -impl Stderr { - pub const fn new() -> Stderr { - Stderr - } -} - -impl io::Write for Stderr { - fn write(&mut self, buf: &[u8]) -> io::Result { - Ok(buf.len()) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - pub const STDIN_BUF_SIZE: usize = 0; pub fn is_ebadf(_err: &io::Error) -> bool { diff --git a/library/std/src/sys/stdio/xous.rs b/library/std/src/sys/stdio/xous.rs index 717361452213..a92167642b70 100644 --- a/library/std/src/sys/stdio/xous.rs +++ b/library/std/src/sys/stdio/xous.rs @@ -1,27 +1,18 @@ +#[expect(dead_code)] +#[path = "unsupported.rs"] +mod unsupported_stdio; + use crate::io; - -pub struct Stdin; -pub struct Stdout {} -pub struct Stderr; - use crate::os::xous::ffi::{Connection, lend, try_lend, try_scalar}; use crate::os::xous::services::{LogLend, LogScalar, log_server, try_connect}; -impl Stdin { - pub const fn new() -> Stdin { - Stdin - } -} - -impl io::Read for Stdin { - fn read(&mut self, _buf: &mut [u8]) -> io::Result { - Ok(0) - } -} +pub type Stdin = unsupported_stdio::Stdin; +pub struct Stdout; +pub struct Stderr; impl Stdout { pub const fn new() -> Stdout { - Stdout {} + Stdout } } @@ -73,7 +64,7 @@ impl io::Write for Stderr { } } -pub const STDIN_BUF_SIZE: usize = 0; +pub const STDIN_BUF_SIZE: usize = unsupported_stdio::STDIN_BUF_SIZE; pub fn is_ebadf(_err: &io::Error) -> bool { true From 650b7d957b463bd760cfa7fdbc42619c172a7626 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 21 Feb 2025 18:33:05 +1100 Subject: [PATCH 153/745] Move methods from `Map` to `TyCtxt`, part 4. Continuing the work from #137350. Removes the unused methods: `expect_variant`, `expect_field`, `expect_foreign_item`. Every method gains a `hir_` prefix. --- clippy_lints/src/attrs/mod.rs | 6 ++--- .../src/default_union_representation.rs | 2 +- clippy_lints/src/derivable_impls.rs | 4 ++-- clippy_lints/src/derive.rs | 2 +- clippy_lints/src/doc/missing_headers.rs | 2 +- clippy_lints/src/escape.rs | 3 +-- clippy_lints/src/exhaustive_items.rs | 2 +- clippy_lints/src/format_impl.rs | 3 +-- clippy_lints/src/four_forward_slashes.rs | 3 +-- clippy_lints/src/functions/must_use.rs | 6 ++--- .../src/inconsistent_struct_constructor.rs | 2 +- clippy_lints/src/inline_fn_without_body.rs | 3 +-- clippy_lints/src/macro_use.rs | 2 +- clippy_lints/src/manual_non_exhaustive.rs | 6 ++--- .../src/matches/match_like_matches.rs | 2 +- clippy_lints/src/matches/match_same_arms.rs | 2 +- clippy_lints/src/methods/is_empty.rs | 2 +- clippy_lints/src/methods/mod.rs | 2 +- clippy_lints/src/missing_doc.rs | 12 +++++----- clippy_lints/src/missing_inline.rs | 6 ++--- .../src/mixed_read_write_in_expression.rs | 2 +- clippy_lints/src/needless_if.rs | 2 +- clippy_lints/src/needless_late_init.rs | 2 +- clippy_lints/src/needless_pass_by_ref_mut.rs | 2 +- clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_lints/src/no_mangle_with_rust_abi.rs | 2 +- clippy_lints/src/non_copy_const.rs | 2 +- clippy_lints/src/operators/op_ref.rs | 4 ++-- clippy_lints/src/pass_by_ref_or_value.rs | 2 +- clippy_lints/src/pub_underscore_fields.rs | 2 +- clippy_lints/src/read_zero_byte_vec.rs | 2 +- clippy_lints/src/return_self_not_must_use.rs | 2 +- clippy_lints/src/returns.rs | 4 ++-- clippy_lints/src/self_named_constructors.rs | 2 +- .../src/undocumented_unsafe_blocks.rs | 3 +-- clippy_lints/src/unused_self.rs | 2 +- clippy_lints/src/unwrap.rs | 2 +- clippy_lints/src/utils/author.rs | 2 +- clippy_lints/src/utils/dump_hir.rs | 2 +- .../internal_lints/lint_without_lint_pass.rs | 2 +- clippy_utils/src/lib.rs | 22 +++++++------------ clippy_utils/src/msrvs.rs | 2 +- clippy_utils/src/sugg.rs | 4 ++-- 43 files changed, 67 insertions(+), 78 deletions(-) diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs index 2b59c218d57a..f9a2f011a144 100644 --- a/clippy_lints/src/attrs/mod.rs +++ b/clippy_lints/src/attrs/mod.rs @@ -465,7 +465,7 @@ impl Attributes { impl<'tcx> LateLintPass<'tcx> for Attributes { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - let attrs = cx.tcx.hir().attrs(item.hir_id()); + let attrs = cx.tcx.hir_attrs(item.hir_id()); if is_relevant_item(cx, item) { inline_always::check(cx, item.span, item.ident.name, attrs); } @@ -474,13 +474,13 @@ impl<'tcx> LateLintPass<'tcx> for Attributes { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) { if is_relevant_impl(cx, item) { - inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id())); + inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir_attrs(item.hir_id())); } } fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { if is_relevant_trait(cx, item) { - inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id())); + inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir_attrs(item.hir_id())); } } } diff --git a/clippy_lints/src/default_union_representation.rs b/clippy_lints/src/default_union_representation.rs index 085ed9222c91..7c64bf46e7bd 100644 --- a/clippy_lints/src/default_union_representation.rs +++ b/clippy_lints/src/default_union_representation.rs @@ -97,7 +97,7 @@ fn is_zst<'tcx>(cx: &LateContext<'tcx>, field: &FieldDef, args: ty::GenericArgsR } fn has_c_repr_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool { - let attrs = cx.tcx.hir().attrs(hir_id); + let attrs = cx.tcx.hir_attrs(hir_id); find_attr!(attrs, AttributeKind::Repr(r) if r.iter().any(|(x, _)| *x == ReprAttr::ReprC)) } diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs index 66a3e5e3d3c7..8d9222e4bf61 100644 --- a/clippy_lints/src/derivable_impls.rs +++ b/clippy_lints/src/derivable_impls.rs @@ -197,9 +197,9 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls { && let ImplItemKind::Fn(_, b) = &impl_item.kind && let Body { value: func_expr, .. } = cx.tcx.hir_body(*b) && let &ty::Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind() - && let attrs = cx.tcx.hir().attrs(item.hir_id()) + && let attrs = cx.tcx.hir_attrs(item.hir_id()) && !attrs.iter().any(|attr| attr.doc_str().is_some()) - && cx.tcx.hir().attrs(impl_item_hir).is_empty() + && cx.tcx.hir_attrs(impl_item_hir).is_empty() { if adt_def.is_struct() { check_struct(cx, item, self_ty, func_expr, adt_def, args, cx.tcx.typeck_body(*b)); diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index db3e6034c5ba..2ae35b400557 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -384,7 +384,7 @@ fn check_unsafe_derive_deserialize<'tcx>( .tcx .inherent_impls(def.did()) .iter() - .map(|imp_did| cx.tcx.hir().expect_item(imp_did.expect_local())) + .map(|imp_did| cx.tcx.hir_expect_item(imp_did.expect_local())) .any(|imp| has_unsafe(cx, imp)) { span_lint_hir_and_then( diff --git a/clippy_lints/src/doc/missing_headers.rs b/clippy_lints/src/doc/missing_headers.rs index e8638595c4b2..e75abf28bace 100644 --- a/clippy_lints/src/doc/missing_headers.rs +++ b/clippy_lints/src/doc/missing_headers.rs @@ -25,7 +25,7 @@ pub fn check( && cx .tcx .hir_parent_iter(owner_id.into()) - .any(|(id, _node)| is_doc_hidden(cx.tcx.hir().attrs(id))) + .any(|(id, _node)| is_doc_hidden(cx.tcx.hir_attrs(id))) { return; } diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 33ba401d60c2..9298f56b68be 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -163,7 +163,6 @@ impl<'tcx> Delegate<'tcx> for EscapeDelegate<'_, 'tcx> { fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId) { if cmt.place.projections.is_empty() { - let map = &self.cx.tcx.hir(); if is_argument(self.cx.tcx, cmt.hir_id) { // Skip closure arguments let parent_id = self.cx.tcx.parent_hir_id(cmt.hir_id); @@ -174,7 +173,7 @@ impl<'tcx> Delegate<'tcx> for EscapeDelegate<'_, 'tcx> { // skip if there is a `self` parameter binding to a type // that contains `Self` (i.e.: `self: Box`), see #4804 if let Some(trait_self_ty) = self.trait_self_ty { - if map.name(cmt.hir_id) == kw::SelfLower && cmt.place.ty().contains(trait_self_ty) { + if self.cx.tcx.hir_name(cmt.hir_id) == kw::SelfLower && cmt.place.ty().contains(trait_self_ty) { return; } } diff --git a/clippy_lints/src/exhaustive_items.rs b/clippy_lints/src/exhaustive_items.rs index 9bf3baba4b59..591912cc8d5e 100644 --- a/clippy_lints/src/exhaustive_items.rs +++ b/clippy_lints/src/exhaustive_items.rs @@ -84,7 +84,7 @@ impl LateLintPass<'_> for ExhaustiveItems { _ => return, }; if cx.effective_visibilities.is_exported(item.owner_id.def_id) - && let attrs = cx.tcx.hir().attrs(item.hir_id()) + && let attrs = cx.tcx.hir_attrs(item.hir_id()) && !attrs.iter().any(|a| a.has_name(sym::non_exhaustive)) && fields.iter().all(|f| cx.tcx.visibility(f.def_id).is_public()) { diff --git a/clippy_lints/src/format_impl.rs b/clippy_lints/src/format_impl.rs index ff75fcf2b417..5b42a40d850b 100644 --- a/clippy_lints/src/format_impl.rs +++ b/clippy_lints/src/format_impl.rs @@ -209,9 +209,8 @@ impl FormatImplExpr<'_, '_> { // Handle dereference of &self -> self that is equivalent (i.e. via *self in fmt() impl) // Since the argument to fmt is itself a reference: &self let reference = peel_ref_operators(self.cx, arg); - let map = self.cx.tcx.hir(); // Is the reference self? - if path_to_local(reference).map(|x| map.name(x)) == Some(kw::SelfLower) { + if path_to_local(reference).map(|x| self.cx.tcx.hir_name(x)) == Some(kw::SelfLower) { let FormatTraitNames { name, .. } = self.format_trait_impl; span_lint( self.cx, diff --git a/clippy_lints/src/four_forward_slashes.rs b/clippy_lints/src/four_forward_slashes.rs index 0bdb99d7b9a4..8822b87f92f7 100644 --- a/clippy_lints/src/four_forward_slashes.rs +++ b/clippy_lints/src/four_forward_slashes.rs @@ -43,8 +43,7 @@ impl<'tcx> LateLintPass<'tcx> for FourForwardSlashes { let sm = cx.sess().source_map(); let mut span = cx .tcx - .hir() - .attrs(item.hir_id()) + .hir_attrs(item.hir_id()) .iter() .filter(|i| i.is_doc_comment()) .fold(item.span.shrink_to_lo(), |span, attr| span.to(attr.span())); diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs index f1c9657f2240..c3e0d5e8b694 100644 --- a/clippy_lints/src/functions/must_use.rs +++ b/clippy_lints/src/functions/must_use.rs @@ -21,7 +21,7 @@ use core::ops::ControlFlow; use super::{DOUBLE_MUST_USE, MUST_USE_CANDIDATE, MUST_USE_UNIT}; pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { - let attrs = cx.tcx.hir().attrs(item.hir_id()); + let attrs = cx.tcx.hir_attrs(item.hir_id()); let attr = cx.tcx.get_attr(item.owner_id, sym::must_use); if let hir::ItemKind::Fn { ref sig, @@ -51,7 +51,7 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp if let hir::ImplItemKind::Fn(ref sig, ref body_id) = item.kind { let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); - let attrs = cx.tcx.hir().attrs(item.hir_id()); + let attrs = cx.tcx.hir_attrs(item.hir_id()); let attr = cx.tcx.get_attr(item.owner_id, sym::must_use); if let Some(attr) = attr { check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, attrs, sig); @@ -74,7 +74,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); - let attrs = cx.tcx.hir().attrs(item.hir_id()); + let attrs = cx.tcx.hir_attrs(item.hir_id()); let attr = cx.tcx.get_attr(item.owner_id, sym::must_use); if let Some(attr) = attr { check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, attrs, sig); diff --git a/clippy_lints/src/inconsistent_struct_constructor.rs b/clippy_lints/src/inconsistent_struct_constructor.rs index 5b58113169b1..e1dd7872b9d4 100644 --- a/clippy_lints/src/inconsistent_struct_constructor.rs +++ b/clippy_lints/src/inconsistent_struct_constructor.rs @@ -182,7 +182,7 @@ fn suggestion<'tcx>( } fn field_with_attrs_span(tcx: TyCtxt<'_>, field: &hir::ExprField<'_>) -> Span { - if let Some(attr) = tcx.hir().attrs(field.hir_id).first() { + if let Some(attr) = tcx.hir_attrs(field.hir_id).first() { field.span.with_lo(attr.span().lo()) } else { field.span diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index 9b4a3b3f9c84..6a436fb4a9d1 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -34,8 +34,7 @@ impl<'tcx> LateLintPass<'tcx> for InlineFnWithoutBody { if let TraitItemKind::Fn(_, TraitFn::Required(_)) = item.kind && let Some(attr) = cx .tcx - .hir() - .attrs(item.hir_id()) + .hir_attrs(item.hir_id()) .iter() .find(|a| a.has_name(sym::inline)) { diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs index 20be22850b76..b712b351d063 100644 --- a/clippy_lints/src/macro_use.rs +++ b/clippy_lints/src/macro_use.rs @@ -98,7 +98,7 @@ impl LateLintPass<'_> for MacroUseImports { if cx.sess().opts.edition >= Edition::Edition2018 && let hir::ItemKind::Use(path, _kind) = &item.kind && let hir_id = item.hir_id() - && let attrs = cx.tcx.hir().attrs(hir_id) + && let attrs = cx.tcx.hir_attrs(hir_id) && let Some(mac_attr) = attrs.iter().find(|attr| attr.has_name(sym::macro_use)) && let Some(id) = path.res.iter().find_map(|res| match res { Res::Def(DefKind::Mod, id) => Some(id), diff --git a/clippy_lints/src/manual_non_exhaustive.rs b/clippy_lints/src/manual_non_exhaustive.rs index 496e0660d4f9..64b07a5536b4 100644 --- a/clippy_lints/src/manual_non_exhaustive.rs +++ b/clippy_lints/src/manual_non_exhaustive.rs @@ -89,11 +89,11 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive { match item.kind { ItemKind::Enum(def, _) if def.variants.len() > 1 => { let iter = def.variants.iter().filter_map(|v| { - (matches!(v.data, VariantData::Unit(_, _)) && is_doc_hidden(cx.tcx.hir().attrs(v.hir_id))) + (matches!(v.data, VariantData::Unit(_, _)) && is_doc_hidden(cx.tcx.hir_attrs(v.hir_id))) .then_some((v.def_id, v.span)) }); if let Ok((id, span)) = iter.exactly_one() - && !attr::contains_name(cx.tcx.hir().attrs(item.hir_id()), sym::non_exhaustive) + && !attr::contains_name(cx.tcx.hir_attrs(item.hir_id()), sym::non_exhaustive) { self.potential_enums.push((item.owner_id.def_id, id, item.span, span)); } @@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive { "this seems like a manual implementation of the non-exhaustive pattern", |diag| { if let Some(non_exhaustive) = - attr::find_by_name(cx.tcx.hir().attrs(item.hir_id()), sym::non_exhaustive) + attr::find_by_name(cx.tcx.hir_attrs(item.hir_id()), sym::non_exhaustive) { diag.span_note(non_exhaustive.span(), "the struct is already non-exhaustive"); } else { diff --git a/clippy_lints/src/matches/match_like_matches.rs b/clippy_lints/src/matches/match_like_matches.rs index d697f427c705..d29d1ea3e96d 100644 --- a/clippy_lints/src/matches/match_like_matches.rs +++ b/clippy_lints/src/matches/match_like_matches.rs @@ -42,7 +42,7 @@ pub(super) fn check_match<'tcx>( cx, scrutinee, arms.iter() - .map(|arm| (cx.tcx.hir().attrs(arm.hir_id), Some(arm.pat), arm.body, arm.guard)), + .map(|arm| (cx.tcx.hir_attrs(arm.hir_id), Some(arm.pat), arm.body, arm.guard)), e, false, ) diff --git a/clippy_lints/src/matches/match_same_arms.rs b/clippy_lints/src/matches/match_same_arms.rs index 41e4c75f843e..250f17fa9025 100644 --- a/clippy_lints/src/matches/match_same_arms.rs +++ b/clippy_lints/src/matches/match_same_arms.rs @@ -75,7 +75,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) { HirIdMapEntry::Occupied(entry) => return *entry.get() == b_id, } // the names technically don't have to match; this makes the lint more conservative - && cx.tcx.hir().name(a_id) == cx.tcx.hir().name(b_id) + && cx.tcx.hir_name(a_id) == cx.tcx.hir_name(b_id) && cx.typeck_results().expr_ty(a) == cx.typeck_results().expr_ty(b) && pat_contains_local(lhs.pat, a_id) && pat_contains_local(rhs.pat, b_id) diff --git a/clippy_lints/src/methods/is_empty.rs b/clippy_lints/src/methods/is_empty.rs index 1c64f78678ae..7c190e123b72 100644 --- a/clippy_lints/src/methods/is_empty.rs +++ b/clippy_lints/src/methods/is_empty.rs @@ -41,7 +41,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_ fn is_under_cfg(cx: &LateContext<'_>, id: HirId) -> bool { cx.tcx .hir_parent_id_iter(id) - .any(|id| cx.tcx.hir().attrs(id).iter().any(|attr| attr.has_name(sym::cfg))) + .any(|id| cx.tcx.hir_attrs(id).iter().any(|attr| attr.has_name(sym::cfg))) } /// Similar to [`clippy_utils::expr_or_init`], but does not go up the chain if the initialization diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 94d3657d9f12..7dde21d3edb1 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -4731,7 +4731,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { } let name = impl_item.ident.name.as_str(); let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id; - let item = cx.tcx.hir().expect_item(parent); + let item = cx.tcx.hir_expect_item(parent); let self_ty = cx.tcx.type_of(item.owner_id).instantiate_identity(); let implements_trait = matches!(item.kind, hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. })); diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 47a9e17b3cfe..3470c266c491 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -182,7 +182,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { } fn check_crate(&mut self, cx: &LateContext<'tcx>) { - let attrs = cx.tcx.hir().attrs(hir::CRATE_HIR_ID); + let attrs = cx.tcx.hir_attrs(hir::CRATE_HIR_ID); self.check_missing_docs_attrs(cx, CRATE_DEF_ID, attrs, cx.tcx.def_span(CRATE_DEF_ID), "the", "crate"); } @@ -224,7 +224,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { let (article, desc) = cx.tcx.article_and_description(it.owner_id.to_def_id()); - let attrs = cx.tcx.hir().attrs(it.hir_id()); + let attrs = cx.tcx.hir_attrs(it.hir_id()); if !is_from_proc_macro(cx, it) { self.check_missing_docs_attrs(cx, it.owner_id.def_id, attrs, it.span, article, desc); } @@ -234,7 +234,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx hir::TraitItem<'_>) { let (article, desc) = cx.tcx.article_and_description(trait_item.owner_id.to_def_id()); - let attrs = cx.tcx.hir().attrs(trait_item.hir_id()); + let attrs = cx.tcx.hir_attrs(trait_item.hir_id()); if !is_from_proc_macro(cx, trait_item) { self.check_missing_docs_attrs(cx, trait_item.owner_id.def_id, attrs, trait_item.span, article, desc); } @@ -252,7 +252,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { } let (article, desc) = cx.tcx.article_and_description(impl_item.owner_id.to_def_id()); - let attrs = cx.tcx.hir().attrs(impl_item.hir_id()); + let attrs = cx.tcx.hir_attrs(impl_item.hir_id()); if !is_from_proc_macro(cx, impl_item) { self.check_missing_docs_attrs(cx, impl_item.owner_id.def_id, attrs, impl_item.span, article, desc); } @@ -261,7 +261,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { fn check_field_def(&mut self, cx: &LateContext<'tcx>, sf: &'tcx hir::FieldDef<'_>) { if !sf.is_positional() { - let attrs = cx.tcx.hir().attrs(sf.hir_id); + let attrs = cx.tcx.hir_attrs(sf.hir_id); if !is_from_proc_macro(cx, sf) { self.check_missing_docs_attrs(cx, sf.def_id, attrs, sf.span, "a", "struct field"); } @@ -270,7 +270,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { } fn check_variant(&mut self, cx: &LateContext<'tcx>, v: &'tcx hir::Variant<'_>) { - let attrs = cx.tcx.hir().attrs(v.hir_id); + let attrs = cx.tcx.hir_attrs(v.hir_id); if !is_from_proc_macro(cx, v) { self.check_missing_docs_attrs(cx, v.def_id, attrs, v.span, "a", "variant"); } diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index 3cf1a80607e8..2c578d816025 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -98,7 +98,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { match it.kind { hir::ItemKind::Fn { .. } => { let desc = "a function"; - let attrs = cx.tcx.hir().attrs(it.hir_id()); + let attrs = cx.tcx.hir_attrs(it.hir_id()); check_missing_inline_attrs(cx, attrs, it.span, desc); }, hir::ItemKind::Trait(ref _is_auto, ref _unsafe, _generics, _bounds, trait_items) => { @@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { // an impl is not provided let desc = "a default trait method"; let item = cx.tcx.hir_trait_item(tit.id); - let attrs = cx.tcx.hir().attrs(item.hir_id()); + let attrs = cx.tcx.hir_attrs(item.hir_id()); check_missing_inline_attrs(cx, attrs, item.span, desc); } }, @@ -168,7 +168,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { } } - let attrs = cx.tcx.hir().attrs(impl_item.hir_id()); + let attrs = cx.tcx.hir_attrs(impl_item.hir_id()); check_missing_inline_attrs(cx, attrs, impl_item.span, desc); } } diff --git a/clippy_lints/src/mixed_read_write_in_expression.rs b/clippy_lints/src/mixed_read_write_in_expression.rs index a7452c8a3c84..be728e6c8b74 100644 --- a/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/clippy_lints/src/mixed_read_write_in_expression.rs @@ -334,7 +334,7 @@ impl<'tcx> Visitor<'tcx> for ReadVisitor<'_, 'tcx> { self.cx, MIXED_READ_WRITE_IN_EXPRESSION, expr.span, - format!("unsequenced read of `{}`", self.cx.tcx.hir().name(self.var)), + format!("unsequenced read of `{}`", self.cx.tcx.hir_name(self.var)), |diag| { diag.span_note( self.write_expr.span, diff --git a/clippy_lints/src/needless_if.rs b/clippy_lints/src/needless_if.rs index 7eefb016aca9..c90019f6ee16 100644 --- a/clippy_lints/src/needless_if.rs +++ b/clippy_lints/src/needless_if.rs @@ -65,7 +65,7 @@ impl LateLintPass<'_> for NeedlessIf { stmt.span, "this `if` branch is empty", "you can remove it", - if cond.can_have_side_effects() || !cx.tcx.hir().attrs(stmt.hir_id).is_empty() { + if cond.can_have_side_effects() || !cx.tcx.hir_attrs(stmt.hir_id).is_empty() { // `{ foo }` or `{ foo } && bar` placed into a statement position would be // interpreted as a block statement, force it to be an expression if cond_snippet.starts_with('{') { diff --git a/clippy_lints/src/needless_late_init.rs b/clippy_lints/src/needless_late_init.rs index 863a1f895c93..3efbed0c2365 100644 --- a/clippy_lints/src/needless_late_init.rs +++ b/clippy_lints/src/needless_late_init.rs @@ -261,7 +261,7 @@ fn check<'tcx>( binding_id: HirId, ) -> Option<()> { let usage = first_usage(cx, binding_id, local_stmt.hir_id, block)?; - let binding_name = cx.tcx.hir().opt_name(binding_id)?; + let binding_name = cx.tcx.hir_opt_name(binding_id)?; let let_snippet = local_snippet_without_semicolon(cx, local)?; match usage.expr.kind { diff --git a/clippy_lints/src/needless_pass_by_ref_mut.rs b/clippy_lints/src/needless_pass_by_ref_mut.rs index dc10de24bc8c..576bb27b254c 100644 --- a/clippy_lints/src/needless_pass_by_ref_mut.rs +++ b/clippy_lints/src/needless_pass_by_ref_mut.rs @@ -147,7 +147,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { // We don't check unsafe functions. return; } - let attrs = cx.tcx.hir().attrs(hir_id); + let attrs = cx.tcx.hir_attrs(hir_id); if header.abi != ExternAbi::Rust || requires_exact_signature(attrs) { return; } diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index dc85176ebb9e..7bee89086b80 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { match kind { FnKind::ItemFn(.., header) => { - let attrs = cx.tcx.hir().attrs(hir_id); + let attrs = cx.tcx.hir_attrs(hir_id); if header.abi != ExternAbi::Rust || requires_exact_signature(attrs) { return; } diff --git a/clippy_lints/src/no_mangle_with_rust_abi.rs b/clippy_lints/src/no_mangle_with_rust_abi.rs index 1baa3cb2f0fd..fe8a02c64c66 100644 --- a/clippy_lints/src/no_mangle_with_rust_abi.rs +++ b/clippy_lints/src/no_mangle_with_rust_abi.rs @@ -40,7 +40,7 @@ impl<'tcx> LateLintPass<'tcx> for NoMangleWithRustAbi { if let ItemKind::Fn { sig: fn_sig, .. } = &item.kind && !item.span.from_expansion() { - let attrs = cx.tcx.hir().attrs(item.hir_id()); + let attrs = cx.tcx.hir_attrs(item.hir_id()); let mut app = Applicability::MaybeIncorrect; let fn_snippet = snippet_with_applicability(cx, fn_sig.span.with_hi(item.ident.span.lo()), "..", &mut app); for attr in attrs { diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index d4da12451f18..9b53608ae7f3 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -351,7 +351,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) { if let ImplItemKind::Const(_, body_id) = &impl_item.kind { let item_def_id = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id; - let item = cx.tcx.hir().expect_item(item_def_id); + let item = cx.tcx.hir_expect_item(item_def_id); match &item.kind { ItemKind::Impl(Impl { diff --git a/clippy_lints/src/operators/op_ref.rs b/clippy_lints/src/operators/op_ref.rs index c3c09946c27d..378fed481f4f 100644 --- a/clippy_lints/src/operators/op_ref.rs +++ b/clippy_lints/src/operators/op_ref.rs @@ -181,7 +181,7 @@ fn in_impl<'tcx>( ) -> Option<(&'tcx rustc_hir::Ty<'tcx>, &'tcx rustc_hir::Ty<'tcx>)> { if let Some(block) = get_enclosing_block(cx, e.hir_id) && let Some(impl_def_id) = cx.tcx.impl_of_method(block.hir_id.owner.to_def_id()) - && let item = cx.tcx.hir().expect_item(impl_def_id.expect_local()) + && let item = cx.tcx.hir_expect_item(impl_def_id.expect_local()) && let ItemKind::Impl(item) = &item.kind && let Some(of_trait) = &item.of_trait && let Some(seg) = of_trait.path.segments.last() @@ -200,7 +200,7 @@ fn in_impl<'tcx>( fn are_equal(cx: &LateContext<'_>, middle_ty: Ty<'_>, hir_ty: &rustc_hir::Ty<'_>) -> bool { if let ty::Adt(adt_def, _) = middle_ty.kind() && let Some(local_did) = adt_def.did().as_local() - && let item = cx.tcx.hir().expect_item(local_did) + && let item = cx.tcx.hir_expect_item(local_did) && let middle_ty_id = item.owner_id.to_def_id() && let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind && let Res::Def(_, hir_ty_id) = path.res diff --git a/clippy_lints/src/pass_by_ref_or_value.rs b/clippy_lints/src/pass_by_ref_or_value.rs index 49bc56083468..320c0286bb7b 100644 --- a/clippy_lints/src/pass_by_ref_or_value.rs +++ b/clippy_lints/src/pass_by_ref_or_value.rs @@ -280,7 +280,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue { if header.abi != ExternAbi::Rust { return; } - let attrs = cx.tcx.hir().attrs(hir_id); + let attrs = cx.tcx.hir_attrs(hir_id); for a in attrs { if let Some(meta_items) = a.meta_item_list() { if a.has_name(sym::proc_macro_derive) diff --git a/clippy_lints/src/pub_underscore_fields.rs b/clippy_lints/src/pub_underscore_fields.rs index db03657c9af4..fd21893232db 100644 --- a/clippy_lints/src/pub_underscore_fields.rs +++ b/clippy_lints/src/pub_underscore_fields.rs @@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for PubUnderscoreFields { // Only pertains to fields that start with an underscore, and are public. if field.ident.as_str().starts_with('_') && is_visible(field) // We ignore fields that have `#[doc(hidden)]`. - && !is_doc_hidden(cx.tcx.hir().attrs(field.hir_id)) + && !is_doc_hidden(cx.tcx.hir_attrs(field.hir_id)) // We ignore fields that are `PhantomData`. && !is_path_lang_item(cx, field.ty, LangItem::PhantomData) { diff --git a/clippy_lints/src/read_zero_byte_vec.rs b/clippy_lints/src/read_zero_byte_vec.rs index 6bd68dd4109d..49b522994fbf 100644 --- a/clippy_lints/src/read_zero_byte_vec.rs +++ b/clippy_lints/src/read_zero_byte_vec.rs @@ -93,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec { }, ), VecInitKind::WithExprCapacity(hir_id) => { - let e = cx.tcx.hir().expect_expr(hir_id); + let e = cx.tcx.hir_expect_expr(hir_id); span_lint_hir_and_then( cx, READ_ZERO_BYTE_VEC, diff --git a/clippy_lints/src/return_self_not_must_use.rs b/clippy_lints/src/return_self_not_must_use.rs index 5a25483c397c..07ae92fa9843 100644 --- a/clippy_lints/src/return_self_not_must_use.rs +++ b/clippy_lints/src/return_self_not_must_use.rs @@ -74,7 +74,7 @@ fn check_method(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_def: LocalDefId, spa // We only show this warning for public exported methods. && cx.effective_visibilities.is_exported(fn_def) // We don't want to emit this lint if the `#[must_use]` attribute is already there. - && !cx.tcx.hir().attrs(owner_id.into()).iter().any(|attr| attr.has_name(sym::must_use)) + && !cx.tcx.hir_attrs(owner_id.into()).iter().any(|attr| attr.has_name(sym::must_use)) && cx.tcx.visibility(fn_def.to_def_id()).is_public() && let ret_ty = return_ty(cx, owner_id) && let self_arg = nth_arg(cx, owner_id, 0) diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 3ba6d6284592..4cb73df8b488 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -231,7 +231,7 @@ impl<'tcx> LateLintPass<'tcx> for Return { && let Some(stmt) = block.stmts.iter().last() && let StmtKind::Let(local) = &stmt.kind && local.ty.is_none() - && cx.tcx.hir().attrs(local.hir_id).is_empty() + && cx.tcx.hir_attrs(local.hir_id).is_empty() && let Some(initexpr) = &local.init && let PatKind::Binding(_, local_id, _, _) = local.pat.kind && path_to_local_id(retexpr, local_id) @@ -401,7 +401,7 @@ fn check_final_expr<'tcx>( // This allows the addition of attributes, like `#[allow]` (See: clippy#9361) // `#[expect(clippy::needless_return)]` needs to be handled separately to // actually fulfill the expectation (clippy::#12998) - match cx.tcx.hir().attrs(expr.hir_id) { + match cx.tcx.hir_attrs(expr.hir_id) { [] => {}, [attr] => { if matches!(Level::from_attr(attr), Some(Level::Expect(_))) diff --git a/clippy_lints/src/self_named_constructors.rs b/clippy_lints/src/self_named_constructors.rs index fc02c3a51716..8b2d597b9e32 100644 --- a/clippy_lints/src/self_named_constructors.rs +++ b/clippy_lints/src/self_named_constructors.rs @@ -52,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors { } let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id; - let item = cx.tcx.hir().expect_item(parent); + let item = cx.tcx.hir_expect_item(parent); let self_ty = cx.tcx.type_of(item.owner_id).instantiate_identity(); let ret_ty = return_ty(cx, impl_item.owner_id); diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index 746bf018bcc3..be533ca915ed 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -429,8 +429,7 @@ fn block_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool { fn include_attrs_in_span(cx: &LateContext<'_>, hir_id: HirId, span: Span) -> Span { span.to(cx .tcx - .hir() - .attrs(hir_id) + .hir_attrs(hir_id) .iter() .fold(span, |acc, attr| acc.to(attr.span()))) } diff --git a/clippy_lints/src/unused_self.rs b/clippy_lints/src/unused_self.rs index 2c6c75693166..582aa6e6001e 100644 --- a/clippy_lints/src/unused_self.rs +++ b/clippy_lints/src/unused_self.rs @@ -57,7 +57,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf { return; } let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id; - let parent_item = cx.tcx.hir().expect_item(parent); + let parent_item = cx.tcx.hir_expect_item(parent); let assoc_item = cx.tcx.associated_item(impl_item.owner_id); let contains_todo = |cx, body: &'_ Body<'_>| -> bool { clippy_utils::visitors::for_each_expr_without_closures(body.value, |e| { diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 6f6683eb9712..b466a8e127a9 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -318,7 +318,7 @@ impl<'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'_, 'tcx> { { if call_to_unwrap == unwrappable.safe_to_unwrap { let is_entire_condition = unwrappable.is_entire_condition; - let unwrappable_variable_name = self.cx.tcx.hir().name(unwrappable.local_id); + let unwrappable_variable_name = self.cx.tcx.hir_name(unwrappable.local_id); let suggested_pattern = if call_to_unwrap { unwrappable.kind.success_variant_pattern() } else { diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 9d8c161873c0..4309cd2c9abd 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -793,7 +793,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { } fn has_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool { - let attrs = cx.tcx.hir().attrs(hir_id); + let attrs = cx.tcx.hir_attrs(hir_id); get_attr(cx.sess(), attrs, "author").count() > 0 } diff --git a/clippy_lints/src/utils/dump_hir.rs b/clippy_lints/src/utils/dump_hir.rs index b108951978f3..9910be9bc285 100644 --- a/clippy_lints/src/utils/dump_hir.rs +++ b/clippy_lints/src/utils/dump_hir.rs @@ -59,6 +59,6 @@ impl<'tcx> LateLintPass<'tcx> for DumpHir { } fn has_attr(cx: &LateContext<'_>, hir_id: hir::HirId) -> bool { - let attrs = cx.tcx.hir().attrs(hir_id); + let attrs = cx.tcx.hir_attrs(hir_id); get_attr(cx.sess(), attrs, "dump").count() > 0 } diff --git a/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs index 89b4c48b8b11..16d51fa09025 100644 --- a/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs +++ b/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs @@ -247,7 +247,7 @@ fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<' /// This function extracts the version value of a `clippy::version` attribute if the given value has /// one pub(super) fn extract_clippy_version_value(cx: &LateContext<'_>, item: &'_ Item<'_>) -> Option { - let attrs = cx.tcx.hir().attrs(item.hir_id()); + let attrs = cx.tcx.hir_attrs(item.hir_id()); attrs.iter().find_map(|attr| { if let hir::Attribute::Unparsed(attr_kind) = &attr // Identify attribute diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index d89692468441..80613a51c140 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -2036,15 +2036,14 @@ pub fn has_attr(attrs: &[hir::Attribute], symbol: Symbol) -> bool { } pub fn has_repr_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool { - find_attr!(cx.tcx.hir().attrs(hir_id), AttributeKind::Repr(..)) + find_attr!(cx.tcx.hir_attrs(hir_id), AttributeKind::Repr(..)) } pub fn any_parent_has_attr(tcx: TyCtxt<'_>, node: HirId, symbol: Symbol) -> bool { - let map = &tcx.hir(); let mut prev_enclosing_node = None; let mut enclosing_node = node; while Some(enclosing_node) != prev_enclosing_node { - if has_attr(map.attrs(enclosing_node), symbol) { + if has_attr(tcx.hir_attrs(enclosing_node), symbol) { return true; } prev_enclosing_node = Some(enclosing_node); @@ -2061,7 +2060,7 @@ pub fn in_automatically_derived(tcx: TyCtxt<'_>, id: HirId) -> bool { .filter(|(_, node)| matches!(node, OwnerNode::Item(item) if matches!(item.kind, ItemKind::Impl(_)))) .any(|(id, _)| { has_attr( - tcx.hir().attrs(tcx.local_def_id_to_hir_id(id.def_id)), + tcx.hir_attrs(tcx.local_def_id_to_hir_id(id.def_id)), sym::automatically_derived, ) }) @@ -2344,16 +2343,14 @@ pub fn std_or_core(cx: &LateContext<'_>) -> Option<&'static str> { pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool { cx.tcx - .hir() - .attrs(hir::CRATE_HIR_ID) + .hir_attrs(hir::CRATE_HIR_ID) .iter() .any(|attr| attr.name_or_empty() == sym::no_std) } pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool { cx.tcx - .hir() - .attrs(hir::CRATE_HIR_ID) + .hir_attrs(hir::CRATE_HIR_ID) .iter() .any(|attr| attr.name_or_empty() == sym::no_core) } @@ -2643,8 +2640,7 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl Fn(&[Sym // We could also check for the type name `test::TestDescAndFn` if let Res::Def(DefKind::Struct, _) = path.res { let has_test_marker = tcx - .hir() - .attrs(item.hir_id()) + .hir_attrs(item.hir_id()) .iter() .any(|a| a.has_name(sym::rustc_test_marker)); if has_test_marker { @@ -2688,7 +2684,7 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool { /// This only checks directly applied attributes, to see if a node is inside a `#[cfg(test)]` parent /// use [`is_in_cfg_test`] pub fn is_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool { - tcx.hir().attrs(id).iter().any(|attr| { + tcx.hir_attrs(id).iter().any(|attr| { if attr.has_name(sym::cfg) && let Some(items) = attr.meta_item_list() && let [item] = &*items @@ -2713,12 +2709,10 @@ pub fn is_in_test(tcx: TyCtxt<'_>, hir_id: HirId) -> bool { /// Checks if the item of any of its parents has `#[cfg(...)]` attribute applied. pub fn inherits_cfg(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { - let hir = tcx.hir(); - tcx.has_attr(def_id, sym::cfg) || tcx .hir_parent_iter(tcx.local_def_id_to_hir_id(def_id)) - .flat_map(|(parent_id, _)| hir.attrs(parent_id)) + .flat_map(|(parent_id, _)| tcx.hir_attrs(parent_id)) .any(|attr| attr.has_name(sym::cfg)) } diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 5bb2b12988a6..0316de172de7 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -108,7 +108,7 @@ impl Msrv { let start = cx.last_node_with_lint_attrs; if let Some(msrv_attr) = once(start) .chain(cx.tcx.hir_parent_id_iter(start)) - .find_map(|id| parse_attrs(cx.tcx.sess, cx.tcx.hir().attrs(id))) + .find_map(|id| parse_attrs(cx.tcx.sess, cx.tcx.hir_attrs(id))) { return Some(msrv_attr); } diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index 24b4f0d9e6d8..9cc66593dcc3 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -847,7 +847,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> { let mut start_snip = snippet_with_applicability(self.cx, start_span, "..", &mut self.applicability); // identifier referring to the variable currently triggered (i.e.: `fp`) - let ident_str = map.name(id).to_string(); + let ident_str = self.cx.tcx.hir_name(id).to_string(); // full identifier that includes projection (i.e.: `fp.field`) let ident_str_with_proj = snippet(self.cx, span, "..").to_string(); @@ -876,7 +876,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> { // item is used in a call // i.e.: `Call`: `|x| please(x)` or `MethodCall`: `|x| [1, 2, 3].contains(x)` ExprKind::Call(_, call_args) | ExprKind::MethodCall(_, _, call_args, _) => { - let expr = self.cx.tcx.hir().expect_expr(cmt.hir_id); + let expr = self.cx.tcx.hir_expect_expr(cmt.hir_id); let arg_ty_kind = self.cx.typeck_results().expr_ty(expr).kind(); if matches!(arg_ty_kind, ty::Ref(_, _, Mutability::Not)) { From 35e6057e715b47fa8ceed67fbf53e459c86d571c Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Tue, 11 Mar 2025 20:59:03 +0100 Subject: [PATCH 154/745] `needless_pass_by_value`: reference the innermost `Option` content If types such as `Option>` are not used by value, then `Option>` will be suggested, instead of `Option<&Option>`. --- clippy_lints/src/needless_pass_by_value.rs | 15 ++++------- clippy_utils/src/lib.rs | 28 +++++++++++++++++---- tests/ui/needless_pass_by_value.rs | 29 ++++++++++++++++++++++ tests/ui/needless_pass_by_value.stderr | 28 +++++++++++++++++++-- 4 files changed, 83 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index f5652e7b832d..1acc3ffeb936 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -1,10 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::is_self; use clippy_utils::ptr::get_spans; use clippy_utils::source::{SpanRangeExt, snippet}; use clippy_utils::ty::{ implements_trait, implements_trait_with_env_from_iter, is_copy, is_type_diagnostic_item, is_type_lang_item, }; +use clippy_utils::{is_self, peel_hir_ty_options}; use rustc_abi::ExternAbi; use rustc_errors::{Applicability, Diag}; use rustc_hir::intravisit::FnKind; @@ -279,18 +279,13 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { } } - let suggestion = if is_type_diagnostic_item(cx, ty, sym::Option) - && let snip = snippet(cx, input.span, "_") - && let Some((first, rest)) = snip.split_once('<') - { - format!("{first}<&{rest}") - } else { - format!("&{}", snippet(cx, input.span, "_")) - }; + let inner_input = peel_hir_ty_options(cx, input); + let before_span = input.span.until(inner_input.span); + let after_span = before_span.shrink_to_hi().to(input.span.shrink_to_hi()); diag.span_suggestion( input.span, "consider taking a reference instead", - suggestion, + format!("{}&{}", snippet(cx, before_span, "_"), snippet(cx, after_span, "_")), Applicability::MaybeIncorrect, ); }; diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 2d2a19c7b78f..61b65382bb2e 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -107,10 +107,10 @@ use rustc_hir::hir_id::{HirIdMap, HirIdSet}; use rustc_hir::intravisit::{FnKind, Visitor, walk_expr}; use rustc_hir::{ self as hir, Arm, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind, ConstContext, - Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, - ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat, - PatExpr, PatExprKind, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitFn, TraitItem, TraitItemKind, - TraitItemRef, TraitRef, TyKind, UnOp, def, + Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArg, GenericArgs, HirId, Impl, ImplItem, + ImplItemKind, ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, + Param, Pat, PatExpr, PatExprKind, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitFn, TraitItem, + TraitItemKind, TraitItemRef, TraitRef, TyKind, UnOp, def, }; use rustc_lexer::{TokenKind, tokenize}; use rustc_lint::{LateContext, Level, Lint, LintContext}; @@ -435,7 +435,7 @@ pub fn qpath_generic_tys<'tcx>(qpath: &QPath<'tcx>) -> impl Iterator Some(ty.as_unambig_ty()), + GenericArg::Type(ty) => Some(ty.as_unambig_ty()), _ => None, }) } @@ -3709,3 +3709,21 @@ pub fn is_mutable(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { true } } + +/// Peel `Option<…>` from `hir_ty` as long as the HIR name is `Option` and it corresponds to the +/// `core::Option<_>` type. +pub fn peel_hir_ty_options<'tcx>(cx: &LateContext<'tcx>, mut hir_ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> { + let Some(option_def_id) = cx.tcx.get_diagnostic_item(sym::Option) else { + return hir_ty; + }; + while let TyKind::Path(QPath::Resolved(None, path)) = hir_ty.kind + && let Some(segment) = path.segments.last() + && segment.ident.name == sym::Option + && let Res::Def(DefKind::Enum, def_id) = segment.res + && def_id == option_def_id + && let [GenericArg::Type(arg_ty)] = segment.args().args + { + hir_ty = arg_ty.as_unambig_ty(); + } + hir_ty +} diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index adea373fd55a..aef7fff28705 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -196,6 +196,35 @@ fn option_inner_ref(x: Option) { assert!(x.is_some()); } +mod non_standard { + #[derive(Debug)] + pub struct Option(T); +} + +fn non_standard_option(x: non_standard::Option) { + //~^ needless_pass_by_value + dbg!(&x); +} + +fn option_by_name(x: Option>>>) { + //~^ needless_pass_by_value + dbg!(&x); +} + +type OptStr = Option; + +fn non_option(x: OptStr) { + //~^ needless_pass_by_value + dbg!(&x); +} + +type Opt = Option; + +fn non_option_either(x: Opt) { + //~^ needless_pass_by_value + dbg!(&x); +} + fn main() { // This should not cause an ICE either // https://github.com/rust-lang/rust-clippy/issues/3144 diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index 987bfc4affc5..fc67e06ca42b 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -29,7 +29,7 @@ error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:58:18 | LL | fn test_match(x: Option>, y: Option>) { - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `Option<&Option>` + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `Option>` error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:73:24 @@ -185,5 +185,29 @@ error: this argument is passed by value, but not consumed in the function body LL | fn option_inner_ref(x: Option) { | ^^^^^^^^^^^^^^ help: consider taking a reference instead: `Option<&String>` -error: aborting due to 23 previous errors +error: this argument is passed by value, but not consumed in the function body + --> tests/ui/needless_pass_by_value.rs:204:27 + | +LL | fn non_standard_option(x: non_standard::Option) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&non_standard::Option` + +error: this argument is passed by value, but not consumed in the function body + --> tests/ui/needless_pass_by_value.rs:209:22 + | +LL | fn option_by_name(x: Option>>>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `Option>>>` + +error: this argument is passed by value, but not consumed in the function body + --> tests/ui/needless_pass_by_value.rs:216:18 + | +LL | fn non_option(x: OptStr) { + | ^^^^^^ help: consider taking a reference instead: `&OptStr` + +error: this argument is passed by value, but not consumed in the function body + --> tests/ui/needless_pass_by_value.rs:223:25 + | +LL | fn non_option_either(x: Opt) { + | ^^^^^^^^^^^ help: consider taking a reference instead: `&Opt` + +error: aborting due to 27 previous errors From 56715d986483f17af09dc2d73c99d20f7def7ab4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 12 Mar 2025 08:03:54 +0100 Subject: [PATCH 155/745] intrinsics: remove unnecessary leading underscore from argument names --- example/mini_core.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index 72c9df59d833..6e345b2a6fdf 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -624,25 +624,25 @@ pub mod intrinsics { #[rustc_intrinsic] pub fn size_of() -> usize; #[rustc_intrinsic] - pub unsafe fn size_of_val(_val: *const T) -> usize; + pub unsafe fn size_of_val(val: *const T) -> usize; #[rustc_intrinsic] pub fn min_align_of() -> usize; #[rustc_intrinsic] - pub unsafe fn min_align_of_val(_val: *const T) -> usize; + pub unsafe fn min_align_of_val(val: *const T) -> usize; #[rustc_intrinsic] - pub unsafe fn copy(_src: *const T, _dst: *mut T, _count: usize); + pub unsafe fn copy(src: *const T, dst: *mut T, count: usize); #[rustc_intrinsic] - pub unsafe fn transmute(_e: T) -> U; + pub unsafe fn transmute(e: T) -> U; #[rustc_intrinsic] - pub unsafe fn ctlz_nonzero(_x: T) -> u32; + pub unsafe fn ctlz_nonzero(x: T) -> u32; #[rustc_intrinsic] pub fn needs_drop() -> bool; #[rustc_intrinsic] - pub fn bitreverse(_x: T) -> T; + pub fn bitreverse(x: T) -> T; #[rustc_intrinsic] - pub fn bswap(_x: T) -> T; + pub fn bswap(x: T) -> T; #[rustc_intrinsic] - pub unsafe fn write_bytes(_dst: *mut T, _val: u8, _count: usize); + pub unsafe fn write_bytes(dst: *mut T, val: u8, count: usize); #[rustc_intrinsic] pub unsafe fn unreachable() -> !; } From cfc743226e86e9a772fa9a7126364ec1bd6aab89 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 12 Mar 2025 11:29:54 +0100 Subject: [PATCH 156/745] Update `ui_test` version to `0.29.2` --- Cargo.toml | 2 +- tests/compile-test.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 23b2b4ff0b47..1a46bcf75025 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ anstream = "0.6.18" [dev-dependencies] cargo_metadata = "0.18.1" -ui_test = "0.26.4" +ui_test = "0.29.2" regex = "1.5.5" serde = { version = "1.0.145", features = ["derive"] } serde_json = "1.0.122" diff --git a/tests/compile-test.rs b/tests/compile-test.rs index f44cf7a7c25a..5cca866ea552 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -16,7 +16,7 @@ use test_utils::IS_RUSTC_TEST_SUITE; use ui_test::custom_flags::Flag; use ui_test::custom_flags::rustfix::RustfixMode; use ui_test::spanned::Spanned; -use ui_test::{Args, CommandBuilder, Config, Match, OutputConflictHandling, status_emitter}; +use ui_test::{Args, CommandBuilder, Config, Match, error_on_output_conflict, status_emitter}; use std::collections::{BTreeMap, HashMap}; use std::env::{self, set_var, var_os}; @@ -142,7 +142,7 @@ impl TestContext { fn base_config(&self, test_dir: &str, mandatory_annotations: bool) -> Config { let target_dir = PathBuf::from(var_os("CARGO_TARGET_DIR").unwrap_or_else(|| "target".into())); let mut config = Config { - output_conflict_handling: OutputConflictHandling::Error, + output_conflict_handling: error_on_output_conflict, filter_files: env::var("TESTNAME") .map(|filters| filters.split(',').map(str::to_string).collect()) .unwrap_or_default(), From e4d3b0a0724adc2f8e6e1bfdacc1d58eb9926202 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 12 Mar 2025 11:30:46 +0100 Subject: [PATCH 157/745] Update `produce_ice` so its error can be checked in ui tests --- clippy_lints/src/utils/internal_lints/produce_ice.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/utils/internal_lints/produce_ice.rs b/clippy_lints/src/utils/internal_lints/produce_ice.rs index 9169e2968eb7..0a07919d659f 100644 --- a/clippy_lints/src/utils/internal_lints/produce_ice.rs +++ b/clippy_lints/src/utils/internal_lints/produce_ice.rs @@ -1,6 +1,6 @@ use rustc_ast::ast::NodeId; use rustc_ast::visit::FnKind; -use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::declare_lint_pass; use rustc_span::Span; @@ -24,8 +24,12 @@ declare_clippy_lint! { declare_lint_pass!(ProduceIce => [PRODUCE_ICE]); impl EarlyLintPass for ProduceIce { - fn check_fn(&mut self, _: &EarlyContext<'_>, fn_kind: FnKind<'_>, _: Span, _: NodeId) { - assert!(!is_trigger_fn(fn_kind), "Would you like some help with that?"); + fn check_fn(&mut self, ctx: &EarlyContext<'_>, fn_kind: FnKind<'_>, span: Span, _: NodeId) { + if is_trigger_fn(fn_kind) { + ctx.sess() + .dcx() + .span_delayed_bug(span, "Would you like some help with that?"); + } } } From ec8c0b3755e9b5269f3190499c04026556d4dd81 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 12 Mar 2025 11:31:09 +0100 Subject: [PATCH 158/745] Make annotations mandatory for internal ui tests --- tests/compile-test.rs | 2 +- tests/ui-internal/custom_ice_message.rs | 1 + tests/ui-internal/custom_ice_message.stderr | 21 +++++++++++++-------- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 5cca866ea552..956a05288f35 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -220,7 +220,7 @@ fn run_internal_tests(cx: &TestContext) { if !RUN_INTERNAL_TESTS { return; } - let mut config = cx.base_config("ui-internal", false); + let mut config = cx.base_config("ui-internal", true); config.bless_command = Some("cargo uitest --features internal -- -- --bless".into()); ui_test::run_tests_generic( diff --git a/tests/ui-internal/custom_ice_message.rs b/tests/ui-internal/custom_ice_message.rs index 9b0db660c997..71819fe37070 100644 --- a/tests/ui-internal/custom_ice_message.rs +++ b/tests/ui-internal/custom_ice_message.rs @@ -10,5 +10,6 @@ #![allow(clippy::missing_clippy_version_attribute)] fn it_looks_like_you_are_trying_to_kill_clippy() {} +//~^ ice: Would you like some help with that? fn main() {} diff --git a/tests/ui-internal/custom_ice_message.stderr b/tests/ui-internal/custom_ice_message.stderr index 801b0f340de9..589e1190a907 100644 --- a/tests/ui-internal/custom_ice_message.stderr +++ b/tests/ui-internal/custom_ice_message.stderr @@ -1,9 +1,18 @@ +note: no errors encountered even though delayed bugs were created -thread '' panicked at clippy_lints/src/utils/internal_lints/produce_ice.rs: -Would you like some help with that? -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +note: those delayed bugs will now be shown as internal compiler errors -error: the compiler unexpectedly panicked. this is a bug. +error: internal compiler error: Would you like some help with that? + --> tests/ui-internal/custom_ice_message.rs:12:1 + | +LL | fn it_looks_like_you_are_trying_to_kill_clippy() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: delayed at clippy_lints/src/utils/internal_lints/produce_ice.rs - disabled backtrace + --> tests/ui-internal/custom_ice_message.rs:12:1 + | +LL | fn it_looks_like_you_are_trying_to_kill_clippy() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new?template=ice.yml @@ -13,9 +22,5 @@ note: rustc running on note: compiler flags: -Z ui-testing -Z deduplicate-diagnostics=no -query stack during panic: -#0 [early_lint_checks] perform lints prior to AST lowering -#1 [hir_crate] getting the crate HIR -... and 3 other queries... use `env RUST_BACKTRACE=1` to see the full query stack note: Clippy version: foo From 092a20ec110326aad03acabab5d41410a92ae0ac Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 12 Mar 2025 11:41:26 +0100 Subject: [PATCH 159/745] Update `lint_message_convention` test to allow clippy "help" message --- tests/lint_message_convention.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/lint_message_convention.rs b/tests/lint_message_convention.rs index 7ed1f485c1cf..9229e2e8c496 100644 --- a/tests/lint_message_convention.rs +++ b/tests/lint_message_convention.rs @@ -44,6 +44,7 @@ impl Message { ".*AT&T x86 assembly syntax used", "note: Clippy version: .*", "the compiler unexpectedly panicked. this is a bug.", + "internal compiler error:", ]) .unwrap() }); From 417d4e6210d5faf1db8ab872979e223dde7e42b2 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Wed, 12 Mar 2025 06:59:37 +0100 Subject: [PATCH 160/745] `needless_pass_by_value`: make verbose suggestion This reduces the number of snippet manipulations, and shows the new reference in context. --- clippy_lints/src/needless_pass_by_value.rs | 9 +- ...needless_pass_by_value-w-late-bound.stderr | 6 +- tests/ui/needless_pass_by_value.stderr | 150 +++++++++++++++--- 3 files changed, 136 insertions(+), 29 deletions(-) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 1acc3ffeb936..7aa1d63c660b 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -279,13 +279,10 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { } } - let inner_input = peel_hir_ty_options(cx, input); - let before_span = input.span.until(inner_input.span); - let after_span = before_span.shrink_to_hi().to(input.span.shrink_to_hi()); - diag.span_suggestion( - input.span, + diag.span_suggestion_verbose( + peel_hir_ty_options(cx, input).span.shrink_to_lo(), "consider taking a reference instead", - format!("{}&{}", snippet(cx, before_span, "_"), snippet(cx, after_span, "_")), + '&', Applicability::MaybeIncorrect, ); }; diff --git a/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr b/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr index 284795700069..b4fb1222539a 100644 --- a/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr +++ b/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr @@ -2,7 +2,7 @@ error: this argument is passed by value, but not consumed in the function body --> tests/ui/crashes/needless_pass_by_value-w-late-bound.rs:7:12 | LL | fn test(x: Foo<'_>) {} - | ^^^^^^^ help: consider taking a reference instead: `&Foo<'_>` + | ^^^^^^^ | help: or consider marking this type as `Copy` --> tests/ui/crashes/needless_pass_by_value-w-late-bound.rs:5:1 @@ -11,6 +11,10 @@ LL | struct Foo<'a>(&'a [(); 100]); | ^^^^^^^^^^^^^^ = note: `-D clippy::needless-pass-by-value` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_value)]` +help: consider taking a reference instead + | +LL | fn test(x: &Foo<'_>) {} + | + error: aborting due to 1 previous error diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index fc67e06ca42b..e4381d1db53a 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -17,43 +17,78 @@ error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:35:22 | LL | fn bar(x: String, y: Wrapper) { - | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` + | ^^^^^^^ + | +help: consider taking a reference instead + | +LL | fn bar(x: String, y: &Wrapper) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:44:71 | LL | fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: V) { - | ^ help: consider taking a reference instead: `&V` + | ^ + | +help: consider taking a reference instead + | +LL | fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: &V) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:58:18 | LL | fn test_match(x: Option>, y: Option>) { - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `Option>` + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider taking a reference instead + | +LL | fn test_match(x: Option>, y: Option>) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:73:24 | LL | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { - | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` + | ^^^^^^^ + | +help: consider taking a reference instead + | +LL | fn test_destructure(x: &Wrapper, y: Wrapper, z: Wrapper) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:73:36 | LL | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { - | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` + | ^^^^^^^ + | +help: consider taking a reference instead + | +LL | fn test_destructure(x: Wrapper, y: &Wrapper, z: Wrapper) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:92:49 | LL | fn test_blanket_ref(vals: T, serializable: S) {} - | ^ help: consider taking a reference instead: `&T` + | ^ + | +help: consider taking a reference instead + | +LL | fn test_blanket_ref(vals: &T, serializable: S) {} + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:95:18 | LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { - | ^^^^^^ help: consider taking a reference instead: `&String` + | ^^^^^^ + | +help: consider taking a reference instead + | +LL | fn issue_2114(s: &String, t: String, u: Vec, v: Vec) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:95:29 @@ -76,7 +111,12 @@ error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:95:40 | LL | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { - | ^^^^^^^^ help: consider taking a reference instead: `&Vec` + | ^^^^^^^^ + | +help: consider taking a reference instead + | +LL | fn issue_2114(s: String, t: String, u: &Vec, v: Vec) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:95:53 @@ -105,109 +145,175 @@ error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:115:12 | LL | t: String, - | ^^^^^^ help: consider taking a reference instead: `&String` + | ^^^^^^ + | +help: consider taking a reference instead + | +LL | t: &String, + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:125:23 | LL | fn baz(&self, uu: U, ss: Self) {} - | ^ help: consider taking a reference instead: `&U` + | ^ + | +help: consider taking a reference instead + | +LL | fn baz(&self, uu: &U, ss: Self) {} + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:125:30 | LL | fn baz(&self, uu: U, ss: Self) {} - | ^^^^ help: consider taking a reference instead: `&Self` + | ^^^^ + | +help: consider taking a reference instead + | +LL | fn baz(&self, uu: U, ss: &Self) {} + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:149:24 | LL | fn bar_copy(x: u32, y: CopyWrapper) { - | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` + | ^^^^^^^^^^^ | help: or consider marking this type as `Copy` --> tests/ui/needless_pass_by_value.rs:147:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^ +help: consider taking a reference instead + | +LL | fn bar_copy(x: u32, y: &CopyWrapper) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:157:29 | LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { - | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` + | ^^^^^^^^^^^ | help: or consider marking this type as `Copy` --> tests/ui/needless_pass_by_value.rs:147:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^ +help: consider taking a reference instead + | +LL | fn test_destructure_copy(x: &CopyWrapper, y: CopyWrapper, z: CopyWrapper) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:157:45 | LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { - | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` + | ^^^^^^^^^^^ | help: or consider marking this type as `Copy` --> tests/ui/needless_pass_by_value.rs:147:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^ +help: consider taking a reference instead + | +LL | fn test_destructure_copy(x: CopyWrapper, y: &CopyWrapper, z: CopyWrapper) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:157:61 | LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { - | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` + | ^^^^^^^^^^^ | help: or consider marking this type as `Copy` --> tests/ui/needless_pass_by_value.rs:147:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^ +help: consider taking a reference instead + | +LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: &CopyWrapper) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:173:40 | LL | fn some_fun<'b, S: Bar<'b, ()>>(items: S) {} - | ^ help: consider taking a reference instead: `&S` + | ^ + | +help: consider taking a reference instead + | +LL | fn some_fun<'b, S: Bar<'b, ()>>(items: &S) {} + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:179:20 | LL | fn more_fun(items: impl Club<'static, i32>) {} - | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&impl Club<'static, i32>` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider taking a reference instead + | +LL | fn more_fun(items: &impl Club<'static, i32>) {} + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:194:24 | LL | fn option_inner_ref(x: Option) { - | ^^^^^^^^^^^^^^ help: consider taking a reference instead: `Option<&String>` + | ^^^^^^^^^^^^^^ + | +help: consider taking a reference instead + | +LL | fn option_inner_ref(x: Option<&String>) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:204:27 | LL | fn non_standard_option(x: non_standard::Option) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&non_standard::Option` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider taking a reference instead + | +LL | fn non_standard_option(x: &non_standard::Option) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:209:22 | LL | fn option_by_name(x: Option>>>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `Option>>>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider taking a reference instead + | +LL | fn option_by_name(x: Option>>>) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:216:18 | LL | fn non_option(x: OptStr) { - | ^^^^^^ help: consider taking a reference instead: `&OptStr` + | ^^^^^^ + | +help: consider taking a reference instead + | +LL | fn non_option(x: &OptStr) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:223:25 | LL | fn non_option_either(x: Opt) { - | ^^^^^^^^^^^ help: consider taking a reference instead: `&Opt` + | ^^^^^^^^^^^ + | +help: consider taking a reference instead + | +LL | fn non_option_either(x: &Opt) { + | + error: aborting due to 27 previous errors From 4ca551cf41d8273a2829f19a8e802fb557f14d6f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 12 Mar 2025 13:08:42 +0000 Subject: [PATCH 161/745] Rustup to rustc 1.87.0-nightly (665025243 2025-03-11) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 4a566552322a..ec730a4402cf 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-03-06" +channel = "nightly-2025-03-12" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From d2b328e6b3a4cd42b85a289ce3285ca0ac461e7c Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 12 Mar 2025 13:08:50 +0000 Subject: [PATCH 162/745] Reduce verbosity of ./scripts/rustup.sh pull --- scripts/rustup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/rustup.sh b/scripts/rustup.sh index 355282911c25..152c243aa6ad 100755 --- a/scripts/rustup.sh +++ b/scripts/rustup.sh @@ -64,7 +64,7 @@ case $1 in cg_clif=$(pwd) pushd ../rust git fetch origin master - git checkout "$RUST_VERS" + git -c advice.detachedHead=false checkout "$RUST_VERS" "$cg_clif/git-fixed-subtree.sh" push --prefix=compiler/rustc_codegen_cranelift/ "$cg_clif" sync_from_rust popd git merge sync_from_rust -m "Sync from rust $RUST_VERS" From eea0db2590a79b58d1354c86954382e2952f7749 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 12 Mar 2025 13:18:52 +0000 Subject: [PATCH 163/745] Fix rustc test suite --- scripts/test_rustc_tests.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index 005e87c2b2ad..5e96210d8589 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -166,6 +166,18 @@ index 30387af428c..f7895b12961 100644 "/build-root", ) .normalize(r#""[^"]*\/symbols.o""#, "\\"/symbols.o\\"") +diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs +index 073116933bd..c3e4578204d 100644 +--- a/src/tools/compiletest/src/runtest/run_make.rs ++++ b/src/tools/compiletest/src/runtest/run_make.rs +@@ -109,7 +109,6 @@ pub(super) fn run_rmake_test(&self) { + // library or compiler features. Here, we force the stage 0 rustc to consider itself as + // a stable-channel compiler via \`RUSTC_BOOTSTRAP=-1\` to prevent *any* unstable + // library/compiler usages, even if stage 0 rustc is *actually* a nightly rustc. +- .env("RUSTC_BOOTSTRAP", "-1") + .arg("-o") + .arg(&recipe_bin) + // Specify library search paths for \`run_make_support\`. EOF echo "[TEST] rustc test suite" From 90645c187c9d640893a8b5d1cf61c4d29dfabde8 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 12 Mar 2025 16:32:00 +0100 Subject: [PATCH 164/745] Reduce FormattingOptions to 64 bits. --- compiler/rustc_ast_lowering/src/expr.rs | 5 - compiler/rustc_ast_lowering/src/format.rs | 40 +-- compiler/rustc_hir/src/lang_items.rs | 1 - compiler/rustc_span/src/symbol.rs | 1 - library/core/src/fmt/float.rs | 6 +- library/core/src/fmt/mod.rs | 392 ++++++++++++---------- library/core/src/fmt/rt.rs | 21 +- 7 files changed, 253 insertions(+), 213 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 5bb6704dde45..6e32f8bc28fa 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -2150,11 +2150,6 @@ impl<'hir> LoweringContext<'_, 'hir> { self.expr_uint(sp, ast::UintTy::U16, value as u128) } - pub(super) fn expr_char(&mut self, sp: Span, value: char) -> hir::Expr<'hir> { - let lit = self.arena.alloc(hir::Lit { span: sp, node: ast::LitKind::Char(value) }); - self.expr(sp, hir::ExprKind::Lit(lit)) - } - pub(super) fn expr_str(&mut self, sp: Span, value: Symbol) -> hir::Expr<'hir> { let lit = self .arena diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index faa47274f96c..343895984ca4 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -361,24 +361,26 @@ fn make_format_spec<'hir>( zero_pad, debug_hex, } = &placeholder.format_options; - let fill = ctx.expr_char(sp, fill.unwrap_or(' ')); - let align = ctx.expr_lang_item_type_relative( - sp, - hir::LangItem::FormatAlignment, - match alignment { - Some(FormatAlignment::Left) => sym::Left, - Some(FormatAlignment::Right) => sym::Right, - Some(FormatAlignment::Center) => sym::Center, - None => sym::Unknown, - }, - ); - // This needs to match `Flag` in library/core/src/fmt/rt.rs. - let flags: u32 = ((sign == Some(FormatSign::Plus)) as u32) - | ((sign == Some(FormatSign::Minus)) as u32) << 1 - | (alternate as u32) << 2 - | (zero_pad as u32) << 3 - | ((debug_hex == Some(FormatDebugHex::Lower)) as u32) << 4 - | ((debug_hex == Some(FormatDebugHex::Upper)) as u32) << 5; + let fill = fill.unwrap_or(' '); + // These need to match the constants in library/core/src/fmt/rt.rs. + let align = match alignment { + Some(FormatAlignment::Left) => 0, + Some(FormatAlignment::Right) => 1, + Some(FormatAlignment::Center) => 2, + None => 3, + }; + // This needs to match the constants in library/core/src/fmt/rt.rs. + let flags: u32 = fill as u32 + | ((sign == Some(FormatSign::Plus)) as u32) << 21 + | ((sign == Some(FormatSign::Minus)) as u32) << 22 + | (alternate as u32) << 23 + | (zero_pad as u32) << 24 + | ((debug_hex == Some(FormatDebugHex::Lower)) as u32) << 25 + | ((debug_hex == Some(FormatDebugHex::Upper)) as u32) << 26 + | (width.is_some() as u32) << 27 + | (precision.is_some() as u32) << 28 + | align << 29 + | 1 << 31; // Highest bit always set. let flags = ctx.expr_u32(sp, flags); let precision = make_count(ctx, sp, precision, argmap); let width = make_count(ctx, sp, width, argmap); @@ -387,7 +389,7 @@ fn make_format_spec<'hir>( hir::LangItem::FormatPlaceholder, sym::new, )); - let args = ctx.arena.alloc_from_iter([position, fill, align, flags, precision, width]); + let args = ctx.arena.alloc_from_iter([position, flags, precision, width]); ctx.expr_call_mut(sp, format_placeholder_new, args) } diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 29f4d5b80769..e625514e9ffa 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -322,7 +322,6 @@ language_item_table! { BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn, GenericRequirement::None; // Lang items needed for `format_args!()`. - FormatAlignment, sym::format_alignment, format_alignment, Target::Enum, GenericRequirement::None; FormatArgument, sym::format_argument, format_argument, Target::Struct, GenericRequirement::None; FormatArguments, sym::format_arguments, format_arguments, Target::Struct, GenericRequirement::None; FormatCount, sym::format_count, format_count, Target::Enum, GenericRequirement::None; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8a8bec35d819..e6b305d2ffd3 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1002,7 +1002,6 @@ symbols! { forbid, forget, format, - format_alignment, format_args, format_args_capture, format_args_macro, diff --git a/library/core/src/fmt/float.rs b/library/core/src/fmt/float.rs index 4a43c12be9aa..870ad9df4fd3 100644 --- a/library/core/src/fmt/float.rs +++ b/library/core/src/fmt/float.rs @@ -86,7 +86,7 @@ where true => flt2dec::Sign::MinusPlus, }; - if let Some(precision) = fmt.options.precision { + if let Some(precision) = fmt.options.get_precision() { float_to_decimal_common_exact(fmt, num, sign, precision) } else { let min_precision = 0; @@ -162,7 +162,7 @@ where true => flt2dec::Sign::MinusPlus, }; - if let Some(precision) = fmt.options.precision { + if let Some(precision) = fmt.options.get_precision() { // 1 integral digit + `precision` fractional digits = `precision + 1` total digits float_to_exponential_common_exact(fmt, num, sign, precision + 1, upper) } else { @@ -180,7 +180,7 @@ where true => flt2dec::Sign::MinusPlus, }; - if let Some(precision) = fmt.options.precision { + if let Some(precision) = fmt.options.get_precision() { // this behavior of {:.PREC?} predates exponential formatting for {:?} float_to_decimal_common_exact(fmt, num, sign, precision) } else { diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index e0dc632df705..e46424700087 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -33,19 +33,6 @@ pub enum Alignment { Center, } -#[doc(hidden)] -#[unstable(feature = "fmt_internals", reason = "internal to standard library", issue = "none")] -impl From for Option { - fn from(value: rt::Alignment) -> Self { - match value { - rt::Alignment::Left => Some(Alignment::Left), - rt::Alignment::Right => Some(Alignment::Right), - rt::Alignment::Center => Some(Alignment::Center), - rt::Alignment::Unknown => None, - } - } -} - #[stable(feature = "debug_builders", since = "1.2.0")] pub use self::builders::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; #[unstable(feature = "debug_closure_helpers", issue = "117729")] @@ -291,11 +278,50 @@ pub enum DebugAsHex { #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[unstable(feature = "formatting_options", issue = "118117")] pub struct FormattingOptions { + /// Flags, with the following bit fields: + /// + /// ```text + /// 31 30 29 28 27 26 25 24 23 22 21 20 0 + /// ┌───┬───────┬───┬───┬───┬───┬───┬───┬───┬───┬──────────────────────────────────┐ + /// │ 1 │ align │ p │ w │ X?│ x?│'0'│ # │ - │ + │ fill │ + /// └───┴───────┴───┴───┴───┴───┴───┴───┴───┴───┴──────────────────────────────────┘ + /// │ │ │ │ └─┬───────────────────┘ └─┬──────────────────────────────┘ + /// │ │ │ │ │ └─ The fill character (21 bits char). + /// │ │ │ │ └─ The debug upper/lower hex, zero pad, alternate, and plus/minus flags. + /// │ │ │ └─ Whether a width is set. (The value is stored separately.) + /// │ │ └─ Whether a precision is set. (The value is stored separately.) + /// │ ├─ 0: Align left. (<) + /// │ ├─ 1: Align right. (>) + /// │ ├─ 2: Align center. (^) + /// │ └─ 3: Alignment not set. (default) + /// └─ Always set. + /// This makes it possible to distinguish formatting flags from + /// a &str size when stored in (the upper bits of) the same field. + /// (fmt::Arguments will make use of this property in the future.) + /// ``` flags: u32, - fill: char, - align: Option, - width: Option, - precision: Option, + /// Width if width flag (bit 27) above is set. Otherwise, always 0. + width: u16, + /// Precision if precision flag (bit 28) above is set. Otherwise, always 0. + precision: u16, +} + +// This needs to match with compiler/rustc_ast_lowering/src/format.rs. +mod flags { + pub(super) const SIGN_PLUS_FLAG: u32 = 1 << 21; + pub(super) const SIGN_MINUS_FLAG: u32 = 1 << 22; + pub(super) const ALTERNATE_FLAG: u32 = 1 << 23; + pub(super) const SIGN_AWARE_ZERO_PAD_FLAG: u32 = 1 << 24; + pub(super) const DEBUG_LOWER_HEX_FLAG: u32 = 1 << 25; + pub(super) const DEBUG_UPPER_HEX_FLAG: u32 = 1 << 26; + pub(super) const WIDTH_FLAG: u32 = 1 << 27; + pub(super) const PRECISION_FLAG: u32 = 1 << 28; + pub(super) const ALIGN_BITS: u32 = 0b11 << 29; + pub(super) const ALIGN_LEFT: u32 = 0 << 29; + pub(super) const ALIGN_RIGHT: u32 = 1 << 29; + pub(super) const ALIGN_CENTER: u32 = 2 << 29; + pub(super) const ALIGN_UNKNOWN: u32 = 3 << 29; + pub(super) const ALWAYS_SET: u32 = 1 << 31; } impl FormattingOptions { @@ -311,7 +337,11 @@ impl FormattingOptions { /// - no [`DebugAsHex`] output mode. #[unstable(feature = "formatting_options", issue = "118117")] pub const fn new() -> Self { - Self { flags: 0, fill: ' ', align: None, width: None, precision: None } + Self { + flags: ' ' as u32 | flags::ALIGN_UNKNOWN | flags::ALWAYS_SET, + width: 0, + precision: 0, + } } /// Sets or removes the sign (the `+` or the `-` flag). @@ -324,13 +354,12 @@ impl FormattingOptions { /// - `-`: Currently not used #[unstable(feature = "formatting_options", issue = "118117")] pub fn sign(&mut self, sign: Option) -> &mut Self { - self.flags = - self.flags & !(1 << rt::Flag::SignMinus as u32 | 1 << rt::Flag::SignPlus as u32); - match sign { - None => {} - Some(Sign::Plus) => self.flags |= 1 << rt::Flag::SignPlus as u32, - Some(Sign::Minus) => self.flags |= 1 << rt::Flag::SignMinus as u32, - } + let sign = match sign { + None => 0, + Some(Sign::Plus) => flags::SIGN_PLUS_FLAG, + Some(Sign::Minus) => flags::SIGN_MINUS_FLAG, + }; + self.flags = self.flags & !(flags::SIGN_PLUS_FLAG | flags::SIGN_MINUS_FLAG) | sign; self } /// Sets or unsets the `0` flag. @@ -339,9 +368,9 @@ impl FormattingOptions { #[unstable(feature = "formatting_options", issue = "118117")] pub fn sign_aware_zero_pad(&mut self, sign_aware_zero_pad: bool) -> &mut Self { if sign_aware_zero_pad { - self.flags |= 1 << rt::Flag::SignAwareZeroPad as u32 + self.flags |= flags::SIGN_AWARE_ZERO_PAD_FLAG; } else { - self.flags &= !(1 << rt::Flag::SignAwareZeroPad as u32) + self.flags &= !flags::SIGN_AWARE_ZERO_PAD_FLAG; } self } @@ -356,9 +385,9 @@ impl FormattingOptions { #[unstable(feature = "formatting_options", issue = "118117")] pub fn alternate(&mut self, alternate: bool) -> &mut Self { if alternate { - self.flags |= 1 << rt::Flag::Alternate as u32 + self.flags |= flags::ALTERNATE_FLAG; } else { - self.flags &= !(1 << rt::Flag::Alternate as u32) + self.flags &= !flags::ALTERNATE_FLAG; } self } @@ -370,7 +399,7 @@ impl FormattingOptions { /// printed around it. #[unstable(feature = "formatting_options", issue = "118117")] pub fn fill(&mut self, fill: char) -> &mut Self { - self.fill = fill; + self.flags = self.flags & (u32::MAX << 21) | fill as u32; self } /// Sets or removes the alignment. @@ -379,7 +408,13 @@ impl FormattingOptions { /// positioned if it is smaller than the width of the formatter. #[unstable(feature = "formatting_options", issue = "118117")] pub fn align(&mut self, align: Option) -> &mut Self { - self.align = align; + let align: u32 = match align { + Some(Alignment::Left) => flags::ALIGN_LEFT, + Some(Alignment::Right) => flags::ALIGN_RIGHT, + Some(Alignment::Center) => flags::ALIGN_CENTER, + None => flags::ALIGN_UNKNOWN, + }; + self.flags = self.flags & !flags::ALIGN_BITS | align; self } /// Sets or removes the width. @@ -390,7 +425,13 @@ impl FormattingOptions { /// will be used to take up the required space. #[unstable(feature = "formatting_options", issue = "118117")] pub fn width(&mut self, width: Option) -> &mut Self { - self.width = width; + if let Some(width) = width { + self.flags |= flags::WIDTH_FLAG; + self.width = width; + } else { + self.flags &= !flags::WIDTH_FLAG; + self.width = 0; + } self } /// Sets or removes the precision. @@ -404,77 +445,85 @@ impl FormattingOptions { /// decimal point should be printed. #[unstable(feature = "formatting_options", issue = "118117")] pub fn precision(&mut self, precision: Option) -> &mut Self { - self.precision = precision; + if let Some(precision) = precision { + self.flags |= flags::PRECISION_FLAG; + self.precision = precision; + } else { + self.flags &= !flags::PRECISION_FLAG; + self.precision = 0; + } self } /// Specifies whether the [`Debug`] trait should use lower-/upper-case /// hexadecimal or normal integers #[unstable(feature = "formatting_options", issue = "118117")] pub fn debug_as_hex(&mut self, debug_as_hex: Option) -> &mut Self { - self.flags = self.flags - & !(1 << rt::Flag::DebugUpperHex as u32 | 1 << rt::Flag::DebugLowerHex as u32); - match debug_as_hex { - None => {} - Some(DebugAsHex::Upper) => self.flags |= 1 << rt::Flag::DebugUpperHex as u32, - Some(DebugAsHex::Lower) => self.flags |= 1 << rt::Flag::DebugLowerHex as u32, - } + let debug_as_hex = match debug_as_hex { + None => 0, + Some(DebugAsHex::Lower) => flags::DEBUG_LOWER_HEX_FLAG, + Some(DebugAsHex::Upper) => flags::DEBUG_UPPER_HEX_FLAG, + }; + self.flags = self.flags & !(flags::DEBUG_LOWER_HEX_FLAG | flags::DEBUG_UPPER_HEX_FLAG) + | debug_as_hex; self } /// Returns the current sign (the `+` or the `-` flag). #[unstable(feature = "formatting_options", issue = "118117")] pub const fn get_sign(&self) -> Option { - const SIGN_PLUS_BITFIELD: u32 = 1 << rt::Flag::SignPlus as u32; - const SIGN_MINUS_BITFIELD: u32 = 1 << rt::Flag::SignMinus as u32; - match self.flags & ((1 << rt::Flag::SignPlus as u32) | (1 << rt::Flag::SignMinus as u32)) { - SIGN_PLUS_BITFIELD => Some(Sign::Plus), - SIGN_MINUS_BITFIELD => Some(Sign::Minus), - 0 => None, - _ => panic!("Invalid sign bits set in flags"), + if self.flags & flags::SIGN_PLUS_FLAG != 0 { + Some(Sign::Plus) + } else if self.flags & flags::SIGN_MINUS_FLAG != 0 { + Some(Sign::Minus) + } else { + None } } /// Returns the current `0` flag. #[unstable(feature = "formatting_options", issue = "118117")] pub const fn get_sign_aware_zero_pad(&self) -> bool { - self.flags & (1 << rt::Flag::SignAwareZeroPad as u32) != 0 + self.flags & flags::SIGN_AWARE_ZERO_PAD_FLAG != 0 } /// Returns the current `#` flag. #[unstable(feature = "formatting_options", issue = "118117")] pub const fn get_alternate(&self) -> bool { - self.flags & (1 << rt::Flag::Alternate as u32) != 0 + self.flags & flags::ALTERNATE_FLAG != 0 } /// Returns the current fill character. #[unstable(feature = "formatting_options", issue = "118117")] pub const fn get_fill(&self) -> char { - self.fill + // SAFETY: We only ever put a valid `char` in the lower 21 bits of the flags field. + unsafe { char::from_u32_unchecked(self.flags & 0x1FFFFF) } } /// Returns the current alignment. #[unstable(feature = "formatting_options", issue = "118117")] pub const fn get_align(&self) -> Option { - self.align + match self.flags & flags::ALIGN_BITS { + flags::ALIGN_LEFT => Some(Alignment::Left), + flags::ALIGN_RIGHT => Some(Alignment::Right), + flags::ALIGN_CENTER => Some(Alignment::Center), + _ => None, + } } /// Returns the current width. #[unstable(feature = "formatting_options", issue = "118117")] pub const fn get_width(&self) -> Option { - self.width + if self.flags & flags::WIDTH_FLAG != 0 { Some(self.width) } else { None } } /// Returns the current precision. #[unstable(feature = "formatting_options", issue = "118117")] pub const fn get_precision(&self) -> Option { - self.precision + if self.flags & flags::PRECISION_FLAG != 0 { Some(self.precision) } else { None } } /// Returns the current precision. #[unstable(feature = "formatting_options", issue = "118117")] pub const fn get_debug_as_hex(&self) -> Option { - const DEBUG_UPPER_BITFIELD: u32 = 1 << rt::Flag::DebugUpperHex as u32; - const DEBUG_LOWER_BITFIELD: u32 = 1 << rt::Flag::DebugLowerHex as u32; - match self.flags - & ((1 << rt::Flag::DebugUpperHex as u32) | (1 << rt::Flag::DebugLowerHex as u32)) - { - DEBUG_UPPER_BITFIELD => Some(DebugAsHex::Upper), - DEBUG_LOWER_BITFIELD => Some(DebugAsHex::Lower), - 0 => None, - _ => panic!("Invalid hex debug bits set in flags"), + if self.flags & flags::DEBUG_LOWER_HEX_FLAG != 0 { + Some(DebugAsHex::Lower) + } else if self.flags & flags::DEBUG_UPPER_HEX_FLAG != 0 { + Some(DebugAsHex::Upper) + } else { + None } } @@ -485,27 +534,6 @@ impl FormattingOptions { pub fn create_formatter<'a>(self, write: &'a mut (dyn Write + 'a)) -> Formatter<'a> { Formatter { options: self, buf: write } } - - #[doc(hidden)] - #[unstable( - feature = "fmt_internals", - reason = "internal routines only exposed for testing", - issue = "none" - )] - /// Flags for formatting - pub fn flags(&mut self, flags: u32) { - self.flags = flags - } - #[doc(hidden)] - #[unstable( - feature = "fmt_internals", - reason = "internal routines only exposed for testing", - issue = "none" - )] - /// Flags for formatting - pub fn get_flags(&self) -> u32 { - self.flags - } } #[unstable(feature = "formatting_options", issue = "118117")] @@ -1478,15 +1506,25 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result { } unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[rt::Argument<'_>]) -> Result { - fmt.options.fill = arg.fill; - fmt.options.align = arg.align.into(); - fmt.options.flags = arg.flags; - // SAFETY: arg and args come from the same Arguments, - // which guarantees the indexes are always within bounds. - unsafe { - fmt.options.width = getcount(args, &arg.width); - fmt.options.precision = getcount(args, &arg.precision); - } + let (width, precision) = + // SAFETY: arg and args come from the same Arguments, + // which guarantees the indexes are always within bounds. + unsafe { (getcount(args, &arg.width), getcount(args, &arg.precision)) }; + + #[cfg(bootstrap)] + let options = + *FormattingOptions { flags: flags::ALWAYS_SET | arg.flags << 21, width: 0, precision: 0 } + .align(match arg.align { + rt::Alignment::Left => Some(Alignment::Left), + rt::Alignment::Right => Some(Alignment::Right), + rt::Alignment::Center => Some(Alignment::Center), + rt::Alignment::Unknown => None, + }) + .fill(arg.fill) + .width(width) + .precision(precision); + #[cfg(not(bootstrap))] + let options = FormattingOptions { flags: arg.flags, width, precision }; // Extract the correct argument debug_assert!(arg.position < args.len()); @@ -1494,17 +1532,18 @@ unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[rt::Argume // which guarantees its index is always within bounds. let value = unsafe { args.get_unchecked(arg.position) }; + // Set all the formatting options. + fmt.options = options; + // Then actually do some printing // SAFETY: this is a placeholder argument. unsafe { value.fmt(fmt) } } +#[cfg(bootstrap)] unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option { match *cnt { - #[cfg(bootstrap)] rt::Count::Is(n) => Some(n as u16), - #[cfg(not(bootstrap))] - rt::Count::Is(n) => Some(n), rt::Count::Implied => None, rt::Count::Param(i) => { debug_assert!(i < args.len()); @@ -1515,6 +1554,20 @@ unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option { } } +#[cfg(not(bootstrap))] +unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> u16 { + match *cnt { + rt::Count::Is(n) => n, + rt::Count::Implied => 0, + rt::Count::Param(i) => { + debug_assert!(i < args.len()); + // SAFETY: cnt and args come from the same Arguments, + // which guarantees this index is always within bounds. + unsafe { args.get_unchecked(i).as_u16().unwrap_unchecked() } + } + } +} + /// Padding after the end of something. Returned by `Formatter::padding`. #[must_use = "don't forget to write the post padding"] pub(crate) struct PostPadding { @@ -1628,40 +1681,28 @@ impl<'a> Formatter<'a> { } // The `width` field is more of a `min-width` parameter at this point. - match self.options.width { - // If there's no minimum length requirements then we can just - // write the bytes. - None => { - write_prefix(self, sign, prefix)?; - self.buf.write_str(buf) - } - // Check if we're over the minimum width, if so then we can also - // just write the bytes. - Some(min) if width >= usize::from(min) => { - write_prefix(self, sign, prefix)?; - self.buf.write_str(buf) - } + let min = self.options.width; + if width >= usize::from(min) { + // We're over the minimum width, so then we can just write the bytes. + write_prefix(self, sign, prefix)?; + self.buf.write_str(buf) + } else if self.sign_aware_zero_pad() { // The sign and prefix goes before the padding if the fill character // is zero - Some(min) if self.sign_aware_zero_pad() => { - let old_fill = crate::mem::replace(&mut self.options.fill, '0'); - let old_align = - crate::mem::replace(&mut self.options.align, Some(Alignment::Right)); - write_prefix(self, sign, prefix)?; - let post_padding = self.padding(min - width as u16, Alignment::Right)?; - self.buf.write_str(buf)?; - post_padding.write(self)?; - self.options.fill = old_fill; - self.options.align = old_align; - Ok(()) - } + let old_options = self.options; + self.options.fill('0').align(Some(Alignment::Right)); + write_prefix(self, sign, prefix)?; + let post_padding = self.padding(min - width as u16, Alignment::Right)?; + self.buf.write_str(buf)?; + post_padding.write(self)?; + self.options = old_options; + Ok(()) + } else { // Otherwise, the sign and prefix goes after the padding - Some(min) => { - let post_padding = self.padding(min - width as u16, Alignment::Right)?; - write_prefix(self, sign, prefix)?; - self.buf.write_str(buf)?; - post_padding.write(self) - } + let post_padding = self.padding(min - width as u16, Alignment::Right)?; + write_prefix(self, sign, prefix)?; + self.buf.write_str(buf)?; + post_padding.write(self) } } @@ -1697,13 +1738,13 @@ impl<'a> Formatter<'a> { #[stable(feature = "rust1", since = "1.0.0")] pub fn pad(&mut self, s: &str) -> Result { // Make sure there's a fast path up front. - if self.options.width.is_none() && self.options.precision.is_none() { + if self.options.flags & (flags::WIDTH_FLAG | flags::PRECISION_FLAG) == 0 { return self.buf.write_str(s); } // The `precision` field can be interpreted as a maximum width for the // string being formatted. - let (s, char_count) = if let Some(max_char_count) = self.options.precision { + let (s, char_count) = if let Some(max_char_count) = self.options.get_precision() { let mut iter = s.char_indices(); let remaining = match iter.advance_by(usize::from(max_char_count)) { Ok(()) => 0, @@ -1719,12 +1760,11 @@ impl<'a> Formatter<'a> { }; // The `width` field is more of a minimum width parameter at this point. - if let Some(width) = self.options.width - && char_count < usize::from(width) - { + if char_count < usize::from(self.options.width) { // If we're under the minimum width, then fill up the minimum width // with the specified string + some alignment. - let post_padding = self.padding(width - char_count as u16, Alignment::Left)?; + let post_padding = + self.padding(self.options.width - char_count as u16, Alignment::Left)?; self.buf.write_str(s)?; post_padding.write(self) } else { @@ -1743,19 +1783,20 @@ impl<'a> Formatter<'a> { padding: u16, default: Alignment, ) -> result::Result { - let align = self.align().unwrap_or(default); + let align = self.options.get_align().unwrap_or(default); + let fill = self.options.get_fill(); - let (pre_pad, post_pad) = match align { - Alignment::Left => (0, padding), - Alignment::Right => (padding, 0), - Alignment::Center => (padding / 2, (padding + 1) / 2), + let padding_left = match align { + Alignment::Left => 0, + Alignment::Right => padding, + Alignment::Center => padding / 2, }; - for _ in 0..pre_pad { - self.buf.write_char(self.options.fill)?; + for _ in 0..padding_left { + self.buf.write_char(fill)?; } - Ok(PostPadding::new(self.options.fill, post_pad)) + Ok(PostPadding::new(fill, padding - padding_left)) } /// Takes the formatted parts and applies the padding. @@ -1767,12 +1808,16 @@ impl<'a> Formatter<'a> { /// /// Any `numfmt::Part::Copy` parts in `formatted` must contain valid UTF-8. unsafe fn pad_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result { - if let Some(mut width) = self.options.width { + if self.options.width == 0 { + // this is the common case and we take a shortcut + // SAFETY: Per the precondition. + unsafe { self.write_formatted_parts(formatted) } + } else { // for the sign-aware zero padding, we render the sign first and // behave as if we had no sign from the beginning. let mut formatted = formatted.clone(); - let old_fill = self.options.fill; - let old_align = self.options.align; + let mut width = self.options.width; + let old_options = self.options; if self.sign_aware_zero_pad() { // a sign always goes first let sign = formatted.sign; @@ -1781,8 +1826,7 @@ impl<'a> Formatter<'a> { // remove the sign from the formatted parts formatted.sign = ""; width = width.saturating_sub(sign.len() as u16); - self.options.fill = '0'; - self.options.align = Some(Alignment::Right); + self.options.fill('0').align(Some(Alignment::Right)); } // remaining parts go through the ordinary padding process. @@ -1799,13 +1843,8 @@ impl<'a> Formatter<'a> { } post_padding.write(self) }; - self.options.fill = old_fill; - self.options.align = old_align; + self.options = old_options; ret - } else { - // this is the common case and we take a shortcut - // SAFETY: Per the precondition. - unsafe { self.write_formatted_parts(formatted) } } } @@ -1926,7 +1965,9 @@ impl<'a> Formatter<'a> { or `sign_aware_zero_pad` methods instead" )] pub fn flags(&self) -> u32 { - self.options.flags + // Extract the debug upper/lower hex, zero pad, alternate, and plus/minus flags + // to stay compatible with older versions of Rust. + self.options.flags >> 21 & 0x3F } /// Returns the character used as 'fill' whenever there is alignment. @@ -1959,7 +2000,7 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn fill(&self) -> char { - self.options.fill + self.options.get_fill() } /// Returns a flag indicating what form of alignment was requested. @@ -1994,7 +2035,7 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags_align", since = "1.28.0")] pub fn align(&self) -> Option { - self.options.align + self.options.get_align() } /// Returns the optionally specified integer width that the output should be. @@ -2024,7 +2065,11 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn width(&self) -> Option { - self.options.width.map(|x| x as usize) + if self.options.flags & flags::WIDTH_FLAG == 0 { + None + } else { + Some(self.options.width as usize) + } } /// Returns the optionally specified precision for numeric types. @@ -2055,7 +2100,11 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn precision(&self) -> Option { - self.options.precision.map(|x| x as usize) + if self.options.flags & flags::PRECISION_FLAG == 0 { + None + } else { + Some(self.options.precision as usize) + } } /// Determines if the `+` flag was specified. @@ -2087,7 +2136,7 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn sign_plus(&self) -> bool { - self.options.flags & (1 << rt::Flag::SignPlus as u32) != 0 + self.options.flags & flags::SIGN_PLUS_FLAG != 0 } /// Determines if the `-` flag was specified. @@ -2116,7 +2165,7 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn sign_minus(&self) -> bool { - self.options.flags & (1 << rt::Flag::SignMinus as u32) != 0 + self.options.flags & flags::SIGN_MINUS_FLAG != 0 } /// Determines if the `#` flag was specified. @@ -2144,7 +2193,7 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn alternate(&self) -> bool { - self.options.flags & (1 << rt::Flag::Alternate as u32) != 0 + self.options.flags & flags::ALTERNATE_FLAG != 0 } /// Determines if the `0` flag was specified. @@ -2170,17 +2219,16 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn sign_aware_zero_pad(&self) -> bool { - self.options.flags & (1 << rt::Flag::SignAwareZeroPad as u32) != 0 + self.options.flags & flags::SIGN_AWARE_ZERO_PAD_FLAG != 0 } // FIXME: Decide what public API we want for these two flags. // https://github.com/rust-lang/rust/issues/48584 fn debug_lower_hex(&self) -> bool { - self.options.flags & (1 << rt::Flag::DebugLowerHex as u32) != 0 + self.options.flags & flags::DEBUG_LOWER_HEX_FLAG != 0 } - fn debug_upper_hex(&self) -> bool { - self.options.flags & (1 << rt::Flag::DebugUpperHex as u32) != 0 + self.options.flags & flags::DEBUG_UPPER_HEX_FLAG != 0 } /// Creates a [`DebugStruct`] builder designed to assist with creation of @@ -2760,7 +2808,7 @@ impl Debug for char { #[stable(feature = "rust1", since = "1.0.0")] impl Display for char { fn fmt(&self, f: &mut Formatter<'_>) -> Result { - if f.options.width.is_none() && f.options.precision.is_none() { + if f.options.flags & (flags::WIDTH_FLAG | flags::PRECISION_FLAG) == 0 { f.write_char(*self) } else { f.pad(self.encode_utf8(&mut [0; MAX_LEN_UTF8])) @@ -2784,26 +2832,24 @@ impl Pointer for *const T { /// /// [problematic]: https://github.com/rust-lang/rust/issues/95489 pub(crate) fn pointer_fmt_inner(ptr_addr: usize, f: &mut Formatter<'_>) -> Result { - let old_width = f.options.width; - let old_flags = f.options.flags; + let old_options = f.options; // The alternate flag is already treated by LowerHex as being special- // it denotes whether to prefix with 0x. We use it to work out whether // or not to zero extend, and then unconditionally set it to get the // prefix. - if f.alternate() { - f.options.flags |= 1 << (rt::Flag::SignAwareZeroPad as u32); + if f.options.get_alternate() { + f.options.sign_aware_zero_pad(true); - if f.options.width.is_none() { - f.options.width = Some((usize::BITS / 4) as u16 + 2); + if f.options.get_width().is_none() { + f.options.width(Some((usize::BITS / 4) as u16 + 2)); } } - f.options.flags |= 1 << (rt::Flag::Alternate as u32); + f.options.alternate(true); let ret = LowerHex::fmt(&ptr_addr, f); - f.options.width = old_width; - f.options.flags = old_flags; + f.options = old_options; ret } diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs index 080fc6ddfc9b..d27f7e6e0d8e 100644 --- a/library/core/src/fmt/rt.rs +++ b/library/core/src/fmt/rt.rs @@ -11,7 +11,9 @@ use crate::ptr::NonNull; #[derive(Copy, Clone)] pub struct Placeholder { pub position: usize, + #[cfg(bootstrap)] pub fill: char, + #[cfg(bootstrap)] pub align: Alignment, pub flags: u32, pub precision: Count, @@ -19,6 +21,7 @@ pub struct Placeholder { } impl Placeholder { + #[cfg(bootstrap)] #[inline] pub const fn new( position: usize, @@ -30,8 +33,15 @@ impl Placeholder { ) -> Self { Self { position, fill, align, flags, precision, width } } + + #[cfg(not(bootstrap))] + #[inline] + pub const fn new(position: usize, flags: u32, precision: Count, width: Count) -> Self { + Self { position, flags, precision, width } + } } +#[cfg(bootstrap)] #[lang = "format_alignment"] #[derive(Copy, Clone, PartialEq, Eq)] pub enum Alignment { @@ -58,17 +68,6 @@ pub enum Count { Implied, } -// This needs to match the order of flags in compiler/rustc_ast_lowering/src/format.rs. -#[derive(Copy, Clone)] -pub(super) enum Flag { - SignPlus, - SignMinus, - Alternate, - SignAwareZeroPad, - DebugLowerHex, - DebugUpperHex, -} - #[derive(Copy, Clone)] enum ArgumentType<'a> { Placeholder { From ba2809e08574c608b6b2cd146649af83d7c354ed Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 12 Mar 2025 16:32:11 +0100 Subject: [PATCH 165/745] Update tests. --- ...onential_common.GVN.32bit.panic-abort.diff | 49 +++++++++---------- ...nential_common.GVN.32bit.panic-unwind.diff | 49 +++++++++---------- ...onential_common.GVN.64bit.panic-abort.diff | 49 +++++++++---------- ...nential_common.GVN.64bit.panic-unwind.diff | 49 +++++++++---------- 4 files changed, 88 insertions(+), 108 deletions(-) diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff index 45fc7365d8d6..6baa902b6f4b 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff @@ -29,16 +29,10 @@ debug precision => _8; let _8: usize; scope 5 (inlined Formatter::<'_>::precision) { - let mut _22: std::option::Option; - scope 6 (inlined Option::::map::::precision::{closure#0}}>) { - let mut _23: isize; - let _24: u16; - let mut _25: usize; - scope 7 { - scope 8 (inlined Formatter::<'_>::precision::{closure#0}) { - } - } - } + let mut _22: u32; + let mut _23: u32; + let mut _24: usize; + let mut _25: u16; } } } @@ -53,7 +47,7 @@ StorageLive(_20); StorageLive(_21); _21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32); - _20 = BitAnd(move _21, const 1_u32); + _20 = BitAnd(move _21, const core::fmt::flags::SIGN_PLUS_FLAG); StorageDead(_21); _4 = Ne(move _20, const 0_u32); StorageDead(_20); @@ -75,12 +69,12 @@ bb3: { StorageLive(_6); - StorageLive(_24); StorageLive(_22); - _22 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option); StorageLive(_23); - _23 = discriminant(_22); - switchInt(move _23) -> [0: bb11, 1: bb12, otherwise: bb10]; + _23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32); + _22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG); + StorageDead(_23); + switchInt(move _22) -> [0: bb10, otherwise: bb11]; } bb4: { @@ -148,30 +142,31 @@ } bb9: { - StorageDead(_23); - StorageDead(_22); - StorageDead(_24); _7 = discriminant(_6); - switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb10]; + switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb12]; } bb10: { - unreachable; - } - - bb11: { + StorageDead(_22); _6 = const Option::::None; goto -> bb9; } - bb12: { - _24 = move ((_22 as Some).0: u16); + bb11: { + StorageDead(_22); + StorageLive(_24); StorageLive(_25); - _25 = copy _24 as usize (IntToInt); - _6 = Option::::Some(move _25); + _25 = copy (((*_1).0: std::fmt::FormattingOptions).2: u16); + _24 = move _25 as usize (IntToInt); StorageDead(_25); + _6 = Option::::Some(move _24); + StorageDead(_24); goto -> bb9; } + + bb12: { + unreachable; + } } ALLOC0 (size: 8, align: 4) { diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff index 578d2c2194b0..36540e038654 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff @@ -29,16 +29,10 @@ debug precision => _8; let _8: usize; scope 5 (inlined Formatter::<'_>::precision) { - let mut _22: std::option::Option; - scope 6 (inlined Option::::map::::precision::{closure#0}}>) { - let mut _23: isize; - let _24: u16; - let mut _25: usize; - scope 7 { - scope 8 (inlined Formatter::<'_>::precision::{closure#0}) { - } - } - } + let mut _22: u32; + let mut _23: u32; + let mut _24: usize; + let mut _25: u16; } } } @@ -53,7 +47,7 @@ StorageLive(_20); StorageLive(_21); _21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32); - _20 = BitAnd(move _21, const 1_u32); + _20 = BitAnd(move _21, const core::fmt::flags::SIGN_PLUS_FLAG); StorageDead(_21); _4 = Ne(move _20, const 0_u32); StorageDead(_20); @@ -75,12 +69,12 @@ bb3: { StorageLive(_6); - StorageLive(_24); StorageLive(_22); - _22 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option); StorageLive(_23); - _23 = discriminant(_22); - switchInt(move _23) -> [0: bb11, 1: bb12, otherwise: bb10]; + _23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32); + _22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG); + StorageDead(_23); + switchInt(move _22) -> [0: bb10, otherwise: bb11]; } bb4: { @@ -148,30 +142,31 @@ } bb9: { - StorageDead(_23); - StorageDead(_22); - StorageDead(_24); _7 = discriminant(_6); - switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb10]; + switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb12]; } bb10: { - unreachable; - } - - bb11: { + StorageDead(_22); _6 = const Option::::None; goto -> bb9; } - bb12: { - _24 = move ((_22 as Some).0: u16); + bb11: { + StorageDead(_22); + StorageLive(_24); StorageLive(_25); - _25 = copy _24 as usize (IntToInt); - _6 = Option::::Some(move _25); + _25 = copy (((*_1).0: std::fmt::FormattingOptions).2: u16); + _24 = move _25 as usize (IntToInt); StorageDead(_25); + _6 = Option::::Some(move _24); + StorageDead(_24); goto -> bb9; } + + bb12: { + unreachable; + } } ALLOC0 (size: 8, align: 4) { diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff index 5f0f7d6cc74f..41c350f3eaeb 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff @@ -29,16 +29,10 @@ debug precision => _8; let _8: usize; scope 5 (inlined Formatter::<'_>::precision) { - let mut _22: std::option::Option; - scope 6 (inlined Option::::map::::precision::{closure#0}}>) { - let mut _23: isize; - let _24: u16; - let mut _25: usize; - scope 7 { - scope 8 (inlined Formatter::<'_>::precision::{closure#0}) { - } - } - } + let mut _22: u32; + let mut _23: u32; + let mut _24: usize; + let mut _25: u16; } } } @@ -53,7 +47,7 @@ StorageLive(_20); StorageLive(_21); _21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32); - _20 = BitAnd(move _21, const 1_u32); + _20 = BitAnd(move _21, const core::fmt::flags::SIGN_PLUS_FLAG); StorageDead(_21); _4 = Ne(move _20, const 0_u32); StorageDead(_20); @@ -75,12 +69,12 @@ bb3: { StorageLive(_6); - StorageLive(_24); StorageLive(_22); - _22 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option); StorageLive(_23); - _23 = discriminant(_22); - switchInt(move _23) -> [0: bb11, 1: bb12, otherwise: bb10]; + _23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32); + _22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG); + StorageDead(_23); + switchInt(move _22) -> [0: bb10, otherwise: bb11]; } bb4: { @@ -148,30 +142,31 @@ } bb9: { - StorageDead(_23); - StorageDead(_22); - StorageDead(_24); _7 = discriminant(_6); - switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb10]; + switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb12]; } bb10: { - unreachable; - } - - bb11: { + StorageDead(_22); _6 = const Option::::None; goto -> bb9; } - bb12: { - _24 = move ((_22 as Some).0: u16); + bb11: { + StorageDead(_22); + StorageLive(_24); StorageLive(_25); - _25 = copy _24 as usize (IntToInt); - _6 = Option::::Some(move _25); + _25 = copy (((*_1).0: std::fmt::FormattingOptions).2: u16); + _24 = move _25 as usize (IntToInt); StorageDead(_25); + _6 = Option::::Some(move _24); + StorageDead(_24); goto -> bb9; } + + bb12: { + unreachable; + } } ALLOC0 (size: 16, align: 8) { diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff index 10cc46a8b828..b839bf81eaf4 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff @@ -29,16 +29,10 @@ debug precision => _8; let _8: usize; scope 5 (inlined Formatter::<'_>::precision) { - let mut _22: std::option::Option; - scope 6 (inlined Option::::map::::precision::{closure#0}}>) { - let mut _23: isize; - let _24: u16; - let mut _25: usize; - scope 7 { - scope 8 (inlined Formatter::<'_>::precision::{closure#0}) { - } - } - } + let mut _22: u32; + let mut _23: u32; + let mut _24: usize; + let mut _25: u16; } } } @@ -53,7 +47,7 @@ StorageLive(_20); StorageLive(_21); _21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32); - _20 = BitAnd(move _21, const 1_u32); + _20 = BitAnd(move _21, const core::fmt::flags::SIGN_PLUS_FLAG); StorageDead(_21); _4 = Ne(move _20, const 0_u32); StorageDead(_20); @@ -75,12 +69,12 @@ bb3: { StorageLive(_6); - StorageLive(_24); StorageLive(_22); - _22 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option); StorageLive(_23); - _23 = discriminant(_22); - switchInt(move _23) -> [0: bb11, 1: bb12, otherwise: bb10]; + _23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32); + _22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG); + StorageDead(_23); + switchInt(move _22) -> [0: bb10, otherwise: bb11]; } bb4: { @@ -148,30 +142,31 @@ } bb9: { - StorageDead(_23); - StorageDead(_22); - StorageDead(_24); _7 = discriminant(_6); - switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb10]; + switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb12]; } bb10: { - unreachable; - } - - bb11: { + StorageDead(_22); _6 = const Option::::None; goto -> bb9; } - bb12: { - _24 = move ((_22 as Some).0: u16); + bb11: { + StorageDead(_22); + StorageLive(_24); StorageLive(_25); - _25 = copy _24 as usize (IntToInt); - _6 = Option::::Some(move _25); + _25 = copy (((*_1).0: std::fmt::FormattingOptions).2: u16); + _24 = move _25 as usize (IntToInt); StorageDead(_25); + _6 = Option::::Some(move _24); + StorageDead(_24); goto -> bb9; } + + bb12: { + unreachable; + } } ALLOC0 (size: 16, align: 8) { From 44094e51481e25b7a3d9abdbcc877251003ca3ba Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Wed, 12 Mar 2025 18:04:24 +0100 Subject: [PATCH 166/745] explain `is_from_proc_macro` in the book --- book/src/development/macro_expansions.md | 76 ++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/book/src/development/macro_expansions.md b/book/src/development/macro_expansions.md index 36092f82e260..ed547130b358 100644 --- a/book/src/development/macro_expansions.md +++ b/book/src/development/macro_expansions.md @@ -150,9 +150,85 @@ if foo_span.in_external_macro(cx.sess().source_map()) { } ``` +### The `is_from_proc_macro` function +A common point of confusion is the existence of [`is_from_proc_macro`] +and how it differs from the other [`in_external_macro`]/[`from_expansion`] functions. + +While [`in_external_macro`] and [`from_expansion`] both work perfectly fine for detecting expanded code +from *declarative* macros (i.e. `macro_rules!` and macros 2.0), +detecting *proc macro*-generated code is a bit more tricky, as proc macros can (and often do) +freely manipulate the span of returned tokens. + +In practice, this often happens through the use of [`quote::quote_spanned!`] with a span from the input tokens. + +In those cases, there is no *reliable* way for the compiler (and tools like Clippy) +to distinguish code that comes from such a proc macro from code that the user wrote directly, +and [`in_external_macro`] will return `false`. + +This is usually not an issue for the compiler and actually helps proc macro authors create better error messages, +as it allows associating parts of the expansion with parts of the macro input and lets the compiler +point the user to the relevant code in case of a compile error. + +However, for Clippy this is inconvenient, because most of the time *we don't* want +to lint proc macro-generated code and this makes it impossible to tell what is and isn't proc macro code. + +> NOTE: this is specifically only an issue when a proc macro explicitly sets the span to that of an **input span**. +> +> For example, other common ways of creating `TokenStream`s, such as `"fn foo() {...}".parse::()`, +> sets each token's span to `Span::call_site()`, which already marks the span as coming from a proc macro +> and the usual span methods have no problem detecting that as a macro span. + +As such, Clippy has its own `is_from_proc_macro` function which tries to *approximate* +whether a span comes from a proc macro, by checking whether the source text at the given span +lines up with the given AST node. + +This function is typically used in combination with the other mentioned macro span functions, +but is usually called much later into the condition chain as it's a bit heavier than most other conditions, +so that the other cheaper conditions can fail faster. For example, the `borrow_deref_ref` lint: +```rs +impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &rustc_hir::Expr<'tcx>) { + if let ... = ... + && ... + && !e.span.from_expansion() + && ... + && ... + && !is_from_proc_macro(cx, e) + && ... + { + ... + } + } +} +``` + +### Testing lints with macro expansions +To test that all of these cases are handled correctly in your lint, +we have a helper auxiliary crate that exposes various macros, used by tests like so: +```rust +//@aux-build:proc_macros.rs + +extern crate proc_macros; + +fn main() { + proc_macros::external!{ code_that_should_trigger_your_lint } + proc_macros::with_span!{ span code_that_should_trigger_your_lint } +} +``` +This exercises two cases: +- `proc_macros::external!` is a simple proc macro that echos the input tokens back but with a macro span: +this represents the usual, common case where an external macro expands to code that your lint would trigger, +and is correctly handled by `in_external_macro` and `Span::from_expansion`. + +- `proc_macros::with_span!` echos back the input tokens starting from the second token +with the span of the first token: this is where the other functions will fail and `is_from_proc_macro` is needed + + [`ctxt`]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/struct.Span.html#method.ctxt [expansion]: https://rustc-dev-guide.rust-lang.org/macro-expansion.html#expansion-and-ast-integration [`from_expansion`]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/struct.Span.html#method.from_expansion [`in_external_macro`]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/struct.Span.html#method.in_external_macro [Span]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/struct.Span.html [SyntaxContext]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/hygiene/struct.SyntaxContext.html +[`is_from_proc_macro`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/fn.is_from_proc_macro.html +[`quote::quote_spanned!`]: https://docs.rs/quote/latest/quote/macro.quote_spanned.html From 0346e926a805a338754a192714cd7f11b29ba816 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 12 Mar 2025 18:39:06 +0100 Subject: [PATCH 167/745] alloc_addresses: use MemoryKind instead of tcx query to determine global allocations --- src/tools/miri/src/alloc_addresses/mod.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs index ff3a25e94bd5..26d71dca3606 100644 --- a/src/tools/miri/src/alloc_addresses/mod.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -170,20 +170,22 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // This ensures the interpreted program and native code have the same view of memory. let base_ptr = match info.kind { AllocKind::LiveData => { - if this.tcx.try_get_global_alloc(alloc_id).is_some() { + if memory_kind == MiriMemoryKind::Global.into() { // For new global allocations, we always pre-allocate the memory to be able use the machine address directly. let prepared_bytes = MiriAllocBytes::zeroed(info.size, info.align) .unwrap_or_else(|| { panic!("Miri ran out of memory: cannot create allocation of {size:?} bytes", size = info.size) }); let ptr = prepared_bytes.as_ptr(); - // Store prepared allocation space to be picked up for use later. + // Store prepared allocation to be picked up for use later. global_state .prepared_alloc_bytes .try_insert(alloc_id, prepared_bytes) .unwrap(); ptr } else { + // Non-global allocations are already in memory at this point so + // we can just get a pointer to where their data is stored. this.get_alloc_bytes_unchecked_raw(alloc_id)? } } @@ -382,6 +384,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { align: Align, ) -> InterpResult<'tcx, MiriAllocBytes> { let this = self.eval_context_ref(); + assert!(this.tcx.try_get_global_alloc(id).is_some()); if this.machine.native_lib.is_some() { // In native lib mode, MiriAllocBytes for global allocations are handled via `prepared_alloc_bytes`. // This additional call ensures that some `MiriAllocBytes` are always prepared, just in case From 82dfa03a71c4be11633bcc35fba7b4898c10d9a3 Mon Sep 17 00:00:00 2001 From: geetanshjuneja Date: Wed, 12 Mar 2025 23:14:14 +0530 Subject: [PATCH 168/745] added check_shim_abi added input arg mismatch test added detailed ub messages added return type mismatch test --- src/tools/miri/src/helpers.rs | 81 +++++++++++++++++-- .../miri/src/shims/unix/foreign_items.rs | 11 ++- .../tests/fail/shims/input_arg_mismatch.rs | 21 +++++ .../fail/shims/input_arg_mismatch.stderr | 17 ++++ .../tests/fail/shims/return_type_mismatch.rs | 21 +++++ .../fail/shims/return_type_mismatch.stderr | 17 ++++ 6 files changed, 161 insertions(+), 7 deletions(-) create mode 100644 src/tools/miri/tests/fail/shims/input_arg_mismatch.rs create mode 100644 src/tools/miri/tests/fail/shims/input_arg_mismatch.stderr create mode 100644 src/tools/miri/tests/fail/shims/return_type_mismatch.rs create mode 100644 src/tools/miri/tests/fail/shims/return_type_mismatch.stderr diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 12e7d0f1a62c..d1429a0be1d0 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -14,7 +14,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::ExportedSymbol; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, MaybeResult, TyAndLayout}; -use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, UintTy}; +use rustc_middle::ty::{self, Binder, FloatTy, FnSig, IntTy, Ty, TyCtxt, UintTy}; use rustc_session::config::CrateType; use rustc_span::{Span, Symbol}; use rustc_target::callconv::{Conv, FnAbi}; @@ -994,10 +994,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { exp_abi: Conv, link_name: Symbol, args: &'a [OpTy<'tcx>], - ) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]> - where - &'a [OpTy<'tcx>; N]: TryFrom<&'a [OpTy<'tcx>]>, - { + ) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]> { self.check_abi_and_shim_symbol_clash(abi, exp_abi, link_name)?; if abi.c_variadic { @@ -1015,6 +1012,80 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) } + /// Check that the given `caller_fn_abi` matches the expected ABI described by + /// `callee_abi`, `callee_input_tys`, `callee_output_ty`, and the return the list of + /// arguments. + fn check_shim_abi<'a, const N: usize>( + &mut self, + link_name: Symbol, + caller_fn_abi: &FnAbi<'tcx, Ty<'tcx>>, + callee_abi: ExternAbi, + callee_input_tys: [Ty<'tcx>; N], + callee_output_ty: Ty<'tcx>, + caller_args: &'a [OpTy<'tcx>], + ) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]> { + let this = self.eval_context_mut(); + let mut inputs_and_output = callee_input_tys.to_vec(); + inputs_and_output.push(callee_output_ty); + let fn_sig_binder = Binder::dummy(FnSig { + inputs_and_output: this.machine.tcx.mk_type_list(&inputs_and_output), + c_variadic: false, + // This does not matter for the ABI. + safety: Safety::Safe, + abi: callee_abi, + }); + let callee_fn_abi = this.fn_abi_of_fn_ptr(fn_sig_binder, Default::default())?; + + this.check_abi_and_shim_symbol_clash(caller_fn_abi, callee_fn_abi.conv, link_name)?; + + if caller_fn_abi.c_variadic { + throw_ub_format!( + "ABI mismatch: calling a non-variadic function with a variadic caller-side signature" + ); + } + + if callee_fn_abi.fixed_count != caller_fn_abi.fixed_count { + throw_ub_format!( + "ABI mismatch: expected {} arguments, found {} arguments ", + callee_fn_abi.fixed_count, + caller_fn_abi.fixed_count + ); + } + + if callee_fn_abi.can_unwind && !caller_fn_abi.can_unwind { + throw_ub_format!( + "ABI mismatch: callee may unwind, but caller-side signature prohibits unwinding", + ); + } + + if !this.check_argument_compat(&caller_fn_abi.ret, &callee_fn_abi.ret)? { + throw_ub!(AbiMismatchReturn { + caller_ty: caller_fn_abi.ret.layout.ty, + callee_ty: callee_fn_abi.ret.layout.ty + }); + } + + if let Some(index) = caller_fn_abi + .args + .iter() + .zip(callee_fn_abi.args.iter()) + .map(|(caller_arg, callee_arg)| this.check_argument_compat(caller_arg, callee_arg)) + .collect::>>()? + .into_iter() + .position(|b| !b) + { + throw_ub!(AbiMismatchArgument { + caller_ty: caller_fn_abi.args[index].layout.ty, + callee_ty: callee_fn_abi.args[index].layout.ty + }); + } + + if let Ok(ops) = caller_args.try_into() { + return interp_ok(ops); + } + unreachable!() + } + /// Check shim for variadic function. /// Returns a tuple that consisting of an array of fixed args, and a slice of varargs. fn check_shim_variadic<'a, const N: usize>( diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 09757071075a..1770b99c0a22 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -1,7 +1,7 @@ use std::ffi::OsStr; use std::str; -use rustc_abi::Size; +use rustc_abi::{ExternAbi, Size}; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutOf; use rustc_span::Symbol; @@ -200,7 +200,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write(fd, buf, count, Some(offset), dest)?; } "close" => { - let [fd] = this.check_shim(abi, Conv::C, link_name, args)?; + let [fd] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32], + this.tcx.types.i32, + args, + )?; let result = this.close(fd)?; this.write_scalar(result, dest)?; } diff --git a/src/tools/miri/tests/fail/shims/input_arg_mismatch.rs b/src/tools/miri/tests/fail/shims/input_arg_mismatch.rs new file mode 100644 index 000000000000..eb8de04dcc41 --- /dev/null +++ b/src/tools/miri/tests/fail/shims/input_arg_mismatch.rs @@ -0,0 +1,21 @@ +//@ignore-target: windows # File handling is not implemented yet +//@compile-flags: -Zmiri-disable-isolation +use std::ffi::{CString, OsStr, c_char, c_int}; +use std::os::unix::ffi::OsStrExt; + +extern "C" { + fn open(path: *const c_char, oflag: c_int, ...) -> c_int; + // correct fd type is i32 + fn close(fd: u32) -> c_int; +} + +fn main() { + let c_path = CString::new(OsStr::new("./text").as_bytes()).expect("CString::new failed"); + let fd = unsafe { + open(c_path.as_ptr(), /* value does not matter */ 0) + } as u32; + let _ = unsafe { + close(fd); + //~^ ERROR: calling a function with argument of type i32 passing data of type u32 + }; +} diff --git a/src/tools/miri/tests/fail/shims/input_arg_mismatch.stderr b/src/tools/miri/tests/fail/shims/input_arg_mismatch.stderr new file mode 100644 index 000000000000..90d4ce78ad4e --- /dev/null +++ b/src/tools/miri/tests/fail/shims/input_arg_mismatch.stderr @@ -0,0 +1,17 @@ +error: Undefined Behavior: calling a function with argument of type i32 passing data of type u32 + --> tests/fail/shims/input_arg_mismatch.rs:LL:CC + | +LL | close(fd); + | ^^^^^^^^^ calling a function with argument of type i32 passing data of type u32 + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = help: this means these two types are not *guaranteed* to be ABI-compatible across all targets + = help: if you think this code should be accepted anyway, please report an issue with Miri + = note: BACKTRACE: + = note: inside `main` at tests/fail/shims/input_arg_mismatch.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/shims/return_type_mismatch.rs b/src/tools/miri/tests/fail/shims/return_type_mismatch.rs new file mode 100644 index 000000000000..6dbdd3f539b3 --- /dev/null +++ b/src/tools/miri/tests/fail/shims/return_type_mismatch.rs @@ -0,0 +1,21 @@ +//@ignore-target: windows # File handling is not implemented yet +//@compile-flags: -Zmiri-disable-isolation +use std::ffi::{CString, OsStr, c_char, c_int, c_short}; +use std::os::unix::ffi::OsStrExt; + +extern "C" { + fn open(path: *const c_char, oflag: c_int, ...) -> c_int; + // correct return type is i32 + fn close(fd: c_int) -> c_short; +} + +fn main() { + let c_path = CString::new(OsStr::new("./text").as_bytes()).expect("CString::new failed"); + let fd = unsafe { + open(c_path.as_ptr(), /* value does not matter */ 0) + }; + let _ = unsafe { + close(fd); + //~^ ERROR: calling a function with return type i32 passing return place of type i16 + }; +} diff --git a/src/tools/miri/tests/fail/shims/return_type_mismatch.stderr b/src/tools/miri/tests/fail/shims/return_type_mismatch.stderr new file mode 100644 index 000000000000..062aa7b49275 --- /dev/null +++ b/src/tools/miri/tests/fail/shims/return_type_mismatch.stderr @@ -0,0 +1,17 @@ +error: Undefined Behavior: calling a function with return type i32 passing return place of type i16 + --> tests/fail/shims/return_type_mismatch.rs:LL:CC + | +LL | close(fd); + | ^^^^^^^^^ calling a function with return type i32 passing return place of type i16 + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = help: this means these two types are not *guaranteed* to be ABI-compatible across all targets + = help: if you think this code should be accepted anyway, please report an issue with Miri + = note: BACKTRACE: + = note: inside `main` at tests/fail/shims/return_type_mismatch.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + From 21601fd04283d129db5af2ed74e07d6382cd0eda Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 12 Mar 2025 15:38:43 +0100 Subject: [PATCH 169/745] Improve `string_to_string` lint in case it is in a `map` call --- clippy_lints/src/strings.rs | 90 ++++++++++++++++++++++++++++++------- 1 file changed, 74 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 4a5f143a2d34..6762fc71d453 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::{snippet, snippet_with_applicability}; use clippy_utils::ty::is_type_lang_item; use clippy_utils::{ @@ -438,27 +438,85 @@ declare_clippy_lint! { declare_lint_pass!(StringToString => [STRING_TO_STRING]); +fn is_parent_map_like(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { + if let Some(parent_expr) = get_parent_expr(cx, expr) + && let ExprKind::MethodCall(name, ..) = parent_expr.kind + && name.ident.name == sym::map + && let Some(caller_def_id) = cx.typeck_results().type_dependent_def_id(parent_expr.hir_id) + && (clippy_utils::is_diag_item_method(cx, caller_def_id, sym::Result) + || clippy_utils::is_diag_item_method(cx, caller_def_id, sym::Option) + || clippy_utils::is_diag_trait_item(cx, caller_def_id, sym::Iterator)) + { + Some(parent_expr.span) + } else { + None + } +} + +fn is_called_from_map_like(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { + let parent = get_parent_expr(cx, expr)?; + + if matches!(parent.kind, ExprKind::Closure(_)) { + is_parent_map_like(cx, parent) + } else { + None + } +} + +fn suggest_cloned_string_to_string(cx: &LateContext<'_>, span: rustc_span::Span) { + span_lint_and_help( + cx, + STRING_TO_STRING, + span, + "`to_string()` called on a `String`", + None, + "consider using `.cloned()`", + ); +} + impl<'tcx> LateLintPass<'tcx> for StringToString { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { if expr.span.from_expansion() { return; } - if let ExprKind::MethodCall(path, self_arg, [], _) = &expr.kind - && path.ident.name == sym::to_string - && let ty = cx.typeck_results().expr_ty(self_arg) - && is_type_lang_item(cx, ty, LangItem::String) - { - #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] - span_lint_and_then( - cx, - STRING_TO_STRING, - expr.span, - "`to_string()` called on a `String`", - |diag| { - diag.help("consider using `.clone()`"); - }, - ); + match &expr.kind { + ExprKind::MethodCall(path, self_arg, [], _) => { + if path.ident.name == sym::to_string + && let ty = cx.typeck_results().expr_ty(self_arg) + && is_type_lang_item(cx, ty.peel_refs(), LangItem::String) + { + if let Some(parent_span) = is_called_from_map_like(cx, expr) { + suggest_cloned_string_to_string(cx, parent_span); + } else { + #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] + span_lint_and_then( + cx, + STRING_TO_STRING, + expr.span, + "`to_string()` called on a `String`", + |diag| { + diag.help("consider using `.clone()`"); + }, + ); + } + } + }, + ExprKind::Path(QPath::TypeRelative(ty, segment)) => { + if segment.ident.name == sym::to_string + && let rustc_hir::TyKind::Path(QPath::Resolved(_, path)) = ty.peel_refs().kind + && let rustc_hir::def::Res::Def(_, def_id) = path.res + && cx + .tcx + .lang_items() + .get(LangItem::String) + .is_some_and(|lang_id| lang_id == def_id) + && let Some(parent_span) = is_parent_map_like(cx, expr) + { + suggest_cloned_string_to_string(cx, parent_span); + } + }, + _ => {}, } } } From 0ffc6cf09781c971a083d25622088a684d091ff4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 12 Mar 2025 15:39:03 +0100 Subject: [PATCH 170/745] Add ui test for `string_to_string` in map calls --- tests/ui/string_to_string_in_map.rs | 25 +++++++++++ tests/ui/string_to_string_in_map.stderr | 55 +++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 tests/ui/string_to_string_in_map.rs create mode 100644 tests/ui/string_to_string_in_map.stderr diff --git a/tests/ui/string_to_string_in_map.rs b/tests/ui/string_to_string_in_map.rs new file mode 100644 index 000000000000..0afefa230730 --- /dev/null +++ b/tests/ui/string_to_string_in_map.rs @@ -0,0 +1,25 @@ +#![deny(clippy::string_to_string)] +#![allow(clippy::unnecessary_literal_unwrap, clippy::useless_vec)] + +fn main() { + let variable1 = String::new(); + let v = &variable1; + let variable2 = Some(v); + let _ = variable2.map(String::to_string); + //~^ string_to_string + let _ = variable2.map(|x| { + println!(); + x.to_string() + }); + //~^^ string_to_string + let _ = variable2.map(|x| x.to_string()); + //~^ string_to_string + let x = Some(String::new()); + let _ = x.unwrap_or_else(|| v.to_string()); + //~^ string_to_string + + let _ = vec![String::new()].iter().map(String::to_string).collect::>(); + //~^ string_to_string + let _ = vec![String::new()].iter().map(|x| x.to_string()).collect::>(); + //~^ string_to_string +} diff --git a/tests/ui/string_to_string_in_map.stderr b/tests/ui/string_to_string_in_map.stderr new file mode 100644 index 000000000000..f77606bbf1ae --- /dev/null +++ b/tests/ui/string_to_string_in_map.stderr @@ -0,0 +1,55 @@ +error: `to_string()` called on a `String` + --> tests/ui/string_to_string_in_map.rs:8:13 + | +LL | let _ = variable2.map(String::to_string); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using `.cloned()` +note: the lint level is defined here + --> tests/ui/string_to_string_in_map.rs:1:9 + | +LL | #![deny(clippy::string_to_string)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `to_string()` called on a `String` + --> tests/ui/string_to_string_in_map.rs:12:9 + | +LL | x.to_string() + | ^^^^^^^^^^^^^ + | + = help: consider using `.clone()` + +error: `to_string()` called on a `String` + --> tests/ui/string_to_string_in_map.rs:15:13 + | +LL | let _ = variable2.map(|x| x.to_string()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using `.cloned()` + +error: `to_string()` called on a `String` + --> tests/ui/string_to_string_in_map.rs:18:33 + | +LL | let _ = x.unwrap_or_else(|| v.to_string()); + | ^^^^^^^^^^^^^ + | + = help: consider using `.clone()` + +error: `to_string()` called on a `String` + --> tests/ui/string_to_string_in_map.rs:21:13 + | +LL | let _ = vec![String::new()].iter().map(String::to_string).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using `.cloned()` + +error: `to_string()` called on a `String` + --> tests/ui/string_to_string_in_map.rs:23:13 + | +LL | let _ = vec![String::new()].iter().map(|x| x.to_string()).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using `.cloned()` + +error: aborting due to 6 previous errors + From 559f23e1f2b0b2b39e6ee2ab20764bddd622fb5d Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Thu, 13 Mar 2025 02:01:16 +0500 Subject: [PATCH 171/745] Update copyright year --- COPYRIGHT | 2 +- LICENSE-APACHE | 2 +- LICENSE-MIT | 2 +- README.md | 2 +- clippy_utils/README.md | 2 +- rustc_tools_util/README.md | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/COPYRIGHT b/COPYRIGHT index 219693d63d97..f402dcf465a3 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,6 +1,6 @@ // REUSE-IgnoreStart -Copyright 2014-2024 The Rust Project Developers +Copyright 2014-2025 The Rust Project Developers Licensed under the Apache License, Version 2.0 or the MIT license diff --git a/LICENSE-APACHE b/LICENSE-APACHE index 506582c31d6d..9990a0cec474 100644 --- a/LICENSE-APACHE +++ b/LICENSE-APACHE @@ -186,7 +186,7 @@ APPENDIX: How to apply the Apache License to your work. same "printed page" as the copyright notice for easier identification within third-party archives. -Copyright 2014-2024 The Rust Project Developers +Copyright 2014-2025 The Rust Project Developers Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/LICENSE-MIT b/LICENSE-MIT index 6d8ee9afb616..5d6e36ef6bfc 100644 --- a/LICENSE-MIT +++ b/LICENSE-MIT @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2014-2024 The Rust Project Developers +Copyright (c) 2014-2025 The Rust Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff --git a/README.md b/README.md index 32c1d33e2ed3..20a5e997e629 100644 --- a/README.md +++ b/README.md @@ -277,7 +277,7 @@ If you want to contribute to Clippy, you can find more information in [CONTRIBUT -Copyright 2014-2024 The Rust Project Developers +Copyright 2014-2025 The Rust Project Developers Licensed under the Apache License, Version 2.0 or the MIT license diff --git a/clippy_utils/README.md b/clippy_utils/README.md index 5dd31b52f880..58c95b317b3b 100644 --- a/clippy_utils/README.md +++ b/clippy_utils/README.md @@ -30,7 +30,7 @@ Function signatures can change or be removed without replacement without any pri -Copyright 2014-2024 The Rust Project Developers +Copyright 2014-2025 The Rust Project Developers Licensed under the Apache License, Version 2.0 <[https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)> or the MIT license diff --git a/rustc_tools_util/README.md b/rustc_tools_util/README.md index ff4ca6f830e6..f47a4c69c2c3 100644 --- a/rustc_tools_util/README.md +++ b/rustc_tools_util/README.md @@ -51,7 +51,7 @@ The changelog for `rustc_tools_util` is available under: -Copyright 2014-2024 The Rust Project Developers +Copyright 2014-2025 The Rust Project Developers Licensed under the Apache License, Version 2.0 or the MIT license From 65bd61d2fbef50d28caed626ce601a908d5be77f Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 12 Mar 2025 09:47:11 +0100 Subject: [PATCH 172/745] Fix armv7-sony-vita-newlibeabihf LLVM target triple It was previously normalized by LLVM to `thumbv7a-vita-unknown-eabihf`, which is probably wrong, as Vita is the OS. --- .../src/spec/targets/armv7_sony_vita_newlibeabihf.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs index 5d292bbf8adf..6a83835059ee 100644 --- a/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs @@ -15,7 +15,7 @@ pub(crate) fn target() -> Target { ); Target { - llvm_target: "thumbv7a-vita-eabihf".into(), + llvm_target: "thumbv7a-sony-vita-eabihf".into(), metadata: TargetMetadata { description: Some( "Armv7-A Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain)".into(), From eab700a0aa4ad3079ad043a9cb4fb89edab3b4b7 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 12 Mar 2025 23:37:35 +0100 Subject: [PATCH 173/745] Fix uclibc LLVM target triples `uclibc` is not an environment understood by LLVM, it is only a concept in Clang that can be selected with `-muclibc` (it affects which dynamic linker is passed to the static linker's `-dynamic-linker` flag). In fact, using `uclibcgnueabi`/`uclibc` is actively harmful, as it prevents LLVM from seeing that the target is gnu-like; we should use `gnueabi`/`gnu` directly instead. --- .../src/spec/targets/armv5te_unknown_linux_uclibceabi.rs | 2 +- .../rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs | 2 +- .../src/spec/targets/mipsel_unknown_linux_uclibc.rs | 2 +- .../rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs index dbe1540364ad..860629b08e19 100644 --- a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs @@ -2,7 +2,7 @@ use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base}; pub(crate) fn target() -> Target { Target { - llvm_target: "armv5te-unknown-linux-uclibcgnueabi".into(), + llvm_target: "armv5te-unknown-linux-gnueabi".into(), metadata: TargetMetadata { description: Some("Armv5TE Linux with uClibc".into()), tier: Some(3), diff --git a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs index 0955b3debea0..c14bfbf46d21 100644 --- a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs +++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs @@ -4,7 +4,7 @@ use crate::spec::{Target, TargetMetadata, TargetOptions, base}; pub(crate) fn target() -> Target { Target { - llvm_target: "mips-unknown-linux-uclibc".into(), + llvm_target: "mips-unknown-linux-gnu".into(), metadata: TargetMetadata { description: Some("MIPS Linux with uClibc".into()), tier: Some(3), diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs index 08c4347fe014..f0056799d66f 100644 --- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs @@ -2,7 +2,7 @@ use crate::spec::{Target, TargetMetadata, TargetOptions, base}; pub(crate) fn target() -> Target { Target { - llvm_target: "mipsel-unknown-linux-uclibc".into(), + llvm_target: "mipsel-unknown-linux-gnu".into(), metadata: TargetMetadata { description: Some("MIPS (LE) Linux with uClibc".into()), tier: Some(3), diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs index a034a9fb2445..4107249dcf1e 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs @@ -8,7 +8,7 @@ pub(crate) fn target() -> Target { base.panic_strategy = PanicStrategy::Abort; Target { - llvm_target: "x86_64-unknown-l4re-uclibc".into(), + llvm_target: "x86_64-unknown-l4re-gnu".into(), metadata: TargetMetadata { description: None, tier: Some(3), From 025eecc3e7e36bb60bdd4e30ae05b9fa3876d14f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 12 Mar 2025 12:36:40 +0100 Subject: [PATCH 174/745] atomic intrinsics: clarify which types are supported and (if applicable) what happens with provenance --- src/intrinsics/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 6735ae024d1c..75f3a3c19724 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -1031,7 +1031,7 @@ fn codegen_regular_intrinsic_call<'tcx>( let layout = src.layout(); match layout.ty.kind() { - ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} + ty::Int(_) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); return Ok(()); @@ -1052,7 +1052,7 @@ fn codegen_regular_intrinsic_call<'tcx>( let layout = src.layout(); match layout.ty.kind() { - ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} + ty::Uint(_) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); return Ok(()); @@ -1073,7 +1073,7 @@ fn codegen_regular_intrinsic_call<'tcx>( let layout = src.layout(); match layout.ty.kind() { - ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} + ty::Int(_) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); return Ok(()); @@ -1094,7 +1094,7 @@ fn codegen_regular_intrinsic_call<'tcx>( let layout = src.layout(); match layout.ty.kind() { - ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} + ty::Uint(_) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); return Ok(()); From c58c06a6f51f2de7a869e278d08438c34a6ea86f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 11 Mar 2025 15:33:37 +0100 Subject: [PATCH 175/745] Return blocks from DropTree::build_mir Rather than requiring the user to pass in a correctly sized blocks map. --- compiler/rustc_mir_build/src/builder/scope.rs | 37 +++++++++---------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index 27ff01b48034..e56c0ae92cac 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -305,27 +305,25 @@ impl DropTree { } /// Builds the MIR for a given drop tree. - /// - /// `blocks` should have the same length as `self.drops`, and may have its - /// first value set to some already existing block. fn build_mir<'tcx, T: DropTreeBuilder<'tcx>>( &mut self, cfg: &mut CFG<'tcx>, - blocks: &mut IndexVec>, - ) { + root_node: Option, + ) -> IndexVec> { debug!("DropTree::build_mir(drops = {:#?})", self); - assert_eq!(blocks.len(), self.drops.len()); - self.assign_blocks::(cfg, blocks); - self.link_blocks(cfg, blocks) + let mut blocks = self.assign_blocks::(cfg, root_node); + self.link_blocks(cfg, &mut blocks); + + blocks } /// Assign blocks for all of the drops in the drop tree that need them. fn assign_blocks<'tcx, T: DropTreeBuilder<'tcx>>( &mut self, cfg: &mut CFG<'tcx>, - blocks: &mut IndexVec>, - ) { + root_node: Option, + ) -> IndexVec> { // StorageDead statements can share blocks with each other and also with // a Drop terminator. We iterate through the drops to find which drops // need their own block. @@ -342,8 +340,11 @@ impl DropTree { Own, } + let mut blocks = IndexVec::from_elem(None, &self.drops); + blocks[ROOT_NODE] = root_node; + let mut needs_block = IndexVec::from_elem(Block::None, &self.drops); - if blocks[ROOT_NODE].is_some() { + if root_node.is_some() { // In some cases (such as drops for `continue`) the root node // already has a block. In this case, make sure that we don't // override it. @@ -385,6 +386,8 @@ impl DropTree { debug!("assign_blocks: blocks = {:#?}", blocks); assert!(entry_points.is_empty()); + + blocks } fn link_blocks<'tcx>( @@ -1574,10 +1577,7 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> { span: Span, continue_block: Option, ) -> Option> { - let mut blocks = IndexVec::from_elem(None, &drops.drops); - blocks[ROOT_NODE] = continue_block; - - drops.build_mir::(&mut self.cfg, &mut blocks); + let blocks = drops.build_mir::(&mut self.cfg, continue_block); let is_coroutine = self.coroutine.is_some(); // Link the exit drop tree to unwind drop tree. @@ -1633,8 +1633,7 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> { let drops = &mut self.scopes.coroutine_drops; let cfg = &mut self.cfg; let fn_span = self.fn_span; - let mut blocks = IndexVec::from_elem(None, &drops.drops); - drops.build_mir::(cfg, &mut blocks); + let blocks = drops.build_mir::(cfg, None); if let Some(root_block) = blocks[ROOT_NODE] { cfg.terminate( root_block, @@ -1670,9 +1669,7 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> { fn_span: Span, resume_block: &mut Option, ) { - let mut blocks = IndexVec::from_elem(None, &drops.drops); - blocks[ROOT_NODE] = *resume_block; - drops.build_mir::(cfg, &mut blocks); + let blocks = drops.build_mir::(cfg, *resume_block); if let (None, Some(resume)) = (*resume_block, blocks[ROOT_NODE]) { cfg.terminate(resume, SourceInfo::outermost(fn_span), TerminatorKind::UnwindResume); From 8dc0c0ece93164da4d10a020a79201c95341bc9f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 12 Mar 2025 13:39:26 +0100 Subject: [PATCH 176/745] Simplify lit_to_mir_constant a bit --- .../src/builder/expr/as_constant.rs | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs index f743ea60a456..64d092e03545 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs @@ -105,23 +105,19 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx> return Const::Ty(Ty::new_error(tcx, guar), ty::Const::new_error(tcx, guar)); } - let trunc = |n, width: ty::UintTy| { - let width = width - .normalize(tcx.data_layout.pointer_size.bits().try_into().unwrap()) - .bit_width() - .unwrap(); - let width = Size::from_bits(width); + let lit_ty = match *ty.kind() { + ty::Pat(base, _) => base, + _ => ty, + }; + + let trunc = |n| { + let width = lit_ty.primitive_size(tcx); trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits()); let result = width.truncate(n); trace!("trunc result: {}", result); ConstValue::Scalar(Scalar::from_uint(result, width)) }; - let lit_ty = match *ty.kind() { - ty::Pat(base, _) => base, - _ => ty, - }; - let value = match (lit, lit_ty.kind()) { (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => { let s = s.as_str(); @@ -149,11 +145,10 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx> (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => { ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1))) } - (ast::LitKind::Int(n, _), ty::Uint(ui)) if !neg => trunc(n.get(), *ui), - (ast::LitKind::Int(n, _), ty::Int(i)) => trunc( - if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() }, - i.to_unsigned(), - ), + (ast::LitKind::Int(n, _), ty::Uint(_)) if !neg => trunc(n.get()), + (ast::LitKind::Int(n, _), ty::Int(_)) => { + trunc(if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() }) + } (ast::LitKind::Float(n, _), ty::Float(fty)) => { parse_float_into_constval(*n, *fty, neg).unwrap() } From 0e4b6c8124b1be1b0c353fc9a68566e106c72953 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 13 Mar 2025 11:46:02 +0100 Subject: [PATCH 177/745] Make `string_to_string` emit a suggestion when `cloned` can be used --- clippy_lints/src/strings.rs | 13 ++++---- tests/ui/string_to_string.rs | 16 +++++++++- tests/ui/string_to_string.stderr | 18 ++++++++++- tests/ui/string_to_string_in_map.fixed | 17 ++++++++++ tests/ui/string_to_string_in_map.rs | 10 +----- tests/ui/string_to_string_in_map.stderr | 41 ++++++------------------- 6 files changed, 66 insertions(+), 49 deletions(-) create mode 100644 tests/ui/string_to_string_in_map.fixed diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 6762fc71d453..247b5e270f82 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::{snippet, snippet_with_applicability}; use clippy_utils::ty::is_type_lang_item; use clippy_utils::{ @@ -440,14 +440,14 @@ declare_lint_pass!(StringToString => [STRING_TO_STRING]); fn is_parent_map_like(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { if let Some(parent_expr) = get_parent_expr(cx, expr) - && let ExprKind::MethodCall(name, ..) = parent_expr.kind + && let ExprKind::MethodCall(name, _, _, parent_span) = parent_expr.kind && name.ident.name == sym::map && let Some(caller_def_id) = cx.typeck_results().type_dependent_def_id(parent_expr.hir_id) && (clippy_utils::is_diag_item_method(cx, caller_def_id, sym::Result) || clippy_utils::is_diag_item_method(cx, caller_def_id, sym::Option) || clippy_utils::is_diag_trait_item(cx, caller_def_id, sym::Iterator)) { - Some(parent_expr.span) + Some(parent_span) } else { None } @@ -464,13 +464,14 @@ fn is_called_from_map_like(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option, span: rustc_span::Span) { - span_lint_and_help( + span_lint_and_sugg( cx, STRING_TO_STRING, span, "`to_string()` called on a `String`", - None, - "consider using `.cloned()`", + "try", + "cloned()".to_string(), + Applicability::MachineApplicable, ); } diff --git a/tests/ui/string_to_string.rs b/tests/ui/string_to_string.rs index 94174e1253b8..8c97d8c16f93 100644 --- a/tests/ui/string_to_string.rs +++ b/tests/ui/string_to_string.rs @@ -1,8 +1,22 @@ #![warn(clippy::string_to_string)] -#![allow(clippy::redundant_clone)] +#![allow(clippy::redundant_clone, clippy::unnecessary_literal_unwrap)] fn main() { let mut message = String::from("Hello"); let mut v = message.to_string(); //~^ string_to_string + + let variable1 = String::new(); + let v = &variable1; + let variable2 = Some(v); + let _ = variable2.map(|x| { + println!(); + x.to_string() + }); + //~^^ string_to_string + + // Should not lint. + let x = Some(String::new()); + let _ = x.unwrap_or_else(|| v.to_string()); + //~^ string_to_string } diff --git a/tests/ui/string_to_string.stderr b/tests/ui/string_to_string.stderr index ae80597d1f84..c0e2e75f51a7 100644 --- a/tests/ui/string_to_string.stderr +++ b/tests/ui/string_to_string.stderr @@ -8,5 +8,21 @@ LL | let mut v = message.to_string(); = note: `-D clippy::string-to-string` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::string_to_string)]` -error: aborting due to 1 previous error +error: `to_string()` called on a `String` + --> tests/ui/string_to_string.rs:14:9 + | +LL | x.to_string() + | ^^^^^^^^^^^^^ + | + = help: consider using `.clone()` + +error: `to_string()` called on a `String` + --> tests/ui/string_to_string.rs:20:33 + | +LL | let _ = x.unwrap_or_else(|| v.to_string()); + | ^^^^^^^^^^^^^ + | + = help: consider using `.clone()` + +error: aborting due to 3 previous errors diff --git a/tests/ui/string_to_string_in_map.fixed b/tests/ui/string_to_string_in_map.fixed new file mode 100644 index 000000000000..b004fd736adf --- /dev/null +++ b/tests/ui/string_to_string_in_map.fixed @@ -0,0 +1,17 @@ +#![deny(clippy::string_to_string)] +#![allow(clippy::unnecessary_literal_unwrap, clippy::useless_vec, clippy::iter_cloned_collect)] + +fn main() { + let variable1 = String::new(); + let v = &variable1; + let variable2 = Some(v); + let _ = variable2.cloned(); + //~^ string_to_string + let _ = variable2.cloned(); + //~^ string_to_string + + let _ = vec![String::new()].iter().cloned().collect::>(); + //~^ string_to_string + let _ = vec![String::new()].iter().cloned().collect::>(); + //~^ string_to_string +} diff --git a/tests/ui/string_to_string_in_map.rs b/tests/ui/string_to_string_in_map.rs index 0afefa230730..387abe84205d 100644 --- a/tests/ui/string_to_string_in_map.rs +++ b/tests/ui/string_to_string_in_map.rs @@ -1,5 +1,5 @@ #![deny(clippy::string_to_string)] -#![allow(clippy::unnecessary_literal_unwrap, clippy::useless_vec)] +#![allow(clippy::unnecessary_literal_unwrap, clippy::useless_vec, clippy::iter_cloned_collect)] fn main() { let variable1 = String::new(); @@ -7,16 +7,8 @@ fn main() { let variable2 = Some(v); let _ = variable2.map(String::to_string); //~^ string_to_string - let _ = variable2.map(|x| { - println!(); - x.to_string() - }); - //~^^ string_to_string let _ = variable2.map(|x| x.to_string()); //~^ string_to_string - let x = Some(String::new()); - let _ = x.unwrap_or_else(|| v.to_string()); - //~^ string_to_string let _ = vec![String::new()].iter().map(String::to_string).collect::>(); //~^ string_to_string diff --git a/tests/ui/string_to_string_in_map.stderr b/tests/ui/string_to_string_in_map.stderr index f77606bbf1ae..44e2119c1002 100644 --- a/tests/ui/string_to_string_in_map.stderr +++ b/tests/ui/string_to_string_in_map.stderr @@ -1,10 +1,9 @@ error: `to_string()` called on a `String` - --> tests/ui/string_to_string_in_map.rs:8:13 + --> tests/ui/string_to_string_in_map.rs:8:23 | LL | let _ = variable2.map(String::to_string); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `cloned()` | - = help: consider using `.cloned()` note: the lint level is defined here --> tests/ui/string_to_string_in_map.rs:1:9 | @@ -12,44 +11,22 @@ LL | #![deny(clippy::string_to_string)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: `to_string()` called on a `String` - --> tests/ui/string_to_string_in_map.rs:12:9 - | -LL | x.to_string() - | ^^^^^^^^^^^^^ - | - = help: consider using `.clone()` - -error: `to_string()` called on a `String` - --> tests/ui/string_to_string_in_map.rs:15:13 + --> tests/ui/string_to_string_in_map.rs:10:23 | LL | let _ = variable2.map(|x| x.to_string()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider using `.cloned()` + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `cloned()` error: `to_string()` called on a `String` - --> tests/ui/string_to_string_in_map.rs:18:33 - | -LL | let _ = x.unwrap_or_else(|| v.to_string()); - | ^^^^^^^^^^^^^ - | - = help: consider using `.clone()` - -error: `to_string()` called on a `String` - --> tests/ui/string_to_string_in_map.rs:21:13 + --> tests/ui/string_to_string_in_map.rs:13:40 | LL | let _ = vec![String::new()].iter().map(String::to_string).collect::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider using `.cloned()` + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `cloned()` error: `to_string()` called on a `String` - --> tests/ui/string_to_string_in_map.rs:23:13 + --> tests/ui/string_to_string_in_map.rs:15:40 | LL | let _ = vec![String::new()].iter().map(|x| x.to_string()).collect::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider using `.cloned()` + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `cloned()` -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors From f9696dda6e9d88a88c057e93fbc854104996bc33 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 7 Mar 2025 17:52:17 +0000 Subject: [PATCH 178/745] Prefer built-in sized impls for rigid types always --- compiler/rustc_middle/src/traits/select.rs | 5 +++- .../src/traits/select/candidate_assembly.rs | 24 +++++++++++++++---- .../src/traits/select/confirmation.rs | 5 ++++ .../src/traits/select/mod.rs | 13 +++++++++- 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 811bd8fb4588..749f3c31bf8d 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -95,10 +95,13 @@ pub type EvaluationCache<'tcx, ENV> = Cache<(ENV, ty::PolyTraitPredicate<'tcx>), /// parameter environment. #[derive(PartialEq, Eq, Debug, Clone, TypeVisitable)] pub enum SelectionCandidate<'tcx> { + /// UwU + SizedCandidate, + /// A builtin implementation for some specific traits, used in cases /// where we cannot rely an ordinary library implementations. /// - /// The most notable examples are `sized`, `Copy` and `Clone`. This is also + /// The most notable examples are `Copy` and `Clone`. This is also /// used for the `DiscriminantKind` and `Pointee` trait, both of which have /// an associated type. BuiltinCandidate { diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index a8d8003ead6e..9c0efec2e6cf 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -86,10 +86,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // `Pointee` is automatically implemented for every type. candidates.vec.push(BuiltinCandidate { has_nested: false }); } else if tcx.is_lang_item(def_id, LangItem::Sized) { - // Sized is never implementable by end-users, it is - // always automatically computed. - let sized_conditions = self.sized_conditions(obligation); - self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates); + self.assemble_builtin_sized_candidate(obligation, &mut candidates); } else if tcx.is_lang_item(def_id, LangItem::Unsize) { self.assemble_candidates_for_unsizing(obligation, &mut candidates); } else if tcx.is_lang_item(def_id, LangItem::Destruct) { @@ -1059,6 +1056,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Assembles the trait which are built-in to the language itself: /// `Copy`, `Clone` and `Sized`. #[instrument(level = "debug", skip(self, candidates))] + fn assemble_builtin_sized_candidate( + &mut self, + obligation: &PolyTraitObligation<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>, + ) { + match self.sized_conditions(obligation) { + BuiltinImplConditions::Where(_) => { + candidates.vec.push(SizedCandidate); + } + BuiltinImplConditions::None => {} + BuiltinImplConditions::Ambiguous => { + candidates.ambiguous = true; + } + } + } + + /// Assembles the trait which are built-in to the language itself: + /// e.g. `Copy` and `Clone`. + #[instrument(level = "debug", skip(self, candidates))] fn assemble_builtin_bound_candidates( &mut self, conditions: BuiltinImplConditions<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 4cd6781ab890..349eab2cbe39 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -40,6 +40,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidate: SelectionCandidate<'tcx>, ) -> Result, SelectionError<'tcx>> { let mut impl_src = match candidate { + SizedCandidate => { + let data = self.confirm_builtin_candidate(obligation, true); + ImplSource::Builtin(BuiltinImplSource::Misc, data) + } + BuiltinCandidate { has_nested } => { let data = self.confirm_builtin_candidate(obligation, has_nested); ImplSource::Builtin(BuiltinImplSource::Misc, data) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index e1adabbeaa66..674ff30786bc 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1801,6 +1801,16 @@ impl<'tcx> SelectionContext<'_, 'tcx> { return Some(candidates.pop().unwrap().candidate); } + // We prefer `Sized` candidates over everything. + let mut sized_candidates = + candidates.iter().filter(|c| matches!(c.candidate, SizedCandidate)); + if let Some(_sized_candidate) = sized_candidates.next() { + // There should only ever be a single sized candidate + // as they would otherwise overlap. + debug_assert_eq!(sized_candidates.next(), None); + return Some(SizedCandidate); + } + // We prefer trivial builtin candidates, i.e. builtin impls without any nested // requirements, over all others. This is a fix for #53123 and prevents winnowing // from accidentally extending the lifetime of a variable. @@ -1940,7 +1950,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // Don't use impl candidates which overlap with other candidates. // This should pretty much only ever happen with malformed impls. if candidates.iter().all(|c| match c.candidate { - BuiltinCandidate { has_nested: _ } + SizedCandidate + | BuiltinCandidate { has_nested: _ } | TransmutabilityCandidate | AutoImplCandidate | ClosureCandidate { .. } From aebbd424607b7797f231bc09f44226fcd3040d7e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 10 Mar 2025 16:50:29 +0000 Subject: [PATCH 179/745] Only prefer Sized candidates, and only if they certainly hold --- compiler/rustc_middle/src/traits/select.rs | 7 +++-- .../src/traits/select/candidate_assembly.rs | 6 ++-- .../src/traits/select/confirmation.rs | 4 +-- .../src/traits/select/mod.rs | 28 ++++++++----------- .../dont-incompletely-prefer-built-in.rs | 21 ++++++++++++++ ...incomplete-prefer-sized-builtin-over-wc.rs | 19 +++++++++++++ ...mplete-prefer-sized-builtin-over-wc.stderr | 27 ++++++++++++++++++ 7 files changed, 89 insertions(+), 23 deletions(-) create mode 100644 tests/ui/sized/dont-incompletely-prefer-built-in.rs create mode 100644 tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs create mode 100644 tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.stderr diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 749f3c31bf8d..aa2ee756bc50 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -95,8 +95,11 @@ pub type EvaluationCache<'tcx, ENV> = Cache<(ENV, ty::PolyTraitPredicate<'tcx>), /// parameter environment. #[derive(PartialEq, Eq, Debug, Clone, TypeVisitable)] pub enum SelectionCandidate<'tcx> { - /// UwU - SizedCandidate, + /// A built-in implementation for the `Sized` trait. This is preferred + /// over all other candidates. + SizedCandidate { + has_nested: bool, + }, /// A builtin implementation for some specific traits, used in cases /// where we cannot rely an ordinary library implementations. diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 9c0efec2e6cf..316198f9e012 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -1062,8 +1062,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates: &mut SelectionCandidateSet<'tcx>, ) { match self.sized_conditions(obligation) { - BuiltinImplConditions::Where(_) => { - candidates.vec.push(SizedCandidate); + BuiltinImplConditions::Where(nested) => { + candidates + .vec + .push(SizedCandidate { has_nested: !nested.skip_binder().is_empty() }); } BuiltinImplConditions::None => {} BuiltinImplConditions::Ambiguous => { diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 349eab2cbe39..29e0b833665b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -40,8 +40,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidate: SelectionCandidate<'tcx>, ) -> Result, SelectionError<'tcx>> { let mut impl_src = match candidate { - SizedCandidate => { - let data = self.confirm_builtin_candidate(obligation, true); + SizedCandidate { has_nested } => { + let data = self.confirm_builtin_candidate(obligation, has_nested); ImplSource::Builtin(BuiltinImplSource::Misc, data) } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 674ff30786bc..956417b122c6 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1803,25 +1803,19 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // We prefer `Sized` candidates over everything. let mut sized_candidates = - candidates.iter().filter(|c| matches!(c.candidate, SizedCandidate)); - if let Some(_sized_candidate) = sized_candidates.next() { + candidates.iter().filter(|c| matches!(c.candidate, SizedCandidate { has_nested: _ })); + if let Some(sized_candidate) = sized_candidates.next() { // There should only ever be a single sized candidate // as they would otherwise overlap. debug_assert_eq!(sized_candidates.next(), None); - return Some(SizedCandidate); - } - - // We prefer trivial builtin candidates, i.e. builtin impls without any nested - // requirements, over all others. This is a fix for #53123 and prevents winnowing - // from accidentally extending the lifetime of a variable. - let mut trivial_builtin = candidates - .iter() - .filter(|c| matches!(c.candidate, BuiltinCandidate { has_nested: false })); - if let Some(_trivial) = trivial_builtin.next() { - // There should only ever be a single trivial builtin candidate - // as they would otherwise overlap. - debug_assert_eq!(trivial_builtin.next(), None); - return Some(BuiltinCandidate { has_nested: false }); + // Only prefer the built-in `Sized` candidate if its nested goals are certain. + // Otherwise, we may encounter failure later on if inference causes this candidate + // to not hold, but a where clause would've applied instead. + if sized_candidate.evaluation.must_apply_modulo_regions() { + return Some(sized_candidate.candidate.clone()); + } else { + return None; + } } // Before we consider where-bounds, we have to deduplicate them here and also @@ -1950,7 +1944,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // Don't use impl candidates which overlap with other candidates. // This should pretty much only ever happen with malformed impls. if candidates.iter().all(|c| match c.candidate { - SizedCandidate + SizedCandidate { has_nested: _ } | BuiltinCandidate { has_nested: _ } | TransmutabilityCandidate | AutoImplCandidate diff --git a/tests/ui/sized/dont-incompletely-prefer-built-in.rs b/tests/ui/sized/dont-incompletely-prefer-built-in.rs new file mode 100644 index 000000000000..f5bf0c8915e7 --- /dev/null +++ b/tests/ui/sized/dont-incompletely-prefer-built-in.rs @@ -0,0 +1,21 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +struct W(T); + +fn is_sized(x: *const T) {} + +fn dummy() -> *const T { todo!() } + +fn non_param_where_bound() +where + W: Sized, +{ + let x: *const W<_> = dummy(); + is_sized::>(x); + let _: *const W = x; +} + +fn main() {} diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs new file mode 100644 index 000000000000..cc3303dccd57 --- /dev/null +++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs @@ -0,0 +1,19 @@ +struct MyType<'a, T: ?Sized>(&'a (), T); + +fn is_sized() {} + +fn foo<'a, T: ?Sized>() +where + (MyType<'a, T>,): Sized, + //~^ ERROR mismatched types + MyType<'static, T>: Sized, +{ + // Preferring the builtin `Sized` impl of tuples + // requires proving `MyType<'a, T>: Sized` which + // can only be proven by using the where-clause, + // adding an unnecessary `'static` constraint. + is_sized::<(MyType<'a, T>,)>(); + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.stderr b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.stderr new file mode 100644 index 000000000000..a54574f743f8 --- /dev/null +++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.stderr @@ -0,0 +1,27 @@ +error[E0308]: mismatched types + --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:7:23 + | +LL | (MyType<'a, T>,): Sized, + | ^^^^^ lifetime mismatch + | + = note: expected trait ` as Sized>` + found trait ` as Sized>` +note: the lifetime `'a` as defined here... + --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:5:8 + | +LL | fn foo<'a, T: ?Sized>() + | ^^ + = note: ...does not necessarily outlive the static lifetime + +error: lifetime may not live long enough + --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:15:5 + | +LL | fn foo<'a, T: ?Sized>() + | -- lifetime `'a` defined here +... +LL | is_sized::<(MyType<'a, T>,)>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From c0230f4a2904e968f4afd833e44db1f4ebe29b21 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 13 Mar 2025 21:17:46 +0000 Subject: [PATCH 180/745] Flesh out tests --- ...complete-infer-via-sized-wc.current.stderr | 9 ++++++ .../incomplete-infer-via-sized-wc.next.stderr | 9 ++++++ .../traits/incomplete-infer-via-sized-wc.rs | 19 +++++++++++++ ...complete-prefer-sized-builtin-over-wc-2.rs | 28 +++++++++++++++++++ ...efer-sized-builtin-over-wc.current.stderr} | 6 ++-- ...e-prefer-sized-builtin-over-wc.next.stderr | 25 +++++++++++++++++ ...incomplete-prefer-sized-builtin-over-wc.rs | 9 +++++- 7 files changed, 101 insertions(+), 4 deletions(-) create mode 100644 tests/ui/traits/incomplete-infer-via-sized-wc.current.stderr create mode 100644 tests/ui/traits/incomplete-infer-via-sized-wc.next.stderr create mode 100644 tests/ui/traits/incomplete-infer-via-sized-wc.rs create mode 100644 tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc-2.rs rename tests/ui/traits/{lifetime-incomplete-prefer-sized-builtin-over-wc.stderr => lifetime-incomplete-prefer-sized-builtin-over-wc.current.stderr} (85%) create mode 100644 tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.next.stderr diff --git a/tests/ui/traits/incomplete-infer-via-sized-wc.current.stderr b/tests/ui/traits/incomplete-infer-via-sized-wc.current.stderr new file mode 100644 index 000000000000..f4930bf890c2 --- /dev/null +++ b/tests/ui/traits/incomplete-infer-via-sized-wc.current.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/incomplete-infer-via-sized-wc.rs:15:5 + | +LL | is_sized::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `is_sized` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/incomplete-infer-via-sized-wc.next.stderr b/tests/ui/traits/incomplete-infer-via-sized-wc.next.stderr new file mode 100644 index 000000000000..f4930bf890c2 --- /dev/null +++ b/tests/ui/traits/incomplete-infer-via-sized-wc.next.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/incomplete-infer-via-sized-wc.rs:15:5 + | +LL | is_sized::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `is_sized` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/incomplete-infer-via-sized-wc.rs b/tests/ui/traits/incomplete-infer-via-sized-wc.rs new file mode 100644 index 000000000000..9dcddea3551d --- /dev/null +++ b/tests/ui/traits/incomplete-infer-via-sized-wc.rs @@ -0,0 +1,19 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Exercises change in . + +struct MaybeSized(T); + +fn is_sized() -> Box { todo!() } + +fn foo() +where + MaybeSized: Sized, +{ + is_sized::>(); + //~^ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc-2.rs b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc-2.rs new file mode 100644 index 000000000000..8a8f7b933b53 --- /dev/null +++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc-2.rs @@ -0,0 +1,28 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Exercises change in . + +trait Trait: Sized {} +impl Trait for T {} + +fn is_sized() {} + +fn normal_ref<'a, 'b, T>() +where + &'a u32: Trait, +{ + is_sized::<&'b u32>(); +} + +struct MyRef<'a, U: ?Sized = ()>(&'a u32, U); +fn my_ref<'a, 'b, T>() +where + MyRef<'a>: Trait, +{ + is_sized::>(); +} + +fn main() {} diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.stderr b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.current.stderr similarity index 85% rename from tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.stderr rename to tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.current.stderr index a54574f743f8..dd9393fae853 100644 --- a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.stderr +++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.current.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:7:23 + --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:13:23 | LL | (MyType<'a, T>,): Sized, | ^^^^^ lifetime mismatch @@ -7,14 +7,14 @@ LL | (MyType<'a, T>,): Sized, = note: expected trait ` as Sized>` found trait ` as Sized>` note: the lifetime `'a` as defined here... - --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:5:8 + --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:11:8 | LL | fn foo<'a, T: ?Sized>() | ^^ = note: ...does not necessarily outlive the static lifetime error: lifetime may not live long enough - --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:15:5 + --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:22:5 | LL | fn foo<'a, T: ?Sized>() | -- lifetime `'a` defined here diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.next.stderr b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.next.stderr new file mode 100644 index 000000000000..05861877d413 --- /dev/null +++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.next.stderr @@ -0,0 +1,25 @@ +error[E0478]: lifetime bound not satisfied + --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:13:23 + | +LL | (MyType<'a, T>,): Sized, + | ^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'a` as defined here + --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:11:8 + | +LL | fn foo<'a, T: ?Sized>() + | ^^ + = note: but lifetime parameter must outlive the static lifetime + +error: lifetime may not live long enough + --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:22:5 + | +LL | fn foo<'a, T: ?Sized>() + | -- lifetime `'a` defined here +... +LL | is_sized::<(MyType<'a, T>,)>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0478`. diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs index cc3303dccd57..ae7a6c9bba33 100644 --- a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs +++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs @@ -1,3 +1,9 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Exercises change in . + struct MyType<'a, T: ?Sized>(&'a (), T); fn is_sized() {} @@ -5,7 +11,8 @@ fn is_sized() {} fn foo<'a, T: ?Sized>() where (MyType<'a, T>,): Sized, - //~^ ERROR mismatched types + //[current]~^ ERROR mismatched types + //[next]~^^ ERROR lifetime bound not satisfied MyType<'static, T>: Sized, { // Preferring the builtin `Sized` impl of tuples From 18299e4491cac4c21f4f989cf4028022dbcf1002 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Fri, 14 Mar 2025 04:55:48 +0000 Subject: [PATCH 181/745] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 8b14b51496a8..2e649e688fa2 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -90384941aae4ea38de00e4702b50757e9b882a19 +addae0705c7cf5b2f2ed7faeec026c894f497b3d From bdaf23b4cd13dd39cebf1756686f581d6040df37 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Fri, 14 Mar 2025 12:19:04 +0100 Subject: [PATCH 182/745] Forward `stream_position` in `Arc` as well It was missed in #137165. --- library/std/src/fs.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index f9a360585e85..7fc010d2ec3f 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -1343,6 +1343,9 @@ impl Seek for Arc { fn seek(&mut self, pos: SeekFrom) -> io::Result { (&**self).seek(pos) } + fn stream_position(&mut self) -> io::Result { + (&**self).stream_position() + } } impl OpenOptions { From 3ca5220114c1e690d876aa46c3aa0f6ec594b9c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 7 Mar 2024 06:47:08 +0100 Subject: [PATCH 183/745] Represent diagnostic side effects as dep nodes --- compiler/rustc_interface/src/callbacks.rs | 5 +- .../rustc_middle/src/dep_graph/dep_node.rs | 1 + compiler/rustc_middle/src/dep_graph/mod.rs | 1 + .../rustc_middle/src/query/on_disk_cache.rs | 20 +--- compiler/rustc_middle/src/ty/context/tls.rs | 16 +-- compiler/rustc_query_impl/src/plumbing.rs | 48 ++++---- .../src/dep_graph/dep_node.rs | 5 +- .../rustc_query_system/src/dep_graph/graph.rs | 105 +++++++++++------- .../rustc_query_system/src/dep_graph/mod.rs | 12 +- compiler/rustc_query_system/src/query/mod.rs | 45 ++------ .../rustc_query_system/src/query/plumbing.rs | 60 ++++------ 11 files changed, 138 insertions(+), 180 deletions(-) diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs index f66b9eb3a285..7c6b7157f71a 100644 --- a/compiler/rustc_interface/src/callbacks.rs +++ b/compiler/rustc_interface/src/callbacks.rs @@ -14,6 +14,7 @@ use std::fmt; use rustc_errors::{DiagInner, TRACK_DIAGNOSTIC}; use rustc_middle::dep_graph::{DepNodeExt, TaskDepsRef}; use rustc_middle::ty::tls; +use rustc_query_impl::QueryCtxt; use rustc_query_system::dep_graph::dep_node::default_dep_kind_debug; use rustc_query_system::dep_graph::{DepContext, DepKind, DepNode}; @@ -41,9 +42,7 @@ fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) { fn track_diagnostic(diagnostic: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R { tls::with_context_opt(|icx| { if let Some(icx) = icx { - if let Some(diagnostics) = icx.diagnostics { - diagnostics.lock().extend(Some(diagnostic.clone())); - } + icx.tcx.dep_graph.record_diagnostic(QueryCtxt::new(icx.tcx), &diagnostic); // Diagnostics are tracked, we can ignore the dependency. let icx = tls::ImplicitCtxt { task_deps: TaskDepsRef::Ignore, ..icx.clone() }; diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 7525aeb92272..f967d8b92c71 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -79,6 +79,7 @@ rustc_query_append!(define_dep_nodes![ [] fn Null() -> (), /// We use this to create a forever-red node. [] fn Red() -> (), + [] fn SideEffect() -> (), [] fn TraitSelect() -> (), [] fn CompileCodegenUnit() -> (), [] fn CompileMonoItem() -> (), diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 2090c3e6da6f..c927538b4cf3 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -46,6 +46,7 @@ impl Deps for DepsType { const DEP_KIND_NULL: DepKind = dep_kinds::Null; const DEP_KIND_RED: DepKind = dep_kinds::Red; + const DEP_KIND_SIDE_EFFECT: DepKind = dep_kinds::SideEffect; const DEP_KIND_MAX: u16 = dep_node::DEP_KIND_VARIANTS - 1; } diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index d9035efaf56d..b4c5d1c6c055 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -357,11 +357,10 @@ impl OnDiskCache { &self, tcx: TyCtxt<'_>, dep_node_index: SerializedDepNodeIndex, - ) -> QuerySideEffects { + ) -> Option { let side_effects: Option = self.load_indexed(tcx, dep_node_index, &self.prev_side_effects_index); - - side_effects.unwrap_or_default() + side_effects } /// Stores a `QuerySideEffects` emitted during the current compilation session. @@ -395,21 +394,6 @@ impl OnDiskCache { opt_value } - /// Stores side effect emitted during computation of an anonymous query. - /// Since many anonymous queries can share the same `DepNode`, we aggregate - /// them -- as opposed to regular queries where we assume that there is a - /// 1:1 relationship between query-key and `DepNode`. - pub fn store_side_effects_for_anon_node( - &self, - dep_node_index: DepNodeIndex, - side_effects: QuerySideEffects, - ) { - let mut current_side_effects = self.current_side_effects.borrow_mut(); - - let x = current_side_effects.entry(dep_node_index).or_default(); - x.append(side_effects); - } - fn load_indexed<'tcx, T>( &self, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_middle/src/ty/context/tls.rs b/compiler/rustc_middle/src/ty/context/tls.rs index eaab8474dd20..5fc80bc79367 100644 --- a/compiler/rustc_middle/src/ty/context/tls.rs +++ b/compiler/rustc_middle/src/ty/context/tls.rs @@ -1,8 +1,6 @@ use std::{mem, ptr}; -use rustc_data_structures::sync::{self, Lock}; -use rustc_errors::DiagInner; -use thin_vec::ThinVec; +use rustc_data_structures::sync; use super::{GlobalCtxt, TyCtxt}; use crate::dep_graph::TaskDepsRef; @@ -22,10 +20,6 @@ pub struct ImplicitCtxt<'a, 'tcx> { /// `ty::query::plumbing` when executing a query. pub query: Option, - /// Where to store diagnostics for the current query job, if any. - /// This is updated by `JobOwner::start` in `ty::query::plumbing` when executing a query. - pub diagnostics: Option<&'a Lock>>, - /// Used to prevent queries from calling too deeply. pub query_depth: usize, @@ -37,13 +31,7 @@ pub struct ImplicitCtxt<'a, 'tcx> { impl<'a, 'tcx> ImplicitCtxt<'a, 'tcx> { pub fn new(gcx: &'tcx GlobalCtxt<'tcx>) -> Self { let tcx = TyCtxt { gcx }; - ImplicitCtxt { - tcx, - query: None, - diagnostics: None, - query_depth: 0, - task_deps: TaskDepsRef::Ignore, - } + ImplicitCtxt { tcx, query: None, query_depth: 0, task_deps: TaskDepsRef::Ignore } } } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index f98d6421307a..47158f6d7aaf 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -5,9 +5,7 @@ use std::num::NonZero; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_data_structures::sync::Lock; use rustc_data_structures::unord::UnordMap; -use rustc_errors::DiagInner; use rustc_hashes::Hash64; use rustc_index::Idx; use rustc_middle::bug; @@ -32,7 +30,6 @@ use rustc_query_system::{QueryOverflow, QueryOverflowNote}; use rustc_serialize::{Decodable, Encodable}; use rustc_session::Limit; use rustc_span::def_id::LOCAL_CRATE; -use thin_vec::ThinVec; use crate::QueryConfigRestored; @@ -92,12 +89,14 @@ impl QueryContext for QueryCtxt<'_> { } // Interactions with on_disk_cache - fn load_side_effects(self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects { + fn load_side_effects( + self, + prev_dep_node_index: SerializedDepNodeIndex, + ) -> Option { self.query_system .on_disk_cache .as_ref() - .map(|c| c.load_side_effects(self.tcx, prev_dep_node_index)) - .unwrap_or_default() + .and_then(|c| c.load_side_effects(self.tcx, prev_dep_node_index)) } #[inline(never)] @@ -108,27 +107,13 @@ impl QueryContext for QueryCtxt<'_> { } } - #[inline(never)] - #[cold] - fn store_side_effects_for_anon_node( - self, - dep_node_index: DepNodeIndex, - side_effects: QuerySideEffects, - ) { - if let Some(c) = self.query_system.on_disk_cache.as_ref() { - c.store_side_effects_for_anon_node(dep_node_index, side_effects) - } - } - /// Executes a job by changing the `ImplicitCtxt` to point to the - /// new query job while it executes. It returns the diagnostics - /// captured during execution and the actual result. + /// new query job while it executes. #[inline(always)] fn start_query( self, token: QueryJobId, depth_limit: bool, - diagnostics: Option<&Lock>>, compute: impl FnOnce() -> R, ) -> R { // The `TyCtxt` stored in TLS has the same global interner lifetime @@ -143,7 +128,6 @@ impl QueryContext for QueryCtxt<'_> { let new_icx = ImplicitCtxt { tcx: self.tcx, query: Some(token), - diagnostics, query_depth: current_icx.query_depth + depth_limit as usize, task_deps: current_icx.task_deps, }; @@ -500,7 +484,7 @@ where is_anon, is_eval_always, fingerprint_style, - force_from_dep_node: Some(|tcx, dep_node| { + force_from_dep_node: Some(|tcx, dep_node, _| { force_from_dep_node(Q::config(tcx), tcx, dep_node) }), try_load_from_on_disk_cache: Some(|tcx, dep_node| { @@ -802,7 +786,7 @@ macro_rules! define_queries { is_anon: false, is_eval_always: false, fingerprint_style: FingerprintStyle::Unit, - force_from_dep_node: Some(|_, dep_node| bug!("force_from_dep_node: encountered {:?}", dep_node)), + force_from_dep_node: Some(|_, dep_node, _| bug!("force_from_dep_node: encountered {:?}", dep_node)), try_load_from_on_disk_cache: None, name: &"Null", } @@ -814,12 +798,26 @@ macro_rules! define_queries { is_anon: false, is_eval_always: false, fingerprint_style: FingerprintStyle::Unit, - force_from_dep_node: Some(|_, dep_node| bug!("force_from_dep_node: encountered {:?}", dep_node)), + force_from_dep_node: Some(|_, dep_node, _| bug!("force_from_dep_node: encountered {:?}", dep_node)), try_load_from_on_disk_cache: None, name: &"Red", } } + pub(crate) fn SideEffect<'tcx>() -> DepKindStruct<'tcx> { + DepKindStruct { + is_anon: false, + is_eval_always: false, + fingerprint_style: FingerprintStyle::Unit, + force_from_dep_node: Some(|tcx, _, prev_index| { + tcx.dep_graph.force_diagnostic_node(QueryCtxt::new(tcx), prev_index); + true + }), + try_load_from_on_disk_cache: None, + name: &"SideEffect", + } + } + pub(crate) fn TraitSelect<'tcx>() -> DepKindStruct<'tcx> { DepKindStruct { is_anon: true, diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs index 9d3368607a21..c0b3bd43e25a 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -64,7 +64,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, use rustc_hir::definitions::DefPathHash; use rustc_macros::{Decodable, Encodable}; -use super::{DepContext, FingerprintStyle}; +use super::{DepContext, FingerprintStyle, SerializedDepNodeIndex}; use crate::ich::StableHashingContext; /// This serves as an index into arrays built by `make_dep_kind_array`. @@ -275,7 +275,8 @@ pub struct DepKindStruct { /// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode` /// is actually a `DefPathHash`, and can therefore just look up the corresponding /// `DefId` in `tcx.def_path_hash_to_def_id`. - pub force_from_dep_node: Option bool>, + pub force_from_dep_node: + Option bool>, /// Invoke a query to put the on-disk cached value in memory. pub try_load_from_on_disk_cache: Option, diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 3109d53cd2ca..de681328bcb5 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -5,13 +5,14 @@ use std::marker::PhantomData; use std::sync::Arc; use std::sync::atomic::{AtomicU32, Ordering}; -use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::profiling::{QueryInvocationId, SelfProfilerRef}; use rustc_data_structures::sharded::{self, ShardedHashMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{AtomicU64, Lock}; use rustc_data_structures::unord::UnordMap; +use rustc_errors::DiagInner; use rustc_index::IndexVec; use rustc_macros::{Decodable, Encodable}; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; @@ -91,8 +92,6 @@ pub(crate) struct DepGraphData { colors: DepNodeColorMap, - processed_side_effects: Lock>, - /// When we load, there may be `.o` files, cached MIR, or other such /// things available to us. If we find that they are not dirty, we /// load the path to the file storing those work-products here into @@ -174,7 +173,6 @@ impl DepGraph { previous_work_products: prev_work_products, dep_node_debug: Default::default(), current, - processed_side_effects: Default::default(), previous: prev_graph, colors, debug_loaded_from_disk: Default::default(), @@ -535,6 +533,24 @@ impl DepGraph { } } + #[inline] + pub fn record_diagnostic(&self, qcx: Qcx, diagnostic: &DiagInner) { + if let Some(ref data) = self.data { + self.read_index(data.encode_diagnostic(qcx, diagnostic)); + } + } + + #[inline] + pub fn force_diagnostic_node( + &self, + qcx: Qcx, + prev_index: SerializedDepNodeIndex, + ) { + if let Some(ref data) = self.data { + data.force_diagnostic_node(qcx, prev_index); + } + } + /// Create a node when we force-feed a value into the query cache. /// This is used to remove cycles during type-checking const generic parameters. /// @@ -656,6 +672,48 @@ impl DepGraphData { pub(crate) fn mark_debug_loaded_from_disk(&self, dep_node: DepNode) { self.debug_loaded_from_disk.lock().insert(dep_node); } + + #[inline] + fn encode_diagnostic( + &self, + qcx: Qcx, + diagnostic: &DiagInner, + ) -> DepNodeIndex { + let dep_node_index = self.current.encoder.send( + DepNode { + kind: D::DEP_KIND_SIDE_EFFECT, + hash: PackedFingerprint::from(Fingerprint::ZERO), + }, + Fingerprint::ZERO, + // We want the side effect node to always be red so it will be forced and emit the + // diagnostic. + std::iter::once(DepNodeIndex::FOREVER_RED_NODE).collect(), + ); + let side_effects = QuerySideEffects { diagnostic: diagnostic.clone() }; + qcx.store_side_effects(dep_node_index, side_effects); + dep_node_index + } + + #[inline] + fn force_diagnostic_node( + &self, + qcx: Qcx, + prev_index: SerializedDepNodeIndex, + ) { + D::with_deps(TaskDepsRef::Ignore, || { + let side_effects = qcx.load_side_effects(prev_index).unwrap(); + + qcx.dep_context().sess().dcx().emit_diagnostic(side_effects.diagnostic.clone()); + + // Promote the previous diagnostics to the current session. + let index = self.current.promote_node_and_deps_to_current(&self.previous, prev_index); + // FIXME: Can this race with a parallel compiler? + qcx.store_side_effects(index, side_effects); + + // Mark the node as green. + self.colors.insert(prev_index, DepNodeColor::Green(index)); + }) + } } impl DepGraph { @@ -794,7 +852,7 @@ impl DepGraphData { // We failed to mark it green, so we try to force the query. debug!("trying to force dependency {dep_dep_node:?}"); - if !qcx.dep_context().try_force_from_dep_node(*dep_dep_node, frame) { + if !qcx.dep_context().try_force_from_dep_node(*dep_dep_node, parent_dep_node_index, frame) { // The DepNode could not be forced. debug!("dependency {dep_dep_node:?} could not be forced"); return None; @@ -867,16 +925,6 @@ impl DepGraphData { // ... emitting any stored diagnostic ... - // FIXME: Store the fact that a node has diagnostics in a bit in the dep graph somewhere - // Maybe store a list on disk and encode this fact in the DepNodeState - let side_effects = qcx.load_side_effects(prev_dep_node_index); - - if side_effects.maybe_any() { - qcx.dep_context().dep_graph().with_query_deserialization(|| { - self.emit_side_effects(qcx, dep_node_index, side_effects) - }); - } - // ... and finally storing a "Green" entry in the color map. // Multiple threads can all write the same color here self.colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index)); @@ -884,33 +932,6 @@ impl DepGraphData { debug!("successfully marked {dep_node:?} as green"); Some(dep_node_index) } - - /// Atomically emits some loaded diagnostics. - /// This may be called concurrently on multiple threads for the same dep node. - #[cold] - #[inline(never)] - fn emit_side_effects>( - &self, - qcx: Qcx, - dep_node_index: DepNodeIndex, - side_effects: QuerySideEffects, - ) { - let mut processed = self.processed_side_effects.lock(); - - if processed.insert(dep_node_index) { - // We were the first to insert the node in the set so this thread - // must process side effects - - // Promote the previous diagnostics to the current session. - qcx.store_side_effects(dep_node_index, side_effects.clone()); - - let dcx = qcx.dep_context().sess().dcx(); - - for diagnostic in side_effects.diagnostics { - dcx.emit_diagnostic(diagnostic); - } - } - } } impl DepGraph { diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index e564ae0cec7a..e3d64d1c0f80 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -58,10 +58,15 @@ pub trait DepContext: Copy { /// dep-node or when the query kind outright does not support it. #[inline] #[instrument(skip(self, frame), level = "debug")] - fn try_force_from_dep_node(self, dep_node: DepNode, frame: Option<&MarkFrame<'_>>) -> bool { + fn try_force_from_dep_node( + self, + dep_node: DepNode, + prev_index: SerializedDepNodeIndex, + frame: Option<&MarkFrame<'_>>, + ) -> bool { let cb = self.dep_kind_info(dep_node.kind); if let Some(f) = cb.force_from_dep_node { - match panic::catch_unwind(panic::AssertUnwindSafe(|| f(self, dep_node))) { + match panic::catch_unwind(panic::AssertUnwindSafe(|| f(self, dep_node, prev_index))) { Err(value) => { if !value.is::() { print_markframe_trace(self.dep_graph(), frame); @@ -101,6 +106,9 @@ pub trait Deps { /// We use this to create a forever-red node. const DEP_KIND_RED: DepKind; + /// We use this to create a side effect node. + const DEP_KIND_SIDE_EFFECT: DepKind; + /// This is the highest value a `DepKind` can have. It's used during encoding to /// pack information into the unused bits. const DEP_KIND_MAX: u16; diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 7490a3f35032..ad246b3e8b10 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -11,14 +11,12 @@ mod caches; pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCache}; mod config; -use rustc_data_structures::sync::Lock; use rustc_errors::DiagInner; use rustc_hashes::Hash64; use rustc_hir::def::DefKind; use rustc_macros::{Decodable, Encodable}; use rustc_span::Span; use rustc_span::def_id::DefId; -use thin_vec::ThinVec; pub use self::config::{HashResult, QueryConfig}; use crate::dep_graph::{DepKind, DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; @@ -70,27 +68,12 @@ impl QueryStackFrame { /// This allows us to 'replay' changes to global state /// that would otherwise only occur if we actually /// executed the query method. -#[derive(Debug, Clone, Default, Encodable, Decodable)] +#[derive(Debug, Encodable, Decodable)] pub struct QuerySideEffects { /// Stores any diagnostics emitted during query execution. /// These diagnostics will be re-emitted if we mark /// the query as green. - pub(super) diagnostics: ThinVec, -} - -impl QuerySideEffects { - /// Returns true if there might be side effects. - #[inline] - pub fn maybe_any(&self) -> bool { - let QuerySideEffects { diagnostics } = self; - // Use `has_capacity` so that the destructor for `self.diagnostics` can be skipped - // if `maybe_any` is known to be false. - diagnostics.has_capacity() - } - pub fn append(&mut self, other: QuerySideEffects) { - let QuerySideEffects { diagnostics } = self; - diagnostics.extend(other.diagnostics); - } + pub(super) diagnostic: DiagInner, } pub trait QueryContext: HasDepContext { @@ -102,28 +85,18 @@ pub trait QueryContext: HasDepContext { fn collect_active_jobs(self) -> QueryMap; /// Load side effects associated to the node in the previous session. - fn load_side_effects(self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects; + fn load_side_effects( + self, + prev_dep_node_index: SerializedDepNodeIndex, + ) -> Option; /// Register diagnostics for the given node, for use in next session. fn store_side_effects(self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects); - /// Register diagnostics for the given node, for use in next session. - fn store_side_effects_for_anon_node( - self, - dep_node_index: DepNodeIndex, - side_effects: QuerySideEffects, - ); - /// Executes a job by changing the `ImplicitCtxt` to point to the - /// new query job while it executes. It returns the diagnostics - /// captured during execution and the actual result. - fn start_query( - self, - token: QueryJobId, - depth_limit: bool, - diagnostics: Option<&Lock>>, - compute: impl FnOnce() -> R, - ) -> R; + /// new query job while it executes. + fn start_query(self, token: QueryJobId, depth_limit: bool, compute: impl FnOnce() -> R) + -> R; fn depth_limit_error(self, job: QueryJobId); } diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 18aae8c00b24..7578cb5e2aeb 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -12,11 +12,9 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sharded::Sharded; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_data_structures::sync::Lock; use rustc_data_structures::{outline, sync}; use rustc_errors::{Diag, FatalError, StashKey}; use rustc_span::{DUMMY_SP, Span}; -use thin_vec::ThinVec; use tracing::instrument; use super::QueryConfig; @@ -25,9 +23,7 @@ use crate::dep_graph::{DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeP use crate::ich::StableHashingContext; use crate::query::caches::QueryCache; use crate::query::job::{QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryLatch, report_cycle}; -use crate::query::{ - QueryContext, QueryMap, QuerySideEffects, QueryStackFrame, SerializedDepNodeIndex, -}; +use crate::query::{QueryContext, QueryMap, QueryStackFrame, SerializedDepNodeIndex}; pub struct QueryState { active: Sharded>, @@ -470,7 +466,7 @@ where } let prof_timer = qcx.dep_context().profiler().query_provider(); - let result = qcx.start_query(job_id, query.depth_limit(), None, || query.compute(qcx, key)); + let result = qcx.start_query(job_id, query.depth_limit(), || query.compute(qcx, key)); let dep_node_index = qcx.dep_context().dep_graph().next_virtual_depnode_index(); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); @@ -507,7 +503,7 @@ where // The diagnostics for this query will be promoted to the current session during // `try_mark_green()`, so we can ignore them here. - if let Some(ret) = qcx.start_query(job_id, false, None, || { + if let Some(ret) = qcx.start_query(job_id, false, || { try_load_from_disk_and_cache_in_memory(query, dep_graph_data, qcx, &key, dep_node) }) { return ret; @@ -515,43 +511,31 @@ where } let prof_timer = qcx.dep_context().profiler().query_provider(); - let diagnostics = Lock::new(ThinVec::new()); - let (result, dep_node_index) = - qcx.start_query(job_id, query.depth_limit(), Some(&diagnostics), || { - if query.anon() { - return dep_graph_data.with_anon_task_inner( - *qcx.dep_context(), - query.dep_kind(), - || query.compute(qcx, key), - ); - } + let (result, dep_node_index) = qcx.start_query(job_id, query.depth_limit(), || { + if query.anon() { + return dep_graph_data.with_anon_task_inner( + *qcx.dep_context(), + query.dep_kind(), + || query.compute(qcx, key), + ); + } - // `to_dep_node` is expensive for some `DepKind`s. - let dep_node = - dep_node_opt.unwrap_or_else(|| query.construct_dep_node(*qcx.dep_context(), &key)); + // `to_dep_node` is expensive for some `DepKind`s. + let dep_node = + dep_node_opt.unwrap_or_else(|| query.construct_dep_node(*qcx.dep_context(), &key)); - dep_graph_data.with_task( - dep_node, - (qcx, query), - key, - |(qcx, query), key| query.compute(qcx, key), - query.hash_result(), - ) - }); + dep_graph_data.with_task( + dep_node, + (qcx, query), + key, + |(qcx, query), key| query.compute(qcx, key), + query.hash_result(), + ) + }); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); - let side_effects = QuerySideEffects { diagnostics: diagnostics.into_inner() }; - - if std::intrinsics::unlikely(side_effects.maybe_any()) { - if query.anon() { - qcx.store_side_effects_for_anon_node(dep_node_index, side_effects); - } else { - qcx.store_side_effects(dep_node_index, side_effects); - } - } - (result, dep_node_index) } From 453b51a65ab00939d2dce3de24ce38489b5c7eb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 14 Mar 2025 18:36:30 +0100 Subject: [PATCH 184/745] Rename `QuerySideEffects` to `QuerySideEffect` --- .../rustc_middle/src/query/on_disk_cache.rs | 30 +++++++++---------- compiler/rustc_query_impl/src/plumbing.rs | 12 ++++---- .../rustc_query_system/src/dep_graph/graph.rs | 16 ++++++---- compiler/rustc_query_system/src/query/mod.rs | 26 +++++++++------- compiler/rustc_session/src/options.rs | 2 +- 5 files changed, 47 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index b4c5d1c6c055..ec5f8f619fe7 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -11,7 +11,7 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, LocalDefId, Stab use rustc_hir::definitions::DefPathHash; use rustc_index::{Idx, IndexVec}; use rustc_macros::{Decodable, Encodable}; -use rustc_query_system::query::QuerySideEffects; +use rustc_query_system::query::QuerySideEffect; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_session::Session; @@ -55,9 +55,9 @@ pub struct OnDiskCache { // The complete cache data in serialized form. serialized_data: RwLock>, - // Collects all `QuerySideEffects` created during the current compilation + // Collects all `QuerySideEffect` created during the current compilation // session. - current_side_effects: Lock>, + current_side_effects: Lock>, file_index_to_stable_id: FxHashMap, @@ -68,7 +68,7 @@ pub struct OnDiskCache { // `serialized_data`. query_result_index: FxHashMap, - // A map from dep-node to the position of any associated `QuerySideEffects` in + // A map from dep-node to the position of any associated `QuerySideEffect` in // `serialized_data`. prev_side_effects_index: FxHashMap, @@ -270,10 +270,10 @@ impl OnDiskCache { .current_side_effects .borrow() .iter() - .map(|(dep_node_index, side_effects)| { + .map(|(dep_node_index, side_effect)| { let pos = AbsoluteBytePos::new(encoder.position()); let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index()); - encoder.encode_tagged(dep_node_index, side_effects); + encoder.encode_tagged(dep_node_index, side_effect); (dep_node_index, pos) }) @@ -352,23 +352,23 @@ impl OnDiskCache { }) } - /// Loads a `QuerySideEffects` created during the previous compilation session. - pub fn load_side_effects( + /// Loads a `QuerySideEffect` created during the previous compilation session. + pub fn load_side_effect( &self, tcx: TyCtxt<'_>, dep_node_index: SerializedDepNodeIndex, - ) -> Option { - let side_effects: Option = + ) -> Option { + let side_effect: Option = self.load_indexed(tcx, dep_node_index, &self.prev_side_effects_index); - side_effects + side_effect } - /// Stores a `QuerySideEffects` emitted during the current compilation session. - /// Anything stored like this will be available via `load_side_effects` in + /// Stores a `QuerySideEffect` emitted during the current compilation session. + /// Anything stored like this will be available via `load_side_effect` in /// the next compilation session. - pub fn store_side_effects(&self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects) { + pub fn store_side_effect(&self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect) { let mut current_side_effects = self.current_side_effects.borrow_mut(); - let prev = current_side_effects.insert(dep_node_index, side_effects); + let prev = current_side_effects.insert(dep_node_index, side_effect); debug_assert!(prev.is_none()); } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 47158f6d7aaf..e11bd6437d7b 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -23,7 +23,7 @@ use rustc_middle::ty::{self, TyCtxt, TyEncoder}; use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext}; use rustc_query_system::ich::StableHashingContext; use rustc_query_system::query::{ - QueryCache, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffects, QueryStackFrame, + QueryCache, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffect, QueryStackFrame, force_query, }; use rustc_query_system::{QueryOverflow, QueryOverflowNote}; @@ -89,21 +89,21 @@ impl QueryContext for QueryCtxt<'_> { } // Interactions with on_disk_cache - fn load_side_effects( + fn load_side_effect( self, prev_dep_node_index: SerializedDepNodeIndex, - ) -> Option { + ) -> Option { self.query_system .on_disk_cache .as_ref() - .and_then(|c| c.load_side_effects(self.tcx, prev_dep_node_index)) + .and_then(|c| c.load_side_effect(self.tcx, prev_dep_node_index)) } #[inline(never)] #[cold] - fn store_side_effects(self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects) { + fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect) { if let Some(c) = self.query_system.on_disk_cache.as_ref() { - c.store_side_effects(dep_node_index, side_effects) + c.store_side_effect(dep_node_index, side_effect) } } diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index de681328bcb5..dbc7f034a6eb 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -25,7 +25,7 @@ use super::serialized::{GraphEncoder, SerializedDepGraph, SerializedDepNodeIndex use super::{DepContext, DepKind, DepNode, Deps, HasDepContext, WorkProductId}; use crate::dep_graph::edges::EdgesVec; use crate::ich::StableHashingContext; -use crate::query::{QueryContext, QuerySideEffects}; +use crate::query::{QueryContext, QuerySideEffect}; #[derive(Clone)] pub struct DepGraph { @@ -689,8 +689,8 @@ impl DepGraphData { // diagnostic. std::iter::once(DepNodeIndex::FOREVER_RED_NODE).collect(), ); - let side_effects = QuerySideEffects { diagnostic: diagnostic.clone() }; - qcx.store_side_effects(dep_node_index, side_effects); + let side_effect = QuerySideEffect::Diagnostic(diagnostic.clone()); + qcx.store_side_effect(dep_node_index, side_effect); dep_node_index } @@ -701,14 +701,18 @@ impl DepGraphData { prev_index: SerializedDepNodeIndex, ) { D::with_deps(TaskDepsRef::Ignore, || { - let side_effects = qcx.load_side_effects(prev_index).unwrap(); + let side_effect = qcx.load_side_effect(prev_index).unwrap(); - qcx.dep_context().sess().dcx().emit_diagnostic(side_effects.diagnostic.clone()); + match &side_effect { + QuerySideEffect::Diagnostic(diagnostic) => { + qcx.dep_context().sess().dcx().emit_diagnostic(diagnostic.clone()); + } + } // Promote the previous diagnostics to the current session. let index = self.current.promote_node_and_deps_to_current(&self.previous, prev_index); // FIXME: Can this race with a parallel compiler? - qcx.store_side_effects(index, side_effects); + qcx.store_side_effect(index, side_effect); // Mark the node as green. self.colors.insert(prev_index, DepNodeColor::Green(index)); diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index ad246b3e8b10..2ed0c810b751 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -62,18 +62,22 @@ impl QueryStackFrame { } } -/// Tracks 'side effects' for a particular query. +/// Track a 'side effects' for a particular query. /// This struct is saved to disk along with the query result, /// and loaded from disk if we mark the query as green. /// This allows us to 'replay' changes to global state /// that would otherwise only occur if we actually /// executed the query method. +/// +/// Each side effect gets an unique dep node index which is added +/// as a dependency of the query which had the effect. #[derive(Debug, Encodable, Decodable)] -pub struct QuerySideEffects { - /// Stores any diagnostics emitted during query execution. - /// These diagnostics will be re-emitted if we mark - /// the query as green. - pub(super) diagnostic: DiagInner, +pub enum QuerySideEffect { + /// Stores a diagnostic emitted during query execution. + /// This diagnostic will be re-emitted if we mark + /// the query as green, as that query will have the side + /// effect dep node as a dependency. + Diagnostic(DiagInner), } pub trait QueryContext: HasDepContext { @@ -84,14 +88,14 @@ pub trait QueryContext: HasDepContext { fn collect_active_jobs(self) -> QueryMap; - /// Load side effects associated to the node in the previous session. - fn load_side_effects( + /// Load a side effect associated to the node in the previous session. + fn load_side_effect( self, prev_dep_node_index: SerializedDepNodeIndex, - ) -> Option; + ) -> Option; - /// Register diagnostics for the given node, for use in next session. - fn store_side_effects(self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects); + /// Register a side effect for the given node, for use in next session. + fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect); /// Executes a job by changing the `ImplicitCtxt` to point to the /// new query job while it executes. diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 804b46a9bec4..8d05cd14e382 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2525,7 +2525,7 @@ written to standard error output)"), "for every macro invocation, print its name and arguments (default: no)"), track_diagnostics: bool = (false, parse_bool, [UNTRACKED], "tracks where in rustc a diagnostic was emitted"), - // Diagnostics are considered side-effects of a query (see `QuerySideEffects`) and are saved + // Diagnostics are considered side-effects of a query (see `QuerySideEffect`) and are saved // alongside query results and changes to translation options can affect diagnostics - so // translation options should be tracked. translate_additional_ftl: Option = (None, parse_opt_pathbuf, [TRACKED], From 9a847b1ea59090d9633a8dca75510cbe91589c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 14 Mar 2025 18:55:02 +0100 Subject: [PATCH 185/745] Add comments --- compiler/rustc_query_system/src/dep_graph/graph.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index dbc7f034a6eb..985ca6490345 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -533,6 +533,8 @@ impl DepGraph { } } + /// This encodes a diagnostic by creating a node with an unique index and assoicating + /// `diagnostic` with it, for use in the next session. #[inline] pub fn record_diagnostic(&self, qcx: Qcx, diagnostic: &DiagInner) { if let Some(ref data) = self.data { @@ -540,6 +542,8 @@ impl DepGraph { } } + /// This forces a diagnostic node green by running its side effect. `prev_index` would + /// refer to a node created used `encode_diagnostic` in the previous session. #[inline] pub fn force_diagnostic_node( &self, @@ -673,12 +677,15 @@ impl DepGraphData { self.debug_loaded_from_disk.lock().insert(dep_node); } + /// This encodes a diagnostic by creating a node with an unique index and assoicating + /// `diagnostic` with it, for use in the next session. #[inline] fn encode_diagnostic( &self, qcx: Qcx, diagnostic: &DiagInner, ) -> DepNodeIndex { + // Use `send` so we get an unique index, even though the dep node is not. let dep_node_index = self.current.encoder.send( DepNode { kind: D::DEP_KIND_SIDE_EFFECT, @@ -694,6 +701,8 @@ impl DepGraphData { dep_node_index } + /// This forces a diagnostic node green by running its side effect. `prev_index` would + /// refer to a node created used `encode_diagnostic` in the previous session. #[inline] fn force_diagnostic_node( &self, From 50c659fcba19f6d51d465815cadcea00d8abb02b Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Fri, 14 Mar 2025 17:30:47 +0100 Subject: [PATCH 186/745] Clarify "owned data" in E0515.md This clarifies the explanation of why this is not allowed and also what to do instead. Fixes 62071 PS There was suggestion of adding a link to the book. I did not yet do that, but if desired that could be added. --- compiler/rustc_error_codes/src/error_codes/E0515.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0515.md b/compiler/rustc_error_codes/src/error_codes/E0515.md index 0f4fbf672239..87bbe4aea705 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0515.md +++ b/compiler/rustc_error_codes/src/error_codes/E0515.md @@ -17,10 +17,13 @@ fn get_dangling_iterator<'a>() -> Iter<'a, i32> { } ``` -Local variables, function parameters and temporaries are all dropped before the -end of the function body. So a reference to them cannot be returned. +Local variables, function parameters and temporaries are all dropped before +the end of the function body. A returned reference (or struct containing a +reference) to such a dropped value would immediately be invalid. Therefore +it is not allowed to return such a reference. -Consider returning an owned value instead: +Consider returning a value that takes ownership of local data instead of +referencing it: ``` use std::vec::IntoIter; From edf65e735cd871d01149131f5d050293a9f1037c Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Wed, 12 Mar 2025 15:59:28 -0700 Subject: [PATCH 187/745] Add support for postfix yield expressions We had a discussion[1] today about whether postfix yield would make sense. It's easy enough to support both in the parser, so we might as well have both and see how people use it while the feature is experimental. [1]: https://rust-lang.zulipchat.com/#narrow/channel/481571-t-lang.2Fgen/topic/postfix-yield/with/505231568 --- compiler/rustc_parse/src/parser/expr.rs | 7 +++++ tests/ui/coroutine/postfix-yield.rs | 34 +++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 tests/ui/coroutine/postfix-yield.rs diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 9b2d562a69ec..1df6283af264 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1310,6 +1310,13 @@ impl<'a> Parser<'a> { return self.parse_match_block(lo, match_span, self_arg, MatchKind::Postfix); } + // Post-fix yield + if self.eat_keyword(exp!(Yield)) { + let yield_span = self.prev_token.span; + self.psess.gated_spans.gate(sym::yield_expr, yield_span); + return Ok(self.mk_expr(yield_span, ExprKind::Yield(Some(self_arg)))); + } + let fn_span_lo = self.token.span; let mut seg = self.parse_path_segment(PathStyle::Expr, None)?; self.check_trailing_angle_brackets(&seg, &[exp!(OpenParen)]); diff --git a/tests/ui/coroutine/postfix-yield.rs b/tests/ui/coroutine/postfix-yield.rs new file mode 100644 index 000000000000..77b1c2a19d0a --- /dev/null +++ b/tests/ui/coroutine/postfix-yield.rs @@ -0,0 +1,34 @@ +// This demonstrates a proposed alternate or additional option of having yield in postfix position. + +//@ run-pass +//@ edition: 2024 + +#![feature(gen_blocks, coroutines, coroutine_trait, yield_expr)] + +use std::ops::{Coroutine, CoroutineState}; +use std::pin::pin; + +fn main() { + // generators (i.e. yield doesn't return anything useful) + let mut gn = gen { + yield 1; + 2.yield; + }; + + assert_eq!(gn.next(), Some(1)); + assert_eq!(gn.next(), Some(2)); + assert_eq!(gn.next(), None); + + //coroutines (i.e. yield returns something useful) + let mut coro = pin!( + #[coroutine] + |_: i32| { + let x = yield 1; + yield x + 2; + } + ); + + assert_eq!(coro.as_mut().resume(0), CoroutineState::Yielded(1)); + assert_eq!(coro.as_mut().resume(2), CoroutineState::Yielded(4)); + assert_eq!(coro.as_mut().resume(3), CoroutineState::Complete(())); +} From 1c0916a2b3cd6c595e1c7b69a31d507f7619bb67 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Wed, 12 Mar 2025 16:27:52 -0700 Subject: [PATCH 188/745] Preserve yield position during pretty printing --- compiler/rustc_ast/src/ast.rs | 11 ++++++++++- compiler/rustc_ast/src/mut_visit.rs | 2 +- compiler/rustc_ast/src/util/classify.rs | 4 ++-- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_ast_lowering/src/expr.rs | 2 +- compiler/rustc_ast_lowering/src/format.rs | 2 +- .../rustc_ast_pretty/src/pprust/state/expr.rs | 14 ++++++++++++-- .../rustc_builtin_macros/src/assert/context.rs | 2 +- compiler/rustc_parse/src/parser/expr.rs | 9 ++++++--- src/tools/rustfmt/src/utils.rs | 4 ++-- tests/pretty/postfix-yield.rs | 15 +++++++++++++++ tests/ui/coroutine/postfix-yield.rs | 6 +++--- 12 files changed, 55 insertions(+), 18 deletions(-) create mode 100644 tests/pretty/postfix-yield.rs diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 1b831c454e6d..9dcdd8683437 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1657,7 +1657,7 @@ pub enum ExprKind { Try(P), /// A `yield`, with an optional value to be yielded. - Yield(Option>), + Yield(Option>, YieldKind), /// A `do yeet` (aka `throw`/`fail`/`bail`/`raise`/whatever), /// with an optional value to be returned. @@ -1903,6 +1903,15 @@ pub enum MatchKind { Postfix, } +/// The kind of yield expression +#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq)] +pub enum YieldKind { + /// yield expr { ... } + Prefix, + /// expr.yield { ... } + Postfix, +} + /// A literal in a meta item. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] pub struct MetaItemLit { diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 4a1636e6aec0..5a9df6ffadf0 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1813,7 +1813,7 @@ pub fn walk_expr(vis: &mut T, Expr { kind, id, span, attrs, token ExprKind::Paren(expr) => { vis.visit_expr(expr); } - ExprKind::Yield(expr) => { + ExprKind::Yield(expr, _) => { visit_opt(expr, |expr| vis.visit_expr(expr)); } ExprKind::Try(expr) => vis.visit_expr(expr), diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs index e43d78f6e721..116847af9f49 100644 --- a/compiler/rustc_ast/src/util/classify.rs +++ b/compiler/rustc_ast/src/util/classify.rs @@ -182,7 +182,7 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option> { | Range(_, Some(e), _) | Ret(Some(e)) | Unary(_, e) - | Yield(Some(e)) + | Yield(Some(e), _) | Yeet(Some(e)) | Become(e) => { expr = e; @@ -217,7 +217,7 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option> { Break(_, None) | Range(_, None, _) | Ret(None) - | Yield(None) + | Yield(None, _) | Array(_) | Call(_, _) | MethodCall(_) diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index cfcb0e23cb5e..a72e834e17a2 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -1269,7 +1269,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V try_visit!(visitor.visit_ty(container)); walk_list!(visitor, visit_ident, fields.iter()); } - ExprKind::Yield(optional_expression) => { + ExprKind::Yield(optional_expression, _) => { visit_opt!(visitor, visit_expr, optional_expression); } ExprKind::Try(subexpression) => try_visit!(visitor.visit_expr(subexpression)), diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 5bb6704dde45..19a08f92ce75 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -351,7 +351,7 @@ impl<'hir> LoweringContext<'_, 'hir> { rest, ) } - ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()), + ExprKind::Yield(opt_expr, _) => self.lower_expr_yield(e.span, opt_expr.as_deref()), ExprKind::Err(guar) => hir::ExprKind::Err(*guar), ExprKind::UnsafeBinderCast(kind, expr, ty) => hir::ExprKind::UnsafeBinderCast( diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index faa47274f96c..2bbf957feebe 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -642,7 +642,7 @@ fn may_contain_yield_point(e: &ast::Expr) -> bool { type Result = ControlFlow<()>; fn visit_expr(&mut self, e: &ast::Expr) -> ControlFlow<()> { - if let ast::ExprKind::Await(_, _) | ast::ExprKind::Yield(_) = e.kind { + if let ast::ExprKind::Await(_, _) | ast::ExprKind::Yield(_, _) = e.kind { ControlFlow::Break(()) } else { visit::walk_expr(self, e) diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index e3c41f117abb..9e53ed41c46c 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -8,7 +8,7 @@ use rustc_ast::util::literal::escape_byte_str_symbol; use rustc_ast::util::parser::{self, ExprPrecedence, Fixity}; use rustc_ast::{ self as ast, BlockCheckMode, FormatAlignment, FormatArgPosition, FormatArgsPiece, FormatCount, - FormatDebugHex, FormatSign, FormatTrait, token, + FormatDebugHex, FormatSign, FormatTrait, YieldKind, token, }; use crate::pp::Breaks::Inconsistent; @@ -761,7 +761,7 @@ impl<'a> State<'a> { self.print_expr(e, FixupContext::default()); self.pclose(); } - ast::ExprKind::Yield(e) => { + ast::ExprKind::Yield(e, YieldKind::Prefix) => { self.word("yield"); if let Some(expr) = e { @@ -773,6 +773,16 @@ impl<'a> State<'a> { ); } } + ast::ExprKind::Yield(e, YieldKind::Postfix) => { + // it's not possible to have a postfix yield with no expression. + let e = e.as_ref().unwrap(); + self.print_expr_cond_paren( + e, + e.precedence() < ExprPrecedence::Unambiguous, + fixup.leftmost_subexpression_with_dot(), + ); + self.word(".yield"); + } ast::ExprKind::Try(e) => { self.print_expr_cond_paren( e, diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index a949ab94f3ad..54c3cebedfc0 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -323,7 +323,7 @@ impl<'cx, 'a> Context<'cx, 'a> { | ExprKind::While(_, _, _) | ExprKind::Yeet(_) | ExprKind::Become(_) - | ExprKind::Yield(_) + | ExprKind::Yield(_, _) | ExprKind::UnsafeBinderCast(..) => {} } } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 1df6283af264..cb04bbc240e4 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -17,6 +17,7 @@ use rustc_ast::{ self as ast, AnonConst, Arm, AttrStyle, AttrVec, BinOp, BinOpKind, BlockCheckMode, CaptureBy, ClosureBinder, DUMMY_NODE_ID, Expr, ExprField, ExprKind, FnDecl, FnRetTy, Label, MacCall, MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind, + YieldKind, }; use rustc_ast_pretty::pprust; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -1314,7 +1315,9 @@ impl<'a> Parser<'a> { if self.eat_keyword(exp!(Yield)) { let yield_span = self.prev_token.span; self.psess.gated_spans.gate(sym::yield_expr, yield_span); - return Ok(self.mk_expr(yield_span, ExprKind::Yield(Some(self_arg)))); + return Ok( + self.mk_expr(yield_span, ExprKind::Yield(Some(self_arg), YieldKind::Postfix)) + ); } let fn_span_lo = self.token.span; @@ -1891,7 +1894,7 @@ impl<'a> Parser<'a> { /// Parse `"yield" expr?`. fn parse_expr_yield(&mut self) -> PResult<'a, P> { let lo = self.prev_token.span; - let kind = ExprKind::Yield(self.parse_expr_opt()?); + let kind = ExprKind::Yield(self.parse_expr_opt()?, YieldKind::Prefix); let span = lo.to(self.prev_token.span); self.psess.gated_spans.gate(sym::yield_expr, span); let expr = self.mk_expr(span, kind); @@ -4045,7 +4048,7 @@ impl MutVisitor for CondChecker<'_> { | ExprKind::MacCall(_) | ExprKind::Struct(_) | ExprKind::Repeat(_, _) - | ExprKind::Yield(_) + | ExprKind::Yield(_, _) | ExprKind::Yeet(_) | ExprKind::Become(_) | ExprKind::IncludedBytes(_) diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs index fe716c186389..bee391532294 100644 --- a/src/tools/rustfmt/src/utils.rs +++ b/src/tools/rustfmt/src/utils.rs @@ -485,7 +485,7 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr | ast::ExprKind::Index(_, ref expr, _) | ast::ExprKind::Unary(_, ref expr) | ast::ExprKind::Try(ref expr) - | ast::ExprKind::Yield(Some(ref expr)) => is_block_expr(context, expr, repr), + | ast::ExprKind::Yield(Some(ref expr), _) => is_block_expr(context, expr, repr), ast::ExprKind::Closure(ref closure) => is_block_expr(context, &closure.body, repr), // This can only be a string lit ast::ExprKind::Lit(_) => { @@ -515,7 +515,7 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr | ast::ExprKind::Tup(..) | ast::ExprKind::Use(..) | ast::ExprKind::Type(..) - | ast::ExprKind::Yield(None) + | ast::ExprKind::Yield(None, _) | ast::ExprKind::Underscore => false, } } diff --git a/tests/pretty/postfix-yield.rs b/tests/pretty/postfix-yield.rs new file mode 100644 index 000000000000..f76e8142ae86 --- /dev/null +++ b/tests/pretty/postfix-yield.rs @@ -0,0 +1,15 @@ +// This demonstrates a proposed alternate or additional option of having yield in postfix position. +//@ edition: 2024 +//@ pp-exact + +#![feature(gen_blocks, coroutines, coroutine_trait, yield_expr)] + +use std::ops::{Coroutine, CoroutineState}; +use std::pin::pin; + +fn main() { + let mut gn = gen { yield 1; 2.yield; (1 + 2).yield; }; + + let mut coro = + pin!(#[coroutine] |_: i32| { let x = 1.yield; (x + 2).yield; }); +} diff --git a/tests/ui/coroutine/postfix-yield.rs b/tests/ui/coroutine/postfix-yield.rs index 77b1c2a19d0a..ff843138c8c2 100644 --- a/tests/ui/coroutine/postfix-yield.rs +++ b/tests/ui/coroutine/postfix-yield.rs @@ -9,7 +9,7 @@ use std::ops::{Coroutine, CoroutineState}; use std::pin::pin; fn main() { - // generators (i.e. yield doesn't return anything useful) + // generators (i.e. yield doesn't return anything useful) let mut gn = gen { yield 1; 2.yield; @@ -23,8 +23,8 @@ fn main() { let mut coro = pin!( #[coroutine] |_: i32| { - let x = yield 1; - yield x + 2; + let x = 1.yield; + (x + 2).yield; } ); From 635eae2d4fc724cb53a3a45975bc18779a3293b1 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Thu, 13 Mar 2025 14:36:02 -0700 Subject: [PATCH 189/745] Teach rustfmt to handle postfix yield --- .../clippy/clippy_utils/src/ast_utils/mod.rs | 5 +++-- src/tools/rustfmt/src/expr.rs | 5 +++-- src/tools/rustfmt/tests/source/postfix-yield.rs | 15 +++++++++++++++ src/tools/rustfmt/tests/target/postfix-yield.rs | 12 ++++++++++++ 4 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 src/tools/rustfmt/tests/source/postfix-yield.rs create mode 100644 src/tools/rustfmt/tests/target/postfix-yield.rs diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs index 707312a97f3b..deda6030831e 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs @@ -201,7 +201,8 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool { (Loop(lt, ll, _), Loop(rt, rl, _)) => eq_label(ll.as_ref(), rl.as_ref()) && eq_block(lt, rt), (Block(lb, ll), Block(rb, rl)) => eq_label(ll.as_ref(), rl.as_ref()) && eq_block(lb, rb), (TryBlock(l), TryBlock(r)) => eq_block(l, r), - (Yield(l), Yield(r)) | (Ret(l), Ret(r)) => eq_expr_opt(l.as_ref(), r.as_ref()), + (Yield(l, lk), Yield(r, rk)) => eq_expr_opt(l.as_ref(), r.as_ref()) && lk == rk, + (Ret(l), Ret(r)) => eq_expr_opt(l.as_ref(), r.as_ref()), (Break(ll, le), Break(rl, re)) => eq_label(ll.as_ref(), rl.as_ref()) && eq_expr_opt(le.as_ref(), re.as_ref()), (Continue(ll), Continue(rl)) => eq_label(ll.as_ref(), rl.as_ref()), (Assign(l1, l2, _), Assign(r1, r2, _)) | (Index(l1, l2, _), Index(r1, r2, _)) => { @@ -688,7 +689,7 @@ pub fn eq_generics(l: &Generics, r: &Generics) -> bool { pub fn eq_where_predicate(l: &WherePredicate, r: &WherePredicate) -> bool { use WherePredicateKind::*; - over(&l.attrs, &r.attrs, eq_attr) + over(&l.attrs, &r.attrs, eq_attr) && match (&l.kind, &r.kind) { (BoundPredicate(l), BoundPredicate(r)) => { over(&l.bound_generic_params, &r.bound_generic_params, |l, r| { diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index eff2d2e3ff4a..92c1ffa6076d 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -221,7 +221,7 @@ pub(crate) fn format_expr( Ok(format!("break{id_str}")) } } - ast::ExprKind::Yield(ref opt_expr) => { + ast::ExprKind::Yield(ref opt_expr, ast::YieldKind::Prefix) => { if let Some(ref expr) = *opt_expr { rewrite_unary_prefix(context, "yield ", &**expr, shape) } else { @@ -243,7 +243,8 @@ pub(crate) fn format_expr( ast::ExprKind::Try(..) | ast::ExprKind::Field(..) | ast::ExprKind::MethodCall(..) - | ast::ExprKind::Await(_, _) => rewrite_chain(expr, context, shape), + | ast::ExprKind::Await(_, _) + | ast::ExprKind::Yield(_, ast::YieldKind::Postfix) => rewrite_chain(expr, context, shape), ast::ExprKind::MacCall(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|_| { wrap_str( diff --git a/src/tools/rustfmt/tests/source/postfix-yield.rs b/src/tools/rustfmt/tests/source/postfix-yield.rs new file mode 100644 index 000000000000..8a8958f3ad4e --- /dev/null +++ b/src/tools/rustfmt/tests/source/postfix-yield.rs @@ -0,0 +1,15 @@ +// This demonstrates a proposed alternate or additional option of having yield in postfix position. +//@ edition: 2024 + +#![feature(gen_blocks, coroutines, coroutine_trait, yield_expr)] + +use std::ops::{Coroutine, CoroutineState}; +use std::pin::pin; + +fn main() { + let mut coro = + pin!(#[coroutine] |_: i32| { let x = 1.yield; + + + (x + 2).yield; }); +} diff --git a/src/tools/rustfmt/tests/target/postfix-yield.rs b/src/tools/rustfmt/tests/target/postfix-yield.rs new file mode 100644 index 000000000000..7e94e1e095ad --- /dev/null +++ b/src/tools/rustfmt/tests/target/postfix-yield.rs @@ -0,0 +1,12 @@ +// This demonstrates a proposed alternate or additional option of having yield in postfix position. +//@ edition: 2024 + +#![feature(gen_blocks, coroutines, coroutine_trait, yield_expr)] + +use std::ops::{Coroutine, CoroutineState}; +use std::pin::pin; + +fn main() { + let mut coro = + pin!(#[coroutine] |_: i32| { let x = 1.yield; (x + 2).yield; }); +} From c5093ac1224fe9eeff5c5694f1c3ff643005d7d4 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Thu, 13 Mar 2025 16:14:31 -0700 Subject: [PATCH 190/745] Fix clippy --- .../clippy/clippy_lints/src/suspicious_operation_groupings.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs index 0d809c17989d..206912d8de40 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs @@ -528,7 +528,7 @@ fn ident_difference_expr_with_base_location( &strip_non_ident_wrappers(left).kind, &strip_non_ident_wrappers(right).kind, ) { - (Yield(_), Yield(_)) + (Yield(_, _), Yield(_, _)) | (Try(_), Try(_)) | (Paren(_), Paren(_)) | (Repeat(_, _), Repeat(_, _)) From 409510c0885ba41b5bceec8406d246260baee38d Mon Sep 17 00:00:00 2001 From: binarycat Date: Thu, 13 Mar 2025 14:56:43 -0500 Subject: [PATCH 191/745] rustdoc js: add nonnull helper and typecheck src-script.js --- src/librustdoc/html/static/js/rustdoc.d.ts | 29 +++++++++++++++++++++ src/librustdoc/html/static/js/src-script.js | 28 +++++++++++++------- src/librustdoc/html/static/js/storage.js | 22 ++++++++++++++++ 3 files changed, 70 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index 4b43c00730d4..e94c6beabea3 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -4,6 +4,10 @@ /* eslint-disable */ declare global { + /** Map from crate name to directory structure, for source view */ + declare var srcIndex: Map; + /** Defined and documented in `main.js` */ + declare function nonnull(x: T|null, msg: string|undefined); interface Window { /** Make the current theme easy to find */ currentTheme: HTMLLinkElement|null; @@ -40,6 +44,23 @@ declare global { * or if this is a docs page, this function does nothing. */ rustdocShowSourceSidebar: function(), + /** + * Close the sidebar in source code view + */ + rustdocCloseSourceSidebar?: function(), + /** + * Shows the sidebar in source code view + */ + rustdocShowSourceSidebar?: function(), + /** + * Toggles the sidebar in source code view + */ + rustdocToggleSrcSidebar?: function(), + /** + * create's the sidebar in source code view. + * called in generated `src-files.js`. + */ + createSrcSidebar?: function(), /** * Set up event listeners for a scraped source example. */ @@ -438,4 +459,12 @@ declare namespace rustdoc { type TypeImpls = { [cratename: string]: Array> } + + /** + * Directory structure for source code view, + * defined in generated `src-files.js`. + * + * is a tuple of (filename, subdirs, filenames). + */ + type Dir = [string, rustdoc.Dir[], string[]] } diff --git a/src/librustdoc/html/static/js/src-script.js b/src/librustdoc/html/static/js/src-script.js index fc27241334bf..b9ab6e85603b 100644 --- a/src/librustdoc/html/static/js/src-script.js +++ b/src/librustdoc/html/static/js/src-script.js @@ -3,10 +3,8 @@ // Local js definitions: /* global addClass, onEachLazy, removeClass, browserSupportsHistoryApi */ -/* global updateLocalStorage, getVar */ +/* global updateLocalStorage, getVar, nonnull */ -// Eventually fix this. -// @ts-nocheck "use strict"; @@ -29,6 +27,14 @@ function closeSidebarIfMobile() { } } +/** + * @param {rustdoc.Dir} elem + * @param {HTMLElement} parent + * @param {string} fullPath + * @param {boolean} hasFoundFile + * + * @returns {boolean} - new value for hasFoundFile + */ function createDirEntry(elem, parent, fullPath, hasFoundFile) { const dirEntry = document.createElement("details"); const summary = document.createElement("summary"); @@ -95,7 +101,7 @@ window.rustdocToggleSrcSidebar = () => { // This function is called from "src-files.js", generated in `html/render/write_shared.rs`. // eslint-disable-next-line no-unused-vars function createSrcSidebar() { - const container = document.querySelector("nav.sidebar"); + const container = nonnull(document.querySelector("nav.sidebar")); const sidebar = document.createElement("div"); sidebar.id = "src-sidebar"; @@ -111,6 +117,7 @@ function createSrcSidebar() { // Focus on the current file in the source files sidebar. const selected_elem = sidebar.getElementsByClassName("selected")[0]; if (typeof selected_elem !== "undefined") { + // @ts-expect-error selected_elem.focus(); } } @@ -130,11 +137,12 @@ function highlightSrcLines() { to = from; from = tmp; } - let elem = document.getElementById(from); + const from_s = "" + from; + let elem = document.getElementById(from_s); if (!elem) { return; } - const x = document.getElementById(from); + const x = document.getElementById(from_s); if (x) { x.scrollIntoView(); } @@ -142,7 +150,7 @@ function highlightSrcLines() { removeClass(e, "line-highlighted"); }); for (let i = from; i <= to; ++i) { - elem = document.getElementById(i); + elem = document.getElementById("" + i); if (!elem) { break; } @@ -153,11 +161,12 @@ function highlightSrcLines() { const handleSrcHighlight = (function() { let prev_line_id = 0; + /** @type {function(string): void} */ const set_fragment = name => { const x = window.scrollX, y = window.scrollY; if (browserSupportsHistoryApi()) { - history.replaceState(null, null, "#" + name); + history.replaceState(null, "", "#" + name); highlightSrcLines(); } else { location.replace("#" + name); @@ -166,6 +175,7 @@ const handleSrcHighlight = (function() { window.scrollTo(x, y); }; + // @ts-expect-error return ev => { let cur_line_id = parseInt(ev.target.id, 10); // This event handler is attached to the entire line number column, but it should only @@ -191,7 +201,7 @@ const handleSrcHighlight = (function() { } else { prev_line_id = cur_line_id; - set_fragment(cur_line_id); + set_fragment("" + cur_line_id); } }; }()); diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index 425b915b5f94..748d2ef33c32 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -21,6 +21,28 @@ const settingsDataset = (function() { return settingsElement && settingsElement.dataset ? settingsElement.dataset : null; })(); +/** + * Assert that the passed value is nonnull, then return it. + * + * Takes an optional error message argument. + * + * Must be defined in this file, as it is loaded before all others. + * + * @template T + * @param {T|null} x + * @param {string=} msg + * @returns T + */ +// used in other files, not yet used in this one. +// eslint-disable-next-line no-unused-vars +function nonnull(x, msg) { + if (x === null) { + throw (msg || "unexpected null value!"); + } else { + return x; + } +} + /** * Get a configuration value. If it's not set, get the default. * From 915e44216acf699e306545ac75e27fc90774e900 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 11 Mar 2025 23:42:36 +0000 Subject: [PATCH 192/745] Do not suggest using `-Zmacro-backtrace` for builtin macros For macros that are implemented on the compiler, we do *not* mention the `-Zmacro-backtrace` flag. This includes `derive`s and standard macros. --- tests/ui/derive_ord_xor_partial_ord.stderr | 4 ---- tests/ui/derived_hash_with_manual_eq.stderr | 2 -- tests/ui/diverging_sub_expression.stderr | 2 -- tests/ui/fallible_impl_from.stderr | 3 --- tests/ui/impl_hash_with_borrow_str_and_bytes.stderr | 1 - tests/ui/issue-7447.stderr | 3 --- tests/ui/same_name_method.stderr | 1 - 7 files changed, 16 deletions(-) diff --git a/tests/ui/derive_ord_xor_partial_ord.stderr b/tests/ui/derive_ord_xor_partial_ord.stderr index 6bbe54eeaa6a..76dca3c79470 100644 --- a/tests/ui/derive_ord_xor_partial_ord.stderr +++ b/tests/ui/derive_ord_xor_partial_ord.stderr @@ -11,7 +11,6 @@ LL | impl PartialOrd for DeriveOrd { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: `-D clippy::derive-ord-xor-partial-ord` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::derive_ord_xor_partial_ord)]` - = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are deriving `Ord` but have implemented `PartialOrd` explicitly --> tests/ui/derive_ord_xor_partial_ord.rs:33:10 @@ -24,7 +23,6 @@ note: `PartialOrd` implemented here | LL | impl PartialOrd for DeriveOrdWithExplicitTypeVariable { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are implementing `Ord` explicitly but have derived `PartialOrd` --> tests/ui/derive_ord_xor_partial_ord.rs:47:1 @@ -42,7 +40,6 @@ note: `PartialOrd` implemented here | LL | #[derive(PartialOrd, PartialEq, Eq)] | ^^^^^^^^^^ - = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are implementing `Ord` explicitly but have derived `PartialOrd` --> tests/ui/derive_ord_xor_partial_ord.rs:69:5 @@ -60,7 +57,6 @@ note: `PartialOrd` implemented here | LL | #[derive(PartialOrd, PartialEq, Eq)] | ^^^^^^^^^^ - = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/tests/ui/derived_hash_with_manual_eq.stderr b/tests/ui/derived_hash_with_manual_eq.stderr index 19a24e752810..55740780c8a5 100644 --- a/tests/ui/derived_hash_with_manual_eq.stderr +++ b/tests/ui/derived_hash_with_manual_eq.stderr @@ -10,7 +10,6 @@ note: `PartialEq` implemented here LL | impl PartialEq for Bar { | ^^^^^^^^^^^^^^^^^^^^^^ = note: `#[deny(clippy::derived_hash_with_manual_eq)]` on by default - = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are deriving `Hash` but have implemented `PartialEq` explicitly --> tests/ui/derived_hash_with_manual_eq.rs:23:10 @@ -23,7 +22,6 @@ note: `PartialEq` implemented here | LL | impl PartialEq for Baz { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/diverging_sub_expression.stderr b/tests/ui/diverging_sub_expression.stderr index 3e417aa39cd8..ba08eb4e5f4b 100644 --- a/tests/ui/diverging_sub_expression.stderr +++ b/tests/ui/diverging_sub_expression.stderr @@ -36,8 +36,6 @@ error: sub-expression diverges | LL | _ => true || panic!("boo"), | ^^^^^^^^^^^^^ - | - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: sub-expression diverges --> tests/ui/diverging_sub_expression.rs:52:29 diff --git a/tests/ui/fallible_impl_from.stderr b/tests/ui/fallible_impl_from.stderr index d773fc3a6d7c..402494b39f30 100644 --- a/tests/ui/fallible_impl_from.stderr +++ b/tests/ui/fallible_impl_from.stderr @@ -38,7 +38,6 @@ note: potential failure(s) | LL | panic!(); | ^^^^^^^^ - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: consider implementing `TryFrom` instead --> tests/ui/fallible_impl_from.rs:40:1 @@ -64,7 +63,6 @@ LL | } else if s.parse::().unwrap() != 42 { | ^^^^^^^^^^^^^^^^^^^^^^^^^ LL | panic!("{:?}", s); | ^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: consider implementing `TryFrom` instead --> tests/ui/fallible_impl_from.rs:60:1 @@ -85,7 +83,6 @@ LL | if s.parse::().ok().unwrap() != 42 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | panic!("{:?}", s); | ^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/tests/ui/impl_hash_with_borrow_str_and_bytes.stderr b/tests/ui/impl_hash_with_borrow_str_and_bytes.stderr index 7328f563ce13..c327ce3f7ca1 100644 --- a/tests/ui/impl_hash_with_borrow_str_and_bytes.stderr +++ b/tests/ui/impl_hash_with_borrow_str_and_bytes.stderr @@ -23,7 +23,6 @@ LL | #[derive(Hash)] = note: ... as (`hash("abc") != hash("abc".as_bytes())` = help: consider either removing one of the `Borrow` implementations (`Borrow` or `Borrow<[u8]>`) ... = help: ... or not implementing `Hash` for this type - = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) error: the semantics of `Borrow` around `Hash` can't be satisfied when both `Borrow` and `Borrow<[u8]>` are implemented --> tests/ui/impl_hash_with_borrow_str_and_bytes.rs:117:6 diff --git a/tests/ui/issue-7447.stderr b/tests/ui/issue-7447.stderr index 5e28c1423840..09a75c6b8d29 100644 --- a/tests/ui/issue-7447.stderr +++ b/tests/ui/issue-7447.stderr @@ -6,15 +6,12 @@ LL | byte_view(panic!()); | = note: `-D clippy::diverging-sub-expression` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::diverging_sub_expression)]` - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: sub-expression diverges --> tests/ui/issue-7447.rs:29:19 | LL | group_entries(panic!()); | ^^^^^^^^ - | - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/same_name_method.stderr b/tests/ui/same_name_method.stderr index fefdb5c9c23d..b2624ac4d264 100644 --- a/tests/ui/same_name_method.stderr +++ b/tests/ui/same_name_method.stderr @@ -23,7 +23,6 @@ note: existing `clone` defined here | LL | #[derive(Clone)] | ^^^^^ - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: method's name is the same as an existing method in a trait --> tests/ui/same_name_method.rs:46:13 From da910b14e2af9d790c18c5861a8669b30a90939d Mon Sep 17 00:00:00 2001 From: KonaeAkira Date: Sat, 15 Mar 2025 00:00:01 +0100 Subject: [PATCH 193/745] Add failing from_over_into test case --- tests/ui/from_over_into.fixed | 11 +++++++++++ tests/ui/from_over_into.rs | 11 +++++++++++ tests/ui/from_over_into.stderr | 18 +++++++++++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/tests/ui/from_over_into.fixed b/tests/ui/from_over_into.fixed index 7d6780a0e02c..7229e5a2d358 100644 --- a/tests/ui/from_over_into.fixed +++ b/tests/ui/from_over_into.fixed @@ -105,4 +105,15 @@ fn issue_12138() { } } +fn issue_112502() { + struct MyInt(i64); + + impl From for i64 { + //~^ from_over_into + fn from(val: MyInt) -> Self { + val.0 + } + } +} + fn main() {} diff --git a/tests/ui/from_over_into.rs b/tests/ui/from_over_into.rs index 387ddde359c1..9c75969c5c13 100644 --- a/tests/ui/from_over_into.rs +++ b/tests/ui/from_over_into.rs @@ -105,4 +105,15 @@ fn issue_12138() { } } +fn issue_112502() { + struct MyInt(i64); + + impl Into for MyInt { + //~^ from_over_into + fn into(self: MyInt) -> i64 { + self.0 + } + } +} + fn main() {} diff --git a/tests/ui/from_over_into.stderr b/tests/ui/from_over_into.stderr index a564bccbaf71..fe779544dd57 100644 --- a/tests/ui/from_over_into.stderr +++ b/tests/ui/from_over_into.stderr @@ -107,5 +107,21 @@ LL | LL ~ fn from(val: Hello) {} | -error: aborting due to 7 previous errors +error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true + --> tests/ui/from_over_into.rs:111:5 + | +LL | impl Into for MyInt { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `impl From for Foreign` is allowed by the orphan rules, for more information see + https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence +help: replace the `Into` implementation with `From` + | +LL ~ impl From for i64 { +LL | +LL ~ fn from(val: MyInt) -> Self { +LL ~ val.0 + | + +error: aborting due to 8 previous errors From 4a324c9dffa87a802a3e976976020ed605eeb1bc Mon Sep 17 00:00:00 2001 From: KonaeAkira Date: Sat, 15 Mar 2025 00:05:32 +0100 Subject: [PATCH 194/745] Fix from_over_into lint suggesting invalid code --- clippy_lints/src/from_over_into.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/from_over_into.rs b/clippy_lints/src/from_over_into.rs index 6da5567d9c70..58a3f9288c0c 100644 --- a/clippy_lints/src/from_over_into.rs +++ b/clippy_lints/src/from_over_into.rs @@ -176,8 +176,8 @@ fn convert_to_from( return None; }; let body = cx.tcx.hir_body(body_id); - let [input] = body.params else { return None }; - let PatKind::Binding(.., self_ident, None) = input.pat.kind else { + let [self_param] = body.params else { return None }; + let PatKind::Binding(.., self_ident, None) = self_param.pat.kind else { return None; }; @@ -197,11 +197,21 @@ fn convert_to_from( // fn into(self) -> T -> fn from(self) -> T // ~~~~ ~~~~ (impl_item.ident.span, String::from("from")), - // fn into([mut] self) -> T -> fn into([mut] v: T) -> T - // ~~~~ ~~~~ - (self_ident.span, format!("val: {from}")), ]; + if self_ident.span.overlaps(self_param.ty_span) { + // fn into([mut] self) -> T -> fn into([mut] val: T) -> T + // ~~~~ ~~~~~~ + suggestions.push((self_ident.span, format!("val: {from}"))); + } else { + // fn into([mut] self: U) -> T -> fn into([mut] val: U) -> T + // ~~~~ ~~~ + suggestions.push((self_ident.span, String::from("val"))); + // fn into([mut] val: U) -> T -> fn into([mut] val: T) -> T + // ~ ~ + suggestions.push((self_param.ty_span, from.to_owned())); + } + if let FnRetTy::Return(_) = sig.decl.output { // fn into(self) -> T -> fn into(self) -> Self // ~ ~~~~ From 9c897a20ae6e6a94c6f6659e9ec917daf6d4f462 Mon Sep 17 00:00:00 2001 From: KonaeAkira Date: Sat, 15 Mar 2025 00:37:44 +0100 Subject: [PATCH 195/745] Simplify implementation --- clippy_lints/src/from_over_into.rs | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/from_over_into.rs b/clippy_lints/src/from_over_into.rs index 58a3f9288c0c..be887b03ae4b 100644 --- a/clippy_lints/src/from_over_into.rs +++ b/clippy_lints/src/from_over_into.rs @@ -194,24 +194,14 @@ fn convert_to_from( // impl Into for U -> impl Into for T // ~ ~ (self_ty.span, into.to_owned()), - // fn into(self) -> T -> fn from(self) -> T - // ~~~~ ~~~~ + // fn into(self: U) -> T -> fn from(self) -> T + // ~~~~ ~~~~ (impl_item.ident.span, String::from("from")), + // fn into([mut] self: U) -> T -> fn into([mut] val: T) -> T + // ~~~~~~~ ~~~~~~ + (self_ident.span.to(self_param.ty_span), format!("val: {from}")), ]; - if self_ident.span.overlaps(self_param.ty_span) { - // fn into([mut] self) -> T -> fn into([mut] val: T) -> T - // ~~~~ ~~~~~~ - suggestions.push((self_ident.span, format!("val: {from}"))); - } else { - // fn into([mut] self: U) -> T -> fn into([mut] val: U) -> T - // ~~~~ ~~~ - suggestions.push((self_ident.span, String::from("val"))); - // fn into([mut] val: U) -> T -> fn into([mut] val: T) -> T - // ~ ~ - suggestions.push((self_param.ty_span, from.to_owned())); - } - if let FnRetTy::Return(_) = sig.decl.output { // fn into(self) -> T -> fn into(self) -> Self // ~ ~~~~ From b43a29711e7ab50c1ee47a2d030273c83099b15e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 15 Mar 2025 03:09:09 +0100 Subject: [PATCH 196/745] Fix `record_diagnostic` --- compiler/rustc_query_system/src/dep_graph/graph.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 985ca6490345..bfd8b3207152 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -538,10 +538,14 @@ impl DepGraph { #[inline] pub fn record_diagnostic(&self, qcx: Qcx, diagnostic: &DiagInner) { if let Some(ref data) = self.data { - self.read_index(data.encode_diagnostic(qcx, diagnostic)); + D::read_deps(|task_deps| match task_deps { + TaskDepsRef::EvalAlways | TaskDepsRef::Ignore => return, + TaskDepsRef::Forbid | TaskDepsRef::Allow(..) => { + self.read_index(data.encode_diagnostic(qcx, diagnostic)); + } + }) } } - /// This forces a diagnostic node green by running its side effect. `prev_index` would /// refer to a node created used `encode_diagnostic` in the previous session. #[inline] From ebc55522cbe8ce0fb2fd1b2fd5e24b13382b3e89 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sat, 15 Mar 2025 05:05:16 +0000 Subject: [PATCH 197/745] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 2e649e688fa2..cc3d0cfc717b 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -addae0705c7cf5b2f2ed7faeec026c894f497b3d +d9e5539a39192028a7b15ae596a8685017faecee From f96eb611f8eb74fb865b51bf88683267c6885375 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 13 Mar 2025 17:09:25 +0000 Subject: [PATCH 198/745] Fold visit into ty --- clippy_utils/src/mir/possible_borrower.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_utils/src/mir/possible_borrower.rs b/clippy_utils/src/mir/possible_borrower.rs index 605764cef89f..db07b6404169 100644 --- a/clippy_utils/src/mir/possible_borrower.rs +++ b/clippy_utils/src/mir/possible_borrower.rs @@ -6,7 +6,7 @@ use rustc_index::bit_set::DenseBitSet; use rustc_lint::LateContext; use rustc_middle::mir::visit::Visitor as _; use rustc_middle::mir::{self, Mutability}; -use rustc_middle::ty::visit::TypeVisitor; +use rustc_middle::ty::TypeVisitor; use rustc_middle::ty::{self, TyCtxt}; use rustc_mir_dataflow::impls::MaybeStorageLive; use rustc_mir_dataflow::{Analysis, ResultsCursor}; From 899eed15adfbcda55e0eb300c037fe8d444f188d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 14 Mar 2025 22:18:04 +0100 Subject: [PATCH 199/745] Refactor metrics generation step --- .github/workflows/ci.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 96c0955e871b..47ee02ab00ed 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -241,13 +241,17 @@ jobs: - name: postprocess metrics into the summary run: | if [ -f build/metrics.json ]; then - ./build/citool/debug/citool postprocess-metrics build/metrics.json ${GITHUB_STEP_SUMMARY} + METRICS=build/metrics.json elif [ -f obj/build/metrics.json ]; then - ./build/citool/debug/citool postprocess-metrics obj/build/metrics.json ${GITHUB_STEP_SUMMARY} + METRICS=obj/build/metrics.json else echo "No metrics.json found" + exit 0 fi + ./build/citool/debug/citool postprocess-metrics \ + ${METRICS} ${GITHUB_STEP_SUMMARY} + - name: upload job metrics to DataDog if: needs.calculate_matrix.outputs.run_type != 'pr' env: From 301c384262522d0c4b5577ffbd10642ee9bee24f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 14 Mar 2025 22:18:41 +0100 Subject: [PATCH 200/745] Do not fail the build if metrics postprocessing or DataDog upload fails --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 47ee02ab00ed..01008d70b65b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -239,6 +239,9 @@ jobs: if: github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1' - name: postprocess metrics into the summary + # This step is not critical, and if some I/O problem happens, we don't want + # to cancel the build. + continue-on-error: true run: | if [ -f build/metrics.json ]; then METRICS=build/metrics.json @@ -253,6 +256,9 @@ jobs: ${METRICS} ${GITHUB_STEP_SUMMARY} - name: upload job metrics to DataDog + # This step is not critical, and if some I/O problem happens, we don't want + # to cancel the build. + continue-on-error: true if: needs.calculate_matrix.outputs.run_type != 'pr' env: DATADOG_API_KEY: ${{ secrets.DATADOG_API_KEY }} From 09d44a48b29fcf4c618ba38e592a1c4f365fc4e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 14 Mar 2025 22:21:41 +0100 Subject: [PATCH 201/745] Print metrics postprocessing to stdout This allows the code to be simplified a little bit. --- .github/workflows/ci.yml | 2 +- src/ci/citool/src/main.rs | 7 ++----- src/ci/citool/src/metrics.rs | 33 ++++++++++----------------------- 3 files changed, 13 insertions(+), 29 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 01008d70b65b..ffcdc40de3a7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -253,7 +253,7 @@ jobs: fi ./build/citool/debug/citool postprocess-metrics \ - ${METRICS} ${GITHUB_STEP_SUMMARY} + ${METRICS} >> ${GITHUB_STEP_SUMMARY} - name: upload job metrics to DataDog # This step is not critical, and if some I/O problem happens, we don't want diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs index cd690ebeb062..53fe75900750 100644 --- a/src/ci/citool/src/main.rs +++ b/src/ci/citool/src/main.rs @@ -158,9 +158,6 @@ enum Args { PostprocessMetrics { /// Path to the metrics.json file metrics_path: PathBuf, - /// Path to a file where the postprocessed metrics summary will be stored. - /// Usually, this will be GITHUB_STEP_SUMMARY on CI. - summary_path: PathBuf, }, /// Upload CI metrics to Datadog. UploadBuildMetrics { @@ -211,8 +208,8 @@ fn main() -> anyhow::Result<()> { Args::UploadBuildMetrics { cpu_usage_csv } => { upload_ci_metrics(&cpu_usage_csv)?; } - Args::PostprocessMetrics { metrics_path, summary_path } => { - postprocess_metrics(&metrics_path, &summary_path)?; + Args::PostprocessMetrics { metrics_path } => { + postprocess_metrics(&metrics_path)?; } Args::PostMergeReport { current: commit, parent } => { post_merge_report(load_db(default_jobs_file)?, parent, commit)?; diff --git a/src/ci/citool/src/metrics.rs b/src/ci/citool/src/metrics.rs index 83b3d5ceed05..8da4d4e53e64 100644 --- a/src/ci/citool/src/metrics.rs +++ b/src/ci/citool/src/metrics.rs @@ -1,6 +1,4 @@ use std::collections::BTreeMap; -use std::fs::File; -use std::io::Write; use std::path::Path; use anyhow::Context; @@ -8,57 +6,46 @@ use build_helper::metrics::{ BuildStep, JsonNode, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, format_build_steps, }; -pub fn postprocess_metrics(metrics_path: &Path, summary_path: &Path) -> anyhow::Result<()> { +pub fn postprocess_metrics(metrics_path: &Path) -> anyhow::Result<()> { let metrics = load_metrics(metrics_path)?; - let mut file = File::options() - .append(true) - .create(true) - .open(summary_path) - .with_context(|| format!("Cannot open summary file at {summary_path:?}"))?; - if !metrics.invocations.is_empty() { - writeln!(file, "# Bootstrap steps")?; - record_bootstrap_step_durations(&metrics, &mut file)?; - record_test_suites(&metrics, &mut file)?; + println!("# Bootstrap steps"); + record_bootstrap_step_durations(&metrics); + record_test_suites(&metrics); } Ok(()) } -fn record_bootstrap_step_durations(metrics: &JsonRoot, file: &mut File) -> anyhow::Result<()> { +fn record_bootstrap_step_durations(metrics: &JsonRoot) { for invocation in &metrics.invocations { let step = BuildStep::from_invocation(invocation); let table = format_build_steps(&step); eprintln!("Step `{}`\n{table}\n", invocation.cmdline); - writeln!( - file, + println!( r"